tab_closeable_state_watcher.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/tab_closeable_state_watcher.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/command_line.h"
83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/browser_shutdown.h"
921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_contents.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_contents_view.h"
123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/tabs/tab_strip_model.h"
1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/chrome_switches.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/notification_service.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chromeos {
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabCloseableStateWatcher::TabStripWatcher, public:
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabCloseableStateWatcher::TabStripWatcher::TabStripWatcher(
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TabCloseableStateWatcher* main_watcher, const Browser* browser)
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : main_watcher_(main_watcher),
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser_(browser) {
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  browser_->tabstrip_model()->AddObserver(this);
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabCloseableStateWatcher::TabStripWatcher::~TabStripWatcher() {
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  browser_->tabstrip_model()->RemoveObserver(this);
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabCloseableStateWatcher::TabStripWatcher,
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//     TabStripModelObserver implementation:
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::TabStripWatcher::TabInsertedAt(
39201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    TabContentsWrapper* tab_contents, int index, bool foreground) {
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  main_watcher_->OnTabStripChanged(browser_, false);
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::TabStripWatcher::TabClosingAt(
44201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    TabStripModel* tab_strip_model,
45201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    TabContentsWrapper* tab_contents,
46201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    int index) {
47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Check if the last tab is closing.
48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (tab_strip_model->count() == 1)
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    main_watcher_->OnTabStripChanged(browser_, true);
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::TabStripWatcher::TabDetachedAt(
53201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    TabContentsWrapper* tab_contents, int index) {
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  main_watcher_->OnTabStripChanged(browser_, false);
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::TabStripWatcher::TabChangedAt(
58201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    TabContentsWrapper* tab_contents, int index, TabChangeType change_type) {
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  main_watcher_->OnTabStripChanged(browser_, false);
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabCloseableStateWatcher, public:
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabCloseableStateWatcher::TabCloseableStateWatcher()
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : can_close_tab_(true),
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      signing_off_(false),
68731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      guest_session_(
69731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          CommandLine::ForCurrentProcess()->HasSwitch(
70731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick              switches::kGuestSession)) {
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserList::AddObserver(this);
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  notification_registrar_.Add(this, NotificationType::APP_EXITING,
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationService::AllSources());
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabCloseableStateWatcher::~TabCloseableStateWatcher() {
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserList::RemoveObserver(this);
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!browser_shutdown::ShuttingDownWithoutClosingBrowsers())
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK(tabstrip_watchers_.empty());
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TabCloseableStateWatcher::CanCloseTab(const Browser* browser) const {
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return browser->type() != Browser::TYPE_NORMAL ? true : can_close_tab_;
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TabCloseableStateWatcher::CanCloseBrowser(Browser* browser) {
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserActionType action_type;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool can_close = CanCloseBrowserImpl(browser, &action_type);
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (action_type == OPEN_WINDOW) {
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser->NewWindow();
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (action_type == OPEN_NTP) {
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // NTP will be opened before closing last tab (via TabStripModelObserver::
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TabClosingAt), close all tabs now.
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser->CloseAllTabs();
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return can_close;
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::OnWindowCloseCanceled(Browser* browser) {
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This could be a call to cancel APP_EXITING if user doesn't proceed with
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // unloading handler.
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (signing_off_) {
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    signing_off_ = false;
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CheckAndUpdateState(browser);
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabCloseableStateWatcher, BrowserList::Observer implementation:
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::OnBrowserAdded(const Browser* browser) {
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Only normal browsers may affect closeable state.
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (browser->type() != Browser::TYPE_NORMAL)
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create TabStripWatcher to observe tabstrip of new browser.
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  tabstrip_watchers_.push_back(new TabStripWatcher(this, browser));
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // When a normal browser is just added, there's no tabs yet, so we wait till
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TabInsertedAt notification to check for change in state.
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid TabCloseableStateWatcher::OnBrowserRemoved(const Browser* browser) {
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Only normal browsers may affect closeable state.
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (browser->type() != Browser::TYPE_NORMAL)
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Remove TabStripWatcher for browser that is being removed.
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (std::vector<TabStripWatcher*>::iterator it = tabstrip_watchers_.begin();
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       it != tabstrip_watchers_.end(); ++it) {
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if ((*it)->browser() == browser) {
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delete (*it);
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tabstrip_watchers_.erase(it);
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CheckAndUpdateState(NULL);
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabCloseableStateWatcher, NotificationObserver implementation:
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::Observe(NotificationType type,
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const NotificationSource& source, const NotificationDetails& details) {
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (type.value != NotificationType::APP_EXITING)
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!signing_off_) {
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    signing_off_ = true;
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SetCloseableState(true);
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabCloseableStateWatcher, private
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::OnTabStripChanged(const Browser* browser,
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool closing_last_tab) {
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!closing_last_tab) {
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CheckAndUpdateState(browser);
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Before closing last tab, open new window or NTP if necessary.
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserActionType action_type;
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CanCloseBrowserImpl(browser, &action_type);
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (action_type != NONE) {
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Browser* mutable_browser = const_cast<Browser*>(browser);
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (action_type == OPEN_WINDOW)
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      mutable_browser->NewWindow();
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    else if (action_type == OPEN_NTP)
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      mutable_browser->NewTab();
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::CheckAndUpdateState(
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const Browser* browser_to_check) {
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We shouldn't update state if we're signing off, or there's no normal
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // browser, or browser is always closeable.
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (signing_off_ || tabstrip_watchers_.empty() ||
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (browser_to_check && browser_to_check->type() != Browser::TYPE_NORMAL))
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool new_can_close;
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (tabstrip_watchers_.size() > 1) {
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    new_can_close = true;
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {  // There's only 1 normal browser.
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!browser_to_check)
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser_to_check = tabstrip_watchers_[0]->browser();
191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (browser_to_check->profile()->IsOffTheRecord() && !guest_session_) {
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new_can_close = true;
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      TabStripModel* tabstrip_model = browser_to_check->tabstrip_model();
195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (tabstrip_model->count() == 1) {
196201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        new_can_close =
197201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch            tabstrip_model->GetTabContentsAt(0)->tab_contents()->GetURL() !=
198201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                GURL(chrome::kChromeUINewTabURL);  // Tab is not NewTabPage.
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new_can_close = true;
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetCloseableState(new_can_close);
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::SetCloseableState(bool closeable) {
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (can_close_tab_ == closeable)  // No change in state.
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  can_close_tab_ = closeable;
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Notify of change in tab closeable state.
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotificationService::current()->Notify(
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationType::TAB_CLOSEABLE_STATE_CHANGED,
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationService::AllSources(),
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Details<bool>(&can_close_tab_));
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TabCloseableStateWatcher::CanCloseBrowserImpl(const Browser* browser,
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BrowserActionType* action_type) const {
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *action_type = NONE;
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Browser is always closeable when signing off.
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (signing_off_)
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Non-normal browsers are always closeable.
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (browser->type() != Browser::TYPE_NORMAL)
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If this is not the last normal browser, it's always closeable.
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (tabstrip_watchers_.size() > 1)
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If last normal browser is incognito, open a non-incognito window,
238731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // and allow closing of incognito one (if not guest).
239731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (browser->profile()->IsOffTheRecord() && !guest_session_) {
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *action_type = OPEN_WINDOW;
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If tab is not closeable, browser is not closeable.
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!can_close_tab_)
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Otherwise, close existing tabs, and deny closing of browser.
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TabClosingAt will open NTP when the last tab is being closed.
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *action_type = OPEN_NTP;
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace chromeos
255