Home | History | Annotate | Download | only in instant
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/instant/instant_unload_handler.h"
      6 
      7 #include "chrome/browser/ui/browser.h"
      8 #include "chrome/browser/ui/browser_navigator.h"
      9 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
     10 #include "content/browser/renderer_host/render_view_host.h"
     11 #include "content/browser/tab_contents/tab_contents.h"
     12 #include "content/browser/tab_contents/tab_contents_delegate.h"
     13 
     14 // TabContentsDelegate implementation. This owns the TabContents supplied to the
     15 // constructor.
     16 class InstantUnloadHandler::TabContentsDelegateImpl
     17     : public TabContentsDelegate {
     18  public:
     19   TabContentsDelegateImpl(InstantUnloadHandler* handler,
     20                           TabContentsWrapper* tab_contents,
     21                           int index)
     22       : handler_(handler),
     23         tab_contents_(tab_contents),
     24         index_(index) {
     25     tab_contents->tab_contents()->set_delegate(this);
     26   }
     27 
     28   ~TabContentsDelegateImpl() {
     29   }
     30 
     31   // Releases ownership of the TabContentsWrapper to the caller.
     32   TabContentsWrapper* ReleaseTab() {
     33     TabContentsWrapper* tab = tab_contents_.release();
     34     tab->tab_contents()->set_delegate(NULL);
     35     return tab;
     36   }
     37 
     38   // See description above field.
     39   int index() const { return index_; }
     40 
     41   // TabContentsDelegate overrides:
     42   virtual void WillRunBeforeUnloadConfirm() {
     43     handler_->Activate(this);
     44   }
     45 
     46   virtual bool ShouldSuppressDialogs() {
     47     return true;  // Return true so dialogs are suppressed.
     48   }
     49 
     50   virtual void CloseContents(TabContents* source) {
     51     handler_->Destroy(this);
     52   }
     53 
     54   // All of the following are overriden to do nothing (they are pure
     55   // virtual). When we're attemping to close the tab, none of this matters.
     56   virtual void OpenURLFromTab(TabContents* source,
     57                               const GURL& url, const GURL& referrer,
     58                               WindowOpenDisposition disposition,
     59                               PageTransition::Type transition) {}
     60   virtual void NavigationStateChanged(const TabContents* source,
     61                                       unsigned changed_flags) {}
     62   virtual void AddNewContents(TabContents* source,
     63                               TabContents* new_contents,
     64                               WindowOpenDisposition disposition,
     65                               const gfx::Rect& initial_pos,
     66                               bool user_gesture) {}
     67   virtual void ActivateContents(TabContents* contents) {}
     68   virtual void DeactivateContents(TabContents* contents) {}
     69   virtual void LoadingStateChanged(TabContents* source) {}
     70   virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {}
     71   virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
     72 
     73  private:
     74   InstantUnloadHandler* handler_;
     75   scoped_ptr<TabContentsWrapper> tab_contents_;
     76 
     77   // The index |tab_contents_| was originally at. If we add the tab back we add
     78   // it at this index.
     79   const int index_;
     80 
     81   DISALLOW_COPY_AND_ASSIGN(TabContentsDelegateImpl);
     82 };
     83 
     84 InstantUnloadHandler::InstantUnloadHandler(Browser* browser)
     85     : browser_(browser) {
     86 }
     87 
     88 InstantUnloadHandler::~InstantUnloadHandler() {
     89 }
     90 
     91 void InstantUnloadHandler::RunUnloadListenersOrDestroy(TabContentsWrapper* tab,
     92                                                        int index) {
     93   if (!tab->tab_contents()->NeedToFireBeforeUnload()) {
     94     // Tab doesn't have any before unload listeners and can be safely deleted.
     95     delete tab;
     96     return;
     97   }
     98 
     99   // Tab has before unload listener. Install a delegate and fire the before
    100   // unload listener.
    101   TabContentsDelegateImpl* delegate =
    102       new TabContentsDelegateImpl(this, tab, index);
    103   delegates_.push_back(delegate);
    104   // TODO: decide if we really want false here. false is used for tab closes,
    105   // and is needed so that the tab correctly closes but it doesn't really match
    106   // what's logically happening.
    107   tab->tab_contents()->render_view_host()->FirePageBeforeUnload(false);
    108 }
    109 
    110 void InstantUnloadHandler::Activate(TabContentsDelegateImpl* delegate) {
    111   // Take ownership of the TabContents from the delegate.
    112   TabContentsWrapper* tab = delegate->ReleaseTab();
    113   browser::NavigateParams params(browser_, tab);
    114   params.disposition = NEW_FOREGROUND_TAB;
    115   params.tabstrip_index = delegate->index();
    116 
    117   // Remove (and delete) the delegate.
    118   ScopedVector<TabContentsDelegateImpl>::iterator i =
    119       std::find(delegates_.begin(), delegates_.end(), delegate);
    120   DCHECK(i != delegates_.end());
    121   delegates_.erase(i);
    122   delegate = NULL;
    123 
    124   // Add the tab back in.
    125   browser::Navigate(&params);
    126 }
    127 
    128 void InstantUnloadHandler::Destroy(TabContentsDelegateImpl* delegate) {
    129   ScopedVector<TabContentsDelegateImpl>::iterator i =
    130       std::find(delegates_.begin(), delegates_.end(), delegate);
    131   DCHECK(i != delegates_.end());
    132   delegates_.erase(i);
    133 }
    134