// 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 <algorithm>
#include <string>
#include <vector>

#include "base/base_paths.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/background/background_application_list_model.h"
#include "chrome/browser/background/background_mode_manager.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.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_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/user_metrics.h"
#include "extensions/common/permissions/permission_set.h"
#include "grit/chrome_unscaled_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"

using content::UserMetricsAction;
using extensions::Extension;
using extensions::UpdatedExtensionPermissionsInfo;

BackgroundModeManager::BackgroundModeData::BackgroundModeData(
    int command_id,
    Profile* profile)
    : applications_(new BackgroundApplicationListModel(profile)),
      command_id_(command_id),
      profile_(profile) {
}

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

///////////////////////////////////////////////////////////////////////////////
//  BackgroundModeManager::BackgroundModeData, StatusIconMenuModel overrides
void BackgroundModeManager::BackgroundModeData::ExecuteCommand(
    int item,
    int event_flags) {
  switch (item) {
    case IDC_MinimumLabelValue:
      // Do nothing. This is just a label.
      break;
    default:
      // Launch the app associated with this item.
      const Extension* extension = applications_->
          GetExtension(item);
      BackgroundModeManager::LaunchBackgroundApplication(profile_, extension);
      break;
  }
}

Browser* BackgroundModeManager::BackgroundModeData::GetBrowserWindow() {
  chrome::HostDesktopType host_desktop_type = chrome::GetActiveDesktop();
  Browser* browser = chrome::FindLastActiveWithProfile(profile_,
                                                       host_desktop_type);
  return browser ? browser : chrome::OpenEmptyWindow(profile_,
                                                     host_desktop_type);
}

int BackgroundModeManager::BackgroundModeData::GetBackgroundAppCount() const {
  return applications_->size();
}

void BackgroundModeManager::BackgroundModeData::BuildProfileMenu(
    StatusIconMenuModel* menu,
    StatusIconMenuModel* containing_menu) {
  int position = 0;
  // When there are no background applications, we want to display
  // just a label stating that none are running.
  if (applications_->size() < 1) {
    menu->AddItemWithStringId(IDC_MinimumLabelValue,
                              IDS_BACKGROUND_APP_NOT_INSTALLED);
    menu->SetCommandIdEnabled(IDC_MinimumLabelValue, false);
  } else {
    for (extensions::ExtensionList::const_iterator cursor =
             applications_->begin();
         cursor != applications_->end();
         ++cursor, ++position) {
      const gfx::ImageSkia* icon = applications_->GetIcon(cursor->get());
      DCHECK(position == applications_->GetPosition(cursor->get()));
      const std::string& name = (*cursor)->name();
      menu->AddItem(position, UTF8ToUTF16(name));
      if (icon)
        menu->SetIcon(menu->GetItemCount() - 1, gfx::Image(*icon));
    }
  }
  if (containing_menu)
    containing_menu->AddSubMenu(command_id_, name_, menu);
}

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

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

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


///////////////////////////////////////////////////////////////////////////////
//  BackgroundModeManager, public
BackgroundModeManager::BackgroundModeManager(
    CommandLine* command_line,
    ProfileInfoCache* profile_cache)
    : profile_cache_(profile_cache),
      status_tray_(NULL),
      status_icon_(NULL),
      context_menu_(NULL),
      in_background_mode_(false),
      keep_alive_for_startup_(false),
      keep_alive_for_test_(false),
      background_mode_suspended_(false),
      keeping_alive_(false),
      current_command_id_(0) {
  // We should never start up if there is no browser process or if we are
  // currently quitting.
  CHECK(g_browser_process != NULL);
  CHECK(!browser_shutdown::IsTryingToQuit());

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

  // 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::Bind(&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_ = true;
    chrome::StartKeepAlive();
  } 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();
  }

  // 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 decrement our KeepAlive
  // count.
  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 (BackgroundModeInfoMap::iterator it =
       background_mode_data_.begin();
       it != background_mode_data_.end();
       ++it) {
    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(background_mode_data_.find(profile) == background_mode_data_.end());
  BackgroundModeInfo bmd(new BackgroundModeData(current_command_id_++,
                                                profile));
  background_mode_data_[profile] = bmd;

  // Initially set the name for this background mode data.
  size_t index = profile_cache_->GetIndexOfProfileWithPath(profile->GetPath());
  string16 name = l10n_util::GetStringUTF16(IDS_PROFILES_DEFAULT_NAME);
  if (index != std::string::npos)
    name = profile_cache_->GetNameOfProfileAtIndex(index);
  bmd->SetName(name);

  // Listen for when extensions are loaded or add the background permission so
  // we can display a "background app installed" notification and enter
  // "launch on login" mode on the Mac.
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
                 content::Source<Profile>(profile));
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
                 content::Source<Profile>(profile));


  // 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.
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY,
                 content::Source<Profile>(profile));

  bmd->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(AppLaunchParams(profile, extension, NEW_FOREGROUND_TAB));
}

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

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

