diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
commit | 09911bf300f1a419907a9412154760efd0b7abc3 (patch) | |
tree | f131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/browser_list.cc | |
parent | 586acc5fe142f498261f52c66862fa417c3d52d2 (diff) | |
download | chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2 |
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/browser_list.cc')
-rw-r--r-- | chrome/browser/browser_list.cc | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/chrome/browser/browser_list.cc b/chrome/browser/browser_list.cc new file mode 100644 index 0000000..12b2cbb --- /dev/null +++ b/chrome/browser/browser_list.cc @@ -0,0 +1,306 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/browser/browser_list.h" + +#include "base/logging.h" +#include "base/message_loop.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chrome_frame.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/profile_manager.h" +#include "chrome/browser/web_contents.h" +#include "chrome/common/notification_service.h" +#include "chrome/views/window.h" + +BrowserList::list_type BrowserList::browsers_; +std::vector<BrowserList::Observer*> BrowserList::observers_; +BrowserList::DependentWindowList BrowserList::dependent_windows_; + +// static +void BrowserList::AddBrowser(Browser* browser) { + browsers_.push_back(browser); + + g_browser_process->AddRefModule(); + + NotificationService::current()->Notify( + NOTIFY_BROWSER_OPENED, + Source<Browser>(browser), 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. + std::vector<Observer*>::size_type original_count = observers_.size(); + for (int i = 0; i < static_cast<int>(observers_.size()); i++) + observers_[i]->OnBrowserAdded(browser); + DCHECK_EQ(original_count, observers_.size()) + << "observer list modified during notification"; +} + +// static +void BrowserList::RemoveBrowser(Browser* browser) { + RemoveBrowserFrom(browser, &last_active_browsers_); + + bool close_app = (browsers_.size() == 1); + NotificationService::current()->Notify( + NOTIFY_BROWSER_CLOSED, + Source<Browser>(browser), Details<bool>(&close_app)); + + // Send out notifications before anything changes. Do some basic checking to + // try to catch evil observers that change the list from under us. + std::vector<Observer*>::size_type original_count = observers_.size(); + for (int i = 0; i < static_cast<int>(observers_.size()); i++) + observers_[i]->OnBrowserRemoving(browser); + DCHECK_EQ(original_count, observers_.size()) + << "observer list modified during notification"; + + RemoveBrowserFrom(browser, &browsers_); + + // If the last Browser object was destroyed, make sure we try to close any + // remaining dependent windows too. + if (browsers_.empty()) + CloseAllDependentWindows(); + + g_browser_process->ReleaseModule(); +} + +// static +void BrowserList::AddDependentWindow(ChromeViews::Window* window) { + DependentWindowList::const_iterator existing = + find(dependent_windows_.begin(), dependent_windows_.end(), window); + DCHECK(existing == dependent_windows_.end()); + dependent_windows_.push_back(window); + g_browser_process->AddRefModule(); +} + +// static +void BrowserList::RemoveDependentWindow(ChromeViews::Window* window) { + DependentWindowList::iterator existing = + find(dependent_windows_.begin(), dependent_windows_.end(), window); + DCHECK(existing != dependent_windows_.end()); + dependent_windows_.erase(existing); + g_browser_process->ReleaseModule(); +} + +// static +void BrowserList::AddObserver(BrowserList::Observer* observer) { + DCHECK(std::find(observers_.begin(), observers_.end(), observer) + == observers_.end()) << "Adding an observer twice"; + observers_.push_back(observer); +} + +// static +void BrowserList::RemoveObserver(BrowserList::Observer* observer) { + std::vector<Observer*>::iterator place = + std::find(observers_.begin(), observers_.end(), observer); + if (place == observers_.end()) { + NOTREACHED() << "Removing an observer that isn't registered."; + return; + } + observers_.erase(place); +} + +// static +void BrowserList::CloseAllBrowsers(bool use_post) { + // Before we close the browsers shutdown all session services. That way an + // exit can restore all browsers open before exiting. + ProfileManager::ShutdownSessionServices(); + + BrowserList::const_iterator iter; + for (iter = BrowserList::begin(); iter != BrowserList::end();) { + if (use_post) { + ::PostMessage((*iter)->GetTopLevelHWND(), WM_CLOSE, 0, 0); + ++iter; + } else { + // This path is hit during logoff/power-down. In this case we won't get + // a final message and so we force the browser to be deleted. + Browser* browser = *iter; + browser->frame()->Close(); + // Close doesn't immediately destroy the browser + // (Browser::TabStripEmpty() uses invoke later) but when we're ending the + // session we need to make sure the browser is destroyed now. So, invoke + // DestroyBrowser to make sure the browser is deleted and cleanup can + // happen. + browser->frame()->DestroyBrowser(); + iter = BrowserList::begin(); + if (iter != BrowserList::end() && browser == *iter) { + // Destroying the browser should have removed it from the browser list. + // We should never get here. + NOTREACHED(); + return; + } + } + } +} + +// static +bool BrowserList::HasBrowserWithProfile(Profile* profile) { + BrowserList::const_iterator iter; + for (size_t i = 0; i < browsers_.size(); ++i) { + if (browsers_[i]->profile() == profile) + return true; + } + return false; +} + +// static +bool BrowserList::is_app_modal_ = false; + +// static +void BrowserList::SetIsShowingAppModalDialog(bool is_app_modal) { + // If we are already modal, we can't go modal again. + DCHECK(!(is_app_modal_ && is_app_modal)); + is_app_modal_ = is_app_modal; +} + +// static +bool BrowserList::IsShowingAppModalDialog() { + return is_app_modal_; +} + +// static +BrowserList::list_type BrowserList::last_active_browsers_; + +// static +void BrowserList::SetLastActive(Browser* browser) { + RemoveBrowserFrom(browser, &last_active_browsers_); + last_active_browsers_.push_back(browser); +} + +// static +Browser* BrowserList::GetLastActive() { + if (!last_active_browsers_.empty()) + return *(last_active_browsers_.rbegin()); + + return NULL; +} + +// static +Browser* BrowserList::FindBrowserWithType(Profile* p, BrowserType::Type t) { + Browser* last_active = GetLastActive(); + if (last_active->profile() == p && last_active->GetType() == t) + return last_active; + + BrowserList::const_iterator i; + for (i = BrowserList::begin(); i != BrowserList::end(); ++i) { + if (*i == last_active) + continue; + + if ((*i)->profile() == p && (*i)->GetType() == t) + return *i; + } + return NULL; +} + +// static +size_t BrowserList::GetBrowserCountForType(Profile* p, BrowserType::Type type) { + BrowserList::const_iterator i; + size_t result = 0; + for (i = BrowserList::begin(); i != BrowserList::end(); ++i) { + if ((*i)->profile() == p && (*i)->GetType() == type) + result++; + } + return result; +} + +// static +size_t BrowserList::GetBrowserCount(Profile* p) { + BrowserList::const_iterator i; + size_t result = 0; + for (i = BrowserList::begin(); i != BrowserList::end(); ++i) { + if ((*i)->profile() == p) + result++; + } + return result; +} + +// static +bool BrowserList::IsOffTheRecordSessionActive() { + BrowserList::const_iterator i; + for (i = BrowserList::begin(); i != BrowserList::end(); ++i) { + if ((*i)->profile()->IsOffTheRecord()) + return true; + } + return false; +} + +// static +void BrowserList::CloseAllDependentWindows() { + // Note that |dependent_windows_| is guaranteed to be consistent for the + // duration of this operation because windows are not actually closed + // (destroyed, then deleted, and thus removed from this list) until we return + // to the message loop. So this basically just schedules a bunch of close + // operations to be performed asynchronously. + DependentWindowList::iterator window = dependent_windows_.begin(); + for (; window != dependent_windows_.end(); ++window) + (*window)->Close(); +} + +// static +void BrowserList::RemoveBrowserFrom(Browser* browser, list_type* browser_list) { + const iterator remove_browser = + find(browser_list->begin(), browser_list->end(), browser); + if (remove_browser != browser_list->end()) + browser_list->erase(remove_browser); +} + +WebContentsIterator::WebContentsIterator() + : browser_iterator_(BrowserList::begin()), + web_view_index_(-1), + cur_(NULL) { + Advance(); + } + +void WebContentsIterator::Advance() { + // Unless we're at the beginning (index = -1) or end (iterator = end()), + // then the current WebContents should be valid. + DCHECK(web_view_index_ || browser_iterator_ == BrowserList::end() || + cur_) << "Trying to advance past the end"; + + // Update cur_ to the next WebContents in the list. + for (;;) { + web_view_index_++; + + while (web_view_index_ >= (*browser_iterator_)->tab_count()) { + // advance browsers + ++browser_iterator_; + web_view_index_ = 0; + if (browser_iterator_ == BrowserList::end()) { + cur_ = NULL; + return; + } + } + + WebContents* next_tab = + (*browser_iterator_)->GetTabContentsAt(web_view_index_)->AsWebContents(); + if (next_tab) { + cur_ = next_tab; + return; + } + } +} |