1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 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" 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/tabs/tab_strip_model.h" 1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/chrome_switches.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h" 14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents_view.h" 16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_service.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( 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen switches::kGuestSession)), 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen waiting_for_browser_(false) { 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserList::AddObserver(this); 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch notification_registrar_.Add(this, NotificationType::APP_EXITING, 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabCloseableStateWatcher::~TabCloseableStateWatcher() { 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserList::RemoveObserver(this); 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!browser_shutdown::ShuttingDownWithoutClosingBrowsers()) 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(tabstrip_watchers_.empty()); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TabCloseableStateWatcher::CanCloseTab(const Browser* browser) const { 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return browser->type() != Browser::TYPE_NORMAL ? true : 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (can_close_tab_ || waiting_for_browser_); 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TabCloseableStateWatcher::CanCloseBrowser(Browser* browser) { 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserActionType action_type; 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool can_close = CanCloseBrowserImpl(browser, &action_type); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (action_type == OPEN_WINDOW) { 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->NewWindow(); 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (action_type == OPEN_NTP) { 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NTP will be opened before closing last tab (via TabStripModelObserver:: 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TabClosingAt), close all tabs now. 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->CloseAllTabs(); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return can_close; 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::OnWindowCloseCanceled(Browser* browser) { 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This could be a call to cancel APP_EXITING if user doesn't proceed with 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // unloading handler. 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (signing_off_) { 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signing_off_ = false; 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CheckAndUpdateState(browser); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabCloseableStateWatcher, BrowserList::Observer implementation: 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::OnBrowserAdded(const Browser* browser) { 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen waiting_for_browser_ = false; 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only normal browsers may affect closeable state. 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (browser->type() != Browser::TYPE_NORMAL) 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create TabStripWatcher to observe tabstrip of new browser. 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tabstrip_watchers_.push_back(new TabStripWatcher(this, browser)); 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When a normal browser is just added, there's no tabs yet, so we wait till 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TabInsertedAt notification to check for change in state. 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 127731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid TabCloseableStateWatcher::OnBrowserRemoved(const Browser* browser) { 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only normal browsers may affect closeable state. 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (browser->type() != Browser::TYPE_NORMAL) 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Remove TabStripWatcher for browser that is being removed. 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<TabStripWatcher*>::iterator it = tabstrip_watchers_.begin(); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it != tabstrip_watchers_.end(); ++it) { 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((*it)->browser() == browser) { 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete (*it); 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tabstrip_watchers_.erase(it); 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CheckAndUpdateState(NULL); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabCloseableStateWatcher, NotificationObserver implementation: 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::Observe(NotificationType type, 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, const NotificationDetails& details) { 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type.value != NotificationType::APP_EXITING) 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!signing_off_) { 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signing_off_ = true; 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetCloseableState(true); 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabCloseableStateWatcher, private 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::OnTabStripChanged(const Browser* browser, 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool closing_last_tab) { 163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (waiting_for_browser_) 164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!closing_last_tab) { 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CheckAndUpdateState(browser); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Before closing last tab, open new window or NTP if necessary. 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserActionType action_type; 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CanCloseBrowserImpl(browser, &action_type); 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (action_type != NONE) { 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* mutable_browser = const_cast<Browser*>(browser); 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (action_type == OPEN_WINDOW) 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mutable_browser->NewWindow(); 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else if (action_type == OPEN_NTP) 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mutable_browser->NewTab(); 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::CheckAndUpdateState( 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const Browser* browser_to_check) { 185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (waiting_for_browser_ || signing_off_ || tabstrip_watchers_.empty() || 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (browser_to_check && browser_to_check->type() != Browser::TYPE_NORMAL)) 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool new_can_close; 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tabstrip_watchers_.size() > 1) { 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_can_close = true; 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { // There's only 1 normal browser. 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser_to_check) 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser_to_check = tabstrip_watchers_[0]->browser(); 196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (browser_to_check->profile()->IsOffTheRecord() && !guest_session_) { 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_can_close = true; 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* tabstrip_model = browser_to_check->tabstrip_model(); 200731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (tabstrip_model->count() == 1) { 201201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch new_can_close = 202201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch tabstrip_model->GetTabContentsAt(0)->tab_contents()->GetURL() != 203201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch GURL(chrome::kChromeUINewTabURL); // Tab is not NewTabPage. 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_can_close = true; 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetCloseableState(new_can_close); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabCloseableStateWatcher::SetCloseableState(bool closeable) { 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (can_close_tab_ == closeable) // No change in state. 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch can_close_tab_ = closeable; 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Notify of change in tab closeable state. 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::current()->Notify( 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::TAB_CLOSEABLE_STATE_CHANGED, 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources(), 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Details<bool>(&can_close_tab_)); 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool TabCloseableStateWatcher::CanCloseBrowserImpl( 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const Browser* browser, 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserActionType* action_type) { 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *action_type = NONE; 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If we're waiting for a new browser allow the close. 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (waiting_for_browser_) 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Browser is always closeable when signing off. 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (signing_off_) 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Non-normal browsers are always closeable. 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (browser->type() != Browser::TYPE_NORMAL) 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If this is not the last normal browser, it's always closeable. 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tabstrip_watchers_.size() > 1) 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If last normal browser is incognito, open a non-incognito window, and allow 248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // closing of incognito one (if not guest). When this happens we need to wait 249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // for the new browser before doing any other actions as the new browser may 250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // be created by way of session restore, which is async. 251731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (browser->profile()->IsOffTheRecord() && !guest_session_) { 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *action_type = OPEN_WINDOW; 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen waiting_for_browser_ = true; 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If tab is not closeable, browser is not closeable. 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!can_close_tab_) 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Otherwise, close existing tabs, and deny closing of browser. 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TabClosingAt will open NTP when the last tab is being closed. 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *action_type = OPEN_NTP; 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace chromeos 268