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 "base/profiler/scoped_tracker.h"
12 #include "content/public/browser/browser_context.h"
13 #include "content/public/browser/resource_context.h"
14 #include "extensions/browser/api/dns/host_resolver_wrapper.h"
15 #include "extensions/browser/api/socket/socket.h"
16 #include "extensions/browser/api/socket/tcp_socket.h"
17 #include "extensions/browser/api/socket/tls_socket.h"
18 #include "extensions/browser/api/socket/udp_socket.h"
19 #include "extensions/browser/extension_system.h"
20 #include "extensions/common/extension.h"
21 #include "extensions/common/permissions/permissions_data.h"
22 #include "extensions/common/permissions/socket_permission.h"
23 #include "net/base/host_port_pair.h"
24 #include "net/base/io_buffer.h"
25 #include "net/base/ip_endpoint.h"
26 #include "net/base/net_errors.h"
27 #include "net/base/net_log.h"
28 #include "net/base/net_util.h"
29 #include "net/url_request/url_request_context.h"
30 #include "net/url_request/url_request_context_getter.h"
32 namespace extensions
{
34 using content::SocketPermissionRequest
;
36 const char kAddressKey
[] = "address";
37 const char kPortKey
[] = "port";
38 const char kBytesWrittenKey
[] = "bytesWritten";
39 const char kDataKey
[] = "data";
40 const char kResultCodeKey
[] = "resultCode";
41 const char kSocketIdKey
[] = "socketId";
43 const char kSocketNotFoundError
[] = "Socket not found";
44 const char kDnsLookupFailedError
[] = "DNS resolution failed";
45 const char kPermissionError
[] = "App does not have permission";
46 const char kNetworkListError
[] = "Network lookup failed or unsupported";
47 const char kTCPSocketBindError
[] =
48 "TCP socket does not support bind. For TCP server please use listen.";
49 const char kMulticastSocketTypeError
[] = "Only UDP socket supports multicast.";
50 const char kSecureSocketTypeError
[] = "Only TCP sockets are supported for TLS.";
51 const char kSocketNotConnectedError
[] = "Socket not connected";
52 const char kWildcardAddress
[] = "*";
53 const uint16 kWildcardPort
= 0;
55 SocketAsyncApiFunction::SocketAsyncApiFunction() {}
57 SocketAsyncApiFunction::~SocketAsyncApiFunction() {}
59 bool SocketAsyncApiFunction::PrePrepare() {
60 manager_
= CreateSocketResourceManager();
61 return manager_
->SetBrowserContext(browser_context());
64 bool SocketAsyncApiFunction::Respond() { return error_
.empty(); }
66 scoped_ptr
<SocketResourceManagerInterface
>
67 SocketAsyncApiFunction::CreateSocketResourceManager() {
68 return scoped_ptr
<SocketResourceManagerInterface
>(
69 new SocketResourceManager
<Socket
>()).Pass();
72 int SocketAsyncApiFunction::AddSocket(Socket
* socket
) {
73 return manager_
->Add(socket
);
76 Socket
* SocketAsyncApiFunction::GetSocket(int api_resource_id
) {
77 return manager_
->Get(extension_
->id(), api_resource_id
);
80 void SocketAsyncApiFunction::ReplaceSocket(int api_resource_id
,
82 manager_
->Replace(extension_
->id(), api_resource_id
, socket
);
85 base::hash_set
<int>* SocketAsyncApiFunction::GetSocketIds() {
86 return manager_
->GetResourceIds(extension_
->id());
89 void SocketAsyncApiFunction::RemoveSocket(int api_resource_id
) {
90 manager_
->Remove(extension_
->id(), api_resource_id
);
93 SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction()
94 : resource_context_(NULL
),
95 request_handle_(new net::HostResolver::RequestHandle
),
96 addresses_(new net::AddressList
) {}
98 SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() {}
100 bool SocketExtensionWithDnsLookupFunction::PrePrepare() {
101 if (!SocketAsyncApiFunction::PrePrepare())
103 resource_context_
= browser_context()->GetResourceContext();
104 return resource_context_
!= NULL
;
107 void SocketExtensionWithDnsLookupFunction::StartDnsLookup(
108 const std::string
& hostname
) {
109 net::HostResolver
* host_resolver
=
110 HostResolverWrapper::GetInstance()->GetHostResolver(resource_context_
);
111 DCHECK(host_resolver
);
113 // Yes, we are passing zero as the port. There are some interesting but not
114 // presently relevant reasons why HostResolver asks for the port of the
115 // hostname you'd like to resolve, even though it doesn't use that value in
116 // determining its answer.
117 net::HostPortPair
host_port_pair(hostname
, 0);
119 net::HostResolver::RequestInfo
request_info(host_port_pair
);
120 int resolve_result
= host_resolver
->Resolve(
122 net::DEFAULT_PRIORITY
,
124 base::Bind(&SocketExtensionWithDnsLookupFunction::OnDnsLookup
, this),
125 request_handle_
.get(),
128 if (resolve_result
!= net::ERR_IO_PENDING
)
129 OnDnsLookup(resolve_result
);
132 void SocketExtensionWithDnsLookupFunction::OnDnsLookup(int resolve_result
) {
133 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed.
134 tracked_objects::ScopedTracker
tracking_profile(
135 FROM_HERE_WITH_EXPLICIT_FUNCTION(
136 "436634 SocketExtensionWithDnsLookupFunction::OnDnsLookup"));
138 if (resolve_result
== net::OK
) {
139 DCHECK(!addresses_
->empty());
140 resolved_address_
= addresses_
->front().ToStringWithoutPort();
142 error_
= kDnsLookupFailedError
;
144 AfterDnsLookup(resolve_result
);
147 SocketCreateFunction::SocketCreateFunction()
148 : socket_type_(kSocketTypeInvalid
) {}
150 SocketCreateFunction::~SocketCreateFunction() {}
152 bool SocketCreateFunction::Prepare() {
153 params_
= core_api::socket::Create::Params::Create(*args_
);
154 EXTENSION_FUNCTION_VALIDATE(params_
.get());
156 switch (params_
->type
) {
157 case extensions::core_api::socket::SOCKET_TYPE_TCP
:
158 socket_type_
= kSocketTypeTCP
;
160 case extensions::core_api::socket::SOCKET_TYPE_UDP
:
161 socket_type_
= kSocketTypeUDP
;
163 case extensions::core_api::socket::SOCKET_TYPE_NONE
:
171 void SocketCreateFunction::Work() {
172 Socket
* socket
= NULL
;
173 if (socket_type_
== kSocketTypeTCP
) {
174 socket
= new TCPSocket(extension_
->id());
175 } else if (socket_type_
== kSocketTypeUDP
) {
176 socket
= new UDPSocket(extension_
->id());
180 base::DictionaryValue
* result
= new base::DictionaryValue();
181 result
->SetInteger(kSocketIdKey
, AddSocket(socket
));
185 bool SocketDestroyFunction::Prepare() {
186 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
190 void SocketDestroyFunction::Work() { RemoveSocket(socket_id_
); }
192 SocketConnectFunction::SocketConnectFunction()
193 : socket_id_(0), hostname_(), port_(0) {
196 SocketConnectFunction::~SocketConnectFunction() {}
198 bool SocketConnectFunction::Prepare() {
199 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
200 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(1, &hostname_
));
202 EXTENSION_FUNCTION_VALIDATE(
203 args_
->GetInteger(2, &port
) && port
>= 0 && port
<= 65535);
204 port_
= static_cast<uint16
>(port
);
208 void SocketConnectFunction::AsyncWorkStart() {
209 Socket
* socket
= GetSocket(socket_id_
);
211 error_
= kSocketNotFoundError
;
212 SetResult(new base::FundamentalValue(-1));
213 AsyncWorkCompleted();
217 socket
->set_hostname(hostname_
);
219 SocketPermissionRequest::OperationType operation_type
;
220 switch (socket
->GetSocketType()) {
221 case Socket::TYPE_TCP
:
222 operation_type
= SocketPermissionRequest::TCP_CONNECT
;
224 case Socket::TYPE_UDP
:
225 operation_type
= SocketPermissionRequest::UDP_SEND_TO
;
228 NOTREACHED() << "Unknown socket type.";
229 operation_type
= SocketPermissionRequest::NONE
;
233 SocketPermission::CheckParam
param(operation_type
, hostname_
, port_
);
234 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
235 APIPermission::kSocket
, ¶m
)) {
236 error_
= kPermissionError
;
237 SetResult(new base::FundamentalValue(-1));
238 AsyncWorkCompleted();
242 StartDnsLookup(hostname_
);
245 void SocketConnectFunction::AfterDnsLookup(int lookup_result
) {
246 if (lookup_result
== net::OK
) {
249 SetResult(new base::FundamentalValue(lookup_result
));
250 AsyncWorkCompleted();
254 void SocketConnectFunction::StartConnect() {
255 Socket
* socket
= GetSocket(socket_id_
);
257 error_
= kSocketNotFoundError
;
258 SetResult(new base::FundamentalValue(-1));
259 AsyncWorkCompleted();
263 socket
->Connect(resolved_address_
,
265 base::Bind(&SocketConnectFunction::OnConnect
, this));
268 void SocketConnectFunction::OnConnect(int result
) {
269 SetResult(new base::FundamentalValue(result
));
270 AsyncWorkCompleted();
273 bool SocketDisconnectFunction::Prepare() {
274 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
278 void SocketDisconnectFunction::Work() {
279 Socket
* socket
= GetSocket(socket_id_
);
281 socket
->Disconnect();
283 error_
= kSocketNotFoundError
;
284 SetResult(base::Value::CreateNullValue());
287 bool SocketBindFunction::Prepare() {
288 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
289 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(1, &address_
));
291 EXTENSION_FUNCTION_VALIDATE(
292 args_
->GetInteger(2, &port
) && port
>= 0 && port
<= 65535);
293 port_
= static_cast<uint16
>(port
);
297 void SocketBindFunction::Work() {
299 Socket
* socket
= GetSocket(socket_id_
);
302 error_
= kSocketNotFoundError
;
303 SetResult(new base::FundamentalValue(result
));
307 if (socket
->GetSocketType() == Socket::TYPE_UDP
) {
308 SocketPermission::CheckParam
param(
309 SocketPermissionRequest::UDP_BIND
, address_
, port_
);
310 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
311 APIPermission::kSocket
, ¶m
)) {
312 error_
= kPermissionError
;
313 SetResult(new base::FundamentalValue(result
));
316 } else if (socket
->GetSocketType() == Socket::TYPE_TCP
) {
317 error_
= kTCPSocketBindError
;
318 SetResult(new base::FundamentalValue(result
));
322 result
= socket
->Bind(address_
, port_
);
323 SetResult(new base::FundamentalValue(result
));
326 SocketListenFunction::SocketListenFunction() {}
328 SocketListenFunction::~SocketListenFunction() {}
330 bool SocketListenFunction::Prepare() {
331 params_
= core_api::socket::Listen::Params::Create(*args_
);
332 EXTENSION_FUNCTION_VALIDATE(params_
.get());
336 void SocketListenFunction::Work() {
339 Socket
* socket
= GetSocket(params_
->socket_id
);
341 SocketPermission::CheckParam
param(
342 SocketPermissionRequest::TCP_LISTEN
, params_
->address
, params_
->port
);
343 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
344 APIPermission::kSocket
, ¶m
)) {
345 error_
= kPermissionError
;
346 SetResult(new base::FundamentalValue(result
));
351 socket
->Listen(params_
->address
,
353 params_
->backlog
.get() ? *params_
->backlog
.get() : 5,
356 error_
= kSocketNotFoundError
;
359 SetResult(new base::FundamentalValue(result
));
362 SocketAcceptFunction::SocketAcceptFunction() {}
364 SocketAcceptFunction::~SocketAcceptFunction() {}
366 bool SocketAcceptFunction::Prepare() {
367 params_
= core_api::socket::Accept::Params::Create(*args_
);
368 EXTENSION_FUNCTION_VALIDATE(params_
.get());
372 void SocketAcceptFunction::AsyncWorkStart() {
373 Socket
* socket
= GetSocket(params_
->socket_id
);
375 socket
->Accept(base::Bind(&SocketAcceptFunction::OnAccept
, this));
377 error_
= kSocketNotFoundError
;
382 void SocketAcceptFunction::OnAccept(int result_code
,
383 net::TCPClientSocket
* socket
) {
384 base::DictionaryValue
* result
= new base::DictionaryValue();
385 result
->SetInteger(kResultCodeKey
, result_code
);
387 Socket
* client_socket
= new TCPSocket(socket
, extension_id(), true);
388 result
->SetInteger(kSocketIdKey
, AddSocket(client_socket
));
392 AsyncWorkCompleted();
395 SocketReadFunction::SocketReadFunction() {}
397 SocketReadFunction::~SocketReadFunction() {}
399 bool SocketReadFunction::Prepare() {
400 params_
= core_api::socket::Read::Params::Create(*args_
);
401 EXTENSION_FUNCTION_VALIDATE(params_
.get());
405 void SocketReadFunction::AsyncWorkStart() {
406 Socket
* socket
= GetSocket(params_
->socket_id
);
408 error_
= kSocketNotFoundError
;
409 OnCompleted(-1, NULL
);
413 socket
->Read(params_
->buffer_size
.get() ? *params_
->buffer_size
.get() : 4096,
414 base::Bind(&SocketReadFunction::OnCompleted
, this));
417 void SocketReadFunction::OnCompleted(int bytes_read
,
418 scoped_refptr
<net::IOBuffer
> io_buffer
) {
419 base::DictionaryValue
* result
= new base::DictionaryValue();
420 result
->SetInteger(kResultCodeKey
, bytes_read
);
421 if (bytes_read
> 0) {
422 result
->Set(kDataKey
,
423 base::BinaryValue::CreateWithCopiedBuffer(io_buffer
->data(),
426 result
->Set(kDataKey
, new base::BinaryValue());
430 AsyncWorkCompleted();
433 SocketWriteFunction::SocketWriteFunction()
434 : socket_id_(0), io_buffer_(NULL
), io_buffer_size_(0) {}
436 SocketWriteFunction::~SocketWriteFunction() {}
438 bool SocketWriteFunction::Prepare() {
439 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
440 base::BinaryValue
* data
= NULL
;
441 EXTENSION_FUNCTION_VALIDATE(args_
->GetBinary(1, &data
));
443 io_buffer_size_
= data
->GetSize();
444 io_buffer_
= new net::WrappedIOBuffer(data
->GetBuffer());
448 void SocketWriteFunction::AsyncWorkStart() {
449 Socket
* socket
= GetSocket(socket_id_
);
452 error_
= kSocketNotFoundError
;
457 socket
->Write(io_buffer_
,
459 base::Bind(&SocketWriteFunction::OnCompleted
, this));
462 void SocketWriteFunction::OnCompleted(int bytes_written
) {
463 base::DictionaryValue
* result
= new base::DictionaryValue();
464 result
->SetInteger(kBytesWrittenKey
, bytes_written
);
467 AsyncWorkCompleted();
470 SocketRecvFromFunction::SocketRecvFromFunction() {}
472 SocketRecvFromFunction::~SocketRecvFromFunction() {}
474 bool SocketRecvFromFunction::Prepare() {
475 params_
= core_api::socket::RecvFrom::Params::Create(*args_
);
476 EXTENSION_FUNCTION_VALIDATE(params_
.get());
480 void SocketRecvFromFunction::AsyncWorkStart() {
481 Socket
* socket
= GetSocket(params_
->socket_id
);
482 if (!socket
|| socket
->GetSocketType() != Socket::TYPE_UDP
) {
483 error_
= kSocketNotFoundError
;
484 OnCompleted(-1, NULL
, std::string(), 0);
488 socket
->RecvFrom(params_
->buffer_size
.get() ? *params_
->buffer_size
: 4096,
489 base::Bind(&SocketRecvFromFunction::OnCompleted
, this));
492 void SocketRecvFromFunction::OnCompleted(int bytes_read
,
493 scoped_refptr
<net::IOBuffer
> io_buffer
,
494 const std::string
& address
,
496 base::DictionaryValue
* result
= new base::DictionaryValue();
497 result
->SetInteger(kResultCodeKey
, bytes_read
);
498 if (bytes_read
> 0) {
499 result
->Set(kDataKey
,
500 base::BinaryValue::CreateWithCopiedBuffer(io_buffer
->data(),
503 result
->Set(kDataKey
, new base::BinaryValue());
505 result
->SetString(kAddressKey
, address
);
506 result
->SetInteger(kPortKey
, port
);
509 AsyncWorkCompleted();
512 SocketSendToFunction::SocketSendToFunction()
513 : socket_id_(0), io_buffer_(NULL
), io_buffer_size_(0), port_(0) {
516 SocketSendToFunction::~SocketSendToFunction() {}
518 bool SocketSendToFunction::Prepare() {
519 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
520 base::BinaryValue
* data
= NULL
;
521 EXTENSION_FUNCTION_VALIDATE(args_
->GetBinary(1, &data
));
522 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(2, &hostname_
));
524 EXTENSION_FUNCTION_VALIDATE(
525 args_
->GetInteger(3, &port
) && port
>= 0 && port
<= 65535);
526 port_
= static_cast<uint16
>(port
);
528 io_buffer_size_
= data
->GetSize();
529 io_buffer_
= new net::WrappedIOBuffer(data
->GetBuffer());
533 void SocketSendToFunction::AsyncWorkStart() {
534 Socket
* socket
= GetSocket(socket_id_
);
536 error_
= kSocketNotFoundError
;
537 SetResult(new base::FundamentalValue(-1));
538 AsyncWorkCompleted();
542 if (socket
->GetSocketType() == Socket::TYPE_UDP
) {
543 SocketPermission::CheckParam
param(
544 SocketPermissionRequest::UDP_SEND_TO
, hostname_
, port_
);
545 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
546 APIPermission::kSocket
, ¶m
)) {
547 error_
= kPermissionError
;
548 SetResult(new base::FundamentalValue(-1));
549 AsyncWorkCompleted();
554 StartDnsLookup(hostname_
);
557 void SocketSendToFunction::AfterDnsLookup(int lookup_result
) {
558 if (lookup_result
== net::OK
) {
561 SetResult(new base::FundamentalValue(lookup_result
));
562 AsyncWorkCompleted();
566 void SocketSendToFunction::StartSendTo() {
567 Socket
* socket
= GetSocket(socket_id_
);
569 error_
= kSocketNotFoundError
;
570 SetResult(new base::FundamentalValue(-1));
571 AsyncWorkCompleted();
575 socket
->SendTo(io_buffer_
,
579 base::Bind(&SocketSendToFunction::OnCompleted
, this));
582 void SocketSendToFunction::OnCompleted(int bytes_written
) {
583 base::DictionaryValue
* result
= new base::DictionaryValue();
584 result
->SetInteger(kBytesWrittenKey
, bytes_written
);
587 AsyncWorkCompleted();
590 SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {}
592 SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {}
594 bool SocketSetKeepAliveFunction::Prepare() {
595 params_
= core_api::socket::SetKeepAlive::Params::Create(*args_
);
596 EXTENSION_FUNCTION_VALIDATE(params_
.get());
600 void SocketSetKeepAliveFunction::Work() {
602 Socket
* socket
= GetSocket(params_
->socket_id
);
605 if (params_
->delay
.get())
606 delay
= *params_
->delay
;
607 result
= socket
->SetKeepAlive(params_
->enable
, delay
);
609 error_
= kSocketNotFoundError
;
611 SetResult(new base::FundamentalValue(result
));
614 SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
616 SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {}
618 bool SocketSetNoDelayFunction::Prepare() {
619 params_
= core_api::socket::SetNoDelay::Params::Create(*args_
);
620 EXTENSION_FUNCTION_VALIDATE(params_
.get());
624 void SocketSetNoDelayFunction::Work() {
626 Socket
* socket
= GetSocket(params_
->socket_id
);
628 result
= socket
->SetNoDelay(params_
->no_delay
);
630 error_
= kSocketNotFoundError
;
631 SetResult(new base::FundamentalValue(result
));
634 SocketGetInfoFunction::SocketGetInfoFunction() {}
636 SocketGetInfoFunction::~SocketGetInfoFunction() {}
638 bool SocketGetInfoFunction::Prepare() {
639 params_
= core_api::socket::GetInfo::Params::Create(*args_
);
640 EXTENSION_FUNCTION_VALIDATE(params_
.get());
644 void SocketGetInfoFunction::Work() {
645 Socket
* socket
= GetSocket(params_
->socket_id
);
647 error_
= kSocketNotFoundError
;
651 core_api::socket::SocketInfo info
;
652 // This represents what we know about the socket, and does not call through
654 if (socket
->GetSocketType() == Socket::TYPE_TCP
)
655 info
.socket_type
= extensions::core_api::socket::SOCKET_TYPE_TCP
;
657 info
.socket_type
= extensions::core_api::socket::SOCKET_TYPE_UDP
;
658 info
.connected
= socket
->IsConnected();
660 // Grab the peer address as known by the OS. This and the call below will
661 // always succeed while the socket is connected, even if the socket has
662 // been remotely closed by the peer; only reading the socket will reveal
663 // that it should be closed locally.
664 net::IPEndPoint peerAddress
;
665 if (socket
->GetPeerAddress(&peerAddress
)) {
666 info
.peer_address
.reset(new std::string(peerAddress
.ToStringWithoutPort()));
667 info
.peer_port
.reset(new int(peerAddress
.port()));
670 // Grab the local address as known by the OS.
671 net::IPEndPoint localAddress
;
672 if (socket
->GetLocalAddress(&localAddress
)) {
673 info
.local_address
.reset(
674 new std::string(localAddress
.ToStringWithoutPort()));
675 info
.local_port
.reset(new int(localAddress
.port()));
678 SetResult(info
.ToValue().release());
681 bool SocketGetNetworkListFunction::RunAsync() {
682 content::BrowserThread::PostTask(
683 content::BrowserThread::FILE,
685 base::Bind(&SocketGetNetworkListFunction::GetNetworkListOnFileThread
,
690 void SocketGetNetworkListFunction::GetNetworkListOnFileThread() {
691 net::NetworkInterfaceList interface_list
;
692 if (GetNetworkList(&interface_list
,
693 net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES
)) {
694 content::BrowserThread::PostTask(
695 content::BrowserThread::UI
,
697 base::Bind(&SocketGetNetworkListFunction::SendResponseOnUIThread
,
703 content::BrowserThread::PostTask(
704 content::BrowserThread::UI
,
706 base::Bind(&SocketGetNetworkListFunction::HandleGetNetworkListError
,
710 void SocketGetNetworkListFunction::HandleGetNetworkListError() {
711 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
712 error_
= kNetworkListError
;
716 void SocketGetNetworkListFunction::SendResponseOnUIThread(
717 const net::NetworkInterfaceList
& interface_list
) {
718 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
720 std::vector
<linked_ptr
<core_api::socket::NetworkInterface
> > create_arg
;
721 create_arg
.reserve(interface_list
.size());
722 for (net::NetworkInterfaceList::const_iterator i
= interface_list
.begin();
723 i
!= interface_list
.end();
725 linked_ptr
<core_api::socket::NetworkInterface
> info
=
726 make_linked_ptr(new core_api::socket::NetworkInterface
);
727 info
->name
= i
->name
;
728 info
->address
= net::IPAddressToString(i
->address
);
729 info
->prefix_length
= i
->prefix_length
;
730 create_arg
.push_back(info
);
733 results_
= core_api::socket::GetNetworkList::Results::Create(create_arg
);
737 SocketJoinGroupFunction::SocketJoinGroupFunction() {}
739 SocketJoinGroupFunction::~SocketJoinGroupFunction() {}
741 bool SocketJoinGroupFunction::Prepare() {
742 params_
= core_api::socket::JoinGroup::Params::Create(*args_
);
743 EXTENSION_FUNCTION_VALIDATE(params_
.get());
747 void SocketJoinGroupFunction::Work() {
749 Socket
* socket
= GetSocket(params_
->socket_id
);
751 error_
= kSocketNotFoundError
;
752 SetResult(new base::FundamentalValue(result
));
756 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
757 error_
= kMulticastSocketTypeError
;
758 SetResult(new base::FundamentalValue(result
));
762 SocketPermission::CheckParam
param(
763 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
767 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
768 APIPermission::kSocket
, ¶m
)) {
769 error_
= kPermissionError
;
770 SetResult(new base::FundamentalValue(result
));
774 result
= static_cast<UDPSocket
*>(socket
)->JoinGroup(params_
->address
);
776 error_
= net::ErrorToString(result
);
778 SetResult(new base::FundamentalValue(result
));
781 SocketLeaveGroupFunction::SocketLeaveGroupFunction() {}
783 SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {}
785 bool SocketLeaveGroupFunction::Prepare() {
786 params_
= core_api::socket::LeaveGroup::Params::Create(*args_
);
787 EXTENSION_FUNCTION_VALIDATE(params_
.get());
791 void SocketLeaveGroupFunction::Work() {
793 Socket
* socket
= GetSocket(params_
->socket_id
);
796 error_
= kSocketNotFoundError
;
797 SetResult(new base::FundamentalValue(result
));
801 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
802 error_
= kMulticastSocketTypeError
;
803 SetResult(new base::FundamentalValue(result
));
807 SocketPermission::CheckParam
param(
808 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
811 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
812 APIPermission::kSocket
, ¶m
)) {
813 error_
= kPermissionError
;
814 SetResult(new base::FundamentalValue(result
));
818 result
= static_cast<UDPSocket
*>(socket
)->LeaveGroup(params_
->address
);
820 error_
= net::ErrorToString(result
);
821 SetResult(new base::FundamentalValue(result
));
824 SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {}
826 SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {}
828 bool SocketSetMulticastTimeToLiveFunction::Prepare() {
829 params_
= core_api::socket::SetMulticastTimeToLive::Params::Create(*args_
);
830 EXTENSION_FUNCTION_VALIDATE(params_
.get());
833 void SocketSetMulticastTimeToLiveFunction::Work() {
835 Socket
* socket
= GetSocket(params_
->socket_id
);
837 error_
= kSocketNotFoundError
;
838 SetResult(new base::FundamentalValue(result
));
842 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
843 error_
= kMulticastSocketTypeError
;
844 SetResult(new base::FundamentalValue(result
));
849 static_cast<UDPSocket
*>(socket
)->SetMulticastTimeToLive(params_
->ttl
);
851 error_
= net::ErrorToString(result
);
852 SetResult(new base::FundamentalValue(result
));
855 SocketSetMulticastLoopbackModeFunction::
856 SocketSetMulticastLoopbackModeFunction() {}
858 SocketSetMulticastLoopbackModeFunction::
859 ~SocketSetMulticastLoopbackModeFunction() {}
861 bool SocketSetMulticastLoopbackModeFunction::Prepare() {
862 params_
= core_api::socket::SetMulticastLoopbackMode::Params::Create(*args_
);
863 EXTENSION_FUNCTION_VALIDATE(params_
.get());
867 void SocketSetMulticastLoopbackModeFunction::Work() {
869 Socket
* socket
= GetSocket(params_
->socket_id
);
871 error_
= kSocketNotFoundError
;
872 SetResult(new base::FundamentalValue(result
));
876 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
877 error_
= kMulticastSocketTypeError
;
878 SetResult(new base::FundamentalValue(result
));
882 result
= static_cast<UDPSocket
*>(socket
)
883 ->SetMulticastLoopbackMode(params_
->enabled
);
885 error_
= net::ErrorToString(result
);
886 SetResult(new base::FundamentalValue(result
));
889 SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {}
891 SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {}
893 bool SocketGetJoinedGroupsFunction::Prepare() {
894 params_
= core_api::socket::GetJoinedGroups::Params::Create(*args_
);
895 EXTENSION_FUNCTION_VALIDATE(params_
.get());
899 void SocketGetJoinedGroupsFunction::Work() {
901 Socket
* socket
= GetSocket(params_
->socket_id
);
903 error_
= kSocketNotFoundError
;
904 SetResult(new base::FundamentalValue(result
));
908 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
909 error_
= kMulticastSocketTypeError
;
910 SetResult(new base::FundamentalValue(result
));
914 SocketPermission::CheckParam
param(
915 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
918 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
919 APIPermission::kSocket
, ¶m
)) {
920 error_
= kPermissionError
;
921 SetResult(new base::FundamentalValue(result
));
925 base::ListValue
* values
= new base::ListValue();
926 values
->AppendStrings((std::vector
<std::string
>&)static_cast<UDPSocket
*>(
927 socket
)->GetJoinedGroups());
931 SocketSecureFunction::SocketSecureFunction() {
934 SocketSecureFunction::~SocketSecureFunction() {
937 bool SocketSecureFunction::Prepare() {
938 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
939 params_
= core_api::socket::Secure::Params::Create(*args_
);
940 EXTENSION_FUNCTION_VALIDATE(params_
.get());
941 url_request_getter_
= browser_context()->GetRequestContext();
945 // Override the regular implementation, which would call AsyncWorkCompleted
946 // immediately after Work().
947 void SocketSecureFunction::AsyncWorkStart() {
948 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
950 Socket
* socket
= GetSocket(params_
->socket_id
);
952 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
953 error_
= kSocketNotFoundError
;
954 AsyncWorkCompleted();
958 // Make sure that the socket is a TCP client socket.
959 if (socket
->GetSocketType() != Socket::TYPE_TCP
||
960 static_cast<TCPSocket
*>(socket
)->ClientStream() == NULL
) {
961 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
962 error_
= kSecureSocketTypeError
;
963 AsyncWorkCompleted();
967 if (!socket
->IsConnected()) {
968 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
969 error_
= kSocketNotConnectedError
;
970 AsyncWorkCompleted();
974 net::URLRequestContext
* url_request_context
=
975 url_request_getter_
->GetURLRequestContext();
977 TLSSocket::UpgradeSocketToTLS(
979 url_request_context
->ssl_config_service(),
980 url_request_context
->cert_verifier(),
981 url_request_context
->transport_security_state(),
983 params_
->options
.get(),
984 base::Bind(&SocketSecureFunction::TlsConnectDone
, this));
987 void SocketSecureFunction::TlsConnectDone(scoped_ptr
<TLSSocket
> socket
,
989 // if an error occurred, socket MUST be NULL.
990 DCHECK(result
== net::OK
|| socket
== NULL
);
992 if (socket
&& result
== net::OK
) {
993 ReplaceSocket(params_
->socket_id
, socket
.release());
995 RemoveSocket(params_
->socket_id
);
996 error_
= net::ErrorToString(result
);
999 results_
= core_api::socket::Secure::Results::Create(result
);
1000 AsyncWorkCompleted();
1003 } // namespace extensions