OLD | NEW |
---|---|
(Empty) | |
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/strings/utf_string_conversions.h" | |
9 #include "base/values.h" | |
10 #include "chrome/common/extensions/api/manifest_types.h" | |
11 #include "chrome/common/extensions/api/sockets/sockets_manifest_data.h" | |
12 #include "chrome/common/extensions/extension_messages.h" | |
13 #include "extensions/common/error_utils.h" | |
14 #include "extensions/common/manifest_constants.h" | |
15 #include "grit/generated_resources.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 api::manifest_types::Sockets; | |
27 using content::SocketPermissionRequest; | |
28 | |
29 SocketsManifestPermission::SocketsManifestPermission() | |
30 : kinds_(kNone) { | |
31 } | |
32 | |
33 SocketsManifestPermission::~SocketsManifestPermission() {} | |
34 | |
35 // static | |
36 scoped_ptr<SocketsManifestPermission> SocketsManifestPermission::FromValue( | |
37 const base::Value& value, | |
38 std::vector<InstallWarning>* install_warnings, | |
Yoyo Zhou
2013/11/14 00:26:55
You don't use this at all.
| |
39 string16* error) { | |
40 scoped_ptr<Sockets> sockets = Sockets::FromValue(value, error); | |
41 if (!sockets) | |
42 return scoped_ptr<SocketsManifestPermission>(); | |
43 | |
44 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission()); | |
45 if (sockets->udp) { | |
46 result->kinds_ |= kUdpPermission; | |
47 if (!ParseHostPattern(result.get(), | |
48 SocketPermissionRequest::UDP_BIND, | |
49 sockets->udp->bind, | |
50 error)) { | |
51 return scoped_ptr<SocketsManifestPermission>(); | |
52 } | |
53 if (!ParseHostPattern(result.get(), | |
54 SocketPermissionRequest::UDP_SEND_TO, | |
55 sockets->udp->send, | |
56 error)) { | |
57 return scoped_ptr<SocketsManifestPermission>(); | |
58 } | |
59 if (!ParseHostPattern(result.get(), | |
60 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, | |
61 sockets->udp->multicast_membership, | |
62 error)) { | |
63 return scoped_ptr<SocketsManifestPermission>(); | |
64 } | |
65 } | |
66 if (sockets->tcp) { | |
67 result->kinds_ |= kTcpPermission; | |
68 if (!ParseHostPattern(result.get(), | |
69 SocketPermissionRequest::TCP_CONNECT, | |
70 sockets->tcp->connect, | |
71 error)) { | |
72 return scoped_ptr<SocketsManifestPermission>(); | |
73 } | |
74 } | |
75 if (sockets->tcp_server) { | |
76 result->kinds_ |= kTcpServerPermission; | |
77 if (!ParseHostPattern(result.get(), | |
78 SocketPermissionRequest::TCP_LISTEN, | |
79 sockets->tcp_server->listen, | |
80 error)) { | |
81 return scoped_ptr<SocketsManifestPermission>(); | |
82 } | |
83 } | |
84 return result.Pass(); | |
85 } | |
86 | |
87 bool SocketsManifestPermission::CheckRequest( | |
88 const Extension* extension, | |
89 const SocketPermissionRequest& request) const { | |
90 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin(); | |
91 it != permissions_.end(); ++it) { | |
92 if (it->Check(request)) | |
93 return true; | |
94 } | |
95 return false; | |
96 } | |
97 | |
98 std::string SocketsManifestPermission::name() const { | |
99 return manifest_keys::kSockets; | |
100 } | |
101 | |
102 std::string SocketsManifestPermission::id() const { | |
103 return name(); | |
104 } | |
105 | |
106 bool SocketsManifestPermission::HasMessages() const { | |
107 bool is_empty = permissions_.empty() && (kinds_ == kNone); | |
108 return !is_empty; | |
109 } | |
110 | |
111 PermissionMessages SocketsManifestPermission::GetMessages() const { | |
112 // TODO(rpaquay): This function and callees is (almost) a copy/paste | |
113 // from |extensions::SocketPermission|. | |
Yoyo Zhou
2013/11/14 00:26:55
nit: no |
| |
114 PermissionMessages result; | |
115 if (!AddAnyHostMessage(result)) { | |
116 AddSpecificHostMessage(result); | |
117 AddSubdomainHostMessage(result); | |
118 } | |
119 AddNetworkListMessage(result); | |
120 return result; | |
121 } | |
122 | |
123 bool SocketsManifestPermission::FromValue(const base::Value* value) { | |
124 if (!value) | |
125 return false; | |
126 | |
127 std::vector<InstallWarning> warnings; | |
128 string16 error; | |
129 scoped_ptr<SocketsManifestPermission> data( | |
130 SocketsManifestPermission::FromValue(*value, &warnings, &error)); | |
131 | |
132 if (!data) | |
133 return false; | |
134 | |
135 permissions_ = data->permissions_; | |
136 kinds_ = data->kinds_; | |
137 return true; | |
138 } | |
139 | |
140 scoped_ptr<base::Value> SocketsManifestPermission::ToValue() const { | |
141 Sockets sockets; | |
142 if (has_udp()) { | |
143 sockets.udp.reset(new Sockets::Udp()); | |
144 sockets.udp->bind = CreateHostPattern(SocketPermissionRequest::UDP_BIND); | |
145 sockets.udp->send = CreateHostPattern(SocketPermissionRequest::UDP_SEND_TO); | |
146 sockets.udp->multicast_membership = | |
147 CreateHostPattern(SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP); | |
148 } | |
149 if (has_tcp()) { | |
150 sockets.tcp.reset(new Sockets::Tcp()); | |
151 sockets.tcp->connect = | |
152 CreateHostPattern(SocketPermissionRequest::TCP_CONNECT); | |
153 } | |
154 if (has_tcp_server()) { | |
155 sockets.tcp_server.reset(new Sockets::TcpServer()); | |
156 sockets.tcp_server->listen = | |
157 CreateHostPattern(SocketPermissionRequest::TCP_LISTEN); | |
158 } | |
159 | |
160 return sockets.ToValue().Pass(); | |
161 } | |
162 | |
163 ManifestPermission* SocketsManifestPermission::Clone() const { | |
164 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission()); | |
165 result->permissions_ = permissions_; | |
166 result->kinds_ = kinds_; | |
167 return result.release(); | |
168 } | |
169 | |
170 ManifestPermission* SocketsManifestPermission::Diff( | |
171 const ManifestPermission* rhs) const { | |
172 const SocketsManifestPermission* other = | |
173 static_cast<const SocketsManifestPermission*>(rhs); | |
174 | |
175 scoped_ptr<SocketsManifestPermission> data(new SocketsManifestPermission()); | |
176 std::set_difference( | |
177 permissions_.begin(), permissions_.end(), | |
178 other->permissions_.begin(), other->permissions_.end(), | |
179 std::inserter<SocketPermissionEntrySet>( | |
180 data->permissions_, data->permissions_.begin())); | |
181 | |
182 data->kinds_ = (kinds_ & (~other->kinds_)); | |
183 return data.release(); | |
184 } | |
185 | |
186 ManifestPermission* SocketsManifestPermission::Union( | |
187 const ManifestPermission* rhs) const { | |
188 const SocketsManifestPermission* other = | |
189 static_cast<const SocketsManifestPermission*>(rhs); | |
190 | |
191 scoped_ptr<SocketsManifestPermission> data(new SocketsManifestPermission()); | |
192 std::set_union( | |
193 permissions_.begin(), permissions_.end(), | |
194 other->permissions_.begin(), other->permissions_.end(), | |
195 std::inserter<SocketPermissionEntrySet>( | |
196 data->permissions_, data->permissions_.begin())); | |
197 | |
198 data->kinds_ = (kinds_ | other->kinds_); | |
199 return data.release(); | |
200 } | |
201 | |
202 ManifestPermission* SocketsManifestPermission::Intersect( | |
203 const ManifestPermission* rhs) const { | |
204 const SocketsManifestPermission* other = | |
205 static_cast<const SocketsManifestPermission*>(rhs); | |
206 | |
207 scoped_ptr<SocketsManifestPermission> data(new SocketsManifestPermission()); | |
208 std::set_intersection( | |
209 permissions_.begin(), permissions_.end(), | |
210 other->permissions_.begin(), other->permissions_.end(), | |
211 std::inserter<SocketPermissionEntrySet>( | |
212 data->permissions_, data->permissions_.begin())); | |
213 | |
214 data->kinds_ = (kinds_ & other->kinds_); | |
215 return data.release(); | |
216 } | |
217 | |
218 bool SocketsManifestPermission::Contains(const ManifestPermission* rhs) const { | |
219 const SocketsManifestPermission* other = | |
220 static_cast<const SocketsManifestPermission*>(rhs); | |
221 | |
222 return std::includes( | |
223 permissions_.begin(), permissions_.end(), | |
224 other->permissions_.begin(), other->permissions_.end()) && | |
225 ((kinds_ | other->kinds_) == kinds_); | |
226 } | |
227 | |
228 bool SocketsManifestPermission::Equal(const ManifestPermission* rhs) const { | |
229 const SocketsManifestPermission* other = | |
230 static_cast<const SocketsManifestPermission*>(rhs); | |
231 | |
232 return (permissions_ == other->permissions_) && | |
233 (kinds_ == other->kinds_); | |
234 } | |
235 | |
236 void SocketsManifestPermission::Write(IPC::Message* m) const { | |
237 IPC::WriteParam(m, permissions_); | |
238 IPC::WriteParam(m, kinds_); | |
239 } | |
240 | |
241 bool SocketsManifestPermission::Read(const IPC::Message* m, | |
242 PickleIterator* iter) { | |
243 return IPC::ReadParam(m, iter, &permissions_) && | |
244 IPC::ReadParam(m, iter, &kinds_); | |
245 } | |
246 | |
247 void SocketsManifestPermission::Log(std::string* log) const { | |
248 IPC::LogParam(permissions_, log); | |
249 IPC::LogParam(kinds_, log); | |
250 } | |
251 | |
252 // static | |
253 bool SocketsManifestPermission::ParseHostPattern( | |
254 SocketsManifestPermission* manifest_data, | |
255 SocketPermissionRequest::OperationType operation_type, | |
256 const scoped_ptr<std::string>& value, | |
257 string16* error) { | |
258 if (value) { | |
259 SocketPermissionEntry entry; | |
260 if (!SocketPermissionEntry::ParseHostPattern( | |
261 operation_type, *value, &entry)) { | |
262 *error = ErrorUtils::FormatErrorMessageUTF16( | |
263 errors::kErrorInvalidHostPattern, *value); | |
264 return false; | |
265 } | |
266 manifest_data->AddPermission(entry); | |
267 } | |
268 return true; | |
269 } | |
270 | |
271 scoped_ptr<std::string> SocketsManifestPermission::CreateHostPattern( | |
272 SocketPermissionRequest::OperationType operation_type) const { | |
273 scoped_ptr<std::string> result; | |
274 for (SocketPermissionEntrySet::const_iterator it = | |
275 entries().begin(); it != entries().end() ; ++it) { | |
276 if (it->pattern().type == operation_type) { | |
277 result.reset(new std::string(it->GetHostPatternAsString())); | |
278 break; | |
279 } | |
280 } | |
281 return result.Pass(); | |
282 } | |
283 | |
284 void SocketsManifestPermission::AddPermission( | |
285 const SocketPermissionEntry& entry) { | |
286 permissions_.insert(entry); | |
287 } | |
288 | |
289 bool SocketsManifestPermission::AddAnyHostMessage( | |
290 PermissionMessages& messages) const { | |
291 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin(); | |
292 it != permissions_.end(); ++it) { | |
293 if (it->IsAddressBoundType() && | |
294 it->GetHostType() == SocketPermissionEntry::ANY_HOST) { | |
295 messages.push_back(PermissionMessage( | |
296 PermissionMessage::kSocketAnyHost, | |
297 l10n_util::GetStringUTF16( | |
298 IDS_EXTENSION_PROMPT_WARNING_SOCKET_ANY_HOST))); | |
299 return true; | |
300 } | |
301 } | |
302 return false; | |
303 } | |
304 | |
305 void SocketsManifestPermission::AddSubdomainHostMessage( | |
306 PermissionMessages& messages) const { | |
307 std::set<string16> domains; | |
308 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin(); | |
309 it != permissions_.end(); ++it) { | |
310 if (it->GetHostType() == SocketPermissionEntry::HOSTS_IN_DOMAINS) | |
311 domains.insert(UTF8ToUTF16(it->pattern().host)); | |
312 } | |
313 if (!domains.empty()) { | |
314 int id = (domains.size() == 1) ? | |
315 IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAIN : | |
316 IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAINS; | |
317 messages.push_back(PermissionMessage( | |
318 PermissionMessage::kSocketDomainHosts, | |
319 l10n_util::GetStringFUTF16( | |
320 id, | |
321 JoinString( | |
322 std::vector<string16>( | |
323 domains.begin(), domains.end()), ' ')))); | |
324 } | |
325 } | |
326 | |
327 void SocketsManifestPermission::AddSpecificHostMessage( | |
328 PermissionMessages& messages) const { | |
329 std::set<string16> hostnames; | |
330 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin(); | |
331 it != permissions_.end(); ++it) { | |
332 if (it->GetHostType() == SocketPermissionEntry::SPECIFIC_HOSTS) | |
333 hostnames.insert(UTF8ToUTF16(it->pattern().host)); | |
334 } | |
335 if (!hostnames.empty()) { | |
336 int id = (hostnames.size() == 1) ? | |
337 IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOST : | |
338 IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOSTS; | |
339 messages.push_back(PermissionMessage( | |
340 PermissionMessage::kSocketSpecificHosts, | |
341 l10n_util::GetStringFUTF16( | |
342 id, | |
343 JoinString( | |
344 std::vector<string16>( | |
345 hostnames.begin(), hostnames.end()), ' ')))); | |
346 } | |
347 } | |
348 | |
349 void SocketsManifestPermission::AddNetworkListMessage( | |
350 PermissionMessages& messages) const { | |
351 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin(); | |
352 it != permissions_.end(); ++it) { | |
353 if (it->pattern().type == SocketPermissionRequest::NETWORK_STATE) { | |
354 messages.push_back(PermissionMessage( | |
355 PermissionMessage::kNetworkState, | |
356 l10n_util::GetStringUTF16( | |
357 IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE))); | |
358 } | |
359 } | |
360 } | |
361 | |
362 } // namespace extensions | |
OLD | NEW |