Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / chrome / browser / extensions / extension_util.cc
blobc1e1c174b650f0bd1206079b6c143e326ee05066
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/metrics/field_trial.h"
10 #include "base/values.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/extension_sync_service.h"
13 #include "chrome/browser/extensions/permissions_updater.h"
14 #include "chrome/browser/extensions/shared_module_service.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/common/extensions/sync_helper.h"
19 #include "content/public/browser/site_instance.h"
20 #include "extensions/browser/extension_prefs.h"
21 #include "extensions/browser/extension_registry.h"
22 #include "extensions/browser/extension_system.h"
23 #include "extensions/browser/extension_util.h"
24 #include "extensions/common/extension.h"
25 #include "extensions/common/extension_icon_set.h"
26 #include "extensions/common/feature_switch.h"
27 #include "extensions/common/features/behavior_feature.h"
28 #include "extensions/common/features/feature_provider.h"
29 #include "extensions/common/manifest.h"
30 #include "extensions/common/manifest_handlers/app_isolation_info.h"
31 #include "extensions/common/manifest_handlers/incognito_info.h"
32 #include "extensions/common/permissions/permissions_data.h"
33 #include "extensions/grit/extensions_browser_resources.h"
34 #include "ui/base/resource/resource_bundle.h"
36 namespace extensions {
37 namespace util {
39 namespace {
41 const char kSupervisedUserExtensionPermissionIncreaseFieldTrialName[] =
42 "SupervisedUserExtensionPermissionIncrease";
44 // The entry into the ExtensionPrefs for allowing an extension to script on
45 // all urls without explicit permission.
46 const char kExtensionAllowedOnAllUrlsPrefName[] =
47 "extension_can_script_all_urls";
49 // The entry into the prefs for when a user has explicitly set the "extension
50 // allowed on all urls" pref.
51 const char kHasSetScriptOnAllUrlsPrefName[] = "has_set_script_all_urls";
53 // Returns true if |extension| should always be enabled in incognito mode.
54 bool IsWhitelistedForIncognito(const Extension* extension) {
55 return FeatureProvider::GetBehaviorFeature(
56 BehaviorFeature::kWhitelistedForIncognito)
57 ->IsAvailableToExtension(extension)
58 .is_available();
61 // Returns |extension_id|. See note below.
62 std::string ReloadExtensionIfEnabled(const std::string& extension_id,
63 content::BrowserContext* context) {
64 ExtensionRegistry* registry = ExtensionRegistry::Get(context);
65 bool extension_is_enabled =
66 registry->enabled_extensions().Contains(extension_id);
68 if (!extension_is_enabled)
69 return extension_id;
71 // When we reload the extension the ID may be invalidated if we've passed it
72 // by const ref everywhere. Make a copy to be safe. http://crbug.com/103762
73 std::string id = extension_id;
74 ExtensionService* service =
75 ExtensionSystem::Get(context)->extension_service();
76 CHECK(service);
77 service->ReloadExtension(id);
78 return id;
81 // Sets the preference for scripting on all urls to |allowed|, optionally
82 // updating the extension's active permissions (based on |update_permissions|).
83 void SetAllowedScriptingOnAllUrlsHelper(
84 content::BrowserContext* context,
85 const std::string& extension_id,
86 bool allowed,
87 bool update_permissions) {
88 // TODO(devlin): Right now, we always need to have a value for this pref.
89 // Once the scripts-require-action feature launches, we can change the set
90 // to be null if false.
91 ExtensionPrefs::Get(context)->UpdateExtensionPref(
92 extension_id,
93 kExtensionAllowedOnAllUrlsPrefName,
94 new base::FundamentalValue(allowed));
96 if (update_permissions) {
97 const Extension* extension =
98 ExtensionRegistry::Get(context)->enabled_extensions().GetByID(
99 extension_id);
100 if (extension) {
101 PermissionsUpdater updater(context);
102 if (allowed)
103 updater.GrantWithheldImpliedAllHosts(extension);
104 else
105 updater.WithholdImpliedAllHosts(extension);
107 // If this was an update to permissions, we also need to sync the change.
108 ExtensionSyncService* sync_service = ExtensionSyncService::Get(context);
109 if (sync_service) // sync_service can be null in unittests.
110 sync_service->SyncExtensionChangeIfNeeded(*extension);
115 } // namespace
117 bool IsIncognitoEnabled(const std::string& extension_id,
118 content::BrowserContext* context) {
119 const Extension* extension = ExtensionRegistry::Get(context)->
120 GetExtensionById(extension_id, ExtensionRegistry::ENABLED);
121 if (extension) {
122 if (!extension->can_be_incognito_enabled())
123 return false;
124 // If this is an existing component extension we always allow it to
125 // work in incognito mode.
126 if (extension->location() == Manifest::COMPONENT)
127 return true;
128 if (IsWhitelistedForIncognito(extension))
129 return true;
131 return ExtensionPrefs::Get(context)->IsIncognitoEnabled(extension_id);
134 void SetIsIncognitoEnabled(const std::string& extension_id,
135 content::BrowserContext* context,
136 bool enabled) {
137 ExtensionRegistry* registry = ExtensionRegistry::Get(context);
138 const Extension* extension =
139 registry->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING);
141 if (extension) {
142 if (!extension->can_be_incognito_enabled())
143 return;
145 // TODO(treib,kalman): Should this be Manifest::IsComponentLocation(..)?
146 // (which also checks for EXTERNAL_COMPONENT).
147 if (extension->location() == Manifest::COMPONENT) {
148 // This shouldn't be called for component extensions unless it is called
149 // by sync, for syncable component extensions.
150 // See http://crbug.com/112290 and associated CLs for the sordid history.
151 DCHECK(sync_helper::IsSyncableComponentExtension(extension));
153 // If we are here, make sure the we aren't trying to change the value.
154 DCHECK_EQ(enabled, IsIncognitoEnabled(extension_id, context));
155 return;
159 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(context);
160 // Broadcast unloaded and loaded events to update browser state. Only bother
161 // if the value changed and the extension is actually enabled, since there is
162 // no UI otherwise.
163 bool old_enabled = extension_prefs->IsIncognitoEnabled(extension_id);
164 if (enabled == old_enabled)
165 return;
167 extension_prefs->SetIsIncognitoEnabled(extension_id, enabled);
169 std::string id = ReloadExtensionIfEnabled(extension_id, context);
171 // Reloading the extension invalidates the |extension| pointer.
172 extension = registry->GetExtensionById(id, ExtensionRegistry::EVERYTHING);
173 if (extension) {
174 Profile* profile = Profile::FromBrowserContext(context);
175 ExtensionSyncService::Get(profile)->SyncExtensionChangeIfNeeded(*extension);
179 bool CanCrossIncognito(const Extension* extension,
180 content::BrowserContext* context) {
181 // We allow the extension to see events and data from another profile iff it
182 // uses "spanning" behavior and it has incognito access. "split" mode
183 // extensions only see events for a matching profile.
184 CHECK(extension);
185 return IsIncognitoEnabled(extension->id(), context) &&
186 !IncognitoInfo::IsSplitMode(extension);
189 bool CanLoadInIncognito(const Extension* extension,
190 content::BrowserContext* context) {
191 CHECK(extension);
192 if (extension->is_hosted_app())
193 return true;
194 // Packaged apps and regular extensions need to be enabled specifically for
195 // incognito (and split mode should be set).
196 return IncognitoInfo::IsSplitMode(extension) &&
197 IsIncognitoEnabled(extension->id(), context);
200 bool AllowFileAccess(const std::string& extension_id,
201 content::BrowserContext* context) {
202 return base::CommandLine::ForCurrentProcess()->HasSwitch(
203 switches::kDisableExtensionsFileAccessCheck) ||
204 ExtensionPrefs::Get(context)->AllowFileAccess(extension_id);
207 void SetAllowFileAccess(const std::string& extension_id,
208 content::BrowserContext* context,
209 bool allow) {
210 // Reload to update browser state. Only bother if the value changed and the
211 // extension is actually enabled, since there is no UI otherwise.
212 if (allow == AllowFileAccess(extension_id, context))
213 return;
215 ExtensionPrefs::Get(context)->SetAllowFileAccess(extension_id, allow);
217 ReloadExtensionIfEnabled(extension_id, context);
220 bool AllowedScriptingOnAllUrls(const std::string& extension_id,
221 content::BrowserContext* context) {
222 bool allowed = false;
223 ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
224 if (!prefs->ReadPrefAsBoolean(extension_id,
225 kExtensionAllowedOnAllUrlsPrefName,
226 &allowed)) {
227 // If there is no value present, we make one, defaulting it to the value of
228 // the 'scripts require action' flag. If the flag is on, then the extension
229 // does not have permission to script on all urls by default.
230 allowed = DefaultAllowedScriptingOnAllUrls();
231 SetAllowedScriptingOnAllUrlsHelper(context, extension_id, allowed, false);
233 return allowed;
236 void SetAllowedScriptingOnAllUrls(const std::string& extension_id,
237 content::BrowserContext* context,
238 bool allowed) {
239 if (allowed != AllowedScriptingOnAllUrls(extension_id, context)) {
240 SetAllowedScriptingOnAllUrlsHelper(context, extension_id, allowed, true);
241 ExtensionPrefs::Get(context)->UpdateExtensionPref(
242 extension_id,
243 kHasSetScriptOnAllUrlsPrefName,
244 new base::FundamentalValue(true));
248 bool HasSetAllowedScriptingOnAllUrls(const std::string& extension_id,
249 content::BrowserContext* context) {
250 bool did_set = false;
251 return ExtensionPrefs::Get(context)->ReadPrefAsBoolean(
252 extension_id,
253 kHasSetScriptOnAllUrlsPrefName,
254 &did_set) && did_set;
257 bool DefaultAllowedScriptingOnAllUrls() {
258 return !FeatureSwitch::scripts_require_action()->IsEnabled();
261 bool IsAppLaunchable(const std::string& extension_id,
262 content::BrowserContext* context) {
263 int reason = ExtensionPrefs::Get(context)->GetDisableReasons(extension_id);
264 return !((reason & Extension::DISABLE_UNSUPPORTED_REQUIREMENT) ||
265 (reason & Extension::DISABLE_CORRUPTED));
268 bool IsAppLaunchableWithoutEnabling(const std::string& extension_id,
269 content::BrowserContext* context) {
270 return ExtensionRegistry::Get(context)->GetExtensionById(
271 extension_id, ExtensionRegistry::ENABLED) != NULL;
274 bool ShouldSync(const Extension* extension,
275 content::BrowserContext* context) {
276 return sync_helper::IsSyncable(extension) &&
277 !util::IsEphemeralApp(extension->id(), context) &&
278 !ExtensionPrefs::Get(context)->DoNotSync(extension->id());
281 bool IsExtensionIdle(const std::string& extension_id,
282 content::BrowserContext* context) {
283 std::vector<std::string> ids_to_check;
284 ids_to_check.push_back(extension_id);
286 const Extension* extension =
287 ExtensionRegistry::Get(context)
288 ->GetExtensionById(extension_id, ExtensionRegistry::ENABLED);
289 if (extension && extension->is_shared_module()) {
290 // We have to check all the extensions that use this shared module for idle
291 // to tell whether it is really 'idle'.
292 SharedModuleService* service = ExtensionSystem::Get(context)
293 ->extension_service()
294 ->shared_module_service();
295 scoped_ptr<ExtensionSet> dependents =
296 service->GetDependentExtensions(extension);
297 for (ExtensionSet::const_iterator i = dependents->begin();
298 i != dependents->end();
299 i++) {
300 ids_to_check.push_back((*i)->id());
304 ProcessManager* process_manager = ProcessManager::Get(context);
305 for (std::vector<std::string>::const_iterator i = ids_to_check.begin();
306 i != ids_to_check.end();
307 i++) {
308 const std::string id = (*i);
309 ExtensionHost* host = process_manager->GetBackgroundHostForExtension(id);
310 if (host)
311 return false;
313 scoped_refptr<content::SiteInstance> site_instance =
314 process_manager->GetSiteInstanceForURL(
315 Extension::GetBaseURLFromExtensionId(id));
316 if (site_instance && site_instance->HasProcess())
317 return false;
319 if (!process_manager->GetRenderFrameHostsForExtension(id).empty())
320 return false;
322 return true;
325 GURL GetSiteForExtensionId(const std::string& extension_id,
326 content::BrowserContext* context) {
327 return content::SiteInstance::GetSiteForURL(
328 context, Extension::GetBaseURLFromExtensionId(extension_id));
331 scoped_ptr<base::DictionaryValue> GetExtensionInfo(const Extension* extension) {
332 DCHECK(extension);
333 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
335 dict->SetString("id", extension->id());
336 dict->SetString("name", extension->name());
338 GURL icon = extensions::ExtensionIconSource::GetIconURL(
339 extension,
340 extension_misc::EXTENSION_ICON_SMALLISH,
341 ExtensionIconSet::MATCH_BIGGER,
342 false, // Not grayscale.
343 NULL); // Don't set bool if exists.
344 dict->SetString("icon", icon.spec());
346 return dict.Pass();
349 const gfx::ImageSkia& GetDefaultAppIcon() {
350 return *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
351 IDR_APP_DEFAULT_ICON);
354 const gfx::ImageSkia& GetDefaultExtensionIcon() {
355 return *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
356 IDR_EXTENSION_DEFAULT_ICON);
359 bool IsNewBookmarkAppsEnabled() {
360 #if defined(OS_MACOSX)
361 return base::CommandLine::ForCurrentProcess()->HasSwitch(
362 switches::kEnableNewBookmarkApps);
363 #else
364 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
365 switches::kDisableNewBookmarkApps);
366 #endif
369 bool CanHostedAppsOpenInWindows() {
370 #if defined(OS_MACOSX)
371 return base::CommandLine::ForCurrentProcess()->HasSwitch(
372 switches::kEnableHostedAppsInWindows);
373 #else
374 return true;
375 #endif
378 bool IsExtensionSupervised(const Extension* extension, Profile* profile) {
379 return extension->was_installed_by_custodian() && profile->IsSupervised();
382 bool NeedCustodianApprovalForPermissionIncrease() {
383 const std::string group_name = base::FieldTrialList::FindFullName(
384 kSupervisedUserExtensionPermissionIncreaseFieldTrialName);
385 return group_name == "NeedCustodianApproval";
388 } // namespace util
389 } // namespace extensions