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

#include <stddef.h>
#include <algorithm>
#include <string>
#include <utility>
#include <vector>

#include "base/base_paths.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/background/background_application_list_model.h"
#include "chrome/browser/background/background_mode_optimizer.h"
#include "chrome/browser/background/background_trigger.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/lifetime/browser_shutdown.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_attributes_entry.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/status_icons/status_icon.h"
#include "chrome/browser/status_icons/status_tray.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/extensions/app_launch_params.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/browser/ui/user_manager.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/chrome_unscaled_resources.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/keep_alive_registry/keep_alive_registry.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/startup_metric_utils/browser/startup_metric_utils.h"
#include "content/public/browser/notification_service.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_handlers/options_page_info.h"
#include "extensions/common/one_shot_event.h"
#include "extensions/common/permissions/permission_set.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"

#if defined(OS_WIN)
#include "chrome/browser/win/app_icon.h"
#endif

using base::UserMetricsAction;
using extensions::Extension;

namespace {

// Enum for recording menu item clicks in UMA.
// NOTE: Do not renumber these as that would confuse interpretation of
// previously logged data. When making changes, also update histograms.xml.
enum MenuItem {
  MENU_ITEM_ABOUT = 0,
  MENU_ITEM_TASK_MANAGER = 1,
  MENU_ITEM_BACKGROUND_CLIENT = 2,
  MENU_ITEM_KEEP_RUNNING = 3,
  MENU_ITEM_EXIT = 4,
  MENU_ITEM_NUM_STATES
};

void RecordMenuItemClick(MenuItem item) {
  UMA_HISTOGRAM_ENUMERATION("BackgroundMode.MenuItemClick", item,
                            MENU_ITEM_NUM_STATES);
}
}  // namespace

// static
bool BackgroundModeManager::should_restart_in_background_ = false;

BackgroundModeManager::BackgroundModeData::BackgroundModeData(
    Profile* profile,
    CommandIdHandlerVector* command_id_handler_vector)
    : applications_(std::make_unique<BackgroundApplicationListModel>(profile)),
      profile_(profile),
      command_id_handler_vector_(command_id_handler_vector) {}

BackgroundModeManager::BackgroundModeData::~BackgroundModeData() {
}

///////////////////////////////////////////////////////////////////////////////
//  BackgroundModeManager::BackgroundModeData, StatusIconMenuModel overrides
void BackgroundModeManager::BackgroundModeData::ExecuteCommand(
    int command_id,
    int event_flags) {
  switch (command_id) {
    case IDC_MinimumLabelValue:
      // Do nothing. This is just a label.
      break;
    default:
      DCHECK(!command_id_handler_vector_->at(command_id).is_null());
      RecordMenuItemClick(MENU_ITEM_BACKGROUND_CLIENT);
      command_id_handler_vector_->at(command_id).Run();
      break;
  }
}

Browser* BackgroundModeManager::BackgroundModeData::GetBrowserWindow() {
  return BackgroundModeManager::GetBrowserWindowForProfile(profile_);
}

bool BackgroundModeManager::BackgroundModeData::HasBackgroundClient() const {
  return applications_->size() > 0 || !registered_triggers_.empty();
}

void BackgroundModeManager::BackgroundModeData::BuildProfileMenu(
    StatusIconMenuModel* menu,
    StatusIconMenuModel* containing_menu) {
  if (HasBackgroundClient()) {
    // Add a menu item for each application (extension).
    for (const auto& application : *applications_) {
      const gfx::ImageSkia* icon = applications_->GetIcon(application.get());
      const std::string& name = application->name();
      int command_id = command_id_handler_vector_->size();
      // Check that the command ID is within the dynamic range.
      DCHECK_LT(command_id, IDC_MinimumLabelValue);
      command_id_handler_vector_->push_back(base::BindRepeating(
          &BackgroundModeManager::LaunchBackgroundApplication, profile_,
          base::RetainedRef(application)));
      menu->AddItem(command_id, base::UTF8ToUTF16(name));
      if (icon)
        menu->SetIcon(menu->GetItemCount() - 1, gfx::Image(*icon));

      // Component extensions with background that do not have an options page
      // will cause this menu item to go to the extensions page with an
      // absent component extension.
      //
      // Ideally, we would remove this item, but this conflicts with the user
      // model where this menu shows the extensions with background.
      //
      // The compromise is to disable the item, avoiding the non-actionable
      // navigate to the extensions page and preserving the user model.
      if (application->location() == extensions::Manifest::COMPONENT) {
        GURL options_page =
            extensions::OptionsPageInfo::GetOptionsPage(application.get());
        if (!options_page.is_valid())
          menu->SetCommandIdEnabled(command_id, false);
      }
    }

    // Add a menu item for each trigger.
    for (auto* trigger : registered_triggers_) {
      const gfx::ImageSkia* icon = trigger->GetIcon();
      const base::string16& name = trigger->GetName();
      int command_id = command_id_handler_vector_->size();
      // Check that the command ID is within the dynamic range.
      DCHECK_LT(command_id, IDC_MinimumLabelValue);
      command_id_handler_vector_->push_back(base::BindRepeating(
          &BackgroundTrigger::OnMenuClick, base::Unretained(trigger)));
      menu->AddItem(command_id, name);
      if (icon)
        menu->SetIcon(menu->GetItemCount() - 1, gfx::Image(*icon));
    }
  } else {
    // When there are no background clients, we want to display just a label
    // stating that none are running.
    menu->AddItemWithStringId(IDC_MinimumLabelValue,
                              IDS_BACKGROUND_APP_NOT_INSTALLED);
    menu->SetCommandIdEnabled(IDC_MinimumLabelValue, false);
  }
  if (containing_menu) {
    int menu_command_id = command_id_handler_vector_->size();
    // Check that the command ID is within the dynamic range.
    DCHECK_LT(menu_command_id, IDC_MinimumLabelValue);
    command_id_handler_vector_->push_back(base::DoNothing());
    containing_menu->AddSubMenu(menu_command_id, name_, menu);
  }
}