///////////////////////////////////////////////////////////////////////////////
//  BackgroundModeManager, content::NotificationObserver overrides
void BackgroundModeManager::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  switch (type) {
    case chrome::NOTIFICATION_EXTENSIONS_READY:
      // Extensions are loaded, so we don't need to manually keep the browser
      // process alive any more when running in no-startup-window mode.
      EndKeepAliveForStartup();
      break;

    case chrome::NOTIFICATION_EXTENSION_LOADED: {
        Extension* extension = content::Details<Extension>(details).ptr();
        Profile* profile = content::Source<Profile>(source).ptr();
        if (BackgroundApplicationListModel::IsBackgroundApp(
                *extension, profile)) {
          // Extensions loaded after the ExtensionsService is ready should be
          // treated as new installs.
          if (extensions::ExtensionSystem::Get(profile)->extension_service()->
                  is_ready()) {
            bool is_being_reloaded = false;
            CheckReloadStatus(extension, &is_being_reloaded);
            // No need to show the notification if we showed to the user
            // previously for this app.
            if (!is_being_reloaded)
              OnBackgroundAppInstalled(extension);
          }
        }
      }
      break;
    case chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED: {
        UpdatedExtensionPermissionsInfo* info =
            content::Details<UpdatedExtensionPermissionsInfo>(details).ptr();
        if (info->permissions->HasAPIPermission(
                extensions::APIPermission::kBackground) &&
            info->reason == UpdatedExtensionPermissionsInfo::ADDED) {
          // Turned on background permission, so treat this as a new install.
          OnBackgroundAppInstalled(info->extension);
        }
      }
      break;
    case chrome::NOTIFICATION_APP_TERMINATING:
      // Make sure we aren't still keeping the app alive (only happens if we
      // don't receive an EXTENSIONS_READY notification for some reason).
      EndKeepAliveForStartup();
      // 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 (BackgroundModeInfoMap::iterator it =
               background_mode_data_.begin();
           it != background_mode_data_.end();
           ++it) {
        it->second->applications_->RemoveObserver(this);
      }
      break;
    default:
      NOTREACHED();
      break;
  }
}

void BackgroundModeManager::OnBackgroundModeEnabledPrefChanged() {
  if (IsBackgroundModePrefEnabled())
    EnableBackgroundMode();
  else
    DisableBackgroundMode();
}

///////////////////////////////////////////////////////////////////////////////
//  BackgroundModeManager, BackgroundApplicationListModel::Observer overrides
void BackgroundModeManager::OnApplicationDataChanged(
    const Extension* extension, Profile* profile) {
  UpdateStatusTrayIconContextMenu();
}

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

  // Update the profile cache with the fact whether background apps are running
  // for this profile.
  size_t profile_index = profile_cache_->GetIndexOfProfileWithPath(
      profile->GetPath());
  if (profile_index != std::string::npos) {
    profile_cache_->SetBackgroundStatusOfProfileAtIndex(
        profile_index, GetBackgroundAppCountForProfile(profile) != 0);
  }

  if (!ShouldBeInBackgroundMode()) {
    // We've uninstalled our last background app, make sure we exit background
    // mode and no longer launch on startup.
    EnableLaunchOnStartup(false);
    EndBackgroundMode();
  } else {
    // We have at least one background app running - 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 applications changed so update the UI.
    UpdateStatusTrayIconContextMenu();
  }
}

