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 "chrome/browser/extensions/extension_prefs.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/extension_sync_service.h"
11 #include "chrome/browser/extensions/extension_system.h"
12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/common/extensions/sync_helper.h"
14 #include "content/public/browser/site_instance.h"
15 #include "extensions/browser/extension_registry.h"
16 #include "extensions/common/extension.h"
17 #include "extensions/common/manifest.h"
18 #include "extensions/common/manifest_handlers/incognito_info.h"
20 using extensions::Extension
;
21 using extensions::ExtensionPrefs
;
22 using extensions::ExtensionRegistry
;
24 namespace extension_util
{
26 bool IsIncognitoEnabled(const std::string
& extension_id
,
27 const ExtensionService
* service
) {
31 const Extension
* extension
= service
->GetInstalledExtension(extension_id
);
32 if (extension
&& !extension
->can_be_incognito_enabled())
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
)
38 if (extension
&& extension
->force_incognito_enabled())
42 return service
->extension_prefs()->IsIncognitoEnabled(extension_id
);
45 void SetIsIncognitoEnabled(const std::string
& extension_id
,
46 ExtensionService
* service
,
48 const Extension
* extension
= service
->GetInstalledExtension(extension_id
);
49 if (extension
&& !extension
->can_be_incognito_enabled())
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
));
57 // If we are here, make sure the we aren't trying to change the value.
58 DCHECK_EQ(enabled
, IsIncognitoEnabled(extension_id
, service
));
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
66 bool old_enabled
= extension_prefs
->IsIncognitoEnabled(extension_id
);
67 if (enabled
== old_enabled
)
70 extension_prefs
->SetIsIncognitoEnabled(extension_id
, enabled
);
72 bool extension_is_enabled
= service
->extensions()->Contains(extension_id
);
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
);
80 // Reloading the extension invalidates the |extension| pointer.
81 extension
= service
->GetInstalledExtension(id
);
83 ExtensionSyncService::Get(service
->profile())->
84 SyncExtensionChangeIfNeeded(*extension
);
88 bool 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.
94 return extension_util::IsIncognitoEnabled(extension
->id(), service
) &&
95 !extensions::IncognitoInfo::IsSplitMode(extension
);
98 bool CanLoadInIncognito(const Extension
* extension
,
99 const ExtensionService
* service
) {
100 if (extension
->is_hosted_app())
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
);
108 bool AllowFileAccess(const Extension
* extension
,
109 const ExtensionService
* service
) {
110 return (CommandLine::ForCurrentProcess()->HasSwitch(
111 switches::kDisableExtensionsFileAccessCheck
) ||
112 service
->extension_prefs()->AllowFileAccess(extension
->id()));
115 void SetAllowFileAccess(const Extension
* extension
,
116 ExtensionService
* service
,
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
)
124 service
->extension_prefs()->SetAllowFileAccess(extension
->id(), allow
);
126 bool extension_is_enabled
= service
->extensions()->Contains(extension
->id());
127 if (extension_is_enabled
)
128 service
->ReloadExtension(extension
->id());
131 bool IsAppLaunchable(const std::string
& extension_id
,
132 const ExtensionService
* service
) {
133 return !(service
->extension_prefs()->GetDisableReasons(extension_id
) &
134 Extension::DISABLE_UNSUPPORTED_REQUIREMENT
);
137 bool IsAppLaunchableWithoutEnabling(const std::string
& extension_id
,
138 const ExtensionService
* service
) {
139 ExtensionRegistry
* registry
=
140 ExtensionRegistry::Get(service
->GetBrowserContext());
141 const Extension
* launchable_extension
= registry
->GetExtensionById(
142 extension_id
, ExtensionRegistry::ENABLED
);
143 return launchable_extension
!= NULL
;
146 bool 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
);
157 content::SiteInstance
* site_instance
= process_manager
->GetSiteInstanceForURL(
158 Extension::GetBaseURLFromExtensionId(extension_id
));
159 if (site_instance
&& site_instance
->HasProcess()) {
163 return process_manager
->GetRenderViewHostsForExtension(extension_id
).empty();
166 bool IsExtensionInstalledPermanently(const std::string
& extension_id
,
167 const ExtensionService
* service
) {
169 const Extension
* extension
= service
->GetInstalledExtension(extension_id
);
170 return extension
&& !extension
->is_ephemeral();
173 bool IsIdleEphemeralApp(const extensions::Extension
* extension
,
174 extensions::ExtensionSystem
* extension_system
) {
176 DCHECK(extension_system
);
178 if (!extension
->is_ephemeral())
181 return IsExtensionIdle(extension
->id(), extension_system
);
184 } // namespace extension_util