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 "chrome/common/extensions/chrome_manifest_handlers.h"
9 #include "chrome/common/extensions/extension_constants.h"
10 #include "chrome/common/extensions/features/base_feature_provider.h"
11 #include "chrome/common/url_constants.h"
12 #include "content/public/common/url_constants.h"
13 #include "extensions/common/extension.h"
14 #include "extensions/common/manifest_constants.h"
15 #include "extensions/common/permissions/api_permission_set.h"
16 #include "extensions/common/permissions/permission_message.h"
17 #include "extensions/common/switches.h"
18 #include "extensions/common/url_pattern.h"
19 #include "extensions/common/url_pattern_set.h"
20 #include "grit/generated_resources.h"
21 #include "ui/base/l10n/l10n_util.h"
22 #include "url/gurl.h"
23
24 namespace {
25 const char kThumbsWhiteListedExtension[] = "khopmbdjffemhegeeobelklnbglcdgfh";
26 } // namespace
27
28 namespace extensions {
29
30 static base::LazyInstance<ChromeExtensionsClient> g_client =
31 LAZY_INSTANCE_INITIALIZER;
32
ChromeExtensionsClient()33 ChromeExtensionsClient::ChromeExtensionsClient()
34 : chrome_api_permissions_(ChromeAPIPermissions()) {
35 }
36
~ChromeExtensionsClient()37 ChromeExtensionsClient::~ChromeExtensionsClient() {
38 }
39
Initialize()40 void ChromeExtensionsClient::Initialize() {
41 RegisterChromeManifestHandlers();
42
43 // Set up the scripting whitelist.
44 // Whitelist ChromeVox, an accessibility extension from Google that needs
45 // the ability to script webui pages. This is temporary and is not
46 // meant to be a general solution.
47 // TODO(dmazzoni): remove this once we have an extension API that
48 // allows any extension to request read-only access to webui pages.
49 scripting_whitelist_.push_back(extension_misc::kChromeVoxExtensionId);
50
51 // Whitelist "Discover DevTools Companion" extension from Google that
52 // needs the ability to script DevTools pages. Companion will assist
53 // online courses and will be needed while the online educational programs
54 // are in place.
55 scripting_whitelist_.push_back("angkfkebojeancgemegoedelbnjgcgme");
56 }
57
58 const PermissionsProvider&
GetPermissionsProvider() const59 ChromeExtensionsClient::GetPermissionsProvider() const {
60 return chrome_api_permissions_;
61 }
62
63 const PermissionMessageProvider&
GetPermissionMessageProvider() const64 ChromeExtensionsClient::GetPermissionMessageProvider() const {
65 return permission_message_provider_;
66 }
67
GetFeatureProviderByName(const std::string & name) const68 FeatureProvider* ChromeExtensionsClient::GetFeatureProviderByName(
69 const std::string& name) const {
70 return BaseFeatureProvider::GetByName(name);
71 }
72
FilterHostPermissions(const URLPatternSet & hosts,URLPatternSet * new_hosts,std::set<PermissionMessage> * messages) const73 void ChromeExtensionsClient::FilterHostPermissions(
74 const URLPatternSet& hosts,
75 URLPatternSet* new_hosts,
76 std::set<PermissionMessage>* messages) const {
77 for (URLPatternSet::const_iterator i = hosts.begin();
78 i != hosts.end(); ++i) {
79 // Filters out every URL pattern that matches chrome:// scheme.
80 if (i->scheme() == chrome::kChromeUIScheme) {
81 // chrome://favicon is the only URL for chrome:// scheme that we
82 // want to support. We want to deprecate the "chrome" scheme.
83 // We should not add any additional "host" here.
84 if (GURL(chrome::kChromeUIFaviconURL).host() != i->host())
85 continue;
86 messages->insert(PermissionMessage(
87 PermissionMessage::kFavicon,
88 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_FAVICON)));
89 } else {
90 new_hosts->AddPattern(*i);
91 }
92 }
93 }
94
SetScriptingWhitelist(const ExtensionsClient::ScriptingWhitelist & whitelist)95 void ChromeExtensionsClient::SetScriptingWhitelist(
96 const ExtensionsClient::ScriptingWhitelist& whitelist) {
97 scripting_whitelist_ = whitelist;
98 }
99
100 const ExtensionsClient::ScriptingWhitelist&
GetScriptingWhitelist() const101 ChromeExtensionsClient::GetScriptingWhitelist() const {
102 return scripting_whitelist_;
103 }
104
GetPermittedChromeSchemeHosts(const Extension * extension,const APIPermissionSet & api_permissions) const105 URLPatternSet ChromeExtensionsClient::GetPermittedChromeSchemeHosts(
106 const Extension* extension,
107 const APIPermissionSet& api_permissions) const {
108 URLPatternSet hosts;
109 // Regular extensions are only allowed access to chrome://favicon.
110 hosts.AddPattern(URLPattern(URLPattern::SCHEME_CHROMEUI,
111 chrome::kChromeUIFaviconURL));
112
113 // Experimental extensions are also allowed chrome://thumb.
114 //
115 // TODO: A public API should be created for retrieving thumbnails.
116 // See http://crbug.com/222856. A temporary hack is implemented here to
117 // make chrome://thumbs available to NTP Russia extension as
118 // non-experimental.
119 if ((api_permissions.find(APIPermission::kExperimental) !=
120 api_permissions.end()) ||
121 (extension->id() == kThumbsWhiteListedExtension &&
122 extension->from_webstore())) {
123 hosts.AddPattern(URLPattern(URLPattern::SCHEME_CHROMEUI,
124 chrome::kChromeUIThumbnailURL));
125 }
126 return hosts;
127 }
128
IsScriptableURL(const GURL & url,std::string * error) const129 bool ChromeExtensionsClient::IsScriptableURL(
130 const GURL& url, std::string* error) const {
131 // The gallery is special-cased as a restricted URL for scripting to prevent
132 // access to special JS bindings we expose to the gallery (and avoid things
133 // like extensions removing the "report abuse" link).
134 // TODO(erikkay): This seems like the wrong test. Shouldn't we we testing
135 // against the store app extent?
136 GURL store_url(extension_urls::GetWebstoreLaunchURL());
137 if (CommandLine::ForCurrentProcess()->HasSwitch(
138 switches::kAllowScriptingGallery)) {
139 return true;
140 }
141 if (url.host() == store_url.host()) {
142 if (error)
143 *error = manifest_errors::kCannotScriptGallery;
144 return false;
145 }
146 return true;
147 }
148
149 // static
GetInstance()150 ChromeExtensionsClient* ChromeExtensionsClient::GetInstance() {
151 return g_client.Pointer();
152 }
153
154 } // namespace extensions
155