| // Copyright (c) 2011 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/instant/instant_unload_handler.h" |
| |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_navigator.h" |
| #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| #include "content/browser/renderer_host/render_view_host.h" |
| #include "content/browser/tab_contents/tab_contents.h" |
| #include "content/browser/tab_contents/tab_contents_delegate.h" |
| |
| // TabContentsDelegate implementation. This owns the TabContents supplied to the |
| // constructor. |
| class InstantUnloadHandler::TabContentsDelegateImpl |
| : public TabContentsDelegate { |
| public: |
| TabContentsDelegateImpl(InstantUnloadHandler* handler, |
| TabContentsWrapper* tab_contents, |
| int index) |
| : handler_(handler), |
| tab_contents_(tab_contents), |
| index_(index) { |
| tab_contents->tab_contents()->set_delegate(this); |
| } |
| |
| ~TabContentsDelegateImpl() { |
| } |
| |
| // Releases ownership of the TabContentsWrapper to the caller. |
| TabContentsWrapper* ReleaseTab() { |
| TabContentsWrapper* tab = tab_contents_.release(); |
| tab->tab_contents()->set_delegate(NULL); |
| return tab; |
| } |
| |
| // See description above field. |
| int index() const { return index_; } |
| |
| // TabContentsDelegate overrides: |
| virtual void WillRunBeforeUnloadConfirm() { |
| handler_->Activate(this); |
| } |
| |
| virtual bool ShouldSuppressDialogs() { |
| return true; // Return true so dialogs are suppressed. |
| } |
| |
| virtual void CloseContents(TabContents* source) { |
| handler_->Destroy(this); |
| } |
| |
| // All of the following are overriden to do nothing (they are pure |
| // virtual). When we're attemping to close the tab, none of this matters. |
| virtual void OpenURLFromTab(TabContents* source, |
| const GURL& url, const GURL& referrer, |
| WindowOpenDisposition disposition, |
| PageTransition::Type transition) {} |
| virtual void NavigationStateChanged(const TabContents* source, |
| unsigned changed_flags) {} |
| virtual void AddNewContents(TabContents* source, |
| TabContents* new_contents, |
| WindowOpenDisposition disposition, |
| const gfx::Rect& initial_pos, |
| bool user_gesture) {} |
| virtual void ActivateContents(TabContents* contents) {} |
| virtual void DeactivateContents(TabContents* contents) {} |
| virtual void LoadingStateChanged(TabContents* source) {} |
| virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {} |
| virtual void UpdateTargetURL(TabContents* source, const GURL& url) {} |
| |
| private: |
| InstantUnloadHandler* handler_; |
| scoped_ptr<TabContentsWrapper> tab_contents_; |
| |
| // The index |tab_contents_| was originally at. If we add the tab back we add |
| // it at this index. |
| const int index_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TabContentsDelegateImpl); |
| }; |
| |
| InstantUnloadHandler::InstantUnloadHandler(Browser* browser) |
| : browser_(browser) { |
| } |
| |
| InstantUnloadHandler::~InstantUnloadHandler() { |
| } |
| |
| void InstantUnloadHandler::RunUnloadListenersOrDestroy(TabContentsWrapper* tab, |
| int index) { |
| if (!tab->tab_contents()->NeedToFireBeforeUnload()) { |
| // Tab doesn't have any before unload listeners and can be safely deleted. |
| delete tab; |
| return; |
| } |
| |
| // Tab has before unload listener. Install a delegate and fire the before |
| // unload listener. |
| TabContentsDelegateImpl* delegate = |
| new TabContentsDelegateImpl(this, tab, index); |
| delegates_.push_back(delegate); |
| // TODO: decide if we really want false here. false is used for tab closes, |
| // and is needed so that the tab correctly closes but it doesn't really match |
| // what's logically happening. |
| tab->tab_contents()->render_view_host()->FirePageBeforeUnload(false); |
| } |
| |
| void InstantUnloadHandler::Activate(TabContentsDelegateImpl* delegate) { |
| // Take ownership of the TabContents from the delegate. |
| TabContentsWrapper* tab = delegate->ReleaseTab(); |
| browser::NavigateParams params(browser_, tab); |
| params.disposition = NEW_FOREGROUND_TAB; |
| params.tabstrip_index = delegate->index(); |
| |
| // Remove (and delete) the delegate. |
| ScopedVector<TabContentsDelegateImpl>::iterator i = |
| std::find(delegates_.begin(), delegates_.end(), delegate); |
| DCHECK(i != delegates_.end()); |
| delegates_.erase(i); |
| delegate = NULL; |
| |
| // Add the tab back in. |
| browser::Navigate(¶ms); |
| } |
| |
| void InstantUnloadHandler::Destroy(TabContentsDelegateImpl* delegate) { |
| ScopedVector<TabContentsDelegateImpl>::iterator i = |
| std::find(delegates_.begin(), delegates_.end(), delegate); |
| DCHECK(i != delegates_.end()); |
| delegates_.erase(i); |
| } |