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

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

Issue 1725007: Simplify the Observer pattern used in the BrowserList. (Closed)
Patch Set: back Compact to protected section Created 10 years, 7 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
« no previous file with comments | « chrome/browser/browser_list.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/browser_list.h" 5 #include "chrome/browser/browser_list.h"
6 6
7 #include "base/histogram.h" 7 #include "base/histogram.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "build/build_config.h" 10 #include "build/build_config.h"
11 #include "chrome/browser/browser_process.h" 11 #include "chrome/browser/browser_process.h"
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 profile_match; 95 profile_match;
96 } 96 }
97 97
98 // Finds a registered Browser object matching |profile| and |type|. This 98 // Finds a registered Browser object matching |profile| and |type|. This
99 // walks the list of Browsers that have ever been activated from most recently 99 // walks the list of Browsers that have ever been activated from most recently
100 // activated to least. If a Browser has never been activated, such as in a test 100 // activated to least. If a Browser has never been activated, such as in a test
101 // scenario, this function will _not_ find it. Fall back to 101 // scenario, this function will _not_ find it. Fall back to
102 // FindBrowserMatching() in that case. 102 // FindBrowserMatching() in that case.
103 Browser* FindInLastActiveMatching(Profile* profile, Browser::Type type, 103 Browser* FindInLastActiveMatching(Profile* profile, Browser::Type type,
104 bool match_incognito) { 104 bool match_incognito) {
105 for (BrowserList::list_type::const_reverse_iterator i = 105 for (BrowserList::BrowserVector::const_reverse_iterator i =
106 BrowserList::begin_last_active(); i != BrowserList::end_last_active(); 106 BrowserList::begin_last_active(); i != BrowserList::end_last_active();
107 ++i) { 107 ++i) {
108 if (BrowserMatchesProfileAndType(*i, profile, type, match_incognito)) 108 if (BrowserMatchesProfileAndType(*i, profile, type, match_incognito))
109 return *i; 109 return *i;
110 } 110 }
111 return NULL; 111 return NULL;
112 } 112 }
113 113
114 // Finds a registered Browser object matching |profile| and |type| even if that 114 // Finds a registered Browser object matching |profile| and |type| even if that
115 // Browser has never been activated. This is a forward walk, and intended as a 115 // Browser has never been activated. This is a forward walk, and intended as a
116 // last ditch fallback mostly to handle tests run on machines where no window is 116 // last ditch fallback mostly to handle tests run on machines where no window is
117 // ever activated. The user experience if this function is relied on is not good 117 // ever activated. The user experience if this function is relied on is not good
118 // since matching browsers will be returned in registration (creation) order. 118 // since matching browsers will be returned in registration (creation) order.
119 Browser* FindBrowserMatching(Profile* profile, Browser::Type type, 119 Browser* FindBrowserMatching(Profile* profile, Browser::Type type,
120 bool match_incognito) { 120 bool match_incognito) {
121 for (BrowserList::const_iterator i = BrowserList::begin(); 121 for (BrowserList::const_iterator i = BrowserList::begin();
122 i != BrowserList::end(); ++i) { 122 i != BrowserList::end(); ++i) {
123 if (BrowserMatchesProfileAndType(*i, profile, type, match_incognito)) 123 if (BrowserMatchesProfileAndType(*i, profile, type, match_incognito))
124 return *i; 124 return *i;
125 } 125 }
126 return NULL; 126 return NULL;
127 } 127 }
128 128
129 } // namespace 129 } // namespace
130 130
131 BrowserList::list_type BrowserList::browsers_; 131 BrowserList::BrowserVector BrowserList::browsers_;
132 std::vector<BrowserList::Observer*> BrowserList::observers_; 132 ObserverList<BrowserList::Observer> BrowserList::observers_;
133 133
134 // static 134 // static
135 void BrowserList::AddBrowser(Browser* browser) { 135 void BrowserList::AddBrowser(Browser* browser) {
136 DCHECK(browser); 136 DCHECK(browser);
137 browsers_.push_back(browser); 137 browsers_.push_back(browser);
138 138
139 g_browser_process->AddRefModule(); 139 g_browser_process->AddRefModule();
140 140
141 if (!activity_observer) 141 if (!activity_observer)
142 activity_observer = new BrowserActivityObserver; 142 activity_observer = new BrowserActivityObserver;
143 143
144 NotificationService::current()->Notify( 144 NotificationService::current()->Notify(
145 NotificationType::BROWSER_OPENED, 145 NotificationType::BROWSER_OPENED,
146 Source<Browser>(browser), 146 Source<Browser>(browser),
147 NotificationService::NoDetails()); 147 NotificationService::NoDetails());
148 148
149 // Send out notifications after add has occurred. Do some basic checking to 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. 150 // try to catch evil observers that change the list from under us.
151 size_t original_count = observers_.size(); 151 size_t original_count = observers_.size();
152 for (size_t i = 0; i < observers_.size(); ++i) 152 FOR_EACH_OBSERVER(Observer, observers_, OnBrowserAdded(browser));
153 observers_[i]->OnBrowserAdded(browser);
154 DCHECK_EQ(original_count, observers_.size()) 153 DCHECK_EQ(original_count, observers_.size())
155 << "observer list modified during notification"; 154 << "observer list modified during notification";
156 } 155 }
157 156
158 // static 157 // static
159 void BrowserList::RemoveBrowser(Browser* browser) { 158 void BrowserList::RemoveBrowser(Browser* browser) {
160 RemoveBrowserFrom(browser, &last_active_browsers_); 159 RemoveBrowserFrom(browser, &last_active_browsers_);
161 160
162 // Closing all windows does not indicate quitting the application on the Mac, 161 // Closing all windows does not indicate quitting the application on the Mac,
163 // however, many UI tests rely on this behavior so leave it be for now and 162 // however, many UI tests rely on this behavior so leave it be for now and
164 // simply ignore the behavior on the Mac outside of unit tests. 163 // simply ignore the behavior on the Mac outside of unit tests.
165 // TODO(andybons): Fix the UI tests to Do The Right Thing. 164 // TODO(andybons): Fix the UI tests to Do The Right Thing.
166 bool close_app_non_mac = (browsers_.size() == 1); 165 bool close_app_non_mac = (browsers_.size() == 1);
167 NotificationService::current()->Notify( 166 NotificationService::current()->Notify(
168 NotificationType::BROWSER_CLOSED, 167 NotificationType::BROWSER_CLOSED,
169 Source<Browser>(browser), Details<bool>(&close_app_non_mac)); 168 Source<Browser>(browser), Details<bool>(&close_app_non_mac));
170 169
171 // Send out notifications before anything changes. Do some basic checking to 170 // Send out notifications before anything changes. Do some basic checking to
172 // try to catch evil observers that change the list from under us. 171 // try to catch evil observers that change the list from under us.
173 size_t original_count = observers_.size(); 172 size_t original_count = observers_.size();
174 for (size_t i = 0; i < observers_.size(); ++i) 173 FOR_EACH_OBSERVER(Observer, observers_, OnBrowserRemoving(browser));
175 observers_[i]->OnBrowserRemoving(browser);
176 DCHECK_EQ(original_count, observers_.size()) 174 DCHECK_EQ(original_count, observers_.size())
177 << "observer list modified during notification"; 175 << "observer list modified during notification";
178 176
179 RemoveBrowserFrom(browser, &browsers_); 177 RemoveBrowserFrom(browser, &browsers_);
180 178
181 // If the last Browser object was destroyed, make sure we try to close any 179 // If the last Browser object was destroyed, make sure we try to close any
182 // remaining dependent windows too. 180 // remaining dependent windows too.
183 if (browsers_.empty()) { 181 if (browsers_.empty()) {
184 AllBrowsersClosed(); 182 AllBrowsersClosed();
185 183
186 delete activity_observer; 184 delete activity_observer;
187 activity_observer = NULL; 185 activity_observer = NULL;
188 } 186 }
189 187
190 g_browser_process->ReleaseModule(); 188 g_browser_process->ReleaseModule();
191 } 189 }
192 190
193 // static 191 // static
194 void BrowserList::AddObserver(BrowserList::Observer* observer) { 192 void BrowserList::AddObserver(BrowserList::Observer* observer) {
195 DCHECK(std::find(observers_.begin(), observers_.end(), observer) 193 observers_.AddObserver(observer);
196 == observers_.end()) << "Adding an observer twice";
197 observers_.push_back(observer);
198 } 194 }
199 195
200 // static 196 // static
201 void BrowserList::RemoveObserver(BrowserList::Observer* observer) { 197 void BrowserList::RemoveObserver(BrowserList::Observer* observer) {
202 std::vector<Observer*>::iterator i = 198 observers_.RemoveObserver(observer);
203 std::find(observers_.begin(), observers_.end(), observer);
204 if (i == observers_.end()) {
205 NOTREACHED() << "Removing an observer that isn't registered.";
206 return;
207 }
208 observers_.erase(i);
209 } 199 }
210 200
211 // static 201 // static
212 void BrowserList::CloseAllBrowsers(bool use_post) { 202 void BrowserList::CloseAllBrowsers(bool use_post) {
213 // Before we close the browsers shutdown all session services. That way an 203 // Before we close the browsers shutdown all session services. That way an
214 // exit can restore all browsers open before exiting. 204 // exit can restore all browsers open before exiting.
215 ProfileManager::ShutdownSessionServices(); 205 ProfileManager::ShutdownSessionServices();
216 206
217 for (BrowserList::const_iterator i = BrowserList::begin(); 207 for (BrowserList::const_iterator i = BrowserList::begin();
218 i != BrowserList::end();) { 208 i != BrowserList::end();) {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 } 300 }
311 301
312 // static 302 // static
313 bool BrowserList::IsInPersistentMode() { 303 bool BrowserList::IsInPersistentMode() {
314 // TODO(atwilson): check the boolean state variable that you will set for 304 // TODO(atwilson): check the boolean state variable that you will set for
315 // persisent instances. 305 // persisent instances.
316 return false; 306 return false;
317 } 307 }
318 308
319 // static 309 // static
320 BrowserList::list_type BrowserList::last_active_browsers_; 310 BrowserList::BrowserVector BrowserList::last_active_browsers_;
321 311
322 // static 312 // static
323 void BrowserList::SetLastActive(Browser* browser) { 313 void BrowserList::SetLastActive(Browser* browser) {
324 RemoveBrowserFrom(browser, &last_active_browsers_); 314 RemoveBrowserFrom(browser, &last_active_browsers_);
325 last_active_browsers_.push_back(browser); 315 last_active_browsers_.push_back(browser);
326 316
327 for (std::vector<Observer*>::const_iterator i = observers_.begin(); 317 FOR_EACH_OBSERVER(Observer, observers_, OnBrowserSetLastActive(browser));
328 i != observers_.end(); ++i) {
329 (*i)->OnBrowserSetLastActive(browser);
330 }
331 } 318 }
332 319
333 // static 320 // static
334 Browser* BrowserList::GetLastActive() { 321 Browser* BrowserList::GetLastActive() {
335 if (!last_active_browsers_.empty()) 322 if (!last_active_browsers_.empty())
336 return *(last_active_browsers_.rbegin()); 323 return *(last_active_browsers_.rbegin());
337 324
338 return NULL; 325 return NULL;
339 } 326 }
340 327
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 bool BrowserList::IsOffTheRecordSessionActive() { 381 bool BrowserList::IsOffTheRecordSessionActive() {
395 for (BrowserList::const_iterator i = BrowserList::begin(); 382 for (BrowserList::const_iterator i = BrowserList::begin();
396 i != BrowserList::end(); ++i) { 383 i != BrowserList::end(); ++i) {
397 if ((*i)->profile()->IsOffTheRecord()) 384 if ((*i)->profile()->IsOffTheRecord())
398 return true; 385 return true;
399 } 386 }
400 return false; 387 return false;
401 } 388 }
402 389
403 // static 390 // static
404 void BrowserList::RemoveBrowserFrom(Browser* browser, list_type* browser_list) { 391 void BrowserList::RemoveBrowserFrom(Browser* browser,
392 BrowserVector* browser_list) {
405 const iterator remove_browser = 393 const iterator remove_browser =
406 std::find(browser_list->begin(), browser_list->end(), browser); 394 std::find(browser_list->begin(), browser_list->end(), browser);
407 if (remove_browser != browser_list->end()) 395 if (remove_browser != browser_list->end())
408 browser_list->erase(remove_browser); 396 browser_list->erase(remove_browser);
409 } 397 }
410 398
411 TabContentsIterator::TabContentsIterator() 399 TabContentsIterator::TabContentsIterator()
412 : browser_iterator_(BrowserList::begin()), 400 : browser_iterator_(BrowserList::begin()),
413 web_view_index_(-1), 401 web_view_index_(-1),
414 cur_(NULL) { 402 cur_(NULL) {
(...skipping 21 matching lines...) Expand all
436 } 424 }
437 425
438 TabContents* next_tab = 426 TabContents* next_tab =
439 (*browser_iterator_)->GetTabContentsAt(web_view_index_); 427 (*browser_iterator_)->GetTabContentsAt(web_view_index_);
440 if (next_tab) { 428 if (next_tab) {
441 cur_ = next_tab; 429 cur_ = next_tab;
442 return; 430 return;
443 } 431 }
444 } 432 }
445 } 433 }
OLDNEW
« no previous file with comments | « chrome/browser/browser_list.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698