Extensions: Remove the legacy GetMessages/HasMessages
[chromium-blink-merge.git] / extensions / common / api / sockets / sockets_manifest_permission.cc
bloba37267a649ac255fff13c13563f3c43ea86ac1e4
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/api/sockets/sockets_manifest_permission.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/stl_util.h"
9 #include "base/strings/string_split.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "extensions/common/api/extensions_manifest_types.h"
13 #include "extensions/common/api/sockets/sockets_manifest_data.h"
14 #include "extensions/common/error_utils.h"
15 #include "extensions/common/manifest_constants.h"
16 #include "grit/extensions_strings.h"
17 #include "ipc/ipc_message.h"
18 #include "ui/base/l10n/l10n_util.h"
20 namespace extensions {
22 namespace sockets_errors {
23 const char kErrorInvalidHostPattern[] = "Invalid host:port pattern '*'";
26 namespace errors = sockets_errors;
27 using api::extensions_manifest_types::Sockets;
28 using api::extensions_manifest_types::SocketHostPatterns;
29 using content::SocketPermissionRequest;
31 namespace {
33 static bool ParseHostPattern(
34 SocketsManifestPermission* permission,
35 content::SocketPermissionRequest::OperationType operation_type,
36 const std::string& host_pattern,
37 base::string16* error) {
38 SocketPermissionEntry entry;
39 if (!SocketPermissionEntry::ParseHostPattern(
40 operation_type, host_pattern, &entry)) {
41 *error = ErrorUtils::FormatErrorMessageUTF16(
42 errors::kErrorInvalidHostPattern, host_pattern);
43 return false;
45 permission->AddPermission(entry);
46 return true;
49 static bool ParseHostPatterns(
50 SocketsManifestPermission* permission,
51 content::SocketPermissionRequest::OperationType operation_type,
52 const scoped_ptr<SocketHostPatterns>& host_patterns,
53 base::string16* error) {
54 if (!host_patterns)
55 return true;
57 if (host_patterns->as_string) {
58 return ParseHostPattern(
59 permission, operation_type, *host_patterns->as_string, error);
62 CHECK(host_patterns->as_strings);
63 for (std::vector<std::string>::const_iterator it =
64 host_patterns->as_strings->begin();
65 it != host_patterns->as_strings->end();
66 ++it) {
67 if (!ParseHostPattern(permission, operation_type, *it, error)) {
68 return false;
71 return true;
74 static void SetHostPatterns(
75 scoped_ptr<SocketHostPatterns>& host_patterns,
76 const SocketsManifestPermission* permission,
77 content::SocketPermissionRequest::OperationType operation_type) {
78 host_patterns.reset(new SocketHostPatterns());
79 host_patterns->as_strings.reset(new std::vector<std::string>());
80 for (SocketPermissionEntrySet::const_iterator it =
81 permission->entries().begin();
82 it != permission->entries().end(); ++it) {
83 if (it->pattern().type == operation_type) {
84 host_patterns->as_strings->push_back(it->GetHostPatternAsString());
89 // Helper function for adding the 'any host' permission. Determines if the
90 // message is needed from |sockets|, and adds the permission to |ids| and/or
91 // |messages|, ignoring them if they are NULL. Returns true if it added the
92 // message.
93 bool AddAnyHostMessage(const SocketPermissionEntrySet& sockets,
94 PermissionIDSet* ids,
95 PermissionMessages* messages) {
96 for (const auto& socket : sockets) {
97 if (socket.IsAddressBoundType() &&
98 socket.GetHostType() == SocketPermissionEntry::ANY_HOST) {
99 if (ids)
100 ids->insert(APIPermission::kSocketAnyHost);
101 if (messages) {
102 messages->push_back(PermissionMessage(
103 PermissionMessage::kSocketAnyHost,
104 l10n_util::GetStringUTF16(
105 IDS_EXTENSION_PROMPT_WARNING_SOCKET_ANY_HOST)));
107 return true;
110 return false;
113 // Helper function for adding subdomain socket permissions. Determines what
114 // messages are needed from |sockets|, and adds permissions to |ids| and/or
115 // |messages|, ignoring them if they are NULL.
116 void AddSubdomainHostMessage(const SocketPermissionEntrySet& sockets,
117 PermissionIDSet* ids,
118 PermissionMessages* messages) {
119 std::set<base::string16> domains;
120 for (const auto& socket : sockets) {
121 if (socket.GetHostType() == SocketPermissionEntry::HOSTS_IN_DOMAINS)
122 domains.insert(base::UTF8ToUTF16(socket.pattern().host));
124 if (!domains.empty()) {
125 // TODO(sashab): This is not correct for all languages - add proper
126 // internationalization of this string for all plural states.
127 if (messages) {
128 int id = (domains.size() == 1)
129 ? IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAIN
130 : IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAINS;
131 messages->push_back(PermissionMessage(
132 PermissionMessage::kSocketDomainHosts,
133 l10n_util::GetStringFUTF16(
134 id, base::JoinString(std::vector<base::string16>(domains.begin(),
135 domains.end()),
136 base::ASCIIToUTF16(" ")))));
138 if (ids) {
139 for (const auto& domain : domains)
140 ids->insert(APIPermission::kSocketDomainHosts, domain);
145 // Helper function for adding specific host socket permissions. Determines what
146 // messages are needed from |sockets|, and adds permissions to |ids| and/or
147 // |messages|, ignoring them if they are NULL.
148 void AddSpecificHostMessage(const SocketPermissionEntrySet& sockets,
149 PermissionIDSet* ids,
150 PermissionMessages* messages) {
151 std::set<base::string16> hostnames;
152 for (const auto& socket : sockets) {
153 if (socket.GetHostType() == SocketPermissionEntry::SPECIFIC_HOSTS)
154 hostnames.insert(base::UTF8ToUTF16(socket.pattern().host));
156 if (!hostnames.empty()) {
157 // TODO(sashab): This is not correct for all languages - add proper
158 // internationalization of this string for all plural states.
159 if (messages) {
160 int id = (hostnames.size() == 1)
161 ? IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOST
162 : IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOSTS;
163 messages->push_back(PermissionMessage(
164 PermissionMessage::kSocketSpecificHosts,
165 l10n_util::GetStringFUTF16(
166 id, base::JoinString(std::vector<base::string16>(
167 hostnames.begin(), hostnames.end()),
168 base::ASCIIToUTF16(" ")))));
170 if (ids) {
171 for (const auto& hostname : hostnames)
172 ids->insert(APIPermission::kSocketSpecificHosts, hostname);
177 // Helper function for adding the network list socket permission. Determines if
178 // the message is needed from |sockets|, and adds the permission to |ids| and/or
179 // |messages|, ignoring them if they are NULL.
180 void AddNetworkListMessage(const SocketPermissionEntrySet& sockets,
181 PermissionIDSet* ids,
182 PermissionMessages* messages) {
183 for (const auto& socket : sockets) {
184 if (socket.pattern().type == SocketPermissionRequest::NETWORK_STATE) {
185 if (ids)
186 ids->insert(APIPermission::kNetworkState);
187 if (messages) {
188 messages->push_back(
189 PermissionMessage(PermissionMessage::kNetworkState,
190 l10n_util::GetStringUTF16(
191 IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE)));
197 } // namespace
199 SocketsManifestPermission::SocketsManifestPermission() {}
201 SocketsManifestPermission::~SocketsManifestPermission() {}
203 // static
204 scoped_ptr<SocketsManifestPermission> SocketsManifestPermission::FromValue(
205 const base::Value& value,
206 base::string16* error) {
207 scoped_ptr<Sockets> sockets = Sockets::FromValue(value, error);
208 if (!sockets)
209 return scoped_ptr<SocketsManifestPermission>();
211 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
212 if (sockets->udp) {
213 if (!ParseHostPatterns(result.get(),
214 SocketPermissionRequest::UDP_BIND,
215 sockets->udp->bind,
216 error)) {
217 return scoped_ptr<SocketsManifestPermission>();
219 if (!ParseHostPatterns(result.get(),
220 SocketPermissionRequest::UDP_SEND_TO,
221 sockets->udp->send,
222 error)) {
223 return scoped_ptr<SocketsManifestPermission>();
225 if (!ParseHostPatterns(result.get(),
226 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
227 sockets->udp->multicast_membership,
228 error)) {
229 return scoped_ptr<SocketsManifestPermission>();
232 if (sockets->tcp) {
233 if (!ParseHostPatterns(result.get(),
234 SocketPermissionRequest::TCP_CONNECT,
235 sockets->tcp->connect,
236 error)) {
237 return scoped_ptr<SocketsManifestPermission>();
240 if (sockets->tcp_server) {
241 if (!ParseHostPatterns(result.get(),
242 SocketPermissionRequest::TCP_LISTEN,
243 sockets->tcp_server->listen,
244 error)) {
245 return scoped_ptr<SocketsManifestPermission>();
248 return result.Pass();
251 bool SocketsManifestPermission::CheckRequest(
252 const Extension* extension,
253 const SocketPermissionRequest& request) const {
254 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
255 it != permissions_.end();
256 ++it) {
257 if (it->Check(request))
258 return true;
260 return false;
263 std::string SocketsManifestPermission::name() const {
264 return manifest_keys::kSockets;
267 std::string SocketsManifestPermission::id() const { return name(); }
269 PermissionIDSet SocketsManifestPermission::GetPermissions() const {
270 PermissionIDSet ids;
271 AddSocketHostPermissions(permissions_, &ids, NULL);
272 return ids;
275 bool SocketsManifestPermission::FromValue(const base::Value* value) {
276 if (!value)
277 return false;
278 base::string16 error;
279 scoped_ptr<SocketsManifestPermission> manifest_permission(
280 SocketsManifestPermission::FromValue(*value, &error));
282 if (!manifest_permission)
283 return false;
285 permissions_ = manifest_permission->permissions_;
286 return true;
289 scoped_ptr<base::Value> SocketsManifestPermission::ToValue() const {
290 Sockets sockets;
292 sockets.udp.reset(new Sockets::Udp());
293 SetHostPatterns(sockets.udp->bind, this, SocketPermissionRequest::UDP_BIND);
294 SetHostPatterns(
295 sockets.udp->send, this, SocketPermissionRequest::UDP_SEND_TO);
296 SetHostPatterns(sockets.udp->multicast_membership,
297 this,
298 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP);
299 if (sockets.udp->bind->as_strings->size() == 0 &&
300 sockets.udp->send->as_strings->size() == 0 &&
301 sockets.udp->multicast_membership->as_strings->size() == 0) {
302 sockets.udp.reset(NULL);
305 sockets.tcp.reset(new Sockets::Tcp());
306 SetHostPatterns(
307 sockets.tcp->connect, this, SocketPermissionRequest::TCP_CONNECT);
308 if (sockets.tcp->connect->as_strings->size() == 0) {
309 sockets.tcp.reset(NULL);
312 sockets.tcp_server.reset(new Sockets::TcpServer());
313 SetHostPatterns(
314 sockets.tcp_server->listen, this, SocketPermissionRequest::TCP_LISTEN);
315 if (sockets.tcp_server->listen->as_strings->size() == 0) {
316 sockets.tcp_server.reset(NULL);
319 return scoped_ptr<base::Value>(sockets.ToValue().release()).Pass();
322 ManifestPermission* SocketsManifestPermission::Diff(
323 const ManifestPermission* rhs) const {
324 const SocketsManifestPermission* other =
325 static_cast<const SocketsManifestPermission*>(rhs);
327 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
328 result->permissions_ = base::STLSetDifference<SocketPermissionEntrySet>(
329 permissions_, other->permissions_);
330 return result.release();
333 ManifestPermission* SocketsManifestPermission::Union(
334 const ManifestPermission* rhs) const {
335 const SocketsManifestPermission* other =
336 static_cast<const SocketsManifestPermission*>(rhs);
338 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
339 result->permissions_ = base::STLSetUnion<SocketPermissionEntrySet>(
340 permissions_, other->permissions_);
341 return result.release();
344 ManifestPermission* SocketsManifestPermission::Intersect(
345 const ManifestPermission* rhs) const {
346 const SocketsManifestPermission* other =
347 static_cast<const SocketsManifestPermission*>(rhs);
349 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
350 result->permissions_ = base::STLSetIntersection<SocketPermissionEntrySet>(
351 permissions_, other->permissions_);
352 return result.release();
355 void SocketsManifestPermission::AddPermission(
356 const SocketPermissionEntry& entry) {
357 permissions_.insert(entry);
360 // static
361 void SocketsManifestPermission::AddSocketHostPermissions(
362 const SocketPermissionEntrySet& sockets,
363 PermissionIDSet* ids,
364 PermissionMessages* messages) {
365 if (!AddAnyHostMessage(sockets, ids, messages)) {
366 AddSpecificHostMessage(sockets, ids, messages);
367 AddSubdomainHostMessage(sockets, ids, messages);
369 AddNetworkListMessage(sockets, ids, messages);
372 } // namespace extensions