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