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

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

Issue 11016023: Quickly close tabs/window with long-running unload handlers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add UnloadController class comment. Created 8 years, 2 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/unload_detached_handler.cc
diff --git a/chrome/browser/ui/unload_detached_handler.cc b/chrome/browser/ui/unload_detached_handler.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0cf1c3b1115bb9c644790a8d59d3f3501b6735ca
--- /dev/null
+++ b/chrome/browser/ui/unload_detached_handler.cc
@@ -0,0 +1,88 @@
+// 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.
+
+#include "chrome/browser/ui/unload_detached_handler.h"
+
+#include "base/message_loop.h"
+#include "chrome/browser/ui/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
+
+namespace chrome {
+
+////////////////////////////////////////////////////////////////////////////////
+// WebContentsDelegate implementation. This owns the TabContents supplied to the
+// constructor.
+class UnloadDetachedHandler::WebContentsDelegateImpl
+ : public content::WebContentsDelegate {
+ public:
+ WebContentsDelegateImpl(UnloadDetachedHandler* handler,
+ TabContents* tab_contents)
+ : handler_(handler),
+ tab_contents_(tab_contents) {
+ tab_contents->web_contents()->SetDelegate(this);
+ }
+
+ virtual bool ShouldSuppressDialogs() OVERRIDE {
+ return true; // Return true so dialogs are suppressed.
+ }
+
+ virtual void CloseContents(content::WebContents* source) OVERRIDE {
+ handler_->Destroy(this);
+ }
+
+ private:
+ UnloadDetachedHandler* const handler_;
+ scoped_ptr<TabContents> tab_contents_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(WebContentsDelegateImpl);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// UnloadDetachedHandler implementation.
+
+UnloadDetachedHandler::UnloadDetachedHandler(const TabsClosedCallback& callback)
+ : tabs_closed_callback_(callback) {
+}
+
+UnloadDetachedHandler::~UnloadDetachedHandler() {
+}
+
+bool UnloadDetachedHandler::DetachWebContents(
+ TabStripModel* tab_strip_model, content::WebContents* web_contents) {
+ if (tab_strip_model->count() > 1) {
+ // Only allow tab to be detached if it is not the last one.
+ // Otherwise, the tab_strip_model would notify the browser that it is empty.
+ // And, the browser would close without waiting for the unload handlers.
+ int index = tab_strip_model->GetIndexOfWebContents(web_contents);
+ if (index != TabStripModel::kNoTab &&
+ web_contents->NeedToFireBeforeUnload()) {
+ TabContents* tab_contents = tab_strip_model->DetachTabContentsAt(index);
+ delegates_.push_back(new WebContentsDelegateImpl(this, tab_contents));
Ben Goodger (Google) 2012/10/29 22:12:43 rather than creating a delegate per-tab, can you j
slamm 2012/10/31 18:03:59 Done. Thats for the suggestion -- much simpler.
+ web_contents->OnUnloadDetachedStarted();
+ return true;
+ }
+ }
+ return false;
+}
+
+bool UnloadDetachedHandler::HasTabs() {
+ return !delegates_.empty();
Ben Goodger (Google) 2012/10/29 22:12:43 if you don't have a list of delegates, you can at
slamm 2012/10/31 18:03:59 I made a web_contents -> tab_contents map. The tab
+}
+
+void UnloadDetachedHandler::Destroy(WebContentsDelegateImpl* delegate) {
+ ScopedVector<WebContentsDelegateImpl>::iterator i =
+ std::find(delegates_.begin(), delegates_.end(), delegate);
+ DCHECK(i != delegates_.end());
+
+ // The delegate's method is a caller on the stack, so schedule the deletion
+ // for later.
+ delegates_.weak_erase(i);
+ MessageLoop::current()->DeleteSoon(FROM_HERE, delegate);
+
+ tabs_closed_callback_.Run();
+}
+
+} // namespace chrome

Powered by Google App Engine
This is Rietveld 408576698