Chromium Code Reviews| 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 |