1 // Copyright (c) 2012 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_UI_BROWSER_LIST_H_ 6 #define CHROME_BROWSER_UI_BROWSER_LIST_H_ 7 8 #include <stddef.h> 9 10 #include <vector> 11 12 #include "base/callback_forward.h" 13 #include "base/containers/flat_set.h" 14 #include "base/lazy_instance.h" 15 #include "base/macros.h" 16 #include "base/observer_list.h" 17 #include "build/build_config.h" 18 19 #if defined(OS_ANDROID) 20 #error This file should only be included on desktop. 21 #endif 22 23 class Browser; 24 class Profile; 25 26 namespace base { 27 class FilePath; 28 } 29 30 class BrowserListObserver; 31 32 // Maintains a list of Browser objects. 33 class BrowserList { 34 public: 35 using BrowserSet = base::flat_set<Browser*>; 36 using BrowserVector = std::vector<Browser*>; 37 using CloseCallback = base::RepeatingCallback<void(const base::FilePath&)>; 38 using const_iterator = BrowserVector::const_iterator; 39 using const_reverse_iterator = BrowserVector::const_reverse_iterator; 40 41 // Returns the last active browser for this list. 42 Browser* GetLastActive() const; 43 begin()44 const_iterator begin() const { return browsers_.begin(); } end()45 const_iterator end() const { return browsers_.end(); } 46 empty()47 bool empty() const { return browsers_.empty(); } size()48 size_t size() const { return browsers_.size(); } 49 get(size_t index)50 Browser* get(size_t index) const { return browsers_[index]; } 51 52 // Returns iterated access to list of open browsers ordered by when 53 // they were last active. The underlying data structure is a vector 54 // and we push_back on recent access so a reverse iterator gives the 55 // latest accessed browser first. begin_last_active()56 const_reverse_iterator begin_last_active() const { 57 return last_active_browsers_.rbegin(); 58 } end_last_active()59 const_reverse_iterator end_last_active() const { 60 return last_active_browsers_.rend(); 61 } 62 63 // Returns the set of browsers that are currently in the closing state. currently_closing_browsers()64 const BrowserSet& currently_closing_browsers() const { 65 return currently_closing_browsers_; 66 } 67 68 static BrowserList* GetInstance(); 69 70 // Adds or removes |browser| from the list it is associated with. The browser 71 // object should be valid BEFORE these calls (for the benefit of observers), 72 // so notify and THEN delete the object. 73 static void AddBrowser(Browser* browser); 74 static void RemoveBrowser(Browser* browser); 75 76 // Adds and removes |observer| from the observer list for all desktops. 77 // Observers are responsible for making sure the notifying browser is relevant 78 // to them (e.g., on the specific desktop they care about if any). 79 static void AddObserver(BrowserListObserver* observer); 80 static void RemoveObserver(BrowserListObserver* observer); 81 82 // Moves all the browsers that show on workspace |new_workspace| to the end of 83 // the browser list (i.e. the browsers that were "activated" most recently). 84 static void MoveBrowsersInWorkspaceToFront(const std::string& new_workspace); 85 86 // Called by Browser objects when their window is activated (focused). This 87 // allows us to determine what the last active Browser was on each desktop. 88 static void SetLastActive(Browser* browser); 89 90 // Notifies the observers when the current active browser becomes not active. 91 static void NotifyBrowserNoLongerActive(Browser* browser); 92 93 // Notifies the observers when browser close was started. This may be called 94 // more than once for a particular browser. 95 static void NotifyBrowserCloseStarted(Browser* browser); 96 97 // Closes all browsers for |profile| across all desktops. 98 // TODO(mlerman): Move the Profile Deletion flow to use the overloaded 99 // version of this method with a callback, then remove this method. 100 static void CloseAllBrowsersWithProfile(Profile* profile); 101 102 // Closes all browsers for |profile| across all desktops. Uses 103 // TryToCloseBrowserList() to do the actual closing. Triggers any 104 // OnBeforeUnload events unless |skip_beforeunload| is true. If all 105 // OnBeforeUnload events are confirmed or |skip_beforeunload| is true, 106 // |on_close_success| is called, otherwise |on_close_aborted| is called. Both 107 // callbacks may be null. 108 // Note that if there is any browser window that has been used before, the 109 // user should always have a chance to save their work before closing windows 110 // without triggering beforeunload events. 111 static void CloseAllBrowsersWithProfile(Profile* profile, 112 const CloseCallback& on_close_success, 113 const CloseCallback& on_close_aborted, 114 bool skip_beforeunload); 115 116 // Similarly to CloseAllBrowsersWithProfile, but DCHECK's that profile is 117 // Off-the-Record and doesn't close browsers with the original profile. 118 static void CloseAllBrowsersWithIncognitoProfile( 119 Profile* profile, 120 const CloseCallback& on_close_success, 121 const CloseCallback& on_close_aborted, 122 bool skip_beforeunload); 123 124 // Returns true if at least one off-the-record browser is active across all 125 // desktops. 126 static bool IsOffTheRecordBrowserActive(); 127 128 // Returns the number of active off-the-record browsers for |profile| across 129 // all desktops. Note that this function does not count devtools windows 130 // opened for off-the-record windows. 131 static int GetOffTheRecordBrowsersActiveForProfile(Profile* profile); 132 133 // Returns the number of active incognito browsers except devtools windows 134 // across all desktops. 135 static size_t GetIncognitoBrowserCount(); 136 137 // Returns the number of active guest browsers except devtools windows 138 // across all desktops. 139 static size_t GetGuestBrowserCount(); 140 141 // Returns true if the off-the-record browser for |profile| is in use in any 142 // window across all desktops. This function considers devtools windows as 143 // well. 144 static bool IsOffTheRecordBrowserInUse(Profile* profile); 145 146 private: 147 BrowserList(); 148 ~BrowserList(); 149 150 // Helper method to remove a browser instance from a list of browsers 151 static void RemoveBrowserFrom(Browser* browser, BrowserVector* browser_list); 152 153 // Attempts to close |browsers_to_close| while respecting OnBeforeUnload 154 // events. If there are no OnBeforeUnload events to be called, 155 // |on_close_success| will be called, with a parameter of |profile_path|, 156 // and the Browsers will then be closed. If at least one unfired 157 // OnBeforeUnload event is found, handle it with a callback to 158 // PostTryToCloseBrowserWindow, which upon success will recursively call this 159 // method to handle any other OnBeforeUnload events. If aborted in the 160 // OnBeforeUnload event, PostTryToCloseBrowserWindow will call 161 // |on_close_aborted| instead and reset all OnBeforeUnload event handlers. 162 static void TryToCloseBrowserList(const BrowserVector& browsers_to_close, 163 const CloseCallback& on_close_success, 164 const CloseCallback& on_close_aborted, 165 const base::FilePath& profile_path, 166 const bool skip_beforeunload); 167 168 // Called after handling an OnBeforeUnload event. If |tab_close_confirmed| is 169 // true, calls |TryToCloseBrowserList()|, passing the parameters 170 // |browsers_to_close|, |on_close_success|, |on_close_aborted|, and 171 // |profile_path|. Otherwise, resets all the OnBeforeUnload event handlers and 172 // calls |on_close_aborted|. 173 static void PostTryToCloseBrowserWindow( 174 const BrowserVector& browsers_to_close, 175 const CloseCallback& on_close_success, 176 const CloseCallback& on_close_aborted, 177 const base::FilePath& profile_path, 178 const bool skip_beforeunload, 179 bool tab_close_confirmed); 180 181 // A vector of the browsers in this list, in the order they were added. 182 BrowserVector browsers_; 183 // A vector of the browsers in this list that have been activated, in the 184 // reverse order in which they were last activated. 185 BrowserVector last_active_browsers_; 186 // A vector of the browsers that are currently in the closing state. 187 BrowserSet currently_closing_browsers_; 188 189 // A list of observers which will be notified of every browser addition and 190 // removal across all BrowserLists. 191 static base::LazyInstance< 192 base::ObserverList<BrowserListObserver>::Unchecked>::Leaky observers_; 193 194 static BrowserList* instance_; 195 196 DISALLOW_COPY_AND_ASSIGN(BrowserList); 197 }; 198 199 #endif // CHROME_BROWSER_UI_BROWSER_LIST_H_ 200