Upstream version 10.39.225.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/manifest_constants.h"
15 #include "grit/extensions_strings.h"
16 #include "ipc/ipc_message.h"
17 #include "ui/base/l10n/l10n_util.h"
18
19 namespace extensions {
20
21 namespace sockets_errors {
22 const char kErrorInvalidHostPattern[] = "Invalid host:port pattern '*'";
23 }
24
25 namespace errors = sockets_errors;
26 using core_api::extensions_manifest_types::Sockets;
27 using core_api::extensions_manifest_types::SocketHostPatterns;
28 using content::SocketPermissionRequest;
29
30 namespace {
31
32 static bool ParseHostPattern(
33     SocketsManifestPermission* permission,
34     content::SocketPermissionRequest::OperationType operation_type,
35     const std::string& host_pattern,
36     base::string16* error) {
37   SocketPermissionEntry entry;
38   if (!SocketPermissionEntry::ParseHostPattern(
39           operation_type, host_pattern, &entry)) {
40     *error = ErrorUtils::FormatErrorMessageUTF16(
41         errors::kErrorInvalidHostPattern, host_pattern);
42     return false;
43   }
44   permission->AddPermission(entry);
45   return true;
46 }
47
48 static bool ParseHostPatterns(
49     SocketsManifestPermission* permission,
50     content::SocketPermissionRequest::OperationType operation_type,
51     const scoped_ptr<SocketHostPatterns>& host_patterns,
52     base::string16* error) {
53   if (!host_patterns)
54     return true;
55
56   if (host_patterns->as_string) {
57     return ParseHostPattern(
58         permission, operation_type, *host_patterns->as_string, error);
59   }
60
61   CHECK(host_patterns->as_strings);
62   for (std::vector<std::string>::const_iterator it =
63            host_patterns->as_strings->begin();
64        it != host_patterns->as_strings->end();
65        ++it) {
66     if (!ParseHostPattern(permission, operation_type, *it, error)) {
67       return false;
68     }
69   }
70   return true;
71 }
72
73 static void SetHostPatterns(
74     scoped_ptr<SocketHostPatterns>& host_patterns,
75     const SocketsManifestPermission* permission,
76     content::SocketPermissionRequest::OperationType operation_type) {
77   host_patterns.reset(new SocketHostPatterns());
78   host_patterns->as_strings.reset(new std::vector<std::string>());
79   for (SocketsManifestPermission::SocketPermissionEntrySet::const_iterator it =
80            permission->entries().begin();
81        it != permission->entries().end();
82        ++it) {
83     if (it->pattern().type == operation_type) {
84       host_patterns->as_strings->push_back(it->GetHostPatternAsString());
85     }
86   }
87 }
88
89 }  // namespace
90
91 SocketsManifestPermission::SocketsManifestPermission() {}
92
93 SocketsManifestPermission::~SocketsManifestPermission() {}
94
95 // static
96 scoped_ptr<SocketsManifestPermission> SocketsManifestPermission::FromValue(
97     const base::Value& value,
98     base::string16* error) {
99   scoped_ptr<Sockets> sockets = Sockets::FromValue(value, error);
100   if (!sockets)
101     return scoped_ptr<SocketsManifestPermission>();
102
103   scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
104   if (sockets->udp) {
105     if (!ParseHostPatterns(result.get(),
106                            SocketPermissionRequest::UDP_BIND,
107                            sockets->udp->bind,
108                            error)) {
109       return scoped_ptr<SocketsManifestPermission>();
110     }
111     if (!ParseHostPatterns(result.get(),
112                            SocketPermissionRequest::UDP_SEND_TO,
113                            sockets->udp->send,
114                            error)) {
115       return scoped_ptr<SocketsManifestPermission>();
116     }
117     if (!ParseHostPatterns(result.get(),
118                            SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
119                            sockets->udp->multicast_membership,
120                            error)) {
121       return scoped_ptr<SocketsManifestPermission>();
122     }
123   }
124   if (sockets->tcp) {
125     if (!ParseHostPatterns(result.get(),
126                            SocketPermissionRequest::TCP_CONNECT,
127                            sockets->tcp->connect,
128                            error)) {
129       return scoped_ptr<SocketsManifestPermission>();
130     }
131   }
132   if (sockets->tcp_server) {
133     if (!ParseHostPatterns(result.get(),
134                            SocketPermissionRequest::TCP_LISTEN,
135                            sockets->tcp_server->listen,
136                            error)) {
137       return scoped_ptr<SocketsManifestPermission>();
138     }
139   }
140   return result.Pass();
141 }
142
143 bool SocketsManifestPermission::CheckRequest(
144     const Extension* extension,
145     const SocketPermissionRequest& request) const {
146   for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
147        it != permissions_.end();
148        ++it) {
149     if (it->Check(request))
150       return true;
151   }
152   return false;
153 }
154
155 std::string SocketsManifestPermission::name() const {
156   return manifest_keys::kSockets;
157 }
158
159 std::string SocketsManifestPermission::id() const { return name(); }
160
161 bool SocketsManifestPermission::HasMessages() const {
162   bool is_empty = permissions_.empty();
163   return !is_empty;
164 }
165
166 PermissionMessages SocketsManifestPermission::GetMessages() const {
167   // TODO(rpaquay): This function and callees is (almost) a copy/paste
168   // from extensions::SocketPermissiona.
169   PermissionMessages result;
170   if (!AddAnyHostMessage(result)) {
171     AddSpecificHostMessage(result);
172     AddSubdomainHostMessage(result);
173   }
174   AddNetworkListMessage(result);
175   return result;
176 }
177
178 bool SocketsManifestPermission::FromValue(const base::Value* value) {
179   if (!value)
180     return false;
181   base::string16 error;
182   scoped_ptr<SocketsManifestPermission> manifest_permission(
183       SocketsManifestPermission::FromValue(*value, &error));
184
185   if (!manifest_permission)
186     return false;
187
188   permissions_ = manifest_permission->permissions_;
189   return true;
190 }
191
192 scoped_ptr<base::Value> SocketsManifestPermission::ToValue() const {
193   Sockets sockets;
194
195   sockets.udp.reset(new Sockets::Udp());
196   SetHostPatterns(sockets.udp->bind, this, SocketPermissionRequest::UDP_BIND);
197   SetHostPatterns(
198       sockets.udp->send, this, SocketPermissionRequest::UDP_SEND_TO);
199   SetHostPatterns(sockets.udp->multicast_membership,
200                   this,
201                   SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP);
202   if (sockets.udp->bind->as_strings->size() == 0 &&
203       sockets.udp->send->as_strings->size() == 0 &&
204       sockets.udp->multicast_membership->as_strings->size() == 0) {
205     sockets.udp.reset(NULL);
206   }
207
208   sockets.tcp.reset(new Sockets::Tcp());
209   SetHostPatterns(
210       sockets.tcp->connect, this, SocketPermissionRequest::TCP_CONNECT);
211   if (sockets.tcp->connect->as_strings->size() == 0) {
212     sockets.tcp.reset(NULL);
213   }
214
215   sockets.tcp_server.reset(new Sockets::TcpServer());
216   SetHostPatterns(
217       sockets.tcp_server->listen, this, SocketPermissionRequest::TCP_LISTEN);
218   if (sockets.tcp_server->listen->as_strings->size() == 0) {
219     sockets.tcp_server.reset(NULL);
220   }
221
222   return scoped_ptr<base::Value>(sockets.ToValue().release()).Pass();
223 }
224
225 ManifestPermission* SocketsManifestPermission::Diff(
226     const ManifestPermission* rhs) const {
227   const SocketsManifestPermission* other =
228       static_cast<const SocketsManifestPermission*>(rhs);
229
230   scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
231   result->permissions_ = base::STLSetDifference<SocketPermissionEntrySet>(
232       permissions_, other->permissions_);
233   return result.release();
234 }
235
236 ManifestPermission* SocketsManifestPermission::Union(
237     const ManifestPermission* rhs) const {
238   const SocketsManifestPermission* other =
239       static_cast<const SocketsManifestPermission*>(rhs);
240
241   scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
242   result->permissions_ = base::STLSetUnion<SocketPermissionEntrySet>(
243       permissions_, other->permissions_);
244   return result.release();
245 }
246
247 ManifestPermission* SocketsManifestPermission::Intersect(
248     const ManifestPermission* rhs) const {
249   const SocketsManifestPermission* other =
250       static_cast<const SocketsManifestPermission*>(rhs);
251
252   scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
253   result->permissions_ = base::STLSetIntersection<SocketPermissionEntrySet>(
254       permissions_, other->permissions_);
255   return result.release();
256 }
257
258 void SocketsManifestPermission::AddPermission(
259     const SocketPermissionEntry& entry) {
260   permissions_.insert(entry);
261 }
262
263 bool SocketsManifestPermission::AddAnyHostMessage(
264     PermissionMessages& messages) const {
265   for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
266        it != permissions_.end();
267        ++it) {
268     if (it->IsAddressBoundType() &&
269         it->GetHostType() == SocketPermissionEntry::ANY_HOST) {
270       messages.push_back(
271           PermissionMessage(PermissionMessage::kSocketAnyHost,
272                             l10n_util::GetStringUTF16(
273                                 IDS_EXTENSION_PROMPT_WARNING_SOCKET_ANY_HOST)));
274       return true;
275     }
276   }
277   return false;
278 }
279
280 void SocketsManifestPermission::AddSubdomainHostMessage(
281     PermissionMessages& messages) const {
282   std::set<base::string16> domains;
283   for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
284        it != permissions_.end();
285        ++it) {
286     if (it->GetHostType() == SocketPermissionEntry::HOSTS_IN_DOMAINS)
287       domains.insert(base::UTF8ToUTF16(it->pattern().host));
288   }
289   if (!domains.empty()) {
290     int id = (domains.size() == 1)
291                  ? IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAIN
292                  : IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAINS;
293     messages.push_back(PermissionMessage(
294         PermissionMessage::kSocketDomainHosts,
295         l10n_util::GetStringFUTF16(
296             id,
297             JoinString(
298                 std::vector<base::string16>(domains.begin(), domains.end()),
299                 ' '))));
300   }
301 }
302
303 void SocketsManifestPermission::AddSpecificHostMessage(
304     PermissionMessages& messages) const {
305   std::set<base::string16> hostnames;
306   for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
307        it != permissions_.end();
308        ++it) {
309     if (it->GetHostType() == SocketPermissionEntry::SPECIFIC_HOSTS)
310       hostnames.insert(base::UTF8ToUTF16(it->pattern().host));
311   }
312   if (!hostnames.empty()) {
313     int id = (hostnames.size() == 1)
314                  ? IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOST
315                  : IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOSTS;
316     messages.push_back(PermissionMessage(
317         PermissionMessage::kSocketSpecificHosts,
318         l10n_util::GetStringFUTF16(
319             id,
320             JoinString(
321                 std::vector<base::string16>(hostnames.begin(), hostnames.end()),
322                 ' '))));
323   }
324 }
325
326 void SocketsManifestPermission::AddNetworkListMessage(
327     PermissionMessages& messages) const {
328   for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
329        it != permissions_.end();
330        ++it) {
331     if (it->pattern().type == SocketPermissionRequest::NETWORK_STATE) {
332       messages.push_back(
333           PermissionMessage(PermissionMessage::kNetworkState,
334                             l10n_util::GetStringUTF16(
335                                 IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE)));
336     }
337   }
338 }
339
340 }  // namespace extensions