Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Side by Side Diff: chrome/browser/ui/browser_list.cc

Issue 10690151: Move implementation of BrowserList onto an inner, instantiatable class, BrowserListImpl. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/browser_list.h" 5 #include "chrome/browser/ui/browser_list.h"
6 6
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/metrics/histogram.h"
10 #include "base/observer_list.h"
11 #include "build/build_config.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/browser_shutdown.h"
14 #include "chrome/browser/lifetime/application_lifetime.h"
15 #include "chrome/browser/prefs/pref_service.h"
16 #include "chrome/browser/profiles/profile.h" 7 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/ui/browser.h" 8 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_window.h" 9 #include "chrome/browser/ui/browser_list_impl.h"
19 #include "chrome/browser/ui/tab_contents/tab_contents.h" 10 #include "chrome/browser/ui/browser_list_observer.h"
jam 2012/07/12 18:53:22 this file isn't part of the change?
20 #include "chrome/common/chrome_notification_types.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/pref_names.h"
23 #include "content/public/browser/browser_shutdown.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/navigation_details.h"
26 #include "content/public/browser/notification_registrar.h"
27 #include "content/public/browser/notification_service.h"
28 #include "content/public/browser/render_process_host.h"
29 #include "content/public/common/result_codes.h"
30
31 #if defined(OS_CHROMEOS)
32 #include "chrome/browser/chromeos/login/user_manager.h"
33 #endif
34 11
35 using content::WebContents; 12 using content::WebContents;
36 13
37 namespace browser {
38
39 // This object is instantiated when the first Browser object is added to the
40 // list and delete when the last one is removed. It watches for loads and
41 // creates histograms of some global object counts.
42 class BrowserActivityObserver : public content::NotificationObserver {
43 public:
44 BrowserActivityObserver() {
45 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
46 content::NotificationService::AllSources());
47 registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING,
48 content::NotificationService::AllSources());
49 }
50 ~BrowserActivityObserver() {}
51
52 private:
53 // content::NotificationObserver implementation.
54 virtual void Observe(int type,
55 const content::NotificationSource& source,
56 const content::NotificationDetails& details) {
57 if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) {
58 const content::LoadCommittedDetails& load =
59 *content::Details<content::LoadCommittedDetails>(details).ptr();
60 if (!load.is_navigation_to_different_page())
61 return; // Don't log for subframes or other trivial types.
62
63 LogRenderProcessHostCount();
64 LogBrowserTabCount();
65 } else if (type == content::NOTIFICATION_APP_TERMINATING) {
66 delete this;
67 }
68 }
69
70 // Counts the number of active RenderProcessHosts and logs them.
71 void LogRenderProcessHostCount() const {
72 int hosts_count = 0;
73 for (content::RenderProcessHost::iterator i(
74 content::RenderProcessHost::AllHostsIterator());
75 !i.IsAtEnd(); i.Advance())
76 ++hosts_count;
77 UMA_HISTOGRAM_CUSTOM_COUNTS("MPArch.RPHCountPerLoad", hosts_count,
78 1, 50, 50);
79 }
80
81 // Counts the number of tabs in each browser window and logs them. This is
82 // different than the number of WebContents objects since WebContents objects
83 // can be used for popups and in dialog boxes. We're just counting toplevel
84 // tabs here.
85 void LogBrowserTabCount() const {
86 int tab_count = 0;
87 for (BrowserList::const_iterator browser_iterator = BrowserList::begin();
88 browser_iterator != BrowserList::end(); browser_iterator++) {
89 // Record how many tabs each window has open.
90 Browser* browser = (*browser_iterator);
91 UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountPerWindow",
92 browser->tab_count(), 1, 200, 50);
93 tab_count += browser->tab_count();
94
95 if (browser->window()->IsActive()) {
96 // Record how many tabs the active window has open.
97 UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountActiveWindow",
98 browser->tab_count(), 1, 200, 50);
99 }
100 }
101 // Record how many tabs total are open (across all windows).
102 UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountPerLoad", tab_count, 1, 200, 50);
103 }
104
105 content::NotificationRegistrar registrar_;
106
107 DISALLOW_COPY_AND_ASSIGN(BrowserActivityObserver);
108 };
109
110 BrowserActivityObserver* g_activity_observer = NULL;
111
112 } // namespace browser
113
114 namespace { 14 namespace {
115 15
116 static BrowserList::BrowserVector& browsers() { 16 chrome::BrowserListImpl* GetNativeList() {
117 CR_DEFINE_STATIC_LOCAL(BrowserList::BrowserVector, browser_vector, ()); 17 return chrome::BrowserListImpl::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE);
118 return browser_vector;
119 }
120
121 static BrowserList::BrowserVector& last_active_browsers() {
122 CR_DEFINE_STATIC_LOCAL(BrowserList::BrowserVector, last_active_vector, ());
123 return last_active_vector;
124 }
125
126 static ObserverList<BrowserList::Observer>& observers() {
127 CR_DEFINE_STATIC_LOCAL(
128 ObserverList<BrowserList::Observer>, observer_vector, ());
129 return observer_vector;
130 } 18 }
131 19
132 } // namespace 20 } // namespace
133 21
134 // static 22 // static
135 void BrowserList::AddBrowser(Browser* browser) { 23 void BrowserList::AddBrowser(Browser* browser) {
136 DCHECK(browser); 24 GetNativeList()->AddBrowser(browser);
137 browsers().push_back(browser);
138
139 g_browser_process->AddRefModule();
140
141 if (!browser::g_activity_observer)
142 browser::g_activity_observer = new browser::BrowserActivityObserver;
143
144 content::NotificationService::current()->Notify(
145 chrome::NOTIFICATION_BROWSER_OPENED,
146 content::Source<Browser>(browser),
147 content::NotificationService::NoDetails());
148
149 // Send out notifications after add has occurred. Do some basic checking to
150 // try to catch evil observers that change the list from under us.
151 size_t original_count = observers().size();
152 FOR_EACH_OBSERVER(Observer, observers(), OnBrowserAdded(browser));
153 DCHECK_EQ(original_count, observers().size())
154 << "observer list modified during notification";
155 } 25 }
156 26
157 // static 27 // static
158 void BrowserList::RemoveBrowser(Browser* browser) { 28 void BrowserList::RemoveBrowser(Browser* browser) {
159 RemoveBrowserFrom(browser, &last_active_browsers()); 29 GetNativeList()->RemoveBrowser(browser);
160
161 // Many UI tests rely on closing the last browser window quitting the
162 // application.
163 // Mac: Closing all windows does not indicate quitting the application. Lie
164 // for now and ignore behavior outside of unit tests.
165 // ChromeOS: Force closing last window to close app with flag.
166 // TODO(andybons | pkotwicz): Fix the UI tests to Do The Right Thing.
167 #if defined(OS_CHROMEOS)
168 bool closing_app;
169 if (CommandLine::ForCurrentProcess()->HasSwitch(
170 switches::kDisableZeroBrowsersOpenForTests))
171 closing_app = (browsers().size() == 1);
172 else
173 closing_app = (browsers().size() == 1 &&
174 browser_shutdown::IsTryingToQuit());
175 #else
176 bool closing_app = (browsers().size() == 1);
177 #endif // OS_CHROMEOS
178
179 content::NotificationService::current()->Notify(
180 chrome::NOTIFICATION_BROWSER_CLOSED,
181 content::Source<Browser>(browser),
182 content::Details<bool>(&closing_app));
183
184 RemoveBrowserFrom(browser, &browsers());
185
186 // Do some basic checking to try to catch evil observers
187 // that change the list from under us.
188 size_t original_count = observers().size();
189 FOR_EACH_OBSERVER(Observer, observers(), OnBrowserRemoved(browser));
190 DCHECK_EQ(original_count, observers().size())
191 << "observer list modified during notification";
192
193 g_browser_process->ReleaseModule();
194
195 // If we're exiting, send out the APP_TERMINATING notification to allow other
196 // modules to shut themselves down.
197 if (browsers().empty() &&
198 (browser_shutdown::IsTryingToQuit() ||
199 g_browser_process->IsShuttingDown())) {
200 // Last browser has just closed, and this is a user-initiated quit or there
201 // is no module keeping the app alive, so send out our notification. No need
202 // to call ProfileManager::ShutdownSessionServices() as part of the
203 // shutdown, because Browser::WindowClosing() already makes sure that the
204 // SessionService is created and notified.
205 browser::NotifyAppTerminating();
206 browser::OnAppExiting();
207 }
208 } 30 }
209 31
210 // static 32 // static
211 void BrowserList::AddObserver(BrowserList::Observer* observer) { 33 void BrowserList::AddObserver(chrome::BrowserListObserver* observer) {
212 observers().AddObserver(observer); 34 GetNativeList()->AddObserver(observer);
213 } 35 }
214 36
215 // static 37 // static
216 void BrowserList::RemoveObserver(BrowserList::Observer* observer) { 38 void BrowserList::RemoveObserver(chrome::BrowserListObserver* observer) {
217 observers().RemoveObserver(observer); 39 GetNativeList()->RemoveObserver(observer);
218 } 40 }
219 41
220 void BrowserList::CloseAllBrowsersWithProfile(Profile* profile) { 42 void BrowserList::CloseAllBrowsersWithProfile(Profile* profile) {
221 BrowserVector browsers_to_close; 43 GetNativeList()->CloseAllBrowsersWithProfile(profile);
222 for (BrowserList::const_iterator i = BrowserList::begin();
223 i != BrowserList::end(); ++i) {
224 if ((*i)->profile()->GetOriginalProfile() == profile->GetOriginalProfile())
225 browsers_to_close.push_back(*i);
226 }
227
228 for (BrowserVector::const_iterator i = browsers_to_close.begin();
229 i != browsers_to_close.end(); ++i) {
230 (*i)->window()->Close();
231 }
232 } 44 }
233 45
234 // static 46 // static
235 BrowserList::const_iterator BrowserList::begin() { 47 BrowserList::const_iterator BrowserList::begin() {
236 return browsers().begin(); 48 return GetNativeList()->begin();
237 } 49 }
238 50
239 // static 51 // static
240 BrowserList::const_iterator BrowserList::end() { 52 BrowserList::const_iterator BrowserList::end() {
241 return browsers().end(); 53 return GetNativeList()->end();
242 } 54 }
243 55
244 // static 56 // static
245 bool BrowserList::empty() { 57 bool BrowserList::empty() {
246 return browsers().empty(); 58 return GetNativeList()->empty();
247 } 59 }
248 60
249 // static 61 // static
250 size_t BrowserList::size() { 62 size_t BrowserList::size() {
251 return browsers().size(); 63 return GetNativeList()->size();
252 } 64 }
253 65
254 // static 66 // static
255 void BrowserList::SetLastActive(Browser* browser) { 67 void BrowserList::SetLastActive(Browser* browser) {
256 // If the browser is currently trying to quit, we don't want to set the last 68 GetNativeList()->SetLastActive(browser);
257 // active browser because that can alter the last active browser that the user
258 // intended depending on the order in which the windows close.
259 if (browser_shutdown::IsTryingToQuit())
260 return;
261 RemoveBrowserFrom(browser, &last_active_browsers());
262 last_active_browsers().push_back(browser);
263
264 FOR_EACH_OBSERVER(Observer, observers(), OnBrowserSetLastActive(browser));
265 } 69 }
266 70
267 // static 71 // static
268 BrowserList::const_reverse_iterator BrowserList::begin_last_active() { 72 BrowserList::const_reverse_iterator BrowserList::begin_last_active() {
269 return last_active_browsers().rbegin(); 73 return GetNativeList()->begin_last_active();
270 } 74 }
271 75
272 // static 76 // static
273 BrowserList::const_reverse_iterator BrowserList::end_last_active() { 77 BrowserList::const_reverse_iterator BrowserList::end_last_active() {
274 return last_active_browsers().rend(); 78 return GetNativeList()->end_last_active();
275 } 79 }
276 80
277 // static 81 // static
278 bool BrowserList::IsOffTheRecordSessionActive() { 82 bool BrowserList::IsOffTheRecordSessionActive() {
279 for (BrowserList::const_iterator i = BrowserList::begin(); 83 return GetNativeList()->IsIncognitoWindowOpen();
280 i != BrowserList::end(); ++i) {
281 if ((*i)->profile()->IsOffTheRecord())
282 return true;
283 }
284 return false;
285 } 84 }
286 85
287 // static 86 // static
288 bool BrowserList::IsOffTheRecordSessionActiveForProfile(Profile* profile) { 87 bool BrowserList::IsOffTheRecordSessionActiveForProfile(Profile* profile) {
289 #if defined(OS_CHROMEOS) 88 return GetNativeList()->IsIncognitoWindowOpenForProfile(profile);
290 // In ChromeOS, we assume that the default profile is always valid, so if
291 // we are in guest mode, keep the OTR profile active so it won't be deleted.
292 if (chromeos::UserManager::Get()->IsLoggedInAsGuest())
293 return true;
294 #endif
295 for (BrowserList::const_iterator i = BrowserList::begin();
296 i != BrowserList::end(); ++i) {
297 if ((*i)->profile()->IsSameProfile(profile) &&
298 (*i)->profile()->IsOffTheRecord()) {
299 return true;
300 }
301 }
302 return false;
303 } 89 }
304 90
305 // static 91 // static
306 Browser* BrowserList::GetLastActive() { 92 Browser* BrowserList::GetLastActive() {
307 if (!last_active_browsers().empty()) 93 return GetNativeList()->GetLastActive();
308 return *(last_active_browsers().rbegin());
309
310 return NULL;
311 } 94 }
312
313 // static
314 void BrowserList::RemoveBrowserFrom(Browser* browser,
315 BrowserVector* browser_list) {
316 const iterator remove_browser =
317 std::find(browser_list->begin(), browser_list->end(), browser);
318 if (remove_browser != browser_list->end())
319 browser_list->erase(remove_browser);
320 }
321
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698