blob: 80ccb4536cc695a33dc7515bb734871068206169 [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"
8#include "chrome/browser/extensions/extension_prefs.h"
9#include "chrome/browser/extensions/extension_service.h"
[email protected]f8aefb132013-10-30 09:29:5210#include "chrome/browser/extensions/extension_sync_service.h"
[email protected]617342a42013-12-18 23:34:0311#include "chrome/browser/extensions/extension_system.h"
[email protected]a7ff4b72013-10-17 20:56:0212#include "chrome/common/chrome_switches.h"
[email protected]a7ff4b72013-10-17 20:56:0213#include "chrome/common/extensions/sync_helper.h"
[email protected]617342a42013-12-18 23:34:0314#include "content/public/browser/site_instance.h"
[email protected]599539802014-01-07 23:06:0015#include "extensions/browser/extension_registry.h"
[email protected]e4452d32013-11-15 23:07:4116#include "extensions/common/extension.h"
[email protected]a7ff4b72013-10-17 20:56:0217#include "extensions/common/manifest.h"
[email protected]1f7de252013-11-06 22:02:0018#include "extensions/common/manifest_handlers/incognito_info.h"
[email protected]a7ff4b72013-10-17 20:56:0219
20using extensions::Extension;
21using extensions::ExtensionPrefs;
[email protected]599539802014-01-07 23:06:0022using extensions::ExtensionRegistry;
[email protected]a7ff4b72013-10-17 20:56:0223
24namespace extension_util {
25
26bool IsIncognitoEnabled(const std::string& extension_id,
27 const ExtensionService* service) {
28 if (!service)
29 return false;
30
31 const Extension* extension = service->GetInstalledExtension(extension_id);
32 if (extension && !extension->can_be_incognito_enabled())
33 return false;
34 // If this is an existing component extension we always allow it to
35 // work in incognito mode.
36 if (extension && extension->location() == extensions::Manifest::COMPONENT)
37 return true;
38 if (extension && extension->force_incognito_enabled())
39 return true;
40
41 // Check the prefs.
42 return service->extension_prefs()->IsIncognitoEnabled(extension_id);
43}
44
45void SetIsIncognitoEnabled(const std::string& extension_id,
46 ExtensionService* service,
47 bool enabled) {
48 const Extension* extension = service->GetInstalledExtension(extension_id);
49 if (extension && !extension->can_be_incognito_enabled())
50 return;
51 if (extension && extension->location() == extensions::Manifest::COMPONENT) {
52 // This shouldn't be called for component extensions unless it is called
53 // by sync, for syncable component extensions.
54 // See http://crbug.com/112290 and associated CLs for the sordid history.
55 DCHECK(extensions::sync_helper::IsSyncable(extension));
56
57 // If we are here, make sure the we aren't trying to change the value.
58 DCHECK_EQ(enabled, IsIncognitoEnabled(extension_id, service));
59 return;
60 }
61
62 ExtensionPrefs* extension_prefs = service->extension_prefs();
63 // Broadcast unloaded and loaded events to update browser state. Only bother
64 // if the value changed and the extension is actually enabled, since there is
65 // no UI otherwise.
66 bool old_enabled = extension_prefs->IsIncognitoEnabled(extension_id);
67 if (enabled == old_enabled)
68 return;
69
70 extension_prefs->SetIsIncognitoEnabled(extension_id, enabled);
71
72 bool extension_is_enabled = service->extensions()->Contains(extension_id);
73
74 // When we reload the extension the ID may be invalidated if we've passed it
75 // by const ref everywhere. Make a copy to be safe.
76 std::string id = extension_id;
77 if (extension_is_enabled)
78 service->ReloadExtension(id);
79
80 // Reloading the extension invalidates the |extension| pointer.
81 extension = service->GetInstalledExtension(id);
[email protected]f8aefb132013-10-30 09:29:5282 if (extension) {
83 ExtensionSyncService::Get(service->profile())->
84 SyncExtensionChangeIfNeeded(*extension);
85 }
[email protected]a7ff4b72013-10-17 20:56:0286}
87
88bool CanCrossIncognito(const Extension* extension,
89 const ExtensionService* service) {
90 // We allow the extension to see events and data from another profile iff it
91 // uses "spanning" behavior and it has incognito access. "split" mode
92 // extensions only see events for a matching profile.
93 CHECK(extension);
94 return extension_util::IsIncognitoEnabled(extension->id(), service) &&
95 !extensions::IncognitoInfo::IsSplitMode(extension);
96}
97
98bool CanLoadInIncognito(const Extension* extension,
99 const ExtensionService* service) {
100 if (extension->is_hosted_app())
101 return true;
102 // Packaged apps and regular extensions need to be enabled specifically for
103 // incognito (and split mode should be set).
104 return extensions::IncognitoInfo::IsSplitMode(extension) &&
105 extension_util::IsIncognitoEnabled(extension->id(), service);
106}
107
108bool AllowFileAccess(const Extension* extension,
109 const ExtensionService* service) {
110 return (CommandLine::ForCurrentProcess()->HasSwitch(
111 switches::kDisableExtensionsFileAccessCheck) ||
112 service->extension_prefs()->AllowFileAccess(extension->id()));
113}
114
115void SetAllowFileAccess(const Extension* extension,
116 ExtensionService* service,
117 bool allow) {
118 // Reload to update browser state. Only bother if the value changed and the
119 // extension is actually enabled, since there is no UI otherwise.
120 bool old_allow = AllowFileAccess(extension, service);
121 if (allow == old_allow)
122 return;
123
124 service->extension_prefs()->SetAllowFileAccess(extension->id(), allow);
125
126 bool extension_is_enabled = service->extensions()->Contains(extension->id());
127 if (extension_is_enabled)
128 service->ReloadExtension(extension->id());
129}
130
[email protected]f5ea0962013-11-22 09:20:47131bool IsAppLaunchable(const std::string& extension_id,
132 const ExtensionService* service) {
133 return !(service->extension_prefs()->GetDisableReasons(extension_id) &
134 Extension::DISABLE_UNSUPPORTED_REQUIREMENT);
135}
136
137bool IsAppLaunchableWithoutEnabling(const std::string& extension_id,
138 const ExtensionService* service) {
[email protected]599539802014-01-07 23:06:00139 ExtensionRegistry* registry =
140 ExtensionRegistry::Get(service->GetBrowserContext());
141 const Extension* launchable_extension = registry->GetExtensionById(
142 extension_id, ExtensionRegistry::ENABLED);
[email protected]f5ea0962013-11-22 09:20:47143 return launchable_extension != NULL;
144}
145
[email protected]617342a42013-12-18 23:34:03146bool IsExtensionIdle(const std::string& extension_id,
147 extensions::ExtensionSystem* extension_system) {
148 DCHECK(extension_system);
149 extensions::ProcessManager* process_manager =
150 extension_system->process_manager();
151 DCHECK(process_manager);
152 extensions::ExtensionHost* host =
153 process_manager->GetBackgroundHostForExtension(extension_id);
154 if (host)
155 return false;
156
157 content::SiteInstance* site_instance = process_manager->GetSiteInstanceForURL(
158 Extension::GetBaseURLFromExtensionId(extension_id));
159 if (site_instance && site_instance->HasProcess()) {
160 return false;
161 }
162
163 return process_manager->GetRenderViewHostsForExtension(extension_id).empty();
164}
165
[email protected]7f81dfa2014-01-07 10:05:45166bool IsExtensionInstalledPermanently(const std::string& extension_id,
167 const ExtensionService* service) {
168 DCHECK(service);
169 const Extension* extension = service->GetInstalledExtension(extension_id);
170 return extension && !extension->is_ephemeral();
171}
172
[email protected]a7ff4b72013-10-17 20:56:02173} // namespace extension_util