///////////////////////////////////////////////////////////////////////////////
//  BackgroundModeManager, ProfileInfoCacheObserver overrides
void BackgroundModeManager::OnProfileAdded(const base::FilePath& profile_path) {
  ProfileInfoCache& cache =
      g_browser_process->profile_manager()->GetProfileInfoCache();
  string16 profile_name = cache.GetNameOfProfileAtIndex(
      cache.GetIndexOfProfileWithPath(profile_path));
  // At this point, the profile should be registered with the background mode
  // manager, but when it's actually added to the cache is when its name is
  // set so we need up to update that with the background_mode_data.
  for (BackgroundModeInfoMap::const_iterator it =
       background_mode_data_.begin();
       it != background_mode_data_.end();
       ++it) {
    if (it->first->GetPath() == profile_path) {
      it->second->SetName(profile_name);
      UpdateStatusTrayIconContextMenu();
      return;
    }
  }
}

void BackgroundModeManager::OnProfileWillBeRemoved(
    const base::FilePath& profile_path) {
  ProfileInfoCache& cache =
      g_browser_process->profile_manager()->GetProfileInfoCache();
  string16 profile_name = cache.GetNameOfProfileAtIndex(
      cache.GetIndexOfProfileWithPath(profile_path));
  // 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()) {
    background_mode_data_.erase(it);
    UpdateStatusTrayIconContextMenu();
  }
}

void BackgroundModeManager::OnProfileNameChanged(
    const base::FilePath& profile_path,
    const string16& old_profile_name) {
  ProfileInfoCache& cache =
      g_browser_process->profile_manager()->GetProfileInfoCache();
  string16 new_profile_name = cache.GetNameOfProfileAtIndex(
      cache.GetIndexOfProfileWithPath(profile_path));
  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, StatusIconMenuModel overrides
void BackgroundModeManager::ExecuteCommand(int command_id, int event_flags) {
  // When a browser window is necessary, we use the first profile. The windows
  // opened for these commands are not profile-specific, so any profile would
  // work and the first is convenient.
  BackgroundModeData* bmd = background_mode_data_.begin()->second.get();
  switch (command_id) {
    case IDC_ABOUT:
      chrome::ShowAboutChrome(bmd->GetBrowserWindow());
      break;
    case IDC_TASK_MANAGER:
      chrome::OpenTaskManager(bmd->GetBrowserWindow());
      break;
    case IDC_EXIT:
      content::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(chrome::WillKeepAlive());

      // 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:
      bmd->ExecuteCommand(command_id, event_flags);
      break;
  }
}


///////////////////////////////////////////////////////////////////////////////
//  BackgroundModeManager, private
void BackgroundModeManager::EndKeepAliveForStartup() {
  if (keep_alive_for_startup_) {
    keep_alive_for_startup_ = false;
    // 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.
    base::MessageLoop::current()->PostTask(FROM_HERE,
                                           base::Bind(&chrome::EndKeepAlive));
  }
}

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;

  // 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();
    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 (!keeping_alive_) {
      keeping_alive_ = true;
      chrome::StartKeepAlive();
    }
    CreateStatusTrayIcon();
    return;
  }

  RemoveStatusTrayIcon();
  if (keeping_alive_) {
    keeping_alive_ = false;
    chrome::EndKeepAlive();
  }
}

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

int BackgroundModeManager::GetBackgroundAppCount() const {
  int count = 0;
  // Walk the BackgroundModeData for all profiles and count the number of apps.
  for (BackgroundModeInfoMap::const_iterator it =
       background_mode_data_.begin();
       it != background_mode_data_.end();
       ++it) {
    count += it->second->GetBackgroundAppCount();
  }
  DCHECK(count >= 0);
  return count;
}

