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.
5 #include "chrome/browser/extensions/extension_util.h"
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/values.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/extensions/extension_sync_service.h"
12 #include "chrome/browser/extensions/permissions_updater.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
15 #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"
31 namespace extensions {
35 // The entry into the ExtensionPrefs for allowing an extension to script on
36 // all urls without explicit permission.
37 const char kExtensionAllowedOnAllUrlsPrefName[] =
38 "extension_can_script_all_urls";
40 // Returns true if |extension_id| for an external component extension should
41 // always be enabled in incognito windows.
42 bool 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
49 return extensions::SimpleFeature::IsIdInList(
51 std::set<std::string>(
53 kExtensionWhitelist + arraysize(kExtensionWhitelist)));
57 bool IsIncognitoEnabled(const std::string& extension_id,
58 content::BrowserContext* context) {
59 const Extension* extension = ExtensionRegistry::Get(context)->
60 GetExtensionById(extension_id, ExtensionRegistry::ENABLED);
62 if (!extension->can_be_incognito_enabled())
64 // If this is an existing component extension we always allow it to
65 // work in incognito mode.
66 if (extension->location() == Manifest::COMPONENT)
68 if (extension->location() == Manifest::EXTERNAL_COMPONENT &&
69 IsWhitelistedForIncognito(extension_id)) {
74 return ExtensionPrefs::Get(context)->IsIncognitoEnabled(extension_id);
77 void SetIsIncognitoEnabled(const std::string& extension_id,
78 content::BrowserContext* context,
80 ExtensionService* service =
81 ExtensionSystem::Get(context)->extension_service();
83 const Extension* extension = service->GetInstalledExtension(extension_id);
86 if (!extension->can_be_incognito_enabled())
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));
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()));
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
105 bool old_enabled = extension_prefs->IsIncognitoEnabled(extension_id);
106 if (enabled == old_enabled)
109 extension_prefs->SetIsIncognitoEnabled(extension_id, enabled);
111 bool extension_is_enabled = service->extensions()->Contains(extension_id);
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);
119 // Reloading the extension invalidates the |extension| pointer.
120 extension = service->GetInstalledExtension(id);
122 ExtensionSyncService::Get(service->profile())->
123 SyncExtensionChangeIfNeeded(*extension);
127 bool 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.
133 return IsIncognitoEnabled(extension->id(), context) &&
134 !IncognitoInfo::IsSplitMode(extension);
137 bool CanLoadInIncognito(const Extension* extension,
138 content::BrowserContext* context) {
140 if (extension->is_hosted_app())
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);
148 bool 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);
155 void SetAllowFileAccess(const std::string& extension_id,
156 content::BrowserContext* context,
158 ExtensionService* service =
159 ExtensionSystem::Get(context)->extension_service();
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))
167 ExtensionPrefs::Get(context)->SetAllowFileAccess(extension_id, allow);
169 bool extension_is_enabled = service->extensions()->Contains(extension_id);
170 if (extension_is_enabled)
171 service->ReloadExtension(extension_id);
174 bool AllowedScriptingOnAllUrls(const std::string& extension_id,
175 content::BrowserContext* context) {
176 bool allowed = false;
177 return ExtensionPrefs::Get(context)->ReadPrefAsBoolean(
179 kExtensionAllowedOnAllUrlsPrefName,
184 void SetAllowedScriptingOnAllUrls(const std::string& extension_id,
185 content::BrowserContext* context,
187 if (allowed == AllowedScriptingOnAllUrls(extension_id, context))
188 return; // Nothing to do here.
190 ExtensionPrefs::Get(context)->UpdateExtensionPref(
192 kExtensionAllowedOnAllUrlsPrefName,
193 allowed ? new base::FundamentalValue(true) : NULL);
195 const Extension* extension =
196 ExtensionRegistry::Get(context)->enabled_extensions().GetByID(
199 PermissionsUpdater updater(context);
201 updater.GrantWithheldImpliedAllHosts(extension);
203 updater.WithholdImpliedAllHosts(extension);
207 bool 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));
214 bool IsAppLaunchableWithoutEnabling(const std::string& extension_id,
215 content::BrowserContext* context) {
216 return ExtensionRegistry::Get(context)->GetExtensionById(
217 extension_id, ExtensionRegistry::ENABLED) != NULL;
220 bool ShouldSyncExtension(const Extension* extension,
221 content::BrowserContext* context) {
222 return sync_helper::IsSyncableExtension(extension) &&
223 !ExtensionPrefs::Get(context)->DoNotSync(extension->id());
226 bool 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());
232 bool 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);
242 content::SiteInstance* site_instance = process_manager->GetSiteInstanceForURL(
243 Extension::GetBaseURLFromExtensionId(extension_id));
244 if (site_instance && site_instance->HasProcess())
247 return process_manager->GetRenderViewHostsForExtension(extension_id).empty();
250 GURL GetSiteForExtensionId(const std::string& extension_id,
251 content::BrowserContext* context) {
252 return content::SiteInstance::GetSiteForURL(
253 context, Extension::GetBaseURLFromExtensionId(extension_id));
256 scoped_ptr<base::DictionaryValue> GetExtensionInfo(const Extension* extension) {
258 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
260 dict->SetString("id", extension->id());
261 dict->SetString("name", extension->name());
263 GURL icon = extensions::ExtensionIconSource::GetIconURL(
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());
274 bool HasIsolatedStorage(const ExtensionInfo& info) {
275 if (!info.extension_manifest.get())
279 scoped_refptr<const Extension> extension(Extension::Create(
281 info.extension_location,
282 *info.extension_manifest,
286 if (!extension.get())
289 return AppIsolationInfo::HasIsolatedStorage(extension.get());
292 bool SiteHasIsolatedStorage(const GURL& extension_site_url,
293 content::BrowserContext* context) {
294 const Extension* extension = ExtensionRegistry::Get(context)->
295 enabled_extensions().GetExtensionOrAppByURL(extension_site_url);
299 return AppIsolationInfo::HasIsolatedStorage(extension);
302 const gfx::ImageSkia& GetDefaultAppIcon() {
303 return *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
304 IDR_APP_DEFAULT_ICON);
307 const gfx::ImageSkia& GetDefaultExtensionIcon() {
308 return *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
309 IDR_EXTENSION_DEFAULT_ICON);
313 } // namespace extensions