void BackgroundModeManager::BackgroundModeData::SetName(
    const base::string16& new_profile_name) {
  name_ = new_profile_name;
}

base::string16 BackgroundModeManager::BackgroundModeData::name() {
  return name_;
}

std::set<const extensions::Extension*>
BackgroundModeManager::BackgroundModeData::GetNewBackgroundApps() {
  std::set<const extensions::Extension*> new_apps;

  // Copy all current extensions into our list of |current_extensions_|.
  for (const auto& application : *applications_) {
    const extensions::ExtensionId& id = application->id();
    if (current_extensions_.count(id) == 0) {
      // Not found in our set yet - add it and maybe return as a previously
      // unseen extension.
      current_extensions_.insert(id);
      // If this application has been newly loaded after the initial startup,
      // notify the user.
      if (applications_->is_ready())
        new_apps.insert(application.get());
    }
  }
  return new_apps;
}

// static
bool BackgroundModeManager::BackgroundModeData::BackgroundModeDataCompare(
    const BackgroundModeData* bmd1,
    const BackgroundModeData* bmd2) {
  return bmd1->name_ < bmd2->name_;
}

void BackgroundModeManager::BackgroundModeData::AddPendingTrigger(
    BackgroundTrigger* trigger, bool should_notify_user) {
  if (HasTrigger(trigger))
    return;
  pending_trigger_data_[trigger] = should_notify_user;
}

BackgroundModeManager::PendingTriggerData
BackgroundModeManager::BackgroundModeData::TakePendingTriggerData() {
  return std::move(pending_trigger_data_);
}

bool BackgroundModeManager::BackgroundModeData::HasPendingTrigger() const {
  return !pending_trigger_data_.empty();
}

void BackgroundModeManager::BackgroundModeData::RegisterTrigger(
    BackgroundTrigger* trigger) {
  if (HasTrigger(trigger))
    return;
  registered_triggers_.insert(trigger);
}

void BackgroundModeManager::BackgroundModeData::UnregisterTrigger(
    BackgroundTrigger* trigger) {
  registered_triggers_.erase(trigger);
  pending_trigger_data_.erase(trigger);
}

bool BackgroundModeManager::BackgroundModeData::HasTrigger(
    BackgroundTrigger* trigger) {
  return base::ContainsKey(registered_triggers_, trigger) ||
         base::ContainsKey(pending_trigger_data_, trigger);
}

