diff options
author | ojan@google.com <ojan@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-29 23:32:47 +0000 |
---|---|---|
committer | ojan@google.com <ojan@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-29 23:32:47 +0000 |
commit | c82192d62ae8518837f448f9bbd9d0c93cd4af13 (patch) | |
tree | 795361f6bb6033caf55862386541c70e08b969be /chrome/browser/browser.cc | |
parent | 9a2bba4ed0996b8bc9f8dab235ad83af3f155948 (diff) | |
download | chromium_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.cc | 61 |
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) { |