| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |