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