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 uint16 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_
));
196 EXTENSION_FUNCTION_VALIDATE(
197 args_
->GetInteger(2, &port
) && port
>= 0 && port
<= 65535);
198 port_
= static_cast<uint16
>(port
);
202 void SocketConnectFunction::AsyncWorkStart() {
203 Socket
* socket
= GetSocket(socket_id_
);
205 error_
= kSocketNotFoundError
;
206 SetResult(new base::FundamentalValue(-1));
207 AsyncWorkCompleted();
211 socket
->set_hostname(hostname_
);
213 SocketPermissionRequest::OperationType operation_type
;
214 switch (socket
->GetSocketType()) {
215 case Socket::TYPE_TCP
:
216 operation_type
= SocketPermissionRequest::TCP_CONNECT
;
218 case Socket::TYPE_UDP
:
219 operation_type
= SocketPermissionRequest::UDP_SEND_TO
;
222 NOTREACHED() << "Unknown socket type.";
223 operation_type
= SocketPermissionRequest::NONE
;
227 SocketPermission::CheckParam
param(operation_type
, hostname_
, port_
);
228 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
229 APIPermission::kSocket
, ¶m
)) {
230 error_
= kPermissionError
;
231 SetResult(new base::FundamentalValue(-1));
232 AsyncWorkCompleted();
236 StartDnsLookup(hostname_
);
239 void SocketConnectFunction::AfterDnsLookup(int lookup_result
) {
240 if (lookup_result
== net::OK
) {
243 SetResult(new base::FundamentalValue(lookup_result
));
244 AsyncWorkCompleted();
248 void SocketConnectFunction::StartConnect() {
249 Socket
* socket
= GetSocket(socket_id_
);
251 error_
= kSocketNotFoundError
;
252 SetResult(new base::FundamentalValue(-1));
253 AsyncWorkCompleted();
257 socket
->Connect(resolved_address_
,
259 base::Bind(&SocketConnectFunction::OnConnect
, this));
262 void SocketConnectFunction::OnConnect(int result
) {
263 SetResult(new base::FundamentalValue(result
));
264 AsyncWorkCompleted();
267 bool SocketDisconnectFunction::Prepare() {
268 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
272 void SocketDisconnectFunction::Work() {
273 Socket
* socket
= GetSocket(socket_id_
);
275 socket
->Disconnect();
277 error_
= kSocketNotFoundError
;
278 SetResult(base::Value::CreateNullValue());
281 bool SocketBindFunction::Prepare() {
282 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
283 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(1, &address_
));
285 EXTENSION_FUNCTION_VALIDATE(
286 args_
->GetInteger(2, &port
) && port
>= 0 && port
<= 65535);
287 port_
= static_cast<uint16
>(port
);
291 void SocketBindFunction::Work() {
293 Socket
* socket
= GetSocket(socket_id_
);
296 error_
= kSocketNotFoundError
;
297 SetResult(new base::FundamentalValue(result
));
301 if (socket
->GetSocketType() == Socket::TYPE_UDP
) {
302 SocketPermission::CheckParam
param(
303 SocketPermissionRequest::UDP_BIND
, address_
, port_
);
304 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
305 APIPermission::kSocket
, ¶m
)) {
306 error_
= kPermissionError
;
307 SetResult(new base::FundamentalValue(result
));
310 } else if (socket
->GetSocketType() == Socket::TYPE_TCP
) {
311 error_
= kTCPSocketBindError
;
312 SetResult(new base::FundamentalValue(result
));
316 result
= socket
->Bind(address_
, port_
);
317 SetResult(new base::FundamentalValue(result
));
320 SocketListenFunction::SocketListenFunction() {}
322 SocketListenFunction::~SocketListenFunction() {}
324 bool SocketListenFunction::Prepare() {
325 params_
= core_api::socket::Listen::Params::Create(*args_
);
326 EXTENSION_FUNCTION_VALIDATE(params_
.get());
330 void SocketListenFunction::Work() {
333 Socket
* socket
= GetSocket(params_
->socket_id
);
335 SocketPermission::CheckParam
param(
336 SocketPermissionRequest::TCP_LISTEN
, params_
->address
, params_
->port
);
337 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
338 APIPermission::kSocket
, ¶m
)) {
339 error_
= kPermissionError
;
340 SetResult(new base::FundamentalValue(result
));
345 socket
->Listen(params_
->address
,
347 params_
->backlog
.get() ? *params_
->backlog
.get() : 5,
350 error_
= kSocketNotFoundError
;
353 SetResult(new base::FundamentalValue(result
));
356 SocketAcceptFunction::SocketAcceptFunction() {}
358 SocketAcceptFunction::~SocketAcceptFunction() {}
360 bool SocketAcceptFunction::Prepare() {
361 params_
= core_api::socket::Accept::Params::Create(*args_
);
362 EXTENSION_FUNCTION_VALIDATE(params_
.get());
366 void SocketAcceptFunction::AsyncWorkStart() {
367 Socket
* socket
= GetSocket(params_
->socket_id
);
369 socket
->Accept(base::Bind(&SocketAcceptFunction::OnAccept
, this));
371 error_
= kSocketNotFoundError
;
376 void SocketAcceptFunction::OnAccept(int result_code
,
377 net::TCPClientSocket
* socket
) {
378 base::DictionaryValue
* result
= new base::DictionaryValue();
379 result
->SetInteger(kResultCodeKey
, result_code
);
381 Socket
* client_socket
= new TCPSocket(socket
, extension_id(), true);
382 result
->SetInteger(kSocketIdKey
, AddSocket(client_socket
));
386 AsyncWorkCompleted();
389 SocketReadFunction::SocketReadFunction() {}
391 SocketReadFunction::~SocketReadFunction() {}
393 bool SocketReadFunction::Prepare() {
394 params_
= core_api::socket::Read::Params::Create(*args_
);
395 EXTENSION_FUNCTION_VALIDATE(params_
.get());
399 void SocketReadFunction::AsyncWorkStart() {
400 Socket
* socket
= GetSocket(params_
->socket_id
);
402 error_
= kSocketNotFoundError
;
403 OnCompleted(-1, NULL
);
407 socket
->Read(params_
->buffer_size
.get() ? *params_
->buffer_size
.get() : 4096,
408 base::Bind(&SocketReadFunction::OnCompleted
, this));
411 void SocketReadFunction::OnCompleted(int bytes_read
,
412 scoped_refptr
<net::IOBuffer
> io_buffer
) {
413 base::DictionaryValue
* result
= new base::DictionaryValue();
414 result
->SetInteger(kResultCodeKey
, bytes_read
);
415 if (bytes_read
> 0) {
416 result
->Set(kDataKey
,
417 base::BinaryValue::CreateWithCopiedBuffer(io_buffer
->data(),
420 result
->Set(kDataKey
, new base::BinaryValue());
424 AsyncWorkCompleted();
427 SocketWriteFunction::SocketWriteFunction()
428 : socket_id_(0), io_buffer_(NULL
), io_buffer_size_(0) {}
430 SocketWriteFunction::~SocketWriteFunction() {}
432 bool SocketWriteFunction::Prepare() {
433 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
434 base::BinaryValue
* data
= NULL
;
435 EXTENSION_FUNCTION_VALIDATE(args_
->GetBinary(1, &data
));
437 io_buffer_size_
= data
->GetSize();
438 io_buffer_
= new net::WrappedIOBuffer(data
->GetBuffer());
442 void SocketWriteFunction::AsyncWorkStart() {
443 Socket
* socket
= GetSocket(socket_id_
);
446 error_
= kSocketNotFoundError
;
451 socket
->Write(io_buffer_
,
453 base::Bind(&SocketWriteFunction::OnCompleted
, this));
456 void SocketWriteFunction::OnCompleted(int bytes_written
) {
457 base::DictionaryValue
* result
= new base::DictionaryValue();
458 result
->SetInteger(kBytesWrittenKey
, bytes_written
);
461 AsyncWorkCompleted();
464 SocketRecvFromFunction::SocketRecvFromFunction() {}
466 SocketRecvFromFunction::~SocketRecvFromFunction() {}
468 bool SocketRecvFromFunction::Prepare() {
469 params_
= core_api::socket::RecvFrom::Params::Create(*args_
);
470 EXTENSION_FUNCTION_VALIDATE(params_
.get());
474 void SocketRecvFromFunction::AsyncWorkStart() {
475 Socket
* socket
= GetSocket(params_
->socket_id
);
477 error_
= kSocketNotFoundError
;
478 OnCompleted(-1, NULL
, std::string(), 0);
482 socket
->RecvFrom(params_
->buffer_size
.get() ? *params_
->buffer_size
: 4096,
483 base::Bind(&SocketRecvFromFunction::OnCompleted
, this));
486 void SocketRecvFromFunction::OnCompleted(int bytes_read
,
487 scoped_refptr
<net::IOBuffer
> io_buffer
,
488 const std::string
& address
,
490 base::DictionaryValue
* result
= new base::DictionaryValue();
491 result
->SetInteger(kResultCodeKey
, bytes_read
);
492 if (bytes_read
> 0) {
493 result
->Set(kDataKey
,
494 base::BinaryValue::CreateWithCopiedBuffer(io_buffer
->data(),
497 result
->Set(kDataKey
, new base::BinaryValue());
499 result
->SetString(kAddressKey
, address
);
500 result
->SetInteger(kPortKey
, port
);
503 AsyncWorkCompleted();
506 SocketSendToFunction::SocketSendToFunction()
507 : socket_id_(0), io_buffer_(NULL
), io_buffer_size_(0), port_(0) {
510 SocketSendToFunction::~SocketSendToFunction() {}
512 bool SocketSendToFunction::Prepare() {
513 EXTENSION_FUNCTION_VALIDATE(args_
->GetInteger(0, &socket_id_
));
514 base::BinaryValue
* data
= NULL
;
515 EXTENSION_FUNCTION_VALIDATE(args_
->GetBinary(1, &data
));
516 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(2, &hostname_
));
518 EXTENSION_FUNCTION_VALIDATE(
519 args_
->GetInteger(3, &port
) && port
>= 0 && port
<= 65535);
520 port_
= static_cast<uint16
>(port
);
522 io_buffer_size_
= data
->GetSize();
523 io_buffer_
= new net::WrappedIOBuffer(data
->GetBuffer());
527 void SocketSendToFunction::AsyncWorkStart() {
528 Socket
* socket
= GetSocket(socket_id_
);
530 error_
= kSocketNotFoundError
;
531 SetResult(new base::FundamentalValue(-1));
532 AsyncWorkCompleted();
536 if (socket
->GetSocketType() == Socket::TYPE_UDP
) {
537 SocketPermission::CheckParam
param(
538 SocketPermissionRequest::UDP_SEND_TO
, hostname_
, port_
);
539 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
540 APIPermission::kSocket
, ¶m
)) {
541 error_
= kPermissionError
;
542 SetResult(new base::FundamentalValue(-1));
543 AsyncWorkCompleted();
548 StartDnsLookup(hostname_
);
551 void SocketSendToFunction::AfterDnsLookup(int lookup_result
) {
552 if (lookup_result
== net::OK
) {
555 SetResult(new base::FundamentalValue(lookup_result
));
556 AsyncWorkCompleted();
560 void SocketSendToFunction::StartSendTo() {
561 Socket
* socket
= GetSocket(socket_id_
);
563 error_
= kSocketNotFoundError
;
564 SetResult(new base::FundamentalValue(-1));
565 AsyncWorkCompleted();
569 socket
->SendTo(io_buffer_
,
573 base::Bind(&SocketSendToFunction::OnCompleted
, this));
576 void SocketSendToFunction::OnCompleted(int bytes_written
) {
577 base::DictionaryValue
* result
= new base::DictionaryValue();
578 result
->SetInteger(kBytesWrittenKey
, bytes_written
);
581 AsyncWorkCompleted();
584 SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {}
586 SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {}
588 bool SocketSetKeepAliveFunction::Prepare() {
589 params_
= core_api::socket::SetKeepAlive::Params::Create(*args_
);
590 EXTENSION_FUNCTION_VALIDATE(params_
.get());
594 void SocketSetKeepAliveFunction::Work() {
596 Socket
* socket
= GetSocket(params_
->socket_id
);
599 if (params_
->delay
.get())
600 delay
= *params_
->delay
;
601 result
= socket
->SetKeepAlive(params_
->enable
, delay
);
603 error_
= kSocketNotFoundError
;
605 SetResult(new base::FundamentalValue(result
));
608 SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
610 SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {}
612 bool SocketSetNoDelayFunction::Prepare() {
613 params_
= core_api::socket::SetNoDelay::Params::Create(*args_
);
614 EXTENSION_FUNCTION_VALIDATE(params_
.get());
618 void SocketSetNoDelayFunction::Work() {
620 Socket
* socket
= GetSocket(params_
->socket_id
);
622 result
= socket
->SetNoDelay(params_
->no_delay
);
624 error_
= kSocketNotFoundError
;
625 SetResult(new base::FundamentalValue(result
));
628 SocketGetInfoFunction::SocketGetInfoFunction() {}
630 SocketGetInfoFunction::~SocketGetInfoFunction() {}
632 bool SocketGetInfoFunction::Prepare() {
633 params_
= core_api::socket::GetInfo::Params::Create(*args_
);
634 EXTENSION_FUNCTION_VALIDATE(params_
.get());
638 void SocketGetInfoFunction::Work() {
639 Socket
* socket
= GetSocket(params_
->socket_id
);
641 error_
= kSocketNotFoundError
;
645 core_api::socket::SocketInfo info
;
646 // This represents what we know about the socket, and does not call through
648 if (socket
->GetSocketType() == Socket::TYPE_TCP
)
649 info
.socket_type
= extensions::core_api::socket::SOCKET_TYPE_TCP
;
651 info
.socket_type
= extensions::core_api::socket::SOCKET_TYPE_UDP
;
652 info
.connected
= socket
->IsConnected();
654 // Grab the peer address as known by the OS. This and the call below will
655 // always succeed while the socket is connected, even if the socket has
656 // been remotely closed by the peer; only reading the socket will reveal
657 // that it should be closed locally.
658 net::IPEndPoint peerAddress
;
659 if (socket
->GetPeerAddress(&peerAddress
)) {
660 info
.peer_address
.reset(new std::string(peerAddress
.ToStringWithoutPort()));
661 info
.peer_port
.reset(new int(peerAddress
.port()));
664 // Grab the local address as known by the OS.
665 net::IPEndPoint localAddress
;
666 if (socket
->GetLocalAddress(&localAddress
)) {
667 info
.local_address
.reset(
668 new std::string(localAddress
.ToStringWithoutPort()));
669 info
.local_port
.reset(new int(localAddress
.port()));
672 SetResult(info
.ToValue().release());
675 bool SocketGetNetworkListFunction::RunAsync() {
676 content::BrowserThread::PostTask(
677 content::BrowserThread::FILE,
679 base::Bind(&SocketGetNetworkListFunction::GetNetworkListOnFileThread
,
684 void SocketGetNetworkListFunction::GetNetworkListOnFileThread() {
685 net::NetworkInterfaceList interface_list
;
686 if (GetNetworkList(&interface_list
,
687 net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES
)) {
688 content::BrowserThread::PostTask(
689 content::BrowserThread::UI
,
691 base::Bind(&SocketGetNetworkListFunction::SendResponseOnUIThread
,
697 content::BrowserThread::PostTask(
698 content::BrowserThread::UI
,
700 base::Bind(&SocketGetNetworkListFunction::HandleGetNetworkListError
,
704 void SocketGetNetworkListFunction::HandleGetNetworkListError() {
705 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
706 error_
= kNetworkListError
;
710 void SocketGetNetworkListFunction::SendResponseOnUIThread(
711 const net::NetworkInterfaceList
& interface_list
) {
712 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
714 std::vector
<linked_ptr
<core_api::socket::NetworkInterface
> > create_arg
;
715 create_arg
.reserve(interface_list
.size());
716 for (net::NetworkInterfaceList::const_iterator i
= interface_list
.begin();
717 i
!= interface_list
.end();
719 linked_ptr
<core_api::socket::NetworkInterface
> info
=
720 make_linked_ptr(new core_api::socket::NetworkInterface
);
721 info
->name
= i
->name
;
722 info
->address
= net::IPAddressToString(i
->address
);
723 info
->prefix_length
= i
->prefix_length
;
724 create_arg
.push_back(info
);
727 results_
= core_api::socket::GetNetworkList::Results::Create(create_arg
);
731 SocketJoinGroupFunction::SocketJoinGroupFunction() {}
733 SocketJoinGroupFunction::~SocketJoinGroupFunction() {}
735 bool SocketJoinGroupFunction::Prepare() {
736 params_
= core_api::socket::JoinGroup::Params::Create(*args_
);
737 EXTENSION_FUNCTION_VALIDATE(params_
.get());
741 void SocketJoinGroupFunction::Work() {
743 Socket
* socket
= GetSocket(params_
->socket_id
);
745 error_
= kSocketNotFoundError
;
746 SetResult(new base::FundamentalValue(result
));
750 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
751 error_
= kMulticastSocketTypeError
;
752 SetResult(new base::FundamentalValue(result
));
756 SocketPermission::CheckParam
param(
757 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
761 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
762 APIPermission::kSocket
, ¶m
)) {
763 error_
= kPermissionError
;
764 SetResult(new base::FundamentalValue(result
));
768 result
= static_cast<UDPSocket
*>(socket
)->JoinGroup(params_
->address
);
770 error_
= net::ErrorToString(result
);
772 SetResult(new base::FundamentalValue(result
));
775 SocketLeaveGroupFunction::SocketLeaveGroupFunction() {}
777 SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {}
779 bool SocketLeaveGroupFunction::Prepare() {
780 params_
= core_api::socket::LeaveGroup::Params::Create(*args_
);
781 EXTENSION_FUNCTION_VALIDATE(params_
.get());
785 void SocketLeaveGroupFunction::Work() {
787 Socket
* socket
= GetSocket(params_
->socket_id
);
790 error_
= kSocketNotFoundError
;
791 SetResult(new base::FundamentalValue(result
));
795 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
796 error_
= kMulticastSocketTypeError
;
797 SetResult(new base::FundamentalValue(result
));
801 SocketPermission::CheckParam
param(
802 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
805 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
806 APIPermission::kSocket
, ¶m
)) {
807 error_
= kPermissionError
;
808 SetResult(new base::FundamentalValue(result
));
812 result
= static_cast<UDPSocket
*>(socket
)->LeaveGroup(params_
->address
);
814 error_
= net::ErrorToString(result
);
815 SetResult(new base::FundamentalValue(result
));
818 SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {}
820 SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {}
822 bool SocketSetMulticastTimeToLiveFunction::Prepare() {
823 params_
= core_api::socket::SetMulticastTimeToLive::Params::Create(*args_
);
824 EXTENSION_FUNCTION_VALIDATE(params_
.get());
827 void SocketSetMulticastTimeToLiveFunction::Work() {
829 Socket
* socket
= GetSocket(params_
->socket_id
);
831 error_
= kSocketNotFoundError
;
832 SetResult(new base::FundamentalValue(result
));
836 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
837 error_
= kMulticastSocketTypeError
;
838 SetResult(new base::FundamentalValue(result
));
843 static_cast<UDPSocket
*>(socket
)->SetMulticastTimeToLive(params_
->ttl
);
845 error_
= net::ErrorToString(result
);
846 SetResult(new base::FundamentalValue(result
));
849 SocketSetMulticastLoopbackModeFunction::
850 SocketSetMulticastLoopbackModeFunction() {}
852 SocketSetMulticastLoopbackModeFunction::
853 ~SocketSetMulticastLoopbackModeFunction() {}
855 bool SocketSetMulticastLoopbackModeFunction::Prepare() {
856 params_
= core_api::socket::SetMulticastLoopbackMode::Params::Create(*args_
);
857 EXTENSION_FUNCTION_VALIDATE(params_
.get());
861 void SocketSetMulticastLoopbackModeFunction::Work() {
863 Socket
* socket
= GetSocket(params_
->socket_id
);
865 error_
= kSocketNotFoundError
;
866 SetResult(new base::FundamentalValue(result
));
870 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
871 error_
= kMulticastSocketTypeError
;
872 SetResult(new base::FundamentalValue(result
));
876 result
= static_cast<UDPSocket
*>(socket
)
877 ->SetMulticastLoopbackMode(params_
->enabled
);
879 error_
= net::ErrorToString(result
);
880 SetResult(new base::FundamentalValue(result
));
883 SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {}
885 SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {}
887 bool SocketGetJoinedGroupsFunction::Prepare() {
888 params_
= core_api::socket::GetJoinedGroups::Params::Create(*args_
);
889 EXTENSION_FUNCTION_VALIDATE(params_
.get());
893 void SocketGetJoinedGroupsFunction::Work() {
895 Socket
* socket
= GetSocket(params_
->socket_id
);
897 error_
= kSocketNotFoundError
;
898 SetResult(new base::FundamentalValue(result
));
902 if (socket
->GetSocketType() != Socket::TYPE_UDP
) {
903 error_
= kMulticastSocketTypeError
;
904 SetResult(new base::FundamentalValue(result
));
908 SocketPermission::CheckParam
param(
909 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP
,
912 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
913 APIPermission::kSocket
, ¶m
)) {
914 error_
= kPermissionError
;
915 SetResult(new base::FundamentalValue(result
));
919 base::ListValue
* values
= new base::ListValue();
920 values
->AppendStrings((std::vector
<std::string
>&)static_cast<UDPSocket
*>(
921 socket
)->GetJoinedGroups());
925 SocketSecureFunction::SocketSecureFunction() {
928 SocketSecureFunction::~SocketSecureFunction() {
931 bool SocketSecureFunction::Prepare() {
932 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
933 params_
= core_api::socket::Secure::Params::Create(*args_
);
934 EXTENSION_FUNCTION_VALIDATE(params_
.get());
935 url_request_getter_
= browser_context()->GetRequestContext();
939 // Override the regular implementation, which would call AsyncWorkCompleted
940 // immediately after Work().
941 void SocketSecureFunction::AsyncWorkStart() {
942 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
944 Socket
* socket
= GetSocket(params_
->socket_id
);
946 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
947 error_
= kSocketNotFoundError
;
948 AsyncWorkCompleted();
952 // Make sure that the socket is a TCP client socket.
953 if (socket
->GetSocketType() != Socket::TYPE_TCP
||
954 static_cast<TCPSocket
*>(socket
)->ClientStream() == NULL
) {
955 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
956 error_
= kSecureSocketTypeError
;
957 AsyncWorkCompleted();
961 if (!socket
->IsConnected()) {
962 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT
));
963 error_
= kSocketNotConnectedError
;
964 AsyncWorkCompleted();
968 net::URLRequestContext
* url_request_context
=
969 url_request_getter_
->GetURLRequestContext();
971 TLSSocket::UpgradeSocketToTLS(
973 url_request_context
->ssl_config_service(),
974 url_request_context
->cert_verifier(),
975 url_request_context
->transport_security_state(),
977 params_
->options
.get(),
978 base::Bind(&SocketSecureFunction::TlsConnectDone
, this));
981 void SocketSecureFunction::TlsConnectDone(scoped_ptr
<TLSSocket
> socket
,
983 // if an error occurred, socket MUST be NULL.
984 DCHECK(result
== net::OK
|| socket
== NULL
);
986 if (socket
&& result
== net::OK
) {
987 ReplaceSocket(params_
->socket_id
, socket
.release());
989 RemoveSocket(params_
->socket_id
);
990 error_
= net::ErrorToString(result
);
993 results_
= core_api::socket::Secure::Results::Create(result
);
994 AsyncWorkCompleted();
997 } // namespace extensions