Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / extension_util.cc
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.
4
5 #include "chrome/browser/extensions/extension_util.h"
6
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/profiles/profile.h"
13 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/extensions/manifest_handlers/app_isolation_info.h"
16 #include "chrome/common/extensions/sync_helper.h"
17 #include "content/public/browser/site_instance.h"
18 #include "extensions/browser/extension_prefs.h"
19 #include "extensions/browser/extension_registry.h"
20 #include "extensions/browser/extension_system.h"
21 #include "extensions/common/extension.h"
22 #include "extensions/common/extension_icon_set.h"
23 #include "extensions/common/manifest.h"
24 #include "extensions/common/manifest_handlers/incognito_info.h"
25 #include "grit/theme_resources.h"
26 #include "ui/base/resource/resource_bundle.h"
27
28 namespace extensions {
29 namespace util {
30
31 bool IsIncognitoEnabled(const std::string& extension_id,
32                         content::BrowserContext* context) {
33   const Extension* extension = ExtensionRegistry::Get(context)->
34       GetExtensionById(extension_id, ExtensionRegistry::ENABLED);
35   if (extension) {
36     if (!extension->can_be_incognito_enabled())
37       return false;
38     // If this is an existing component extension we always allow it to
39     // work in incognito mode.
40     if (extension->location() == Manifest::COMPONENT)
41       return true;
42   }
43
44   return ExtensionPrefs::Get(context)->IsIncognitoEnabled(extension_id);
45 }
46
47 void SetIsIncognitoEnabled(const std::string& extension_id,
48                            content::BrowserContext* context,
49                            bool enabled) {
50   ExtensionService* service =
51       ExtensionSystem::Get(context)->extension_service();
52   CHECK(service);
53   const Extension* extension = service->GetInstalledExtension(extension_id);
54
55   if (extension) {
56     if (!extension->can_be_incognito_enabled())
57       return;
58
59     if (extension->location() == Manifest::COMPONENT) {
60       // This shouldn't be called for component extensions unless it is called
61       // by sync, for syncable component extensions.
62       // See http://crbug.com/112290 and associated CLs for the sordid history.
63       DCHECK(sync_helper::IsSyncable(extension));
64
65       // If we are here, make sure the we aren't trying to change the value.
66       DCHECK_EQ(enabled, IsIncognitoEnabled(extension_id, service->profile()));
67       return;
68     }
69   }
70
71   ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(service->profile());
72   // Broadcast unloaded and loaded events to update browser state. Only bother
73   // if the value changed and the extension is actually enabled, since there is
74   // no UI otherwise.
75   bool old_enabled = extension_prefs->IsIncognitoEnabled(extension_id);
76   if (enabled == old_enabled)
77     return;
78
79   extension_prefs->SetIsIncognitoEnabled(extension_id, enabled);
80
81   bool extension_is_enabled = service->extensions()->Contains(extension_id);
82
83   // When we reload the extension the ID may be invalidated if we've passed it
84   // by const ref everywhere. Make a copy to be safe.
85   std::string id = extension_id;
86   if (extension_is_enabled)
87     service->ReloadExtension(id);
88
89   // Reloading the extension invalidates the |extension| pointer.
90   extension = service->GetInstalledExtension(id);
91   if (extension) {
92     ExtensionSyncService::Get(service->profile())->
93         SyncExtensionChangeIfNeeded(*extension);
94   }
95 }
96
97 bool CanCrossIncognito(const Extension* extension,
98                        content::BrowserContext* context) {
99   // We allow the extension to see events and data from another profile iff it
100   // uses "spanning" behavior and it has incognito access. "split" mode
101   // extensions only see events for a matching profile.
102   CHECK(extension);
103   return IsIncognitoEnabled(extension->id(), context) &&
104          !IncognitoInfo::IsSplitMode(extension);
105 }
106
107 bool CanLoadInIncognito(const Extension* extension,
108                         content::BrowserContext* context) {
109   CHECK(extension);
110   if (extension->is_hosted_app())
111     return true;
112   // Packaged apps and regular extensions need to be enabled specifically for
113   // incognito (and split mode should be set).
114   return IncognitoInfo::IsSplitMode(extension) &&
115          IsIncognitoEnabled(extension->id(), context);
116 }
117
118 bool AllowFileAccess(const std::string& extension_id,
119                      content::BrowserContext* context) {
120   return CommandLine::ForCurrentProcess()->HasSwitch(
121              switches::kDisableExtensionsFileAccessCheck) ||
122          ExtensionPrefs::Get(context)->AllowFileAccess(extension_id);
123 }
124
125 void SetAllowFileAccess(const std::string& extension_id,
126                         content::BrowserContext* context,
127                         bool allow) {
128   ExtensionService* service =
129       ExtensionSystem::Get(context)->extension_service();
130   CHECK(service);
131
132   // Reload to update browser state. Only bother if the value changed and the
133   // extension is actually enabled, since there is no UI otherwise.
134   if (allow == AllowFileAccess(extension_id, context))
135     return;
136
137   ExtensionPrefs::Get(context)->SetAllowFileAccess(extension_id, allow);
138
139   bool extension_is_enabled = service->extensions()->Contains(extension_id);
140   if (extension_is_enabled)
141     service->ReloadExtension(extension_id);
142 }
143
144 bool IsAppLaunchable(const std::string& extension_id,
145                      content::BrowserContext* context) {
146   return !(ExtensionPrefs::Get(context)->GetDisableReasons(extension_id) &
147            Extension::DISABLE_UNSUPPORTED_REQUIREMENT);
148 }
149
150 bool IsAppLaunchableWithoutEnabling(const std::string& extension_id,
151                                     content::BrowserContext* context) {
152   return ExtensionRegistry::Get(context)->GetExtensionById(
153       extension_id, ExtensionRegistry::ENABLED) != NULL;
154 }
155
156 bool IsExtensionIdle(const std::string& extension_id,
157                      content::BrowserContext* context) {
158   ProcessManager* process_manager =
159       ExtensionSystem::Get(context)->process_manager();
160   DCHECK(process_manager);
161   ExtensionHost* host =
162       process_manager->GetBackgroundHostForExtension(extension_id);
163   if (host)
164     return false;
165
166   content::SiteInstance* site_instance = process_manager->GetSiteInstanceForURL(
167       Extension::GetBaseURLFromExtensionId(extension_id));
168   if (site_instance && site_instance->HasProcess())
169     return false;
170
171   return process_manager->GetRenderViewHostsForExtension(extension_id).empty();
172 }
173
174 bool IsExtensionInstalledPermanently(const std::string& extension_id,
175                                      content::BrowserContext* context) {
176   const Extension* extension = ExtensionRegistry::Get(context)->
177       GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING);
178   return extension && !extension->is_ephemeral();
179 }
180
181 GURL GetSiteForExtensionId(const std::string& extension_id,
182                            content::BrowserContext* context) {
183   return content::SiteInstance::GetSiteForURL(
184       context, Extension::GetBaseURLFromExtensionId(extension_id));
185 }
186
187 scoped_ptr<base::DictionaryValue> GetExtensionInfo(const Extension* extension) {
188   DCHECK(extension);
189   scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
190
191   dict->SetString("id", extension->id());
192   dict->SetString("name", extension->name());
193
194   GURL icon = extensions::ExtensionIconSource::GetIconURL(
195       extension,
196       extension_misc::EXTENSION_ICON_SMALLISH,
197       ExtensionIconSet::MATCH_BIGGER,
198       false,  // Not grayscale.
199       NULL);  // Don't set bool if exists.
200   dict->SetString("icon", icon.spec());
201
202   return dict.Pass();
203 }
204
205 bool HasIsolatedStorage(const ExtensionInfo& info) {
206   if (!info.extension_manifest.get())
207     return false;
208
209   std::string error;
210   scoped_refptr<const Extension> extension(Extension::Create(
211       info.extension_path,
212       info.extension_location,
213       *info.extension_manifest,
214       Extension::NO_FLAGS,
215       info.extension_id,
216       &error));
217   if (!extension.get())
218     return false;
219
220   return AppIsolationInfo::HasIsolatedStorage(extension.get());
221 }
222
223 bool SiteHasIsolatedStorage(const GURL& extension_site_url,
224                             content::BrowserContext* context) {
225   const Extension* extension = ExtensionRegistry::Get(context)->
226       enabled_extensions().GetExtensionOrAppByURL(extension_site_url);
227   if (extension)
228     return AppIsolationInfo::HasIsolatedStorage(extension);
229
230   if (extension_site_url.SchemeIs(kExtensionScheme)) {
231     // The site URL may also be from an evicted ephemeral app. We do not
232     // immediately delete their data when they are removed from extension
233     // system.
234     ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
235     DCHECK(prefs);
236     scoped_ptr<ExtensionInfo> info = prefs->GetEvictedEphemeralAppInfo(
237         extension_site_url.host());
238     if (info.get())
239       return HasIsolatedStorage(*info);
240   }
241
242   return false;
243 }
244
245 const gfx::ImageSkia& GetDefaultAppIcon() {
246   return *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
247       IDR_APP_DEFAULT_ICON);
248 }
249
250 const gfx::ImageSkia& GetDefaultExtensionIcon() {
251   return *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
252       IDR_EXTENSION_DEFAULT_ICON);
253 }
254
255 }  // namespace util
256 }  // namespace extensions