summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-31 23:54:19 +0000
committerpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-31 23:54:19 +0000
commit4421b8c0cdcda67bfbdca6b75d44aef5e204e860 (patch)
treeafb22f52b005b8ca6582a08038a41418c0bb7b12
parent88feaca65d66932c73847d7150cf9a7d91f7069d (diff)
downloadchromium_src-4421b8c0cdcda67bfbdca6b75d44aef5e204e860.zip
chromium_src-4421b8c0cdcda67bfbdca6b75d44aef5e204e860.tar.gz
chromium_src-4421b8c0cdcda67bfbdca6b75d44aef5e204e860.tar.bz2
Merge 139167 - Add NOTIFICATION_TAB_CONTENTS_DESTROYED when a TabContentsWrapper is about to be torn down. Code that wants to access TabContentsWrappers (and their members) safely should listen to this rather than NOTIFICATION_WEB_CONTENTS_DESTROYED.
This fixes a crash in GoogleURLTracker that tried to access the already-NULLed infobar_tab_helper() on the TCW. The other points changed in this CL probably work fine today, but using this notification is more future-proof if we muck with destruction order (and sometimes slightly simpler to boot). This also eliminates one use of NOTIFICATION_WEB_CONTENTS_DESTROYED entirely; there was some hacky code in task_manager_resource_providers.cc that tried to use it to backstop listening for another notification. Because the notification order is different with the new notification this wouldn't work; it also seems totally bogus anyway, so I just ripped it out. Finally, this adds a public getter for whether a TabContentsWrapper is being destroyed, and switches most places that were checking for the similar WebContents::IsBeingDestroyed() flag to use this instead. This is usually more correct (since a number of places would check for WebContents destruction but if not found start accessing pieces of the TabContentsWrapper). BUG=128512 TEST=none Review URL: https://chromiumcodereview.appspot.com/10445028 TBR=pkasting@chromium.org Review URL: https://chromiumcodereview.appspot.com/10454102 git-svn-id: svn://svn.chromium.org/chrome/branches/1132/src@139928 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/sync/glue/session_change_processor.cc13
-rw-r--r--chrome/browser/tabs/tab_strip_model.cc7
-rw-r--r--chrome/browser/tabs/tab_strip_model_unittest.cc6
-rw-r--r--chrome/browser/task_manager/task_manager_resource_providers.cc15
-rw-r--r--chrome/browser/ui/blocked_content/blocked_content_tab_helper.cc5
-rw-r--r--chrome/browser/ui/cocoa/applescript/window_applescript.mm6
-rw-r--r--chrome/browser/ui/content_settings/content_setting_bubble_model.cc23
-rw-r--r--chrome/browser/ui/gtk/browser_window_gtk.cc2
-rw-r--r--chrome/browser/ui/gtk/tab_contents_container_gtk.cc24
-rw-r--r--chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.cc26
-rw-r--r--chrome/browser/ui/sync/tab_contents_wrapper_synced_tab_delegate.cc4
-rw-r--r--chrome/browser/ui/tab_contents/tab_contents_wrapper.cc7
-rw-r--r--chrome/browser/ui/tab_contents/tab_contents_wrapper.h3
-rw-r--r--chrome/browser/ui/views/frame/browser_view.cc2
-rw-r--r--chrome/browser/ui/views/tabs/default_tab_drag_controller.cc18
-rw-r--r--chrome/common/chrome_notification_types.h13
16 files changed, 83 insertions, 91 deletions
diff --git a/chrome/browser/sync/glue/session_change_processor.cc b/chrome/browser/sync/glue/session_change_processor.cc
index cf146c8..79d5eb5 100644
--- a/chrome/browser/sync/glue/session_change_processor.cc
+++ b/chrome/browser/sync/glue/session_change_processor.cc
@@ -139,19 +139,15 @@ void SessionChangeProcessor::Observe(
break;
}
- case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: {
+ case chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED: {
TabContentsWrapper* tab_contents_wrapper =
- TabContentsWrapper::GetCurrentWrapperForContents(
- content::Source<WebContents>(source).ptr());
- if (!tab_contents_wrapper) {
- return;
- }
+ content::Source<TabContentsWrapper>(source).ptr();
SyncedTabDelegate* tab = tab_contents_wrapper->synced_tab_delegate();
if (!tab || tab->profile() != profile_) {
return;
}
modified_tabs.push_back(tab);
- DVLOG(1) << "Received NOTIFICATION_WEB_CONTENTS_DESTROYED for profile "
+ DVLOG(1) << "Received NOTIFICATION_TAB_CONTENTS_DESTROYED for profile "
<< profile_;
break;
}
@@ -354,8 +350,7 @@ void SessionChangeProcessor::StartObserving() {
return;
notification_registrar_.Add(this, chrome::NOTIFICATION_TAB_PARENTED,
content::NotificationService::AllSources());
- notification_registrar_.Add(this,
- content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
+ notification_registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
content::NotificationService::AllSources());
notification_registrar_.Add(this, content::NOTIFICATION_NAV_LIST_PRUNED,
content::NotificationService::AllSources());
diff --git a/chrome/browser/tabs/tab_strip_model.cc b/chrome/browser/tabs/tab_strip_model.cc
index ad67ca9..bf92305 100644
--- a/chrome/browser/tabs/tab_strip_model.cc
+++ b/chrome/browser/tabs/tab_strip_model.cc
@@ -73,7 +73,7 @@ TabStripModel::TabStripModel(TabStripModelDelegate* delegate, Profile* profile)
order_controller_(NULL) {
DCHECK(delegate_);
registrar_.Add(this,
- content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
+ chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
content::NotificationService::AllBrowserContextsAndSources());
registrar_.Add(this,
chrome::NOTIFICATION_EXTENSION_UNLOADED,
@@ -1006,11 +1006,12 @@ void TabStripModel::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
- case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: {
+ case chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED: {
// Sometimes, on qemu, it seems like a WebContents object can be destroyed
// while we still have a reference to it. We need to break this reference
// here so we don't crash later.
- int index = GetWrapperIndex(content::Source<WebContents>(source).ptr());
+ int index = GetIndexOfTabContents(
+ content::Source<TabContentsWrapper>(source).ptr());
if (index != TabStripModel::kNoTab) {
// Note that we only detach the contents here, not close it - it's
// already been closed. We just want to undo our bookkeeping.
diff --git a/chrome/browser/tabs/tab_strip_model_unittest.cc b/chrome/browser/tabs/tab_strip_model_unittest.cc
index 178fe53..c9dae4d 100644
--- a/chrome/browser/tabs/tab_strip_model_unittest.cc
+++ b/chrome/browser/tabs/tab_strip_model_unittest.cc
@@ -26,6 +26,7 @@
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
+#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
@@ -59,9 +60,8 @@ class DeleteTabContentsOnDestroyedObserver
TabContentsWrapper* tab_to_delete)
: source_(source),
tab_to_delete_(tab_to_delete) {
- registrar_.Add(this,
- content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::Source<WebContents>(source->web_contents()));
+ registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
+ content::Source<TabContentsWrapper>(source));
}
virtual void Observe(int type,
diff --git a/chrome/browser/task_manager/task_manager_resource_providers.cc b/chrome/browser/task_manager/task_manager_resource_providers.cc
index 327ea9a..a910100 100644
--- a/chrome/browser/task_manager/task_manager_resource_providers.cc
+++ b/chrome/browser/task_manager/task_manager_resource_providers.cc
@@ -397,12 +397,6 @@ void TaskManagerTabContentsResourceProvider::StartUpdating() {
content::NotificationService::AllBrowserContextsAndSources());
registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
content::NotificationService::AllBrowserContextsAndSources());
- // TAB_CONTENTS_DISCONNECTED should be enough to know when to remove a
- // resource. This is an attempt at mitigating a crasher that seem to
- // indicate a resource is still referencing a deleted WebContents
- // (http://crbug.com/7321).
- registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::NotificationService::AllBrowserContextsAndSources());
registrar_.Add(this, chrome::NOTIFICATION_INSTANT_COMMITTED,
content::NotificationService::AllBrowserContextsAndSources());
}
@@ -422,9 +416,6 @@ void TaskManagerTabContentsResourceProvider::StopUpdating() {
this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
content::NotificationService::AllBrowserContextsAndSources());
registrar_.Remove(
- this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::NotificationService::AllBrowserContextsAndSources());
- registrar_.Remove(
this, chrome::NOTIFICATION_INSTANT_COMMITTED,
content::NotificationService::AllBrowserContextsAndSources());
@@ -520,12 +511,6 @@ void TaskManagerTabContentsResourceProvider::Observe(int type,
Remove(tab_contents);
Add(tab_contents);
break;
- case content::NOTIFICATION_WEB_CONTENTS_DESTROYED:
- // If this DCHECK is triggered, it could explain http://crbug.com/7321 .
- DCHECK(resources_.find(tab_contents) ==
- resources_.end()) << "TAB_CONTENTS_DESTROYED with no associated "
- "TAB_CONTENTS_DISCONNECTED";
- // Fall through.
case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED:
Remove(tab_contents);
break;
diff --git a/chrome/browser/ui/blocked_content/blocked_content_tab_helper.cc b/chrome/browser/ui/blocked_content/blocked_content_tab_helper.cc
index 2d09a71..38f29c5 100644
--- a/chrome/browser/ui/blocked_content/blocked_content_tab_helper.cc
+++ b/chrome/browser/ui/blocked_content/blocked_content_tab_helper.cc
@@ -50,9 +50,8 @@ void BlockedContentTabHelper::DidNavigateMainFrame(
void BlockedContentTabHelper::PopupNotificationVisibilityChanged(
bool visible) {
- if (web_contents()->IsBeingDestroyed())
- return;
- tab_contents_wrapper_->content_settings()->SetPopupsBlocked(visible);
+ if (!tab_contents_wrapper_->in_destructor())
+ tab_contents_wrapper_->content_settings()->SetPopupsBlocked(visible);
}
void BlockedContentTabHelper::SendNotification(TabContentsWrapper* contents,
diff --git a/chrome/browser/ui/cocoa/applescript/window_applescript.mm b/chrome/browser/ui/cocoa/applescript/window_applescript.mm
index 5a5f095..c46b357 100644
--- a/chrome/browser/ui/cocoa/applescript/window_applescript.mm
+++ b/chrome/browser/ui/cocoa/applescript/window_applescript.mm
@@ -151,13 +151,13 @@
for (int i = 0; i < browser_->tab_count(); ++i) {
// Check to see if tab is closing.
- if (browser_->GetWebContentsAt(i)->IsBeingDestroyed()) {
+ TabContentsWrapper* tab_contents = browser_->GetTabContentsWrapperAt(i);
+ if (tab_contents->in_destructor()) {
continue;
}
scoped_nsobject<TabAppleScript> tab(
- [[TabAppleScript alloc]
- initWithTabContent:(browser_->GetTabContentsWrapperAt(i))]);
+ [[TabAppleScript alloc] initWithTabContent:tab_contents]);
[tab setContainer:self
property:AppleScript::kTabsProperty];
[tabs addObject:tab];
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
index 4978542..6cf65de 100644
--- a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
+++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
@@ -542,8 +542,8 @@ ContentSettingBubbleModel::ContentSettingBubbleModel(
: tab_contents_(tab_contents),
profile_(profile),
content_type_(content_type) {
- registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::Source<WebContents>(tab_contents->web_contents()));
+ registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
+ content::Source<TabContentsWrapper>(tab_contents));
registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
content::Source<Profile>(profile_));
}
@@ -576,17 +576,12 @@ void ContentSettingBubbleModel::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
- switch (type) {
- case content::NOTIFICATION_WEB_CONTENTS_DESTROYED:
- DCHECK(source ==
- content::Source<WebContents>(tab_contents_->web_contents()));
- tab_contents_ = NULL;
- break;
- case chrome::NOTIFICATION_PROFILE_DESTROYED:
- DCHECK(source == content::Source<Profile>(profile_));
- profile_ = NULL;
- break;
- default:
- NOTREACHED();
+ if (type == chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED) {
+ DCHECK_EQ(tab_contents_, content::Source<TabContentsWrapper>(source).ptr());
+ tab_contents_ = NULL;
+ } else {
+ DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
+ DCHECK_EQ(profile_, content::Source<Profile>(source).ptr());
+ profile_ = NULL;
}
}
diff --git a/chrome/browser/ui/gtk/browser_window_gtk.cc b/chrome/browser/ui/gtk/browser_window_gtk.cc
index 394dbce..cb9543c 100644
--- a/chrome/browser/ui/gtk/browser_window_gtk.cc
+++ b/chrome/browser/ui/gtk/browser_window_gtk.cc
@@ -1328,7 +1328,7 @@ void BrowserWindowGtk::ActiveTabChanged(TabContentsWrapper* old_contents,
int index,
bool user_gesture) {
TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::ActiveTabChanged");
- if (old_contents && !old_contents->web_contents()->IsBeingDestroyed())
+ if (old_contents && !old_contents->in_destructor())
old_contents->web_contents()->GetView()->StoreFocus();
// Update various elements that are interested in knowing the current
diff --git a/chrome/browser/ui/gtk/tab_contents_container_gtk.cc b/chrome/browser/ui/gtk/tab_contents_container_gtk.cc
index 7a543b2..5055fbe 100644
--- a/chrome/browser/ui/gtk/tab_contents_container_gtk.cc
+++ b/chrome/browser/ui/gtk/tab_contents_container_gtk.cc
@@ -9,8 +9,8 @@
#include "base/i18n/rtl.h"
#include "chrome/browser/ui/gtk/status_bubble_gtk.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/gtk/gtk_expanded_container.h"
@@ -67,8 +67,8 @@ void TabContentsContainerGtk::Init() {
void TabContentsContainerGtk::SetTab(TabContentsWrapper* tab) {
HideTab(tab_);
if (tab_) {
- registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::Source<WebContents>(tab_->web_contents()));
+ registrar_.Remove(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
+ content::Source<TabContentsWrapper>(tab_));
}
tab_ = tab;
@@ -80,8 +80,8 @@ void TabContentsContainerGtk::SetTab(TabContentsWrapper* tab) {
} else if (tab_) {
// Otherwise we actually have to add it to the widget hierarchy.
PackTab(tab);
- registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::Source<WebContents>(tab_->web_contents()));
+ registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
+ content::Source<TabContentsWrapper>(tab_));
}
}
@@ -98,8 +98,8 @@ void TabContentsContainerGtk::SetPreview(TabContentsWrapper* preview) {
preview_ = preview;
PackTab(preview);
- registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::Source<WebContents>(preview_->web_contents()));
+ registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
+ content::Source<TabContentsWrapper>(preview_));
}
void TabContentsContainerGtk::RemovePreview() {
@@ -112,8 +112,8 @@ void TabContentsContainerGtk::RemovePreview() {
if (preview_widget)
gtk_container_remove(GTK_CONTAINER(expanded_), preview_widget);
- registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::Source<WebContents>(preview_->web_contents()));
+ registrar_.Remove(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
+ content::Source<TabContentsWrapper>(preview_));
preview_ = NULL;
}
@@ -178,9 +178,9 @@ void TabContentsContainerGtk::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
- DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED);
-
- WebContentsDestroyed(content::Source<WebContents>(source).ptr());
+ DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED, type);
+ WebContentsDestroyed(
+ content::Source<TabContentsWrapper>(source)->web_contents());
}
void TabContentsContainerGtk::WebContentsDestroyed(WebContents* contents) {
diff --git a/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.cc b/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.cc
index b003ca4..c73f322 100644
--- a/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.cc
+++ b/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.cc
@@ -18,8 +18,8 @@
#include "chrome/browser/ui/gtk/tabs/dragged_view_gtk.h"
#include "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/gtk/gtk_screen_util.h"
#include "ui/gfx/screen.h"
@@ -163,10 +163,8 @@ DraggedTabData DraggedTabControllerGtk::InitDraggedTabData(TabGtk* tab) {
DraggedTabData dragged_tab_data(tab, contents, original_delegate,
source_model_index, pinned, mini);
- registrar_.Add(
- this,
- content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::Source<WebContents>(dragged_tab_data.contents_->web_contents()));
+ registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
+ content::Source<TabContentsWrapper>(dragged_tab_data.contents_));
return dragged_tab_data;
}
@@ -227,13 +225,15 @@ void DraggedTabControllerGtk::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
- DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED);
- WebContents* destroyed_contents = content::Source<WebContents>(source).ptr();
+ DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED, type);
+ TabContentsWrapper* destroyed_tab_contents =
+ content::Source<TabContentsWrapper>(source).ptr();
+ WebContents* destroyed_web_contents = destroyed_tab_contents->web_contents();
for (size_t i = 0; i < drag_data_->size(); ++i) {
- if (drag_data_->get(i)->contents_->web_contents() == destroyed_contents) {
+ if (drag_data_->get(i)->contents_ == destroyed_tab_contents) {
// One of the tabs we're dragging has been destroyed. Cancel the drag.
- if (destroyed_contents->GetDelegate() == this)
- destroyed_contents->SetDelegate(NULL);
+ if (destroyed_web_contents->GetDelegate() == this)
+ destroyed_web_contents->SetDelegate(NULL);
drag_data_->get(i)->contents_ = NULL;
drag_data_->get(i)->original_delegate_ = NULL;
EndDragImpl(TAB_DESTROYED);
@@ -845,10 +845,8 @@ void DraggedTabControllerGtk::CleanUpDraggedTabs() {
if (attached_tabstrip_ != source_tabstrip_) {
for (size_t i = 0; i < drag_data_->size(); ++i) {
if (drag_data_->get(i)->contents_) {
- registrar_.Remove(
- this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::Source<WebContents>(
- drag_data_->get(i)->contents_->web_contents()));
+ registrar_.Remove(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
+ content::Source<TabContentsWrapper>(drag_data_->get(i)->contents_));
}
source_tabstrip_->DestroyDraggedTab(drag_data_->get(i)->tab_);
drag_data_->get(i)->tab_ = NULL;
diff --git a/chrome/browser/ui/sync/tab_contents_wrapper_synced_tab_delegate.cc b/chrome/browser/ui/sync/tab_contents_wrapper_synced_tab_delegate.cc
index cc7c126..c5eb182 100644
--- a/chrome/browser/ui/sync/tab_contents_wrapper_synced_tab_delegate.cc
+++ b/chrome/browser/ui/sync/tab_contents_wrapper_synced_tab_delegate.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -29,7 +29,7 @@ SessionID::id_type TabContentsWrapperSyncedTabDelegate::GetSessionId() const {
}
bool TabContentsWrapperSyncedTabDelegate::IsBeingDestroyed() const {
- return tab_contents_wrapper_->web_contents()->IsBeingDestroyed();
+ return tab_contents_wrapper_->in_destructor();
}
Profile* TabContentsWrapperSyncedTabDelegate::profile() const {
diff --git a/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc b/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc
index 5e457ea..824eb17 100644
--- a/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc
+++ b/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc
@@ -45,7 +45,9 @@
#include "chrome/browser/ui/sync/one_click_signin_helper.h"
#include "chrome/browser/ui/sync/tab_contents_wrapper_synced_tab_delegate.h"
#include "chrome/browser/ui/tab_contents/core_tab_helper.h"
+#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
+#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"
using content::WebContents;
@@ -157,6 +159,11 @@ TabContentsWrapper::TabContentsWrapper(WebContents* contents)
TabContentsWrapper::~TabContentsWrapper() {
in_destructor_ = true;
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
+ content::Source<TabContentsWrapper>(this),
+ content::NotificationService::NoDetails());
+
// Need to tear down infobars before the WebContents goes away.
// TODO(avi): Can we get this handled by the tab helper itself?
infobar_tab_helper_.reset();
diff --git a/chrome/browser/ui/tab_contents/tab_contents_wrapper.h b/chrome/browser/ui/tab_contents/tab_contents_wrapper.h
index 3fc5e14..83a5d3f 100644
--- a/chrome/browser/ui/tab_contents/tab_contents_wrapper.h
+++ b/chrome/browser/ui/tab_contents/tab_contents_wrapper.h
@@ -105,6 +105,9 @@ class TabContentsWrapper : public content::WebContentsObserver {
// Returns the Profile that is associated with this TabContentsWrapper.
Profile* profile() const;
+ // True if this TabContentsWrapper is being torn down.
+ bool in_destructor() const { return in_destructor_; }
+
// Tab Helpers ---------------------------------------------------------------
AutocompleteHistoryManager* autocomplete_history_manager() {
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index e2ab96b..aa702e1 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1361,7 +1361,7 @@ void BrowserView::TabDeactivated(TabContentsWrapper* contents) {
// We do not store the focus when closing the tab to work-around bug 4633.
// Some reports seem to show that the focus manager and/or focused view can
// be garbage at that point, it is not clear why.
- if (!contents->web_contents()->IsBeingDestroyed())
+ if (!contents->in_destructor())
contents->web_contents()->GetView()->StoreFocus();
}
diff --git a/chrome/browser/ui/views/tabs/default_tab_drag_controller.cc b/chrome/browser/ui/views/tabs/default_tab_drag_controller.cc
index 523e5e4..f87aa3e 100644
--- a/chrome/browser/ui/views/tabs/default_tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/default_tab_drag_controller.cc
@@ -393,10 +393,8 @@ void DefaultTabDragController::InitTabDragData(BaseTab* tab,
drag_data->contents = GetModel(source_tabstrip_)->GetTabContentsAt(
drag_data->source_model_index);
drag_data->pinned = source_tabstrip_->IsTabPinned(tab);
- registrar_.Add(
- this,
- content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::Source<WebContents>(drag_data->contents->web_contents()));
+ registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED,
+ content::Source<TabContentsWrapper>(drag_data->contents));
// We need to be the delegate so we receive messages about stuff, otherwise
// our dragged WebContents may be replaced and subsequently
@@ -514,13 +512,15 @@ void DefaultTabDragController::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
- DCHECK_EQ(type, content::NOTIFICATION_WEB_CONTENTS_DESTROYED);
- WebContents* destroyed_contents = content::Source<WebContents>(source).ptr();
+ DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED, type);
+ TabContentsWrapper* destroyed_tab_contents =
+ content::Source<TabContentsWrapper>(source).ptr();
+ WebContents* destroyed_web_contents = destroyed_tab_contents->web_contents();
for (size_t i = 0; i < drag_data_.size(); ++i) {
- if (drag_data_[i].contents->web_contents() == destroyed_contents) {
+ if (drag_data_[i].contents == destroyed_tab_contents) {
// One of the tabs we're dragging has been destroyed. Cancel the drag.
- if (destroyed_contents->GetDelegate() == this)
- destroyed_contents->SetDelegate(NULL);
+ if (destroyed_web_contents->GetDelegate() == this)
+ destroyed_web_contents->SetDelegate(NULL);
drag_data_[i].contents = NULL;
drag_data_[i].original_delegate = NULL;
EndDragImpl(TAB_DESTROYED);
diff --git a/chrome/common/chrome_notification_types.h b/chrome/common/chrome_notification_types.h
index 3734b2c..5e42fda 100644
--- a/chrome/common/chrome_notification_types.h
+++ b/chrome/common/chrome_notification_types.h
@@ -159,10 +159,19 @@ enum NotificationType {
// Source<NavigationController> with a pointer to the controller for the
// closed tab. No details are expected.
//
- // See also content::NOTIFICATION_WEB_CONTENTS_DESTROYED, which is sent when
- // the WebContents containing the NavigationController is destroyed.
+ // See also NOTIFICATION_TAB_CONTENTS_DESTROYED, which is sent when the
+ // TabContentsWrapper is destroyed, and
+ // content::NOTIFICATION_WEB_CONTENTS_DESTROYED, which is sent when the
+ // WebContents containing the NavigationController is destroyed.
NOTIFICATION_TAB_CLOSING,
+ // Sent when a TabContentsWrapper is being destroyed. At this point it's safe
+ // to call TabContentsWrapper member functions, which is not true of the
+ // similar content::NOTIFICATION_WEB_CONTENTS_DESTROYED that fires later
+ // during teardown. The source is a Source<TabContentsWrapper>. There are no
+ // details.
+ NOTIFICATION_TAB_CONTENTS_DESTROYED,
+
// Stuff inside the tabs ---------------------------------------------------
// Sent when the bookmark bubble hides. The source is the profile, the