15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_paths.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/app/chrome_command_ids.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/background/background_application_list_model.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/background/background_mode_manager.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_shutdown.h" 217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/lifetime/application_lifetime.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile_info_cache.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/status_icons/status_icon.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/status_icons/status_tray.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_commands.h" 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/ui/browser_dialogs.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_finder.h" 331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/chrome_pages.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/extensions/application_launch.h" 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/host_desktop.h" 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/ui/user_manager.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/chromium_strings.h" 4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/generated_resources.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/user_metrics.h" 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/manifest_handlers/options_page_info.h" 491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "extensions/common/permissions/permission_set.h" 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "grit/chrome_unscaled_resources.h" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::UserMetricsAction; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::UpdatedExtensionPermissionsInfo; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace { 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int kInvalidExtensionIndex = -1; 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackgroundModeManager::BackgroundModeData::BackgroundModeData( 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Profile* profile, 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CommandIdExtensionVector* command_id_extension_vector) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : applications_(new BackgroundApplicationListModel(profile)), 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) profile_(profile), 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) command_id_extension_vector_(command_id_extension_vector) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackgroundModeManager::BackgroundModeData::~BackgroundModeData() { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 74424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// BackgroundModeManager::BackgroundModeData, StatusIconMenuModel overrides 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BackgroundModeManager::BackgroundModeData::ExecuteCommand( 76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int command_id, 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int event_flags) { 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) switch (command_id) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IDC_MinimumLabelValue: 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do nothing. This is just a label. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Launch the app associated with this Command ID. 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int extension_index = command_id_extension_vector_->at(command_id); 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (extension_index != kInvalidExtensionIndex) { 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const Extension* extension = 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) applications_->GetExtension(extension_index); 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BackgroundModeManager::LaunchBackgroundApplication(profile_, extension); 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Browser* BackgroundModeManager::BackgroundModeData::GetBrowserWindow() { 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome::HostDesktopType host_desktop_type = chrome::GetActiveDesktop(); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Browser* browser = chrome::FindLastActiveWithProfile(profile_, 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) host_desktop_type); 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return browser ? browser : chrome::OpenEmptyWindow(profile_, 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) host_desktop_type); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BackgroundModeManager::BackgroundModeData::GetBackgroundAppCount() const { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return applications_->size(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::BackgroundModeData::BuildProfileMenu( 107424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) StatusIconMenuModel* menu, 108424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) StatusIconMenuModel* containing_menu) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int position = 0; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When there are no background applications, we want to display 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // just a label stating that none are running. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (applications_->size() < 1) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu->AddItemWithStringId(IDC_MinimumLabelValue, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_BACKGROUND_APP_NOT_INSTALLED); 115424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) menu->SetCommandIdEnabled(IDC_MinimumLabelValue, false); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (extensions::ExtensionList::const_iterator cursor = 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) applications_->begin(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor != applications_->end(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++cursor, ++position) { 121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const gfx::ImageSkia* icon = applications_->GetIcon(cursor->get()); 122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(position == applications_->GetPosition(cursor->get())); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name = (*cursor)->name(); 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int command_id = command_id_extension_vector_->size(); 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Check that the command ID is within the dynamic range. 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(command_id < IDC_MinimumLabelValue); 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) command_id_extension_vector_->push_back(position); 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) menu->AddItem(command_id, base::UTF8ToUTF16(name)); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu->SetIcon(menu->GetItemCount() - 1, gfx::Image(*icon)); 1310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Component extensions with background that do not have an options page 1330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // will cause this menu item to go to the extensions page with an 1340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // absent component extension. 1350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // 1360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Ideally, we would remove this item, but this conflicts with the user 1370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // model where this menu shows the extensions with background. 1380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // 1390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // The compromise is to disable the item, avoiding the non-actionable 1400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // navigate to the extensions page and preserving the user model. 1410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if ((*cursor)->location() == extensions::Manifest::COMPONENT) { 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GURL options_page = 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::OptionsPageInfo::GetOptionsPage(cursor->get()); 1440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!options_page.is_valid()) 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) menu->SetCommandIdEnabled(command_id, false); 1460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (containing_menu) { 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int menu_command_id = command_id_extension_vector_->size(); 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Check that the command ID is within the dynamic range. 152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(menu_command_id < IDC_MinimumLabelValue); 153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) command_id_extension_vector_->push_back(kInvalidExtensionIndex); 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) containing_menu->AddSubMenu(menu_command_id, name_, menu); 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::BackgroundModeData::SetName( 159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& new_profile_name) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_ = new_profile_name; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 BackgroundModeManager::BackgroundModeData::name() { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return name_; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstd::set<const extensions::Extension*> 168116680a4aac90f2aa7413d9095a592090648e557Ben MurdochBackgroundModeManager::BackgroundModeData::GetNewBackgroundApps() { 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::set<const extensions::Extension*> new_apps; 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Copy all current extensions into our list of |current_extensions_|. 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (extensions::ExtensionList::const_iterator it = applications_->begin(); 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it != applications_->end(); ++it) { 174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const extensions::ExtensionId& id = (*it)->id(); 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (current_extensions_.count(id) == 0) { 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Not found in our set yet - add it and maybe return as a previously 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // unseen extension. 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch current_extensions_.insert(id); 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If this application has been newly loaded after the initial startup, 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // notify the user. 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (applications_->is_ready()) { 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const extensions::Extension* extension = (*it).get(); 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new_apps.insert(extension); 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return new_apps; 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BackgroundModeManager::BackgroundModeData::BackgroundModeDataCompare( 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BackgroundModeData* bmd1, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BackgroundModeData* bmd2) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bmd1->name_ < bmd2->name_; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BackgroundModeManager, public 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackgroundModeManager::BackgroundModeManager( 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine* command_line, 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileInfoCache* profile_cache) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : profile_cache_(profile_cache), 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_tray_(NULL), 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_icon_(NULL), 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_menu_(NULL), 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_background_mode_(false), 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keep_alive_for_startup_(false), 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keep_alive_for_test_(false), 2101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) background_mode_suspended_(false), 211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) keeping_alive_(false) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should never start up if there is no browser process or if we are 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // currently quitting. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(g_browser_process != NULL); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!browser_shutdown::IsTryingToQuit()); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add self as an observer for the profile info cache so we know when profiles 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are deleted and their names change. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_cache_->AddObserver(this); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Listen for the background mode preference changing. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (g_browser_process->local_state()) { // Skip for unit tests 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pref_registrar_.Init(g_browser_process->local_state()); 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pref_registrar_.Add( 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prefs::kBackgroundModeEnabled, 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&BackgroundModeManager::OnBackgroundModeEnabledPrefChanged, 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keep the browser alive until extensions are done loading - this is needed 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by the --no-startup-window flag. We want to stay alive until we load 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extensions, at which point we should either run in background mode (if 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // there are background apps) or exit if there are none. 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (command_line->HasSwitch(switches::kNoStartupWindow)) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keep_alive_for_startup_ = true; 236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chrome::IncrementKeepAliveCount(); 2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } else { 2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Otherwise, start with background mode suspended in case we're launching 2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // in a mode that doesn't open a browser window. It will be resumed when the 2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // first browser window is opened. 2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SuspendBackgroundMode(); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the -keep-alive-for-test flag is passed, then always keep chrome running 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the background until the user explicitly terminates it. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (command_line->HasSwitch(switches::kKeepAliveForTest)) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keep_alive_for_test_ = true; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShouldBeInBackgroundMode()) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartBackgroundMode(); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Listen for the application shutting down so we can decrement our KeepAlive 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // count. 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::AllSources()); 2561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) BrowserList::AddObserver(this); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackgroundModeManager::~BackgroundModeManager() { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove ourselves from the application observer list (only needed by unit 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tests since APP_TERMINATING is what does this in a real running system). 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BackgroundModeInfoMap::iterator it = 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_mode_data_.begin(); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != background_mode_data_.end(); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->second->applications_->RemoveObserver(this); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) BrowserList::RemoveObserver(this); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're going away, so exit background mode (does nothing if we aren't in 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // background mode currently). This is primarily needed for unit tests, 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because in an actual running system we'd get an APP_TERMINATING 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notification before being destroyed. 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EndBackgroundMode(); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BackgroundModeManager::RegisterPrefs(PrefRegistrySimple* registry) { 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_MACOSX) 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registry->RegisterBooleanPref(prefs::kUserRemovedLoginItem, false); 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registry->RegisterBooleanPref(prefs::kChromeCreatedLoginItem, false); 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registry->RegisterBooleanPref(prefs::kMigratedLoginItemPref, false); 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registry->RegisterBooleanPref(prefs::kBackgroundModeEnabled, true); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::RegisterProfile(Profile* profile) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't want to register multiple times for one profile. 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(background_mode_data_.find(profile) == background_mode_data_.end()); 291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BackgroundModeInfo bmd(new BackgroundModeData(profile, 292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &command_id_extension_vector_)); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_mode_data_[profile] = bmd; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initially set the name for this background mode data. 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index = profile_cache_->GetIndexOfProfileWithPath(profile->GetPath()); 297a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 name = l10n_util::GetStringUTF16(IDS_PROFILES_DEFAULT_NAME); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != std::string::npos) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = profile_cache_->GetNameOfProfileAtIndex(index); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bmd->SetName(name); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for the presence of background apps after all extensions have been 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // loaded, to handle the case where an extension has been manually removed 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // while Chrome was not running. 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) registrar_.Add(this, 3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile>(profile)); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bmd->applications_->AddObserver(this); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're adding a new profile and running in multi-profile mode, this new 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // profile should be added to the status icon if one currently exists. 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (in_background_mode_ && status_icon_) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateStatusTrayIconContextMenu(); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::LaunchBackgroundApplication( 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile, 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension) { 3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) OpenApplication(AppLaunchParams(profile, extension, NEW_FOREGROUND_TAB)); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool BackgroundModeManager::IsBackgroundModeActive() { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return in_background_mode_; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BackgroundModeManager::NumberOfBackgroundModeData() { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return background_mode_data_.size(); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BackgroundModeManager, content::NotificationObserver overrides 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::Observe( 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED: 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Extensions are loaded, so we don't need to manually keep the browser 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // process alive any more when running in no-startup-window mode. 342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DecrementKeepAliveCountForStartup(); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_APP_TERMINATING: 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we aren't still keeping the app alive (only happens if we 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // don't receive an EXTENSIONS_READY notification for some reason). 347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DecrementKeepAliveCountForStartup(); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Performing an explicit shutdown, so exit background mode (does nothing 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if we aren't in background mode currently). 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EndBackgroundMode(); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shutting down, so don't listen for any more notifications so we don't 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // try to re-enter/exit background mode again. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.RemoveAll(); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BackgroundModeInfoMap::iterator it = 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_mode_data_.begin(); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != background_mode_data_.end(); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->second->applications_->RemoveObserver(this); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::OnBackgroundModeEnabledPrefChanged() { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsBackgroundModePrefEnabled()) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnableBackgroundMode(); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisableBackgroundMode(); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BackgroundModeManager, BackgroundApplicationListModel::Observer overrides 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::OnApplicationDataChanged( 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension, Profile* profile) { 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateStatusTrayIconContextMenu(); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::OnApplicationListChanged(Profile* profile) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsBackgroundModePrefEnabled()) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the profile cache with the fact whether background apps are running 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for this profile. 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t profile_index = profile_cache_->GetIndexOfProfileWithPath( 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile->GetPath()); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_index != std::string::npos) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_cache_->SetBackgroundStatusOfProfileAtIndex( 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_index, GetBackgroundAppCountForProfile(profile) != 0); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ShouldBeInBackgroundMode()) { 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We've uninstalled our last background app, make sure we exit background 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mode and no longer launch on startup. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnableLaunchOnStartup(false); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EndBackgroundMode(); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have at least one background app running - make sure we're in 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // background mode. 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!in_background_mode_) { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're entering background mode - make sure we have launch-on-startup 404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // enabled. On Mac, the platform-specific code tracks whether the user 405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // has deleted a login item in the past, and if so, no login item will 406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // be created (to avoid overriding the specific user action). 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnableLaunchOnStartup(true); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartBackgroundMode(); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // List of applications changed so update the UI. 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateStatusTrayIconContextMenu(); 413116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 414116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Notify the user about any new applications. 415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BackgroundModeData* bmd = GetBackgroundModeData(profile); 416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::set<const extensions::Extension*> new_apps = 417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bmd->GetNewBackgroundApps(); 418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (std::set<const extensions::Extension*>::const_iterator it = 419116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new_apps.begin(); it != new_apps.end(); ++it) { 420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch OnBackgroundAppInstalled(*it); 421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BackgroundModeManager, ProfileInfoCacheObserver overrides 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BackgroundModeManager::OnProfileAdded(const base::FilePath& profile_path) { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileInfoCache& cache = 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_browser_process->profile_manager()->GetProfileInfoCache(); 430a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 profile_name = cache.GetNameOfProfileAtIndex( 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache.GetIndexOfProfileWithPath(profile_path)); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // At this point, the profile should be registered with the background mode 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // manager, but when it's actually added to the cache is when its name is 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set so we need up to update that with the background_mode_data. 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BackgroundModeInfoMap::const_iterator it = 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_mode_data_.begin(); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != background_mode_data_.end(); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it->first->GetPath() == profile_path) { 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->second->SetName(profile_name); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateStatusTrayIconContextMenu(); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::OnProfileWillBeRemoved( 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& profile_path) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileInfoCache& cache = 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_browser_process->profile_manager()->GetProfileInfoCache(); 451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 profile_name = cache.GetNameOfProfileAtIndex( 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache.GetIndexOfProfileWithPath(profile_path)); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the profile from our map of profiles. 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundModeInfoMap::iterator it = 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBackgroundModeIterator(profile_name); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a profile isn't running a background app, it may not be in the map. 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != background_mode_data_.end()) { 458a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) it->second->applications_->RemoveObserver(this); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_mode_data_.erase(it); 460a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If there are no background mode profiles any longer, then turn off 461a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // background mode. 462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!ShouldBeInBackgroundMode()) { 463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EnableLaunchOnStartup(false); 464a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EndBackgroundMode(); 465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateStatusTrayIconContextMenu(); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::OnProfileNameChanged( 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& profile_path, 472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& old_profile_name) { 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileInfoCache& cache = 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_browser_process->profile_manager()->GetProfileInfoCache(); 475a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 new_profile_name = cache.GetNameOfProfileAtIndex( 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache.GetIndexOfProfileWithPath(profile_path)); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundModeInfoMap::const_iterator it = 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBackgroundModeIterator(old_profile_name); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We check that the returned iterator is valid due to unittests, but really 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this should only be called on profiles already known by the background 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mode manager. 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != background_mode_data_.end()) { 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->second->SetName(new_profile_name); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateStatusTrayIconContextMenu(); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBackgroundModeManager::BackgroundModeData* 4891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBackgroundModeManager::GetBackgroundModeDataForLastProfile() const { 4901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Profile* most_recent_profile = g_browser_process->profile_manager()-> 4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetLastUsedProfileAllowedByPolicy(); 4921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BackgroundModeInfoMap::const_iterator profile_background_data = 4931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci background_mode_data_.find(most_recent_profile); 4941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (profile_background_data == background_mode_data_.end()) 4961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return NULL; 4971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Do not permit a locked profile to be used to open a browser. 4991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ProfileInfoCache& cache = 5001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_browser_process->profile_manager()->GetProfileInfoCache(); 5011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (cache.ProfileIsSigninRequiredAtIndex(cache.GetIndexOfProfileWithPath( 5021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci profile_background_data->first->GetPath()))) 5031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return NULL; 5041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return profile_background_data->second.get(); 5061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 509424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// BackgroundModeManager::BackgroundModeData, StatusIconMenuModel overrides 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BackgroundModeManager::ExecuteCommand(int command_id, int event_flags) { 5111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BackgroundModeData* bmd = GetBackgroundModeDataForLastProfile(); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (command_id) { 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IDC_ABOUT: 5141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (bmd) { 5151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome::ShowAboutChrome(bmd->GetBrowserWindow()); 5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 5171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UserManager::Show(base::FilePath(), 5181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci profiles::USER_MANAGER_NO_TUTORIAL, 5191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci profiles::USER_MANAGER_SELECT_PROFILE_ABOUT_CHROME); 5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IDC_TASK_MANAGER: 5231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (bmd) { 5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome::OpenTaskManager(bmd->GetBrowserWindow()); 5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UserManager::Show(base::FilePath(), 5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci profiles::USER_MANAGER_NO_TUTORIAL, 5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci profiles::USER_MANAGER_SELECT_PROFILE_TASK_MANAGER); 5291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IDC_EXIT: 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RecordAction(UserMetricsAction("Exit")); 5331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) chrome::CloseAllBrowsers(); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND: { 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Background mode must already be enabled (as otherwise this menu would 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not be visible). 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsBackgroundModePrefEnabled()); 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(chrome::WillKeepAlive()); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the background mode pref to "disabled" - the resulting notification 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will result in a call to DisableBackgroundMode(). 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* service = g_browser_process->local_state(); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(service); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service->SetBoolean(prefs::kBackgroundModeEnabled, false); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 5491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (bmd) { 5501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bmd->ExecuteCommand(command_id, event_flags); 5511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 5521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UserManager::Show(base::FilePath(), 5531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci profiles::USER_MANAGER_NO_TUTORIAL, 5541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION); 5551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BackgroundModeManager, private 563a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BackgroundModeManager::DecrementKeepAliveCountForStartup() { 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (keep_alive_for_startup_) { 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keep_alive_for_startup_ = false; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We call this via the message queue to make sure we don't try to end 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // keep-alive (which can shutdown Chrome) before the message loop has 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // started. 569a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::MessageLoop::current()->PostTask( 570a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, base::Bind(&chrome::DecrementKeepAliveCount)); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::StartBackgroundMode() { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ShouldBeInBackgroundMode()); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't bother putting ourselves in background mode if we're already there 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or if background mode is disabled. 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (in_background_mode_) 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark ourselves as running in background mode. 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_background_mode_ = true; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) UpdateKeepAliveAndTrayIcon(); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::current()->Notify( 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED, 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<BackgroundModeManager>(this), 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Details<bool>(&in_background_mode_)); 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::EndBackgroundMode() { 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!in_background_mode_) 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_background_mode_ = false; 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) UpdateKeepAliveAndTrayIcon(); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::current()->Notify( 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED, 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<BackgroundModeManager>(this), 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Details<bool>(&in_background_mode_)); 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::EnableBackgroundMode() { 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsBackgroundModePrefEnabled()); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If background mode should be enabled, but isn't, turn it on. 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!in_background_mode_ && ShouldBeInBackgroundMode()) { 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartBackgroundMode(); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnableLaunchOnStartup(true); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::DisableBackgroundMode() { 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!IsBackgroundModePrefEnabled()); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If background mode is currently enabled, turn it off. 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (in_background_mode_) { 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EndBackgroundMode(); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnableLaunchOnStartup(false); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void BackgroundModeManager::SuspendBackgroundMode() { 6241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) background_mode_suspended_ = true; 6251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) UpdateKeepAliveAndTrayIcon(); 6261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 6271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 6281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void BackgroundModeManager::ResumeBackgroundMode() { 6291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) background_mode_suspended_ = false; 6301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) UpdateKeepAliveAndTrayIcon(); 6311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 6321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 6331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void BackgroundModeManager::UpdateKeepAliveAndTrayIcon() { 6341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (in_background_mode_ && !background_mode_suspended_) { 6351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!keeping_alive_) { 6361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) keeping_alive_ = true; 637a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chrome::IncrementKeepAliveCount(); 6381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 6391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateStatusTrayIcon(); 6401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return; 6411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 6421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 6431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) RemoveStatusTrayIcon(); 6441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (keeping_alive_) { 6451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) keeping_alive_ = false; 646a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chrome::DecrementKeepAliveCount(); 6471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 6481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 6491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 6501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void BackgroundModeManager::OnBrowserAdded(Browser* browser) { 6511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ResumeBackgroundMode(); 6521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 6531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BackgroundModeManager::GetBackgroundAppCount() const { 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Walk the BackgroundModeData for all profiles and count the number of apps. 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BackgroundModeInfoMap::const_iterator it = 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_mode_data_.begin(); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != background_mode_data_.end(); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count += it->second->GetBackgroundAppCount(); 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(count >= 0); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return count; 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BackgroundModeManager::GetBackgroundAppCountForProfile( 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* const profile) const { 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundModeData* bmd = GetBackgroundModeData(profile); 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bmd->GetBackgroundAppCount(); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BackgroundModeManager::ShouldBeInBackgroundMode() const { 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return IsBackgroundModePrefEnabled() && 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (GetBackgroundAppCount() > 0 || keep_alive_for_test_); 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::OnBackgroundAppInstalled( 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension) { 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Background mode is disabled - don't do anything. 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsBackgroundModePrefEnabled()) 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Ensure we have a tray icon (needed so we can display the app-installed 6851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // notification below). 6861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EnableBackgroundMode(); 6871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ResumeBackgroundMode(); 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify the user that a background app has been installed. 690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (extension) { // NULL when called by unit tests. 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisplayAppInstalledNotification(extension); 692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 694eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::CreateStatusTrayIcon() { 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only need status icons on windows/linux. ChromeOS doesn't allow exiting 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chrome and Mac can use the dock icon instead. 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since there are multiple profiles which share the status tray, we now 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // use the browser process to keep track of it. 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!status_tray_) 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_tray_ = g_browser_process->status_tray(); 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the platform doesn't support status icons, or we've already created 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // our status icon, just return. 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!status_tray_ || status_icon_) 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rlp): Status tray icon should have submenus for each profile. 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia* image_skia = ui::ResourceBundle::GetSharedInstance(). 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetImageSkiaNamed(IDR_STATUS_TRAY_ICON); 714a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 715a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) status_icon_ = status_tray_->CreateStatusIcon( 716a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) StatusTray::BACKGROUND_MODE_ICON, 717a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *image_skia, 718a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); 719a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!status_icon_) 720a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateStatusTrayIconContextMenu(); 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::UpdateStatusTrayIconContextMenu() { 7251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Ensure we have a tray icon if appropriate. 7261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) UpdateKeepAliveAndTrayIcon(); 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't have a status icon or one could not be created succesfully, 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then no need to continue the update. 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!status_icon_) 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should only get here if we have a profile loaded, or if we're running 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in test mode. 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (background_mode_data_.empty()) { 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(keep_alive_for_test_); 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 740f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // We are building a new menu. Reset the Command IDs. 741f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) command_id_extension_vector_.clear(); 742f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 743f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Clear the submenus too since we will be creating new ones. 744f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) submenus.clear(); 745f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rlp): Add current profile color or indicator. 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a context menu item for Chrome. 748424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) scoped_ptr<StatusIconMenuModel> menu(new StatusIconMenuModel(this)); 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add About item 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu->AddItem(IDC_ABOUT, l10n_util::GetStringUTF16(IDS_ABOUT)); 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu->AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER); 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu->AddSeparator(ui::NORMAL_SEPARATOR); 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_cache_->GetNumberOfProfiles() > 1) { 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<BackgroundModeData*> bmd_vector; 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BackgroundModeInfoMap::iterator it = 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_mode_data_.begin(); 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != background_mode_data_.end(); 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bmd_vector.push_back(it->second.get()); 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::sort(bmd_vector.begin(), bmd_vector.end(), 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &BackgroundModeData::BackgroundModeDataCompare); 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int profiles_with_apps = 0; 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<BackgroundModeData*>::const_iterator bmd_it = 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bmd_vector.begin(); 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bmd_it != bmd_vector.end(); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++bmd_it) { 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundModeData* bmd = *bmd_it; 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should only display the profile in the status icon if it has at 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // least one background app. 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bmd->GetBackgroundAppCount() > 0) { 773424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) StatusIconMenuModel* submenu = new StatusIconMenuModel(bmd); 774f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // The submenu constructor caller owns the lifetime of the submenu. 775f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // The containing menu does not handle the lifetime. 776f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) submenus.push_back(submenu); 777424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bmd->BuildProfileMenu(submenu, menu.get()); 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profiles_with_apps++; 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should only be displaying the status tray icon if there is at least 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one profile with a background app. 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(profiles_with_apps, 0); 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should only have one profile in the cache if we are not 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // using multi-profiles. If keep_alive_for_test_ is set, then we may not 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have any profiles in the cache. 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(profile_cache_->GetNumberOfProfiles() == size_t(1) || 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keep_alive_for_test_); 790424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) background_mode_data_.begin()->second->BuildProfileMenu(menu.get(), NULL); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) menu->AddSeparator(ui::NORMAL_SEPARATOR); 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu->AddCheckItemWithStringId( 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND, 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND); 797424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) menu->SetCommandIdChecked(IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND, 798424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) true); 799424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 800424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) PrefService* service = g_browser_process->local_state(); 801424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(service); 802424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool enabled = 803424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) service->IsUserModifiablePreference(prefs::kBackgroundModeEnabled); 804424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) menu->SetCommandIdEnabled(IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND, 805424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) enabled); 806424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu->AddItemWithStringId(IDC_EXIT, IDS_EXIT); 8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 809424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) context_menu_ = menu.get(); 810424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) status_icon_->SetContextMenu(menu.Pass()); 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundModeManager::RemoveStatusTrayIcon() { 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status_icon_) 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_tray_->RemoveStatusIcon(status_icon_); 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_icon_ = NULL; 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_menu_ = NULL; 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackgroundModeManager::BackgroundModeData* 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackgroundModeManager::GetBackgroundModeData(Profile* const profile) const { 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(background_mode_data_.find(profile) != background_mode_data_.end()); 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return background_mode_data_.find(profile)->second.get(); 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackgroundModeManager::BackgroundModeInfoMap::iterator 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackgroundModeManager::GetBackgroundModeIterator( 828a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& profile_name) { 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundModeInfoMap::iterator profile_it = 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_mode_data_.end(); 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BackgroundModeInfoMap::iterator it = 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_mode_data_.begin(); 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != background_mode_data_.end(); 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it->second->name() == profile_name) { 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_it = it; 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return profile_it; 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BackgroundModeManager::IsBackgroundModePrefEnabled() const { 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* service = g_browser_process->local_state(); 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(service); 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return service->GetBoolean(prefs::kBackgroundModeEnabled); 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 847