| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/extension_permission_set.h" | 5 #include "chrome/common/extensions/extension_permission_set.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/memory/singleton.h" | 10 #include "base/memory/singleton.h" |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 "tabs.update", | 74 "tabs.update", |
| 75 }; | 75 }; |
| 76 const size_t kNumNonPermissionFunctionNames = | 76 const size_t kNumNonPermissionFunctionNames = |
| 77 arraysize(kNonPermissionFunctionNames); | 77 arraysize(kNonPermissionFunctionNames); |
| 78 | 78 |
| 79 const char kOldUnlimitedStoragePermission[] = "unlimited_storage"; | 79 const char kOldUnlimitedStoragePermission[] = "unlimited_storage"; |
| 80 const char kWindowsPermission[] = "windows"; | 80 const char kWindowsPermission[] = "windows"; |
| 81 | 81 |
| 82 void AddPatternsAndRemovePaths(const URLPatternSet& set, URLPatternSet* out) { | 82 void AddPatternsAndRemovePaths(const URLPatternSet& set, URLPatternSet* out) { |
| 83 CHECK(out); | 83 CHECK(out); |
| 84 const URLPatternList& patterns = set.patterns(); | 84 for (URLPatternSet::const_iterator i = set.begin(); i != set.end(); ++i) { |
| 85 for (size_t i = 0; i < patterns.size(); ++i) { | 85 URLPattern p = *i; |
| 86 URLPattern p = patterns.at(i); | |
| 87 p.SetPath("/*"); | 86 p.SetPath("/*"); |
| 88 out->AddPattern(p); | 87 out->AddPattern(p); |
| 89 } | 88 } |
| 90 } | 89 } |
| 91 | 90 |
| 92 } // namespace | 91 } // namespace |
| 93 | 92 |
| 94 // | 93 // |
| 95 // PermissionMessage | 94 // PermissionMessage |
| 96 // | 95 // |
| 97 | 96 |
| 98 // static | 97 // static |
| 99 ExtensionPermissionMessage ExtensionPermissionMessage::CreateFromHostList( | 98 ExtensionPermissionMessage ExtensionPermissionMessage::CreateFromHostList( |
| 100 const std::vector<std::string>& hosts) { | 99 const std::set<std::string>& hosts) { |
| 101 CHECK(hosts.size() > 0); | 100 std::vector<std::string> host_list(hosts.begin(), hosts.end()); |
| 101 CHECK(host_list.size() > 0); |
| 102 ID message_id; | 102 ID message_id; |
| 103 string16 message; | 103 string16 message; |
| 104 switch (hosts.size()) { | 104 |
| 105 switch (host_list.size()) { |
| 105 case 1: | 106 case 1: |
| 106 message_id = kHosts1; | 107 message_id = kHosts1; |
| 107 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_1_HOST, | 108 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_1_HOST, |
| 108 UTF8ToUTF16(hosts[0])); | 109 UTF8ToUTF16(host_list[0])); |
| 109 break; | 110 break; |
| 110 case 2: | 111 case 2: |
| 111 message_id = kHosts2; | 112 message_id = kHosts2; |
| 112 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_2_HOSTS, | 113 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_2_HOSTS, |
| 113 UTF8ToUTF16(hosts[0]), | 114 UTF8ToUTF16(host_list[0]), |
| 114 UTF8ToUTF16(hosts[1])); | 115 UTF8ToUTF16(host_list[1])); |
| 115 break; | 116 break; |
| 116 case 3: | 117 case 3: |
| 117 message_id = kHosts3; | 118 message_id = kHosts3; |
| 118 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_3_HOSTS, | 119 message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_3_HOSTS, |
| 119 UTF8ToUTF16(hosts[0]), | 120 UTF8ToUTF16(host_list[0]), |
| 120 UTF8ToUTF16(hosts[1]), | 121 UTF8ToUTF16(host_list[1]), |
| 121 UTF8ToUTF16(hosts[2])); | 122 UTF8ToUTF16(host_list[2])); |
| 122 break; | 123 break; |
| 123 default: | 124 default: |
| 124 message_id = kHosts4OrMore; | 125 message_id = kHosts4OrMore; |
| 125 message = l10n_util::GetStringFUTF16( | 126 message = l10n_util::GetStringFUTF16( |
| 126 IDS_EXTENSION_PROMPT_WARNING_4_OR_MORE_HOSTS, | 127 IDS_EXTENSION_PROMPT_WARNING_4_OR_MORE_HOSTS, |
| 127 UTF8ToUTF16(hosts[0]), | 128 UTF8ToUTF16(host_list[0]), |
| 128 UTF8ToUTF16(hosts[1]), | 129 UTF8ToUTF16(host_list[1]), |
| 129 base::IntToString16(hosts.size() - 2)); | 130 base::IntToString16(hosts.size() - 2)); |
| 130 break; | 131 break; |
| 131 } | 132 } |
| 132 | 133 |
| 133 return ExtensionPermissionMessage(message_id, message); | 134 return ExtensionPermissionMessage(message_id, message); |
| 134 } | 135 } |
| 135 | 136 |
| 136 ExtensionPermissionMessage::ExtensionPermissionMessage( | 137 ExtensionPermissionMessage::ExtensionPermissionMessage( |
| 137 ExtensionPermissionMessage::ID id, const string16& message) | 138 ExtensionPermissionMessage::ID id, const string16& message) |
| 138 : id_(id), message_(message) { | 139 : id_(id), message_(message) { |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 std::set<std::string> apis_str; | 448 std::set<std::string> apis_str; |
| 448 for (ExtensionAPIPermissionSet::const_iterator i = apis_.begin(); | 449 for (ExtensionAPIPermissionSet::const_iterator i = apis_.begin(); |
| 449 i != apis_.end(); ++i) { | 450 i != apis_.end(); ++i) { |
| 450 ExtensionAPIPermission* permission = info->GetByID(*i); | 451 ExtensionAPIPermission* permission = info->GetByID(*i); |
| 451 if (permission) | 452 if (permission) |
| 452 apis_str.insert(permission->name()); | 453 apis_str.insert(permission->name()); |
| 453 } | 454 } |
| 454 return apis_str; | 455 return apis_str; |
| 455 } | 456 } |
| 456 | 457 |
| 457 std::vector<std::string> | 458 std::set<std::string> |
| 458 ExtensionPermissionSet::GetDistinctHostsForDisplay() const { | 459 ExtensionPermissionSet::GetDistinctHostsForDisplay() const { |
| 459 return GetDistinctHosts(effective_hosts_.patterns(), true); | 460 return GetDistinctHosts(effective_hosts_, true); |
| 460 } | 461 } |
| 461 | 462 |
| 462 ExtensionPermissionMessages | 463 ExtensionPermissionMessages |
| 463 ExtensionPermissionSet::GetPermissionMessages() const { | 464 ExtensionPermissionSet::GetPermissionMessages() const { |
| 464 ExtensionPermissionMessages messages; | 465 ExtensionPermissionMessages messages; |
| 465 | 466 |
| 466 if (HasEffectiveFullAccess()) { | 467 if (HasEffectiveFullAccess()) { |
| 467 messages.push_back(ExtensionPermissionMessage( | 468 messages.push_back(ExtensionPermissionMessage( |
| 468 ExtensionPermissionMessage::kFullAccess, | 469 ExtensionPermissionMessage::kFullAccess, |
| 469 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS))); | 470 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS))); |
| 470 return messages; | 471 return messages; |
| 471 } | 472 } |
| 472 | 473 |
| 473 if (HasEffectiveAccessToAllHosts()) { | 474 if (HasEffectiveAccessToAllHosts()) { |
| 474 messages.push_back(ExtensionPermissionMessage( | 475 messages.push_back(ExtensionPermissionMessage( |
| 475 ExtensionPermissionMessage::kHostsAll, | 476 ExtensionPermissionMessage::kHostsAll, |
| 476 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS))); | 477 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS))); |
| 477 } else { | 478 } else { |
| 478 std::vector<std::string> hosts = GetDistinctHostsForDisplay(); | 479 std::set<std::string> hosts = GetDistinctHostsForDisplay(); |
| 479 if (!hosts.empty()) | 480 if (!hosts.empty()) |
| 480 messages.push_back(ExtensionPermissionMessage::CreateFromHostList(hosts)); | 481 messages.push_back(ExtensionPermissionMessage::CreateFromHostList(hosts)); |
| 481 } | 482 } |
| 482 | 483 |
| 483 std::set<ExtensionPermissionMessage> simple_msgs = | 484 std::set<ExtensionPermissionMessage> simple_msgs = |
| 484 GetSimplePermissionMessages(); | 485 GetSimplePermissionMessages(); |
| 485 messages.insert(messages.end(), simple_msgs.begin(), simple_msgs.end()); | 486 messages.insert(messages.end(), simple_msgs.begin(), simple_msgs.end()); |
| 486 | 487 |
| 487 return messages; | 488 return messages; |
| 488 } | 489 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 // We only need to check our host list to verify access. The host list should | 555 // We only need to check our host list to verify access. The host list should |
| 555 // already reflect any special rules (such as chrome://favicon, component | 556 // already reflect any special rules (such as chrome://favicon, component |
| 556 // all hosts access, etc.). | 557 // all hosts access, etc.). |
| 557 return scriptable_hosts().MatchesURL(origin); | 558 return scriptable_hosts().MatchesURL(origin); |
| 558 } | 559 } |
| 559 | 560 |
| 560 bool ExtensionPermissionSet::HasEffectiveAccessToAllHosts() const { | 561 bool ExtensionPermissionSet::HasEffectiveAccessToAllHosts() const { |
| 561 // There are two ways this set can have effective access to all hosts: | 562 // There are two ways this set can have effective access to all hosts: |
| 562 // 1) it has an <all_urls> URL pattern. | 563 // 1) it has an <all_urls> URL pattern. |
| 563 // 2) it has a named permission with implied full URL access. | 564 // 2) it has a named permission with implied full URL access. |
| 564 const URLPatternList patterns = effective_hosts().patterns(); | 565 for (URLPatternSet::const_iterator host = effective_hosts().begin(); |
| 565 for (URLPatternList::const_iterator host = patterns.begin(); | 566 host != effective_hosts().end(); ++host) { |
| 566 host != patterns.end(); ++host) { | |
| 567 if (host->match_all_urls() || | 567 if (host->match_all_urls() || |
| 568 (host->match_subdomains() && host->host().empty())) | 568 (host->match_subdomains() && host->host().empty())) |
| 569 return true; | 569 return true; |
| 570 } | 570 } |
| 571 | 571 |
| 572 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance(); | 572 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance(); |
| 573 for (ExtensionAPIPermissionSet::const_iterator i = apis().begin(); | 573 for (ExtensionAPIPermissionSet::const_iterator i = apis().begin(); |
| 574 i != apis().end(); ++i) { | 574 i != apis().end(); ++i) { |
| 575 ExtensionAPIPermission* permission = info->GetByID(*i); | 575 ExtensionAPIPermission* permission = info->GetByID(*i); |
| 576 if (permission->implies_full_url_access()) | 576 if (permission->implies_full_url_access()) |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 if (HasLessHostPrivilegesThan(permissions)) | 619 if (HasLessHostPrivilegesThan(permissions)) |
| 620 return true; | 620 return true; |
| 621 | 621 |
| 622 if (HasLessAPIPrivilegesThan(permissions)) | 622 if (HasLessAPIPrivilegesThan(permissions)) |
| 623 return true; | 623 return true; |
| 624 | 624 |
| 625 return false; | 625 return false; |
| 626 } | 626 } |
| 627 | 627 |
| 628 // static | 628 // static |
| 629 std::vector<std::string> ExtensionPermissionSet::GetDistinctHosts( | 629 std::set<std::string> ExtensionPermissionSet::GetDistinctHosts( |
| 630 const URLPatternList& host_patterns, bool include_rcd) { | 630 const URLPatternSet& host_patterns, bool include_rcd) { |
| 631 // Use a vector to preserve order (also faster than a map on small sets). | 631 // Use a vector to preserve order (also faster than a map on small sets). |
| 632 // Each item is a host split into two parts: host without RCDs and | 632 // Each item is a host split into two parts: host without RCDs and |
| 633 // current best RCD. | 633 // current best RCD. |
| 634 typedef std::vector<std::pair<std::string, std::string> > HostVector; | 634 typedef std::vector<std::pair<std::string, std::string> > HostVector; |
| 635 HostVector hosts_best_rcd; | 635 HostVector hosts_best_rcd; |
| 636 for (size_t i = 0; i < host_patterns.size(); ++i) { | 636 for (URLPatternSet::const_iterator i = host_patterns.begin(); |
| 637 std::string host = host_patterns[i].host(); | 637 i != host_patterns.end(); ++i) { |
| 638 std::string host = i->host(); |
| 638 | 639 |
| 639 // Add the subdomain wildcard back to the host, if necessary. | 640 // Add the subdomain wildcard back to the host, if necessary. |
| 640 if (host_patterns[i].match_subdomains()) | 641 if (i->match_subdomains()) |
| 641 host = "*." + host; | 642 host = "*." + host; |
| 642 | 643 |
| 643 // If the host has an RCD, split it off so we can detect duplicates. | 644 // If the host has an RCD, split it off so we can detect duplicates. |
| 644 std::string rcd; | 645 std::string rcd; |
| 645 size_t reg_len = net::RegistryControlledDomainService::GetRegistryLength( | 646 size_t reg_len = net::RegistryControlledDomainService::GetRegistryLength( |
| 646 host, false); | 647 host, false); |
| 647 if (reg_len && reg_len != std::string::npos) { | 648 if (reg_len && reg_len != std::string::npos) { |
| 648 if (include_rcd) // else leave rcd empty | 649 if (include_rcd) // else leave rcd empty |
| 649 rcd = host.substr(host.size() - reg_len); | 650 rcd = host.substr(host.size() - reg_len); |
| 650 host = host.substr(0, host.size() - reg_len); | 651 host = host.substr(0, host.size() - reg_len); |
| 651 } | 652 } |
| 652 | 653 |
| 653 // Check if we've already seen this host. | 654 // Check if we've already seen this host. |
| 654 HostVector::iterator it = hosts_best_rcd.begin(); | 655 HostVector::iterator it = hosts_best_rcd.begin(); |
| 655 for (; it != hosts_best_rcd.end(); ++it) { | 656 for (; it != hosts_best_rcd.end(); ++it) { |
| 656 if (it->first == host) | 657 if (it->first == host) |
| 657 break; | 658 break; |
| 658 } | 659 } |
| 659 // If this host was found, replace the RCD if this one is better. | 660 // If this host was found, replace the RCD if this one is better. |
| 660 if (it != hosts_best_rcd.end()) { | 661 if (it != hosts_best_rcd.end()) { |
| 661 if (include_rcd && RcdBetterThan(rcd, it->second)) | 662 if (include_rcd && RcdBetterThan(rcd, it->second)) |
| 662 it->second = rcd; | 663 it->second = rcd; |
| 663 } else { // Previously unseen host, append it. | 664 } else { // Previously unseen host, append it. |
| 664 hosts_best_rcd.push_back(std::make_pair(host, rcd)); | 665 hosts_best_rcd.push_back(std::make_pair(host, rcd)); |
| 665 } | 666 } |
| 666 } | 667 } |
| 667 | 668 |
| 668 // Build up the final vector by concatenating hosts and RCDs. | 669 // Build up the final vector by concatenating hosts and RCDs. |
| 669 std::vector<std::string> distinct_hosts; | 670 std::set<std::string> distinct_hosts; |
| 670 for (HostVector::iterator it = hosts_best_rcd.begin(); | 671 for (HostVector::iterator it = hosts_best_rcd.begin(); |
| 671 it != hosts_best_rcd.end(); ++it) | 672 it != hosts_best_rcd.end(); ++it) |
| 672 distinct_hosts.push_back(it->first + it->second); | 673 distinct_hosts.insert(it->first + it->second); |
| 673 return distinct_hosts; | 674 return distinct_hosts; |
| 674 } | 675 } |
| 675 | 676 |
| 676 void ExtensionPermissionSet::InitEffectiveHosts() { | 677 void ExtensionPermissionSet::InitEffectiveHosts() { |
| 677 effective_hosts_.ClearPatterns(); | 678 effective_hosts_.ClearPatterns(); |
| 678 | 679 |
| 679 if (HasEffectiveAccessToAllHosts()) { | 680 if (HasEffectiveAccessToAllHosts()) { |
| 680 URLPattern all_urls(URLPattern::SCHEME_ALL); | 681 URLPattern all_urls(URLPattern::SCHEME_ALL); |
| 681 all_urls.set_match_all_urls(true); | 682 all_urls.SetMatchAllURLs(true); |
| 682 effective_hosts_.AddPattern(all_urls); | 683 effective_hosts_.AddPattern(all_urls); |
| 683 return; | 684 return; |
| 684 } | 685 } |
| 685 | 686 |
| 686 URLPatternSet::CreateUnion( | 687 URLPatternSet::CreateUnion( |
| 687 explicit_hosts(), scriptable_hosts(), &effective_hosts_); | 688 explicit_hosts(), scriptable_hosts(), &effective_hosts_); |
| 688 } | 689 } |
| 689 | 690 |
| 690 void ExtensionPermissionSet::InitImplicitExtensionPermissions( | 691 void ExtensionPermissionSet::InitImplicitExtensionPermissions( |
| 691 const Extension* extension) { | 692 const Extension* extension) { |
| 692 // Add the implied permissions. | 693 // Add the implied permissions. |
| 693 if (!extension->plugins().empty()) | 694 if (!extension->plugins().empty()) |
| 694 apis_.insert(ExtensionAPIPermission::kPlugin); | 695 apis_.insert(ExtensionAPIPermission::kPlugin); |
| 695 | 696 |
| 696 if (!extension->devtools_url().is_empty()) | 697 if (!extension->devtools_url().is_empty()) |
| 697 apis_.insert(ExtensionAPIPermission::kDevtools); | 698 apis_.insert(ExtensionAPIPermission::kDevtools); |
| 698 | 699 |
| 699 // Add the scriptable hosts. | 700 // Add the scriptable hosts. |
| 700 for (UserScriptList::const_iterator content_script = | 701 for (UserScriptList::const_iterator content_script = |
| 701 extension->content_scripts().begin(); | 702 extension->content_scripts().begin(); |
| 702 content_script != extension->content_scripts().end(); ++content_script) { | 703 content_script != extension->content_scripts().end(); ++content_script) { |
| 703 URLPatternList::const_iterator pattern = | 704 URLPatternSet::const_iterator pattern = |
| 704 content_script->url_patterns().begin(); | 705 content_script->url_patterns().begin(); |
| 705 for (; pattern != content_script->url_patterns().end(); ++pattern) | 706 for (; pattern != content_script->url_patterns().end(); ++pattern) |
| 706 scriptable_hosts_.AddPattern(*pattern); | 707 scriptable_hosts_.AddPattern(*pattern); |
| 707 } | 708 } |
| 708 } | 709 } |
| 709 | 710 |
| 710 std::set<ExtensionPermissionMessage> | 711 std::set<ExtensionPermissionMessage> |
| 711 ExtensionPermissionSet::GetSimplePermissionMessages() const { | 712 ExtensionPermissionSet::GetSimplePermissionMessages() const { |
| 712 std::set<ExtensionPermissionMessage> messages; | 713 std::set<ExtensionPermissionMessage> messages; |
| 713 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance(); | 714 ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 const ExtensionPermissionSet* permissions) const { | 751 const ExtensionPermissionSet* permissions) const { |
| 751 // If this permission set can access any host, then it can't be elevated. | 752 // If this permission set can access any host, then it can't be elevated. |
| 752 if (HasEffectiveAccessToAllHosts()) | 753 if (HasEffectiveAccessToAllHosts()) |
| 753 return false; | 754 return false; |
| 754 | 755 |
| 755 // Likewise, if the other permission set has full host access, then it must be | 756 // Likewise, if the other permission set has full host access, then it must be |
| 756 // a privilege increase. | 757 // a privilege increase. |
| 757 if (permissions->HasEffectiveAccessToAllHosts()) | 758 if (permissions->HasEffectiveAccessToAllHosts()) |
| 758 return true; | 759 return true; |
| 759 | 760 |
| 760 const URLPatternList old_list = effective_hosts().patterns(); | 761 const URLPatternSet& old_list = effective_hosts(); |
| 761 const URLPatternList new_list = permissions->effective_hosts().patterns(); | 762 const URLPatternSet& new_list = permissions->effective_hosts(); |
| 762 | 763 |
| 763 // TODO(jstritar): This is overly conservative with respect to subdomains. | 764 // TODO(jstritar): This is overly conservative with respect to subdomains. |
| 764 // For example, going from *.google.com to www.google.com will be | 765 // For example, going from *.google.com to www.google.com will be |
| 765 // considered an elevation, even though it is not (http://crbug.com/65337). | 766 // considered an elevation, even though it is not (http://crbug.com/65337). |
| 766 std::vector<std::string> new_hosts = GetDistinctHosts(new_list, false); | 767 std::set<std::string> new_hosts_set = GetDistinctHosts(new_list, false); |
| 767 std::vector<std::string> old_hosts = GetDistinctHosts(old_list, false); | 768 std::set<std::string> old_hosts_set = GetDistinctHosts(old_list, false); |
| 768 | |
| 769 std::set<std::string> old_hosts_set(old_hosts.begin(), old_hosts.end()); | |
| 770 std::set<std::string> new_hosts_set(new_hosts.begin(), new_hosts.end()); | |
| 771 std::set<std::string> new_hosts_only; | 769 std::set<std::string> new_hosts_only; |
| 772 | 770 |
| 773 std::set_difference(new_hosts_set.begin(), new_hosts_set.end(), | 771 std::set_difference(new_hosts_set.begin(), new_hosts_set.end(), |
| 774 old_hosts_set.begin(), old_hosts_set.end(), | 772 old_hosts_set.begin(), old_hosts_set.end(), |
| 775 std::inserter(new_hosts_only, new_hosts_only.begin())); | 773 std::inserter(new_hosts_only, new_hosts_only.begin())); |
| 776 | 774 |
| 777 return !new_hosts_only.empty(); | 775 return !new_hosts_only.empty(); |
| 778 } | 776 } |
| OLD | NEW |