Move extension_messages.h to extensions/common.
[chromium-blink-merge.git] / chrome / common / extensions / api / sockets / sockets_manifest_permission.cc
blob143ec9b67849edd44980110df7add9f95dbb6aa8
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.
5 #include "chrome/common/extensions/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 "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"
20 namespace extensions {
22 namespace sockets_errors {
23 const char kErrorInvalidHostPattern[] = "Invalid host:port pattern '*'";
26 namespace errors = sockets_errors;
27 using api::manifest_types::Sockets;
28 using api::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(permission, operation_type,
59 *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(); ++it) {
66 if (!ParseHostPattern(permission, operation_type, *it, error)) {
67 return false;
70 return true;
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());
87 } // namespace
89 SocketsManifestPermission::SocketsManifestPermission() {}
91 SocketsManifestPermission::~SocketsManifestPermission() {}
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>();
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>();
109 if (!ParseHostPatterns(result.get(),
110 SocketPermissionRequest::UDP_SEND_TO,
111 sockets->udp->send,
112 error)) {
113 return scoped_ptr<SocketsManifestPermission>();
115 if (!ParseHostPatterns(result.get(),
116 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
117 sockets->udp->multicast_membership,
118 error)) {
119 return scoped_ptr<SocketsManifestPermission>();
122 if (sockets->tcp) {
123 if (!ParseHostPatterns(result.get(),
124 SocketPermissionRequest::TCP_CONNECT,
125 sockets->tcp->connect,
126 error)) {
127 return scoped_ptr<SocketsManifestPermission>();
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>();
138 return result.Pass();
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;
149 return false;
152 std::string SocketsManifestPermission::name() const {
153 return manifest_keys::kSockets;
156 std::string SocketsManifestPermission::id() const {
157 return name();
160 bool SocketsManifestPermission::HasMessages() const {
161 bool is_empty = permissions_.empty();
162 return !is_empty;
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);
173 AddNetworkListMessage(result);
174 return result;
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));
184 if (!manifest_permission)
185 return false;
187 permissions_ = manifest_permission->permissions_;
188 return true;
191 scoped_ptr<base::Value> SocketsManifestPermission::ToValue() const {
192 Sockets sockets;
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);
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);
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);
221 return scoped_ptr<base::Value>(sockets.ToValue().release()).Pass();
224 ManifestPermission* SocketsManifestPermission::Clone() const {
225 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
226 result->permissions_ = permissions_;
227 return result.release();
230 ManifestPermission* SocketsManifestPermission::Diff(
231 const ManifestPermission* rhs) const {
232 const SocketsManifestPermission* other =
233 static_cast<const SocketsManifestPermission*>(rhs);
235 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
236 result->permissions_ = base::STLSetDifference<SocketPermissionEntrySet>(
237 permissions_, other->permissions_);
238 return result.release();
241 ManifestPermission* SocketsManifestPermission::Union(
242 const ManifestPermission* rhs) const {
243 const SocketsManifestPermission* other =
244 static_cast<const SocketsManifestPermission*>(rhs);
246 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
247 result->permissions_ = base::STLSetUnion<SocketPermissionEntrySet>(
248 permissions_, other->permissions_);
249 return result.release();
252 ManifestPermission* SocketsManifestPermission::Intersect(
253 const ManifestPermission* rhs) const {
254 const SocketsManifestPermission* other =
255 static_cast<const SocketsManifestPermission*>(rhs);
257 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
258 result->permissions_ = base::STLSetIntersection<SocketPermissionEntrySet>(
259 permissions_, other->permissions_);
260 return result.release();
263 bool SocketsManifestPermission::Contains(const ManifestPermission* rhs) const {
264 const SocketsManifestPermission* other =
265 static_cast<const SocketsManifestPermission*>(rhs);
267 return base::STLIncludes<SocketPermissionEntrySet>(permissions_,
268 other->permissions_);
271 bool SocketsManifestPermission::Equal(const ManifestPermission* rhs) const {
272 const SocketsManifestPermission* other =
273 static_cast<const SocketsManifestPermission*>(rhs);
275 return (permissions_ == other->permissions_);
278 void SocketsManifestPermission::Write(IPC::Message* m) const {
279 IPC::WriteParam(m, permissions_);
282 bool SocketsManifestPermission::Read(const IPC::Message* m,
283 PickleIterator* iter) {
284 return IPC::ReadParam(m, iter, &permissions_);
287 void SocketsManifestPermission::Log(std::string* log) const {
288 IPC::LogParam(permissions_, log);
291 void SocketsManifestPermission::AddPermission(
292 const SocketPermissionEntry& entry) {
293 permissions_.insert(entry);
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;
309 return false;
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));
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(
328 JoinString(
329 std::vector<base::string16>(
330 domains.begin(), domains.end()), ' '))));
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));
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(
350 JoinString(
351 std::vector<base::string16>(
352 hostnames.begin(), hostnames.end()), ' '))));
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)));
369 } // namespace extensions