Index: chrome/browser/ui/browser_list.cc |
diff --git a/chrome/browser/ui/browser_list.cc b/chrome/browser/ui/browser_list.cc |
index 000c4c6210db311e0600ad9cac30d7a454e833c8..f21e37e32e557ee2a963533c18271ac636eb36c3 100644 |
--- a/chrome/browser/ui/browser_list.cc |
+++ b/chrome/browser/ui/browser_list.cc |
@@ -32,6 +32,10 @@ base::LazyInstance<ObserverList<chrome::BrowserListObserver> >::Leaky |
BrowserList* BrowserList::native_instance_ = NULL; |
BrowserList* BrowserList::ash_instance_ = NULL; |
+// static |
+// Whether the BrowserList is currently processing OnBeforeUnload events. |
+bool before_unload_callback_expected_; |
+ |
//////////////////////////////////////////////////////////////////////////////// |
// BrowserList, public: |
@@ -116,6 +120,7 @@ void BrowserList::RemoveObserver(chrome::BrowserListObserver* observer) { |
observers_.Get().RemoveObserver(observer); |
} |
+// static |
void BrowserList::CloseAllBrowsersWithProfile(Profile* profile) { |
BrowserVector browsers_to_close; |
for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
@@ -130,6 +135,74 @@ void BrowserList::CloseAllBrowsersWithProfile(Profile* profile) { |
} |
// static |
+void BrowserList::CloseAllBrowsersWithProfile(Profile* profile, |
+ const base::Callback<void(const base::FilePath&)>& on_close_success) { |
+ before_unload_callback_expected_ = false; |
+ BrowserVector browsers_to_close; |
+ for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
+ if (it->profile()->GetOriginalProfile() == profile->GetOriginalProfile()) |
+ browsers_to_close.push_back(*it); |
+ } |
+ |
+ TryToCloseBrowserList(browsers_to_close, |
+ on_close_success, |
+ profile->GetPath()); |
+} |
+ |
+// static |
+void BrowserList::TryToCloseBrowserList(const BrowserVector& browsers_to_close, |
+ const base::Callback<void(const base::FilePath&)>& on_close_success, |
+ const base::FilePath& profile_path) { |
+ for (BrowserVector::const_iterator it = browsers_to_close.begin(); |
+ it != browsers_to_close.end(); ++it) { |
+ if ((*it)->CallBeforeUnloadHandlers( |
+ base::Bind(&BrowserList::PostBeforeUnloadHandlers, |
+ browsers_to_close, |
+ on_close_success, |
+ profile_path))) { |
+ // Note that the UnloadController has been called to fire and handle one |
+ // OnBeforeUnload event. We expect the callback to be called once. |
+ before_unload_callback_expected_ = true; |
+ return; |
+ } |
+ } |
+ |
+ for (BrowserVector::const_iterator it = browsers_to_close.begin(); |
+ it != browsers_to_close.end(); ++it) |
+ (*it)->window()->Close(); |
+ |
+ on_close_success.Run(profile_path); |
+} |
+ |
+// static |
+void BrowserList::PostBeforeUnloadHandlers( |
+ const BrowserVector& browsers_to_close, |
+ const base::Callback<void(const base::FilePath&)>& on_close_success, |
+ const base::FilePath& profile_path, |
+ bool tab_close_confirmed) { |
+ // If multiple windows' OnBeforeUnload events have been handled when the user |
+ // clicks "Stay on this page", then resetting the handlers will call each |
+ // window's UnloadController's CancelWindowClose method, triggering the |
+ // UnloadController's callback (this method). The following check ensures this |
+ // callback only executes once. |
Peter Kasting
2014/08/29 21:30:25
It seems like we can simplify this to avoid the me
Mike Lerman
2014/09/02 15:15:40
I like that AutoReset class! And done.
|
+ if (!before_unload_callback_expected_) |
+ return; |
+ |
+ // The UnloadController has called back for the processing of a |
+ // particular OnBeforeUnload event. We expect no more callbacks. |
+ before_unload_callback_expected_ = false; |
+ |
+ if (tab_close_confirmed) { |
+ TryToCloseBrowserList(browsers_to_close, on_close_success, profile_path); |
+ } else { |
+ for (BrowserVector::const_iterator it = browsers_to_close.begin(); |
+ it != browsers_to_close.end(); ++it) { |
+ (*it)->ResetBeforeUnloadHandlers(); |
+ } |
+ } |
+} |
+ |
+// static |
void BrowserList::SetLastActive(Browser* browser) { |
content::RecordAction(UserMetricsAction("ActiveBrowserChanged")); |
BrowserList* browser_list = GetInstance(browser->host_desktop_type()); |