///////////////////////////////////////////////////////////////////////////////
//  BackgroundModeManager, public
BackgroundModeManager::BackgroundModeManager(
    const base::CommandLine& command_line,
    ProfileAttributesStorage* profile_storage)
    : profile_storage_(profile_storage),
      task_runner_(CreateTaskRunner()),
      weak_factory_(this) {
  // We should never start up if there is no browser process or if we are
  // currently quitting.
  CHECK(g_browser_process);
  CHECK(!browser_shutdown::IsTryingToQuit());

  // Add self as an observer for the ProfileAttributesStorage so we know when
  // profiles are deleted and their names change.
  profile_storage_->AddObserver(this);

  UMA_HISTOGRAM_BOOLEAN("BackgroundMode.OnStartup.AutoLaunchState",
                        command_line.HasSwitch(switches::kNoStartupWindow));
  UMA_HISTOGRAM_BOOLEAN("BackgroundMode.OnStartup.IsBackgroundModePrefEnabled",
                        IsBackgroundModePrefEnabled());

  // Listen for the background mode preference changing.
  if (g_browser_process->local_state()) {  // Skip for unit tests
    pref_registrar_.Init(g_browser_process->local_state());
    pref_registrar_.Add(
        prefs::kBackgroundModeEnabled,
        base::BindRepeating(
            &BackgroundModeManager::OnBackgroundModeEnabledPrefChanged,
            base::Unretained(this)));
  }

  // Keep the browser alive until extensions are done loading - this is needed
  // by the --no-startup-window flag. We want to stay alive until we load
  // extensions, at which point we should either run in background mode (if
  // there are background apps) or exit if there are none.
  if (command_line.HasSwitch(switches::kNoStartupWindow)) {
    keep_alive_for_startup_.reset(
        new ScopedKeepAlive(KeepAliveOrigin::BACKGROUND_MODE_MANAGER_STARTUP,
                            KeepAliveRestartOption::DISABLED));
  } else {
    // Otherwise, start with background mode suspended in case we're launching
    // in a mode that doesn't open a browser window. It will be resumed when the
    // first browser window is opened.
    SuspendBackgroundMode();
    optimizer_ = BackgroundModeOptimizer::Create();
  }

  // If the -keep-alive-for-test flag is passed, then always keep chrome running
  // in the background until the user explicitly terminates it.
  if (command_line.HasSwitch(switches::kKeepAliveForTest))
    keep_alive_for_test_ = true;

  if (ShouldBeInBackgroundMode())
    StartBackgroundMode();

  // Listen for the application shutting down so we can release our KeepAlive.
  registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
                 content::NotificationService::AllSources());
  BrowserList::AddObserver(this);
}

BackgroundModeManager::~BackgroundModeManager() {
  // Remove ourselves from the application observer list (only needed by unit
  // tests since APP_TERMINATING is what does this in a real running system).
  for (const auto& it : background_mode_data_)
    it.second->applications()->RemoveObserver(this);
  BrowserList::RemoveObserver(this);

  // We're going away, so exit background mode (does nothing if we aren't in
  // background mode currently). This is primarily needed for unit tests,
  // because in an actual running system we'd get an APP_TERMINATING
  // notification before being destroyed.
  EndBackgroundMode();
}

// static
void BackgroundModeManager::RegisterPrefs(PrefRegistrySimple* registry) {
#if defined(OS_MACOSX)
  registry->RegisterBooleanPref(prefs::kUserRemovedLoginItem, false);
  registry->RegisterBooleanPref(prefs::kChromeCreatedLoginItem, false);
  registry->RegisterBooleanPref(prefs::kMigratedLoginItemPref, false);
#endif
  registry->RegisterBooleanPref(prefs::kBackgroundModeEnabled, true);
}

void BackgroundModeManager::RegisterProfile(Profile* profile) {
  // We don't want to register multiple times for one profile.
  DCHECK(!base::ContainsKey(background_mode_data_, profile));
  auto bmd = std::make_unique<BackgroundModeData>(profile,
                                                  &command_id_handler_vector_);
  BackgroundModeData* bmd_ptr = bmd.get();
  background_mode_data_[profile] = std::move(bmd);

  // Initially set the name for this background mode data.
  base::string16 name = l10n_util::GetStringUTF16(IDS_PROFILES_DEFAULT_NAME);
  ProfileAttributesEntry* entry;
  if (profile_storage_->GetProfileAttributesWithPath(
      profile->GetPath(), &entry)) {
    name = entry->GetName();
  }
  bmd_ptr->SetName(name);

  // Check for the presence of background apps after all extensions have been
  // loaded, to handle the case where an extension has been manually removed
  // while Chrome was not running.
  extensions::ExtensionSystem::Get(profile)->ready().Post(
      FROM_HERE,
      base::Bind(&BackgroundModeManager::OnExtensionsReady,
        weak_factory_.GetWeakPtr(), profile));

  bmd_ptr->applications()->AddObserver(this);

  // If we're adding a new profile and running in multi-profile mode, this new
  // profile should be added to the status icon if one currently exists.
  if (in_background_mode_ && status_icon_)
    UpdateStatusTrayIconContextMenu();
}

// static
void BackgroundModeManager::LaunchBackgroundApplication(
    Profile* profile,
    const Extension* extension) {
  OpenApplication(CreateAppLaunchParamsUserContainer(
      profile, extension, WindowOpenDisposition::NEW_FOREGROUND_TAB,
      extensions::SOURCE_BACKGROUND));
}

