| 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));
|
| + web_contents->OnUnloadDetachedStarted();
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool UnloadDetachedHandler::HasTabs() {
|
| + return !delegates_.empty();
|
| +}
|
| +
|
| +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
|
|
|