Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / extensions / common / api / sockets / sockets_manifest_permission.cc
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.
4
5 #include "extensions/common/api/sockets/sockets_manifest_permission.h"
6
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"
19
20 namespace extensions {
21
22 namespace sockets_errors {
23 const char kErrorInvalidHostPattern[] = "Invalid host:port pattern '*'";
24 }
25
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;
30
31 namespace {
32
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;
44   }
45   permission->AddPermission(entry);
46   return true;
47 }
48
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;
56
57   if (host_patterns->as_string) {
58     return ParseHostPattern(
59         permission, operation_type, *host_patterns->as_string, error);
60   }
61
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;
69     }
70   }
71   return true;
72 }
73
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());
86     }
87   }
88 }
89
90 }  // namespace
91
92 SocketsManifestPermission::SocketsManifestPermission() {}
93
94 SocketsManifestPermission::~SocketsManifestPermission() {}
95
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>();
103
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>();
111     }
112     if (!ParseHostPatterns(result.get(),
113                            SocketPermissionRequest::UDP_SEND_TO,
114                            sockets->udp->send,
115                            error)) {
116       return scoped_ptr<SocketsManifestPermission>();
117     }
118     if (!ParseHostPatterns(result.get(),
119                            SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
120                            sockets->udp->multicast_membership,
121                            error)) {
122       return scoped_ptr<SocketsManifestPermission>();
123     }
124   }
125   if (sockets->tcp) {
126     if (!ParseHostPatterns(result.get(),
127                            SocketPermissionRequest::TCP_CONNECT,
128                            sockets->tcp->connect,
129                            error)) {
130       return scoped_ptr<SocketsManifestPermission>();
131     }
132   }
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>();
139     }
140   }
141   return result.Pass();
142 }
143
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;
152   }
153   return false;
154 }
155
156 std::string SocketsManifestPermission::name() const {
157   return manifest_keys::kSockets;
158 }
159
160 std::string SocketsManifestPermission::id() const { return name(); }
161
162 bool SocketsManifestPermission::HasMessages() const {
163   bool is_empty = permissions_.empty();
164   return !is_empty;
165 }
166
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);
174   }
175   AddNetworkListMessage(result);
176   return result;
177 }
178
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));
185
186   if (!manifest_permission)
187     return false;
188
189   permissions_ = manifest_permission->permissions_;
190   return true;
191 }
192
193 scoped_ptr<base::Value> SocketsManifestPermission::ToValue() const {
194   Sockets sockets;
195
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);
207   }
208
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);
214   }
215
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);
221   }
222
223   return scoped_ptr<base::Value>(sockets.ToValue().release()).Pass();
224 }
225
226 ManifestPermission* SocketsManifestPermission::Clone() const {
227   scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
228   result->permissions_ = permissions_;
229   return result.release();
230 }
231
232 ManifestPermission* SocketsManifestPermission::Diff(
233     const ManifestPermission* rhs) const {
234   const SocketsManifestPermission* other =
235       static_cast<const SocketsManifestPermission*>(rhs);
236
237   scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
238   result->permissions_ = base::STLSetDifference<SocketPermissionEntrySet>(
239       permissions_, other->permissions_);
240   return result.release();
241 }
242
243 ManifestPermission* SocketsManifestPermission::Union(
244     const ManifestPermission* rhs) const {
245   const SocketsManifestPermission* other =
246       static_cast<const SocketsManifestPermission*>(rhs);
247
248   scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
249   result->permissions_ = base::STLSetUnion<SocketPermissionEntrySet>(
250       permissions_, other->permissions_);
251   return result.release();
252 }
253
254 ManifestPermission* SocketsManifestPermission::Intersect(
255     const ManifestPermission* rhs) const {
256   const SocketsManifestPermission* other =
257       static_cast<const SocketsManifestPermission*>(rhs);
258
259   scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
260   result->permissions_ = base::STLSetIntersection<SocketPermissionEntrySet>(
261       permissions_, other->permissions_);
262   return result.release();
263 }
264
265 bool SocketsManifestPermission::Contains(const ManifestPermission* rhs) const {
266   const SocketsManifestPermission* other =
267       static_cast<const SocketsManifestPermission*>(rhs);
268
269   return base::STLIncludes<SocketPermissionEntrySet>(permissions_,
270                                                      other->permissions_);
271 }
272
273 bool SocketsManifestPermission::Equal(const ManifestPermission* rhs) const {
274   const SocketsManifestPermission* other =
275       static_cast<const SocketsManifestPermission*>(rhs);
276
277   return (permissions_ == other->permissions_);
278 }
279
280 void SocketsManifestPermission::Write(IPC::Message* m) const {
281   IPC::WriteParam(m, permissions_);
282 }
283
284 bool SocketsManifestPermission::Read(const IPC::Message* m,
285                                      PickleIterator* iter) {
286   return IPC::ReadParam(m, iter, &permissions_);
287 }
288
289 void SocketsManifestPermission::Log(std::string* log) const {
290   IPC::LogParam(permissions_, log);
291 }
292
293 void SocketsManifestPermission::AddPermission(
294     const SocketPermissionEntry& entry) {
295   permissions_.insert(entry);
296 }
297
298 bool SocketsManifestPermission::AddAnyHostMessage(
299     PermissionMessages& messages) const {
300   for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
301        it != permissions_.end();
302        ++it) {
303     if (it->IsAddressBoundType() &&
304         it->GetHostType() == SocketPermissionEntry::ANY_HOST) {
305       messages.push_back(
306           PermissionMessage(PermissionMessage::kSocketAnyHost,
307                             l10n_util::GetStringUTF16(
308                                 IDS_EXTENSION_PROMPT_WARNING_SOCKET_ANY_HOST)));
309       return true;
310     }
311   }
312   return false;
313 }
314
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();
320        ++it) {
321     if (it->GetHostType() == SocketPermissionEntry::HOSTS_IN_DOMAINS)
322       domains.insert(base::UTF8ToUTF16(it->pattern().host));
323   }
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(
331             id,
332             JoinString(
333                 std::vector<base::string16>(domains.begin(), domains.end()),
334                 ' '))));
335   }
336 }
337
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();
343        ++it) {
344     if (it->GetHostType() == SocketPermissionEntry::SPECIFIC_HOSTS)
345       hostnames.insert(base::UTF8ToUTF16(it->pattern().host));
346   }
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(
354             id,
355             JoinString(
356                 std::vector<base::string16>(hostnames.begin(), hostnames.end()),
357                 ' '))));
358   }
359 }
360
361 void SocketsManifestPermission::AddNetworkListMessage(
362     PermissionMessages& messages) const {
363   for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
364        it != permissions_.end();
365        ++it) {
366     if (it->pattern().type == SocketPermissionRequest::NETWORK_STATE) {
367       messages.push_back(
368           PermissionMessage(PermissionMessage::kNetworkState,
369                             l10n_util::GetStringUTF16(
370                                 IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE)));
371     }
372   }
373 }
374
375 }  // namespace extensions