// static
Browser* BackgroundModeManager::GetBrowserWindowForProfile(Profile* profile) {
  Browser* browser = chrome::FindLastActiveWithProfile(profile);
  return browser ? browser : chrome::OpenEmptyWindow(profile);
}

bool BackgroundModeManager::IsBackgroundModeActive() {
  return in_background_mode_;
}

bool BackgroundModeManager::IsBackgroundWithoutWindows() const {
  return KeepAliveRegistry::GetInstance()->WouldRestartWithout({
      // Transient startup related KeepAlives, not related to any UI.
      KeepAliveOrigin::SESSION_RESTORE,
      KeepAliveOrigin::BACKGROUND_MODE_MANAGER_STARTUP,

      // Notification KeepAlives are not dependent on the Chrome UI being
      // loaded, and can be registered when we were in pure background mode.
      // They just block it to avoid issues. Ignore them when determining if we
      // are in that mode.
      KeepAliveOrigin::NOTIFICATION,
      KeepAliveOrigin::PENDING_NOTIFICATION_CLICK_EVENT,
      KeepAliveOrigin::IN_FLIGHT_PUSH_MESSAGE,
  });
}

size_t BackgroundModeManager::NumberOfBackgroundModeData() {
  return background_mode_data_.size();
}

void BackgroundModeManager::RegisterTrigger(const Profile* profile,
                                            BackgroundTrigger* trigger,
                                            bool should_notify_user) {
  BackgroundModeManager::BackgroundModeData* bmd =
      GetBackgroundModeData(profile);
  if (!bmd)
    return;

  // Only proceed if we don't have this trigger yet.
  if (bmd->HasTrigger(trigger))
    return;

  // If the background pref is disabled, store it as a pending trigger that may
  // be registered later if the pref gets enabled.
  if (!IsBackgroundModePrefEnabled()) {
    bmd->AddPendingTrigger(trigger, should_notify_user);
    return;
  }

  bmd->RegisterTrigger(trigger);
  std::vector<base::string16> new_client_names;
  if (should_notify_user)
    new_client_names.push_back(trigger->GetName());
  OnClientsChanged(profile, new_client_names);
}

void BackgroundModeManager::UnregisterTrigger(const Profile* profile,
                                              BackgroundTrigger* trigger) {
  if (!IsBackgroundModePrefEnabled())
    return;

  BackgroundModeManager::BackgroundModeData* bmd =
      GetBackgroundModeData(profile);
  if (!bmd)
    return;

  // Only proceed if this is a known trigger.
  if (!bmd->HasTrigger(trigger))
    return;
  bmd->UnregisterTrigger(trigger);

  std::vector<base::string16> new_client_names;
  OnClientsChanged(profile, new_client_names);
}

///////////////////////////////////////////////////////////////////////////////
//  BackgroundModeManager, content::NotificationObserver overrides
void BackgroundModeManager::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type);

  // Make sure we aren't still keeping the app alive (only happens if we
  // don't receive an EXTENSIONS_READY notification for some reason).
  ReleaseStartupKeepAlive();
  // Performing an explicit shutdown, so exit background mode (does nothing
  // if we aren't in background mode currently).
  EndBackgroundMode();
  // Shutting down, so don't listen for any more notifications so we don't
  // try to re-enter/exit background mode again.
  registrar_.RemoveAll();
  for (const auto& it : background_mode_data_)
    it.second->applications()->RemoveObserver(this);
}

void BackgroundModeManager::OnExtensionsReady(const Profile* profile) {
  BackgroundModeManager::BackgroundModeData* bmd =
      GetBackgroundModeData(profile);
  if (bmd) {
    UMA_HISTOGRAM_COUNTS_100("BackgroundMode.BackgroundApplicationsCount",
                             bmd->applications()->size());
  }
  // Extensions are loaded, so we don't need to manually keep the browser
  // process alive any more when running in no-startup-window mode.
  ReleaseStartupKeepAlive();
}

void BackgroundModeManager::OnBackgroundModeEnabledPrefChanged() {
  bool enabled = IsBackgroundModePrefEnabled();
  UMA_HISTOGRAM_BOOLEAN("BackgroundMode.BackgroundModeEnabledPrefChanged",
                        enabled);
  if (enabled)
    EnableBackgroundMode();
  else
    DisableBackgroundMode();
}

///////////////////////////////////////////////////////////////////////////////
//  BackgroundModeManager, BackgroundApplicationListModel::Observer overrides
void BackgroundModeManager::OnApplicationDataChanged() {
  UpdateStatusTrayIconContextMenu();
}

