Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / common / extensions / chrome_extensions_client.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/common/extensions/chrome_extensions_client.h"
6
7 #include "base/command_line.h"
8 #include "base/strings/string_util.h"
9 #include "chrome/common/chrome_switches.h"
10 #include "chrome/common/chrome_version_info.h"
11 #include "chrome/common/extensions/api/generated_schemas.h"
12 #include "chrome/common/extensions/chrome_manifest_handlers.h"
13 #include "chrome/common/extensions/extension_constants.h"
14 #include "chrome/common/extensions/features/chrome_channel_feature_filter.h"
15 #include "chrome/common/extensions/features/feature_channel.h"
16 #include "chrome/common/url_constants.h"
17 #include "chrome/grit/chromium_strings.h"
18 #include "chrome/grit/common_resources.h"
19 #include "chrome/grit/extensions_api_resources.h"
20 #include "chrome/grit/generated_resources.h"
21 #include "content/public/common/url_constants.h"
22 #include "extensions/common/api/generated_schemas.h"
23 #include "extensions/common/common_manifest_handlers.h"
24 #include "extensions/common/extension.h"
25 #include "extensions/common/extension_api.h"
26 #include "extensions/common/extension_urls.h"
27 #include "extensions/common/features/api_feature.h"
28 #include "extensions/common/features/base_feature_provider.h"
29 #include "extensions/common/features/feature_provider.h"
30 #include "extensions/common/features/json_feature_provider_source.h"
31 #include "extensions/common/features/manifest_feature.h"
32 #include "extensions/common/features/permission_feature.h"
33 #include "extensions/common/features/simple_feature.h"
34 #include "extensions/common/manifest_constants.h"
35 #include "extensions/common/manifest_handler.h"
36 #include "extensions/common/permissions/api_permission_set.h"
37 #include "extensions/common/permissions/permission_message.h"
38 #include "extensions/common/permissions/permissions_info.h"
39 #include "extensions/common/url_pattern.h"
40 #include "extensions/common/url_pattern_set.h"
41 #include "extensions/grit/extensions_resources.h"
42 #include "ui/base/l10n/l10n_util.h"
43 #include "url/gurl.h"
44
45 namespace extensions {
46
47 namespace {
48
49 // TODO(battre): Delete the HTTP URL once the blacklist is downloaded via HTTPS.
50 const char kExtensionBlocklistUrlPrefix[] =
51     "http://www.gstatic.com/chrome/extensions/blacklist";
52 const char kExtensionBlocklistHttpsUrlPrefix[] =
53     "https://www.gstatic.com/chrome/extensions/blacklist";
54
55 const char kThumbsWhiteListedExtension[] = "khopmbdjffemhegeeobelklnbglcdgfh";
56
57 template <class FeatureClass>
58 SimpleFeature* CreateFeature() {
59   SimpleFeature* feature = new FeatureClass;
60   feature->AddFilter(
61       scoped_ptr<SimpleFeatureFilter>(new ChromeChannelFeatureFilter(feature)));
62   return feature;
63 }
64
65 }  // namespace
66
67 static base::LazyInstance<ChromeExtensionsClient> g_client =
68     LAZY_INSTANCE_INITIALIZER;
69
70 ChromeExtensionsClient::ChromeExtensionsClient()
71     : chrome_api_permissions_(ChromeAPIPermissions()),
72       extensions_api_permissions_(ExtensionsAPIPermissions()) {
73 }
74
75 ChromeExtensionsClient::~ChromeExtensionsClient() {
76 }
77
78 void ChromeExtensionsClient::Initialize() {
79   // Registration could already be finalized in unit tests, where the utility
80   // thread runs in-process.
81   if (!ManifestHandler::IsRegistrationFinalized()) {
82     RegisterCommonManifestHandlers();
83     RegisterChromeManifestHandlers();
84     ManifestHandler::FinalizeRegistration();
85   }
86
87   // Set up permissions.
88   PermissionsInfo::GetInstance()->AddProvider(chrome_api_permissions_);
89   PermissionsInfo::GetInstance()->AddProvider(extensions_api_permissions_);
90
91   // Set up the scripting whitelist.
92   // Whitelist ChromeVox, an accessibility extension from Google that needs
93   // the ability to script webui pages. This is temporary and is not
94   // meant to be a general solution.
95   // TODO(dmazzoni): remove this once we have an extension API that
96   // allows any extension to request read-only access to webui pages.
97   scripting_whitelist_.push_back(extension_misc::kChromeVoxExtensionId);
98
99   // Whitelist "Discover DevTools Companion" extension from Google that
100   // needs the ability to script DevTools pages. Companion will assist
101   // online courses and will be needed while the online educational programs
102   // are in place.
103   scripting_whitelist_.push_back("angkfkebojeancgemegoedelbnjgcgme");
104 }
105
106 const PermissionMessageProvider&
107 ChromeExtensionsClient::GetPermissionMessageProvider() const {
108   return permission_message_provider_;
109 }
110
111 const std::string ChromeExtensionsClient::GetProductName() {
112   return l10n_util::GetStringUTF8(IDS_PRODUCT_NAME);
113 }
114
115 scoped_ptr<FeatureProvider> ChromeExtensionsClient::CreateFeatureProvider(
116     const std::string& name) const {
117   scoped_ptr<FeatureProvider> provider;
118   scoped_ptr<JSONFeatureProviderSource> source(
119       CreateFeatureProviderSource(name));
120   if (name == "api") {
121     provider.reset(new BaseFeatureProvider(source->dictionary(),
122                                            CreateFeature<APIFeature>));
123   } else if (name == "manifest") {
124     provider.reset(new BaseFeatureProvider(source->dictionary(),
125                                            CreateFeature<ManifestFeature>));
126   } else if (name == "permission") {
127     provider.reset(new BaseFeatureProvider(source->dictionary(),
128                                            CreateFeature<PermissionFeature>));
129   } else {
130     NOTREACHED();
131   }
132   return provider.Pass();
133 }
134
135 scoped_ptr<JSONFeatureProviderSource>
136 ChromeExtensionsClient::CreateFeatureProviderSource(
137     const std::string& name) const {
138   scoped_ptr<JSONFeatureProviderSource> source(
139       new JSONFeatureProviderSource(name));
140   if (name == "api") {
141     source->LoadJSON(IDR_EXTENSION_API_FEATURES);
142     source->LoadJSON(IDR_CHROME_EXTENSION_API_FEATURES);
143   } else if (name == "manifest") {
144     source->LoadJSON(IDR_EXTENSION_MANIFEST_FEATURES);
145     source->LoadJSON(IDR_CHROME_EXTENSION_MANIFEST_FEATURES);
146   } else if (name == "permission") {
147     source->LoadJSON(IDR_EXTENSION_PERMISSION_FEATURES);
148     source->LoadJSON(IDR_CHROME_EXTENSION_PERMISSION_FEATURES);
149   } else {
150     NOTREACHED();
151     source.reset();
152   }
153   return source.Pass();
154 }
155
156 void ChromeExtensionsClient::FilterHostPermissions(
157     const URLPatternSet& hosts,
158     URLPatternSet* new_hosts,
159     std::set<PermissionMessage>* messages) const {
160   for (URLPatternSet::const_iterator i = hosts.begin();
161        i != hosts.end(); ++i) {
162     // Filters out every URL pattern that matches chrome:// scheme.
163     if (i->scheme() == content::kChromeUIScheme) {
164       // chrome://favicon is the only URL for chrome:// scheme that we
165       // want to support. We want to deprecate the "chrome" scheme.
166       // We should not add any additional "host" here.
167       if (GURL(chrome::kChromeUIFaviconURL).host() != i->host())
168         continue;
169       messages->insert(PermissionMessage(
170           PermissionMessage::kFavicon,
171           l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_FAVICON)));
172     } else {
173       new_hosts->AddPattern(*i);
174     }
175   }
176 }
177
178 void ChromeExtensionsClient::SetScriptingWhitelist(
179     const ExtensionsClient::ScriptingWhitelist& whitelist) {
180   scripting_whitelist_ = whitelist;
181 }
182
183 const ExtensionsClient::ScriptingWhitelist&
184 ChromeExtensionsClient::GetScriptingWhitelist() const {
185   return scripting_whitelist_;
186 }
187
188 URLPatternSet ChromeExtensionsClient::GetPermittedChromeSchemeHosts(
189       const Extension* extension,
190       const APIPermissionSet& api_permissions) const {
191   URLPatternSet hosts;
192   // Regular extensions are only allowed access to chrome://favicon.
193   hosts.AddPattern(URLPattern(URLPattern::SCHEME_CHROMEUI,
194                               chrome::kChromeUIFaviconURL));
195
196   // Experimental extensions are also allowed chrome://thumb.
197   //
198   // TODO: A public API should be created for retrieving thumbnails.
199   // See http://crbug.com/222856. A temporary hack is implemented here to
200   // make chrome://thumbs available to NTP Russia extension as
201   // non-experimental.
202   if ((api_permissions.find(APIPermission::kExperimental) !=
203        api_permissions.end()) ||
204       (extension->id() == kThumbsWhiteListedExtension &&
205        extension->from_webstore())) {
206     hosts.AddPattern(URLPattern(URLPattern::SCHEME_CHROMEUI,
207                                 chrome::kChromeUIThumbnailURL));
208   }
209   return hosts;
210 }
211
212 bool ChromeExtensionsClient::IsScriptableURL(
213     const GURL& url, std::string* error) const {
214   // The gallery is special-cased as a restricted URL for scripting to prevent
215   // access to special JS bindings we expose to the gallery (and avoid things
216   // like extensions removing the "report abuse" link).
217   // TODO(erikkay): This seems like the wrong test.  Shouldn't we we testing
218   // against the store app extent?
219   GURL store_url(extension_urls::GetWebstoreLaunchURL());
220   if (url.host() == store_url.host()) {
221     if (error)
222       *error = manifest_errors::kCannotScriptGallery;
223     return false;
224   }
225   return true;
226 }
227
228 bool ChromeExtensionsClient::IsAPISchemaGenerated(
229     const std::string& name) const {
230   // Test from most common to least common.
231   return api::GeneratedSchemas::IsGenerated(name) ||
232          core_api::GeneratedSchemas::IsGenerated(name);
233 }
234
235 base::StringPiece ChromeExtensionsClient::GetAPISchema(
236     const std::string& name) const {
237   // Test from most common to least common.
238   if (api::GeneratedSchemas::IsGenerated(name))
239     return api::GeneratedSchemas::Get(name);
240
241   return core_api::GeneratedSchemas::Get(name);
242 }
243
244 void ChromeExtensionsClient::RegisterAPISchemaResources(
245     ExtensionAPI* api) const {
246   api->RegisterSchemaResource("accessibilityPrivate",
247                               IDR_EXTENSION_API_JSON_ACCESSIBILITYPRIVATE);
248   api->RegisterSchemaResource("app", IDR_EXTENSION_API_JSON_APP);
249   api->RegisterSchemaResource("browserAction",
250                               IDR_EXTENSION_API_JSON_BROWSERACTION);
251   api->RegisterSchemaResource("commands", IDR_EXTENSION_API_JSON_COMMANDS);
252   api->RegisterSchemaResource("declarativeContent",
253                               IDR_EXTENSION_API_JSON_DECLARATIVE_CONTENT);
254   api->RegisterSchemaResource("fileBrowserHandler",
255                               IDR_EXTENSION_API_JSON_FILEBROWSERHANDLER);
256   api->RegisterSchemaResource("inputMethodPrivate",
257                               IDR_EXTENSION_API_JSON_INPUTMETHODPRIVATE);
258   api->RegisterSchemaResource("pageAction", IDR_EXTENSION_API_JSON_PAGEACTION);
259   api->RegisterSchemaResource("privacy", IDR_EXTENSION_API_JSON_PRIVACY);
260   api->RegisterSchemaResource("processes", IDR_EXTENSION_API_JSON_PROCESSES);
261   api->RegisterSchemaResource("proxy", IDR_EXTENSION_API_JSON_PROXY);
262   api->RegisterSchemaResource("scriptBadge",
263                               IDR_EXTENSION_API_JSON_SCRIPTBADGE);
264   api->RegisterSchemaResource("ttsEngine", IDR_EXTENSION_API_JSON_TTSENGINE);
265   api->RegisterSchemaResource("tts", IDR_EXTENSION_API_JSON_TTS);
266   api->RegisterSchemaResource("types", IDR_EXTENSION_API_JSON_TYPES);
267   api->RegisterSchemaResource("types.private",
268                               IDR_EXTENSION_API_JSON_TYPES_PRIVATE);
269   api->RegisterSchemaResource("webstore", IDR_EXTENSION_API_JSON_WEBSTORE);
270 }
271
272 bool ChromeExtensionsClient::ShouldSuppressFatalErrors() const {
273   // Suppress fatal errors only on beta and stable channels.
274   return GetCurrentChannel() > chrome::VersionInfo::CHANNEL_DEV;
275 }
276
277 std::string ChromeExtensionsClient::GetWebstoreBaseURL() const {
278   std::string gallery_prefix = extension_urls::kChromeWebstoreBaseURL;
279   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAppsGalleryURL))
280     gallery_prefix = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
281         switches::kAppsGalleryURL);
282   if (EndsWith(gallery_prefix, "/", true))
283     gallery_prefix = gallery_prefix.substr(0, gallery_prefix.length() - 1);
284   return gallery_prefix;
285 }
286
287 std::string ChromeExtensionsClient::GetWebstoreUpdateURL() const {
288   CommandLine* cmdline = CommandLine::ForCurrentProcess();
289   if (cmdline->HasSwitch(switches::kAppsGalleryUpdateURL))
290     return cmdline->GetSwitchValueASCII(switches::kAppsGalleryUpdateURL);
291   else
292     return extension_urls::GetDefaultWebstoreUpdateUrl().spec();
293 }
294
295 bool ChromeExtensionsClient::IsBlacklistUpdateURL(const GURL& url) const {
296   // The extension blacklist URL is returned from the update service and
297   // therefore not determined by Chromium. If the location of the blacklist file
298   // ever changes, we need to update this function. A DCHECK in the
299   // ExtensionUpdater ensures that we notice a change. This is the full URL
300   // of a blacklist:
301   // http://www.gstatic.com/chrome/extensions/blacklist/l_0_0_0_7.txt
302   return StartsWithASCII(url.spec(), kExtensionBlocklistUrlPrefix, true) ||
303          StartsWithASCII(url.spec(), kExtensionBlocklistHttpsUrlPrefix, true);
304 }
305
306 // static
307 ChromeExtensionsClient* ChromeExtensionsClient::GetInstance() {
308   return g_client.Pointer();
309 }
310
311 }  // namespace extensions