Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / common / extensions / api / sockets / sockets_manifest_permission.cc
1 // Copyright 2013 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 "chrome/common/extensions/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 "chrome/common/extensions/api/manifest_types.h"
12 #include "chrome/common/extensions/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/generated_resources.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 api::manifest_types::Sockets;
28 using api::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(permission, operation_type,
59                             *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(); ++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(); it != permission->entries().end() ; ++it) {
81     if (it->pattern().type == operation_type) {
82       host_patterns->as_strings->push_back(it->GetHostPatternAsString());
83     }
84   }
85 }
86
87 }  // namespace
88
89 SocketsManifestPermission::SocketsManifestPermission() {}
90
91 SocketsManifestPermission::~SocketsManifestPermission() {}
92
93 // static
94 scoped_ptr<SocketsManifestPermission> SocketsManifestPermission::FromValue(
95     const base::Value& value,
96     base::string16* error) {
97   scoped_ptr<Sockets> sockets = Sockets::FromValue(value, error);
98   if (!sockets)
99     return scoped_ptr<SocketsManifestPermission>();
100
101   scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
102   if (sockets->udp) {
103     if (!ParseHostPatterns(result.get(),
104                            SocketPermissionRequest::UDP_BIND,
105                            sockets->udp->bind,
106                            error)) {
107       return scoped_ptr<SocketsManifestPermission>();
108     }
109     if (!ParseHostPatterns(result.get(),
110                            SocketPermissionRequest::UDP_SEND_TO,
111                            sockets->udp->send,
112                            error)) {
113       return scoped_ptr<SocketsManifestPermission>();
114     }
115     if (!ParseHostPatterns(result.get(),
116                            SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
117                            sockets->udp->multicast_membership,
118                            error)) {
119       return scoped_ptr<SocketsManifestPermission>();
120     }
121   }
122   if (sockets->tcp) {
123     if (!ParseHostPatterns(result.get(),
124                            SocketPermissionRequest::TCP_CONNECT,
125                            sockets->tcp->connect,
126                            error)) {
127       return scoped_ptr<SocketsManifestPermission>();
128     }
129   }
130   if (sockets->tcp_server) {
131     if (!ParseHostPatterns(result.get(),
132                            SocketPermissionRequest::TCP_LISTEN,
133                            sockets->tcp_server->listen,
134                            error)) {
135       return scoped_ptr<SocketsManifestPermission>();
136     }
137   }
138   return result.Pass();
139 }
140
141 bool SocketsManifestPermission::CheckRequest(
142     const Extension* extension,
143     const SocketPermissionRequest& request) const {
144   for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
145        it != permissions_.end(); ++it) {
146     if (it->Check(request))
147       return true;
148   }
149   return false;
150 }
151
152 std::string SocketsManifestPermission::name() const {
153   return manifest_keys::kSockets;
154 }
155
156 std::string SocketsManifestPermission::id() const {
157   return name();
158 }
159
160 bool SocketsManifestPermission::HasMessages() const {
161   bool is_empty = permissions_.empty();
162   return !is_empty;
163 }
164
165 PermissionMessages SocketsManifestPermission::GetMessages() const {
166   // TODO(rpaquay): This function and callees is (almost) a copy/paste
167   // from extensions::SocketPermissiona.
168   PermissionMessages result;
169   if (!AddAnyHostMessage(result)) {
170     AddSpecificHostMessage(result);
171     AddSubdomainHostMessage(result);
172   }
173   AddNetworkListMessage(result);
174   return result;
175 }
176
177 bool SocketsManifestPermission::FromValue(const base::Value* value) {
178   if (!value)
179     return false;
180   base::string16 error;
181   scoped_ptr<SocketsManifestPermission> manifest_permission(
182       SocketsManifestPermission::FromValue(*value, &error));
183
184   if (!manifest_permission)
185     return false;
186
187   permissions_ = manifest_permission->permissions_;
188   return true;
189 }
190
191 scoped_ptr<base::Value> SocketsManifestPermission::ToValue() const {
192   Sockets sockets;
193
194   sockets.udp.reset(new Sockets::Udp());
195   SetHostPatterns(sockets.udp->bind, this,
196                   SocketPermissionRequest::UDP_BIND);
197   SetHostPatterns(sockets.udp->send, this,
198                   SocketPermissionRequest::UDP_SEND_TO);
199   SetHostPatterns(sockets.udp->multicast_membership, this,
200                   SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP);
201   if (sockets.udp->bind->as_strings->size() == 0 &&
202       sockets.udp->send->as_strings->size() == 0 &&
203       sockets.udp->multicast_membership->as_strings->size() == 0) {
204     sockets.udp.reset(NULL);
205   }
206
207   sockets.tcp.reset(new Sockets::Tcp());
208   SetHostPatterns(sockets.tcp->connect, this,
209                   SocketPermissionRequest::TCP_CONNECT);
210   if (sockets.tcp->connect->as_strings->size() == 0) {
211     sockets.tcp.reset(NULL);
212   }
213
214   sockets.tcp_server.reset(new Sockets::TcpServer());
215   SetHostPatterns(sockets.tcp_server->listen, this,
216                   SocketPermissionRequest::TCP_LISTEN);
217   if (sockets.tcp_server->listen->as_strings->size() == 0) {
218     sockets.tcp_server.reset(NULL);
219   }
220
221   return scoped_ptr<base::Value>(sockets.ToValue().release()).Pass();
222 }
223
224 ManifestPermission* SocketsManifestPermission::Clone() const {
225   scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
226   result->permissions_ = permissions_;
227   return result.release();
228 }
229
230 ManifestPermission* SocketsManifestPermission::Diff(
231     const ManifestPermission* rhs) const {
232   const SocketsManifestPermission* other =
233       static_cast<const SocketsManifestPermission*>(rhs);
234
235   scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
236   result->permissions_ = base::STLSetDifference<SocketPermissionEntrySet>(
237       permissions_, other->permissions_);
238   return result.release();
239 }
240
241 ManifestPermission* SocketsManifestPermission::Union(
242     const ManifestPermission* rhs) const {
243   const SocketsManifestPermission* other =
244       static_cast<const SocketsManifestPermission*>(rhs);
245
246   scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
247   result->permissions_ = base::STLSetUnion<SocketPermissionEntrySet>(
248       permissions_, other->permissions_);
249   return result.release();
250 }
251
252 ManifestPermission* SocketsManifestPermission::Intersect(
253     const ManifestPermission* rhs) const {
254   const SocketsManifestPermission* other =
255       static_cast<const SocketsManifestPermission*>(rhs);
256
257   scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
258   result->permissions_ = base::STLSetIntersection<SocketPermissionEntrySet>(
259       permissions_, other->permissions_);
260   return result.release();
261 }
262
263 bool SocketsManifestPermission::Contains(const ManifestPermission* rhs) const {
264   const SocketsManifestPermission* other =
265       static_cast<const SocketsManifestPermission*>(rhs);
266
267   return base::STLIncludes<SocketPermissionEntrySet>(permissions_,
268                                                      other->permissions_);
269 }
270
271 bool SocketsManifestPermission::Equal(const ManifestPermission* rhs) const {
272   const SocketsManifestPermission* other =
273       static_cast<const SocketsManifestPermission*>(rhs);
274
275   return (permissions_ == other->permissions_);
276 }
277
278 void SocketsManifestPermission::Write(IPC::Message* m) const {
279   IPC::WriteParam(m, permissions_);
280 }
281
282 bool SocketsManifestPermission::Read(const IPC::Message* m,
283                                      PickleIterator* iter) {
284   return IPC::ReadParam(m, iter, &permissions_);
285 }
286
287 void SocketsManifestPermission::Log(std::string* log) const {
288   IPC::LogParam(permissions_, log);
289 }
290
291 void SocketsManifestPermission::AddPermission(
292     const SocketPermissionEntry& entry) {
293   permissions_.insert(entry);
294 }
295
296 bool SocketsManifestPermission::AddAnyHostMessage(
297     PermissionMessages& messages) const {
298   for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
299       it != permissions_.end(); ++it) {
300     if (it->IsAddressBoundType() &&
301         it->GetHostType() == SocketPermissionEntry::ANY_HOST) {
302       messages.push_back(PermissionMessage(
303           PermissionMessage::kSocketAnyHost,
304           l10n_util::GetStringUTF16(
305               IDS_EXTENSION_PROMPT_WARNING_SOCKET_ANY_HOST)));
306       return true;
307     }
308   }
309   return false;
310 }
311
312 void SocketsManifestPermission::AddSubdomainHostMessage(
313     PermissionMessages& messages) const {
314   std::set<base::string16> domains;
315   for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
316       it != permissions_.end(); ++it) {
317     if (it->GetHostType() == SocketPermissionEntry::HOSTS_IN_DOMAINS)
318       domains.insert(base::UTF8ToUTF16(it->pattern().host));
319   }
320   if (!domains.empty()) {
321     int id = (domains.size() == 1) ?
322              IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAIN :
323              IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAINS;
324     messages.push_back(PermissionMessage(
325         PermissionMessage::kSocketDomainHosts,
326         l10n_util::GetStringFUTF16(
327             id,
328             JoinString(
329                 std::vector<base::string16>(
330                     domains.begin(), domains.end()), ' '))));
331   }
332 }
333
334 void SocketsManifestPermission::AddSpecificHostMessage(
335     PermissionMessages& messages) const {
336   std::set<base::string16> hostnames;
337   for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
338     it != permissions_.end(); ++it) {
339     if (it->GetHostType() == SocketPermissionEntry::SPECIFIC_HOSTS)
340       hostnames.insert(base::UTF8ToUTF16(it->pattern().host));
341   }
342   if (!hostnames.empty()) {
343     int id = (hostnames.size() == 1) ?
344              IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOST :
345              IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOSTS;
346     messages.push_back(PermissionMessage(
347         PermissionMessage::kSocketSpecificHosts,
348         l10n_util::GetStringFUTF16(
349             id,
350             JoinString(
351                 std::vector<base::string16>(
352                     hostnames.begin(), hostnames.end()), ' '))));
353   }
354 }
355
356 void SocketsManifestPermission::AddNetworkListMessage(
357     PermissionMessages& messages) const {
358   for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
359       it != permissions_.end(); ++it) {
360     if (it->pattern().type == SocketPermissionRequest::NETWORK_STATE) {
361       messages.push_back(PermissionMessage(
362           PermissionMessage::kNetworkState,
363           l10n_util::GetStringUTF16(
364               IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE)));
365     }
366   }
367 }
368
369 }  // namespace extensions