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/socket/socket_api.h"
10 #include "base/containers/hash_tables.h"
11 #include "content/public/browser/browser_context.h"
12 #include "content/public/browser/resource_context.h"
13 #include "extensions/browser/api/dns/host_resolver_wrapper.h"
14 #include "extensions/browser/api/socket/socket.h"
15 #include "extensions/browser/api/socket/tcp_socket.h"
16 #include "extensions/browser/api/socket/tls_socket.h"
17 #include "extensions/browser/api/socket/udp_socket.h"
18 #include "extensions/browser/extension_system.h"
19 #include "extensions/common/extension.h"
20 #include "extensions/common/permissions/permissions_data.h"
21 #include "extensions/common/permissions/socket_permission.h"
22 #include "net/base/host_port_pair.h"
23 #include "net/base/io_buffer.h"
24 #include "net/base/ip_endpoint.h"
25 #include "net/base/net_errors.h"
26 #include "net/base/net_log.h"
27 #include "net/base/net_util.h"
28 #include "net/url_request/url_request_context.h"
29 #include "net/url_request/url_request_context_getter.h"
31 namespace extensions
{
33 using content::SocketPermissionRequest
;
35 const char kAddressKey
[] = "address";
36 const char kPortKey
[] = "port";
37 const char kBytesWrittenKey
[] = "bytesWritten";
38 const char kDataKey
[] = "data";
39 const char kResultCodeKey
[] = "resultCode";
40 const char kSocketIdKey
[] = "socketId";
42 const char kSocketNotFoundError
[] = "Socket not found";
43 const char kDnsLookupFailedError
[] = "DNS resolution failed";
44 const char kPermissionError
[] = "App does not have permission";
45 const char kNetworkListError
[] = "Network lookup failed or unsupported";
46 const char kTCPSocketBindError
[] =
47 "TCP socket does not support bind. For TCP server please use listen.";
48 const char kMulticastSocketTypeError
[] = "Only UDP socket supports multicast.";
49 const char kSecureSocketTypeError
[] = "Only TCP sockets are supported for TLS.";
50 const char kSocketNotConnectedError
[] = "Socket not connected";
51 const char kWildcardAddress
[] = "*";
52 const int kWildcardPort
= 0;
54 SocketAsyncApiFunction::SocketAsyncApiFunction() {}
56 SocketAsyncApiFunction::~SocketAsyncApiFunction() {}
58 bool SocketAsyncApiFunction::PrePrepare() {
59 manager_
= CreateSocketResourceManager();
60 return manager_
->SetBrowserContext(browser_context());
63 bool SocketAsyncApiFunction::Respond() { return error_
.empty(); }
65 scoped_ptr
<SocketResourceManagerInterface
>
66 SocketAsyncApiFunction::CreateSocketResourceManager() {
67 return scoped_ptr
<SocketResourceManagerInterface
>(
68 new SocketResourceManager
<Socket
>()).Pass();
71 int SocketAsyncApiFunction::AddSocket(Socket
* socket
) {
72 return manager_
->Add(socket
);
75 Socket
* SocketAsyncApiFunction::GetSocket(int api_resource_id
) {
76 return manager_
->Get(extension_
->id(), api_resource_id
);
79 void SocketAsyncApiFunction::ReplaceSocket(int api_resource_id
,
81 manager_
->Replace(extension_
->id(), api_resource_id
, socket
);
84 base::hash_set
<int>* SocketAsyncApiFunction::GetSocketIds() {
85 return manager_
->GetResourceIds(extension_
->id());
88 void SocketAsyncApiFunction::RemoveSocket(int api_resource_id
) {
89 manager_
->Remove(extension_
->id(), api_resource_id
);
92 SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction()
93 : resource_context_(NULL
),
94 request_handle_(new net::HostResolver::RequestHandle
),
95 addresses_(new net::AddressList
) {}
97 SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() {}
99 bool SocketExtensionWithDnsLookupFunction::PrePrepare() {
100 if (!SocketAsyncApiFunction::PrePrepare())
102 resource_context_
= browser_context()->GetResourceContext();
103 return resource_context_
!= NULL
;
106 void SocketExtensionWithDnsLookupFunction::StartDnsLookup(
107 const std::string
& hostname
) {
108 net::HostResolver
* host_resolver
=
109 HostResolverWrapper::GetInstance()->GetHostResolver(resource_context_
);
110 DCHECK(host_resolver
);
112 // Yes, we are passing zero as the port. There are some interesting but not
113 // presently relevant reasons why HostResolver asks for the port of the
114 // hostname you'd like to resolve, even though it doesn't use that value in
115 // determining its answer.
116 net::HostPortPair
host_port_pair(hostname
, 0);
118 net::HostResolver::RequestInfo
request_info(host_port_pair
);
119 int resolve_result
= host_resolver
->Resolve(
121 net::DEFAULT_PRIORITY
,
123 base::Bind(&SocketExtensionWithDnsLookupFunction::OnDnsLookup
, this),
124 request_handle_
.get(),
127 if (resolve_result
!= net::ERR_IO_PENDING
)
128 OnDnsLookup(resolve_result
);
131 void SocketExtensionWithDnsLookupFunction::OnDnsLookup(int resolve_result
) {
132 if (resolve_result
== net::OK
) {
133 DCHECK(!addresses_
->empty());
134 resolved_address_
= addresses_
->front().ToStringWithoutPort();
136 error_
= kDnsLookupFailedError
;
138 AfterDnsLookup(resolve_result
);
141 SocketCreateFunction::SocketCreateFunction()
142 : socket_type_(kSocketTypeInvalid
) {}
144 SocketCreateFunction::~SocketCreateFunction() {}
146 bool SocketCreateFunction::Prepare() {
147 params_
= core_api::socket::Create::Params::Create(*args_
);
148 EXTENSION_FUNCTION_VALIDATE(params_
.get());
150 switch (params_
->type
) {
151 case extensions::core_api::socket::SOCKET_TYPE_TCP
:
152 socket_type_
= kSocketTypeTCP
;
154 case extensions::core_api::socket::SOCKET_TYPE_UDP
:
155 socket_type_
= kSocketTypeUDP
;
157 case extensions::core_api::socket::SOCKET_TYPE_NONE
:
165 void SocketCreateFunction::Work() {
166 Socket
* socket
= NULL
;
167 if (socket_type_
== kSocketTypeTCP
) {
168 socket
= new TCPSocket(extension_
->id());
169 } else if (socket_type_
== kSocketTypeUDP
) {
170 socket
= new UDPSocket(extension_
->id());
174 base::DictionaryValue
* result
= new base::DictionaryValue();
175 result
->SetInteger(kSocketIdKey
, AddSocket(socket
));
179 bool SocketDestroyFunction::Prepare() {
180 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
184 void SocketDestroyFunction::Work() { RemoveSocket(socket_id_
); }
186 SocketConnectFunction::SocketConnectFunction()
187 : socket_id_(0), hostname_(), port_(0) {
190 SocketConnectFunction::~SocketConnectFunction() {}
192 bool SocketConnectFunction::Prepare() {
193 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
194 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(1, &hostname_
));
195 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(2, &port_
));
199 void SocketConnectFunction::AsyncWorkStart() {
200 Socket
* socket
= GetSocket(socket_id_
);
202 error_
= kSocketNotFoundError
;
203 SetResult(new base::FundamentalValue(-1));
204 AsyncWorkCompleted();
208 socket
->set_hostname(hostname_
);
210 SocketPermissionRequest::OperationType operation_type
;
211 switch (socket
->GetSocketType()) {
212 case Socket::TYPE_TCP
:
213 operation_type
= SocketPermissionRequest::TCP_CONNECT
;
215 case Socket::TYPE_UDP
:
216 operation_type
= SocketPermissionRequest::UDP_SEND_TO
;
219 NOTREACHED() << "Unknown socket type.";
220 operation_type
= SocketPermissionRequest::NONE
;
224 SocketPermission::CheckParam
param(operation_type
, hostname_
, port_
);
225 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
226 APIPermission::kSocket
, ¶m
)) {
227 error_
= kPermissionError
;
228 SetResult(new base::FundamentalValue(-1));
229 AsyncWorkCompleted();
233 StartDnsLookup(hostname_
);
236 void SocketConnectFunction::AfterDnsLookup(int lookup_result
) {
237 if (lookup_result
== net::OK
) {
240 SetResult(new base::FundamentalValue(lookup_result
));
241 AsyncWorkCompleted();
245 void SocketConnectFunction::StartConnect() {
246 Socket
* socket
= GetSocket(socket_id_
);
248 error_
= kSocketNotFoundError
;
249 SetResult(new base::FundamentalValue(-1));
250 AsyncWorkCompleted();
254 socket
->Connect(resolved_address_
,
256 base::Bind(&SocketConnectFunction::OnConnect
, this));
259 void SocketConnectFunction::OnConnect(int result
) {
260 SetResult(new base::FundamentalValue(result
));
261 AsyncWorkCompleted();
264 bool SocketDisconnectFunction::Prepare() {
265 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
269 void SocketDisconnectFunction::Work() {
270 Socket
* socket
= GetSocket(socket_id_
);
272 socket
->Disconnect();
274 error_
= kSocketNotFoundError
;
275 SetResult(base::Value::CreateNullValue());
278 bool SocketBindFunction::Prepare() {
279 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
280 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(1, &address_
));
281 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(2, &port_
));
285 void SocketBindFunction::Work() {
287 Socket
* socket
= GetSocket(socket_id_
);
290 error_
= kSocketNotFoundError
;
291 SetResult(new base::FundamentalValue(result
));
295 if (socket
->GetSocketType() == Socket::TYPE_UDP
) {
296 SocketPermission::CheckParam
param(
297 SocketPermissionRequest::UDP_BIND
, address_
, port_
);
298 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
299 APIPermission::kSocket
, ¶m
)) {
300 error_
= kPermissionError
;
301 SetResult(new base::FundamentalValue(result
));
304 } else if (socket
->GetSocketType() == Socket::TYPE_TCP
) {
305 error_
= kTCPSocketBindError
;
306 SetResult(new base::FundamentalValue(result
));
310 result
= socket
->Bind(address_
, port_
);
311 SetResult(new base::FundamentalValue(result
));
314 SocketListenFunction::SocketListenFunction() {}
316 SocketListenFunction::~SocketListenFunction() {}
318 bool SocketListenFunction::Prepare() {
319 params_
= core_api::socket::Listen::Params::Create(*args_
);
320 EXTENSION_FUNCTION_VALIDATE(params_
.get());
324 void SocketListenFunction::Work() {
327 Socket
* socket
= GetSocket(params_
->socket_id
);
329 SocketPermission::CheckParam
param(
330 SocketPermissionRequest::TCP_LISTEN
, params_
->address
, params_
->port
);
331 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
332 APIPermission::kSocket
, ¶m
)) {
333 error_
= kPermissionError
;
334 SetResult(new base::FundamentalValue(result
));
339 socket
->Listen(params_
->address
,
341 params_
->backlog
.get() ? *params_
->backlog
.get() : 5,
344 error_
= kSocketNotFoundError
;
347 SetResult(new base::FundamentalValue(result
));
350 SocketAcceptFunction::SocketAcceptFunction() {}
352 SocketAcceptFunction::~SocketAcceptFunction() {}
354 bool SocketAcceptFunction::Prepare() {
355 params_
= core_api::socket::Accept::Params::Create(*args_
);
356 EXTENSION_FUNCTION_VALIDATE(params_
.get());
360 void SocketAcceptFunction::AsyncWorkStart() {
361 Socket
* socket
= GetSocket(params_
->socket_id
);
363 socket
->Accept(base::Bind(&SocketAcceptFunction::OnAccept
, this));
365 error_
= kSocketNotFoundError
;
370 void SocketAcceptFunction::OnAccept(int result_code
,
371 net::TCPClientSocket
* socket
) {
372 base::DictionaryValue
* result
= new base::DictionaryValue();
373 result
->SetInteger(kResultCodeKey
, result_code
);
375 Socket
* client_socket
= new TCPSocket(socket
, extension_id(), true);
376 result
->SetInteger(kSocketIdKey
, AddSocket(client_socket
));
380 AsyncWorkCompleted();
383 SocketReadFunction::SocketReadFunction() {}
385 SocketReadFunction::~SocketReadFunction() {}
387 bool SocketReadFunction::Prepare() {
388 params_
= core_api::socket::Read::Params::Create(*args_
);
389 EXTENSION_FUNCTION_VALIDATE(params_
.get());
393 void SocketReadFunction::AsyncWorkStart() {
394 Socket
* socket
= GetSocket(params_
->socket_id
);
396 error_
= kSocketNotFoundError
;
397 OnCompleted(-1, NULL
);
401 socket
->Read(params_
->buffer_size
.get() ? *params_
->buffer_size
.get() : 4096,
402 base::Bind(&SocketReadFunction::OnCompleted
, this));
405 void SocketReadFunction::OnCompleted(int bytes_read
,
406 scoped_refptr
<net::IOBuffer
> io_buffer
) {
407 base::DictionaryValue
* result
= new base::DictionaryValue();
408 result
->SetInteger(kResultCodeKey
, bytes_read
);
409 if (bytes_read
> 0) {
410 result
->Set(kDataKey
,
411 base::BinaryValue::CreateWithCopiedBuffer(io_buffer
->data(),
414 result
->Set(kDataKey
, new base::BinaryValue());
418 AsyncWorkCompleted();
421 SocketWriteFunction::SocketWriteFunction()
422 : socket_id_(0), io_buffer_(NULL
), io_buffer_size_(0) {}
424 SocketWriteFunction::~SocketWriteFunction() {}
426 bool SocketWriteFunction::Prepare() {
427 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
428 base::BinaryValue
* data
= NULL
;
429 EXTENSION_FUNCTION_VALIDATE(args_
->GetBinary(1, &data
));
431 io_buffer_size_
= data
->GetSize();
432 io_buffer_
= new net::WrappedIOBuffer(data
->GetBuffer());
436 void SocketWriteFunction::AsyncWorkStart() {
437 Socket
* socket
= GetSocket(socket_id_
);
440 error_
= kSocketNotFoundError
;
445 socket
->Write(io_buffer_
,
447 base::Bind(&SocketWriteFunction::OnCompleted
, this));
450 void SocketWriteFunction::OnCompleted(int bytes_written
) {
451 base::DictionaryValue
* result
= new base::DictionaryValue();
452 result
->SetInteger(kBytesWrittenKey
, bytes_written
);
455 AsyncWorkCompleted();
458 SocketRecvFromFunction::SocketRecvFromFunction() {}
460 SocketRecvFromFunction::~SocketRecvFromFunction() {}
462 bool SocketRecvFromFunction::Prepare() {
463 params_
= core_api::socket::RecvFrom::Params::Create(*args_
);
464 EXTENSION_FUNCTION_VALIDATE(params_
.get());
468 void SocketRecvFromFunction::AsyncWorkStart() {
469 Socket
* socket
= GetSocket(params_
->socket_id
);
471 error_
= kSocketNotFoundError
;
472 OnCompleted(-1, NULL
, std::string(), 0);
476 socket
->RecvFrom(params_
->buffer_size
.get() ? *params_
->buffer_size
: 4096,
477 base::Bind(&SocketRecvFromFunction::OnCompleted
, this));
480 void SocketRecvFromFunction::OnCompleted(int bytes_read
,
481 scoped_refptr
<net::IOBuffer
> io_buffer
,
482 const std::string
& address
,
484 base::DictionaryValue
* result
= new base::DictionaryValue();
485 result
->SetInteger(kResultCodeKey
, bytes_read
);
486 if (bytes_read
> 0) {
487 result
->Set(kDataKey
,
488 base::BinaryValue::CreateWithCopiedBuffer(io_buffer
->data(),
491 result
->Set(kDataKey
, new base::BinaryValue());
493 result
->SetString(kAddressKey
, address
);
494 result
->SetInteger(kPortKey
, port
);
497 AsyncWorkCompleted();
500 SocketSendToFunction::SocketSendToFunction()
501 : socket_id_(0), io_buffer_(NULL
), io_buffer_size_(0), port_(0) {
504 SocketSendToFunction::~SocketSendToFunction() {}
506 bool SocketSendToFunction::Prepare() {
507 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
508 base::BinaryValue
* data
= NULL
;
509 EXTENSION_FUNCTION_VALIDATE(args_
->GetBinary(1, &data
));
510 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(2, &hostname_
));
511 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(3, &port_
));
513 io_buffer_size_
= data
->GetSize();
514 io_buffer_
= new net::WrappedIOBuffer(data
->GetBuffer());
518 void SocketSendToFunction::AsyncWorkStart() {
519 Socket
* socket
= GetSocket(socket_id_
);
521 error_
= kSocketNotFoundError
;
522 SetResult(new base::FundamentalValue(-1));
523 AsyncWorkCompleted();
527 if (socket
->GetSocketType() == Socket::TYPE_UDP
) {
528 SocketPermission::CheckParam
param(
529 SocketPermissionRequest::UDP_SEND_TO
, hostname_
, port_
);
530 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
531 APIPermission::kSocket
, ¶m
)) {
532 error_
= kPermissionError
;
533 SetResult(new base::FundamentalValue(-1));
534 AsyncWorkCompleted();
539 StartDnsLookup(hostname_
);
542 void SocketSendToFunction::AfterDnsLookup(int lookup_result
) {
543 if (lookup_result
== net::OK
) {
546 SetResult(new base::FundamentalValue(lookup_result
));
547 AsyncWorkCompleted();
551 void SocketSendToFunction::StartSendTo() {
552 Socket
* socket
= GetSocket(socket_id_
);
554 error_
= kSocketNotFoundError
;
555 SetResult(new base::FundamentalValue(-1));
556 AsyncWorkCompleted();
560 socket
->SendTo(io_buffer_
,
564 base::Bind(&SocketSendToFunction::OnCompleted
, this));
567 void SocketSendToFunction::OnCompleted(int bytes_written
) {
568 base::DictionaryValue
* result
= new base::DictionaryValue();
569 result
->SetInteger(kBytesWrittenKey
, bytes_written
);
572 AsyncWorkCompleted();
575 SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {}
577 SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {}
579 bool SocketSetKeepAliveFunction::Prepare() {
580 params_
= core_api::socket::SetKeepAlive::Params::Create(*args_
);
581 EXTENSION_FUNCTION_VALIDATE(params_
.get());
585 void SocketSetKeepAliveFunction::Work() {
587 Socket
* socket
= GetSocket(params_
->socket_id
);
590 if (params_
->delay
.get())
591 delay
= *params_
->delay
;
592 result
= socket
->SetKeepAlive(params_
->enable
, delay
);
594 error_
= kSocketNotFoundError
;
596 SetResult(new base::FundamentalValue(result
));
599 SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
601 SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {}
603 bool SocketSetNoDelayFunction::Prepare() {
604 params_
= core_api::socket::SetNoDelay::Params::Create(*args_
);
605 EXTENSION_FUNCTION_VALIDATE(params_
.get());
609 void SocketSetNoDelayFunction::Work() {
611 Socket
* socket
= GetSocket(params_
->socket_id
);
613 result
= socket
->SetNoDelay(params_
->no_delay
);
615 error_
= kSocketNotFoundError
;
616 SetResult(new base::FundamentalValue(result
));
619 SocketGetInfoFunction::SocketGetInfoFunction() {}
621 SocketGetInfoFunction::~SocketGetInfoFunction() {}
623 bool SocketGetInfoFunction::Prepare() {
624 params_
= core_api::socket::GetInfo::Params::Create(*args_
);
625 EXTENSION_FUNCTION_VALIDATE(params_
.get());
629 void SocketGetInfoFunction::Work() {
630 Socket
* socket
= GetSocket(params_
->socket_id
);
632 error_
= kSocketNotFoundError
;
636 core_api::socket::SocketInfo info
;
637 // This represents what we know about the socket, and does not call through
639 if (socket
->GetSocketType() == Socket::TYPE_TCP
)
640 info
.socket_type
= extensions::core_api::socket::SOCKET_TYPE_TCP
;
642 info
.socket_type
= extensions::core_api::socket::SOCKET_TYPE_UDP
;
643 info
.connected
= socket
->IsConnected();
645 // Grab the peer address as known by the OS. This and the call below will
646 // always succeed while the socket is connected, even if the socket has
647 // been remotely closed by the peer; only reading the socket will reveal
648 // that it should be closed locally.
649 net::IPEndPoint peerAddress
;
650 if (socket
->GetPeerAddress(&peerAddress
)) {
651 info
.peer_address
.reset(new std::string(peerAddress
.ToStringWithoutPort()));
652 info
.peer_port
.reset(new int(peerAddress
.port()));
655 // Grab the local address as known by the OS.
656 net::IPEndPoint localAddress
;
657 if (socket
->GetLocalAddress(&localAddress
)) {
658 info
.local_address
.reset(
659 new std::string(localAddress
.ToStringWithoutPort()));
660 info
.local_port
.reset(new int(localAddress
.port()));
663 SetResult(info
.ToValue().release());
666 bool SocketGetNetworkListFunction::RunAsync() {
667 content::BrowserThread::PostTask(
668 content::BrowserThread::FILE,
670 base::Bind(&SocketGetNetworkListFunction::GetNetworkListOnFileThread
,
675 void SocketGetNetworkListFunction::GetNetworkListOnFileThread() {
676 net::NetworkInterfaceList interface_list
;
677 if (GetNetworkList(&interface_list
,
678 net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES
)) {
679 content::BrowserThread::PostTask(
680 content::BrowserThread::UI
,
682 base::Bind(&SocketGetNetworkListFunction::SendResponseOnUIThread
,
688 content::BrowserThread::PostTask(
689 content::BrowserThread::UI
,
691 base::Bind(&SocketGetNetworkListFunction::HandleGetNetworkListError
,
695 void SocketGetNetworkListFunction::HandleGetNetworkListError() {
696 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
697 error_
= kNetworkListError
;
701 void SocketGetNetworkListFunction::SendResponseOnUIThread(
702 const net::NetworkInterfaceList
& interface_list
) {
703 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
705 std::vector
<linked_ptr
<core_api::socket::NetworkInterface
> > create_arg
;
706 create_arg
.reserve(interface_list
.size());
707 for (net::NetworkInterfaceList::const_iterator i
= interface_list
.begin();
708 i
!= interface_list
.end();
710 linked_ptr
<core_api::socket::NetworkInterface
> info
=
711 make_linked_ptr(new core_api::socket::NetworkInterface
);
712 info
->name
= i
->name
;
713 info
->address
= net::IPAddressToString(i
->address
);
714 info
->prefix_length
= i
->network_prefix
;
715 create_arg
.push_back(info
);
718 results_
= core_api::socket::GetNetworkList::Results::Create(create_arg
);
722 SocketJoinGroupFunction::SocketJoinGroupFunction() {}
724 SocketJoinGroupFunction::~SocketJoinGroupFunction() {}
726 bool SocketJoinGroupFunction::Prepare() {
727 params_
= core_api::socket::JoinGroup::Params::Create(*args_
);
728 EXTENSION_FUNCTION_VALIDATE(params_
.get());
732 void SocketJoinGroupFunction::Work() {
734 Socket
* socket
= GetSocket(params_
->socket_id
);
736 error_
= kSocketNotFoundError
;
737 SetResult(new base::FundamentalValue(result
));
741 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
742 error_
= kMulticastSocketTypeError
;
743 SetResult(new base::FundamentalValue(result
));
747 SocketPermission::CheckParam
param(
748 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
752 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
753 APIPermission::kSocket
, ¶m
)) {
754 error_
= kPermissionError
;
755 SetResult(new base::FundamentalValue(result
));
759 result
= static_cast<UDPSocket
*>(socket
)->JoinGroup(params_
->address
);
761 error_
= net::ErrorToString(result
);
763 SetResult(new base::FundamentalValue(result
));
766 SocketLeaveGroupFunction::SocketLeaveGroupFunction() {}
768 SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {}
770 bool SocketLeaveGroupFunction::Prepare() {
771 params_
= core_api::socket::LeaveGroup::Params::Create(*args_
);
772 EXTENSION_FUNCTION_VALIDATE(params_
.get());
776 void SocketLeaveGroupFunction::Work() {
778 Socket
* socket
= GetSocket(params_
->socket_id
);
781 error_
= kSocketNotFoundError
;
782 SetResult(new base::FundamentalValue(result
));
786 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
787 error_
= kMulticastSocketTypeError
;
788 SetResult(new base::FundamentalValue(result
));
792 SocketPermission::CheckParam
param(
793 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
796 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
797 APIPermission::kSocket
, ¶m
)) {
798 error_
= kPermissionError
;
799 SetResult(new base::FundamentalValue(result
));
803 result
= static_cast<UDPSocket
*>(socket
)->LeaveGroup(params_
->address
);
805 error_
= net::ErrorToString(result
);
806 SetResult(new base::FundamentalValue(result
));
809 SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {}
811 SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {}
813 bool SocketSetMulticastTimeToLiveFunction::Prepare() {
814 params_
= core_api::socket::SetMulticastTimeToLive::Params::Create(*args_
);
815 EXTENSION_FUNCTION_VALIDATE(params_
.get());
818 void SocketSetMulticastTimeToLiveFunction::Work() {
820 Socket
* socket
= GetSocket(params_
->socket_id
);
822 error_
= kSocketNotFoundError
;
823 SetResult(new base::FundamentalValue(result
));
827 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
828 error_
= kMulticastSocketTypeError
;
829 SetResult(new base::FundamentalValue(result
));
834 static_cast<UDPSocket
*>(socket
)->SetMulticastTimeToLive(params_
->ttl
);
836 error_
= net::ErrorToString(result
);
837 SetResult(new base::FundamentalValue(result
));
840 SocketSetMulticastLoopbackModeFunction::
841 SocketSetMulticastLoopbackModeFunction() {}
843 SocketSetMulticastLoopbackModeFunction::
844 ~SocketSetMulticastLoopbackModeFunction() {}
846 bool SocketSetMulticastLoopbackModeFunction::Prepare() {
847 params_
= core_api::socket::SetMulticastLoopbackMode::Params::Create(*args_
);
848 EXTENSION_FUNCTION_VALIDATE(params_
.get());
852 void SocketSetMulticastLoopbackModeFunction::Work() {
854 Socket
* socket
= GetSocket(params_
->socket_id
);
856 error_
= kSocketNotFoundError
;
857 SetResult(new base::FundamentalValue(result
));
861 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
862 error_
= kMulticastSocketTypeError
;
863 SetResult(new base::FundamentalValue(result
));
867 result
= static_cast<UDPSocket
*>(socket
)
868 ->SetMulticastLoopbackMode(params_
->enabled
);
870 error_
= net::ErrorToString(result
);
871 SetResult(new base::FundamentalValue(result
));
874 SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {}
876 SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {}
878 bool SocketGetJoinedGroupsFunction::Prepare() {
879 params_
= core_api::socket::GetJoinedGroups::Params::Create(*args_
);
880 EXTENSION_FUNCTION_VALIDATE(params_
.get());
884 void SocketGetJoinedGroupsFunction::Work() {
886 Socket
* socket
= GetSocket(params_
->socket_id
);
888 error_
= kSocketNotFoundError
;
889 SetResult(new base::FundamentalValue(result
));
893 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
894 error_
= kMulticastSocketTypeError
;
895 SetResult(new base::FundamentalValue(result
));
899 SocketPermission::CheckParam
param(
900 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
903 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
904 APIPermission::kSocket
, ¶m
)) {
905 error_
= kPermissionError
;
906 SetResult(new base::FundamentalValue(result
));
910 base::ListValue
* values
= new base::ListValue();
911 values
->AppendStrings((std::vector
<std::string
>&)static_cast<UDPSocket
*>(
912 socket
)->GetJoinedGroups());
916 SocketSecureFunction::SocketSecureFunction() {
919 SocketSecureFunction::~SocketSecureFunction() {
922 bool SocketSecureFunction::Prepare() {
923 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
924 params_
= core_api::socket::Secure::Params::Create(*args_
);
925 EXTENSION_FUNCTION_VALIDATE(params_
.get());
926 url_request_getter_
= browser_context()->GetRequestContext();
930 // Override the regular implementation, which would call AsyncWorkCompleted
931 // immediately after Work().
932 void SocketSecureFunction::AsyncWorkStart() {
933 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
935 Socket
* socket
= GetSocket(params_
->socket_id
);
937 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
938 error_
= kSocketNotFoundError
;
939 AsyncWorkCompleted();
943 // Make sure that the socket is a TCP client socket.
944 if (socket
->GetSocketType() != Socket::TYPE_TCP
||
945 static_cast<TCPSocket
*>(socket
)->ClientStream() == NULL
) {
946 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
947 error_
= kSecureSocketTypeError
;
948 AsyncWorkCompleted();
952 if (!socket
->IsConnected()) {
953 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
954 error_
= kSocketNotConnectedError
;
955 AsyncWorkCompleted();
959 net::URLRequestContext
* url_request_context
=
960 url_request_getter_
->GetURLRequestContext();
962 TLSSocket::UpgradeSocketToTLS(
964 url_request_context
->ssl_config_service(),
965 url_request_context
->cert_verifier(),
966 url_request_context
->transport_security_state(),
968 params_
->options
.get(),
969 base::Bind(&SocketSecureFunction::TlsConnectDone
, this));
972 void SocketSecureFunction::TlsConnectDone(scoped_ptr
<TLSSocket
> socket
,
974 // if an error occurred, socket MUST be NULL.
975 DCHECK(result
== net::OK
|| socket
== NULL
);
977 if (socket
&& result
== net::OK
) {
978 ReplaceSocket(params_
->socket_id
, socket
.release());
980 RemoveSocket(params_
->socket_id
);
981 error_
= net::ErrorToString(result
);
984 results_
= core_api::socket::Secure::Results::Create(result
);
985 AsyncWorkCompleted();
988 } // namespace extensions