summaryrefslogtreecommitdiffstats
path: root/chrome/browser/instant/instant_unload_handler.cc
blob: d4e8e78cf132284e6745049f4706114b87e4a5b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// 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) OVERRIDE {
    handler_->Destroy(this);
  }

 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(&params);
}

void InstantUnloadHandler::Destroy(TabContentsDelegateImpl* delegate) {
  ScopedVector<TabContentsDelegateImpl>::iterator i =
      std::find(delegates_.begin(), delegates_.end(), delegate);
  DCHECK(i != delegates_.end());
  delegates_.erase(i);
}