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/browser/extensions/api/sockets_udp/sockets_udp_api.h" | |
6 | |
7 #include "chrome/browser/extensions/api/socket/udp_socket.h" | |
8 #include "chrome/browser/extensions/api/sockets_udp/udp_socket_event_dispatcher.
h" | |
9 #include "chrome/common/extensions/api/sockets/sockets_manifest_data.h" | |
10 #include "content/public/common/socket_permission_request.h" | |
11 #include "net/base/net_errors.h" | |
12 | |
13 namespace extensions { | |
14 namespace api { | |
15 | |
16 using content::SocketPermissionRequest; | |
17 | |
18 const char kSocketNotFoundError[] = "Socket not found"; | |
19 const char kPermissionError[] = "App does not have permission"; | |
20 const char kWildcardAddress[] = "*"; | |
21 const int kWildcardPort = 0; | |
22 | |
23 UDPSocketAsyncApiFunction::~UDPSocketAsyncApiFunction() {} | |
24 | |
25 scoped_ptr<SocketResourceManagerInterface> | |
26 UDPSocketAsyncApiFunction::CreateSocketResourceManager() { | |
27 return scoped_ptr<SocketResourceManagerInterface>( | |
28 new SocketResourceManager<ResumableUDPSocket>()).Pass(); | |
29 } | |
30 | |
31 ResumableUDPSocket* UDPSocketAsyncApiFunction::GetUdpSocket(int socket_id) { | |
32 return static_cast<ResumableUDPSocket*>(GetSocket(socket_id)); | |
33 } | |
34 | |
35 UDPSocketExtensionWithDnsLookupFunction:: | |
36 ~UDPSocketExtensionWithDnsLookupFunction() {} | |
37 | |
38 scoped_ptr<SocketResourceManagerInterface> | |
39 UDPSocketExtensionWithDnsLookupFunction::CreateSocketResourceManager() { | |
40 return scoped_ptr<SocketResourceManagerInterface>( | |
41 new SocketResourceManager<ResumableUDPSocket>()).Pass(); | |
42 } | |
43 | |
44 ResumableUDPSocket* UDPSocketExtensionWithDnsLookupFunction::GetUdpSocket( | |
45 int socket_id) { | |
46 return static_cast<ResumableUDPSocket*>(GetSocket(socket_id)); | |
47 } | |
48 | |
49 linked_ptr<sockets_udp::SocketInfo> CreateSocketInfo( | |
50 int socket_id, | |
51 ResumableUDPSocket* socket) { | |
52 linked_ptr<sockets_udp::SocketInfo> socket_info( | |
53 new sockets_udp::SocketInfo()); | |
54 // This represents what we know about the socket, and does not call through | |
55 // to the system. | |
56 socket_info->socket_id = socket_id; | |
57 if (!socket->name().empty()) { | |
58 socket_info->name.reset(new std::string(socket->name())); | |
59 } | |
60 socket_info->persistent = socket->persistent(); | |
61 if (socket->buffer_size() > 0) { | |
62 socket_info->buffer_size.reset(new int(socket->buffer_size())); | |
63 } | |
64 socket_info->paused = socket->paused(); | |
65 | |
66 // Grab the local address as known by the OS. | |
67 net::IPEndPoint localAddress; | |
68 if (socket->GetLocalAddress(&localAddress)) { | |
69 socket_info->local_address.reset( | |
70 new std::string(localAddress.ToStringWithoutPort())); | |
71 socket_info->local_port.reset(new int(localAddress.port())); | |
72 } | |
73 | |
74 return socket_info; | |
75 } | |
76 | |
77 void SetSocketProperties(ResumableUDPSocket* socket, | |
78 sockets_udp::SocketProperties* properties) { | |
79 if (properties->name.get()) { | |
80 socket->set_name(*properties->name.get()); | |
81 } | |
82 if (properties->persistent.get()) { | |
83 socket->set_persistent(*properties->persistent.get()); | |
84 } | |
85 if (properties->buffer_size.get()) { | |
86 socket->set_buffer_size(*properties->buffer_size.get()); | |
87 } | |
88 } | |
89 | |
90 SocketsUdpCreateFunction::SocketsUdpCreateFunction() {} | |
91 | |
92 SocketsUdpCreateFunction::~SocketsUdpCreateFunction() {} | |
93 | |
94 bool SocketsUdpCreateFunction::Prepare() { | |
95 params_ = sockets_udp::Create::Params::Create(*args_); | |
96 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
97 return true; | |
98 } | |
99 | |
100 void SocketsUdpCreateFunction::Work() { | |
101 ResumableUDPSocket* socket = new ResumableUDPSocket(extension_->id()); | |
102 | |
103 sockets_udp::SocketProperties* properties = params_.get()->properties.get(); | |
104 if (properties) { | |
105 SetSocketProperties(socket, properties); | |
106 } | |
107 | |
108 sockets_udp::CreateInfo create_info; | |
109 create_info.socket_id = AddSocket(socket); | |
110 results_ = sockets_udp::Create::Results::Create(create_info); | |
111 } | |
112 | |
113 SocketsUdpUpdateFunction::SocketsUdpUpdateFunction() {} | |
114 | |
115 SocketsUdpUpdateFunction::~SocketsUdpUpdateFunction() {} | |
116 | |
117 bool SocketsUdpUpdateFunction::Prepare() { | |
118 params_ = sockets_udp::Update::Params::Create(*args_); | |
119 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
120 return true; | |
121 } | |
122 | |
123 void SocketsUdpUpdateFunction::Work() { | |
124 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); | |
125 if (!socket) { | |
126 error_ = kSocketNotFoundError; | |
127 return; | |
128 } | |
129 | |
130 SetSocketProperties(socket, ¶ms_.get()->properties); | |
131 results_ = sockets_udp::Update::Results::Create(); | |
132 } | |
133 | |
134 SocketsUdpSetPausedFunction::SocketsUdpSetPausedFunction() | |
135 : socket_event_dispatcher_(NULL) {} | |
136 | |
137 SocketsUdpSetPausedFunction::~SocketsUdpSetPausedFunction() {} | |
138 | |
139 bool SocketsUdpSetPausedFunction::Prepare() { | |
140 params_ = api::sockets_udp::SetPaused::Params::Create(*args_); | |
141 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
142 | |
143 socket_event_dispatcher_ = UDPSocketEventDispatcher::Get(browser_context()); | |
144 DCHECK(socket_event_dispatcher_) << "There is no socket event dispatcher. " | |
145 "If this assertion is failing during a test, then it is likely that " | |
146 "TestExtensionSystem is failing to provide an instance of " | |
147 "UDPSocketEventDispatcher."; | |
148 return socket_event_dispatcher_ != NULL; | |
149 } | |
150 | |
151 void SocketsUdpSetPausedFunction::Work() { | |
152 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); | |
153 if (!socket) { | |
154 error_ = kSocketNotFoundError; | |
155 return; | |
156 } | |
157 | |
158 if (socket->paused() != params_->paused) { | |
159 socket->set_paused(params_->paused); | |
160 if (socket->IsBound() && !params_->paused) { | |
161 socket_event_dispatcher_->OnSocketResume(extension_->id(), | |
162 params_->socket_id); | |
163 } | |
164 } | |
165 | |
166 results_ = sockets_udp::SetPaused::Results::Create(); | |
167 } | |
168 | |
169 SocketsUdpBindFunction::SocketsUdpBindFunction() | |
170 : socket_event_dispatcher_(NULL) { | |
171 } | |
172 | |
173 SocketsUdpBindFunction::~SocketsUdpBindFunction() {} | |
174 | |
175 bool SocketsUdpBindFunction::Prepare() { | |
176 params_ = sockets_udp::Bind::Params::Create(*args_); | |
177 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
178 | |
179 socket_event_dispatcher_ = UDPSocketEventDispatcher::Get(browser_context()); | |
180 DCHECK(socket_event_dispatcher_) << "There is no socket event dispatcher. " | |
181 "If this assertion is failing during a test, then it is likely that " | |
182 "TestExtensionSystem is failing to provide an instance of " | |
183 "UDPSocketEventDispatcher."; | |
184 return socket_event_dispatcher_ != NULL; | |
185 } | |
186 | |
187 void SocketsUdpBindFunction::Work() { | |
188 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); | |
189 if (!socket) { | |
190 error_ = kSocketNotFoundError; | |
191 return; | |
192 } | |
193 | |
194 content::SocketPermissionRequest param( | |
195 SocketPermissionRequest::UDP_BIND, | |
196 params_->address, | |
197 params_->port); | |
198 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) { | |
199 error_ = kPermissionError; | |
200 return; | |
201 } | |
202 | |
203 int net_result = socket->Bind(params_->address, params_->port); | |
204 if (net_result == net::OK) { | |
205 socket_event_dispatcher_->OnSocketBind(extension_->id(), | |
206 params_->socket_id); | |
207 } | |
208 | |
209 if (net_result != net::OK) | |
210 error_ = net::ErrorToString(net_result); | |
211 results_ = sockets_udp::Bind::Results::Create(net_result); | |
212 } | |
213 | |
214 SocketsUdpSendFunction::SocketsUdpSendFunction() | |
215 : io_buffer_size_(0) {} | |
216 | |
217 SocketsUdpSendFunction::~SocketsUdpSendFunction() {} | |
218 | |
219 bool SocketsUdpSendFunction::Prepare() { | |
220 params_ = sockets_udp::Send::Params::Create(*args_); | |
221 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
222 io_buffer_size_ = params_->data.size(); | |
223 io_buffer_ = new net::WrappedIOBuffer(params_->data.data()); | |
224 | |
225 return true; | |
226 } | |
227 | |
228 void SocketsUdpSendFunction::AsyncWorkStart() { | |
229 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); | |
230 if (!socket) { | |
231 error_ = kSocketNotFoundError; | |
232 AsyncWorkCompleted(); | |
233 return; | |
234 } | |
235 | |
236 content::SocketPermissionRequest param( | |
237 SocketPermissionRequest::UDP_SEND_TO, | |
238 params_->address, | |
239 params_->port); | |
240 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) { | |
241 error_ = kPermissionError; | |
242 AsyncWorkCompleted(); | |
243 return; | |
244 } | |
245 | |
246 StartDnsLookup(params_->address); | |
247 } | |
248 | |
249 void SocketsUdpSendFunction::AfterDnsLookup(int lookup_result) { | |
250 if (lookup_result == net::OK) { | |
251 StartSendTo(); | |
252 } else { | |
253 SetSendResult(lookup_result, -1); | |
254 } | |
255 } | |
256 | |
257 void SocketsUdpSendFunction::StartSendTo() { | |
258 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); | |
259 if (!socket) { | |
260 error_ = kSocketNotFoundError; | |
261 AsyncWorkCompleted(); | |
262 return; | |
263 } | |
264 | |
265 socket->SendTo(io_buffer_, io_buffer_size_, resolved_address_, params_->port, | |
266 base::Bind(&SocketsUdpSendFunction::OnCompleted, this)); | |
267 } | |
268 | |
269 void SocketsUdpSendFunction::OnCompleted(int net_result) { | |
270 if (net_result >= net::OK) { | |
271 SetSendResult(net::OK, net_result); | |
272 } else { | |
273 SetSendResult(net_result, -1); | |
274 } | |
275 } | |
276 | |
277 void SocketsUdpSendFunction::SetSendResult(int net_result, int bytes_sent) { | |
278 CHECK(net_result <= net::OK) << "Network status code must be < 0"; | |
279 | |
280 sockets_udp::SendInfo send_info; | |
281 send_info.result_code = net_result; | |
282 if (net_result == net::OK) { | |
283 send_info.bytes_sent.reset(new int(bytes_sent)); | |
284 } | |
285 | |
286 if (net_result != net::OK) | |
287 error_ = net::ErrorToString(net_result); | |
288 results_ = sockets_udp::Send::Results::Create(send_info); | |
289 AsyncWorkCompleted(); | |
290 } | |
291 | |
292 SocketsUdpCloseFunction::SocketsUdpCloseFunction() {} | |
293 | |
294 SocketsUdpCloseFunction::~SocketsUdpCloseFunction() {} | |
295 | |
296 bool SocketsUdpCloseFunction::Prepare() { | |
297 params_ = sockets_udp::Close::Params::Create(*args_); | |
298 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
299 return true; | |
300 } | |
301 | |
302 void SocketsUdpCloseFunction::Work() { | |
303 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); | |
304 if (!socket) { | |
305 error_ = kSocketNotFoundError; | |
306 return; | |
307 } | |
308 | |
309 socket->Disconnect(); | |
310 RemoveSocket(params_->socket_id); | |
311 results_ = sockets_udp::Close::Results::Create(); | |
312 } | |
313 | |
314 SocketsUdpGetInfoFunction::SocketsUdpGetInfoFunction() {} | |
315 | |
316 SocketsUdpGetInfoFunction::~SocketsUdpGetInfoFunction() {} | |
317 | |
318 bool SocketsUdpGetInfoFunction::Prepare() { | |
319 params_ = sockets_udp::GetInfo::Params::Create(*args_); | |
320 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
321 return true; | |
322 } | |
323 | |
324 void SocketsUdpGetInfoFunction::Work() { | |
325 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); | |
326 if (!socket) { | |
327 error_ = kSocketNotFoundError; | |
328 return; | |
329 } | |
330 | |
331 linked_ptr<sockets_udp::SocketInfo> socket_info = | |
332 CreateSocketInfo(params_->socket_id, socket); | |
333 results_ = sockets_udp::GetInfo::Results::Create(*socket_info); | |
334 } | |
335 | |
336 SocketsUdpGetSocketsFunction::SocketsUdpGetSocketsFunction() {} | |
337 | |
338 SocketsUdpGetSocketsFunction::~SocketsUdpGetSocketsFunction() {} | |
339 | |
340 bool SocketsUdpGetSocketsFunction::Prepare() { | |
341 return true; | |
342 } | |
343 | |
344 void SocketsUdpGetSocketsFunction::Work() { | |
345 std::vector<linked_ptr<sockets_udp::SocketInfo> > socket_infos; | |
346 base::hash_set<int>* resource_ids = GetSocketIds(); | |
347 if (resource_ids != NULL) { | |
348 for (base::hash_set<int>::iterator it = resource_ids->begin(); | |
349 it != resource_ids->end(); ++it) { | |
350 int socket_id = *it; | |
351 ResumableUDPSocket* socket = GetUdpSocket(socket_id); | |
352 if (socket) { | |
353 socket_infos.push_back(CreateSocketInfo(socket_id, socket)); | |
354 } | |
355 } | |
356 } | |
357 results_ = sockets_udp::GetSockets::Results::Create(socket_infos); | |
358 } | |
359 | |
360 SocketsUdpJoinGroupFunction::SocketsUdpJoinGroupFunction() {} | |
361 | |
362 SocketsUdpJoinGroupFunction::~SocketsUdpJoinGroupFunction() {} | |
363 | |
364 bool SocketsUdpJoinGroupFunction::Prepare() { | |
365 params_ = sockets_udp::JoinGroup::Params::Create(*args_); | |
366 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
367 return true; | |
368 } | |
369 | |
370 void SocketsUdpJoinGroupFunction::Work() { | |
371 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); | |
372 if (!socket) { | |
373 error_ = kSocketNotFoundError; | |
374 return; | |
375 } | |
376 | |
377 content::SocketPermissionRequest param( | |
378 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, | |
379 kWildcardAddress, | |
380 kWildcardPort); | |
381 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) { | |
382 error_ = kPermissionError; | |
383 return; | |
384 } | |
385 | |
386 int net_result = socket->JoinGroup(params_->address); | |
387 if (net_result != net::OK) | |
388 error_ = net::ErrorToString(net_result); | |
389 results_ = sockets_udp::JoinGroup::Results::Create(net_result); | |
390 } | |
391 | |
392 SocketsUdpLeaveGroupFunction::SocketsUdpLeaveGroupFunction() {} | |
393 | |
394 SocketsUdpLeaveGroupFunction::~SocketsUdpLeaveGroupFunction() {} | |
395 | |
396 bool SocketsUdpLeaveGroupFunction::Prepare() { | |
397 params_ = api::sockets_udp::LeaveGroup::Params::Create(*args_); | |
398 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
399 return true; | |
400 } | |
401 | |
402 void SocketsUdpLeaveGroupFunction::Work() { | |
403 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); | |
404 if (!socket) { | |
405 error_ = kSocketNotFoundError; | |
406 return; | |
407 } | |
408 | |
409 content::SocketPermissionRequest param( | |
410 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, | |
411 kWildcardAddress, | |
412 kWildcardPort); | |
413 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) { | |
414 error_ = kPermissionError; | |
415 return; | |
416 } | |
417 | |
418 int net_result = socket->LeaveGroup(params_->address); | |
419 if (net_result != net::OK) | |
420 error_ = net::ErrorToString(net_result); | |
421 results_ = sockets_udp::LeaveGroup::Results::Create(net_result); | |
422 } | |
423 | |
424 SocketsUdpSetMulticastTimeToLiveFunction:: | |
425 SocketsUdpSetMulticastTimeToLiveFunction() {} | |
426 | |
427 SocketsUdpSetMulticastTimeToLiveFunction:: | |
428 ~SocketsUdpSetMulticastTimeToLiveFunction() {} | |
429 | |
430 bool SocketsUdpSetMulticastTimeToLiveFunction::Prepare() { | |
431 params_ = api::sockets_udp::SetMulticastTimeToLive::Params::Create(*args_); | |
432 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
433 return true; | |
434 } | |
435 | |
436 void SocketsUdpSetMulticastTimeToLiveFunction::Work() { | |
437 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); | |
438 if (!socket) { | |
439 error_ = kSocketNotFoundError; | |
440 return; | |
441 } | |
442 | |
443 int net_result = socket->SetMulticastTimeToLive(params_->ttl); | |
444 if (net_result != net::OK) | |
445 error_ = net::ErrorToString(net_result); | |
446 results_ = sockets_udp::SetMulticastTimeToLive::Results::Create(net_result); | |
447 } | |
448 | |
449 SocketsUdpSetMulticastLoopbackModeFunction:: | |
450 SocketsUdpSetMulticastLoopbackModeFunction() {} | |
451 | |
452 SocketsUdpSetMulticastLoopbackModeFunction:: | |
453 ~SocketsUdpSetMulticastLoopbackModeFunction() {} | |
454 | |
455 bool SocketsUdpSetMulticastLoopbackModeFunction::Prepare() { | |
456 params_ = api::sockets_udp::SetMulticastLoopbackMode::Params::Create(*args_); | |
457 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
458 return true; | |
459 } | |
460 | |
461 void SocketsUdpSetMulticastLoopbackModeFunction::Work() { | |
462 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); | |
463 if (!socket) { | |
464 error_ = kSocketNotFoundError; | |
465 return; | |
466 } | |
467 | |
468 int net_result = socket->SetMulticastLoopbackMode(params_->enabled); | |
469 if (net_result != net::OK) | |
470 error_ = net::ErrorToString(net_result); | |
471 results_ = sockets_udp::SetMulticastLoopbackMode::Results::Create(net_result); | |
472 } | |
473 | |
474 SocketsUdpGetJoinedGroupsFunction::SocketsUdpGetJoinedGroupsFunction() {} | |
475 | |
476 SocketsUdpGetJoinedGroupsFunction::~SocketsUdpGetJoinedGroupsFunction() {} | |
477 | |
478 bool SocketsUdpGetJoinedGroupsFunction::Prepare() { | |
479 params_ = api::sockets_udp::GetJoinedGroups::Params::Create(*args_); | |
480 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
481 return true; | |
482 } | |
483 | |
484 void SocketsUdpGetJoinedGroupsFunction::Work() { | |
485 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); | |
486 if (!socket) { | |
487 error_ = kSocketNotFoundError; | |
488 return; | |
489 } | |
490 | |
491 content::SocketPermissionRequest param( | |
492 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, | |
493 kWildcardAddress, | |
494 kWildcardPort); | |
495 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) { | |
496 error_ = kPermissionError; | |
497 return; | |
498 } | |
499 | |
500 const std::vector<std::string>& groups = socket->GetJoinedGroups(); | |
501 results_ = sockets_udp::GetJoinedGroups::Results::Create(groups); | |
502 } | |
503 | |
504 } // namespace api | |
505 } // namespace extensions | |
OLD | NEW |