void BackgroundModeManager::OnApplicationListChanged(const Profile* profile) {
  if (!IsBackgroundModePrefEnabled())
    return;

  BackgroundModeManager::BackgroundModeData* bmd =
      GetBackgroundModeData(profile);
  if (!bmd)
    return;

  // Get the new apps (if any) and process them.
  std::set<const extensions::Extension*> new_apps = bmd->GetNewBackgroundApps();
  std::vector<base::string16> new_names;
  for (auto* app : new_apps)
    new_names.push_back(base::UTF8ToUTF16(app->name()));
  OnClientsChanged(profile, new_names);
}

///////////////////////////////////////////////////////////////////////////////
//  BackgroundModeManager, ProfileAttributesStorage::Observer overrides
void BackgroundModeManager::OnProfileAdded(const base::FilePath& profile_path) {
  ProfileAttributesEntry* entry;
  bool success =
      profile_storage_->GetProfileAttributesWithPath(profile_path, &entry);
  DCHECK(success);
  base::string16 profile_name = entry->GetName();
  // At this point, the profile should be registered with the background mode
  // manager, but when it's actually added to the ProfileAttributesStorage is
  // when its name is set so we need up to update that with the
  // background_mode_data.
  for (const auto& it : background_mode_data_) {
    if (it.first->GetPath() == profile_path) {
      it.second->SetName(profile_name);
      UpdateStatusTrayIconContextMenu();
      return;
    }
  }
}

void BackgroundModeManager::OnProfileWillBeRemoved(
    const base::FilePath& profile_path) {
  ProfileAttributesEntry* entry;
  bool success =
      profile_storage_->GetProfileAttributesWithPath(profile_path, &entry);
  DCHECK(success);
  base::string16 profile_name = entry->GetName();
  // Remove the profile from our map of profiles.
  BackgroundModeInfoMap::iterator it =
      GetBackgroundModeIterator(profile_name);
  // If a profile isn't running a background app, it may not be in the map.
  if (it != background_mode_data_.end()) {
    it->second->applications()->RemoveObserver(this);
    background_mode_data_.erase(it);
    // If there are no background mode profiles any longer, then turn off
    // background mode.
    if (!ShouldBeInBackgroundMode()) {
      EnableLaunchOnStartup(false);
      EndBackgroundMode();
    }
    UpdateStatusTrayIconContextMenu();
  }
}

void BackgroundModeManager::OnProfileNameChanged(
    const base::FilePath& profile_path,
    const base::string16& old_profile_name) {
  ProfileAttributesEntry* entry;
  bool success =
      profile_storage_->GetProfileAttributesWithPath(profile_path, &entry);
  DCHECK(success);
  base::string16 new_profile_name = entry->GetName();
  BackgroundModeInfoMap::const_iterator it =
      GetBackgroundModeIterator(old_profile_name);
  // We check that the returned iterator is valid due to unittests, but really
  // this should only be called on profiles already known by the background
  // mode manager.
  if (it != background_mode_data_.end()) {
    it->second->SetName(new_profile_name);
    UpdateStatusTrayIconContextMenu();
  }
}

BackgroundModeManager::BackgroundModeData*
BackgroundModeManager::GetBackgroundModeDataForLastProfile() const {
  Profile* most_recent_profile = g_browser_process->profile_manager()->
      GetLastUsedProfileAllowedByPolicy();
  BackgroundModeInfoMap::const_iterator profile_background_data =
      background_mode_data_.find(most_recent_profile);

  if (profile_background_data == background_mode_data_.end())
    return nullptr;

  // Do not permit a locked profile to be used to open a browser.
  ProfileAttributesEntry* entry;
  bool success = profile_storage_->GetProfileAttributesWithPath(
      profile_background_data->first->GetPath(), &entry);
  DCHECK(success);
  if (entry->IsSigninRequired())
    return nullptr;

  return profile_background_data->second.get();
}

