1 // Copyright 2014 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 "extensions/browser/api/sockets_udp/sockets_udp_api.h"
7 #include "content/public/common/socket_permission_request.h"
8 #include "extensions/browser/api/socket/udp_socket.h"
9 #include "extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.h"
10 #include "extensions/common/api/sockets/sockets_manifest_data.h"
11 #include "net/base/net_errors.h"
13 namespace extensions
{
16 using content::SocketPermissionRequest
;
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;
23 UDPSocketAsyncApiFunction::~UDPSocketAsyncApiFunction() {}
25 scoped_ptr
<SocketResourceManagerInterface
>
26 UDPSocketAsyncApiFunction::CreateSocketResourceManager() {
27 return scoped_ptr
<SocketResourceManagerInterface
>(
28 new SocketResourceManager
<ResumableUDPSocket
>()).Pass();
31 ResumableUDPSocket
* UDPSocketAsyncApiFunction::GetUdpSocket(int socket_id
) {
32 return static_cast<ResumableUDPSocket
*>(GetSocket(socket_id
));
35 UDPSocketExtensionWithDnsLookupFunction::
36 ~UDPSocketExtensionWithDnsLookupFunction() {}
38 scoped_ptr
<SocketResourceManagerInterface
>
39 UDPSocketExtensionWithDnsLookupFunction::CreateSocketResourceManager() {
40 return scoped_ptr
<SocketResourceManagerInterface
>(
41 new SocketResourceManager
<ResumableUDPSocket
>()).Pass();
44 ResumableUDPSocket
* UDPSocketExtensionWithDnsLookupFunction::GetUdpSocket(
46 return static_cast<ResumableUDPSocket
*>(GetSocket(socket_id
));
49 linked_ptr
<sockets_udp::SocketInfo
> CreateSocketInfo(
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
56 socket_info
->socket_id
= socket_id
;
57 if (!socket
->name().empty()) {
58 socket_info
->name
.reset(new std::string(socket
->name()));
60 socket_info
->persistent
= socket
->persistent();
61 if (socket
->buffer_size() > 0) {
62 socket_info
->buffer_size
.reset(new int(socket
->buffer_size()));
64 socket_info
->paused
= socket
->paused();
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()));
77 void SetSocketProperties(ResumableUDPSocket
* socket
,
78 sockets_udp::SocketProperties
* properties
) {
79 if (properties
->name
.get()) {
80 socket
->set_name(*properties
->name
.get());
82 if (properties
->persistent
.get()) {
83 socket
->set_persistent(*properties
->persistent
.get());
85 if (properties
->buffer_size
.get()) {
86 socket
->set_buffer_size(*properties
->buffer_size
.get());
90 SocketsUdpCreateFunction::SocketsUdpCreateFunction() {}
92 SocketsUdpCreateFunction::~SocketsUdpCreateFunction() {}
94 bool SocketsUdpCreateFunction::Prepare() {
95 params_
= sockets_udp::Create::Params::Create(*args_
);
96 EXTENSION_FUNCTION_VALIDATE(params_
.get());
100 void SocketsUdpCreateFunction::Work() {
101 ResumableUDPSocket
* socket
= new ResumableUDPSocket(extension_
->id());
103 sockets_udp::SocketProperties
* properties
= params_
.get()->properties
.get();
105 SetSocketProperties(socket
, properties
);
108 sockets_udp::CreateInfo create_info
;
109 create_info
.socket_id
= AddSocket(socket
);
110 results_
= sockets_udp::Create::Results::Create(create_info
);
113 SocketsUdpUpdateFunction::SocketsUdpUpdateFunction() {}
115 SocketsUdpUpdateFunction::~SocketsUdpUpdateFunction() {}
117 bool SocketsUdpUpdateFunction::Prepare() {
118 params_
= sockets_udp::Update::Params::Create(*args_
);
119 EXTENSION_FUNCTION_VALIDATE(params_
.get());
123 void SocketsUdpUpdateFunction::Work() {
124 ResumableUDPSocket
* socket
= GetUdpSocket(params_
->socket_id
);
126 error_
= kSocketNotFoundError
;
130 SetSocketProperties(socket
, ¶ms_
.get()->properties
);
131 results_
= sockets_udp::Update::Results::Create();
134 SocketsUdpSetPausedFunction::SocketsUdpSetPausedFunction()
135 : socket_event_dispatcher_(NULL
) {}
137 SocketsUdpSetPausedFunction::~SocketsUdpSetPausedFunction() {}
139 bool SocketsUdpSetPausedFunction::Prepare() {
140 params_
= api::sockets_udp::SetPaused::Params::Create(*args_
);
141 EXTENSION_FUNCTION_VALIDATE(params_
.get());
143 socket_event_dispatcher_
= UDPSocketEventDispatcher::Get(browser_context());
144 DCHECK(socket_event_dispatcher_
)
145 << "There is no socket event dispatcher. "
146 "If this assertion is failing during a test, then it is likely that "
147 "TestExtensionSystem is failing to provide an instance of "
148 "UDPSocketEventDispatcher.";
149 return socket_event_dispatcher_
!= NULL
;
152 void SocketsUdpSetPausedFunction::Work() {
153 ResumableUDPSocket
* socket
= GetUdpSocket(params_
->socket_id
);
155 error_
= kSocketNotFoundError
;
159 if (socket
->paused() != params_
->paused
) {
160 socket
->set_paused(params_
->paused
);
161 if (socket
->IsBound() && !params_
->paused
) {
162 socket_event_dispatcher_
->OnSocketResume(extension_
->id(),
167 results_
= sockets_udp::SetPaused::Results::Create();
170 SocketsUdpBindFunction::SocketsUdpBindFunction()
171 : socket_event_dispatcher_(NULL
) {}
173 SocketsUdpBindFunction::~SocketsUdpBindFunction() {}
175 bool SocketsUdpBindFunction::Prepare() {
176 params_
= sockets_udp::Bind::Params::Create(*args_
);
177 EXTENSION_FUNCTION_VALIDATE(params_
.get());
179 socket_event_dispatcher_
= UDPSocketEventDispatcher::Get(browser_context());
180 DCHECK(socket_event_dispatcher_
)
181 << "There is no socket event dispatcher. "
182 "If this assertion is failing during a test, then it is likely that "
183 "TestExtensionSystem is failing to provide an instance of "
184 "UDPSocketEventDispatcher.";
185 return socket_event_dispatcher_
!= NULL
;
188 void SocketsUdpBindFunction::AsyncWorkStart() {
189 ResumableUDPSocket
* socket
= GetUdpSocket(params_
->socket_id
);
191 error_
= kSocketNotFoundError
;
192 AsyncWorkCompleted();
196 content::SocketPermissionRequest
param(
197 SocketPermissionRequest::UDP_BIND
, params_
->address
, params_
->port
);
198 if (!SocketsManifestData::CheckRequest(extension(), param
)) {
199 error_
= kPermissionError
;
200 AsyncWorkCompleted();
204 int net_result
= socket
->Bind(params_
->address
, params_
->port
);
205 results_
= sockets_udp::Bind::Results::Create(net_result
);
206 if (net_result
== net::OK
) {
207 socket_event_dispatcher_
->OnSocketBind(extension_
->id(),
210 error_
= net::ErrorToString(net_result
);
211 AsyncWorkCompleted();
215 OpenFirewallHole(params_
->address
, params_
->socket_id
, socket
);
218 SocketsUdpSendFunction::SocketsUdpSendFunction() : io_buffer_size_(0) {}
220 SocketsUdpSendFunction::~SocketsUdpSendFunction() {}
222 bool SocketsUdpSendFunction::Prepare() {
223 params_
= sockets_udp::Send::Params::Create(*args_
);
224 EXTENSION_FUNCTION_VALIDATE(params_
.get());
225 io_buffer_size_
= params_
->data
.size();
226 io_buffer_
= new net::WrappedIOBuffer(params_
->data
.data());
231 void SocketsUdpSendFunction::AsyncWorkStart() {
232 ResumableUDPSocket
* socket
= GetUdpSocket(params_
->socket_id
);
234 error_
= kSocketNotFoundError
;
235 AsyncWorkCompleted();
239 content::SocketPermissionRequest
param(
240 SocketPermissionRequest::UDP_SEND_TO
, params_
->address
, params_
->port
);
241 if (!SocketsManifestData::CheckRequest(extension(), param
)) {
242 error_
= kPermissionError
;
243 AsyncWorkCompleted();
247 StartDnsLookup(net::HostPortPair(params_
->address
, params_
->port
));
250 void SocketsUdpSendFunction::AfterDnsLookup(int lookup_result
) {
251 if (lookup_result
== net::OK
) {
254 SetSendResult(lookup_result
, -1);
258 void SocketsUdpSendFunction::StartSendTo() {
259 ResumableUDPSocket
* socket
= GetUdpSocket(params_
->socket_id
);
261 error_
= kSocketNotFoundError
;
262 AsyncWorkCompleted();
266 socket
->SendTo(io_buffer_
, io_buffer_size_
, addresses_
.front(),
267 base::Bind(&SocketsUdpSendFunction::OnCompleted
, this));
270 void SocketsUdpSendFunction::OnCompleted(int net_result
) {
271 if (net_result
>= net::OK
) {
272 SetSendResult(net::OK
, net_result
);
274 SetSendResult(net_result
, -1);
278 void SocketsUdpSendFunction::SetSendResult(int net_result
, int bytes_sent
) {
279 CHECK(net_result
<= net::OK
) << "Network status code must be < 0";
281 sockets_udp::SendInfo send_info
;
282 send_info
.result_code
= net_result
;
283 if (net_result
== net::OK
) {
284 send_info
.bytes_sent
.reset(new int(bytes_sent
));
287 if (net_result
!= net::OK
)
288 error_
= net::ErrorToString(net_result
);
289 results_
= sockets_udp::Send::Results::Create(send_info
);
290 AsyncWorkCompleted();
293 SocketsUdpCloseFunction::SocketsUdpCloseFunction() {}
295 SocketsUdpCloseFunction::~SocketsUdpCloseFunction() {}
297 bool SocketsUdpCloseFunction::Prepare() {
298 params_
= sockets_udp::Close::Params::Create(*args_
);
299 EXTENSION_FUNCTION_VALIDATE(params_
.get());
303 void SocketsUdpCloseFunction::Work() {
304 ResumableUDPSocket
* socket
= GetUdpSocket(params_
->socket_id
);
306 error_
= kSocketNotFoundError
;
310 socket
->Disconnect();
311 RemoveSocket(params_
->socket_id
);
312 results_
= sockets_udp::Close::Results::Create();
315 SocketsUdpGetInfoFunction::SocketsUdpGetInfoFunction() {}
317 SocketsUdpGetInfoFunction::~SocketsUdpGetInfoFunction() {}
319 bool SocketsUdpGetInfoFunction::Prepare() {
320 params_
= sockets_udp::GetInfo::Params::Create(*args_
);
321 EXTENSION_FUNCTION_VALIDATE(params_
.get());
325 void SocketsUdpGetInfoFunction::Work() {
326 ResumableUDPSocket
* socket
= GetUdpSocket(params_
->socket_id
);
328 error_
= kSocketNotFoundError
;
332 linked_ptr
<sockets_udp::SocketInfo
> socket_info
=
333 CreateSocketInfo(params_
->socket_id
, socket
);
334 results_
= sockets_udp::GetInfo::Results::Create(*socket_info
);
337 SocketsUdpGetSocketsFunction::SocketsUdpGetSocketsFunction() {}
339 SocketsUdpGetSocketsFunction::~SocketsUdpGetSocketsFunction() {}
341 bool SocketsUdpGetSocketsFunction::Prepare() { return true; }
343 void SocketsUdpGetSocketsFunction::Work() {
344 std::vector
<linked_ptr
<sockets_udp::SocketInfo
> > socket_infos
;
345 base::hash_set
<int>* resource_ids
= GetSocketIds();
346 if (resource_ids
!= NULL
) {
347 for (base::hash_set
<int>::iterator it
= resource_ids
->begin();
348 it
!= resource_ids
->end();
351 ResumableUDPSocket
* socket
= GetUdpSocket(socket_id
);
353 socket_infos
.push_back(CreateSocketInfo(socket_id
, socket
));
357 results_
= sockets_udp::GetSockets::Results::Create(socket_infos
);
360 SocketsUdpJoinGroupFunction::SocketsUdpJoinGroupFunction() {}
362 SocketsUdpJoinGroupFunction::~SocketsUdpJoinGroupFunction() {}
364 bool SocketsUdpJoinGroupFunction::Prepare() {
365 params_
= sockets_udp::JoinGroup::Params::Create(*args_
);
366 EXTENSION_FUNCTION_VALIDATE(params_
.get());
370 void SocketsUdpJoinGroupFunction::Work() {
371 ResumableUDPSocket
* socket
= GetUdpSocket(params_
->socket_id
);
373 error_
= kSocketNotFoundError
;
377 content::SocketPermissionRequest
param(
378 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
381 if (!SocketsManifestData::CheckRequest(extension(), param
)) {
382 error_
= kPermissionError
;
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
);
392 SocketsUdpLeaveGroupFunction::SocketsUdpLeaveGroupFunction() {}
394 SocketsUdpLeaveGroupFunction::~SocketsUdpLeaveGroupFunction() {}
396 bool SocketsUdpLeaveGroupFunction::Prepare() {
397 params_
= api::sockets_udp::LeaveGroup::Params::Create(*args_
);
398 EXTENSION_FUNCTION_VALIDATE(params_
.get());
402 void SocketsUdpLeaveGroupFunction::Work() {
403 ResumableUDPSocket
* socket
= GetUdpSocket(params_
->socket_id
);
405 error_
= kSocketNotFoundError
;
409 content::SocketPermissionRequest
param(
410 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
413 if (!SocketsManifestData::CheckRequest(extension(), param
)) {
414 error_
= kPermissionError
;
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
);
424 SocketsUdpSetMulticastTimeToLiveFunction::
425 SocketsUdpSetMulticastTimeToLiveFunction() {}
427 SocketsUdpSetMulticastTimeToLiveFunction::
428 ~SocketsUdpSetMulticastTimeToLiveFunction() {}
430 bool SocketsUdpSetMulticastTimeToLiveFunction::Prepare() {
431 params_
= api::sockets_udp::SetMulticastTimeToLive::Params::Create(*args_
);
432 EXTENSION_FUNCTION_VALIDATE(params_
.get());
436 void SocketsUdpSetMulticastTimeToLiveFunction::Work() {
437 ResumableUDPSocket
* socket
= GetUdpSocket(params_
->socket_id
);
439 error_
= kSocketNotFoundError
;
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
);
449 SocketsUdpSetMulticastLoopbackModeFunction::
450 SocketsUdpSetMulticastLoopbackModeFunction() {}
452 SocketsUdpSetMulticastLoopbackModeFunction::
453 ~SocketsUdpSetMulticastLoopbackModeFunction() {}
455 bool SocketsUdpSetMulticastLoopbackModeFunction::Prepare() {
456 params_
= api::sockets_udp::SetMulticastLoopbackMode::Params::Create(*args_
);
457 EXTENSION_FUNCTION_VALIDATE(params_
.get());
461 void SocketsUdpSetMulticastLoopbackModeFunction::Work() {
462 ResumableUDPSocket
* socket
= GetUdpSocket(params_
->socket_id
);
464 error_
= kSocketNotFoundError
;
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
);
474 SocketsUdpGetJoinedGroupsFunction::SocketsUdpGetJoinedGroupsFunction() {}
476 SocketsUdpGetJoinedGroupsFunction::~SocketsUdpGetJoinedGroupsFunction() {}
478 bool SocketsUdpGetJoinedGroupsFunction::Prepare() {
479 params_
= api::sockets_udp::GetJoinedGroups::Params::Create(*args_
);
480 EXTENSION_FUNCTION_VALIDATE(params_
.get());
484 void SocketsUdpGetJoinedGroupsFunction::Work() {
485 ResumableUDPSocket
* socket
= GetUdpSocket(params_
->socket_id
);
487 error_
= kSocketNotFoundError
;
491 content::SocketPermissionRequest
param(
492 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
495 if (!SocketsManifestData::CheckRequest(extension(), param
)) {
496 error_
= kPermissionError
;
500 const std::vector
<std::string
>& groups
= socket
->GetJoinedGroups();
501 results_
= sockets_udp::GetJoinedGroups::Results::Create(groups
);
504 SocketsUdpSetBroadcastFunction::SocketsUdpSetBroadcastFunction() {
507 SocketsUdpSetBroadcastFunction::~SocketsUdpSetBroadcastFunction() {
510 bool SocketsUdpSetBroadcastFunction::Prepare() {
511 params_
= api::sockets_udp::SetBroadcast::Params::Create(*args_
);
512 EXTENSION_FUNCTION_VALIDATE(params_
.get());
516 void SocketsUdpSetBroadcastFunction::Work() {
517 ResumableUDPSocket
* socket
= GetUdpSocket(params_
->socket_id
);
519 error_
= kSocketNotFoundError
;
523 int net_result
= socket
->SetBroadcast(params_
->enabled
);
524 if (net_result
!= net::OK
) {
525 error_
= net::ErrorToString(net_result
);
527 results_
= sockets_udp::SetBroadcast::Results::Create(net_result
);
531 } // namespace extensions