Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / common / permissions / permission_message_util.cc
blob566fe8526ad2b56fd3a9e3c3eb49bbb680e3395f
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
3 // found in the LICENSE file.
5 #include "extensions/common/permissions/permission_message_util.h"
7 #include "base/macros.h"
8 #include "base/strings/string_split.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "extensions/common/permissions/api_permission_set.h"
11 #include "extensions/common/url_pattern_set.h"
12 #include "grit/extensions_strings.h"
13 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
14 #include "ui/base/l10n/l10n_util.h"
15 #include "url/url_constants.h"
17 using extensions::URLPatternSet;
19 namespace {
21 // Helper for GetDistinctHosts(): com > net > org > everything else.
22 bool RcdBetterThan(const std::string& a, const std::string& b) {
23 if (a == b)
24 return false;
25 if (a == "com")
26 return true;
27 if (a == "net")
28 return b != "com";
29 if (a == "org")
30 return b != "com" && b != "net";
31 return false;
34 } // namespace
36 namespace permission_message_util {
38 // The number of host messages supported. The first N - 1 of these messages are
39 // specific for the number of hosts; the last one is a catch-all for N or more
40 // hosts.
41 static const int kNumMessages = 4;
43 std::vector<base::string16> GetHostListFromHosts(
44 const std::set<std::string>& hosts,
45 PermissionMessageProperties properties) {
46 int host_msg_id = hosts.size() < kNumMessages
47 ? IDS_EXTENSION_PROMPT_WARNING_HOST_AND_SUBDOMAIN
48 : IDS_EXTENSION_PROMPT_WARNING_HOST_AND_SUBDOMAIN_LIST;
49 std::vector<base::string16> host_list;
50 for (std::set<std::string>::const_iterator it = hosts.begin();
51 it != hosts.end();
52 ++it) {
53 std::string host = *it;
54 host_list.push_back(
55 host[0] == '*' && host[1] == '.'
56 ? l10n_util::GetStringFUTF16(host_msg_id,
57 base::UTF8ToUTF16(host.erase(0, 2)))
58 : base::UTF8ToUTF16(host));
60 DCHECK(host_list.size());
61 return host_list;
64 void AddHostPermissions(extensions::PermissionIDSet* permissions,
65 const std::set<std::string>& hosts,
66 PermissionMessageProperties properties) {
67 std::vector<base::string16> host_list =
68 GetHostListFromHosts(hosts, properties);
70 // Create a separate permission for each host, and add it to the permissions
71 // list.
72 // TODO(sashab): Add coalescing rules for kHostReadOnly and kHostReadWrite
73 // to mimic the current behavior of CreateFromHostList() above.
74 for (const auto& host : host_list) {
75 permissions->insert(properties == kReadOnly
76 ? extensions::APIPermission::kHostReadOnly
77 : extensions::APIPermission::kHostReadWrite,
78 host);
82 std::set<std::string> GetDistinctHosts(const URLPatternSet& host_patterns,
83 bool include_rcd,
84 bool exclude_file_scheme) {
85 // Use a vector to preserve order (also faster than a map on small sets).
86 // Each item is a host split into two parts: host without RCDs and
87 // current best RCD.
88 typedef base::StringPairs HostVector;
89 HostVector hosts_best_rcd;
90 for (URLPatternSet::const_iterator i = host_patterns.begin();
91 i != host_patterns.end();
92 ++i) {
93 if (exclude_file_scheme && i->scheme() == url::kFileScheme)
94 continue;
96 std::string host = i->host();
98 // Add the subdomain wildcard back to the host, if necessary.
99 if (i->match_subdomains())
100 host = "*." + host;
102 // If the host has an RCD, split it off so we can detect duplicates.
103 std::string rcd;
104 size_t reg_len = net::registry_controlled_domains::GetRegistryLength(
105 host,
106 net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
107 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
108 if (reg_len && reg_len != std::string::npos) {
109 if (include_rcd) // else leave rcd empty
110 rcd = host.substr(host.size() - reg_len);
111 host = host.substr(0, host.size() - reg_len);
114 // Check if we've already seen this host.
115 HostVector::iterator it = hosts_best_rcd.begin();
116 for (; it != hosts_best_rcd.end(); ++it) {
117 if (it->first == host)
118 break;
120 // If this host was found, replace the RCD if this one is better.
121 if (it != hosts_best_rcd.end()) {
122 if (include_rcd && RcdBetterThan(rcd, it->second))
123 it->second = rcd;
124 } else { // Previously unseen host, append it.
125 hosts_best_rcd.push_back(std::make_pair(host, rcd));
129 // Build up the final vector by concatenating hosts and RCDs.
130 std::set<std::string> distinct_hosts;
131 for (HostVector::iterator it = hosts_best_rcd.begin();
132 it != hosts_best_rcd.end();
133 ++it)
134 distinct_hosts.insert(it->first + it->second);
135 return distinct_hosts;
138 } // namespace permission_message_util