shortcut_manager.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/apps/shortcut_manager.h" 6 7#include "base/bind.h" 8#include "base/command_line.h" 9#include "base/compiler_specific.h" 10#include "base/prefs/pref_service.h" 11#include "base/strings/string16.h" 12#include "base/strings/utf_string_conversions.h" 13#include "chrome/browser/browser_process.h" 14#include "chrome/browser/extensions/extension_service.h" 15#include "chrome/browser/extensions/extension_ui_util.h" 16#include "chrome/browser/profiles/profile.h" 17#include "chrome/browser/profiles/profile_info_cache.h" 18#include "chrome/browser/profiles/profile_manager.h" 19#include "chrome/browser/shell_integration.h" 20#include "chrome/browser/web_applications/web_app.h" 21#include "chrome/common/chrome_switches.h" 22#include "chrome/common/pref_names.h" 23#include "components/pref_registry/pref_registry_syncable.h" 24#include "content/public/browser/browser_thread.h" 25#include "extensions/browser/extension_registry.h" 26#include "extensions/browser/extension_system.h" 27#include "extensions/common/extension_set.h" 28#include "extensions/common/one_shot_event.h" 29 30using extensions::Extension; 31 32namespace { 33 34// Creates a shortcut for an application in the applications menu, if there is 35// not already one present. 36void CreateShortcutsInApplicationsMenu(Profile* profile, 37 const Extension* app) { 38 web_app::ShortcutLocations creation_locations; 39 // Create the shortcut in the Chrome Apps subdir. 40 creation_locations.applications_menu_location = 41 web_app::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS; 42 web_app::CreateShortcuts( 43 web_app::SHORTCUT_CREATION_AUTOMATED, creation_locations, profile, app); 44} 45 46bool ShouldCreateShortcutFor(Profile* profile, const Extension* extension) { 47 return extension->is_platform_app() && 48 extension->location() != extensions::Manifest::COMPONENT && 49 extensions::ui_util::ShouldDisplayInAppLauncher(extension, profile); 50} 51 52} // namespace 53 54// static 55void AppShortcutManager::RegisterProfilePrefs( 56 user_prefs::PrefRegistrySyncable* registry) { 57 // Indicates whether app shortcuts have been created. 58 registry->RegisterBooleanPref( 59 prefs::kAppShortcutsHaveBeenCreated, false, 60 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 61} 62 63AppShortcutManager::AppShortcutManager(Profile* profile) 64 : profile_(profile), 65 is_profile_info_cache_observer_(false), 66 prefs_(profile->GetPrefs()), 67 extension_registry_observer_(this), 68 weak_ptr_factory_(this) { 69 // Use of g_browser_process requires that we are either on the UI thread, or 70 // there are no threads initialized (such as in unit tests). 71 DCHECK(!content::BrowserThread::IsThreadInitialized( 72 content::BrowserThread::UI) || 73 content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 74 75 extension_registry_observer_.Add( 76 extensions::ExtensionRegistry::Get(profile_)); 77 // Wait for extensions to be ready before running OnceOffCreateShortcuts. 78 extensions::ExtensionSystem::Get(profile)->ready().Post( 79 FROM_HERE, 80 base::Bind(&AppShortcutManager::OnceOffCreateShortcuts, 81 weak_ptr_factory_.GetWeakPtr())); 82 83 ProfileManager* profile_manager = g_browser_process->profile_manager(); 84 // profile_manager might be NULL in testing environments. 85 if (profile_manager) { 86 profile_manager->GetProfileInfoCache().AddObserver(this); 87 is_profile_info_cache_observer_ = true; 88 } 89} 90 91AppShortcutManager::~AppShortcutManager() { 92 if (g_browser_process && is_profile_info_cache_observer_) { 93 ProfileManager* profile_manager = g_browser_process->profile_manager(); 94 // profile_manager might be NULL in testing environments or during shutdown. 95 if (profile_manager) 96 profile_manager->GetProfileInfoCache().RemoveObserver(this); 97 } 98} 99 100void AppShortcutManager::OnExtensionWillBeInstalled( 101 content::BrowserContext* browser_context, 102 const Extension* extension, 103 bool is_update, 104 bool from_ephemeral, 105 const std::string& old_name) { 106 if (!extension->is_app()) 107 return; 108 109 // If the app is being updated, update any existing shortcuts but do not 110 // create new ones. If it is being installed, automatically create a 111 // shortcut in the applications menu (e.g., Start Menu). 112 if (is_update && !from_ephemeral) { 113 web_app::UpdateAllShortcuts( 114 base::UTF8ToUTF16(old_name), profile_, extension); 115 } else if (ShouldCreateShortcutFor(profile_, extension)) { 116 CreateShortcutsInApplicationsMenu(profile_, extension); 117 } 118} 119 120void AppShortcutManager::OnExtensionUninstalled( 121 content::BrowserContext* browser_context, 122 const Extension* extension) { 123 web_app::DeleteAllShortcuts(profile_, extension); 124} 125 126void AppShortcutManager::OnProfileWillBeRemoved( 127 const base::FilePath& profile_path) { 128 if (profile_path != profile_->GetPath()) 129 return; 130 content::BrowserThread::PostTask( 131 content::BrowserThread::FILE, FROM_HERE, 132 base::Bind(&web_app::internals::DeleteAllShortcutsForProfile, 133 profile_path)); 134} 135 136void AppShortcutManager::OnceOffCreateShortcuts() { 137 if (prefs_->GetBoolean(prefs::kAppShortcutsHaveBeenCreated)) 138 return; 139 140 prefs_->SetBoolean(prefs::kAppShortcutsHaveBeenCreated, true); 141 142 // Check if extension system/service are available. They might not be in 143 // tests. 144 extensions::ExtensionSystem* extension_system; 145 ExtensionServiceInterface* extension_service; 146 if (!(extension_system = extensions::ExtensionSystem::Get(profile_)) || 147 !(extension_service = extension_system->extension_service())) 148 return; 149 150 // Create an applications menu shortcut for each app in this profile. 151 const extensions::ExtensionSet* apps = extension_service->extensions(); 152 for (extensions::ExtensionSet::const_iterator it = apps->begin(); 153 it != apps->end(); ++it) { 154 if (ShouldCreateShortcutFor(profile_, it->get())) 155 CreateShortcutsInApplicationsMenu(profile_, it->get()); 156 } 157} 158