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
),
173 request_handle_(new net::HostResolver::RequestHandle
),
174 addresses_(new net::AddressList
) {}
176 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 std::string
& hostname
) {
187 net::HostResolver
* host_resolver
=
188 HostResolverWrapper::GetInstance()->GetHostResolver(resource_context_
);
189 DCHECK(host_resolver
);
191 // Yes, we are passing zero as the port. There are some interesting but not
192 // presently relevant reasons why HostResolver asks for the port of the
193 // hostname you'd like to resolve, even though it doesn't use that value in
194 // determining its answer.
195 net::HostPortPair
host_port_pair(hostname
, 0);
197 net::HostResolver::RequestInfo
request_info(host_port_pair
);
198 int resolve_result
= host_resolver
->Resolve(
200 net::DEFAULT_PRIORITY
,
202 base::Bind(&SocketExtensionWithDnsLookupFunction::OnDnsLookup
, this),
203 request_handle_
.get(),
206 if (resolve_result
!= net::ERR_IO_PENDING
)
207 OnDnsLookup(resolve_result
);
210 void SocketExtensionWithDnsLookupFunction::OnDnsLookup(int resolve_result
) {
211 if (resolve_result
== net::OK
) {
212 DCHECK(!addresses_
->empty());
213 resolved_address_
= addresses_
->front().ToStringWithoutPort();
215 error_
= kDnsLookupFailedError
;
217 AfterDnsLookup(resolve_result
);
220 SocketCreateFunction::SocketCreateFunction()
221 : socket_type_(kSocketTypeInvalid
) {}
223 SocketCreateFunction::~SocketCreateFunction() {}
225 bool SocketCreateFunction::Prepare() {
226 params_
= core_api::socket::Create::Params::Create(*args_
);
227 EXTENSION_FUNCTION_VALIDATE(params_
.get());
229 switch (params_
->type
) {
230 case extensions::core_api::socket::SOCKET_TYPE_TCP
:
231 socket_type_
= kSocketTypeTCP
;
233 case extensions::core_api::socket::SOCKET_TYPE_UDP
:
234 socket_type_
= kSocketTypeUDP
;
236 case extensions::core_api::socket::SOCKET_TYPE_NONE
:
244 void SocketCreateFunction::Work() {
245 Socket
* socket
= NULL
;
246 if (socket_type_
== kSocketTypeTCP
) {
247 socket
= new TCPSocket(extension_
->id());
248 } else if (socket_type_
== kSocketTypeUDP
) {
249 socket
= new UDPSocket(extension_
->id());
253 base::DictionaryValue
* result
= new base::DictionaryValue();
254 result
->SetInteger(kSocketIdKey
, AddSocket(socket
));
258 bool SocketDestroyFunction::Prepare() {
259 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
263 void SocketDestroyFunction::Work() { RemoveSocket(socket_id_
); }
265 SocketConnectFunction::SocketConnectFunction()
266 : socket_id_(0), hostname_(), port_(0) {
269 SocketConnectFunction::~SocketConnectFunction() {}
271 bool SocketConnectFunction::Prepare() {
272 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
273 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(1, &hostname_
));
275 EXTENSION_FUNCTION_VALIDATE(
276 args_
->GetInteger(2, &port
) && port
>= 0 && port
<= 65535);
277 port_
= static_cast<uint16
>(port
);
281 void SocketConnectFunction::AsyncWorkStart() {
282 Socket
* socket
= GetSocket(socket_id_
);
284 error_
= kSocketNotFoundError
;
285 SetResult(new base::FundamentalValue(-1));
286 AsyncWorkCompleted();
290 socket
->set_hostname(hostname_
);
292 SocketPermissionRequest::OperationType operation_type
;
293 switch (socket
->GetSocketType()) {
294 case Socket::TYPE_TCP
:
295 operation_type
= SocketPermissionRequest::TCP_CONNECT
;
297 case Socket::TYPE_UDP
:
298 operation_type
= SocketPermissionRequest::UDP_SEND_TO
;
301 NOTREACHED() << "Unknown socket type.";
302 operation_type
= SocketPermissionRequest::NONE
;
306 SocketPermission::CheckParam
param(operation_type
, hostname_
, port_
);
307 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
308 APIPermission::kSocket
, ¶m
)) {
309 error_
= kPermissionError
;
310 SetResult(new base::FundamentalValue(-1));
311 AsyncWorkCompleted();
315 StartDnsLookup(hostname_
);
318 void SocketConnectFunction::AfterDnsLookup(int lookup_result
) {
319 if (lookup_result
== net::OK
) {
322 SetResult(new base::FundamentalValue(lookup_result
));
323 AsyncWorkCompleted();
327 void SocketConnectFunction::StartConnect() {
328 Socket
* socket
= GetSocket(socket_id_
);
330 error_
= kSocketNotFoundError
;
331 SetResult(new base::FundamentalValue(-1));
332 AsyncWorkCompleted();
336 socket
->Connect(resolved_address_
,
338 base::Bind(&SocketConnectFunction::OnConnect
, this));
341 void SocketConnectFunction::OnConnect(int result
) {
342 SetResult(new base::FundamentalValue(result
));
343 AsyncWorkCompleted();
346 bool SocketDisconnectFunction::Prepare() {
347 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
351 void SocketDisconnectFunction::Work() {
352 Socket
* socket
= GetSocket(socket_id_
);
354 socket
->Disconnect();
356 error_
= kSocketNotFoundError
;
357 SetResult(base::Value::CreateNullValue());
360 bool SocketBindFunction::Prepare() {
361 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
362 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(1, &address_
));
364 EXTENSION_FUNCTION_VALIDATE(
365 args_
->GetInteger(2, &port
) && port
>= 0 && port
<= 65535);
366 port_
= static_cast<uint16
>(port
);
370 void SocketBindFunction::AsyncWorkStart() {
371 Socket
* socket
= GetSocket(socket_id_
);
373 error_
= kSocketNotFoundError
;
374 SetResult(new base::FundamentalValue(-1));
375 AsyncWorkCompleted();
379 if (socket
->GetSocketType() == Socket::TYPE_TCP
) {
380 error_
= kTCPSocketBindError
;
381 SetResult(new base::FundamentalValue(-1));
382 AsyncWorkCompleted();
386 CHECK(socket
->GetSocketType() == Socket::TYPE_UDP
);
387 SocketPermission::CheckParam
param(SocketPermissionRequest::UDP_BIND
,
389 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
390 APIPermission::kSocket
, ¶m
)) {
391 error_
= kPermissionError
;
392 SetResult(new base::FundamentalValue(-1));
393 AsyncWorkCompleted();
397 int result
= socket
->Bind(address_
, port_
);
398 SetResult(new base::FundamentalValue(result
));
399 if (result
!= net::OK
) {
400 AsyncWorkCompleted();
404 OpenFirewallHole(address_
, socket_id_
, socket
);
407 SocketListenFunction::SocketListenFunction() {}
409 SocketListenFunction::~SocketListenFunction() {}
411 bool SocketListenFunction::Prepare() {
412 params_
= core_api::socket::Listen::Params::Create(*args_
);
413 EXTENSION_FUNCTION_VALIDATE(params_
.get());
417 void SocketListenFunction::AsyncWorkStart() {
418 Socket
* socket
= GetSocket(params_
->socket_id
);
420 error_
= kSocketNotFoundError
;
421 SetResult(new base::FundamentalValue(-1));
422 AsyncWorkCompleted();
426 SocketPermission::CheckParam
param(SocketPermissionRequest::TCP_LISTEN
,
427 params_
->address
, params_
->port
);
428 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
429 APIPermission::kSocket
, ¶m
)) {
430 error_
= kPermissionError
;
431 SetResult(new base::FundamentalValue(-1));
432 AsyncWorkCompleted();
436 int result
= socket
->Listen(
437 params_
->address
, params_
->port
,
438 params_
->backlog
.get() ? *params_
->backlog
.get() : 5, &error_
);
439 SetResult(new base::FundamentalValue(result
));
440 if (result
!= net::OK
) {
441 AsyncWorkCompleted();
445 OpenFirewallHole(params_
->address
, params_
->socket_id
, socket
);
448 SocketAcceptFunction::SocketAcceptFunction() {}
450 SocketAcceptFunction::~SocketAcceptFunction() {}
452 bool SocketAcceptFunction::Prepare() {
453 params_
= core_api::socket::Accept::Params::Create(*args_
);
454 EXTENSION_FUNCTION_VALIDATE(params_
.get());
458 void SocketAcceptFunction::AsyncWorkStart() {
459 Socket
* socket
= GetSocket(params_
->socket_id
);
461 socket
->Accept(base::Bind(&SocketAcceptFunction::OnAccept
, this));
463 error_
= kSocketNotFoundError
;
468 void SocketAcceptFunction::OnAccept(int result_code
,
469 net::TCPClientSocket
* socket
) {
470 base::DictionaryValue
* result
= new base::DictionaryValue();
471 result
->SetInteger(kResultCodeKey
, result_code
);
473 Socket
* client_socket
= new TCPSocket(socket
, extension_id(), true);
474 result
->SetInteger(kSocketIdKey
, AddSocket(client_socket
));
478 AsyncWorkCompleted();
481 SocketReadFunction::SocketReadFunction() {}
483 SocketReadFunction::~SocketReadFunction() {}
485 bool SocketReadFunction::Prepare() {
486 params_
= core_api::socket::Read::Params::Create(*args_
);
487 EXTENSION_FUNCTION_VALIDATE(params_
.get());
491 void SocketReadFunction::AsyncWorkStart() {
492 Socket
* socket
= GetSocket(params_
->socket_id
);
494 error_
= kSocketNotFoundError
;
495 OnCompleted(-1, NULL
);
499 socket
->Read(params_
->buffer_size
.get() ? *params_
->buffer_size
.get() : 4096,
500 base::Bind(&SocketReadFunction::OnCompleted
, this));
503 void SocketReadFunction::OnCompleted(int bytes_read
,
504 scoped_refptr
<net::IOBuffer
> io_buffer
) {
505 base::DictionaryValue
* result
= new base::DictionaryValue();
506 result
->SetInteger(kResultCodeKey
, bytes_read
);
507 if (bytes_read
> 0) {
508 result
->Set(kDataKey
,
509 base::BinaryValue::CreateWithCopiedBuffer(io_buffer
->data(),
512 result
->Set(kDataKey
, new base::BinaryValue());
516 AsyncWorkCompleted();
519 SocketWriteFunction::SocketWriteFunction()
520 : socket_id_(0), io_buffer_(NULL
), io_buffer_size_(0) {}
522 SocketWriteFunction::~SocketWriteFunction() {}
524 bool SocketWriteFunction::Prepare() {
525 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
526 base::BinaryValue
* data
= NULL
;
527 EXTENSION_FUNCTION_VALIDATE(args_
->GetBinary(1, &data
));
529 io_buffer_size_
= data
->GetSize();
530 io_buffer_
= new net::WrappedIOBuffer(data
->GetBuffer());
534 void SocketWriteFunction::AsyncWorkStart() {
535 Socket
* socket
= GetSocket(socket_id_
);
538 error_
= kSocketNotFoundError
;
543 socket
->Write(io_buffer_
,
545 base::Bind(&SocketWriteFunction::OnCompleted
, this));
548 void SocketWriteFunction::OnCompleted(int bytes_written
) {
549 base::DictionaryValue
* result
= new base::DictionaryValue();
550 result
->SetInteger(kBytesWrittenKey
, bytes_written
);
553 AsyncWorkCompleted();
556 SocketRecvFromFunction::SocketRecvFromFunction() {}
558 SocketRecvFromFunction::~SocketRecvFromFunction() {}
560 bool SocketRecvFromFunction::Prepare() {
561 params_
= core_api::socket::RecvFrom::Params::Create(*args_
);
562 EXTENSION_FUNCTION_VALIDATE(params_
.get());
566 void SocketRecvFromFunction::AsyncWorkStart() {
567 Socket
* socket
= GetSocket(params_
->socket_id
);
568 if (!socket
|| socket
->GetSocketType() != Socket::TYPE_UDP
) {
569 error_
= kSocketNotFoundError
;
570 OnCompleted(-1, NULL
, std::string(), 0);
574 socket
->RecvFrom(params_
->buffer_size
.get() ? *params_
->buffer_size
: 4096,
575 base::Bind(&SocketRecvFromFunction::OnCompleted
, this));
578 void SocketRecvFromFunction::OnCompleted(int bytes_read
,
579 scoped_refptr
<net::IOBuffer
> io_buffer
,
580 const std::string
& address
,
582 base::DictionaryValue
* result
= new base::DictionaryValue();
583 result
->SetInteger(kResultCodeKey
, bytes_read
);
584 if (bytes_read
> 0) {
585 result
->Set(kDataKey
,
586 base::BinaryValue::CreateWithCopiedBuffer(io_buffer
->data(),
589 result
->Set(kDataKey
, new base::BinaryValue());
591 result
->SetString(kAddressKey
, address
);
592 result
->SetInteger(kPortKey
, port
);
595 AsyncWorkCompleted();
598 SocketSendToFunction::SocketSendToFunction()
599 : socket_id_(0), io_buffer_(NULL
), io_buffer_size_(0), port_(0) {
602 SocketSendToFunction::~SocketSendToFunction() {}
604 bool SocketSendToFunction::Prepare() {
605 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
606 base::BinaryValue
* data
= NULL
;
607 EXTENSION_FUNCTION_VALIDATE(args_
->GetBinary(1, &data
));
608 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(2, &hostname_
));
610 EXTENSION_FUNCTION_VALIDATE(
611 args_
->GetInteger(3, &port
) && port
>= 0 && port
<= 65535);
612 port_
= static_cast<uint16
>(port
);
614 io_buffer_size_
= data
->GetSize();
615 io_buffer_
= new net::WrappedIOBuffer(data
->GetBuffer());
619 void SocketSendToFunction::AsyncWorkStart() {
620 Socket
* socket
= GetSocket(socket_id_
);
622 error_
= kSocketNotFoundError
;
623 SetResult(new base::FundamentalValue(-1));
624 AsyncWorkCompleted();
628 if (socket
->GetSocketType() == Socket::TYPE_UDP
) {
629 SocketPermission::CheckParam
param(
630 SocketPermissionRequest::UDP_SEND_TO
, hostname_
, port_
);
631 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
632 APIPermission::kSocket
, ¶m
)) {
633 error_
= kPermissionError
;
634 SetResult(new base::FundamentalValue(-1));
635 AsyncWorkCompleted();
640 StartDnsLookup(hostname_
);
643 void SocketSendToFunction::AfterDnsLookup(int lookup_result
) {
644 if (lookup_result
== net::OK
) {
647 SetResult(new base::FundamentalValue(lookup_result
));
648 AsyncWorkCompleted();
652 void SocketSendToFunction::StartSendTo() {
653 Socket
* socket
= GetSocket(socket_id_
);
655 error_
= kSocketNotFoundError
;
656 SetResult(new base::FundamentalValue(-1));
657 AsyncWorkCompleted();
661 socket
->SendTo(io_buffer_
,
665 base::Bind(&SocketSendToFunction::OnCompleted
, this));
668 void SocketSendToFunction::OnCompleted(int bytes_written
) {
669 base::DictionaryValue
* result
= new base::DictionaryValue();
670 result
->SetInteger(kBytesWrittenKey
, bytes_written
);
673 AsyncWorkCompleted();
676 SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {}
678 SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {}
680 bool SocketSetKeepAliveFunction::Prepare() {
681 params_
= core_api::socket::SetKeepAlive::Params::Create(*args_
);
682 EXTENSION_FUNCTION_VALIDATE(params_
.get());
686 void SocketSetKeepAliveFunction::Work() {
688 Socket
* socket
= GetSocket(params_
->socket_id
);
691 if (params_
->delay
.get())
692 delay
= *params_
->delay
;
693 result
= socket
->SetKeepAlive(params_
->enable
, delay
);
695 error_
= kSocketNotFoundError
;
697 SetResult(new base::FundamentalValue(result
));
700 SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
702 SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {}
704 bool SocketSetNoDelayFunction::Prepare() {
705 params_
= core_api::socket::SetNoDelay::Params::Create(*args_
);
706 EXTENSION_FUNCTION_VALIDATE(params_
.get());
710 void SocketSetNoDelayFunction::Work() {
712 Socket
* socket
= GetSocket(params_
->socket_id
);
714 result
= socket
->SetNoDelay(params_
->no_delay
);
716 error_
= kSocketNotFoundError
;
717 SetResult(new base::FundamentalValue(result
));
720 SocketGetInfoFunction::SocketGetInfoFunction() {}
722 SocketGetInfoFunction::~SocketGetInfoFunction() {}
724 bool SocketGetInfoFunction::Prepare() {
725 params_
= core_api::socket::GetInfo::Params::Create(*args_
);
726 EXTENSION_FUNCTION_VALIDATE(params_
.get());
730 void SocketGetInfoFunction::Work() {
731 Socket
* socket
= GetSocket(params_
->socket_id
);
733 error_
= kSocketNotFoundError
;
737 core_api::socket::SocketInfo info
;
738 // This represents what we know about the socket, and does not call through
740 if (socket
->GetSocketType() == Socket::TYPE_TCP
)
741 info
.socket_type
= extensions::core_api::socket::SOCKET_TYPE_TCP
;
743 info
.socket_type
= extensions::core_api::socket::SOCKET_TYPE_UDP
;
744 info
.connected
= socket
->IsConnected();
746 // Grab the peer address as known by the OS. This and the call below will
747 // always succeed while the socket is connected, even if the socket has
748 // been remotely closed by the peer; only reading the socket will reveal
749 // that it should be closed locally.
750 net::IPEndPoint peerAddress
;
751 if (socket
->GetPeerAddress(&peerAddress
)) {
752 info
.peer_address
.reset(new std::string(peerAddress
.ToStringWithoutPort()));
753 info
.peer_port
.reset(new int(peerAddress
.port()));
756 // Grab the local address as known by the OS.
757 net::IPEndPoint localAddress
;
758 if (socket
->GetLocalAddress(&localAddress
)) {
759 info
.local_address
.reset(
760 new std::string(localAddress
.ToStringWithoutPort()));
761 info
.local_port
.reset(new int(localAddress
.port()));
764 SetResult(info
.ToValue().release());
767 bool SocketGetNetworkListFunction::RunAsync() {
768 BrowserThread::PostTask(
769 BrowserThread::FILE, FROM_HERE
,
770 base::Bind(&SocketGetNetworkListFunction::GetNetworkListOnFileThread
,
775 void SocketGetNetworkListFunction::GetNetworkListOnFileThread() {
776 net::NetworkInterfaceList interface_list
;
777 if (GetNetworkList(&interface_list
,
778 net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES
)) {
779 BrowserThread::PostTask(
780 BrowserThread::UI
, FROM_HERE
,
781 base::Bind(&SocketGetNetworkListFunction::SendResponseOnUIThread
, this,
786 BrowserThread::PostTask(
787 BrowserThread::UI
, FROM_HERE
,
788 base::Bind(&SocketGetNetworkListFunction::HandleGetNetworkListError
,
792 void SocketGetNetworkListFunction::HandleGetNetworkListError() {
793 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
794 error_
= kNetworkListError
;
798 void SocketGetNetworkListFunction::SendResponseOnUIThread(
799 const net::NetworkInterfaceList
& interface_list
) {
800 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
802 std::vector
<linked_ptr
<core_api::socket::NetworkInterface
> > create_arg
;
803 create_arg
.reserve(interface_list
.size());
804 for (net::NetworkInterfaceList::const_iterator i
= interface_list
.begin();
805 i
!= interface_list
.end();
807 linked_ptr
<core_api::socket::NetworkInterface
> info
=
808 make_linked_ptr(new core_api::socket::NetworkInterface
);
809 info
->name
= i
->name
;
810 info
->address
= net::IPAddressToString(i
->address
);
811 info
->prefix_length
= i
->prefix_length
;
812 create_arg
.push_back(info
);
815 results_
= core_api::socket::GetNetworkList::Results::Create(create_arg
);
819 SocketJoinGroupFunction::SocketJoinGroupFunction() {}
821 SocketJoinGroupFunction::~SocketJoinGroupFunction() {}
823 bool SocketJoinGroupFunction::Prepare() {
824 params_
= core_api::socket::JoinGroup::Params::Create(*args_
);
825 EXTENSION_FUNCTION_VALIDATE(params_
.get());
829 void SocketJoinGroupFunction::Work() {
831 Socket
* socket
= GetSocket(params_
->socket_id
);
833 error_
= kSocketNotFoundError
;
834 SetResult(new base::FundamentalValue(result
));
838 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
839 error_
= kMulticastSocketTypeError
;
840 SetResult(new base::FundamentalValue(result
));
844 SocketPermission::CheckParam
param(
845 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
849 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
850 APIPermission::kSocket
, ¶m
)) {
851 error_
= kPermissionError
;
852 SetResult(new base::FundamentalValue(result
));
856 result
= static_cast<UDPSocket
*>(socket
)->JoinGroup(params_
->address
);
858 error_
= net::ErrorToString(result
);
860 SetResult(new base::FundamentalValue(result
));
863 SocketLeaveGroupFunction::SocketLeaveGroupFunction() {}
865 SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {}
867 bool SocketLeaveGroupFunction::Prepare() {
868 params_
= core_api::socket::LeaveGroup::Params::Create(*args_
);
869 EXTENSION_FUNCTION_VALIDATE(params_
.get());
873 void SocketLeaveGroupFunction::Work() {
875 Socket
* socket
= GetSocket(params_
->socket_id
);
878 error_
= kSocketNotFoundError
;
879 SetResult(new base::FundamentalValue(result
));
883 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
884 error_
= kMulticastSocketTypeError
;
885 SetResult(new base::FundamentalValue(result
));
889 SocketPermission::CheckParam
param(
890 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
893 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
894 APIPermission::kSocket
, ¶m
)) {
895 error_
= kPermissionError
;
896 SetResult(new base::FundamentalValue(result
));
900 result
= static_cast<UDPSocket
*>(socket
)->LeaveGroup(params_
->address
);
902 error_
= net::ErrorToString(result
);
903 SetResult(new base::FundamentalValue(result
));
906 SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {}
908 SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {}
910 bool SocketSetMulticastTimeToLiveFunction::Prepare() {
911 params_
= core_api::socket::SetMulticastTimeToLive::Params::Create(*args_
);
912 EXTENSION_FUNCTION_VALIDATE(params_
.get());
915 void SocketSetMulticastTimeToLiveFunction::Work() {
917 Socket
* socket
= GetSocket(params_
->socket_id
);
919 error_
= kSocketNotFoundError
;
920 SetResult(new base::FundamentalValue(result
));
924 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
925 error_
= kMulticastSocketTypeError
;
926 SetResult(new base::FundamentalValue(result
));
931 static_cast<UDPSocket
*>(socket
)->SetMulticastTimeToLive(params_
->ttl
);
933 error_
= net::ErrorToString(result
);
934 SetResult(new base::FundamentalValue(result
));
937 SocketSetMulticastLoopbackModeFunction::
938 SocketSetMulticastLoopbackModeFunction() {}
940 SocketSetMulticastLoopbackModeFunction::
941 ~SocketSetMulticastLoopbackModeFunction() {}
943 bool SocketSetMulticastLoopbackModeFunction::Prepare() {
944 params_
= core_api::socket::SetMulticastLoopbackMode::Params::Create(*args_
);
945 EXTENSION_FUNCTION_VALIDATE(params_
.get());
949 void SocketSetMulticastLoopbackModeFunction::Work() {
951 Socket
* socket
= GetSocket(params_
->socket_id
);
953 error_
= kSocketNotFoundError
;
954 SetResult(new base::FundamentalValue(result
));
958 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
959 error_
= kMulticastSocketTypeError
;
960 SetResult(new base::FundamentalValue(result
));
964 result
= static_cast<UDPSocket
*>(socket
)
965 ->SetMulticastLoopbackMode(params_
->enabled
);
967 error_
= net::ErrorToString(result
);
968 SetResult(new base::FundamentalValue(result
));
971 SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {}
973 SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {}
975 bool SocketGetJoinedGroupsFunction::Prepare() {
976 params_
= core_api::socket::GetJoinedGroups::Params::Create(*args_
);
977 EXTENSION_FUNCTION_VALIDATE(params_
.get());
981 void SocketGetJoinedGroupsFunction::Work() {
983 Socket
* socket
= GetSocket(params_
->socket_id
);
985 error_
= kSocketNotFoundError
;
986 SetResult(new base::FundamentalValue(result
));
990 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
991 error_
= kMulticastSocketTypeError
;
992 SetResult(new base::FundamentalValue(result
));
996 SocketPermission::CheckParam
param(
997 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
1000 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
1001 APIPermission::kSocket
, ¶m
)) {
1002 error_
= kPermissionError
;
1003 SetResult(new base::FundamentalValue(result
));
1007 base::ListValue
* values
= new base::ListValue();
1008 values
->AppendStrings((std::vector
<std::string
>&)static_cast<UDPSocket
*>(
1009 socket
)->GetJoinedGroups());
1013 SocketSecureFunction::SocketSecureFunction() {
1016 SocketSecureFunction::~SocketSecureFunction() {
1019 bool SocketSecureFunction::Prepare() {
1020 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
1021 params_
= core_api::socket::Secure::Params::Create(*args_
);
1022 EXTENSION_FUNCTION_VALIDATE(params_
.get());
1023 url_request_getter_
= browser_context()->GetRequestContext();
1027 // Override the regular implementation, which would call AsyncWorkCompleted
1028 // immediately after Work().
1029 void SocketSecureFunction::AsyncWorkStart() {
1030 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
1032 Socket
* socket
= GetSocket(params_
->socket_id
);
1034 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
1035 error_
= kSocketNotFoundError
;
1036 AsyncWorkCompleted();
1040 // Make sure that the socket is a TCP client socket.
1041 if (socket
->GetSocketType() != Socket::TYPE_TCP
||
1042 static_cast<TCPSocket
*>(socket
)->ClientStream() == NULL
) {
1043 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
1044 error_
= kSecureSocketTypeError
;
1045 AsyncWorkCompleted();
1049 if (!socket
->IsConnected()) {
1050 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
1051 error_
= kSocketNotConnectedError
;
1052 AsyncWorkCompleted();
1056 net::URLRequestContext
* url_request_context
=
1057 url_request_getter_
->GetURLRequestContext();
1059 TLSSocket::UpgradeSocketToTLS(
1061 url_request_context
->ssl_config_service(),
1062 url_request_context
->cert_verifier(),
1063 url_request_context
->transport_security_state(),
1065 params_
->options
.get(),
1066 base::Bind(&SocketSecureFunction::TlsConnectDone
, this));
1069 void SocketSecureFunction::TlsConnectDone(scoped_ptr
<TLSSocket
> socket
,
1071 // if an error occurred, socket MUST be NULL.
1072 DCHECK(result
== net::OK
|| socket
== NULL
);
1074 if (socket
&& result
== net::OK
) {
1075 ReplaceSocket(params_
->socket_id
, socket
.release());
1077 RemoveSocket(params_
->socket_id
);
1078 error_
= net::ErrorToString(result
);
1081 results_
= core_api::socket::Secure::Results::Create(result
);
1082 AsyncWorkCompleted();
1085 } // namespace extensions