///////////////////////////////////////////////////////////////////////////////
//  BackgroundModeManager::BackgroundModeData, StatusIconMenuModel overrides
void BackgroundModeManager::ExecuteCommand(int command_id, int event_flags) {
  BackgroundModeData* bmd = GetBackgroundModeDataForLastProfile();
  switch (command_id) {
    case IDC_ABOUT:
      RecordMenuItemClick(MENU_ITEM_ABOUT);
      if (bmd) {
        chrome::ShowAboutChrome(bmd->GetBrowserWindow());
      } else {
        UserManager::Show(base::FilePath(),
                          profiles::USER_MANAGER_SELECT_PROFILE_ABOUT_CHROME);
      }
      break;
    case IDC_TASK_MANAGER:
    RecordMenuItemClick(MENU_ITEM_TASK_MANAGER);
      if (bmd) {
        chrome::OpenTaskManager(bmd->GetBrowserWindow());
      } else {
        UserManager::Show(base::FilePath(),
                          profiles::USER_MANAGER_SELECT_PROFILE_TASK_MANAGER);
      }
      break;
    case IDC_EXIT:
      RecordMenuItemClick(MENU_ITEM_EXIT);
      base::RecordAction(UserMetricsAction("Exit"));
      chrome::CloseAllBrowsers();
      break;
    case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: {
      // Background mode must already be enabled (as otherwise this menu would
      // not be visible).
      DCHECK(IsBackgroundModePrefEnabled());
      DCHECK(KeepAliveRegistry::GetInstance()->IsKeepingAlive());

      RecordMenuItemClick(MENU_ITEM_KEEP_RUNNING);

      // Set the background mode pref to "disabled" - the resulting notification
      // will result in a call to DisableBackgroundMode().
      PrefService* service = g_browser_process->local_state();
      DCHECK(service);
      service->SetBoolean(prefs::kBackgroundModeEnabled, false);
      break;
    }
    default:
      if (bmd) {
        bmd->ExecuteCommand(command_id, event_flags);
      } else {
        UserManager::Show(base::FilePath(),
                          profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION);
      }
      break;
  }
}


///////////////////////////////////////////////////////////////////////////////
//  BackgroundModeManager, private
void BackgroundModeManager::ReleaseStartupKeepAliveCallback() {
  keep_alive_for_startup_.reset();
  optimizer_ = BackgroundModeOptimizer::Create();
}

void BackgroundModeManager::ReleaseStartupKeepAlive() {
  if (keep_alive_for_startup_) {
    // We call this via the message queue to make sure we don't try to end
    // keep-alive (which can shutdown Chrome) before the message loop has
    // started. This object reference is safe because it's going to be kept
    // alive by the browser process until after the callback is called.
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::BindOnce(&BackgroundModeManager::ReleaseStartupKeepAliveCallback,
                       base::Unretained(this)));
  }
}

void BackgroundModeManager::StartBackgroundMode() {
  DCHECK(ShouldBeInBackgroundMode());
  // Don't bother putting ourselves in background mode if we're already there
  // or if background mode is disabled.
  if (in_background_mode_)
    return;

  startup_metric_utils::SetBackgroundModeEnabled();

  // Mark ourselves as running in background mode.
  in_background_mode_ = true;

  UpdateKeepAliveAndTrayIcon();

  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED,
      content::Source<BackgroundModeManager>(this),
      content::Details<bool>(&in_background_mode_));
}

void BackgroundModeManager::EndBackgroundMode() {
  if (!in_background_mode_)
    return;
  in_background_mode_ = false;

  UpdateKeepAliveAndTrayIcon();

  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED,
      content::Source<BackgroundModeManager>(this),
      content::Details<bool>(&in_background_mode_));
}

void BackgroundModeManager::EnableBackgroundMode() {
  DCHECK(IsBackgroundModePrefEnabled());
  // If background mode should be enabled, but isn't, turn it on.
  if (!in_background_mode_ && ShouldBeInBackgroundMode()) {
    StartBackgroundMode();

    // Register pending triggers.
    for (const auto& bmd_iterator : background_mode_data_) {
      PendingTriggerData pending_trigger_data =
          bmd_iterator.second->TakePendingTriggerData();
      for (const auto& trigger_data_iterator : pending_trigger_data) {
        const Profile* profile = bmd_iterator.first;
        BackgroundTrigger* trigger = trigger_data_iterator.first;
        bool should_notify_user = trigger_data_iterator.second;
        RegisterTrigger(profile, trigger, should_notify_user);
      }
    }

    EnableLaunchOnStartup(true);
  }
}

void BackgroundModeManager::DisableBackgroundMode() {
  DCHECK(!IsBackgroundModePrefEnabled());
  // If background mode is currently enabled, turn it off.
  if (in_background_mode_) {
    EndBackgroundMode();
    EnableLaunchOnStartup(false);
  }
}

void BackgroundModeManager::SuspendBackgroundMode() {
  background_mode_suspended_ = true;
  UpdateKeepAliveAndTrayIcon();
}

void BackgroundModeManager::ResumeBackgroundMode() {
  background_mode_suspended_ = false;
  UpdateKeepAliveAndTrayIcon();
}

void BackgroundModeManager::UpdateKeepAliveAndTrayIcon() {
  if (in_background_mode_ && !background_mode_suspended_) {
    if (!keep_alive_) {
      keep_alive_ = std::make_unique<ScopedKeepAlive>(
          KeepAliveOrigin::BACKGROUND_MODE_MANAGER,
          KeepAliveRestartOption::ENABLED);
    }
    CreateStatusTrayIcon();
    return;
  }

  RemoveStatusTrayIcon();
  keep_alive_.reset();
}

