1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/browser_list_impl.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/notification_service.h"
// #include "build/build_config.h"
// #include "chrome/browser/prefs/pref_service.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/user_manager.h"
#endif
namespace chrome {
// static
BrowserListImpl* BrowserListImpl::native_instance_ = NULL;
BrowserListImpl* BrowserListImpl::ash_instance_ = NULL;
////////////////////////////////////////////////////////////////////////////////
// BrowserListImpl, public:
// static
BrowserListImpl* BrowserListImpl::GetInstance(HostDesktopType type) {
BrowserListImpl** list = NULL;
if (type == HOST_DESKTOP_TYPE_NATIVE)
list = &native_instance_;
else if (type == HOST_DESKTOP_TYPE_ASH)
list = &ash_instance_;
else
NOTREACHED();
if (!*list)
*list = new BrowserListImpl;
return *list;
}
void BrowserListImpl::AddBrowser(Browser* browser) {
DCHECK(browser);
browsers_.push_back(browser);
g_browser_process->AddRefModule();
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_BROWSER_OPENED,
content::Source<Browser>(browser),
content::NotificationService::NoDetails());
// Send out notifications after add has occurred. Do some basic checking to
// try to catch evil observers that change the list from under us.
size_t original_count = observers_.size();
FOR_EACH_OBSERVER(BrowserListObserver, observers_, OnBrowserAdded(browser));
DCHECK_EQ(original_count, observers_.size())
<< "observer list modified during notification";
}
void BrowserListImpl::RemoveBrowser(Browser* browser) {
RemoveBrowserFrom(browser, &last_active_browsers_);
// Many UI tests rely on closing the last browser window quitting the
// application.
// Mac: Closing all windows does not indicate quitting the application. Lie
// for now and ignore behavior outside of unit tests.
// ChromeOS: Force closing last window to close app with flag.
// TODO(andybons | pkotwicz): Fix the UI tests to Do The Right Thing.
#if defined(OS_CHROMEOS)
bool closing_app;
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableZeroBrowsersOpenForTests))
closing_app = (browsers_.size() == 1);
else
closing_app = (browsers_.size() == 1 &&
browser_shutdown::IsTryingToQuit());
#else
bool closing_app = (browsers_.size() == 1);
#endif // OS_CHROMEOS
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_BROWSER_CLOSED,
content::Source<Browser>(browser),
content::Details<bool>(&closing_app));
RemoveBrowserFrom(browser, &browsers_);
// Do some basic checking to try to catch evil observers
// that change the list from under us.
size_t original_count = observers_.size();
FOR_EACH_OBSERVER(BrowserListObserver, observers_, OnBrowserRemoved(browser));
DCHECK_EQ(original_count, observers_.size())
<< "observer list modified during notification";
g_browser_process->ReleaseModule();
// If we're exiting, send out the APP_TERMINATING notification to allow other
// modules to shut themselves down.
if (browsers_.empty() &&
(browser_shutdown::IsTryingToQuit() ||
g_browser_process->IsShuttingDown())) {
// Last browser has just closed, and this is a user-initiated quit or there
// is no module keeping the app alive, so send out our notification. No need
// to call ProfileManager::ShutdownSessionServices() as part of the
// shutdown, because Browser::WindowClosing() already makes sure that the
// SessionService is created and notified.
browser::NotifyAppTerminating();
browser::OnAppExiting();
}
}
void BrowserListImpl::AddObserver(BrowserListObserver* observer) {
observers_.AddObserver(observer);
}
void BrowserListImpl::RemoveObserver(BrowserListObserver* observer) {
observers_.RemoveObserver(observer);
}
void BrowserListImpl::SetLastActive(Browser* browser) {
// If the browser is currently trying to quit, we don't want to set the last
// active browser because that can alter the last active browser that the user
// intended depending on the order in which the windows close.
if (browser_shutdown::IsTryingToQuit())
return;
RemoveBrowserFrom(browser, &last_active_browsers_);
last_active_browsers_.push_back(browser);
FOR_EACH_OBSERVER(BrowserListObserver, observers_,
OnBrowserSetLastActive(browser));
}
Browser* BrowserListImpl::GetLastActive() {
if (!last_active_browsers_.empty())
return *(last_active_browsers_.rbegin());
return NULL;
}
void BrowserListImpl::CloseAllBrowsersWithProfile(Profile* profile) {
BrowserVector browsers_to_close;
for (BrowserListImpl::const_iterator i = BrowserListImpl::begin();
i != BrowserListImpl::end(); ++i) {
if ((*i)->profile()->GetOriginalProfile() == profile->GetOriginalProfile())
browsers_to_close.push_back(*i);
}
for (BrowserVector::const_iterator i = browsers_to_close.begin();
i != browsers_to_close.end(); ++i) {
(*i)->window()->Close();
}
}
bool BrowserListImpl::IsIncognitoWindowOpen() {
for (BrowserListImpl::const_iterator i = BrowserListImpl::begin();
i != BrowserListImpl::end(); ++i) {
if ((*i)->profile()->IsOffTheRecord())
return true;
}
return false;
}
bool BrowserListImpl::IsIncognitoWindowOpenForProfile(Profile* profile) {
#if defined(OS_CHROMEOS)
// In ChromeOS, we assume that the default profile is always valid, so if
// we are in guest mode, keep the OTR profile active so it won't be deleted.
if (chromeos::UserManager::Get()->IsLoggedInAsGuest())
return true;
#endif
for (BrowserListImpl::const_iterator i = BrowserListImpl::begin();
i != BrowserListImpl::end(); ++i) {
if ((*i)->profile()->IsSameProfile(profile) &&
(*i)->profile()->IsOffTheRecord()) {
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
// BrowserListImpl, private:
BrowserListImpl::BrowserListImpl() {
}
BrowserListImpl::~BrowserListImpl() {
}
void BrowserListImpl::RemoveBrowserFrom(Browser* browser,
BrowserVector* browser_list) {
const iterator remove_browser =
std::find(browser_list->begin(), browser_list->end(), browser);
if (remove_browser != browser_list->end())
browser_list->erase(remove_browser);
}
} // namespace chrome
|