Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(973)

Unified Diff: chrome/browser/ui/fast_unload_controller.cc

Issue 2681203002: Add Browser::SkipCallBeforeUnload so that the browser windows can be closed regardless of beforeunl… (Closed)
Patch Set: cr - remove delegate in UnloadController Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/fast_unload_controller.cc
diff --git a/chrome/browser/ui/fast_unload_controller.cc b/chrome/browser/ui/fast_unload_controller.cc
index 73ee5dc366a361dad76e84ee5bbedee0b174d9fc..add48b149446e25ca2899372a7c297cc82a0e08f 100644
--- a/chrome/browser/ui/fast_unload_controller.cc
+++ b/chrome/browser/ui/fast_unload_controller.cc
@@ -16,12 +16,12 @@
#include "chrome/browser/ui/tab_contents/core_tab_helper.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/tabs/tab_strip_model_delegate.h"
+#include "chrome/browser/ui/unload_controller_web_contents_delegate.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_delegate.h"
#include "extensions/features/features.h"
#if BUILDFLAG(ENABLE_EXTENSIONS)
@@ -32,37 +32,14 @@
namespace chrome {
////////////////////////////////////////////////////////////////////////////////
-// DetachedWebContentsDelegate will delete web contents when they close.
-class FastUnloadController::DetachedWebContentsDelegate
- : public content::WebContentsDelegate {
- public:
- DetachedWebContentsDelegate() { }
- ~DetachedWebContentsDelegate() override {}
-
- private:
- // WebContentsDelegate implementation.
- bool ShouldSuppressDialogs(content::WebContents* source) override {
- return true; // Return true so dialogs are suppressed.
- }
-
- void CloseContents(content::WebContents* source) override {
- // Finished detached close.
- // FastUnloadController will observe
- // |NOTIFICATION_WEB_CONTENTS_DISCONNECTED|.
- delete source;
- }
-
- DISALLOW_COPY_AND_ASSIGN(DetachedWebContentsDelegate);
-};
-
-////////////////////////////////////////////////////////////////////////////////
// FastUnloadController, public:
FastUnloadController::FastUnloadController(Browser* browser)
: browser_(browser),
tab_needing_before_unload_ack_(NULL),
is_attempting_to_close_browser_(false),
- detached_delegate_(new DetachedWebContentsDelegate()),
+ detached_delegate_(
+ base::MakeUnique<UnloadControllerWebContentsDelegate>()),
weak_factory_(this) {
browser_->tab_strip_model()->AddObserver(this);
}
@@ -156,7 +133,7 @@ bool FastUnloadController::BeforeUnloadFired(content::WebContents* contents,
// Now that beforeunload has fired, queue the tab to fire unload.
tab_needing_before_unload_ack_ = NULL;
tabs_needing_unload_.insert(contents);
- ProcessPendingTabs();
+ ProcessPendingTabs(false);
// We want to handle firing the unload event ourselves since we want to
// fire all the beforeunload events before attempting to fire the unload
// events should the user cancel closing the browser.
@@ -199,24 +176,26 @@ bool FastUnloadController::ShouldCloseWindow() {
// Cases 2 and 3.
on_close_confirmed_.Reset();
- ProcessPendingTabs();
+ ProcessPendingTabs(false);
return false;
}
-bool FastUnloadController::CallBeforeUnloadHandlers(
+bool FastUnloadController::TryToCloseWindow(
+ bool skip_beforeunload,
const base::Callback<void(bool)>& on_close_confirmed) {
-// The devtools browser gets its beforeunload events as the results of
-// intercepting events from the inspected tab, so don't send them here as well.
+ // The devtools browser gets its beforeunload events as the results of
+ // intercepting events from the inspected tab, so don't send them here as
+ // well.
if (browser_->is_devtools() || !TabsNeedBeforeUnloadFired())
return false;
on_close_confirmed_ = on_close_confirmed;
is_attempting_to_close_browser_ = true;
- ProcessPendingTabs();
- return true;
+ ProcessPendingTabs(skip_beforeunload);
+ return !skip_beforeunload;
}
-void FastUnloadController::ResetBeforeUnloadHandlers() {
+void FastUnloadController::ResetTryToCloseWindow() {
if (!is_calling_before_unload_handlers())
return;
CancelWindowClose();
@@ -252,10 +231,7 @@ bool FastUnloadController::HasCompletedUnloadProcessing() const {
tabs_needing_unload_ack_.empty();
}
-void FastUnloadController::CancelWindowClose() {
- // Closing of window can be canceled from a beforeunload handler.
- DCHECK(is_attempting_to_close_browser_);
- tabs_needing_before_unload_.clear();
+void FastUnloadController::CancelTabNeedingBeforeUnloadAck() {
if (tab_needing_before_unload_ack_ != NULL) {
CoreTabHelper* core_tab_helper =
CoreTabHelper::FromWebContents(tab_needing_before_unload_ack_);
@@ -263,6 +239,13 @@ void FastUnloadController::CancelWindowClose() {
DevToolsWindow::OnPageCloseCanceled(tab_needing_before_unload_ack_);
tab_needing_before_unload_ack_ = NULL;
}
+}
+
+void FastUnloadController::CancelWindowClose() {
+ // Closing of window can be canceled from a beforeunload handler.
+ DCHECK(is_attempting_to_close_browser_);
+ tabs_needing_before_unload_.clear();
+ CancelTabNeedingBeforeUnloadAck();
for (WebContentsSet::iterator it = tabs_needing_unload_.begin();
it != tabs_needing_unload_.end(); it++) {
content::WebContents* contents = *it;
@@ -382,7 +365,7 @@ bool FastUnloadController::DetachWebContents(content::WebContents* contents) {
return false;
}
-void FastUnloadController::ProcessPendingTabs() {
+void FastUnloadController::ProcessPendingTabs(bool skip_beforeunload) {
if (!is_attempting_to_close_browser_) {
// Because we might invoke this after a delay it's possible for the value of
// is_attempting_to_close_browser_ to have changed since we scheduled the
@@ -391,39 +374,54 @@ void FastUnloadController::ProcessPendingTabs() {
}
if (tab_needing_before_unload_ack_ != NULL) {
- // Wait for |BeforeUnloadFired| before proceeding.
- return;
+ if (skip_beforeunload) {
+ // Cancel and skip the ongoing before unload event.
+ tabs_needing_before_unload_.insert(tab_needing_before_unload_ack_);
+ CancelTabNeedingBeforeUnloadAck();
+ } else {
+ // Wait for |BeforeUnloadFired| before proceeding.
+ return;
+ }
}
// Process a beforeunload handler.
if (!tabs_needing_before_unload_.empty()) {
- WebContentsSet::iterator it = tabs_needing_before_unload_.begin();
- content::WebContents* contents = *it;
- tabs_needing_before_unload_.erase(it);
- // Null check render_view_host here as this gets called on a PostTask and
- // the tab's render_view_host may have been nulled out.
- if (contents->GetRenderViewHost()) {
- tab_needing_before_unload_ack_ = contents;
-
- CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
- core_tab_helper->OnCloseStarted();
-
- // If there's a devtools window attached to |contents|,
- // we would like devtools to call its own beforeunload handlers first,
- // and then call beforeunload handlers for |contents|.
- // See DevToolsWindow::InterceptPageBeforeUnload for details.
- if (!DevToolsWindow::InterceptPageBeforeUnload(contents))
- contents->DispatchBeforeUnload();
+ if (skip_beforeunload) {
+ tabs_needing_unload_.insert(tabs_needing_before_unload_.begin(),
+ tabs_needing_before_unload_.end());
+ tabs_needing_before_unload_.clear();
} else {
- ProcessPendingTabs();
+ WebContentsSet::iterator it = tabs_needing_before_unload_.begin();
+ content::WebContents* contents = *it;
+ tabs_needing_before_unload_.erase(it);
+ // Null check render_view_host here as this gets called on a PostTask and
+ // the tab's render_view_host may have been nulled out.
+ if (contents->GetRenderViewHost()) {
+ tab_needing_before_unload_ack_ = contents;
+
+ CoreTabHelper* core_tab_helper =
+ CoreTabHelper::FromWebContents(contents);
+ core_tab_helper->OnCloseStarted();
+
+ // If there's a devtools window attached to |contents|,
+ // we would like devtools to call its own beforeunload handlers first,
+ // and then call beforeunload handlers for |contents|.
+ // See DevToolsWindow::InterceptPageBeforeUnload for details.
+ if (!DevToolsWindow::InterceptPageBeforeUnload(contents))
+ contents->DispatchBeforeUnload();
+ } else {
+ ProcessPendingTabs(skip_beforeunload);
+ }
+ return;
}
- return;
}
if (is_calling_before_unload_handlers()) {
- on_close_confirmed_.Run(true);
+ if (!skip_beforeunload)
+ on_close_confirmed_.Run(true);
return;
}
+
// Process all the unload handlers. (The beforeunload handlers have finished.)
if (!tabs_needing_unload_.empty()) {
browser_->OnWindowClosing();
@@ -494,7 +492,7 @@ void FastUnloadController::ClearUnloadState(content::WebContents* contents) {
void FastUnloadController::PostTaskForProcessPendingTabs() {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&FastUnloadController::ProcessPendingTabs,
- weak_factory_.GetWeakPtr()));
+ weak_factory_.GetWeakPtr(), false));
}
} // namespace chrome

Powered by Google App Engine
This is Rietveld 408576698