void BackgroundModeManager::OnBrowserAdded(Browser* browser) {
  ResumeBackgroundMode();
}

void BackgroundModeManager::OnClientsChanged(
    const Profile* profile,
    const std::vector<base::string16>& new_client_names) {
  DCHECK(IsBackgroundModePrefEnabled());

  // Update the ProfileAttributesStorage with the fact whether background
  // clients are running for this profile.
  ProfileAttributesEntry* entry;
  if (profile_storage_->
      GetProfileAttributesWithPath(profile->GetPath(), &entry)) {
    entry->SetBackgroundStatus(HasBackgroundClientForProfile(profile));
  }

  if (!ShouldBeInBackgroundMode()) {
    // We've uninstalled our last background client, make sure we exit
    // background mode and no longer launch on startup.
    EnableLaunchOnStartup(false);
    EndBackgroundMode();
  } else {
    // We have at least one background client - make sure we're in background
    // mode.
    if (!in_background_mode_) {
      // We're entering background mode - make sure we have launch-on-startup
      // enabled. On Mac, the platform-specific code tracks whether the user
      // has deleted a login item in the past, and if so, no login item will
      // be created (to avoid overriding the specific user action).
      EnableLaunchOnStartup(true);
      StartBackgroundMode();
    }

    // List of clients changed so update the UI.
    UpdateStatusTrayIconContextMenu();

    // Notify the user about any new clients.
    for (const auto& name : new_client_names)
      OnBackgroundClientInstalled(name);
  }
}

bool BackgroundModeManager::HasBackgroundClient() const {
  for (const auto& it : background_mode_data_) {
    if (it.second->HasBackgroundClient())
      return true;
  }
  return false;
}

bool BackgroundModeManager::HasBackgroundClientForProfile(
    const Profile* profile) const {
  BackgroundModeManager::BackgroundModeData* bmd =
      GetBackgroundModeData(profile);
  return bmd && bmd->HasBackgroundClient();
}

bool BackgroundModeManager::HasPendingTrigger() const {
  for (const auto& it : background_mode_data_) {
    if (it.second->HasPendingTrigger())
      return true;
  }
  return false;
}

bool BackgroundModeManager::ShouldBeInBackgroundMode() const {
  return IsBackgroundModePrefEnabled() &&
         (HasBackgroundClient() || HasPendingTrigger() || keep_alive_for_test_);
}

void BackgroundModeManager::OnBackgroundClientInstalled(
    const base::string16& name) {
  // Background mode is disabled - don't do anything.
  if (!IsBackgroundModePrefEnabled())
    return;

  // Ensure we have a tray icon (needed so we can display the app-installed
  // notification below).
  EnableBackgroundMode();
  ResumeBackgroundMode();

  // Notify the user that a background client has been installed.
  DisplayClientInstalledNotification(name);
}

// Gets the image for the status tray icon, at the correct size for the current
// platform and display settings.
gfx::ImageSkia GetStatusTrayIcon() {
#if defined(OS_WIN)
  // On Windows, use GetSmallAppIconSize to get the correct image size. The
  // user's "text size" setting in Windows determines how large the system tray
  // icon should be.
  gfx::Size size = GetSmallAppIconSize();

  // This loads all of the icon images, which is a bit wasteful because we're
  // going to pick one and throw the rest away, but that is the price of using
  // the ImageFamily abstraction. Note: We could just use the LoadImage function
  // from the Windows API, but that does a *terrible* job scaling images.
  // Therefore, we fetch the images and do our own high-quality scaling.
  std::unique_ptr<gfx::ImageFamily> family = GetAppIconImageFamily();
  DCHECK(family);
  if (!family)
    return gfx::ImageSkia();

  return family->CreateExact(size).AsImageSkia();
#else
  // On other platforms, just get a static resource image.
  return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
      IDR_STATUS_TRAY_ICON);
#endif
}

