summaryrefslogtreecommitdiffstats
path: root/chrome/browser/browser.cc
diff options
context:
space:
mode:
authorojan@google.com <ojan@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-29 23:32:47 +0000
committerojan@google.com <ojan@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-29 23:32:47 +0000
commitc82192d62ae8518837f448f9bbd9d0c93cd4af13 (patch)
tree795361f6bb6033caf55862386541c70e08b969be /chrome/browser/browser.cc
parent9a2bba4ed0996b8bc9f8dab235ad83af3f155948 (diff)
downloadchromium_src-c82192d62ae8518837f448f9bbd9d0c93cd4af13.zip
chromium_src-c82192d62ae8518837f448f9bbd9d0c93cd4af13.tar.gz
chromium_src-c82192d62ae8518837f448f9bbd9d0c93cd4af13.tar.bz2
Fix not closing the browser with hung, crashed and interstitial tabs. Adds a 1 second hang monitor for the beforeunload/unload events to fire.
BUG=1296059 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/browser.cc')
-rw-r--r--chrome/browser/browser.cc61
1 files changed, 51 insertions, 10 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index 75c6bb4..aebd7cf 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -211,7 +211,7 @@ Browser::Browser(const gfx::Rect& initial_bounds,
controller_(this),
toolbar_(&controller_, this),
chrome_updater_factory_(this),
- frame_method_factory_(this),
+ method_factory_(this),
hung_window_detector_(&hung_plugin_action_),
ticker_(0),
tabstrip_model_(this, profile),
@@ -788,6 +788,12 @@ void Browser::Observe(NotificationType type,
frame_->ShelfVisibilityChanged();
}
}
+ } else if (type == NOTIFY_WEB_CONTENTS_DISCONNECTED) {
+ // Need to do this asynchronously as it will close the tab, which is
+ // currently on the call stack above us.
+ MessageLoop::current()->PostTask(FROM_HERE,
+ method_factory_.NewRunnableMethod(&Browser::ClearUnloadStateOnCrash,
+ Source<TabContents>(source).ptr()));
} else {
NOTREACHED() << "Got a notification we didn't register for.";
}
@@ -1002,19 +1008,27 @@ void Browser::MoveToFront(bool should_activate) {
bool Browser::ShouldCloseWindow() {
if (is_processing_tab_unload_events_) {
- return false;
+ return tabs_needing_before_unload_fired_.empty() &&
+ tabs_needing_unload_fired_.empty();
}
is_processing_tab_unload_events_ = true;
for (int i = 0; i < tab_count(); ++i) {
- if (tabstrip_model_.TabHasUnloadListener(i))
- tabs_needing_before_unload_fired_.push_back(GetTabContentsAt(i));
+ if (tabstrip_model_.TabHasUnloadListener(i)) {
+ TabContents* tab = GetTabContentsAt(i);
+
+ // If the tab crashes in the beforeunload or unload handler, it won't be
+ // able to ack. But we know we can close it.
+ NotificationService::current()->
+ AddObserver(this, NOTIFY_WEB_CONTENTS_DISCONNECTED,
+ Source<TabContents>(tab));
+
+ tabs_needing_before_unload_fired_.push_back(tab);
+ }
}
- if (tabs_needing_before_unload_fired_.empty()) {
- is_processing_tab_unload_events_ = false;
+ if (tabs_needing_before_unload_fired_.empty())
return true;
- }
ProcessPendingBeforeUnloadTabs();
return false;
@@ -1080,16 +1094,43 @@ void Browser::UnloadFired(TabContents* tab) {
}
}
+ NotificationService::current()->
+ RemoveObserver(this, NOTIFY_WEB_CONTENTS_DISCONNECTED,
+ Source<TabContents>(tab));
+
if (tabs_needing_unload_fired_.empty()) {
// We've finished all the unload events and can proceed to close the
// browser.
- is_processing_tab_unload_events_ = false;
OnWindowClosing();
} else {
ProcessPendingUnloadTabs();
}
}
+void Browser::ClearUnloadStateOnCrash(TabContents* tab) {
+ bool is_waiting_on_before_unload = false;
+
+ for (UnloadListenerVector::iterator it =
+ tabs_needing_before_unload_fired_.begin();
+ it != tabs_needing_before_unload_fired_.end();
+ ++it) {
+ if (*it == tab) {
+ is_waiting_on_before_unload = true;
+ break;
+ }
+ }
+
+ if (is_waiting_on_before_unload) {
+ // Even though beforeunload didn't really fire, we call the same function
+ // so that all the appropriate cleanup happens.
+ BeforeUnloadFired(tab, true);
+ } else {
+ // Even though unload didn't really fire, we call the same function
+ // so that all the appropriate cleanup happens.
+ UnloadFired(tab);
+ }
+}
+
void Browser::OnWindowClosing() {
if (!ShouldCloseWindow())
@@ -1269,7 +1310,7 @@ void Browser::CloseFrameAfterDragSession() {
// otherwise the frame will think the drag session is still active and ignore
// the request.
MessageLoop::current()->PostTask(FROM_HERE,
- frame_method_factory_.NewRunnableMethod(&Browser::CloseFrame));
+ method_factory_.NewRunnableMethod(&Browser::CloseFrame));
}
////////////////////////////////////////////////////////////////////////////////
@@ -1417,7 +1458,7 @@ void Browser::TabStripEmpty() {
// NOTE: If you change to be immediate (no invokeLater) then you'll need to
// update BrowserList::CloseAllBrowsers.
MessageLoop::current()->PostTask(FROM_HERE,
- frame_method_factory_.NewRunnableMethod(&Browser::CloseFrame));
+ method_factory_.NewRunnableMethod(&Browser::CloseFrame));
}
void Browser::RemoveShelvesForTabContents(TabContents* contents) {