Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(174)

Side by Side Diff: chrome/common/extensions/api/sockets/sockets_manifest_permission.cc

Issue 51433002: Enable permission warnings from ManifestHandlers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix unit test and clang presubmit errors. Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 string16* error) {
39 scoped_ptr<Sockets> sockets = Sockets::FromValue(value, error);
40 if (!sockets)
41 return scoped_ptr<SocketsManifestPermission>();
42
43 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
44 if (sockets->udp) {
45 result->kinds_ |= kUdpPermission;
46 if (!ParseHostPattern(result.get(),
47 SocketPermissionRequest::UDP_BIND,
48 sockets->udp->bind,
49 error)) {
50 return scoped_ptr<SocketsManifestPermission>();
51 }
52 if (!ParseHostPattern(result.get(),
53 SocketPermissionRequest::UDP_SEND_TO,
54 sockets->udp->send,
55 error)) {
56 return scoped_ptr<SocketsManifestPermission>();
57 }
58 if (!ParseHostPattern(result.get(),
59 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
60 sockets->udp->multicast_membership,
61 error)) {
62 return scoped_ptr<SocketsManifestPermission>();
63 }
64 }
65 if (sockets->tcp) {
66 result->kinds_ |= kTcpPermission;
67 if (!ParseHostPattern(result.get(),
68 SocketPermissionRequest::TCP_CONNECT,
69 sockets->tcp->connect,
70 error)) {
71 return scoped_ptr<SocketsManifestPermission>();
72 }
73 }
74 if (sockets->tcp_server) {
75 result->kinds_ |= kTcpServerPermission;
76 if (!ParseHostPattern(result.get(),
77 SocketPermissionRequest::TCP_LISTEN,
78 sockets->tcp_server->listen,
79 error)) {
80 return scoped_ptr<SocketsManifestPermission>();
81 }
82 }
83 return result.Pass();
84 }
85
86 bool SocketsManifestPermission::CheckRequest(
87 const Extension* extension,
88 const SocketPermissionRequest& request) const {
89 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
90 it != permissions_.end(); ++it) {
91 if (it->Check(request))
92 return true;
93 }
94 return false;
95 }
96
97 std::string SocketsManifestPermission::name() const {
98 return manifest_keys::kSockets;
99 }
100
101 std::string SocketsManifestPermission::id() const {
102 return name();
103 }
104
105 bool SocketsManifestPermission::HasMessages() const {
106 bool is_empty = permissions_.empty() && (kinds_ == kNone);
107 return !is_empty;
108 }
109
110 PermissionMessages SocketsManifestPermission::GetMessages() const {
111 // TODO(rpaquay): This function and callees is (almost) a copy/paste
112 // from extensions::SocketPermissiona.
113 PermissionMessages result;
114 if (!AddAnyHostMessage(result)) {
115 AddSpecificHostMessage(result);
116 AddSubdomainHostMessage(result);
117 }
118 AddNetworkListMessage(result);
119 return result;
120 }
121
122 bool SocketsManifestPermission::FromValue(const base::Value* value) {
123 if (!value)
124 return false;
125 string16 error;
126 scoped_ptr<SocketsManifestPermission> data(
127 SocketsManifestPermission::FromValue(*value, &error));
128
129 if (!data)
130 return false;
131
132 permissions_ = data->permissions_;
133 kinds_ = data->kinds_;
134 return true;
135 }
136
137 scoped_ptr<base::Value> SocketsManifestPermission::ToValue() const {
138 Sockets sockets;
139 if (has_udp()) {
140 sockets.udp.reset(new Sockets::Udp());
141 sockets.udp->bind = CreateHostPattern(SocketPermissionRequest::UDP_BIND);
142 sockets.udp->send = CreateHostPattern(SocketPermissionRequest::UDP_SEND_TO);
143 sockets.udp->multicast_membership =
144 CreateHostPattern(SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP);
145 }
146 if (has_tcp()) {
147 sockets.tcp.reset(new Sockets::Tcp());
148 sockets.tcp->connect =
149 CreateHostPattern(SocketPermissionRequest::TCP_CONNECT);
150 }
151 if (has_tcp_server()) {
152 sockets.tcp_server.reset(new Sockets::TcpServer());
153 sockets.tcp_server->listen =
154 CreateHostPattern(SocketPermissionRequest::TCP_LISTEN);
155 }
156
157 return scoped_ptr<base::Value>(sockets.ToValue().release()).Pass();
158 }
159
160 ManifestPermission* SocketsManifestPermission::Clone() const {
161 scoped_ptr<SocketsManifestPermission> result(new SocketsManifestPermission());
162 result->permissions_ = permissions_;
163 result->kinds_ = kinds_;
164 return result.release();
165 }
166
167 ManifestPermission* SocketsManifestPermission::Diff(
168 const ManifestPermission* rhs) const {
169 const SocketsManifestPermission* other =
170 static_cast<const SocketsManifestPermission*>(rhs);
171
172 scoped_ptr<SocketsManifestPermission> data(new SocketsManifestPermission());
173 std::set_difference(
174 permissions_.begin(), permissions_.end(),
175 other->permissions_.begin(), other->permissions_.end(),
176 std::inserter<SocketPermissionEntrySet>(
177 data->permissions_, data->permissions_.begin()));
178
179 data->kinds_ = (kinds_ & (~other->kinds_));
180
181 // Note: We may need to fix up |kinds_| because any permission entry
182 // in a given group (udp, tcp, etc.) implies the corresponding kind bit set.
183 data->kinds_ |= HasOperationType(data->permissions_,
184 SocketPermissionRequest::UDP_BIND, kUdpPermission);
185 data->kinds_ |= HasOperationType(data->permissions_,
186 SocketPermissionRequest::UDP_SEND_TO, kUdpPermission);
187 data->kinds_ |= HasOperationType(data->permissions_,
188 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, kUdpPermission);
189 data->kinds_ |= HasOperationType(data->permissions_,
190 SocketPermissionRequest::TCP_CONNECT, kTcpPermission);
191 data->kinds_ |= HasOperationType(data->permissions_,
192 SocketPermissionRequest::TCP_LISTEN, kTcpServerPermission);
193 return data.release();
194 }
195
196 ManifestPermission* SocketsManifestPermission::Union(
197 const ManifestPermission* rhs) const {
198 const SocketsManifestPermission* other =
199 static_cast<const SocketsManifestPermission*>(rhs);
200
201 scoped_ptr<SocketsManifestPermission> data(new SocketsManifestPermission());
202 std::set_union(
203 permissions_.begin(), permissions_.end(),
204 other->permissions_.begin(), other->permissions_.end(),
205 std::inserter<SocketPermissionEntrySet>(
206 data->permissions_, data->permissions_.begin()));
207
208 data->kinds_ = (kinds_ | other->kinds_);
209 return data.release();
210 }
211
212 ManifestPermission* SocketsManifestPermission::Intersect(
213 const ManifestPermission* rhs) const {
214 const SocketsManifestPermission* other =
215 static_cast<const SocketsManifestPermission*>(rhs);
216
217 scoped_ptr<SocketsManifestPermission> data(new SocketsManifestPermission());
218 std::set_intersection(
219 permissions_.begin(), permissions_.end(),
220 other->permissions_.begin(), other->permissions_.end(),
221 std::inserter<SocketPermissionEntrySet>(
222 data->permissions_, data->permissions_.begin()));
223
224 data->kinds_ = (kinds_ & other->kinds_);
225 return data.release();
226 }
227
228 bool SocketsManifestPermission::Contains(const ManifestPermission* rhs) const {
229 const SocketsManifestPermission* other =
230 static_cast<const SocketsManifestPermission*>(rhs);
231
232 return std::includes(
233 permissions_.begin(), permissions_.end(),
234 other->permissions_.begin(), other->permissions_.end()) &&
235 ((kinds_ | other->kinds_) == kinds_);
236 }
237
238 bool SocketsManifestPermission::Equal(const ManifestPermission* rhs) const {
239 const SocketsManifestPermission* other =
240 static_cast<const SocketsManifestPermission*>(rhs);
241
242 return (permissions_ == other->permissions_) &&
243 (kinds_ == other->kinds_);
244 }
245
246 void SocketsManifestPermission::Write(IPC::Message* m) const {
247 IPC::WriteParam(m, permissions_);
248 IPC::WriteParam(m, kinds_);
249 }
250
251 bool SocketsManifestPermission::Read(const IPC::Message* m,
252 PickleIterator* iter) {
253 return IPC::ReadParam(m, iter, &permissions_) &&
254 IPC::ReadParam(m, iter, &kinds_);
255 }
256
257 void SocketsManifestPermission::Log(std::string* log) const {
258 IPC::LogParam(permissions_, log);
259 IPC::LogParam(kinds_, log);
260 }
261
262 // static
263 bool SocketsManifestPermission::ParseHostPattern(
264 SocketsManifestPermission* manifest_data,
265 SocketPermissionRequest::OperationType operation_type,
266 const scoped_ptr<std::string>& value,
267 string16* error) {
268 if (value) {
269 SocketPermissionEntry entry;
270 if (!SocketPermissionEntry::ParseHostPattern(
271 operation_type, *value, &entry)) {
272 *error = ErrorUtils::FormatErrorMessageUTF16(
273 errors::kErrorInvalidHostPattern, *value);
274 return false;
275 }
276 manifest_data->AddPermission(entry);
277 }
278 return true;
279 }
280
281 // static
282 SocketsManifestPermission::PermissionKind SocketsManifestPermission::
283 HasOperationType(const SocketPermissionEntrySet& set,
284 SocketPermissionRequest::OperationType operation_type,
285 PermissionKind kind) {
286 for (SocketPermissionEntrySet::const_iterator it = set.begin();
287 it != set.end() ; ++it) {
288 if (it->pattern().type == operation_type)
289 return kind;
290 }
291 return kNone;
292 }
293
294
295 scoped_ptr<std::string> SocketsManifestPermission::CreateHostPattern(
296 SocketPermissionRequest::OperationType operation_type) const {
297 scoped_ptr<std::string> result;
298 for (SocketPermissionEntrySet::const_iterator it =
299 entries().begin(); it != entries().end() ; ++it) {
300 if (it->pattern().type == operation_type) {
301 result.reset(new std::string(it->GetHostPatternAsString()));
302 break;
303 }
304 }
305 return result.Pass();
306 }
307
308 void SocketsManifestPermission::AddPermission(
309 const SocketPermissionEntry& entry) {
310 permissions_.insert(entry);
311 }
312
313 bool SocketsManifestPermission::AddAnyHostMessage(
314 PermissionMessages& messages) const {
315 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
316 it != permissions_.end(); ++it) {
317 if (it->IsAddressBoundType() &&
318 it->GetHostType() == SocketPermissionEntry::ANY_HOST) {
319 messages.push_back(PermissionMessage(
320 PermissionMessage::kSocketAnyHost,
321 l10n_util::GetStringUTF16(
322 IDS_EXTENSION_PROMPT_WARNING_SOCKET_ANY_HOST)));
323 return true;
324 }
325 }
326 return false;
327 }
328
329 void SocketsManifestPermission::AddSubdomainHostMessage(
330 PermissionMessages& messages) const {
331 std::set<string16> domains;
332 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
333 it != permissions_.end(); ++it) {
334 if (it->GetHostType() == SocketPermissionEntry::HOSTS_IN_DOMAINS)
335 domains.insert(UTF8ToUTF16(it->pattern().host));
336 }
337 if (!domains.empty()) {
338 int id = (domains.size() == 1) ?
339 IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAIN :
340 IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAINS;
341 messages.push_back(PermissionMessage(
342 PermissionMessage::kSocketDomainHosts,
343 l10n_util::GetStringFUTF16(
344 id,
345 JoinString(
346 std::vector<string16>(
347 domains.begin(), domains.end()), ' '))));
348 }
349 }
350
351 void SocketsManifestPermission::AddSpecificHostMessage(
352 PermissionMessages& messages) const {
353 std::set<string16> hostnames;
354 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
355 it != permissions_.end(); ++it) {
356 if (it->GetHostType() == SocketPermissionEntry::SPECIFIC_HOSTS)
357 hostnames.insert(UTF8ToUTF16(it->pattern().host));
358 }
359 if (!hostnames.empty()) {
360 int id = (hostnames.size() == 1) ?
361 IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOST :
362 IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOSTS;
363 messages.push_back(PermissionMessage(
364 PermissionMessage::kSocketSpecificHosts,
365 l10n_util::GetStringFUTF16(
366 id,
367 JoinString(
368 std::vector<string16>(
369 hostnames.begin(), hostnames.end()), ' '))));
370 }
371 }
372
373 void SocketsManifestPermission::AddNetworkListMessage(
374 PermissionMessages& messages) const {
375 for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
376 it != permissions_.end(); ++it) {
377 if (it->pattern().type == SocketPermissionRequest::NETWORK_STATE) {
378 messages.push_back(PermissionMessage(
379 PermissionMessage::kNetworkState,
380 l10n_util::GetStringUTF16(
381 IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE)));
382 }
383 }
384 }
385
386 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698