1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_CHROMEOS_TAB_CLOSEABLE_STATE_WATCHER_H_ 6 #define CHROME_BROWSER_CHROMEOS_TAB_CLOSEABLE_STATE_WATCHER_H_ 7 #pragma once 8 9 #include <vector> 10 11 #include "chrome/browser/tab_closeable_state_watcher.h" 12 #include "chrome/browser/tabs/tab_strip_model_observer.h" 13 #include "chrome/browser/ui/browser_list.h" 14 #include "content/common/notification_registrar.h" 15 16 namespace chromeos { 17 18 // This class overrides ::TabCloseableStateWatcher to allow or disallow tabs or 19 // browsers to be closed based on increase or decrease in number of tabs or 20 // browsers. We only do this on Chromeos and only for non-tests. 21 // 22 // Normal session: 23 // 1) A tab, and hence its containing browser, is not closeable if the tab is 24 // the last NewTabPage in the last normal non-incognito browser and user is not 25 // signing off. 26 // 2) Otherwise, if user closes a normal non-incognito browser or the last tab 27 // in it, the browser stays open, the existing tabs are closed, and a new 28 // NewTabPage is opened. 29 // 3) Or, if user closes a normal incognito browser or the last tab in it, the 30 // browser closes, a new non-incognito normal browser is opened with a 31 // NewTabPage (which, by rule 1, will not be closeable). 32 // 33 // BWSI session (all browsers are incognito): 34 // Almost the same as in the normal session, but 35 // 1) A tab, and hence its containing browser, is not closeable if the tab is 36 // the last NewTabPage in the last browser (again, all browsers are incognito 37 // browsers). 38 // 2-3) Otherwise, if user closes a normal incognito browser or the last tab in 39 // it, the browser stays open, the existing tabs are closed, and a new 40 // NewTabPage is open. 41 42 class TabCloseableStateWatcher : public ::TabCloseableStateWatcher, 43 public BrowserList::Observer, 44 public NotificationObserver { 45 public: 46 TabCloseableStateWatcher(); 47 virtual ~TabCloseableStateWatcher(); 48 49 // TabCloseableStateWatcher implementation: 50 virtual bool CanCloseTab(const Browser* browser) const; 51 virtual bool CanCloseBrowser(Browser* browser); 52 virtual void OnWindowCloseCanceled(Browser* browser); 53 54 private: 55 enum BrowserActionType { 56 NONE = 0, // Nothing to do. 57 OPEN_WINDOW = 1, // Opens a regular (i.e. non-incognito) normal browser. 58 OPEN_NTP = 2, // Opens a NewTabPage. 59 }; 60 61 // BrowserList::Observer implementation: 62 virtual void OnBrowserAdded(const Browser* browser); 63 virtual void OnBrowserRemoved(const Browser* browser); 64 65 // NotificationObserver implementation: 66 virtual void Observe(NotificationType type, const NotificationSource& source, 67 const NotificationDetails& details); 68 69 // Called by private class TabStripWatcher for TabStripModelObserver 70 // notifications. 71 // |closing_last_tab| is true if the tab strip is closing the last tab. 72 virtual void OnTabStripChanged(const Browser* browser, bool closing_last_tab); 73 74 // Utility functions. 75 76 // Checks the closeable state of tab. If it has changed, updates it and 77 // notifies all normal browsers. 78 // |browser_to_check| is the browser whose closeable state the caller is 79 // interested in; can be NULL if caller is interested in all browsers, e.g. 80 // when a browser is being removed and there's no specific browser to check. 81 void CheckAndUpdateState(const Browser* browser_to_check); 82 83 // Sets the new closeable state and fires notification. 84 void SetCloseableState(bool closeable); 85 86 // Returns true if closing of |browser| is permitted. 87 // |action_type| is the action to take regardless if browser is closeable. 88 bool CanCloseBrowserImpl(const Browser* browser, 89 BrowserActionType* action_type); 90 91 // Data members. 92 93 // This is true if tab can be closed; it's updated in CheckAndUpdateState and 94 // when sign-off notification is received. 95 bool can_close_tab_; 96 97 // This is true when sign-off notification is received; it lets us know to 98 // allow closing of all tabs and browsers in this situation. 99 bool signing_off_; 100 101 // Is in guest session? 102 bool guest_session_; 103 104 // Set to true if we're waiting for a new browser to be created. When true we 105 // uncoditionally allow everything as we know a browser is in the process of 106 // being created. 107 bool waiting_for_browser_; 108 109 NotificationRegistrar notification_registrar_; 110 111 // TabStripWatcher is a TabStripModelObserver that funnels all interesting 112 // methods to TabCloseableStateWatcher::OnTabStripChanged. TabStripWatcher is 113 // needed so we know which browser the TabStripModelObserver method relates 114 // to. 115 class TabStripWatcher : public TabStripModelObserver { 116 public: 117 TabStripWatcher(TabCloseableStateWatcher* main_watcher, 118 const Browser* browser); 119 virtual ~TabStripWatcher(); 120 121 // TabStripModelObserver implementation: 122 virtual void TabInsertedAt(TabContentsWrapper* contents, int index, 123 bool foreground); 124 virtual void TabClosingAt(TabStripModel* tab_strip_model, 125 TabContentsWrapper* contents, 126 int index); 127 virtual void TabDetachedAt(TabContentsWrapper* contents, int index); 128 virtual void TabChangedAt(TabContentsWrapper* contents, int index, 129 TabChangeType change_type); 130 131 const Browser* browser() const { 132 return browser_; 133 } 134 135 private: 136 TabCloseableStateWatcher* main_watcher_; 137 const Browser* browser_; 138 139 DISALLOW_COPY_AND_ASSIGN(TabStripWatcher); 140 }; 141 142 friend class TabStripWatcher; 143 144 std::vector<TabStripWatcher*> tabstrip_watchers_; 145 146 DISALLOW_COPY_AND_ASSIGN(TabCloseableStateWatcher); 147 }; 148 149 } // namespace chromeos 150 151 #endif // CHROME_BROWSER_CHROMEOS_TAB_CLOSEABLE_STATE_WATCHER_H_ 152