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/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "extensions/common/api/extensions_manifest_types.h"
12 #include "extensions/common/api/sockets/sockets_manifest_data.h"
13 #include "extensions/common/error_utils.h"
14 #include "extensions/common/extension_messages.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 core_api::extensions_manifest_types::Sockets;
28 using core_api::extensions_manifest_types::SocketHostPatterns;
29 using content::SocketPermissionRequest;
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);
45 permission->AddPermission(entry);
49 static bool ParseHostPatterns(
50 SocketsManifestPermission* permission,
51 content::SocketPermissionRequest::OperationType operation_type,
52 const scoped_ptr<SocketHostPatterns>& host_patterns,
53 base::string16* error) {
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();
67 if (!ParseHostPattern(permission, operation_type, *it, error)) {
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 (SocketsManifestPermission::SocketPermissionEntrySet::const_iterator it =
81 permission->entries().begin();
82 it != permission->entries().end();
84 if (it->pattern().type == operation_type) {
85 host_patterns->as_strings->push_back(it->GetHostPatternAsString());
92 SocketsManifestPermission::SocketsManifestPermission() {}
94 SocketsManifestPermission::~SocketsManifestPermission() {}
97 scoped_ptr<SocketsManifestPermission> SocketsManifestPermission::FromValue(
98 const base::Value& value,
99 base::string16* error) {
100 scoped_ptr<Sockets> sockets = Sockets::FromValue(value, error);
102 return scoped_ptr<SocketsManifestPermission>();
104 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
106 if (!ParseHostPatterns(result.get(),
107 SocketPermissionRequest::UDP_BIND,
110 return scoped_ptr<SocketsManifestPermission>();
112 if (!ParseHostPatterns(result.get(),
113 SocketPermissionRequest::UDP_SEND_TO,
116 return scoped_ptr<SocketsManifestPermission>();
118 if (!ParseHostPatterns(result.get(),
119 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
120 sockets->udp->multicast_membership,
122 return scoped_ptr<SocketsManifestPermission>();
126 if (!ParseHostPatterns(result.get(),
127 SocketPermissionRequest::TCP_CONNECT,
128 sockets->tcp->connect,
130 return scoped_ptr<SocketsManifestPermission>();
133 if (sockets->tcp_server) {
134 if (!ParseHostPatterns(result.get(),
135 SocketPermissionRequest::TCP_LISTEN,
136 sockets->tcp_server->listen,
138 return scoped_ptr<SocketsManifestPermission>();
141 return result.Pass();
144 bool SocketsManifestPermission::CheckRequest(
145 const Extension* extension,
146 const SocketPermissionRequest& request) const {
147 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
148 it != permissions_.end();
150 if (it->Check(request))
156 std::string SocketsManifestPermission::name() const {
157 return manifest_keys::kSockets;
160 std::string SocketsManifestPermission::id() const { return name(); }
162 bool SocketsManifestPermission::HasMessages() const {
163 bool is_empty = permissions_.empty();
167 PermissionMessages SocketsManifestPermission::GetMessages() const {
168 // TODO(rpaquay): This function and callees is (almost) a copy/paste
169 // from extensions::SocketPermissiona.
170 PermissionMessages result;
171 if (!AddAnyHostMessage(result)) {
172 AddSpecificHostMessage(result);
173 AddSubdomainHostMessage(result);
175 AddNetworkListMessage(result);
179 bool SocketsManifestPermission::FromValue(const base::Value* value) {
182 base::string16 error;
183 scoped_ptr<SocketsManifestPermission> manifest_permission(
184 SocketsManifestPermission::FromValue(*value, &error));
186 if (!manifest_permission)
189 permissions_ = manifest_permission->permissions_;
193 scoped_ptr<base::Value> SocketsManifestPermission::ToValue() const {
196 sockets.udp.reset(new Sockets::Udp());
197 SetHostPatterns(sockets.udp->bind, this, SocketPermissionRequest::UDP_BIND);
199 sockets.udp->send, this, SocketPermissionRequest::UDP_SEND_TO);
200 SetHostPatterns(sockets.udp->multicast_membership,
202 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP);
203 if (sockets.udp->bind->as_strings->size() == 0 &&
204 sockets.udp->send->as_strings->size() == 0 &&
205 sockets.udp->multicast_membership->as_strings->size() == 0) {
206 sockets.udp.reset(NULL);
209 sockets.tcp.reset(new Sockets::Tcp());
211 sockets.tcp->connect, this, SocketPermissionRequest::TCP_CONNECT);
212 if (sockets.tcp->connect->as_strings->size() == 0) {
213 sockets.tcp.reset(NULL);
216 sockets.tcp_server.reset(new Sockets::TcpServer());
218 sockets.tcp_server->listen, this, SocketPermissionRequest::TCP_LISTEN);
219 if (sockets.tcp_server->listen->as_strings->size() == 0) {
220 sockets.tcp_server.reset(NULL);
223 return scoped_ptr<base::Value>(sockets.ToValue().release()).Pass();
226 ManifestPermission* SocketsManifestPermission::Clone() const {
227 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
228 result->permissions_ = permissions_;
229 return result.release();
232 ManifestPermission* SocketsManifestPermission::Diff(
233 const ManifestPermission* rhs) const {
234 const SocketsManifestPermission* other =
235 static_cast<const SocketsManifestPermission*>(rhs);
237 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
238 result->permissions_ = base::STLSetDifference<SocketPermissionEntrySet>(
239 permissions_, other->permissions_);
240 return result.release();
243 ManifestPermission* SocketsManifestPermission::Union(
244 const ManifestPermission* rhs) const {
245 const SocketsManifestPermission* other =
246 static_cast<const SocketsManifestPermission*>(rhs);
248 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
249 result->permissions_ = base::STLSetUnion<SocketPermissionEntrySet>(
250 permissions_, other->permissions_);
251 return result.release();
254 ManifestPermission* SocketsManifestPermission::Intersect(
255 const ManifestPermission* rhs) const {
256 const SocketsManifestPermission* other =
257 static_cast<const SocketsManifestPermission*>(rhs);
259 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
260 result->permissions_ = base::STLSetIntersection<SocketPermissionEntrySet>(
261 permissions_, other->permissions_);
262 return result.release();
265 bool SocketsManifestPermission::Contains(const ManifestPermission* rhs) const {
266 const SocketsManifestPermission* other =
267 static_cast<const SocketsManifestPermission*>(rhs);
269 return base::STLIncludes<SocketPermissionEntrySet>(permissions_,
270 other->permissions_);
273 bool SocketsManifestPermission::Equal(const ManifestPermission* rhs) const {
274 const SocketsManifestPermission* other =
275 static_cast<const SocketsManifestPermission*>(rhs);
277 return (permissions_ == other->permissions_);
280 void SocketsManifestPermission::Write(IPC::Message* m) const {
281 IPC::WriteParam(m, permissions_);
284 bool SocketsManifestPermission::Read(const IPC::Message* m,
285 PickleIterator* iter) {
286 return IPC::ReadParam(m, iter, &permissions_);
289 void SocketsManifestPermission::Log(std::string* log) const {
290 IPC::LogParam(permissions_, log);
293 void SocketsManifestPermission::AddPermission(
294 const SocketPermissionEntry& entry) {
295 permissions_.insert(entry);
298 bool SocketsManifestPermission::AddAnyHostMessage(
299 PermissionMessages& messages) const {
300 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
301 it != permissions_.end();
303 if (it->IsAddressBoundType() &&
304 it->GetHostType() == SocketPermissionEntry::ANY_HOST) {
306 PermissionMessage(PermissionMessage::kSocketAnyHost,
307 l10n_util::GetStringUTF16(
308 IDS_EXTENSION_PROMPT_WARNING_SOCKET_ANY_HOST)));
315 void SocketsManifestPermission::AddSubdomainHostMessage(
316 PermissionMessages& messages) const {
317 std::set<base::string16> domains;
318 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
319 it != permissions_.end();
321 if (it->GetHostType() == SocketPermissionEntry::HOSTS_IN_DOMAINS)
322 domains.insert(base::UTF8ToUTF16(it->pattern().host));
324 if (!domains.empty()) {
325 int id = (domains.size() == 1)
326 ? IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAIN
327 : IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAINS;
328 messages.push_back(PermissionMessage(
329 PermissionMessage::kSocketDomainHosts,
330 l10n_util::GetStringFUTF16(
333 std::vector<base::string16>(domains.begin(), domains.end()),
338 void SocketsManifestPermission::AddSpecificHostMessage(
339 PermissionMessages& messages) const {
340 std::set<base::string16> hostnames;
341 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
342 it != permissions_.end();
344 if (it->GetHostType() == SocketPermissionEntry::SPECIFIC_HOSTS)
345 hostnames.insert(base::UTF8ToUTF16(it->pattern().host));
347 if (!hostnames.empty()) {
348 int id = (hostnames.size() == 1)
349 ? IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOST
350 : IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOSTS;
351 messages.push_back(PermissionMessage(
352 PermissionMessage::kSocketSpecificHosts,
353 l10n_util::GetStringFUTF16(
356 std::vector<base::string16>(hostnames.begin(), hostnames.end()),
361 void SocketsManifestPermission::AddNetworkListMessage(
362 PermissionMessages& messages) const {
363 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
364 it != permissions_.end();
366 if (it->pattern().type == SocketPermissionRequest::NETWORK_STATE) {
368 PermissionMessage(PermissionMessage::kNetworkState,
369 l10n_util::GetStringUTF16(
370 IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE)));
375 } // namespace extensions