172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// found in the LICENSE file.
4201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/instant/instant_unload_handler.h"
6201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
7201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/ui/browser.h"
8201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/ui/browser_navigator.h"
921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h"
11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents_delegate.h"
13201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
14201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// TabContentsDelegate implementation. This owns the TabContents supplied to the
15201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// constructor.
16201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochclass InstantUnloadHandler::TabContentsDelegateImpl
17201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    : public TabContentsDelegate {
18201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch public:
19201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TabContentsDelegateImpl(InstantUnloadHandler* handler,
20201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          TabContentsWrapper* tab_contents,
21201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          int index)
22201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      : handler_(handler),
23201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        tab_contents_(tab_contents),
24201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        index_(index) {
25201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    tab_contents->tab_contents()->set_delegate(this);
26201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
27201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
28201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ~TabContentsDelegateImpl() {
29201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
30201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
31201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Releases ownership of the TabContentsWrapper to the caller.
32201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TabContentsWrapper* ReleaseTab() {
33201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    TabContentsWrapper* tab = tab_contents_.release();
34201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    tab->tab_contents()->set_delegate(NULL);
35201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return tab;
36201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
37201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
38201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // See description above field.
39201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  int index() const { return index_; }
40201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
41201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // TabContentsDelegate overrides:
42201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void WillRunBeforeUnloadConfirm() {
43201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    handler_->Activate(this);
44201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
45201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
46201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual bool ShouldSuppressDialogs() {
47201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return true;  // Return true so dialogs are suppressed.
48201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
49201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
50201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void CloseContents(TabContents* source) {
51201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    handler_->Destroy(this);
52201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
53201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
54201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // All of the following are overriden to do nothing (they are pure
55201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // virtual). When we're attemping to close the tab, none of this matters.
56201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void OpenURLFromTab(TabContents* source,
57201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                              const GURL& url, const GURL& referrer,
58201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                              WindowOpenDisposition disposition,
59201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                              PageTransition::Type transition) {}
60201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void NavigationStateChanged(const TabContents* source,
61201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                      unsigned changed_flags) {}
62201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void AddNewContents(TabContents* source,
63201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                              TabContents* new_contents,
64201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                              WindowOpenDisposition disposition,
65201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                              const gfx::Rect& initial_pos,
66201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                              bool user_gesture) {}
67201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void ActivateContents(TabContents* contents) {}
68201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void DeactivateContents(TabContents* contents) {}
69201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void LoadingStateChanged(TabContents* source) {}
70201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {}
71201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
72201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
73201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch private:
74201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  InstantUnloadHandler* handler_;
75201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<TabContentsWrapper> tab_contents_;
76201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
77201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // The index |tab_contents_| was originally at. If we add the tab back we add
78201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // it at this index.
79201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  const int index_;
80201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
81201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(TabContentsDelegateImpl);
82201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch};
83201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
84201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochInstantUnloadHandler::InstantUnloadHandler(Browser* browser)
85201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    : browser_(browser) {
86201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
87201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
88201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochInstantUnloadHandler::~InstantUnloadHandler() {
89201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
90201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
91201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid InstantUnloadHandler::RunUnloadListenersOrDestroy(TabContentsWrapper* tab,
92201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                       int index) {
93201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!tab->tab_contents()->NeedToFireBeforeUnload()) {
94201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Tab doesn't have any before unload listeners and can be safely deleted.
95201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    delete tab;
96201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;
97201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
98201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
99201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Tab has before unload listener. Install a delegate and fire the before
100201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // unload listener.
101201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TabContentsDelegateImpl* delegate =
102201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new TabContentsDelegateImpl(this, tab, index);
103201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  delegates_.push_back(delegate);
104201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // TODO: decide if we really want false here. false is used for tab closes,
105201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // and is needed so that the tab correctly closes but it doesn't really match
106201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // what's logically happening.
107201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  tab->tab_contents()->render_view_host()->FirePageBeforeUnload(false);
108201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
109201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
110201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid InstantUnloadHandler::Activate(TabContentsDelegateImpl* delegate) {
111201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Take ownership of the TabContents from the delegate.
112201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TabContentsWrapper* tab = delegate->ReleaseTab();
113201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  browser::NavigateParams params(browser_, tab);
114201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  params.disposition = NEW_FOREGROUND_TAB;
115201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  params.tabstrip_index = delegate->index();
116201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
117201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Remove (and delete) the delegate.
118201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ScopedVector<TabContentsDelegateImpl>::iterator i =
119201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      std::find(delegates_.begin(), delegates_.end(), delegate);
120201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(i != delegates_.end());
121201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  delegates_.erase(i);
122201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  delegate = NULL;
123201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
124201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Add the tab back in.
125201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  browser::Navigate(&params);
126201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
127201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
128201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid InstantUnloadHandler::Destroy(TabContentsDelegateImpl* delegate) {
129201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ScopedVector<TabContentsDelegateImpl>::iterator i =
130201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      std::find(delegates_.begin(), delegates_.end(), delegate);
131201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(i != delegates_.end());
132201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  delegates_.erase(i);
133201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
134