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

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

Issue 14651017: Move RuntimeData and related permissions out of Extension class (Closed) Base URL: http://git.chromium.org/chromium/src.git@dc_unref_permissions
Patch Set: Created 7 years, 7 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
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 "chrome/common/extensions/permissions/permissions_data.h" 5 #include "chrome/common/extensions/permissions/permissions_data.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/string16.h" 9 #include "base/string16.h"
10 #include "base/stringprintf.h" 10 #include "base/stringprintf.h"
11 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
12 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "chrome/common/chrome_switches.h" 14 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/extensions/extension.h" 15 #include "chrome/common/extensions/extension.h"
16 #include "chrome/common/extensions/extension_manifest_constants.h" 16 #include "chrome/common/extensions/extension_manifest_constants.h"
17 #include "chrome/common/extensions/features/base_feature_provider.h" 17 #include "chrome/common/extensions/features/base_feature_provider.h"
18 #include "chrome/common/extensions/features/feature.h" 18 #include "chrome/common/extensions/features/feature.h"
19 #include "chrome/common/extensions/manifest.h"
19 #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" 20 #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
20 #include "chrome/common/extensions/permissions/api_permission_set.h" 21 #include "chrome/common/extensions/permissions/api_permission_set.h"
21 #include "chrome/common/extensions/permissions/permission_set.h" 22 #include "chrome/common/extensions/permissions/permission_set.h"
22 #include "chrome/common/extensions/permissions/permissions_info.h" 23 #include "chrome/common/extensions/permissions/permissions_info.h"
24 #include "chrome/common/extensions/user_script.h"
23 #include "chrome/common/url_constants.h" 25 #include "chrome/common/url_constants.h"
26 #include "extensions/common/constants.h"
24 #include "extensions/common/error_utils.h" 27 #include "extensions/common/error_utils.h"
28 #include "extensions/common/url_pattern_set.h"
29 #include "googleurl/src/gurl.h"
25 30
26 namespace keys = extension_manifest_keys; 31 namespace keys = extension_manifest_keys;
27 namespace errors = extension_manifest_errors; 32 namespace errors = extension_manifest_errors;
28 33
29 namespace extensions { 34 namespace extensions {
30 35
31 namespace { 36 namespace {
32 37
33 const char kThumbsWhiteListedExtension[] = "khopmbdjffemhegeeobelklnbglcdgfh"; 38 const char kThumbsWhiteListedExtension[] = "khopmbdjffemhegeeobelklnbglcdgfh";
34 39
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 // make chrome://thumbs available to NTP Russia extension as 90 // make chrome://thumbs available to NTP Russia extension as
86 // non-experimental. 91 // non-experimental.
87 if (pattern.host() == chrome::kChromeUIThumbnailHost) { 92 if (pattern.host() == chrome::kChromeUIThumbnailHost) {
88 return 93 return
89 permissions.find(APIPermission::kExperimental) != permissions.end() || 94 permissions.find(APIPermission::kExperimental) != permissions.end() ||
90 (extension->id() == kThumbsWhiteListedExtension && 95 (extension->id() == kThumbsWhiteListedExtension &&
91 extension->from_webstore()); 96 extension->from_webstore());
92 } 97 }
93 98
94 // Component extensions can have access to all of chrome://*. 99 // Component extensions can have access to all of chrome://*.
95 if (extension->CanExecuteScriptEverywhere()) 100 if (PermissionsData::CanExecuteScriptEverywhere(extension))
96 return true; 101 return true;
97 102
98 if (CommandLine::ForCurrentProcess()->HasSwitch( 103 if (CommandLine::ForCurrentProcess()->HasSwitch(
99 switches::kExtensionsOnChromeURLs)) { 104 switches::kExtensionsOnChromeURLs)) {
100 return true; 105 return true;
101 } 106 }
102 107
103 // TODO(aboxhall): return from_webstore() when webstore handles blocking 108 // TODO(aboxhall): return from_webstore() when webstore handles blocking
104 // extensions which request chrome:// urls 109 // extensions which request chrome:// urls
105 return false; 110 return false;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 } 182 }
178 } 183 }
179 184
180 // Remove permissions that are not available to this extension. 185 // Remove permissions that are not available to this extension.
181 for (std::vector<APIPermission::ID>::const_iterator iter = to_remove.begin(); 186 for (std::vector<APIPermission::ID>::const_iterator iter = to_remove.begin();
182 iter != to_remove.end(); ++iter) { 187 iter != to_remove.end(); ++iter) {
183 api_permissions->erase(*iter); 188 api_permissions->erase(*iter);
184 } 189 }
185 190
186 // Parse host pattern permissions. 191 // Parse host pattern permissions.
187 const int kAllowedSchemes = extension->CanExecuteScriptEverywhere() ? 192 const int kAllowedSchemes =
193 PermissionsData::CanExecuteScriptEverywhere(extension) ?
188 URLPattern::SCHEME_ALL : Extension::kValidHostPermissionSchemes; 194 URLPattern::SCHEME_ALL : Extension::kValidHostPermissionSchemes;
189 195
190 for (std::vector<std::string>::const_iterator iter = host_data.begin(); 196 for (std::vector<std::string>::const_iterator iter = host_data.begin();
191 iter != host_data.end(); ++iter) { 197 iter != host_data.end(); ++iter) {
192 const std::string& permission_str = *iter; 198 const std::string& permission_str = *iter;
193 199
194 // Check if it's a host pattern permission. 200 // Check if it's a host pattern permission.
195 URLPattern pattern = URLPattern(kAllowedSchemes); 201 URLPattern pattern = URLPattern(kAllowedSchemes);
196 URLPattern::ParseResult parse_result = pattern.Parse(permission_str); 202 URLPattern::ParseResult parse_result = pattern.Parse(permission_str);
197 if (parse_result == URLPattern::PARSE_SUCCESS) { 203 if (parse_result == URLPattern::PARSE_SUCCESS) {
198 // The path component is not used for host permissions, so we force it 204 // The path component is not used for host permissions, so we force it
199 // to match all paths. 205 // to match all paths.
200 pattern.SetPath("/*"); 206 pattern.SetPath("/*");
201 int valid_schemes = pattern.valid_schemes(); 207 int valid_schemes = pattern.valid_schemes();
202 if (pattern.MatchesScheme(chrome::kFileScheme) && 208 if (pattern.MatchesScheme(chrome::kFileScheme) &&
203 !extension->CanExecuteScriptEverywhere()) { 209 !PermissionsData::CanExecuteScriptEverywhere(extension)) {
204 extension->set_wants_file_access(true); 210 extension->set_wants_file_access(true);
205 if (!(extension->creation_flags() & Extension::ALLOW_FILE_ACCESS)) 211 if (!(extension->creation_flags() & Extension::ALLOW_FILE_ACCESS))
206 valid_schemes &= ~URLPattern::SCHEME_FILE; 212 valid_schemes &= ~URLPattern::SCHEME_FILE;
207 } 213 }
208 214
209 if (pattern.scheme() != chrome::kChromeUIScheme && 215 if (pattern.scheme() != chrome::kChromeUIScheme &&
210 !extension->CanExecuteScriptEverywhere()) { 216 !PermissionsData::CanExecuteScriptEverywhere(extension)) {
211 // Keep chrome:// in allowed schemes only if it's explicitly requested 217 // Keep chrome:// in allowed schemes only if it's explicitly requested
212 // or CanExecuteScriptEverywhere is true. If the 218 // or CanExecuteScriptEverywhere is true. If the
213 // extensions_on_chrome_urls flag is not set, CanSpecifyHostPermission 219 // extensions_on_chrome_urls flag is not set, CanSpecifyHostPermission
214 // will fail, so don't check the flag here. 220 // will fail, so don't check the flag here.
215 valid_schemes &= ~URLPattern::SCHEME_CHROMEUI; 221 valid_schemes &= ~URLPattern::SCHEME_CHROMEUI;
216 } 222 }
217 pattern.SetValidSchemes(valid_schemes); 223 pattern.SetValidSchemes(valid_schemes);
218 224
219 if (!CanSpecifyHostPermission(extension, pattern, *api_permissions)) { 225 if (!CanSpecifyHostPermission(extension, pattern, *api_permissions)) {
220 // TODO(aboxhall): make a warning (see pattern.match_all_urls() block 226 // TODO(aboxhall): make a warning (see pattern.match_all_urls() block
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 initial_required_permissions_->api_permissions; 292 initial_required_permissions_->api_permissions;
287 } 293 }
288 294
289 // static 295 // static
290 APIPermissionSet* PermissionsData::GetInitialAPIPermissions( 296 APIPermissionSet* PermissionsData::GetInitialAPIPermissions(
291 Extension* extension) { 297 Extension* extension) {
292 return &extension->permissions_data()-> 298 return &extension->permissions_data()->
293 initial_required_permissions_->api_permissions; 299 initial_required_permissions_->api_permissions;
294 } 300 }
295 301
302 // static
303 void PermissionsData::SetActivePermissions(const Extension* extension,
304 const PermissionSet* permissions) {
305 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
306 extension->permissions_data()->active_permissions_ = permissions;
307 }
308
309 // static
310 scoped_refptr<const PermissionSet> PermissionsData::GetActivePermissions(
311 const Extension* extension) {
312 return extension->permissions_data()->active_permissions_;
313 }
314
315 // static
316 scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions(
317 const Extension* extension,
318 int tab_id) {
319 CHECK_GE(tab_id, 0);
320 TabPermissionsMap::const_iterator iter =
321 extension->permissions_data()->tab_specific_permissions_.find(tab_id);
322 return
323 (iter != extension->permissions_data()->tab_specific_permissions_.end())
324 ? iter->second
325 : NULL;
326 }
327
328 // static
329 void PermissionsData::UpdateTabSpecificPermissions(
330 const Extension* extension,
331 int tab_id,
332 scoped_refptr<const PermissionSet> permissions) {
333 CHECK_GE(tab_id, 0);
334 TabPermissionsMap* tab_permissions =
335 &extension->permissions_data()->tab_specific_permissions_;
336 if (tab_permissions->count(tab_id)) {
337 (*tab_permissions)[tab_id] = PermissionSet::CreateUnion(
338 (*tab_permissions)[tab_id],
339 permissions.get());
340 } else {
341 (*tab_permissions)[tab_id] = permissions;
342 }
343 }
344
345 // static
346 void PermissionsData::ClearTabSpecificPermissions(
347 const Extension* extension,
348 int tab_id) {
349 CHECK_GE(tab_id, 0);
350 extension->permissions_data()->tab_specific_permissions_.erase(tab_id);
351 }
352
353 // static
354 bool PermissionsData::HasAPIPermission(const Extension* extension,
355 APIPermission::ID permission) {
356 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
357 return extension->permissions_data()->
Yoyo Zhou 2013/05/11 00:57:04 These should probably be GetActivePermissions. The
Devlin 2013/05/13 22:44:23 Done.
358 active_permissions_->HasAPIPermission(permission);
359 }
360
361 // static
362 bool PermissionsData::HasAPIPermission(const Extension* extension,
363 const std::string& function_name) {
364 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
365 return extension->permissions_data()->
366 active_permissions_->HasAccessToFunction(function_name,
367 true); // include implicit
368 }
369
370 // static
371 bool PermissionsData::HasAPIPermissionForTab(
372 const Extension* extension,
373 int tab_id,
374 APIPermission::ID permission) {
375 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
376 if (HasAPIPermission(extension, permission))
377 return true;
378 scoped_refptr<const PermissionSet> tab_permissions =
379 GetTabSpecificPermissions(extension, tab_id);
380 return tab_permissions.get() && tab_permissions->HasAPIPermission(permission);
381 }
382
383 // static
384 bool PermissionsData::CheckAPIPermissionWithParam(
385 const Extension* extension,
386 APIPermission::ID permission,
387 const APIPermission::CheckParam* param) {
388 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
389 return extension->permissions_data()->active_permissions_->
390 CheckAPIPermissionWithParam(permission, param);
391 }
392
393 // static
394 const URLPatternSet& PermissionsData::GetEffectiveHostPermissions(
395 const Extension* extension) {
396 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
397 return extension->permissions_data()->active_permissions_->effective_hosts();
398 }
399
400 // static
401 bool PermissionsData::CanSilentlyIncreasePermissions(
402 const Extension* extension) {
403 return extension->location() != Manifest::INTERNAL;
404 }
405
406 // static
407 bool PermissionsData::ShouldSkipPermissionWarnings(const Extension* extension) {
408 return Extension::IsTrustedId(extension->id());
Yoyo Zhou 2013/05/11 00:57:04 Why not move IsTrustedId to here?
Devlin 2013/05/13 22:44:23 Done.
409 }
410
411 // static
412 bool PermissionsData::HasHostPermission(const Extension* extension,
413 const GURL& url) {
414 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
415 return extension->permissions_data()->active_permissions_->
416 HasExplicitAccessToOrigin(url);
417 }
418
419 // static
420 bool PermissionsData::HasEffectiveAccessToAllHosts(const Extension* extension) {
421 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
422 return extension->permissions_data()->active_permissions_->
423 HasEffectiveAccessToAllHosts();
424 }
425
426 // static
427 PermissionMessages PermissionsData::GetPermissionMessages(
428 const Extension* extension) {
429 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
430 if (Extension::IsTrustedId(extension->id())) {
Yoyo Zhou 2013/05/11 00:57:04 I think these should use ShouldSkipPermissionWarni
Devlin 2013/05/13 22:44:23 Done.
431 return PermissionMessages();
432 } else {
433 return extension->permissions_data()->active_permissions_->
434 GetPermissionMessages(extension->GetType());
435 }
436 }
437
438 // static
439 std::vector<string16> PermissionsData::GetPermissionMessageStrings(
440 const Extension* extension) {
441 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
442 if (Extension::IsTrustedId(extension->id())) {
443 return std::vector<string16>();
444 } else {
445 return extension->permissions_data()->active_permissions_->
446 GetWarningMessages(extension->GetType());
447 }
448 }
449
450 // static
451 bool PermissionsData::CanExecuteScriptOnPage(const Extension* extension,
452 const GURL& document_url,
453 const GURL& top_frame_url,
454 int tab_id,
455 const UserScript* script,
456 std::string* error) {
457 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
458 // The gallery is special-cased as a restricted URL for scripting to prevent
459 // access to special JS bindings we expose to the gallery (and avoid things
460 // like extensions removing the "report abuse" link).
461 // TODO(erikkay): This seems like the wrong test. Shouldn't we we testing
462 // against the store app extent?
463 GURL store_url(extension_urls::GetWebstoreLaunchURL());
464 const CommandLine* command_line = CommandLine::ForCurrentProcess();
465 bool can_execute_everywhere = CanExecuteScriptEverywhere(extension);
466
467 if ((document_url.host() == store_url.host()) &&
468 !can_execute_everywhere &&
469 !command_line->HasSwitch(switches::kAllowScriptingGallery)) {
470 if (error)
471 *error = errors::kCannotScriptGallery;
472 return false;
473 }
474
475 if (!command_line->HasSwitch(switches::kExtensionsOnChromeURLs)) {
476 if (document_url.SchemeIs(chrome::kChromeUIScheme) &&
477 !can_execute_everywhere) {
478 if (error)
479 *error = errors::kCannotAccessChromeUrl;
480 return false;
481 }
482 }
483
484 if (top_frame_url.SchemeIs(extensions::kExtensionScheme) &&
485 top_frame_url.GetOrigin() !=
486 Extension::GetBaseURLFromExtensionId(extension->id()).GetOrigin() &&
487 !can_execute_everywhere) {
488 if (error)
489 *error = errors::kCannotAccessExtensionUrl;
490 return false;
491 }
492
493 // If a tab ID is specified, try the tab-specific permissions.
494 if (tab_id >= 0) {
495 scoped_refptr<const PermissionSet> tab_permissions =
496 GetTabSpecificPermissions(extension, tab_id);
497 if (tab_permissions.get() &&
498 tab_permissions->explicit_hosts().MatchesSecurityOrigin(document_url)) {
499 return true;
500 }
501 }
502
503 bool can_access = false;
504
505 if (script) {
506 // If a script is specified, use its matches.
507 can_access = script->MatchesURL(document_url);
508 } else {
509 // Otherwise, see if this extension has permission to execute script
510 // programmatically on pages.
511 can_access = GetActivePermissions(extension)->
512 HasExplicitAccessToOrigin(document_url);
513 }
514
515 if (!can_access && error) {
516 *error = ErrorUtils::FormatErrorMessage(errors::kCannotAccessPage,
517 document_url.spec());
518 }
519
520 return can_access;
521 }
522
523 // static
524 bool PermissionsData::CanExecuteScriptEverywhere(const Extension* extension) {
525 if (extension->location() == Manifest::COMPONENT)
526 return true;
527
528 const Extension::ScriptingWhitelist* whitelist =
529 Extension::GetScriptingWhitelist();
530
531 for (Extension::ScriptingWhitelist::const_iterator iter = whitelist->begin();
532 iter != whitelist->end(); ++iter) {
533 if (extension->id() == *iter)
534 return true;
535 }
536
537 return false;
538 }
539
540 // static
541 bool PermissionsData::CanCaptureVisiblePage(const Extension* extension,
542 const GURL& page_url,
543 int tab_id,
544 std::string* error) {
545 if (tab_id >= 0) {
546 scoped_refptr<const PermissionSet> tab_permissions =
547 GetTabSpecificPermissions(extension, tab_id);
548 if (tab_permissions.get() &&
549 tab_permissions->explicit_hosts().MatchesSecurityOrigin(page_url)) {
550 return true;
551 }
552 }
553
554 if (HasHostPermission(extension, page_url) ||
555 page_url.GetOrigin() == extension->url()) {
556 return true;
557 }
558
559 if (error) {
560 *error = ErrorUtils::FormatErrorMessage(errors::kCannotAccessPage,
561 page_url.spec());
562 }
563 return false;
564 }
565
296 bool PermissionsData::ParsePermissions(Extension* extension, string16* error) { 566 bool PermissionsData::ParsePermissions(Extension* extension, string16* error) {
297 initial_required_permissions_.reset(new InitialPermissions); 567 initial_required_permissions_.reset(new InitialPermissions);
298 if (!ParseHelper(extension, 568 if (!ParseHelper(extension,
299 keys::kPermissions, 569 keys::kPermissions,
300 &initial_required_permissions_->api_permissions, 570 &initial_required_permissions_->api_permissions,
301 &initial_required_permissions_->host_permissions, 571 &initial_required_permissions_->host_permissions,
302 error)) { 572 error)) {
303 return false; 573 return false;
304 } 574 }
305 575
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 return false; 612 return false;
343 } 613 }
344 614
345 return true; 615 return true;
346 } 616 }
347 617
348 void PermissionsData::FinalizePermissions(Extension* extension) { 618 void PermissionsData::FinalizePermissions(Extension* extension) {
349 URLPatternSet scriptable_hosts = 619 URLPatternSet scriptable_hosts =
350 ContentScriptsInfo::GetScriptableHosts(extension); 620 ContentScriptsInfo::GetScriptableHosts(extension);
351 621
352 extension->SetActivePermissions(new PermissionSet( 622 active_permissions_ = new PermissionSet(
353 initial_required_permissions_->api_permissions, 623 initial_required_permissions_->api_permissions,
354 initial_required_permissions_->host_permissions, 624 initial_required_permissions_->host_permissions,
355 scriptable_hosts)); 625 scriptable_hosts);
356 626
357 required_permission_set_ = new PermissionSet( 627 required_permission_set_ = new PermissionSet(
358 initial_required_permissions_->api_permissions, 628 initial_required_permissions_->api_permissions,
359 initial_required_permissions_->host_permissions, 629 initial_required_permissions_->host_permissions,
360 scriptable_hosts); 630 scriptable_hosts);
361 631
362 optional_permission_set_ = new PermissionSet( 632 optional_permission_set_ = new PermissionSet(
363 initial_optional_permissions_->api_permissions, 633 initial_optional_permissions_->api_permissions,
364 initial_optional_permissions_->host_permissions, 634 initial_optional_permissions_->host_permissions,
365 URLPatternSet()); 635 URLPatternSet());
366 636
367 initial_required_permissions_.reset(); 637 initial_required_permissions_.reset();
368 initial_optional_permissions_.reset(); 638 initial_optional_permissions_.reset();
369 } 639 }
370 640
371 } // namespace extensions 641 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698