Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / extensions / common / api / sockets / sockets_manifest_permission.cc
blob455d1dad308645537a992deba9d7cbd06caa0ac5
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;
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 (SocketsManifestPermission::SocketPermissionEntrySet::const_iterator it =
81 permission->entries().begin();
82 it != permission->entries().end();
83 ++it) {
84 if (it->pattern().type == operation_type) {
85 host_patterns->as_strings->push_back(it->GetHostPatternAsString());
90 } // namespace
92 SocketsManifestPermission::SocketsManifestPermission() {}
94 SocketsManifestPermission::~SocketsManifestPermission() {}
96 // static
97 scoped_ptr<SocketsManifestPermission> SocketsManifestPermission::FromValue(
98 const base::Value& value,
99 base::string16* error) {
100 scoped_ptr<Sockets> sockets = Sockets::FromValue(value, error);
101 if (!sockets)
102 return scoped_ptr<SocketsManifestPermission>();
104 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
105 if (sockets->udp) {
106 if (!ParseHostPatterns(result.get(),
107 SocketPermissionRequest::UDP_BIND,
108 sockets->udp->bind,
109 error)) {
110 return scoped_ptr<SocketsManifestPermission>();
112 if (!ParseHostPatterns(result.get(),
113 SocketPermissionRequest::UDP_SEND_TO,
114 sockets->udp->send,
115 error)) {
116 return scoped_ptr<SocketsManifestPermission>();
118 if (!ParseHostPatterns(result.get(),
119 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
120 sockets->udp->multicast_membership,
121 error)) {
122 return scoped_ptr<SocketsManifestPermission>();
125 if (sockets->tcp) {
126 if (!ParseHostPatterns(result.get(),
127 SocketPermissionRequest::TCP_CONNECT,
128 sockets->tcp->connect,
129 error)) {
130 return scoped_ptr<SocketsManifestPermission>();
133 if (sockets->tcp_server) {
134 if (!ParseHostPatterns(result.get(),
135 SocketPermissionRequest::TCP_LISTEN,
136 sockets->tcp_server->listen,
137 error)) {
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();
149 ++it) {
150 if (it->Check(request))
151 return true;
153 return false;
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();
164 return !is_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);
176 return result;
179 bool SocketsManifestPermission::FromValue(const base::Value* value) {
180 if (!value)
181 return false;
182 base::string16 error;
183 scoped_ptr<SocketsManifestPermission> manifest_permission(
184 SocketsManifestPermission::FromValue(*value, &error));
186 if (!manifest_permission)
187 return false;
189 permissions_ = manifest_permission->permissions_;
190 return true;
193 scoped_ptr<base::Value> SocketsManifestPermission::ToValue() const {
194 Sockets sockets;
196 sockets.udp.reset(new Sockets::Udp());
197 SetHostPatterns(sockets.udp->bind, this, SocketPermissionRequest::UDP_BIND);
198 SetHostPatterns(
199 sockets.udp->send, this, SocketPermissionRequest::UDP_SEND_TO);
200 SetHostPatterns(sockets.udp->multicast_membership,
201 this,
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());
210 SetHostPatterns(
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());
217 SetHostPatterns(
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::Diff(
227 const ManifestPermission* rhs) const {
228 const SocketsManifestPermission* other =
229 static_cast<const SocketsManifestPermission*>(rhs);
231 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
232 result->permissions_ = base::STLSetDifference<SocketPermissionEntrySet>(
233 permissions_, other->permissions_);
234 return result.release();
237 ManifestPermission* SocketsManifestPermission::Union(
238 const ManifestPermission* rhs) const {
239 const SocketsManifestPermission* other =
240 static_cast<const SocketsManifestPermission*>(rhs);
242 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
243 result->permissions_ = base::STLSetUnion<SocketPermissionEntrySet>(
244 permissions_, other->permissions_);
245 return result.release();
248 ManifestPermission* SocketsManifestPermission::Intersect(
249 const ManifestPermission* rhs) const {
250 const SocketsManifestPermission* other =
251 static_cast<const SocketsManifestPermission*>(rhs);
253 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
254 result->permissions_ = base::STLSetIntersection<SocketPermissionEntrySet>(
255 permissions_, other->permissions_);
256 return result.release();
259 void SocketsManifestPermission::AddPermission(
260 const SocketPermissionEntry& entry) {
261 permissions_.insert(entry);
264 bool SocketsManifestPermission::AddAnyHostMessage(
265 PermissionMessages& messages) const {
266 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
267 it != permissions_.end();
268 ++it) {
269 if (it->IsAddressBoundType() &&
270 it->GetHostType() == SocketPermissionEntry::ANY_HOST) {
271 messages.push_back(
272 PermissionMessage(PermissionMessage::kSocketAnyHost,
273 l10n_util::GetStringUTF16(
274 IDS_EXTENSION_PROMPT_WARNING_SOCKET_ANY_HOST)));
275 return true;
278 return false;
281 void SocketsManifestPermission::AddSubdomainHostMessage(
282 PermissionMessages& messages) const {
283 std::set<base::string16> domains;
284 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
285 it != permissions_.end();
286 ++it) {
287 if (it->GetHostType() == SocketPermissionEntry::HOSTS_IN_DOMAINS)
288 domains.insert(base::UTF8ToUTF16(it->pattern().host));
290 if (!domains.empty()) {
291 int id = (domains.size() == 1)
292 ? IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAIN
293 : IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAINS;
294 messages.push_back(PermissionMessage(
295 PermissionMessage::kSocketDomainHosts,
296 l10n_util::GetStringFUTF16(
298 JoinString(
299 std::vector<base::string16>(domains.begin(), domains.end()),
300 ' '))));
304 void SocketsManifestPermission::AddSpecificHostMessage(
305 PermissionMessages& messages) const {
306 std::set<base::string16> hostnames;
307 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
308 it != permissions_.end();
309 ++it) {
310 if (it->GetHostType() == SocketPermissionEntry::SPECIFIC_HOSTS)
311 hostnames.insert(base::UTF8ToUTF16(it->pattern().host));
313 if (!hostnames.empty()) {
314 int id = (hostnames.size() == 1)
315 ? IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOST
316 : IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOSTS;
317 messages.push_back(PermissionMessage(
318 PermissionMessage::kSocketSpecificHosts,
319 l10n_util::GetStringFUTF16(
321 JoinString(
322 std::vector<base::string16>(hostnames.begin(), hostnames.end()),
323 ' '))));
327 void SocketsManifestPermission::AddNetworkListMessage(
328 PermissionMessages& messages) const {
329 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
330 it != permissions_.end();
331 ++it) {
332 if (it->pattern().type == SocketPermissionRequest::NETWORK_STATE) {
333 messages.push_back(
334 PermissionMessage(PermissionMessage::kNetworkState,
335 l10n_util::GetStringUTF16(
336 IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE)));
341 } // namespace extensions