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_util.h"
27 #include "net/log/net_log.h"
28 #include "net/url_request/url_request_context.h"
29 #include "net/url_request/url_request_context_getter.h"
31 #if defined(OS_CHROMEOS)
32 #include "content/public/browser/browser_thread.h"
35 namespace extensions
{
37 using content::BrowserThread
;
38 using content::SocketPermissionRequest
;
40 const char kAddressKey
[] = "address";
41 const char kPortKey
[] = "port";
42 const char kBytesWrittenKey
[] = "bytesWritten";
43 const char kDataKey
[] = "data";
44 const char kResultCodeKey
[] = "resultCode";
45 const char kSocketIdKey
[] = "socketId";
47 const char kSocketNotFoundError
[] = "Socket not found";
48 const char kDnsLookupFailedError
[] = "DNS resolution failed";
49 const char kPermissionError
[] = "App does not have permission";
50 const char kNetworkListError
[] = "Network lookup failed or unsupported";
51 const char kTCPSocketBindError
[] =
52 "TCP socket does not support bind. For TCP server please use listen.";
53 const char kMulticastSocketTypeError
[] = "Only UDP socket supports multicast.";
54 const char kSecureSocketTypeError
[] = "Only TCP sockets are supported for TLS.";
55 const char kSocketNotConnectedError
[] = "Socket not connected";
56 const char kWildcardAddress
[] = "*";
57 const uint16 kWildcardPort
= 0;
59 #if defined(OS_CHROMEOS)
60 const char kFirewallFailure
[] = "Failed to open firewall port";
63 SocketAsyncApiFunction::SocketAsyncApiFunction() {}
65 SocketAsyncApiFunction::~SocketAsyncApiFunction() {}
67 bool SocketAsyncApiFunction::PrePrepare() {
68 manager_
= CreateSocketResourceManager();
69 return manager_
->SetBrowserContext(browser_context());
72 bool SocketAsyncApiFunction::Respond() { return error_
.empty(); }
74 scoped_ptr
<SocketResourceManagerInterface
>
75 SocketAsyncApiFunction::CreateSocketResourceManager() {
76 return scoped_ptr
<SocketResourceManagerInterface
>(
77 new SocketResourceManager
<Socket
>()).Pass();
80 int SocketAsyncApiFunction::AddSocket(Socket
* socket
) {
81 return manager_
->Add(socket
);
84 Socket
* SocketAsyncApiFunction::GetSocket(int api_resource_id
) {
85 return manager_
->Get(extension_
->id(), api_resource_id
);
88 void SocketAsyncApiFunction::ReplaceSocket(int api_resource_id
,
90 manager_
->Replace(extension_
->id(), api_resource_id
, socket
);
93 base::hash_set
<int>* SocketAsyncApiFunction::GetSocketIds() {
94 return manager_
->GetResourceIds(extension_
->id());
97 void SocketAsyncApiFunction::RemoveSocket(int api_resource_id
) {
98 manager_
->Remove(extension_
->id(), api_resource_id
);
101 void SocketAsyncApiFunction::OpenFirewallHole(const std::string
& address
,
104 #if defined(OS_CHROMEOS)
105 if (!net::IsLocalhost(address
)) {
106 net::IPEndPoint local_address
;
107 if (!socket
->GetLocalAddress(&local_address
)) {
108 NOTREACHED() << "Cannot get address of recently bound socket.";
109 error_
= kFirewallFailure
;
110 SetResult(new base::FundamentalValue(-1));
111 AsyncWorkCompleted();
115 AppFirewallHole::PortType type
= socket
->GetSocketType() == Socket::TYPE_TCP
116 ? AppFirewallHole::PortType::TCP
117 : AppFirewallHole::PortType::UDP
;
119 BrowserThread::PostTask(
120 BrowserThread::UI
, FROM_HERE
,
121 base::Bind(&SocketAsyncApiFunction::OpenFirewallHoleOnUIThread
, this,
122 type
, local_address
.port(), socket_id
));
126 AsyncWorkCompleted();
129 #if defined(OS_CHROMEOS)
131 void SocketAsyncApiFunction::OpenFirewallHoleOnUIThread(
132 AppFirewallHole::PortType type
,
135 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
136 AppFirewallHoleManager
* manager
=
137 AppFirewallHoleManager::Get(browser_context());
138 scoped_ptr
<AppFirewallHole
, BrowserThread::DeleteOnUIThread
> hole(
139 manager
->Open(type
, port
, extension_id()).release());
140 BrowserThread::PostTask(
141 BrowserThread::IO
, FROM_HERE
,
142 base::Bind(&SocketAsyncApiFunction::OnFirewallHoleOpened
, this, socket_id
,
143 base::Passed(&hole
)));
146 void SocketAsyncApiFunction::OnFirewallHoleOpened(
148 scoped_ptr
<AppFirewallHole
, BrowserThread::DeleteOnUIThread
> hole
) {
149 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
151 error_
= kFirewallFailure
;
152 SetResult(new base::FundamentalValue(-1));
153 AsyncWorkCompleted();
157 Socket
* socket
= GetSocket(socket_id
);
159 error_
= kSocketNotFoundError
;
160 SetResult(new base::FundamentalValue(-1));
161 AsyncWorkCompleted();
165 socket
->set_firewall_hole(hole
.Pass());
166 AsyncWorkCompleted();
169 #endif // OS_CHROMEOS
171 SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction()
172 : resource_context_(NULL
) {
175 SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() {
178 bool SocketExtensionWithDnsLookupFunction::PrePrepare() {
179 if (!SocketAsyncApiFunction::PrePrepare())
181 resource_context_
= browser_context()->GetResourceContext();
182 return resource_context_
!= NULL
;
185 void SocketExtensionWithDnsLookupFunction::StartDnsLookup(
186 const net::HostPortPair
& host_port_pair
) {
187 net::HostResolver
* host_resolver
=
188 HostResolverWrapper::GetInstance()->GetHostResolver(resource_context_
);
189 DCHECK(host_resolver
);
191 // RequestHandle is not needed because we never need to cancel requests.
192 net::HostResolver::RequestHandle request_handle
;
194 net::HostResolver::RequestInfo
request_info(host_port_pair
);
195 int resolve_result
= host_resolver
->Resolve(
196 request_info
, net::DEFAULT_PRIORITY
, &addresses_
,
197 base::Bind(&SocketExtensionWithDnsLookupFunction::OnDnsLookup
, this),
198 &request_handle
, net::BoundNetLog());
200 if (resolve_result
!= net::ERR_IO_PENDING
)
201 OnDnsLookup(resolve_result
);
204 void SocketExtensionWithDnsLookupFunction::OnDnsLookup(int resolve_result
) {
205 if (resolve_result
== net::OK
) {
206 DCHECK(!addresses_
.empty());
208 error_
= kDnsLookupFailedError
;
210 AfterDnsLookup(resolve_result
);
213 SocketCreateFunction::SocketCreateFunction()
214 : socket_type_(kSocketTypeInvalid
) {}
216 SocketCreateFunction::~SocketCreateFunction() {}
218 bool SocketCreateFunction::Prepare() {
219 params_
= core_api::socket::Create::Params::Create(*args_
);
220 EXTENSION_FUNCTION_VALIDATE(params_
.get());
222 switch (params_
->type
) {
223 case extensions::core_api::socket::SOCKET_TYPE_TCP
:
224 socket_type_
= kSocketTypeTCP
;
226 case extensions::core_api::socket::SOCKET_TYPE_UDP
:
227 socket_type_
= kSocketTypeUDP
;
229 case extensions::core_api::socket::SOCKET_TYPE_NONE
:
237 void SocketCreateFunction::Work() {
238 Socket
* socket
= NULL
;
239 if (socket_type_
== kSocketTypeTCP
) {
240 socket
= new TCPSocket(extension_
->id());
241 } else if (socket_type_
== kSocketTypeUDP
) {
242 socket
= new UDPSocket(extension_
->id());
246 base::DictionaryValue
* result
= new base::DictionaryValue();
247 result
->SetInteger(kSocketIdKey
, AddSocket(socket
));
251 bool SocketDestroyFunction::Prepare() {
252 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
256 void SocketDestroyFunction::Work() { RemoveSocket(socket_id_
); }
258 SocketConnectFunction::SocketConnectFunction()
259 : socket_id_(0), hostname_(), port_(0) {
262 SocketConnectFunction::~SocketConnectFunction() {}
264 bool SocketConnectFunction::Prepare() {
265 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
266 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(1, &hostname_
));
268 EXTENSION_FUNCTION_VALIDATE(
269 args_
->GetInteger(2, &port
) && port
>= 0 && port
<= 65535);
270 port_
= static_cast<uint16
>(port
);
274 void SocketConnectFunction::AsyncWorkStart() {
275 Socket
* socket
= GetSocket(socket_id_
);
277 error_
= kSocketNotFoundError
;
278 SetResult(new base::FundamentalValue(-1));
279 AsyncWorkCompleted();
283 socket
->set_hostname(hostname_
);
285 SocketPermissionRequest::OperationType operation_type
;
286 switch (socket
->GetSocketType()) {
287 case Socket::TYPE_TCP
:
288 operation_type
= SocketPermissionRequest::TCP_CONNECT
;
290 case Socket::TYPE_UDP
:
291 operation_type
= SocketPermissionRequest::UDP_SEND_TO
;
294 NOTREACHED() << "Unknown socket type.";
295 operation_type
= SocketPermissionRequest::NONE
;
299 SocketPermission::CheckParam
param(operation_type
, hostname_
, port_
);
300 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
301 APIPermission::kSocket
, ¶m
)) {
302 error_
= kPermissionError
;
303 SetResult(new base::FundamentalValue(-1));
304 AsyncWorkCompleted();
308 StartDnsLookup(net::HostPortPair(hostname_
, port_
));
311 void SocketConnectFunction::AfterDnsLookup(int lookup_result
) {
312 if (lookup_result
== net::OK
) {
315 SetResult(new base::FundamentalValue(lookup_result
));
316 AsyncWorkCompleted();
320 void SocketConnectFunction::StartConnect() {
321 Socket
* socket
= GetSocket(socket_id_
);
323 error_
= kSocketNotFoundError
;
324 SetResult(new base::FundamentalValue(-1));
325 AsyncWorkCompleted();
329 socket
->Connect(addresses_
,
330 base::Bind(&SocketConnectFunction::OnConnect
, this));
333 void SocketConnectFunction::OnConnect(int result
) {
334 SetResult(new base::FundamentalValue(result
));
335 AsyncWorkCompleted();
338 bool SocketDisconnectFunction::Prepare() {
339 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
343 void SocketDisconnectFunction::Work() {
344 Socket
* socket
= GetSocket(socket_id_
);
346 socket
->Disconnect();
348 error_
= kSocketNotFoundError
;
349 SetResult(base::Value::CreateNullValue());
352 bool SocketBindFunction::Prepare() {
353 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
354 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(1, &address_
));
356 EXTENSION_FUNCTION_VALIDATE(
357 args_
->GetInteger(2, &port
) && port
>= 0 && port
<= 65535);
358 port_
= static_cast<uint16
>(port
);
362 void SocketBindFunction::AsyncWorkStart() {
363 Socket
* socket
= GetSocket(socket_id_
);
365 error_
= kSocketNotFoundError
;
366 SetResult(new base::FundamentalValue(-1));
367 AsyncWorkCompleted();
371 if (socket
->GetSocketType() == Socket::TYPE_TCP
) {
372 error_
= kTCPSocketBindError
;
373 SetResult(new base::FundamentalValue(-1));
374 AsyncWorkCompleted();
378 CHECK(socket
->GetSocketType() == Socket::TYPE_UDP
);
379 SocketPermission::CheckParam
param(SocketPermissionRequest::UDP_BIND
,
381 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
382 APIPermission::kSocket
, ¶m
)) {
383 error_
= kPermissionError
;
384 SetResult(new base::FundamentalValue(-1));
385 AsyncWorkCompleted();
389 int result
= socket
->Bind(address_
, port_
);
390 SetResult(new base::FundamentalValue(result
));
391 if (result
!= net::OK
) {
392 AsyncWorkCompleted();
396 OpenFirewallHole(address_
, socket_id_
, socket
);
399 SocketListenFunction::SocketListenFunction() {}
401 SocketListenFunction::~SocketListenFunction() {}
403 bool SocketListenFunction::Prepare() {
404 params_
= core_api::socket::Listen::Params::Create(*args_
);
405 EXTENSION_FUNCTION_VALIDATE(params_
.get());
409 void SocketListenFunction::AsyncWorkStart() {
410 Socket
* socket
= GetSocket(params_
->socket_id
);
412 error_
= kSocketNotFoundError
;
413 SetResult(new base::FundamentalValue(-1));
414 AsyncWorkCompleted();
418 SocketPermission::CheckParam
param(SocketPermissionRequest::TCP_LISTEN
,
419 params_
->address
, params_
->port
);
420 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
421 APIPermission::kSocket
, ¶m
)) {
422 error_
= kPermissionError
;
423 SetResult(new base::FundamentalValue(-1));
424 AsyncWorkCompleted();
428 int result
= socket
->Listen(
429 params_
->address
, params_
->port
,
430 params_
->backlog
.get() ? *params_
->backlog
.get() : 5, &error_
);
431 SetResult(new base::FundamentalValue(result
));
432 if (result
!= net::OK
) {
433 AsyncWorkCompleted();
437 OpenFirewallHole(params_
->address
, params_
->socket_id
, socket
);
440 SocketAcceptFunction::SocketAcceptFunction() {}
442 SocketAcceptFunction::~SocketAcceptFunction() {}
444 bool SocketAcceptFunction::Prepare() {
445 params_
= core_api::socket::Accept::Params::Create(*args_
);
446 EXTENSION_FUNCTION_VALIDATE(params_
.get());
450 void SocketAcceptFunction::AsyncWorkStart() {
451 Socket
* socket
= GetSocket(params_
->socket_id
);
453 socket
->Accept(base::Bind(&SocketAcceptFunction::OnAccept
, this));
455 error_
= kSocketNotFoundError
;
460 void SocketAcceptFunction::OnAccept(int result_code
,
461 net::TCPClientSocket
* socket
) {
462 base::DictionaryValue
* result
= new base::DictionaryValue();
463 result
->SetInteger(kResultCodeKey
, result_code
);
465 Socket
* client_socket
= new TCPSocket(socket
, extension_id(), true);
466 result
->SetInteger(kSocketIdKey
, AddSocket(client_socket
));
470 AsyncWorkCompleted();
473 SocketReadFunction::SocketReadFunction() {}
475 SocketReadFunction::~SocketReadFunction() {}
477 bool SocketReadFunction::Prepare() {
478 params_
= core_api::socket::Read::Params::Create(*args_
);
479 EXTENSION_FUNCTION_VALIDATE(params_
.get());
483 void SocketReadFunction::AsyncWorkStart() {
484 Socket
* socket
= GetSocket(params_
->socket_id
);
486 error_
= kSocketNotFoundError
;
487 OnCompleted(-1, NULL
);
491 socket
->Read(params_
->buffer_size
.get() ? *params_
->buffer_size
.get() : 4096,
492 base::Bind(&SocketReadFunction::OnCompleted
, this));
495 void SocketReadFunction::OnCompleted(int bytes_read
,
496 scoped_refptr
<net::IOBuffer
> io_buffer
) {
497 base::DictionaryValue
* result
= new base::DictionaryValue();
498 result
->SetInteger(kResultCodeKey
, bytes_read
);
499 if (bytes_read
> 0) {
500 result
->Set(kDataKey
,
501 base::BinaryValue::CreateWithCopiedBuffer(io_buffer
->data(),
504 result
->Set(kDataKey
, new base::BinaryValue());
508 AsyncWorkCompleted();
511 SocketWriteFunction::SocketWriteFunction()
512 : socket_id_(0), io_buffer_(NULL
), io_buffer_size_(0) {}
514 SocketWriteFunction::~SocketWriteFunction() {}
516 bool SocketWriteFunction::Prepare() {
517 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
518 base::BinaryValue
* data
= NULL
;
519 EXTENSION_FUNCTION_VALIDATE(args_
->GetBinary(1, &data
));
521 io_buffer_size_
= data
->GetSize();
522 io_buffer_
= new net::WrappedIOBuffer(data
->GetBuffer());
526 void SocketWriteFunction::AsyncWorkStart() {
527 Socket
* socket
= GetSocket(socket_id_
);
530 error_
= kSocketNotFoundError
;
535 socket
->Write(io_buffer_
,
537 base::Bind(&SocketWriteFunction::OnCompleted
, this));
540 void SocketWriteFunction::OnCompleted(int bytes_written
) {
541 base::DictionaryValue
* result
= new base::DictionaryValue();
542 result
->SetInteger(kBytesWrittenKey
, bytes_written
);
545 AsyncWorkCompleted();
548 SocketRecvFromFunction::SocketRecvFromFunction() {}
550 SocketRecvFromFunction::~SocketRecvFromFunction() {}
552 bool SocketRecvFromFunction::Prepare() {
553 params_
= core_api::socket::RecvFrom::Params::Create(*args_
);
554 EXTENSION_FUNCTION_VALIDATE(params_
.get());
558 void SocketRecvFromFunction::AsyncWorkStart() {
559 Socket
* socket
= GetSocket(params_
->socket_id
);
560 if (!socket
|| socket
->GetSocketType() != Socket::TYPE_UDP
) {
561 error_
= kSocketNotFoundError
;
562 OnCompleted(-1, NULL
, std::string(), 0);
566 socket
->RecvFrom(params_
->buffer_size
.get() ? *params_
->buffer_size
: 4096,
567 base::Bind(&SocketRecvFromFunction::OnCompleted
, this));
570 void SocketRecvFromFunction::OnCompleted(int bytes_read
,
571 scoped_refptr
<net::IOBuffer
> io_buffer
,
572 const std::string
& address
,
574 base::DictionaryValue
* result
= new base::DictionaryValue();
575 result
->SetInteger(kResultCodeKey
, bytes_read
);
576 if (bytes_read
> 0) {
577 result
->Set(kDataKey
,
578 base::BinaryValue::CreateWithCopiedBuffer(io_buffer
->data(),
581 result
->Set(kDataKey
, new base::BinaryValue());
583 result
->SetString(kAddressKey
, address
);
584 result
->SetInteger(kPortKey
, port
);
587 AsyncWorkCompleted();
590 SocketSendToFunction::SocketSendToFunction()
591 : socket_id_(0), io_buffer_(NULL
), io_buffer_size_(0), port_(0) {
594 SocketSendToFunction::~SocketSendToFunction() {}
596 bool SocketSendToFunction::Prepare() {
597 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
598 base::BinaryValue
* data
= NULL
;
599 EXTENSION_FUNCTION_VALIDATE(args_
->GetBinary(1, &data
));
600 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(2, &hostname_
));
602 EXTENSION_FUNCTION_VALIDATE(
603 args_
->GetInteger(3, &port
) && port
>= 0 && port
<= 65535);
604 port_
= static_cast<uint16
>(port
);
606 io_buffer_size_
= data
->GetSize();
607 io_buffer_
= new net::WrappedIOBuffer(data
->GetBuffer());
611 void SocketSendToFunction::AsyncWorkStart() {
612 Socket
* socket
= GetSocket(socket_id_
);
614 error_
= kSocketNotFoundError
;
615 SetResult(new base::FundamentalValue(-1));
616 AsyncWorkCompleted();
620 if (socket
->GetSocketType() == Socket::TYPE_UDP
) {
621 SocketPermission::CheckParam
param(
622 SocketPermissionRequest::UDP_SEND_TO
, hostname_
, port_
);
623 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
624 APIPermission::kSocket
, ¶m
)) {
625 error_
= kPermissionError
;
626 SetResult(new base::FundamentalValue(-1));
627 AsyncWorkCompleted();
632 StartDnsLookup(net::HostPortPair(hostname_
, port_
));
635 void SocketSendToFunction::AfterDnsLookup(int lookup_result
) {
636 if (lookup_result
== net::OK
) {
639 SetResult(new base::FundamentalValue(lookup_result
));
640 AsyncWorkCompleted();
644 void SocketSendToFunction::StartSendTo() {
645 Socket
* socket
= GetSocket(socket_id_
);
647 error_
= kSocketNotFoundError
;
648 SetResult(new base::FundamentalValue(-1));
649 AsyncWorkCompleted();
653 socket
->SendTo(io_buffer_
, io_buffer_size_
, addresses_
.front(),
654 base::Bind(&SocketSendToFunction::OnCompleted
, this));
657 void SocketSendToFunction::OnCompleted(int bytes_written
) {
658 base::DictionaryValue
* result
= new base::DictionaryValue();
659 result
->SetInteger(kBytesWrittenKey
, bytes_written
);
662 AsyncWorkCompleted();
665 SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {}
667 SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {}
669 bool SocketSetKeepAliveFunction::Prepare() {
670 params_
= core_api::socket::SetKeepAlive::Params::Create(*args_
);
671 EXTENSION_FUNCTION_VALIDATE(params_
.get());
675 void SocketSetKeepAliveFunction::Work() {
677 Socket
* socket
= GetSocket(params_
->socket_id
);
680 if (params_
->delay
.get())
681 delay
= *params_
->delay
;
682 result
= socket
->SetKeepAlive(params_
->enable
, delay
);
684 error_
= kSocketNotFoundError
;
686 SetResult(new base::FundamentalValue(result
));
689 SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
691 SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {}
693 bool SocketSetNoDelayFunction::Prepare() {
694 params_
= core_api::socket::SetNoDelay::Params::Create(*args_
);
695 EXTENSION_FUNCTION_VALIDATE(params_
.get());
699 void SocketSetNoDelayFunction::Work() {
701 Socket
* socket
= GetSocket(params_
->socket_id
);
703 result
= socket
->SetNoDelay(params_
->no_delay
);
705 error_
= kSocketNotFoundError
;
706 SetResult(new base::FundamentalValue(result
));
709 SocketGetInfoFunction::SocketGetInfoFunction() {}
711 SocketGetInfoFunction::~SocketGetInfoFunction() {}
713 bool SocketGetInfoFunction::Prepare() {
714 params_
= core_api::socket::GetInfo::Params::Create(*args_
);
715 EXTENSION_FUNCTION_VALIDATE(params_
.get());
719 void SocketGetInfoFunction::Work() {
720 Socket
* socket
= GetSocket(params_
->socket_id
);
722 error_
= kSocketNotFoundError
;
726 core_api::socket::SocketInfo info
;
727 // This represents what we know about the socket, and does not call through
729 if (socket
->GetSocketType() == Socket::TYPE_TCP
)
730 info
.socket_type
= extensions::core_api::socket::SOCKET_TYPE_TCP
;
732 info
.socket_type
= extensions::core_api::socket::SOCKET_TYPE_UDP
;
733 info
.connected
= socket
->IsConnected();
735 // Grab the peer address as known by the OS. This and the call below will
736 // always succeed while the socket is connected, even if the socket has
737 // been remotely closed by the peer; only reading the socket will reveal
738 // that it should be closed locally.
739 net::IPEndPoint peerAddress
;
740 if (socket
->GetPeerAddress(&peerAddress
)) {
741 info
.peer_address
.reset(new std::string(peerAddress
.ToStringWithoutPort()));
742 info
.peer_port
.reset(new int(peerAddress
.port()));
745 // Grab the local address as known by the OS.
746 net::IPEndPoint localAddress
;
747 if (socket
->GetLocalAddress(&localAddress
)) {
748 info
.local_address
.reset(
749 new std::string(localAddress
.ToStringWithoutPort()));
750 info
.local_port
.reset(new int(localAddress
.port()));
753 SetResult(info
.ToValue().release());
756 bool SocketGetNetworkListFunction::RunAsync() {
757 BrowserThread::PostTask(
758 BrowserThread::FILE, FROM_HERE
,
759 base::Bind(&SocketGetNetworkListFunction::GetNetworkListOnFileThread
,
764 void SocketGetNetworkListFunction::GetNetworkListOnFileThread() {
765 net::NetworkInterfaceList interface_list
;
766 if (GetNetworkList(&interface_list
,
767 net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES
)) {
768 BrowserThread::PostTask(
769 BrowserThread::UI
, FROM_HERE
,
770 base::Bind(&SocketGetNetworkListFunction::SendResponseOnUIThread
, this,
775 BrowserThread::PostTask(
776 BrowserThread::UI
, FROM_HERE
,
777 base::Bind(&SocketGetNetworkListFunction::HandleGetNetworkListError
,
781 void SocketGetNetworkListFunction::HandleGetNetworkListError() {
782 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
783 error_
= kNetworkListError
;
787 void SocketGetNetworkListFunction::SendResponseOnUIThread(
788 const net::NetworkInterfaceList
& interface_list
) {
789 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
791 std::vector
<linked_ptr
<core_api::socket::NetworkInterface
> > create_arg
;
792 create_arg
.reserve(interface_list
.size());
793 for (net::NetworkInterfaceList::const_iterator i
= interface_list
.begin();
794 i
!= interface_list
.end();
796 linked_ptr
<core_api::socket::NetworkInterface
> info
=
797 make_linked_ptr(new core_api::socket::NetworkInterface
);
798 info
->name
= i
->name
;
799 info
->address
= net::IPAddressToString(i
->address
);
800 info
->prefix_length
= i
->prefix_length
;
801 create_arg
.push_back(info
);
804 results_
= core_api::socket::GetNetworkList::Results::Create(create_arg
);
808 SocketJoinGroupFunction::SocketJoinGroupFunction() {}
810 SocketJoinGroupFunction::~SocketJoinGroupFunction() {}
812 bool SocketJoinGroupFunction::Prepare() {
813 params_
= core_api::socket::JoinGroup::Params::Create(*args_
);
814 EXTENSION_FUNCTION_VALIDATE(params_
.get());
818 void SocketJoinGroupFunction::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
));
833 SocketPermission::CheckParam
param(
834 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
838 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
839 APIPermission::kSocket
, ¶m
)) {
840 error_
= kPermissionError
;
841 SetResult(new base::FundamentalValue(result
));
845 result
= static_cast<UDPSocket
*>(socket
)->JoinGroup(params_
->address
);
847 error_
= net::ErrorToString(result
);
849 SetResult(new base::FundamentalValue(result
));
852 SocketLeaveGroupFunction::SocketLeaveGroupFunction() {}
854 SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {}
856 bool SocketLeaveGroupFunction::Prepare() {
857 params_
= core_api::socket::LeaveGroup::Params::Create(*args_
);
858 EXTENSION_FUNCTION_VALIDATE(params_
.get());
862 void SocketLeaveGroupFunction::Work() {
864 Socket
* socket
= GetSocket(params_
->socket_id
);
867 error_
= kSocketNotFoundError
;
868 SetResult(new base::FundamentalValue(result
));
872 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
873 error_
= kMulticastSocketTypeError
;
874 SetResult(new base::FundamentalValue(result
));
878 SocketPermission::CheckParam
param(
879 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
882 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
883 APIPermission::kSocket
, ¶m
)) {
884 error_
= kPermissionError
;
885 SetResult(new base::FundamentalValue(result
));
889 result
= static_cast<UDPSocket
*>(socket
)->LeaveGroup(params_
->address
);
891 error_
= net::ErrorToString(result
);
892 SetResult(new base::FundamentalValue(result
));
895 SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {}
897 SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {}
899 bool SocketSetMulticastTimeToLiveFunction::Prepare() {
900 params_
= core_api::socket::SetMulticastTimeToLive::Params::Create(*args_
);
901 EXTENSION_FUNCTION_VALIDATE(params_
.get());
904 void SocketSetMulticastTimeToLiveFunction::Work() {
906 Socket
* socket
= GetSocket(params_
->socket_id
);
908 error_
= kSocketNotFoundError
;
909 SetResult(new base::FundamentalValue(result
));
913 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
914 error_
= kMulticastSocketTypeError
;
915 SetResult(new base::FundamentalValue(result
));
920 static_cast<UDPSocket
*>(socket
)->SetMulticastTimeToLive(params_
->ttl
);
922 error_
= net::ErrorToString(result
);
923 SetResult(new base::FundamentalValue(result
));
926 SocketSetMulticastLoopbackModeFunction::
927 SocketSetMulticastLoopbackModeFunction() {}
929 SocketSetMulticastLoopbackModeFunction::
930 ~SocketSetMulticastLoopbackModeFunction() {}
932 bool SocketSetMulticastLoopbackModeFunction::Prepare() {
933 params_
= core_api::socket::SetMulticastLoopbackMode::Params::Create(*args_
);
934 EXTENSION_FUNCTION_VALIDATE(params_
.get());
938 void SocketSetMulticastLoopbackModeFunction::Work() {
940 Socket
* socket
= GetSocket(params_
->socket_id
);
942 error_
= kSocketNotFoundError
;
943 SetResult(new base::FundamentalValue(result
));
947 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
948 error_
= kMulticastSocketTypeError
;
949 SetResult(new base::FundamentalValue(result
));
953 result
= static_cast<UDPSocket
*>(socket
)
954 ->SetMulticastLoopbackMode(params_
->enabled
);
956 error_
= net::ErrorToString(result
);
957 SetResult(new base::FundamentalValue(result
));
960 SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {}
962 SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {}
964 bool SocketGetJoinedGroupsFunction::Prepare() {
965 params_
= core_api::socket::GetJoinedGroups::Params::Create(*args_
);
966 EXTENSION_FUNCTION_VALIDATE(params_
.get());
970 void SocketGetJoinedGroupsFunction::Work() {
972 Socket
* socket
= GetSocket(params_
->socket_id
);
974 error_
= kSocketNotFoundError
;
975 SetResult(new base::FundamentalValue(result
));
979 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
980 error_
= kMulticastSocketTypeError
;
981 SetResult(new base::FundamentalValue(result
));
985 SocketPermission::CheckParam
param(
986 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
989 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
990 APIPermission::kSocket
, ¶m
)) {
991 error_
= kPermissionError
;
992 SetResult(new base::FundamentalValue(result
));
996 base::ListValue
* values
= new base::ListValue();
997 values
->AppendStrings((std::vector
<std::string
>&)static_cast<UDPSocket
*>(
998 socket
)->GetJoinedGroups());
1002 SocketSecureFunction::SocketSecureFunction() {
1005 SocketSecureFunction::~SocketSecureFunction() {
1008 bool SocketSecureFunction::Prepare() {
1009 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
1010 params_
= core_api::socket::Secure::Params::Create(*args_
);
1011 EXTENSION_FUNCTION_VALIDATE(params_
.get());
1012 url_request_getter_
= browser_context()->GetRequestContext();
1016 // Override the regular implementation, which would call AsyncWorkCompleted
1017 // immediately after Work().
1018 void SocketSecureFunction::AsyncWorkStart() {
1019 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
1021 Socket
* socket
= GetSocket(params_
->socket_id
);
1023 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
1024 error_
= kSocketNotFoundError
;
1025 AsyncWorkCompleted();
1029 // Make sure that the socket is a TCP client socket.
1030 if (socket
->GetSocketType() != Socket::TYPE_TCP
||
1031 static_cast<TCPSocket
*>(socket
)->ClientStream() == NULL
) {
1032 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
1033 error_
= kSecureSocketTypeError
;
1034 AsyncWorkCompleted();
1038 if (!socket
->IsConnected()) {
1039 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
1040 error_
= kSocketNotConnectedError
;
1041 AsyncWorkCompleted();
1045 net::URLRequestContext
* url_request_context
=
1046 url_request_getter_
->GetURLRequestContext();
1048 TLSSocket::UpgradeSocketToTLS(
1050 url_request_context
->ssl_config_service(),
1051 url_request_context
->cert_verifier(),
1052 url_request_context
->transport_security_state(),
1054 params_
->options
.get(),
1055 base::Bind(&SocketSecureFunction::TlsConnectDone
, this));
1058 void SocketSecureFunction::TlsConnectDone(scoped_ptr
<TLSSocket
> socket
,
1060 // if an error occurred, socket MUST be NULL.
1061 DCHECK(result
== net::OK
|| socket
== NULL
);
1063 if (socket
&& result
== net::OK
) {
1064 ReplaceSocket(params_
->socket_id
, socket
.release());
1066 RemoveSocket(params_
->socket_id
);
1067 error_
= net::ErrorToString(result
);
1070 results_
= core_api::socket::Secure::Results::Create(result
);
1071 AsyncWorkCompleted();
1074 } // namespace extensions