| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/features/simple_feature.h" | 5 #include "extensions/common/features/simple_feature.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 namespace extensions { | 28 namespace extensions { |
| 29 | 29 |
| 30 namespace { | 30 namespace { |
| 31 | 31 |
| 32 // A singleton copy of the --whitelisted-extension-id so that we don't need to | 32 // A singleton copy of the --whitelisted-extension-id so that we don't need to |
| 33 // copy it from the CommandLine each time. | 33 // copy it from the CommandLine each time. |
| 34 std::string* g_whitelisted_extension_id = NULL; | 34 std::string* g_whitelisted_extension_id = NULL; |
| 35 | 35 |
| 36 Feature::Availability IsAvailableToManifestForBind( | 36 Feature::Availability IsAvailableToManifestForBind( |
| 37 const std::string& extension_id, | 37 const std::string& extension_id, |
| 38 const std::string& hashed_id, |
| 38 Manifest::Type type, | 39 Manifest::Type type, |
| 39 Manifest::Location location, | 40 Manifest::Location location, |
| 40 int manifest_version, | 41 int manifest_version, |
| 41 Feature::Platform platform, | 42 Feature::Platform platform, |
| 42 const Feature* feature) { | 43 const Feature* feature) { |
| 43 return feature->IsAvailableToManifest( | 44 return feature->IsAvailableToManifest(extension_id, hashed_id, type, location, |
| 44 extension_id, type, location, manifest_version, platform); | 45 manifest_version, platform); |
| 45 } | 46 } |
| 46 | 47 |
| 47 Feature::Availability IsAvailableToContextForBind(const Extension* extension, | 48 Feature::Availability IsAvailableToContextForBind(const Extension* extension, |
| 48 Feature::Context context, | 49 Feature::Context context, |
| 49 const GURL& url, | 50 const GURL& url, |
| 50 Feature::Platform platform, | 51 Feature::Platform platform, |
| 51 const Feature* feature) { | 52 const Feature* feature) { |
| 52 return feature->IsAvailableToContext(extension, context, url, platform); | 53 return feature->IsAvailableToContext(extension, context, url, platform); |
| 53 } | 54 } |
| 54 | 55 |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 result = filter->Parse(dictionary); | 357 result = filter->Parse(dictionary); |
| 357 if (!result.empty()) | 358 if (!result.empty()) |
| 358 break; | 359 break; |
| 359 } | 360 } |
| 360 | 361 |
| 361 return result; | 362 return result; |
| 362 } | 363 } |
| 363 | 364 |
| 364 Feature::Availability SimpleFeature::IsAvailableToManifest( | 365 Feature::Availability SimpleFeature::IsAvailableToManifest( |
| 365 const std::string& extension_id, | 366 const std::string& extension_id, |
| 367 const std::string& hashed_id, |
| 366 Manifest::Type type, | 368 Manifest::Type type, |
| 367 Manifest::Location location, | 369 Manifest::Location location, |
| 368 int manifest_version, | 370 int manifest_version, |
| 369 Platform platform) const { | 371 Platform platform) const { |
| 370 // Check extension type first to avoid granting platform app permissions | 372 // Check extension type first to avoid granting platform app permissions |
| 371 // to component extensions. | 373 // to component extensions. |
| 372 // HACK(kalman): user script -> extension. Solve this in a more generic way | 374 // HACK(kalman): user script -> extension. Solve this in a more generic way |
| 373 // when we compile feature files. | 375 // when we compile feature files. |
| 374 Manifest::Type type_to_check = (type == Manifest::TYPE_USER_SCRIPT) ? | 376 Manifest::Type type_to_check = (type == Manifest::TYPE_USER_SCRIPT) ? |
| 375 Manifest::TYPE_EXTENSION : type; | 377 Manifest::TYPE_EXTENSION : type; |
| 376 if (!extension_types_.empty() && | 378 if (!extension_types_.empty() && |
| 377 !ContainsValue(extension_types_, type_to_check)) { | 379 !ContainsValue(extension_types_, type_to_check)) { |
| 378 return CreateAvailability(INVALID_TYPE, type); | 380 return CreateAvailability(INVALID_TYPE, type); |
| 379 } | 381 } |
| 380 | 382 |
| 381 if (IsIdInBlacklist(extension_id)) | 383 if (IsIdInBlacklist(extension_id, hashed_id)) |
| 382 return CreateAvailability(FOUND_IN_BLACKLIST, type); | 384 return CreateAvailability(FOUND_IN_BLACKLIST, type); |
| 383 | 385 |
| 384 // TODO(benwells): don't grant all component extensions. | 386 // TODO(benwells): don't grant all component extensions. |
| 385 // See http://crbug.com/370375 for more details. | 387 // See http://crbug.com/370375 for more details. |
| 386 // Component extensions can access any feature. | 388 // Component extensions can access any feature. |
| 387 // NOTE: Deliberately does not match EXTERNAL_COMPONENT. | 389 // NOTE: Deliberately does not match EXTERNAL_COMPONENT. |
| 388 if (component_extensions_auto_granted_ && location == Manifest::COMPONENT) | 390 if (component_extensions_auto_granted_ && location == Manifest::COMPONENT) |
| 389 return CreateAvailability(IS_AVAILABLE, type); | 391 return CreateAvailability(IS_AVAILABLE, type); |
| 390 | 392 |
| 391 if (!whitelist_.empty() && !IsIdInWhitelist(extension_id) && | 393 if (!whitelist_.empty() && !IsIdInWhitelist(extension_id, hashed_id) && |
| 392 !IsWhitelistedForTest(extension_id)) { | 394 !IsWhitelistedForTest(extension_id) && !IsWhitelistedForTest(hashed_id)) { |
| 393 return CreateAvailability(NOT_FOUND_IN_WHITELIST, type); | 395 return CreateAvailability(NOT_FOUND_IN_WHITELIST, type); |
| 394 } | 396 } |
| 395 | 397 |
| 396 if (!MatchesManifestLocation(location)) | 398 if (!MatchesManifestLocation(location)) |
| 397 return CreateAvailability(INVALID_LOCATION, type); | 399 return CreateAvailability(INVALID_LOCATION, type); |
| 398 | 400 |
| 399 if (!platforms_.empty() && !ContainsValue(platforms_, platform)) | 401 if (!platforms_.empty() && !ContainsValue(platforms_, platform)) |
| 400 return CreateAvailability(INVALID_PLATFORM, type); | 402 return CreateAvailability(INVALID_PLATFORM, type); |
| 401 | 403 |
| 402 if (min_manifest_version_ != 0 && manifest_version < min_manifest_version_) | 404 if (min_manifest_version_ != 0 && manifest_version < min_manifest_version_) |
| 403 return CreateAvailability(INVALID_MIN_MANIFEST_VERSION, type); | 405 return CreateAvailability(INVALID_MIN_MANIFEST_VERSION, type); |
| 404 | 406 |
| 405 if (max_manifest_version_ != 0 && manifest_version > max_manifest_version_) | 407 if (max_manifest_version_ != 0 && manifest_version > max_manifest_version_) |
| 406 return CreateAvailability(INVALID_MAX_MANIFEST_VERSION, type); | 408 return CreateAvailability(INVALID_MAX_MANIFEST_VERSION, type); |
| 407 | 409 |
| 408 if (!command_line_switch_.empty() && | 410 if (!command_line_switch_.empty() && |
| 409 !IsCommandLineSwitchEnabled(command_line_switch_)) { | 411 !IsCommandLineSwitchEnabled(command_line_switch_)) { |
| 410 return CreateAvailability(MISSING_COMMAND_LINE_SWITCH, type); | 412 return CreateAvailability(MISSING_COMMAND_LINE_SWITCH, type); |
| 411 } | 413 } |
| 412 | 414 |
| 413 for (const auto& filter : filters_) { | 415 for (const auto& filter : filters_) { |
| 414 Availability availability = filter->IsAvailableToManifest( | 416 Availability availability = filter->IsAvailableToManifest( |
| 415 extension_id, type, location, manifest_version, platform); | 417 extension_id, type, location, manifest_version, platform); |
| 416 if (!availability.is_available()) | 418 if (!availability.is_available()) |
| 417 return availability; | 419 return availability; |
| 418 } | 420 } |
| 419 | 421 |
| 420 return CheckDependencies(base::Bind(&IsAvailableToManifestForBind, | 422 return CheckDependencies(base::Bind(&IsAvailableToManifestForBind, |
| 421 extension_id, | 423 extension_id, hashed_id, type, location, |
| 422 type, | 424 manifest_version, platform)); |
| 423 location, | |
| 424 manifest_version, | |
| 425 platform)); | |
| 426 } | 425 } |
| 427 | 426 |
| 428 Feature::Availability SimpleFeature::IsAvailableToContext( | 427 Feature::Availability SimpleFeature::IsAvailableToContext( |
| 429 const Extension* extension, | 428 const Extension* extension, |
| 430 SimpleFeature::Context context, | 429 SimpleFeature::Context context, |
| 431 const GURL& url, | 430 const GURL& url, |
| 432 SimpleFeature::Platform platform) const { | 431 SimpleFeature::Platform platform) const { |
| 433 if (extension) { | 432 if (extension) { |
| 434 Availability result = IsAvailableToManifest(extension->id(), | 433 Availability result = IsAvailableToManifest( |
| 435 extension->GetType(), | 434 extension->id(), HashedIdInHex(extension->id()), extension->GetType(), |
| 436 extension->location(), | 435 extension->location(), extension->manifest_version(), platform); |
| 437 extension->manifest_version(), | |
| 438 platform); | |
| 439 if (!result.is_available()) | 436 if (!result.is_available()) |
| 440 return result; | 437 return result; |
| 441 } | 438 } |
| 442 | 439 |
| 443 // TODO(lazyboy): This isn't quite right for Extension Service Worker | 440 // TODO(lazyboy): This isn't quite right for Extension Service Worker |
| 444 // extension API calls, since there's no guarantee that the extension is | 441 // extension API calls, since there's no guarantee that the extension is |
| 445 // "active" in current renderer process when the API permission check is | 442 // "active" in current renderer process when the API permission check is |
| 446 // done. | 443 // done. |
| 447 if (!contexts_.empty() && !ContainsValue(contexts_, context)) | 444 if (!contexts_.empty() && !ContainsValue(contexts_, context)) |
| 448 return CreateAvailability(INVALID_CONTEXT, context); | 445 return CreateAvailability(INVALID_CONTEXT, context); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 Context context) const { | 557 Context context) const { |
| 561 return Availability( | 558 return Availability( |
| 562 result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(), | 559 result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(), |
| 563 context)); | 560 context)); |
| 564 } | 561 } |
| 565 | 562 |
| 566 bool SimpleFeature::IsInternal() const { | 563 bool SimpleFeature::IsInternal() const { |
| 567 return false; | 564 return false; |
| 568 } | 565 } |
| 569 | 566 |
| 570 bool SimpleFeature::IsIdInBlacklist(const std::string& extension_id) const { | 567 bool SimpleFeature::IsIdInBlacklist(const std::string& extension_id, |
| 571 return IsIdInList(extension_id, blacklist_); | 568 const std::string& hashed_id) const { |
| 569 return (IsIdInList(extension_id, blacklist_) || |
| 570 IsIdInList(hashed_id, blacklist_)); |
| 572 } | 571 } |
| 573 | 572 |
| 574 bool SimpleFeature::IsIdInWhitelist(const std::string& extension_id) const { | 573 bool SimpleFeature::IsIdInWhitelist(const std::string& extension_id, |
| 575 return IsIdInList(extension_id, whitelist_); | 574 const std::string& hashed_id) const { |
| 575 return (IsIdInList(extension_id, whitelist_) || |
| 576 IsIdInList(hashed_id, whitelist_)); |
| 576 } | 577 } |
| 577 | 578 |
| 578 // static | 579 // static |
| 579 bool SimpleFeature::IsIdInArray(const std::string& extension_id, | 580 bool SimpleFeature::IsIdInArray(const std::string& extension_id, |
| 580 const char* const array[], | 581 const char* const array[], |
| 581 size_t array_length) { | 582 size_t array_length) { |
| 582 if (!IsValidExtensionId(extension_id)) | 583 if (!IsValidExtensionId(extension_id)) |
| 583 return false; | 584 return false; |
| 584 | 585 |
| 585 const char* const* start = array; | 586 const char* const* start = array; |
| 586 const char* const* end = array + array_length; | 587 const char* const* end = array + array_length; |
| 587 | 588 |
| 588 return ((std::find(start, end, extension_id) != end) || | 589 return (std::find(start, end, extension_id) != end); |
| 589 (std::find(start, end, HashedIdInHex(extension_id)) != end)); | |
| 590 } | 590 } |
| 591 | 591 |
| 592 // static | 592 // static |
| 593 bool SimpleFeature::IsIdInList(const std::string& extension_id, | 593 bool SimpleFeature::IsIdInList(const std::string& extension_id, |
| 594 const std::vector<std::string>& list) { | 594 const std::vector<std::string>& list) { |
| 595 if (!IsValidExtensionId(extension_id)) | 595 if (!IsValidExtensionId(extension_id)) |
| 596 return false; | 596 return false; |
| 597 | 597 |
| 598 return (ContainsValue(list, extension_id) || | 598 return ContainsValue(list, extension_id); |
| 599 ContainsValue(list, HashedIdInHex(extension_id))); | |
| 600 } | 599 } |
| 601 | 600 |
| 602 bool SimpleFeature::MatchesManifestLocation( | 601 bool SimpleFeature::MatchesManifestLocation( |
| 603 Manifest::Location manifest_location) const { | 602 Manifest::Location manifest_location) const { |
| 604 switch (location_) { | 603 switch (location_) { |
| 605 case SimpleFeature::UNSPECIFIED_LOCATION: | 604 case SimpleFeature::UNSPECIFIED_LOCATION: |
| 606 return true; | 605 return true; |
| 607 case SimpleFeature::COMPONENT_LOCATION: | 606 case SimpleFeature::COMPONENT_LOCATION: |
| 608 return manifest_location == Manifest::COMPONENT; | 607 return manifest_location == Manifest::COMPONENT; |
| 609 case SimpleFeature::EXTERNAL_COMPONENT_LOCATION: | 608 case SimpleFeature::EXTERNAL_COMPONENT_LOCATION: |
| (...skipping 24 matching lines...) Expand all Loading... |
| 634 bool SimpleFeature::IsValidExtensionId(const std::string& extension_id) { | 633 bool SimpleFeature::IsValidExtensionId(const std::string& extension_id) { |
| 635 // Belt-and-suspenders philosophy here. We should be pretty confident by this | 634 // Belt-and-suspenders philosophy here. We should be pretty confident by this |
| 636 // point that we've validated the extension ID format, but in case something | 635 // point that we've validated the extension ID format, but in case something |
| 637 // slips through, we avoid a class of attack where creative ID manipulation | 636 // slips through, we avoid a class of attack where creative ID manipulation |
| 638 // leads to hash collisions. | 637 // leads to hash collisions. |
| 639 // 128 bits / 4 = 32 mpdecimal characters | 638 // 128 bits / 4 = 32 mpdecimal characters |
| 640 return (extension_id.length() == 32); | 639 return (extension_id.length() == 32); |
| 641 } | 640 } |
| 642 | 641 |
| 643 } // namespace extensions | 642 } // namespace extensions |
| OLD | NEW |