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

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: Latest master 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 26 matching lines...) Expand all
247 extension->AddInstallWarning(InstallWarning( 253 extension->AddInstallWarning(InstallWarning(
248 InstallWarning::FORMAT_TEXT, 254 InstallWarning::FORMAT_TEXT,
249 base::StringPrintf( 255 base::StringPrintf(
250 "Permission '%s' is unknown or URL pattern is malformed.", 256 "Permission '%s' is unknown or URL pattern is malformed.",
251 permission_str.c_str()))); 257 permission_str.c_str())));
252 } 258 }
253 259
254 return true; 260 return true;
255 } 261 }
256 262
263 // Returns true if this extension id is from a trusted provider.
264 bool IsTrustedId(const std::string& extension_id) {
265 // See http://b/4946060 for more details.
266 return extension_id == std::string("nckgahadagoaajjgafhacjanaoiihapd");
267 }
268
257 } // namespace 269 } // namespace
258 270
259 struct PermissionsData::InitialPermissions { 271 struct PermissionsData::InitialPermissions {
260 APIPermissionSet api_permissions; 272 APIPermissionSet api_permissions;
261 URLPatternSet host_permissions; 273 URLPatternSet host_permissions;
262 }; 274 };
263 275
264 PermissionsData::PermissionsData() { 276 PermissionsData::PermissionsData() {
265 } 277 }
266 278
(...skipping 19 matching lines...) Expand all
286 initial_required_permissions_->api_permissions; 298 initial_required_permissions_->api_permissions;
287 } 299 }
288 300
289 // static 301 // static
290 APIPermissionSet* PermissionsData::GetInitialAPIPermissions( 302 APIPermissionSet* PermissionsData::GetInitialAPIPermissions(
291 Extension* extension) { 303 Extension* extension) {
292 return &extension->permissions_data()-> 304 return &extension->permissions_data()->
293 initial_required_permissions_->api_permissions; 305 initial_required_permissions_->api_permissions;
294 } 306 }
295 307
308 // static
309 void PermissionsData::SetActivePermissions(const Extension* extension,
310 const PermissionSet* permissions) {
311 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
312 extension->permissions_data()->active_permissions_ = permissions;
313 }
314
315 // static
316 scoped_refptr<const PermissionSet> PermissionsData::GetActivePermissions(
317 const Extension* extension) {
318 return extension->permissions_data()->active_permissions_;
319 }
320
321 // static
322 scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions(
323 const Extension* extension,
324 int tab_id) {
325 CHECK_GE(tab_id, 0);
326 TabPermissionsMap::const_iterator iter =
327 extension->permissions_data()->tab_specific_permissions_.find(tab_id);
328 return
329 (iter != extension->permissions_data()->tab_specific_permissions_.end())
330 ? iter->second
331 : NULL;
332 }
333
334 // static
335 void PermissionsData::UpdateTabSpecificPermissions(
336 const Extension* extension,
337 int tab_id,
338 scoped_refptr<const PermissionSet> permissions) {
339 CHECK_GE(tab_id, 0);
340 TabPermissionsMap* tab_permissions =
341 &extension->permissions_data()->tab_specific_permissions_;
342 if (tab_permissions->count(tab_id)) {
343 (*tab_permissions)[tab_id] = PermissionSet::CreateUnion(
344 (*tab_permissions)[tab_id],
345 permissions.get());
346 } else {
347 (*tab_permissions)[tab_id] = permissions;
348 }
349 }
350
351 // static
352 void PermissionsData::ClearTabSpecificPermissions(
353 const Extension* extension,
354 int tab_id) {
355 CHECK_GE(tab_id, 0);
356 extension->permissions_data()->tab_specific_permissions_.erase(tab_id);
357 }
358
359 // static
360 bool PermissionsData::HasAPIPermission(const Extension* extension,
361 APIPermission::ID permission) {
362 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
363 return GetActivePermissions(extension)->HasAPIPermission(permission);
364 }
365
366 // static
367 bool PermissionsData::HasAPIPermission(const Extension* extension,
368 const std::string& function_name) {
369 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
370 return GetActivePermissions(extension)->HasAccessToFunction(
371 function_name, true); // include implicit
372 }
373
374 // static
375 bool PermissionsData::HasAPIPermissionForTab(
376 const Extension* extension,
377 int tab_id,
378 APIPermission::ID permission) {
379 if (HasAPIPermission(extension, permission))
380 return true;
381
382 // Place autolock below the HasAPIPermission() check, since HasAPIPermission
383 // also acquires the lock.
384 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
385 scoped_refptr<const PermissionSet> tab_permissions =
386 GetTabSpecificPermissions(extension, tab_id);
387 return tab_permissions.get() && tab_permissions->HasAPIPermission(permission);
388 }
389
390 // static
391 bool PermissionsData::CheckAPIPermissionWithParam(
392 const Extension* extension,
393 APIPermission::ID permission,
394 const APIPermission::CheckParam* param) {
395 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
396 return GetActivePermissions(extension)->CheckAPIPermissionWithParam(
397 permission, param);
398 }
399
400 // static
401 const URLPatternSet& PermissionsData::GetEffectiveHostPermissions(
402 const Extension* extension) {
403 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
404 return GetActivePermissions(extension)->effective_hosts();
405 }
406
407 // static
408 bool PermissionsData::CanSilentlyIncreasePermissions(
409 const Extension* extension) {
410 return extension->location() != Manifest::INTERNAL;
411 }
412
413 // static
414 bool PermissionsData::ShouldSkipPermissionWarnings(const Extension* extension) {
415 return IsTrustedId(extension->id());
416 }
417
418 // static
419 bool PermissionsData::HasHostPermission(const Extension* extension,
420 const GURL& url) {
421 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
422 return GetActivePermissions(extension)->HasExplicitAccessToOrigin(url);
423 }
424
425 // static
426 bool PermissionsData::HasEffectiveAccessToAllHosts(const Extension* extension) {
427 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
428 return GetActivePermissions(extension)->HasEffectiveAccessToAllHosts();
429 }
430
431 // static
432 PermissionMessages PermissionsData::GetPermissionMessages(
433 const Extension* extension) {
434 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
435 if (ShouldSkipPermissionWarnings(extension)) {
436 return PermissionMessages();
437 } else {
438 return GetActivePermissions(extension)->GetPermissionMessages(
439 extension->GetType());
440 }
441 }
442
443 // static
444 std::vector<string16> PermissionsData::GetPermissionMessageStrings(
445 const Extension* extension) {
446 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
447 if (ShouldSkipPermissionWarnings(extension)) {
448 return std::vector<string16>();
449 } else {
450 return GetActivePermissions(extension)->GetWarningMessages(
451 extension->GetType());
452 }
453 }
454
455 // static
456 bool PermissionsData::CanExecuteScriptOnPage(const Extension* extension,
457 const GURL& document_url,
458 const GURL& top_frame_url,
459 int tab_id,
460 const UserScript* script,
461 std::string* error) {
462 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
463 // The gallery is special-cased as a restricted URL for scripting to prevent
464 // access to special JS bindings we expose to the gallery (and avoid things
465 // like extensions removing the "report abuse" link).
466 // TODO(erikkay): This seems like the wrong test. Shouldn't we we testing
467 // against the store app extent?
468 GURL store_url(extension_urls::GetWebstoreLaunchURL());
469 const CommandLine* command_line = CommandLine::ForCurrentProcess();
470 bool can_execute_everywhere = CanExecuteScriptEverywhere(extension);
471
472 if ((document_url.host() == store_url.host()) &&
473 !can_execute_everywhere &&
474 !command_line->HasSwitch(switches::kAllowScriptingGallery)) {
475 if (error)
476 *error = errors::kCannotScriptGallery;
477 return false;
478 }
479
480 if (!command_line->HasSwitch(switches::kExtensionsOnChromeURLs)) {
481 if (document_url.SchemeIs(chrome::kChromeUIScheme) &&
482 !can_execute_everywhere) {
483 if (error)
484 *error = errors::kCannotAccessChromeUrl;
485 return false;
486 }
487 }
488
489 if (top_frame_url.SchemeIs(extensions::kExtensionScheme) &&
490 top_frame_url.GetOrigin() !=
491 Extension::GetBaseURLFromExtensionId(extension->id()).GetOrigin() &&
492 !can_execute_everywhere) {
493 if (error)
494 *error = errors::kCannotAccessExtensionUrl;
495 return false;
496 }
497
498 // If a tab ID is specified, try the tab-specific permissions.
499 if (tab_id >= 0) {
500 scoped_refptr<const PermissionSet> tab_permissions =
501 GetTabSpecificPermissions(extension, tab_id);
502 if (tab_permissions.get() &&
503 tab_permissions->explicit_hosts().MatchesSecurityOrigin(document_url)) {
504 return true;
505 }
506 }
507
508 bool can_access = false;
509
510 if (script) {
511 // If a script is specified, use its matches.
512 can_access = script->MatchesURL(document_url);
513 } else {
514 // Otherwise, see if this extension has permission to execute script
515 // programmatically on pages.
516 can_access = GetActivePermissions(extension)->
517 HasExplicitAccessToOrigin(document_url);
518 }
519
520 if (!can_access && error) {
521 *error = ErrorUtils::FormatErrorMessage(errors::kCannotAccessPage,
522 document_url.spec());
523 }
524
525 return can_access;
526 }
527
528 // static
529 bool PermissionsData::CanExecuteScriptEverywhere(const Extension* extension) {
530 if (extension->location() == Manifest::COMPONENT)
531 return true;
532
533 const Extension::ScriptingWhitelist* whitelist =
534 Extension::GetScriptingWhitelist();
535
536 for (Extension::ScriptingWhitelist::const_iterator iter = whitelist->begin();
537 iter != whitelist->end(); ++iter) {
538 if (extension->id() == *iter)
539 return true;
540 }
541
542 return false;
543 }
544
545 // static
546 bool PermissionsData::CanCaptureVisiblePage(const Extension* extension,
547 const GURL& page_url,
548 int tab_id,
549 std::string* error) {
550 if (tab_id >= 0) {
551 scoped_refptr<const PermissionSet> tab_permissions =
552 GetTabSpecificPermissions(extension, tab_id);
553 if (tab_permissions.get() &&
554 tab_permissions->explicit_hosts().MatchesSecurityOrigin(page_url)) {
555 return true;
556 }
557 }
558
559 if (HasHostPermission(extension, page_url) ||
560 page_url.GetOrigin() == extension->url()) {
561 return true;
562 }
563
564 if (error) {
565 *error = ErrorUtils::FormatErrorMessage(errors::kCannotAccessPage,
566 page_url.spec());
567 }
568 return false;
569 }
570
296 bool PermissionsData::ParsePermissions(Extension* extension, string16* error) { 571 bool PermissionsData::ParsePermissions(Extension* extension, string16* error) {
297 initial_required_permissions_.reset(new InitialPermissions); 572 initial_required_permissions_.reset(new InitialPermissions);
298 if (!ParseHelper(extension, 573 if (!ParseHelper(extension,
299 keys::kPermissions, 574 keys::kPermissions,
300 &initial_required_permissions_->api_permissions, 575 &initial_required_permissions_->api_permissions,
301 &initial_required_permissions_->host_permissions, 576 &initial_required_permissions_->host_permissions,
302 error)) { 577 error)) {
303 return false; 578 return false;
304 } 579 }
305 580
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 return false; 617 return false;
343 } 618 }
344 619
345 return true; 620 return true;
346 } 621 }
347 622
348 void PermissionsData::FinalizePermissions(Extension* extension) { 623 void PermissionsData::FinalizePermissions(Extension* extension) {
349 URLPatternSet scriptable_hosts = 624 URLPatternSet scriptable_hosts =
350 ContentScriptsInfo::GetScriptableHosts(extension); 625 ContentScriptsInfo::GetScriptableHosts(extension);
351 626
352 extension->SetActivePermissions(new PermissionSet( 627 active_permissions_ = new PermissionSet(
353 initial_required_permissions_->api_permissions, 628 initial_required_permissions_->api_permissions,
354 initial_required_permissions_->host_permissions, 629 initial_required_permissions_->host_permissions,
355 scriptable_hosts)); 630 scriptable_hosts);
356 631
357 required_permission_set_ = new PermissionSet( 632 required_permission_set_ = new PermissionSet(
358 initial_required_permissions_->api_permissions, 633 initial_required_permissions_->api_permissions,
359 initial_required_permissions_->host_permissions, 634 initial_required_permissions_->host_permissions,
360 scriptable_hosts); 635 scriptable_hosts);
361 636
362 optional_permission_set_ = new PermissionSet( 637 optional_permission_set_ = new PermissionSet(
363 initial_optional_permissions_->api_permissions, 638 initial_optional_permissions_->api_permissions,
364 initial_optional_permissions_->host_permissions, 639 initial_optional_permissions_->host_permissions,
365 URLPatternSet()); 640 URLPatternSet());
366 641
367 initial_required_permissions_.reset(); 642 initial_required_permissions_.reset();
368 initial_optional_permissions_.reset(); 643 initial_optional_permissions_.reset();
369 } 644 }
370 645
371 } // namespace extensions 646 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698