// 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.h"

#include <algorithm>

#include "base/auto_reset.h"
#include "base/logging.h"
#include "base/metrics/user_metrics.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/lifetime/browser_shutdown.h"
#include "chrome/browser/lifetime/termination_notification.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/browser_window.h"
#include "content/public/browser/notification_service.h"

using base::UserMetricsAction;
using content::WebContents;

namespace {

BrowserList::BrowserVector GetBrowsersToClose(Profile* profile) {
  BrowserList::BrowserVector browsers_to_close;
  for (auto* browser : *BrowserList::GetInstance()) {
    if (browser->profile()->GetOriginalProfile() ==
        profile->GetOriginalProfile())
      browsers_to_close.push_back(browser);
  }
  return browsers_to_close;
}

BrowserList::BrowserVector GetIncognitoBrowsersToClose(Profile* profile) {
  BrowserList::BrowserVector browsers_to_close;
  for (auto* browser : *BrowserList::GetInstance()) {
    if (browser->profile() == profile)
      browsers_to_close.push_back(browser);
  }
  return browsers_to_close;
}

}  // namespace

// static
base::LazyInstance<base::ObserverList<BrowserListObserver>>::Leaky
    BrowserList::observers_ = LAZY_INSTANCE_INITIALIZER;

// static
BrowserList* BrowserList::instance_ = NULL;

////////////////////////////////////////////////////////////////////////////////
// BrowserList, public:

Browser* BrowserList::GetLastActive() const {
  if (!last_active_browsers_.empty())
    return *(last_active_browsers_.rbegin());
  return NULL;
}

// static
BrowserList* BrowserList::GetInstance() {
  BrowserList** list = &instance_;
  if (!*list)
    *list = new BrowserList;
  return *list;
}

// static
void BrowserList::AddBrowser(Browser* browser) {
  DCHECK(browser);
  DCHECK(browser->window()) << "Browser should not be added to BrowserList "
                               "until it is fully constructed.";
  GetInstance()->browsers_.push_back(browser);

  browser->RegisterKeepAlive();

  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_BROWSER_OPENED,
      content::Source<Browser>(browser),
      content::NotificationService::NoDetails());

  for (BrowserListObserver& observer : observers_.Get())
    observer.OnBrowserAdded(browser);

  if (browser->window()->IsActive())
    SetLastActive(browser);
}

// static
void BrowserList::RemoveBrowser(Browser* browser) {
  // Remove |browser| from the appropriate list instance.
  BrowserList* browser_list = GetInstance();
  RemoveBrowserFrom(browser, &browser_list->last_active_browsers_);
  browser_list->currently_closing_browsers_.erase(browser);

  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_BROWSER_CLOSED,
      content::Source<Browser>(browser),
      content::NotificationService::NoDetails());

  RemoveBrowserFrom(browser, &browser_list->browsers_);

  for (BrowserListObserver& observer : observers_.Get())
    observer.OnBrowserRemoved(browser);

  browser->UnregisterKeepAlive();

  // If we're exiting, send out the APP_TERMINATING notification to allow other
  // modules to shut themselves down.
  if (chrome::GetTotalBrowserCount() == 0 &&
      (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_shutdown::NotifyAppTerminating();
    chrome::OnAppExiting();
  }
}

// static
void BrowserList::AddObserver(BrowserListObserver* observer) {
  observers_.Get().AddObserver(observer);
}

// static
void BrowserList::RemoveObserver(BrowserListObserver* observer) {
  observers_.Get().RemoveObserver(observer);
}

// static
void BrowserList::CloseAllBrowsersWithProfile(Profile* profile) {
  BrowserVector browsers_to_close;
  for (auto* browser : *BrowserList::GetInstance()) {
    if (browser->profile()->GetOriginalProfile() ==
        profile->GetOriginalProfile())
      browsers_to_close.push_back(browser);
  }

  for (BrowserVector::const_iterator it = browsers_to_close.begin();
       it != browsers_to_close.end(); ++it) {
    (*it)->window()->Close();
  }
}

// static
void BrowserList::CloseAllBrowsersWithProfile(
    Profile* profile,
    const CloseCallback& on_close_success,
    const CloseCallback& on_close_aborted,
    bool skip_beforeunload) {
  TryToCloseBrowserList(GetBrowsersToClose(profile), on_close_success,
                        on_close_aborted, profile->GetPath(),
                        skip_beforeunload);
}

// static
void BrowserList::CloseAllBrowsersWithIncognitoProfile(
    Profile* profile,
    const CloseCallback& on_close_success,
    const CloseCallback& on_close_aborted,
    bool skip_beforeunload) {
  DCHECK(profile->IsOffTheRecord());
  TryToCloseBrowserList(GetIncognitoBrowsersToClose(profile), on_close_success,
                        on_close_aborted, profile->GetPath(),
                        skip_beforeunload);
}

// static
void BrowserList::TryToCloseBrowserList(const BrowserVector& browsers_to_close,
                                        const CloseCallback& on_close_success,
                                        const CloseCallback& on_close_aborted,
                                        const base::FilePath& profile_path,
                                        const bool skip_beforeunload) {
  for (BrowserVector::const_iterator it = browsers_to_close.begin();
       it != browsers_to_close.end(); ++it) {
    if ((*it)->TryToCloseWindow(
            skip_beforeunload,
            base::Bind(&BrowserList::PostTryToCloseBrowserWindow,
                       browsers_to_close, on_close_success, on_close_aborted,
                       profile_path, skip_beforeunload))) {
      return;
    }
  }

  if (on_close_success)
    on_close_success.Run(profile_path);

  for (Browser* b : browsers_to_close) {
    // BeforeUnload handlers may close browser windows, so we need to explicitly
    // check whether they still exist.
    if (b->window())
      b->window()->Close();
  }
}

