Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(280)

Side by Side Diff: extensions/common/permissions/permissions_data.cc

Issue 348313003: Create withheld permissions (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Test fix Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/common/permissions/permissions_data.h" 5 #include "extensions/common/permissions/permissions_data.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "content/public/common/url_constants.h" 8 #include "content/public/common/url_constants.h"
9 #include "extensions/common/constants.h" 9 #include "extensions/common/constants.h"
10 #include "extensions/common/error_utils.h" 10 #include "extensions/common/error_utils.h"
11 #include "extensions/common/extensions_client.h" 11 #include "extensions/common/extensions_client.h"
12 #include "extensions/common/feature_switch.h"
12 #include "extensions/common/manifest.h" 13 #include "extensions/common/manifest.h"
13 #include "extensions/common/manifest_constants.h" 14 #include "extensions/common/manifest_constants.h"
14 #include "extensions/common/manifest_handlers/permissions_parser.h" 15 #include "extensions/common/manifest_handlers/permissions_parser.h"
15 #include "extensions/common/permissions/permission_message_provider.h" 16 #include "extensions/common/permissions/permission_message_provider.h"
16 #include "extensions/common/switches.h" 17 #include "extensions/common/switches.h"
17 #include "extensions/common/url_pattern_set.h" 18 #include "extensions/common/url_pattern_set.h"
18 #include "extensions/common/user_script.h" 19 #include "extensions/common/user_script.h"
19 #include "url/gurl.h" 20 #include "url/gurl.h"
20 #include "url/url_constants.h" 21 #include "url/url_constants.h"
21 22
22 namespace extensions { 23 namespace extensions {
23 24
24 namespace { 25 namespace {
25 26
26 PermissionsData::PolicyDelegate* g_policy_delegate = NULL; 27 PermissionsData::PolicyDelegate* g_policy_delegate = NULL;
27 28
28 // Returns true if this extension id is from a trusted provider. 29 // Returns true if this extension id is from a trusted provider.
29 bool ShouldSkipPermissionWarnings(const std::string& extension_id) { 30 bool ShouldSkipPermissionWarnings(const std::string& extension_id) {
30 // See http://b/4946060 for more details. 31 // See http://b/4946060 for more details.
31 return extension_id == std::string("nckgahadagoaajjgafhacjanaoiihapd"); 32 return extension_id == std::string("nckgahadagoaajjgafhacjanaoiihapd");
32 } 33 }
33 34
35 // Divvy up the |url patterns| between those we grant and those we do not. If
36 // |withhold_permissions| is false (because the requisite feature is not
37 // enabled), no permissions are withheld.
38 void SegregateUrlPermissions(const URLPatternSet& url_patterns,
39 bool withhold_permissions,
40 URLPatternSet* granted,
41 URLPatternSet* withheld) {
42 for (URLPatternSet::const_iterator iter = url_patterns.begin();
43 iter != url_patterns.end();
44 ++iter) {
45 if (withhold_permissions && iter->ImpliesAllHosts())
46 withheld->AddPattern(*iter);
47 else
48 granted->AddPattern(*iter);
49 }
50 }
51
34 } // namespace 52 } // namespace
35 53
36 PermissionsData::PermissionsData(const Extension* extension) 54 PermissionsData::PermissionsData(const Extension* extension)
37 : extension_id_(extension->id()), manifest_type_(extension->GetType()) { 55 : extension_id_(extension->id()), manifest_type_(extension->GetType()) {
38 base::AutoLock auto_lock(runtime_lock_); 56 InitializePermissions(PermissionsParser::GetRequiredPermissions(extension),
39 scoped_refptr<const PermissionSet> required_permissions = 57 extension);
40 PermissionsParser::GetRequiredPermissions(extension);
41 active_permissions_unsafe_ =
42 new PermissionSet(required_permissions->apis(),
43 required_permissions->manifest_permissions(),
44 required_permissions->explicit_hosts(),
45 required_permissions->scriptable_hosts());
46 } 58 }
47 59
48 PermissionsData::~PermissionsData() { 60 PermissionsData::~PermissionsData() {
49 } 61 }
50 62
51 // static 63 // static
52 void PermissionsData::SetPolicyDelegate(PolicyDelegate* delegate) { 64 void PermissionsData::SetPolicyDelegate(PolicyDelegate* delegate) {
53 g_policy_delegate = delegate; 65 g_policy_delegate = delegate;
54 } 66 }
55 67
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 top_frame_url.host() != extension->id() && 118 top_frame_url.host() != extension->id() &&
107 !allow_on_chrome_urls) { 119 !allow_on_chrome_urls) {
108 if (error) 120 if (error)
109 *error = manifest_errors::kCannotAccessExtensionUrl; 121 *error = manifest_errors::kCannotAccessExtensionUrl;
110 return true; 122 return true;
111 } 123 }
112 124
113 return false; 125 return false;
114 } 126 }
115 127
116 void PermissionsData::SetActivePermissions( 128 void PermissionsData::InitializePermissions(const PermissionSet* permissions,
not at google - send to devlin 2014/06/27 23:24:34 you don't actually use |permissions| anywhere.
Devlin 2014/06/30 17:06:10 Whoops! Done.
117 const PermissionSet* permissions) const { 129 const Extension* extension) const {
118 base::AutoLock auto_lock(runtime_lock_); 130 base::AutoLock auto_lock(runtime_lock_);
119 active_permissions_unsafe_ = permissions; 131 scoped_refptr<const PermissionSet> required_permissions =
132 PermissionsParser::GetRequiredPermissions(extension);
133
134 // We withhold permissions iff the switch to do so is enabled, the extension
135 // shows up in chrome:extensions (so the user can grant withheld permissions),
136 // the extension is not part of chrome or corporate policy, and also not on
137 // the scripting whitelist.
138 bool withhold_permissions =
139 FeatureSwitch::scripts_require_action()->IsEnabled() &&
140 extension->ShouldDisplayInExtensionSettings() &&
141 !Manifest::IsPolicyLocation(extension->location()) &&
142 !Manifest::IsComponentLocation(extension->location()) &&
143 !CanExecuteScriptEverywhere(extension);
144
145 URLPatternSet granted_explicit_hosts;
146 URLPatternSet withheld_explicit_hosts;
147 SegregateUrlPermissions(required_permissions->explicit_hosts(),
148 withhold_permissions,
149 &granted_explicit_hosts,
150 &withheld_explicit_hosts);
151
152 URLPatternSet granted_scriptable_hosts;
153 URLPatternSet withheld_scriptable_hosts;
154 SegregateUrlPermissions(required_permissions->scriptable_hosts(),
155 withhold_permissions,
156 &granted_scriptable_hosts,
157 &withheld_scriptable_hosts);
158
159 active_permissions_unsafe_ =
160 new PermissionSet(required_permissions->apis(),
161 required_permissions->manifest_permissions(),
162 granted_explicit_hosts,
163 granted_scriptable_hosts);
164
165 withheld_permissions_unsafe_ = new PermissionSet(APIPermissionSet(),
166 ManifestPermissionSet(),
167 withheld_explicit_hosts,
168 withheld_scriptable_hosts);
169 }
170
171 void PermissionsData::SetPermissions(const PermissionSet* active,
172 const PermissionSet* withheld) const {
173 base::AutoLock auto_lock(runtime_lock_);
174 active_permissions_unsafe_ = active;
175 withheld_permissions_unsafe_ = withheld;
120 } 176 }
121 177
122 void PermissionsData::UpdateTabSpecificPermissions( 178 void PermissionsData::UpdateTabSpecificPermissions(
123 int tab_id, 179 int tab_id,
124 scoped_refptr<const PermissionSet> permissions) const { 180 scoped_refptr<const PermissionSet> permissions) const {
125 base::AutoLock auto_lock(runtime_lock_); 181 base::AutoLock auto_lock(runtime_lock_);
126 CHECK_GE(tab_id, 0); 182 CHECK_GE(tab_id, 0);
127 TabPermissionsMap::iterator iter = tab_specific_permissions_.find(tab_id); 183 TabPermissionsMap::iterator iter = tab_specific_permissions_.find(tab_id);
128 if (iter == tab_specific_permissions_.end()) 184 if (iter == tab_specific_permissions_.end())
129 tab_specific_permissions_[tab_id] = permissions; 185 tab_specific_permissions_[tab_id] = permissions;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 } 253 }
198 254
199 std::vector<base::string16> 255 std::vector<base::string16>
200 PermissionsData::GetPermissionMessageDetailsStrings() const { 256 PermissionsData::GetPermissionMessageDetailsStrings() const {
201 if (ShouldSkipPermissionWarnings(extension_id_)) 257 if (ShouldSkipPermissionWarnings(extension_id_))
202 return std::vector<base::string16>(); 258 return std::vector<base::string16>();
203 return PermissionMessageProvider::Get()->GetWarningMessagesDetails( 259 return PermissionMessageProvider::Get()->GetWarningMessagesDetails(
204 active_permissions(), manifest_type_); 260 active_permissions(), manifest_type_);
205 } 261 }
206 262
263 bool PermissionsData::HasWithheldAllHosts() const {
264 // Since we currently only withhold all_hosts, it's sufficient to check
265 // that either set is not empty.
266 return !withheld_permissions()->explicit_hosts().is_empty() ||
267 !withheld_permissions()->scriptable_hosts().is_empty();
268 }
269
270 void PermissionsData::WithholdAllHosts() const {
271 base::AutoLock auto_lock(runtime_lock_);
272
273 URLPatternSet withheld_scriptable =
274 withheld_permissions_unsafe_->scriptable_hosts();
275 URLPatternSet active_scriptable;
276 SegregateUrlPermissions(active_permissions_unsafe_->scriptable_hosts(),
277 true, // withhold permissions
278 &active_scriptable,
279 &withheld_scriptable);
280
281 URLPatternSet withheld_explicit =
282 withheld_permissions_unsafe_->explicit_hosts();
283 URLPatternSet active_explicit;
284 SegregateUrlPermissions(active_permissions_unsafe_->explicit_hosts(),
285 true, // withhold permissions
286 &active_explicit,
287 &withheld_explicit);
288
289 active_permissions_unsafe_ =
290 new PermissionSet(active_permissions_unsafe_->apis(),
291 active_permissions_unsafe_->manifest_permissions(),
292 active_explicit,
293 active_scriptable);
294 withheld_permissions_unsafe_ =
295 new PermissionSet(withheld_permissions_unsafe_->apis(),
296 withheld_permissions_unsafe_->manifest_permissions(),
297 withheld_explicit,
298 withheld_scriptable);
299 }
300
301 void PermissionsData::GrantWithheldAllHosts() const {
302 base::AutoLock auto_lock(runtime_lock_);
303
304 // Move the all-hosts permission from withheld to active.
305 // We can cheat a bit here since we know that the only host permission we
306 // withhold is allhosts (or something similar enough to it), so we can just
307 // grant all withheld host permissions.
308 URLPatternSet explicit_hosts;
309 URLPatternSet::CreateUnion(active_permissions_unsafe_->explicit_hosts(),
310 withheld_permissions_unsafe_->explicit_hosts(),
311 &explicit_hosts);
312 URLPatternSet scriptable_hosts;
313 URLPatternSet::CreateUnion(active_permissions_unsafe_->scriptable_hosts(),
314 withheld_permissions_unsafe_->scriptable_hosts(),
315 &scriptable_hosts);
316 scoped_refptr<const PermissionSet> new_active_permissions =
317 new PermissionSet(active_permissions_unsafe_->apis(),
318 active_permissions_unsafe_->manifest_permissions(),
319 explicit_hosts,
320 scriptable_hosts);
321
322 active_permissions_unsafe_ = new_active_permissions;
323 // Since we only withhold host permissions (so far), we know that withheld
324 // permissions will be empty.
325 withheld_permissions_unsafe_ = new PermissionSet();
326 }
327
207 bool PermissionsData::CanAccessPage(const Extension* extension, 328 bool PermissionsData::CanAccessPage(const Extension* extension,
208 const GURL& document_url, 329 const GURL& document_url,
209 const GURL& top_frame_url, 330 const GURL& top_frame_url,
210 int tab_id, 331 int tab_id,
211 int process_id, 332 int process_id,
212 std::string* error) const { 333 std::string* error) const {
334 AccessType result = CanRunOnPage(extension,
335 document_url,
336 top_frame_url,
337 tab_id,
338 process_id,
339 active_permissions()->explicit_hosts(),
340 withheld_permissions()->explicit_hosts(),
341 error);
342 // TODO(rdevlin.cronin) Update callers so that they only need ALLOW_ACCESS.
343 return result == ALLOW_ACCESS || result == REQUEST_ACCESS;
344 }
345
346 PermissionsData::AccessType PermissionsData::CanAccessPageWithUserConsent(
347 const Extension* extension,
348 const GURL& document_url,
349 const GURL& top_frame_url,
350 int tab_id,
351 int process_id,
352 std::string* error) const {
213 return CanRunOnPage(extension, 353 return CanRunOnPage(extension,
214 document_url, 354 document_url,
215 top_frame_url, 355 top_frame_url,
216 tab_id, 356 tab_id,
217 process_id, 357 process_id,
218 active_permissions()->explicit_hosts(), 358 active_permissions()->explicit_hosts(),
359 withheld_permissions()->explicit_hosts(),
219 error); 360 error);
220 } 361 }
221 362
222 bool PermissionsData::CanRunContentScriptOnPage(const Extension* extension, 363 bool PermissionsData::CanRunContentScriptOnPage(const Extension* extension,
223 const GURL& document_url, 364 const GURL& document_url,
224 const GURL& top_frame_url, 365 const GURL& top_frame_url,
225 int tab_id, 366 int tab_id,
226 int process_id, 367 int process_id,
227 std::string* error) const { 368 std::string* error) const {
369 AccessType result = CanRunOnPage(extension,
370 document_url,
371 top_frame_url,
372 tab_id,
373 process_id,
374 active_permissions()->scriptable_hosts(),
375 withheld_permissions()->scriptable_hosts(),
376 error);
377 // TODO(rdevlin.cronin) Update callers so that they only need ALLOW_ACCESS.
378 return result == ALLOW_ACCESS || result == REQUEST_ACCESS;
379 }
380
381 PermissionsData::AccessType
382 PermissionsData::CanRunContentScriptOnPageWithUserConsent(
383 const Extension* extension,
384 const GURL& document_url,
385 const GURL& top_frame_url,
386 int tab_id,
387 int process_id,
388 std::string* error) const {
228 return CanRunOnPage(extension, 389 return CanRunOnPage(extension,
229 document_url, 390 document_url,
230 top_frame_url, 391 top_frame_url,
231 tab_id, 392 tab_id,
232 process_id, 393 process_id,
233 active_permissions()->scriptable_hosts(), 394 active_permissions()->scriptable_hosts(),
395 withheld_permissions()->scriptable_hosts(),
234 error); 396 error);
235 } 397 }
236 398
237 bool PermissionsData::CanCaptureVisiblePage(int tab_id, 399 bool PermissionsData::CanCaptureVisiblePage(int tab_id,
238 std::string* error) const { 400 std::string* error) const {
239 const URLPattern all_urls(URLPattern::SCHEME_ALL, 401 const URLPattern all_urls(URLPattern::SCHEME_ALL,
240 URLPattern::kAllUrlsPattern); 402 URLPattern::kAllUrlsPattern);
241 403
242 if (active_permissions()->explicit_hosts().ContainsPattern(all_urls)) 404 if (active_permissions()->explicit_hosts().ContainsPattern(all_urls))
243 return true; 405 return true;
244 406
245 if (tab_id >= 0) { 407 if (tab_id >= 0) {
246 scoped_refptr<const PermissionSet> tab_permissions = 408 scoped_refptr<const PermissionSet> tab_permissions =
247 GetTabSpecificPermissions(tab_id); 409 GetTabSpecificPermissions(tab_id);
248 if (tab_permissions && 410 if (tab_permissions &&
249 tab_permissions->HasAPIPermission(APIPermission::kTab)) { 411 tab_permissions->HasAPIPermission(APIPermission::kTab)) {
250 return true; 412 return true;
251 } 413 }
252 if (error) 414 if (error)
253 *error = manifest_errors::kActiveTabPermissionNotGranted; 415 *error = manifest_errors::kActiveTabPermissionNotGranted;
254 return false; 416 return false;
255 } 417 }
256 418
257 if (error) 419 if (error)
258 *error = manifest_errors::kAllURLOrActiveTabNeeded; 420 *error = manifest_errors::kAllURLOrActiveTabNeeded;
259 return false; 421 return false;
260 } 422 }
261 423
262 // static
263 bool PermissionsData::RequiresActionForScriptExecution(
264 const Extension* extension) const {
265 return RequiresActionForScriptExecution(extension, -1, GURL());
266 }
267
268 // static
269 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
293 scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions( 424 scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions(
294 int tab_id) const { 425 int tab_id) const {
295 base::AutoLock auto_lock(runtime_lock_); 426 base::AutoLock auto_lock(runtime_lock_);
296 CHECK_GE(tab_id, 0); 427 CHECK_GE(tab_id, 0);
297 TabPermissionsMap::const_iterator iter = 428 TabPermissionsMap::const_iterator iter =
298 tab_specific_permissions_.find(tab_id); 429 tab_specific_permissions_.find(tab_id);
299 return (iter != tab_specific_permissions_.end()) ? iter->second : NULL; 430 return (iter != tab_specific_permissions_.end()) ? iter->second : NULL;
300 } 431 }
301 432
302 bool PermissionsData::HasTabSpecificPermissionToExecuteScript( 433 bool PermissionsData::HasTabSpecificPermissionToExecuteScript(
303 int tab_id, 434 int tab_id,
304 const GURL& url) const { 435 const GURL& url) const {
305 if (tab_id >= 0) { 436 if (tab_id >= 0) {
306 scoped_refptr<const PermissionSet> tab_permissions = 437 scoped_refptr<const PermissionSet> tab_permissions =
307 GetTabSpecificPermissions(tab_id); 438 GetTabSpecificPermissions(tab_id);
308 if (tab_permissions.get() && 439 if (tab_permissions.get() &&
309 tab_permissions->explicit_hosts().MatchesSecurityOrigin(url)) { 440 tab_permissions->explicit_hosts().MatchesSecurityOrigin(url)) {
310 return true; 441 return true;
311 } 442 }
312 } 443 }
313 return false; 444 return false;
314 } 445 }
315 446
316 bool PermissionsData::CanRunOnPage(const Extension* extension, 447 PermissionsData::AccessType PermissionsData::CanRunOnPage(
317 const GURL& document_url, 448 const Extension* extension,
318 const GURL& top_frame_url, 449 const GURL& document_url,
319 int tab_id, 450 const GURL& top_frame_url,
320 int process_id, 451 int tab_id,
321 const URLPatternSet& permitted_url_patterns, 452 int process_id,
322 std::string* error) const { 453 const URLPatternSet& permitted_url_patterns,
454 const URLPatternSet& withheld_url_patterns,
455 std::string* error) const {
323 if (g_policy_delegate && 456 if (g_policy_delegate &&
324 !g_policy_delegate->CanExecuteScriptOnPage( 457 !g_policy_delegate->CanExecuteScriptOnPage(
325 extension, document_url, top_frame_url, tab_id, process_id, error)) { 458 extension, document_url, top_frame_url, tab_id, process_id, error)) {
326 return false; 459 return DENY_ACCESS;
327 } 460 }
328 461
329 if (IsRestrictedUrl(document_url, top_frame_url, extension, error)) 462 if (IsRestrictedUrl(document_url, top_frame_url, extension, error))
330 return false; 463 return DENY_ACCESS;
331 464
332 if (HasTabSpecificPermissionToExecuteScript(tab_id, top_frame_url)) 465 if (HasTabSpecificPermissionToExecuteScript(tab_id, top_frame_url))
333 return true; 466 return ALLOW_ACCESS;
334 467
335 bool can_access = permitted_url_patterns.MatchesURL(document_url); 468 if (permitted_url_patterns.MatchesURL(document_url))
469 return ALLOW_ACCESS;
336 470
337 if (!can_access && error) { 471 if (withheld_url_patterns.MatchesURL(document_url))
472 return REQUEST_ACCESS;
473
474 if (error) {
338 *error = ErrorUtils::FormatErrorMessage(manifest_errors::kCannotAccessPage, 475 *error = ErrorUtils::FormatErrorMessage(manifest_errors::kCannotAccessPage,
339 document_url.spec()); 476 document_url.spec());
340 } 477 }
341 478 return DENY_ACCESS;
342 return can_access;
343 } 479 }
344 480
345 } // namespace extensions 481 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698