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 <vector>
9
10#include "base/basictypes.h"
11#include "base/lazy_instance.h"
12#include "base/observer_list.h"
13#include "chrome/browser/ui/host_desktop.h"
14
15class Browser;
16class Profile;
17
18namespace base {
19class FilePath;
20}
21
22namespace chrome {
23class BrowserListObserver;
24}
25
26// Maintains a list of Browser objects present in a given HostDesktop (see
27// HostDesktopType).
28class BrowserList {
29 public:
30  typedef std::vector<Browser*> BrowserVector;
31  typedef BrowserVector::const_iterator const_iterator;
32  typedef BrowserVector::const_reverse_iterator const_reverse_iterator;
33
34  // Returns the last active browser for this list.
35  Browser* GetLastActive() const;
36
37  // Browsers are added to the list before they have constructed windows,
38  // so the |window()| member function may return NULL.
39  const_iterator begin() const { return browsers_.begin(); }
40  const_iterator end() const { return browsers_.end(); }
41
42  bool empty() const { return browsers_.empty(); }
43  size_t size() const { return browsers_.size(); }
44
45  Browser* get(size_t index) const { return browsers_[index]; }
46
47  // Returns iterated access to list of open browsers ordered by when
48  // they were last active. The underlying data structure is a vector
49  // and we push_back on recent access so a reverse iterator gives the
50  // latest accessed browser first.
51  const_reverse_iterator begin_last_active() const {
52    return last_active_browsers_.rbegin();
53  }
54  const_reverse_iterator end_last_active() const {
55    return last_active_browsers_.rend();
56  }
57
58  static BrowserList* GetInstance(chrome::HostDesktopType type);
59
60  // Adds or removes |browser| from the list it is associated with. The browser
61  // object should be valid BEFORE these calls (for the benefit of observers),
62  // so notify and THEN delete the object.
63  static void AddBrowser(Browser* browser);
64  static void RemoveBrowser(Browser* browser);
65
66  // Adds and removes |observer| from the observer list for all desktops.
67  // Observers are responsible for making sure the notifying browser is relevant
68  // to them (e.g., on the specific desktop they care about if any).
69  static void AddObserver(chrome::BrowserListObserver* observer);
70  static void RemoveObserver(chrome::BrowserListObserver* observer);
71
72  // Called by Browser objects when their window is activated (focused).  This
73  // allows us to determine what the last active Browser was on each desktop.
74  // Note: This only takes effect on the appropriate browser list as determined
75  // by |browser->host_desktop_type()|.
76  static void SetLastActive(Browser* browser);
77
78  // Closes all browsers for |profile| across all desktops.
79  // TODO(mlerman): Move the Profile Deletion flow to use the overloaded
80  // version of this method with a callback, then remove this method.
81  static void CloseAllBrowsersWithProfile(Profile* profile);
82
83  // Closes all browsers for |profile| across all desktops. Uses
84  // TryToCloseBrowserList() to do the actual closing and trigger any
85  // OnBeforeUnload events. If all OnBeforeUnload events are confirmed,
86  // |on_close_success| is called.
87  static void CloseAllBrowsersWithProfile(
88      Profile* profile,
89      const base::Callback<void(const base::FilePath&)>& on_close_success);
90
91  // Returns true if at least one incognito session is active across all
92  // desktops.
93  static bool IsOffTheRecordSessionActive();
94
95  // Returns true if at least one incognito session is active for |profile|
96  // across all desktops.
97  static bool IsOffTheRecordSessionActiveForProfile(Profile* profile);
98
99 private:
100  BrowserList();
101  ~BrowserList();
102
103  // Helper method to remove a browser instance from a list of browsers
104  static void RemoveBrowserFrom(Browser* browser, BrowserVector* browser_list);
105
106  // Attempts to close |browsers_to_close| while respecting OnBeforeUnload
107  // events. If there are no OnBeforeUnload events to be called,
108  // |on_close_confirmed| will be called, with a parameter of |profile_path|,
109  // and the Browsers will then be closed. If at least one unfired
110  // OnBeforeUnload event is found, handle it with a callback to
111  // PostBeforeUnloadHandlers, which upon success will recursively call this
112  // method to handle any other OnBeforeUnload events.
113  static void TryToCloseBrowserList(
114      const BrowserVector& browsers_to_close,
115      const base::Callback<void(const base::FilePath&)>& on_close_success,
116      const base::FilePath& profile_path);
117
118  // Called after handling an OnBeforeUnload event. If |tab_close_confirmed| is
119  // true, calls |TryToCloseBrowserList()|, passing the parameters
120  // |browsers_to_close|, |on_close_confirmed|, and |profile_path|. Otherwise,
121  // resets all the OnBeforeUnload event handlers.
122  static void PostBeforeUnloadHandlers(
123      const BrowserVector& browsers_to_close,
124      const base::Callback<void(const base::FilePath&)>& on_close_success,
125      const base::FilePath& profile_path,
126      bool tab_close_confirmed);
127
128  // A vector of the browsers in this list, in the order they were added.
129  BrowserVector browsers_;
130  // A vector of the browsers in this list that have been activated, in the
131  // reverse order in which they were last activated.
132  BrowserVector last_active_browsers_;
133
134  // A list of observers which will be notified of every browser addition and
135  // removal across all BrowserLists.
136  static base::LazyInstance<ObserverList<chrome::BrowserListObserver> >::Leaky
137      observers_;
138
139  // Nothing fancy, since we only have two HDTs.
140  static BrowserList* native_instance_;
141  static BrowserList* ash_instance_;
142
143  DISALLOW_COPY_AND_ASSIGN(BrowserList);
144};
145
146#endif  // CHROME_BROWSER_UI_BROWSER_LIST_H_
147