// static
void BrowserList::PostTryToCloseBrowserWindow(
    const BrowserVector& browsers_to_close,
    const CloseCallback& on_close_success,
    const CloseCallback& on_close_aborted,
    const base::FilePath& profile_path,
    const bool skip_beforeunload,
    bool tab_close_confirmed) {
  // We need this bool to avoid infinite recursion when resetting the
  // BeforeUnload handlers, since doing that will trigger calls back to this
  // method for each affected window.
  static bool resetting_handlers = false;

  if (tab_close_confirmed) {
    TryToCloseBrowserList(browsers_to_close, on_close_success, on_close_aborted,
                          profile_path, skip_beforeunload);
  } else if (!resetting_handlers) {
    base::AutoReset<bool> resetting_handlers_scoper(&resetting_handlers, true);
    for (BrowserVector::const_iterator it = browsers_to_close.begin();
         it != browsers_to_close.end(); ++it) {
      (*it)->ResetTryToCloseWindow();
    }
    if (on_close_aborted)
      on_close_aborted.Run(profile_path);
  }
}

// static
void BrowserList::MoveBrowsersInWorkspaceToFront(
    const std::string& new_workspace) {
  DCHECK(!new_workspace.empty());

  BrowserList* instance = GetInstance();

  Browser* old_last_active = instance->GetLastActive();
  BrowserVector& last_active_browsers = instance->last_active_browsers_;

  // Perform a stable partition on the browsers in the list so that the browsers
  // in the new workspace appear after the browsers in the other workspaces.
  //
  // For example, if we have a list of browser-workspace pairs
  // [{b1, 0}, {b2, 1}, {b3, 0}, {b4, 1}]
  // and we switch to workspace 1, we want the resulting browser list to look
  // like [{b1, 0}, {b3, 0}, {b2, 1}, {b4, 1}].
  std::stable_partition(
      last_active_browsers.begin(), last_active_browsers.end(),
      [&new_workspace](Browser* browser) {
        return !browser->window()->IsVisibleOnAllWorkspaces() &&
               browser->window()->GetWorkspace() != new_workspace;
      });

  Browser* new_last_active = instance->GetLastActive();
  if (old_last_active != new_last_active) {
    for (BrowserListObserver& observer : observers_.Get())
      observer.OnBrowserSetLastActive(new_last_active);
  }
}

// static
void BrowserList::SetLastActive(Browser* browser) {
  BrowserList* instance = GetInstance();
  DCHECK(std::find(instance->begin(), instance->end(), browser) !=
         instance->end())
      << "SetLastActive called for a browser before the browser was added to "
         "the BrowserList.";
  DCHECK(browser->window() != nullptr)
      << "SetLastActive called for a browser with no window set.";

  base::RecordAction(UserMetricsAction("ActiveBrowserChanged"));

  RemoveBrowserFrom(browser, &instance->last_active_browsers_);
  instance->last_active_browsers_.push_back(browser);

  for (BrowserListObserver& observer : observers_.Get())
    observer.OnBrowserSetLastActive(browser);
}

// static
void BrowserList::NotifyBrowserNoLongerActive(Browser* browser) {
  BrowserList* instance = GetInstance();
  DCHECK(std::find(instance->begin(), instance->end(), browser) !=
         instance->end())
      << "NotifyBrowserNoLongerActive called for a browser before the browser "
         "was added to the BrowserList.";
  DCHECK(browser->window() != nullptr)
      << "NotifyBrowserNoLongerActive called for a browser with no window set.";

  for (BrowserListObserver& observer : observers_.Get())
    observer.OnBrowserNoLongerActive(browser);
}

// static
void BrowserList::NotifyBrowserCloseStarted(Browser* browser) {
  GetInstance()->currently_closing_browsers_.insert(browser);

  for (BrowserListObserver& observer : observers_.Get())
    observer.OnBrowserClosing(browser);
}

// static
bool BrowserList::IsIncognitoSessionActive() {
  for (auto* browser : *BrowserList::GetInstance()) {
    if (browser->profile()->IsOffTheRecord())
      return true;
  }
  return false;
}

// static
bool BrowserList::IsIncognitoSessionActiveForProfile(Profile* profile) {
  for (auto* browser : *BrowserList::GetInstance()) {
    if (browser->profile()->IsSameProfile(profile) &&
        browser->profile()->IsOffTheRecord()) {
      return true;
    }
  }
  return false;
}

////////////////////////////////////////////////////////////////////////////////
// BrowserList, private:

BrowserList::BrowserList() {
}

BrowserList::~BrowserList() {
}

// static
void BrowserList::RemoveBrowserFrom(Browser* browser,
                                    BrowserVector* browser_list) {
  BrowserVector::iterator remove_browser =
      std::find(browser_list->begin(), browser_list->end(), browser);
  if (remove_browser != browser_list->end())
    browser_list->erase(remove_browser);
}