void BackgroundModeManager::CreateStatusTrayIcon() {
  // Only need status icons on windows/linux. ChromeOS doesn't allow exiting
  // Chrome and Mac can use the dock icon instead.

  // Since there are multiple profiles which share the status tray, we now
  // use the browser process to keep track of it.
#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
  if (!status_tray_)
    status_tray_ = g_browser_process->status_tray();
#endif

  // If the platform doesn't support status icons, or we've already created
  // our status icon, just return.
  if (!status_tray_ || status_icon_)
    return;

  status_icon_ = status_tray_->CreateStatusIcon(
      StatusTray::BACKGROUND_MODE_ICON, GetStatusTrayIcon(),
      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
  if (!status_icon_)
    return;
  UpdateStatusTrayIconContextMenu();
}

void BackgroundModeManager::UpdateStatusTrayIconContextMenu() {
  // Ensure we have a tray icon if appropriate.
  UpdateKeepAliveAndTrayIcon();

  // If we don't have a status icon or one could not be created succesfully,
  // then no need to continue the update.
  if (!status_icon_)
    return;

  // We should only get here if we have a profile loaded, or if we're running
  // in test mode.
  if (background_mode_data_.empty()) {
    DCHECK(keep_alive_for_test_);
    return;
  }

  command_id_handler_vector_.clear();
  submenus.clear();

  std::unique_ptr<StatusIconMenuModel> menu(new StatusIconMenuModel(this));
  menu->AddItem(IDC_ABOUT, l10n_util::GetStringUTF16(IDS_ABOUT));
  menu->AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER);
  menu->AddSeparator(ui::NORMAL_SEPARATOR);

  // If there are multiple profiles they each get a submenu.
  if (profile_storage_->GetNumberOfProfiles() > 1) {
    std::vector<BackgroundModeData*> bmd_vector;
    for (const auto& it : background_mode_data_)
      bmd_vector.push_back(it.second.get());
    std::sort(bmd_vector.begin(), bmd_vector.end(),
              &BackgroundModeData::BackgroundModeDataCompare);
    int profiles_using_background_mode = 0;
    for (auto* bmd : bmd_vector) {
      // We should only display the profile in the status icon if it has at
      // least one background app.
      if (bmd->HasBackgroundClient()) {
        // The submenu constructor caller owns the lifetime of the submenu.
        // The containing menu does not handle the lifetime.
        submenus.push_back(std::make_unique<StatusIconMenuModel>(bmd));
        bmd->BuildProfileMenu(submenus.back().get(), menu.get());
        profiles_using_background_mode++;
      }
    }
    // We should only be displaying the status tray icon if there is at least
    // one profile using background mode. If |keep_alive_for_test_| is set,
    // there may not be any profiles and that is okay.
    DCHECK(profiles_using_background_mode > 0 || keep_alive_for_test_);
  } else {
    // We should only have one profile in the ProfileAttributesStorage if we are
    // not using multi-profiles. If |keep_alive_for_test_| is set, then we may
    // not have any profiles in the ProfileAttributesStorage.
    DCHECK(profile_storage_->GetNumberOfProfiles() == size_t(1) ||
           keep_alive_for_test_);
    background_mode_data_.begin()->second->BuildProfileMenu(menu.get(),
                                                            nullptr);
  }

  menu->AddSeparator(ui::NORMAL_SEPARATOR);
  menu->AddCheckItemWithStringId(
      IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND,
      IDS_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND);
  menu->SetCommandIdChecked(IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND,
                            true);

  PrefService* service = g_browser_process->local_state();
  DCHECK(service);
  bool enabled =
      service->IsUserModifiablePreference(prefs::kBackgroundModeEnabled);
  menu->SetCommandIdEnabled(IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND,
                            enabled);

  menu->AddItemWithStringId(IDC_EXIT, IDS_EXIT);

  context_menu_ = menu.get();
  status_icon_->SetContextMenu(std::move(menu));
}

void BackgroundModeManager::RemoveStatusTrayIcon() {
  if (status_icon_)
    status_tray_->RemoveStatusIcon(status_icon_);
  status_icon_ = nullptr;
  context_menu_ = nullptr;
}

BackgroundModeManager::BackgroundModeData*
BackgroundModeManager::GetBackgroundModeData(const Profile* profile) const {
  // Profiles are shut down and destroyed asynchronously after
  // OnProfileWillBeRemoved is called, so we may have dropped anything
  // associated with the profile already.
  auto it = background_mode_data_.find(profile);
  return it != background_mode_data_.end() ? it->second.get() : nullptr;
}

BackgroundModeManager::BackgroundModeInfoMap::iterator
BackgroundModeManager::GetBackgroundModeIterator(
    const base::string16& profile_name) {
  BackgroundModeInfoMap::iterator profile_it =
      background_mode_data_.end();
  for (BackgroundModeInfoMap::iterator it =
       background_mode_data_.begin();
       it != background_mode_data_.end();
       ++it) {
    if (it->second->name() == profile_name) {
      profile_it = it;
    }
  }
  return profile_it;
}

bool BackgroundModeManager::IsBackgroundModePrefEnabled() const {
  PrefService* service = g_browser_process->local_state();
  DCHECK(service);
  return service->GetBoolean(prefs::kBackgroundModeEnabled);
}
