blob: 45dc7408cc3cda2f8d46ea09561abce570b7bf7a [file] [log] [blame]
[email protected]a7ff4b72013-10-17 20:56:021// 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/extensions/extension_util.h"
6
7#include "base/command_line.h"
[email protected]bb2feea2014-03-18 22:08:138#include "base/logging.h"
9#include "base/values.h"
[email protected]a7ff4b72013-10-17 20:56:0210#include "chrome/browser/extensions/extension_service.h"
[email protected]f8aefb132013-10-30 09:29:5211#include "chrome/browser/extensions/extension_sync_service.h"
[email protected]1d5cf4142014-01-24 18:25:2212#include "chrome/browser/profiles/profile.h"
[email protected]bb2feea2014-03-18 22:08:1313#include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
[email protected]a7ff4b72013-10-17 20:56:0214#include "chrome/common/chrome_switches.h"
[email protected]ca0336342014-03-21 12:58:3415#include "chrome/common/extensions/manifest_handlers/app_isolation_info.h"
[email protected]a7ff4b72013-10-17 20:56:0216#include "chrome/common/extensions/sync_helper.h"
[email protected]617342a42013-12-18 23:34:0317#include "content/public/browser/site_instance.h"
[email protected]489db0842014-01-22 18:20:0318#include "extensions/browser/extension_prefs.h"
[email protected]599539802014-01-07 23:06:0019#include "extensions/browser/extension_registry.h"
[email protected]59b0e602014-01-30 00:41:2420#include "extensions/browser/extension_system.h"
[email protected]30e190f82014-05-26 16:44:3921#include "extensions/browser/extension_util.h"
[email protected]e4452d32013-11-15 23:07:4122#include "extensions/common/extension.h"
[email protected]4b7908842014-04-07 23:50:2223#include "extensions/common/extension_icon_set.h"
[email protected]a7ff4b72013-10-17 20:56:0224#include "extensions/common/manifest.h"
[email protected]1f7de252013-11-06 22:02:0025#include "extensions/common/manifest_handlers/incognito_info.h"
[email protected]7eb20e32014-04-30 08:50:5626#include "grit/theme_resources.h"
27#include "ui/base/resource/resource_bundle.h"
[email protected]a7ff4b72013-10-17 20:56:0228
[email protected]1d5cf4142014-01-24 18:25:2229namespace extensions {
30namespace util {
[email protected]a7ff4b72013-10-17 20:56:0231
[email protected]b33c8c22014-05-29 19:51:0832namespace {
33// The entry into the ExtensionPrefs for allowing an extension to script on
34// all urls without explicit permission.
35const char kExtensionAllowedOnAllUrlsPrefName[] =
36 "extension_can_script_all_urls";
37}
38
[email protected]a7ff4b72013-10-17 20:56:0239bool IsIncognitoEnabled(const std::string& extension_id,
[email protected]1d5cf4142014-01-24 18:25:2240 content::BrowserContext* context) {
41 const Extension* extension = ExtensionRegistry::Get(context)->
42 GetExtensionById(extension_id, ExtensionRegistry::ENABLED);
43 if (extension) {
44 if (!extension->can_be_incognito_enabled())
45 return false;
46 // If this is an existing component extension we always allow it to
47 // work in incognito mode.
48 if (extension->location() == Manifest::COMPONENT)
49 return true;
[email protected]1d5cf4142014-01-24 18:25:2250 }
[email protected]a7ff4b72013-10-17 20:56:0251
[email protected]1d5cf4142014-01-24 18:25:2252 return ExtensionPrefs::Get(context)->IsIncognitoEnabled(extension_id);
[email protected]a7ff4b72013-10-17 20:56:0253}
54
55void SetIsIncognitoEnabled(const std::string& extension_id,
[email protected]1d5cf4142014-01-24 18:25:2256 content::BrowserContext* context,
[email protected]a7ff4b72013-10-17 20:56:0257 bool enabled) {
[email protected]1d5cf4142014-01-24 18:25:2258 ExtensionService* service =
[email protected]59b0e602014-01-30 00:41:2459 ExtensionSystem::Get(context)->extension_service();
[email protected]1d5cf4142014-01-24 18:25:2260 CHECK(service);
[email protected]a7ff4b72013-10-17 20:56:0261 const Extension* extension = service->GetInstalledExtension(extension_id);
[email protected]a7ff4b72013-10-17 20:56:0262
[email protected]1d5cf4142014-01-24 18:25:2263 if (extension) {
64 if (!extension->can_be_incognito_enabled())
65 return;
66
67 if (extension->location() == Manifest::COMPONENT) {
68 // This shouldn't be called for component extensions unless it is called
69 // by sync, for syncable component extensions.
70 // See http://crbug.com/112290 and associated CLs for the sordid history.
71 DCHECK(sync_helper::IsSyncable(extension));
72
73 // If we are here, make sure the we aren't trying to change the value.
74 DCHECK_EQ(enabled, IsIncognitoEnabled(extension_id, service->profile()));
75 return;
76 }
[email protected]a7ff4b72013-10-17 20:56:0277 }
78
[email protected]7c82539c2014-02-19 06:09:1779 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(service->profile());
[email protected]a7ff4b72013-10-17 20:56:0280 // Broadcast unloaded and loaded events to update browser state. Only bother
81 // if the value changed and the extension is actually enabled, since there is
82 // no UI otherwise.
83 bool old_enabled = extension_prefs->IsIncognitoEnabled(extension_id);
84 if (enabled == old_enabled)
85 return;
86
87 extension_prefs->SetIsIncognitoEnabled(extension_id, enabled);
88
89 bool extension_is_enabled = service->extensions()->Contains(extension_id);
90
91 // When we reload the extension the ID may be invalidated if we've passed it
92 // by const ref everywhere. Make a copy to be safe.
93 std::string id = extension_id;
94 if (extension_is_enabled)
95 service->ReloadExtension(id);
96
97 // Reloading the extension invalidates the |extension| pointer.
98 extension = service->GetInstalledExtension(id);
[email protected]f8aefb132013-10-30 09:29:5299 if (extension) {
100 ExtensionSyncService::Get(service->profile())->
101 SyncExtensionChangeIfNeeded(*extension);
102 }
[email protected]a7ff4b72013-10-17 20:56:02103}
104
105bool CanCrossIncognito(const Extension* extension,
[email protected]1d5cf4142014-01-24 18:25:22106 content::BrowserContext* context) {
[email protected]a7ff4b72013-10-17 20:56:02107 // We allow the extension to see events and data from another profile iff it
108 // uses "spanning" behavior and it has incognito access. "split" mode
109 // extensions only see events for a matching profile.
110 CHECK(extension);
[email protected]1d5cf4142014-01-24 18:25:22111 return IsIncognitoEnabled(extension->id(), context) &&
112 !IncognitoInfo::IsSplitMode(extension);
[email protected]a7ff4b72013-10-17 20:56:02113}
114
115bool CanLoadInIncognito(const Extension* extension,
[email protected]1d5cf4142014-01-24 18:25:22116 content::BrowserContext* context) {
117 CHECK(extension);
[email protected]a7ff4b72013-10-17 20:56:02118 if (extension->is_hosted_app())
119 return true;
120 // Packaged apps and regular extensions need to be enabled specifically for
121 // incognito (and split mode should be set).
[email protected]1d5cf4142014-01-24 18:25:22122 return IncognitoInfo::IsSplitMode(extension) &&
123 IsIncognitoEnabled(extension->id(), context);
[email protected]a7ff4b72013-10-17 20:56:02124}
125
[email protected]1d5cf4142014-01-24 18:25:22126bool AllowFileAccess(const std::string& extension_id,
127 content::BrowserContext* context) {
128 return CommandLine::ForCurrentProcess()->HasSwitch(
129 switches::kDisableExtensionsFileAccessCheck) ||
130 ExtensionPrefs::Get(context)->AllowFileAccess(extension_id);
[email protected]a7ff4b72013-10-17 20:56:02131}
132
[email protected]1d5cf4142014-01-24 18:25:22133void SetAllowFileAccess(const std::string& extension_id,
134 content::BrowserContext* context,
[email protected]a7ff4b72013-10-17 20:56:02135 bool allow) {
[email protected]1d5cf4142014-01-24 18:25:22136 ExtensionService* service =
[email protected]59b0e602014-01-30 00:41:24137 ExtensionSystem::Get(context)->extension_service();
[email protected]1d5cf4142014-01-24 18:25:22138 CHECK(service);
139
[email protected]a7ff4b72013-10-17 20:56:02140 // Reload to update browser state. Only bother if the value changed and the
141 // extension is actually enabled, since there is no UI otherwise.
[email protected]1d5cf4142014-01-24 18:25:22142 if (allow == AllowFileAccess(extension_id, context))
[email protected]a7ff4b72013-10-17 20:56:02143 return;
144
[email protected]7c82539c2014-02-19 06:09:17145 ExtensionPrefs::Get(context)->SetAllowFileAccess(extension_id, allow);
[email protected]a7ff4b72013-10-17 20:56:02146
[email protected]1d5cf4142014-01-24 18:25:22147 bool extension_is_enabled = service->extensions()->Contains(extension_id);
[email protected]a7ff4b72013-10-17 20:56:02148 if (extension_is_enabled)
[email protected]1d5cf4142014-01-24 18:25:22149 service->ReloadExtension(extension_id);
[email protected]a7ff4b72013-10-17 20:56:02150}
151
[email protected]b33c8c22014-05-29 19:51:08152bool AllowedScriptingOnAllUrls(const std::string& extension_id,
153 content::BrowserContext* context) {
154 bool allowed = false;
155 return ExtensionPrefs::Get(context)->ReadPrefAsBoolean(
156 extension_id,
157 kExtensionAllowedOnAllUrlsPrefName,
158 &allowed) &&
159 allowed;
160}
161
162void SetAllowedScriptingOnAllUrls(const std::string& extension_id,
163 content::BrowserContext* context,
164 bool allowed) {
165 ExtensionPrefs::Get(context)->UpdateExtensionPref(
166 extension_id,
167 kExtensionAllowedOnAllUrlsPrefName,
168 allowed ? new base::FundamentalValue(true) : NULL);
169}
170
[email protected]f5ea0962013-11-22 09:20:47171bool IsAppLaunchable(const std::string& extension_id,
[email protected]1d5cf4142014-01-24 18:25:22172 content::BrowserContext* context) {
173 return !(ExtensionPrefs::Get(context)->GetDisableReasons(extension_id) &
[email protected]f5ea0962013-11-22 09:20:47174 Extension::DISABLE_UNSUPPORTED_REQUIREMENT);
175}
176
177bool IsAppLaunchableWithoutEnabling(const std::string& extension_id,
[email protected]1d5cf4142014-01-24 18:25:22178 content::BrowserContext* context) {
179 return ExtensionRegistry::Get(context)->GetExtensionById(
180 extension_id, ExtensionRegistry::ENABLED) != NULL;
[email protected]f5ea0962013-11-22 09:20:47181}
182
[email protected]658eae52014-06-14 20:28:05183bool ShouldSyncExtension(const Extension* extension,
184 content::BrowserContext* context) {
185 return sync_helper::IsSyncableExtension(extension) &&
186 !ExtensionPrefs::Get(context)->DoNotSync(extension->id());
187}
188
[email protected]30e190f82014-05-26 16:44:39189bool ShouldSyncApp(const Extension* app, content::BrowserContext* context) {
190 return sync_helper::IsSyncableApp(app) &&
[email protected]658eae52014-06-14 20:28:05191 !util::IsEphemeralApp(app->id(), context) &&
192 !ExtensionPrefs::Get(context)->DoNotSync(app->id());
[email protected]30e190f82014-05-26 16:44:39193}
194
[email protected]617342a42013-12-18 23:34:03195bool IsExtensionIdle(const std::string& extension_id,
[email protected]1d5cf4142014-01-24 18:25:22196 content::BrowserContext* context) {
197 ProcessManager* process_manager =
[email protected]59b0e602014-01-30 00:41:24198 ExtensionSystem::Get(context)->process_manager();
[email protected]617342a42013-12-18 23:34:03199 DCHECK(process_manager);
[email protected]1d5cf4142014-01-24 18:25:22200 ExtensionHost* host =
[email protected]617342a42013-12-18 23:34:03201 process_manager->GetBackgroundHostForExtension(extension_id);
202 if (host)
203 return false;
204
205 content::SiteInstance* site_instance = process_manager->GetSiteInstanceForURL(
206 Extension::GetBaseURLFromExtensionId(extension_id));
[email protected]1d5cf4142014-01-24 18:25:22207 if (site_instance && site_instance->HasProcess())
[email protected]617342a42013-12-18 23:34:03208 return false;
[email protected]617342a42013-12-18 23:34:03209
210 return process_manager->GetRenderViewHostsForExtension(extension_id).empty();
211}
212
[email protected]3a746ec2014-03-15 05:30:56213GURL GetSiteForExtensionId(const std::string& extension_id,
214 content::BrowserContext* context) {
215 return content::SiteInstance::GetSiteForURL(
216 context, Extension::GetBaseURLFromExtensionId(extension_id));
217}
218
[email protected]bb2feea2014-03-18 22:08:13219scoped_ptr<base::DictionaryValue> GetExtensionInfo(const Extension* extension) {
220 DCHECK(extension);
221 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
222
223 dict->SetString("id", extension->id());
224 dict->SetString("name", extension->name());
225
226 GURL icon = extensions::ExtensionIconSource::GetIconURL(
227 extension,
228 extension_misc::EXTENSION_ICON_SMALLISH,
229 ExtensionIconSet::MATCH_BIGGER,
230 false, // Not grayscale.
231 NULL); // Don't set bool if exists.
232 dict->SetString("icon", icon.spec());
233
234 return dict.Pass();
235}
236
[email protected]ca0336342014-03-21 12:58:34237bool HasIsolatedStorage(const ExtensionInfo& info) {
238 if (!info.extension_manifest.get())
239 return false;
240
241 std::string error;
242 scoped_refptr<const Extension> extension(Extension::Create(
243 info.extension_path,
244 info.extension_location,
245 *info.extension_manifest,
246 Extension::NO_FLAGS,
247 info.extension_id,
248 &error));
249 if (!extension.get())
250 return false;
251
252 return AppIsolationInfo::HasIsolatedStorage(extension.get());
253}
254
255bool SiteHasIsolatedStorage(const GURL& extension_site_url,
256 content::BrowserContext* context) {
257 const Extension* extension = ExtensionRegistry::Get(context)->
258 enabled_extensions().GetExtensionOrAppByURL(extension_site_url);
259 if (extension)
260 return AppIsolationInfo::HasIsolatedStorage(extension);
261
262 if (extension_site_url.SchemeIs(kExtensionScheme)) {
263 // The site URL may also be from an evicted ephemeral app. We do not
264 // immediately delete their data when they are removed from extension
265 // system.
266 ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
267 DCHECK(prefs);
268 scoped_ptr<ExtensionInfo> info = prefs->GetEvictedEphemeralAppInfo(
269 extension_site_url.host());
270 if (info.get())
271 return HasIsolatedStorage(*info);
272 }
273
274 return false;
275}
276
[email protected]7eb20e32014-04-30 08:50:56277const gfx::ImageSkia& GetDefaultAppIcon() {
278 return *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
279 IDR_APP_DEFAULT_ICON);
280}
281
282const gfx::ImageSkia& GetDefaultExtensionIcon() {
283 return *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
284 IDR_EXTENSION_DEFAULT_ICON);
285}
286
[email protected]1d5cf4142014-01-24 18:25:22287} // namespace util
288} // namespace extensions