int BackgroundModeManager::GetBackgroundAppCountForProfile(
    Profile* const profile) const {
  BackgroundModeData* bmd = GetBackgroundModeData(profile);
  return bmd->GetBackgroundAppCount();
}

bool BackgroundModeManager::ShouldBeInBackgroundMode() const {
  return IsBackgroundModePrefEnabled() &&
      (GetBackgroundAppCount() > 0 || keep_alive_for_test_);
}

void BackgroundModeManager::OnBackgroundAppInstalled(
    const Extension* extension) {
  // 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 app has been installed.
  if (extension) {  // NULL when called by unit tests.
    DisplayAppInstalledNotification(extension);
  }
}

void BackgroundModeManager::CheckReloadStatus(
    const Extension* extension,
    bool* is_being_reloaded) {
    // Walk the BackgroundModeData for all profiles to see if one of their
    // extensions is being reloaded.
    for (BackgroundModeInfoMap::const_iterator it =
             background_mode_data_.begin();
         it != background_mode_data_.end();
         ++it) {
      Profile* profile = it->first;
      // If the extension is being reloaded, no need to show a notification.
      if (profile->GetExtensionService()->IsBeingReloaded(extension->id()))
        *is_being_reloaded = true;
    }
}

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;

  // TODO(rlp): Status tray icon should have submenus for each profile.
  gfx::ImageSkia* image_skia = ui::ResourceBundle::GetSharedInstance().
      GetImageSkiaNamed(IDR_STATUS_TRAY_ICON);

  status_icon_ = status_tray_->CreateStatusIcon(
      StatusTray::BACKGROUND_MODE_ICON,
      *image_skia,
      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;
  }

  // TODO(rlp): Add current profile color or indicator.
  // Create a context menu item for Chrome.
  scoped_ptr<StatusIconMenuModel> menu(new StatusIconMenuModel(this));
  // Add About item
  menu->AddItem(IDC_ABOUT, l10n_util::GetStringUTF16(IDS_ABOUT));
  menu->AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER);
  menu->AddSeparator(ui::NORMAL_SEPARATOR);

  if (profile_cache_->GetNumberOfProfiles() > 1) {
    std::vector<BackgroundModeData*> bmd_vector;
    for (BackgroundModeInfoMap::iterator it =
         background_mode_data_.begin();
         it != background_mode_data_.end();
         ++it) {
       bmd_vector.push_back(it->second.get());
    }
    std::sort(bmd_vector.begin(), bmd_vector.end(),
              &BackgroundModeData::BackgroundModeDataCompare);
    int profiles_with_apps = 0;
    for (std::vector<BackgroundModeData*>::const_iterator bmd_it =
         bmd_vector.begin();
         bmd_it != bmd_vector.end();
         ++bmd_it) {
      BackgroundModeData* bmd = *bmd_it;
      // We should only display the profile in the status icon if it has at
      // least one background app.
      if (bmd->GetBackgroundAppCount() > 0) {
        StatusIconMenuModel* submenu = new StatusIconMenuModel(bmd);
        bmd->BuildProfileMenu(submenu, menu.get());
        profiles_with_apps++;
      }
    }
    // We should only be displaying the status tray icon if there is at least
    // one profile with a background app.
    DCHECK_GT(profiles_with_apps, 0);
  } else {
    // We should only have one profile in the cache if we are not
    // using multi-profiles. If keep_alive_for_test_ is set, then we may not
    // have any profiles in the cache.
    DCHECK(profile_cache_->GetNumberOfProfiles() == size_t(1) ||
           keep_alive_for_test_);
    background_mode_data_.begin()->second->BuildProfileMenu(menu.get(), NULL);
  }

  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(menu.Pass());
}

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

BackgroundModeManager::BackgroundModeData*
BackgroundModeManager::GetBackgroundModeData(Profile* const profile) const {
  DCHECK(background_mode_data_.find(profile) != background_mode_data_.end());
  return background_mode_data_.find(profile)->second.get();
}

BackgroundModeManager::BackgroundModeInfoMap::iterator
BackgroundModeManager::GetBackgroundModeIterator(
    const 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);
}
