1 // Copyright (c) 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 "extensions/common/permissions/permissions_data.h"
6
7 #include "base/command_line.h"
8 #include "content/public/common/url_constants.h"
9 #include "extensions/common/constants.h"
10 #include "extensions/common/error_utils.h"
11 #include "extensions/common/extensions_client.h"
12 #include "extensions/common/manifest.h"
13 #include "extensions/common/manifest_constants.h"
14 #include "extensions/common/manifest_handlers/permissions_parser.h"
15 #include "extensions/common/permissions/permission_message_provider.h"
16 #include "extensions/common/switches.h"
17 #include "extensions/common/url_pattern_set.h"
18 #include "extensions/common/user_script.h"
19 #include "url/gurl.h"
20 #include "url/url_constants.h"
21
22 namespace extensions {
23
24 namespace {
25
26 PermissionsData::PolicyDelegate* g_policy_delegate = NULL;
27
28 } // namespace
29
PermissionsData(const Extension * extension)30 PermissionsData::PermissionsData(const Extension* extension)
31 : extension_id_(extension->id()), manifest_type_(extension->GetType()) {
32 base::AutoLock auto_lock(runtime_lock_);
33 scoped_refptr<const PermissionSet> required_permissions =
34 PermissionsParser::GetRequiredPermissions(extension);
35 active_permissions_unsafe_ =
36 new PermissionSet(required_permissions->apis(),
37 required_permissions->manifest_permissions(),
38 required_permissions->explicit_hosts(),
39 required_permissions->scriptable_hosts());
40 }
41
~PermissionsData()42 PermissionsData::~PermissionsData() {
43 }
44
45 // static
SetPolicyDelegate(PolicyDelegate * delegate)46 void PermissionsData::SetPolicyDelegate(PolicyDelegate* delegate) {
47 g_policy_delegate = delegate;
48 }
49
50 // static
CanSilentlyIncreasePermissions(const Extension * extension)51 bool PermissionsData::CanSilentlyIncreasePermissions(
52 const Extension* extension) {
53 return extension->location() != Manifest::INTERNAL;
54 }
55
56 // static
CanExecuteScriptEverywhere(const Extension * extension)57 bool PermissionsData::CanExecuteScriptEverywhere(const Extension* extension) {
58 if (extension->location() == Manifest::COMPONENT)
59 return true;
60
61 const ExtensionsClient::ScriptingWhitelist& whitelist =
62 ExtensionsClient::Get()->GetScriptingWhitelist();
63
64 return std::find(whitelist.begin(), whitelist.end(), extension->id()) !=
65 whitelist.end();
66 }
67
ShouldSkipPermissionWarnings(const std::string & extension_id)68 bool PermissionsData::ShouldSkipPermissionWarnings(
69 const std::string& extension_id) {
70 // See http://b/4946060 for more details.
71 return extension_id == std::string("nckgahadagoaajjgafhacjanaoiihapd");
72 }
73
74 // static
IsRestrictedUrl(const GURL & document_url,const GURL & top_frame_url,const Extension * extension,std::string * error)75 bool PermissionsData::IsRestrictedUrl(const GURL& document_url,
76 const GURL& top_frame_url,
77 const Extension* extension,
78 std::string* error) {
79 if (CanExecuteScriptEverywhere(extension))
80 return false;
81
82 // Check if the scheme is valid for extensions. If not, return.
83 if (!URLPattern::IsValidSchemeForExtensions(document_url.scheme()) &&
84 document_url.spec() != url::kAboutBlankURL) {
85 if (error) {
86 *error = ErrorUtils::FormatErrorMessage(
87 manifest_errors::kCannotAccessPage,
88 document_url.spec());
89 }
90 return true;
91 }
92
93 if (!ExtensionsClient::Get()->IsScriptableURL(document_url, error))
94 return true;
95
96 bool allow_on_chrome_urls = base::CommandLine::ForCurrentProcess()->HasSwitch(
97 switches::kExtensionsOnChromeURLs);
98 if (document_url.SchemeIs(content::kChromeUIScheme) &&
99 !allow_on_chrome_urls) {
100 if (error)
101 *error = manifest_errors::kCannotAccessChromeUrl;
102 return true;
103 }
104
105 if (top_frame_url.SchemeIs(kExtensionScheme) &&
106 top_frame_url.host() != extension->id() &&
107 !allow_on_chrome_urls) {
108 if (error)
109 *error = manifest_errors::kCannotAccessExtensionUrl;
110 return true;
111 }
112
113 return false;
114 }
115
SetActivePermissions(const PermissionSet * permissions) const116 void PermissionsData::SetActivePermissions(
117 const PermissionSet* permissions) const {
118 base::AutoLock auto_lock(runtime_lock_);
119 active_permissions_unsafe_ = permissions;
120 }
121
UpdateTabSpecificPermissions(int tab_id,scoped_refptr<const PermissionSet> permissions) const122 void PermissionsData::UpdateTabSpecificPermissions(
123 int tab_id,
124 scoped_refptr<const PermissionSet> permissions) const {
125 base::AutoLock auto_lock(runtime_lock_);
126 CHECK_GE(tab_id, 0);
127 TabPermissionsMap::iterator iter = tab_specific_permissions_.find(tab_id);
128 if (iter == tab_specific_permissions_.end())
129 tab_specific_permissions_[tab_id] = permissions;
130 else
131 iter->second = PermissionSet::CreateUnion(iter->second, permissions);
132 }
133
ClearTabSpecificPermissions(int tab_id) const134 void PermissionsData::ClearTabSpecificPermissions(int tab_id) const {
135 base::AutoLock auto_lock(runtime_lock_);
136 CHECK_GE(tab_id, 0);
137 tab_specific_permissions_.erase(tab_id);
138 }
139
HasAPIPermission(APIPermission::ID permission) const140 bool PermissionsData::HasAPIPermission(APIPermission::ID permission) const {
141 return active_permissions()->HasAPIPermission(permission);
142 }
143
HasAPIPermission(const std::string & permission_name) const144 bool PermissionsData::HasAPIPermission(
145 const std::string& permission_name) const {
146 return active_permissions()->HasAPIPermission(permission_name);
147 }
148
HasAPIPermissionForTab(int tab_id,APIPermission::ID permission) const149 bool PermissionsData::HasAPIPermissionForTab(
150 int tab_id,
151 APIPermission::ID permission) const {
152 if (HasAPIPermission(permission))
153 return true;
154
155 scoped_refptr<const PermissionSet> tab_permissions =
156 GetTabSpecificPermissions(tab_id);
157
158 // Place autolock below the HasAPIPermission() and
159 // GetTabSpecificPermissions(), since each already acquires the lock.
160 base::AutoLock auto_lock(runtime_lock_);
161 return tab_permissions.get() && tab_permissions->HasAPIPermission(permission);
162 }
163
CheckAPIPermissionWithParam(APIPermission::ID permission,const APIPermission::CheckParam * param) const164 bool PermissionsData::CheckAPIPermissionWithParam(
165 APIPermission::ID permission,
166 const APIPermission::CheckParam* param) const {
167 return active_permissions()->CheckAPIPermissionWithParam(permission, param);
168 }
169
GetEffectiveHostPermissions() const170 const URLPatternSet& PermissionsData::GetEffectiveHostPermissions() const {
171 return active_permissions()->effective_hosts();
172 }
173
HasHostPermission(const GURL & url) const174 bool PermissionsData::HasHostPermission(const GURL& url) const {
175 return active_permissions()->HasExplicitAccessToOrigin(url);
176 }
177
HasEffectiveAccessToAllHosts() const178 bool PermissionsData::HasEffectiveAccessToAllHosts() const {
179 return active_permissions()->HasEffectiveAccessToAllHosts();
180 }
181
GetPermissionMessages() const182 PermissionMessages PermissionsData::GetPermissionMessages() const {
183 if (ShouldSkipPermissionWarnings(extension_id_)) {
184 return PermissionMessages();
185 } else {
186 return PermissionMessageProvider::Get()->GetPermissionMessages(
187 active_permissions(), manifest_type_);
188 }
189 }
190
GetPermissionMessageStrings() const191 std::vector<base::string16> PermissionsData::GetPermissionMessageStrings()
192 const {
193 if (ShouldSkipPermissionWarnings(extension_id_))
194 return std::vector<base::string16>();
195 return PermissionMessageProvider::Get()->GetWarningMessages(
196 active_permissions(), manifest_type_);
197 }
198
199 std::vector<base::string16>
GetPermissionMessageDetailsStrings() const200 PermissionsData::GetPermissionMessageDetailsStrings() const {
201 if (ShouldSkipPermissionWarnings(extension_id_))
202 return std::vector<base::string16>();
203 return PermissionMessageProvider::Get()->GetWarningMessagesDetails(
204 active_permissions(), manifest_type_);
205 }
206
CanAccessPage(const Extension * extension,const GURL & document_url,const GURL & top_frame_url,int tab_id,int process_id,std::string * error) const207 bool PermissionsData::CanAccessPage(const Extension* extension,
208 const GURL& document_url,
209 const GURL& top_frame_url,
210 int tab_id,
211 int process_id,
212 std::string* error) const {
213 return CanRunOnPage(extension,
214 document_url,
215 top_frame_url,
216 tab_id,
217 process_id,
218 active_permissions()->explicit_hosts(),
219 error);
220 }
221
CanRunContentScriptOnPage(const Extension * extension,const GURL & document_url,const GURL & top_frame_url,int tab_id,int process_id,std::string * error) const222 bool PermissionsData::CanRunContentScriptOnPage(const Extension* extension,
223 const GURL& document_url,
224 const GURL& top_frame_url,
225 int tab_id,
226 int process_id,
227 std::string* error) const {
228 return CanRunOnPage(extension,
229 document_url,
230 top_frame_url,
231 tab_id,
232 process_id,
233 active_permissions()->scriptable_hosts(),
234 error);
235 }
236
CanCaptureVisiblePage(int tab_id,std::string * error) const237 bool PermissionsData::CanCaptureVisiblePage(int tab_id,
238 std::string* error) const {
239 const URLPattern all_urls(URLPattern::SCHEME_ALL,
240 URLPattern::kAllUrlsPattern);
241
242 if (active_permissions()->explicit_hosts().ContainsPattern(all_urls))
243 return true;
244
245 if (tab_id >= 0) {
246 scoped_refptr<const PermissionSet> tab_permissions =
247 GetTabSpecificPermissions(tab_id);
248 if (tab_permissions &&
249 tab_permissions->HasAPIPermission(APIPermission::kTab)) {
250 return true;
251 }
252 if (error)
253 *error = manifest_errors::kActiveTabPermissionNotGranted;
254 return false;
255 }
256
257 if (error)
258 *error = manifest_errors::kAllURLOrActiveTabNeeded;
259 return false;
260 }
261
262 // static
RequiresActionForScriptExecution(const Extension * extension) const263 bool PermissionsData::RequiresActionForScriptExecution(
264 const Extension* extension) const {
265 return RequiresActionForScriptExecution(extension, -1, GURL());
266 }
267
268 // static
RequiresActionForScriptExecution(const Extension * extension,int tab_id,const GURL & url) const269 bool PermissionsData::RequiresActionForScriptExecution(
270 const Extension* extension,
271 int tab_id,
272 const GURL& url) const {
273 // For now, the user should be notified when an extension with all hosts
274 // permission tries to execute a script on a page. Exceptions for policy-
275 // enabled and component extensions, and extensions which are whitelisted to
276 // execute scripts everywhere.
277 if (!extension->ShouldDisplayInExtensionSettings() ||
278 Manifest::IsPolicyLocation(extension->location()) ||
279 Manifest::IsComponentLocation(extension->location()) ||
280 CanExecuteScriptEverywhere(extension) ||
281 !active_permissions()->ShouldWarnAllHosts()) {
282 return false;
283 }
284
285 // If the extension has explicit permission to run on the given tab, then
286 // we don't need to alert the user.
287 if (HasTabSpecificPermissionToExecuteScript(tab_id, url))
288 return false;
289
290 return true;
291 }
292
GetTabSpecificPermissions(int tab_id) const293 scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions(
294 int tab_id) const {
295 base::AutoLock auto_lock(runtime_lock_);
296 CHECK_GE(tab_id, 0);
297 TabPermissionsMap::const_iterator iter =
298 tab_specific_permissions_.find(tab_id);
299 return (iter != tab_specific_permissions_.end()) ? iter->second : NULL;
300 }
301
HasTabSpecificPermissionToExecuteScript(int tab_id,const GURL & url) const302 bool PermissionsData::HasTabSpecificPermissionToExecuteScript(
303 int tab_id,
304 const GURL& url) const {
305 if (tab_id >= 0) {
306 scoped_refptr<const PermissionSet> tab_permissions =
307 GetTabSpecificPermissions(tab_id);
308 if (tab_permissions.get() &&
309 tab_permissions->explicit_hosts().MatchesSecurityOrigin(url)) {
310 return true;
311 }
312 }
313 return false;
314 }
315
CanRunOnPage(const Extension * extension,const GURL & document_url,const GURL & top_frame_url,int tab_id,int process_id,const URLPatternSet & permitted_url_patterns,std::string * error) const316 bool PermissionsData::CanRunOnPage(const Extension* extension,
317 const GURL& document_url,
318 const GURL& top_frame_url,
319 int tab_id,
320 int process_id,
321 const URLPatternSet& permitted_url_patterns,
322 std::string* error) const {
323 if (g_policy_delegate &&
324 !g_policy_delegate->CanExecuteScriptOnPage(
325 extension, document_url, top_frame_url, tab_id, process_id, error)) {
326 return false;
327 }
328
329 if (IsRestrictedUrl(document_url, top_frame_url, extension, error))
330 return false;
331
332 if (HasTabSpecificPermissionToExecuteScript(tab_id, top_frame_url))
333 return true;
334
335 bool can_access = permitted_url_patterns.MatchesURL(document_url);
336
337 if (!can_access && error) {
338 *error = ErrorUtils::FormatErrorMessage(manifest_errors::kCannotAccessPage,
339 document_url.spec());
340 }
341
342 return can_access;
343 }
344
345 } // namespace extensions
346