extension_util.cc revision 116680a4aac90f2aa7413d9095a592090648e557
1ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 2ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// found in the LICENSE file. 4ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 5ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/extensions/extension_util.h" 6ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 7ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/command_line.h" 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/logging.h" 9ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/values.h" 10ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/extensions/extension_service.h" 11ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/extensions/extension_sync_service.h" 12ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/extensions/permissions_updater.h" 13ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/profiles/profile.h" 14ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 16#include "chrome/common/extensions/manifest_handlers/app_isolation_info.h" 17#include "chrome/common/extensions/sync_helper.h" 18#include "content/public/browser/site_instance.h" 19#include "extensions/browser/extension_prefs.h" 20#include "extensions/browser/extension_registry.h" 21#include "extensions/browser/extension_system.h" 22#include "extensions/browser/extension_util.h" 23#include "extensions/common/extension.h" 24#include "extensions/common/extension_icon_set.h" 25#include "extensions/common/features/simple_feature.h" 26#include "extensions/common/manifest.h" 27#include "extensions/common/manifest_handlers/incognito_info.h" 28#include "grit/theme_resources.h" 29#include "ui/base/resource/resource_bundle.h" 30 31namespace extensions { 32namespace util { 33 34namespace { 35// The entry into the ExtensionPrefs for allowing an extension to script on 36// all urls without explicit permission. 37const char kExtensionAllowedOnAllUrlsPrefName[] = 38 "extension_can_script_all_urls"; 39 40// Returns true if |extension_id| for an external component extension should 41// always be enabled in incognito windows. 42bool IsWhitelistedForIncognito(const std::string& extension_id) { 43 static const char* kExtensionWhitelist[] = { 44 "D5736E4B5CF695CB93A2FB57E4FDC6E5AFAB6FE2", // http://crbug.com/312900 45 "D57DE394F36DC1C3220E7604C575D29C51A6C495", // http://crbug.com/319444 46 "3F65507A3B39259B38C8173C6FFA3D12DF64CCE9" // http://crbug.com/371562 47 }; 48 49 return extensions::SimpleFeature::IsIdInList( 50 extension_id, 51 std::set<std::string>( 52 kExtensionWhitelist, 53 kExtensionWhitelist + arraysize(kExtensionWhitelist))); 54} 55} // namespace 56 57bool IsIncognitoEnabled(const std::string& extension_id, 58 content::BrowserContext* context) { 59 const Extension* extension = ExtensionRegistry::Get(context)-> 60 GetExtensionById(extension_id, ExtensionRegistry::ENABLED); 61 if (extension) { 62 if (!extension->can_be_incognito_enabled()) 63 return false; 64 // If this is an existing component extension we always allow it to 65 // work in incognito mode. 66 if (extension->location() == Manifest::COMPONENT) 67 return true; 68 if (extension->location() == Manifest::EXTERNAL_COMPONENT && 69 IsWhitelistedForIncognito(extension_id)) { 70 return true; 71 } 72 } 73 74 return ExtensionPrefs::Get(context)->IsIncognitoEnabled(extension_id); 75} 76 77void SetIsIncognitoEnabled(const std::string& extension_id, 78 content::BrowserContext* context, 79 bool enabled) { 80 ExtensionService* service = 81 ExtensionSystem::Get(context)->extension_service(); 82 CHECK(service); 83 const Extension* extension = service->GetInstalledExtension(extension_id); 84 85 if (extension) { 86 if (!extension->can_be_incognito_enabled()) 87 return; 88 89 if (extension->location() == Manifest::COMPONENT) { 90 // This shouldn't be called for component extensions unless it is called 91 // by sync, for syncable component extensions. 92 // See http://crbug.com/112290 and associated CLs for the sordid history. 93 DCHECK(sync_helper::IsSyncable(extension)); 94 95 // If we are here, make sure the we aren't trying to change the value. 96 DCHECK_EQ(enabled, IsIncognitoEnabled(extension_id, service->profile())); 97 return; 98 } 99 } 100 101 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(service->profile()); 102 // Broadcast unloaded and loaded events to update browser state. Only bother 103 // if the value changed and the extension is actually enabled, since there is 104 // no UI otherwise. 105 bool old_enabled = extension_prefs->IsIncognitoEnabled(extension_id); 106 if (enabled == old_enabled) 107 return; 108 109 extension_prefs->SetIsIncognitoEnabled(extension_id, enabled); 110 111 bool extension_is_enabled = service->extensions()->Contains(extension_id); 112 113 // When we reload the extension the ID may be invalidated if we've passed it 114 // by const ref everywhere. Make a copy to be safe. 115 std::string id = extension_id; 116 if (extension_is_enabled) 117 service->ReloadExtension(id); 118 119 // Reloading the extension invalidates the |extension| pointer. 120 extension = service->GetInstalledExtension(id); 121 if (extension) { 122 ExtensionSyncService::Get(service->profile())-> 123 SyncExtensionChangeIfNeeded(*extension); 124 } 125} 126 127bool CanCrossIncognito(const Extension* extension, 128 content::BrowserContext* context) { 129 // We allow the extension to see events and data from another profile iff it 130 // uses "spanning" behavior and it has incognito access. "split" mode 131 // extensions only see events for a matching profile. 132 CHECK(extension); 133 return IsIncognitoEnabled(extension->id(), context) && 134 !IncognitoInfo::IsSplitMode(extension); 135} 136 137bool CanLoadInIncognito(const Extension* extension, 138 content::BrowserContext* context) { 139 CHECK(extension); 140 if (extension->is_hosted_app()) 141 return true; 142 // Packaged apps and regular extensions need to be enabled specifically for 143 // incognito (and split mode should be set). 144 return IncognitoInfo::IsSplitMode(extension) && 145 IsIncognitoEnabled(extension->id(), context); 146} 147 148bool AllowFileAccess(const std::string& extension_id, 149 content::BrowserContext* context) { 150 return CommandLine::ForCurrentProcess()->HasSwitch( 151 switches::kDisableExtensionsFileAccessCheck) || 152 ExtensionPrefs::Get(context)->AllowFileAccess(extension_id); 153} 154 155void SetAllowFileAccess(const std::string& extension_id, 156 content::BrowserContext* context, 157 bool allow) { 158 ExtensionService* service = 159 ExtensionSystem::Get(context)->extension_service(); 160 CHECK(service); 161 162 // Reload to update browser state. Only bother if the value changed and the 163 // extension is actually enabled, since there is no UI otherwise. 164 if (allow == AllowFileAccess(extension_id, context)) 165 return; 166 167 ExtensionPrefs::Get(context)->SetAllowFileAccess(extension_id, allow); 168 169 bool extension_is_enabled = service->extensions()->Contains(extension_id); 170 if (extension_is_enabled) 171 service->ReloadExtension(extension_id); 172} 173 174bool AllowedScriptingOnAllUrls(const std::string& extension_id, 175 content::BrowserContext* context) { 176 bool allowed = false; 177 return ExtensionPrefs::Get(context)->ReadPrefAsBoolean( 178 extension_id, 179 kExtensionAllowedOnAllUrlsPrefName, 180 &allowed) && 181 allowed; 182} 183 184void SetAllowedScriptingOnAllUrls(const std::string& extension_id, 185 content::BrowserContext* context, 186 bool allowed) { 187 if (allowed == AllowedScriptingOnAllUrls(extension_id, context)) 188 return; // Nothing to do here. 189 190 ExtensionPrefs::Get(context)->UpdateExtensionPref( 191 extension_id, 192 kExtensionAllowedOnAllUrlsPrefName, 193 allowed ? new base::FundamentalValue(true) : NULL); 194 195 const Extension* extension = 196 ExtensionRegistry::Get(context)->enabled_extensions().GetByID( 197 extension_id); 198 if (extension) { 199 PermissionsUpdater updater(context); 200 if (allowed) 201 updater.GrantWithheldImpliedAllHosts(extension); 202 else 203 updater.WithholdImpliedAllHosts(extension); 204 } 205} 206 207bool IsAppLaunchable(const std::string& extension_id, 208 content::BrowserContext* context) { 209 int reason = ExtensionPrefs::Get(context)->GetDisableReasons(extension_id); 210 return !((reason & Extension::DISABLE_UNSUPPORTED_REQUIREMENT) || 211 (reason & Extension::DISABLE_CORRUPTED)); 212} 213 214bool IsAppLaunchableWithoutEnabling(const std::string& extension_id, 215 content::BrowserContext* context) { 216 return ExtensionRegistry::Get(context)->GetExtensionById( 217 extension_id, ExtensionRegistry::ENABLED) != NULL; 218} 219 220bool ShouldSyncExtension(const Extension* extension, 221 content::BrowserContext* context) { 222 return sync_helper::IsSyncableExtension(extension) && 223 !ExtensionPrefs::Get(context)->DoNotSync(extension->id()); 224} 225 226bool ShouldSyncApp(const Extension* app, content::BrowserContext* context) { 227 return sync_helper::IsSyncableApp(app) && 228 !util::IsEphemeralApp(app->id(), context) && 229 !ExtensionPrefs::Get(context)->DoNotSync(app->id()); 230} 231 232bool IsExtensionIdle(const std::string& extension_id, 233 content::BrowserContext* context) { 234 ProcessManager* process_manager = 235 ExtensionSystem::Get(context)->process_manager(); 236 DCHECK(process_manager); 237 ExtensionHost* host = 238 process_manager->GetBackgroundHostForExtension(extension_id); 239 if (host) 240 return false; 241 242 content::SiteInstance* site_instance = process_manager->GetSiteInstanceForURL( 243 Extension::GetBaseURLFromExtensionId(extension_id)); 244 if (site_instance && site_instance->HasProcess()) 245 return false; 246 247 return process_manager->GetRenderViewHostsForExtension(extension_id).empty(); 248} 249 250GURL GetSiteForExtensionId(const std::string& extension_id, 251 content::BrowserContext* context) { 252 return content::SiteInstance::GetSiteForURL( 253 context, Extension::GetBaseURLFromExtensionId(extension_id)); 254} 255 256scoped_ptr<base::DictionaryValue> GetExtensionInfo(const Extension* extension) { 257 DCHECK(extension); 258 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); 259 260 dict->SetString("id", extension->id()); 261 dict->SetString("name", extension->name()); 262 263 GURL icon = extensions::ExtensionIconSource::GetIconURL( 264 extension, 265 extension_misc::EXTENSION_ICON_SMALLISH, 266 ExtensionIconSet::MATCH_BIGGER, 267 false, // Not grayscale. 268 NULL); // Don't set bool if exists. 269 dict->SetString("icon", icon.spec()); 270 271 return dict.Pass(); 272} 273 274bool HasIsolatedStorage(const ExtensionInfo& info) { 275 if (!info.extension_manifest.get()) 276 return false; 277 278 std::string error; 279 scoped_refptr<const Extension> extension(Extension::Create( 280 info.extension_path, 281 info.extension_location, 282 *info.extension_manifest, 283 Extension::NO_FLAGS, 284 info.extension_id, 285 &error)); 286 if (!extension.get()) 287 return false; 288 289 return AppIsolationInfo::HasIsolatedStorage(extension.get()); 290} 291 292bool SiteHasIsolatedStorage(const GURL& extension_site_url, 293 content::BrowserContext* context) { 294 const Extension* extension = ExtensionRegistry::Get(context)-> 295 enabled_extensions().GetExtensionOrAppByURL(extension_site_url); 296 if (!extension) 297 return false; 298 299 return AppIsolationInfo::HasIsolatedStorage(extension); 300} 301 302const gfx::ImageSkia& GetDefaultAppIcon() { 303 return *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 304 IDR_APP_DEFAULT_ICON); 305} 306 307const gfx::ImageSkia& GetDefaultExtensionIcon() { 308 return *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 309 IDR_EXTENSION_DEFAULT_ICON); 310} 311 312} // namespace util 313} // namespace extensions 314