Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / browser / api / socket / socket_api.cc
blob456d33ebcc0ca663b42eca2eb0121274cd9ea584
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"
7 #include <vector>
9 #include "base/bind.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/network_interfaces.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"
33 #endif // OS_CHROMEOS
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";
61 #endif // OS_CHROMEOS
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,
89 Socket* socket) {
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,
102 int socket_id,
103 Socket* socket) {
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();
112 return;
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));
123 return;
125 #endif
126 AsyncWorkCompleted();
129 #if defined(OS_CHROMEOS)
131 void SocketAsyncApiFunction::OpenFirewallHoleOnUIThread(
132 AppFirewallHole::PortType type,
133 uint16_t port,
134 int socket_id) {
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(
147 int socket_id,
148 scoped_ptr<AppFirewallHole, BrowserThread::DeleteOnUIThread> hole) {
149 DCHECK_CURRENTLY_ON(BrowserThread::IO);
150 if (!hole) {
151 error_ = kFirewallFailure;
152 SetResult(new base::FundamentalValue(-1));
153 AsyncWorkCompleted();
154 return;
157 Socket* socket = GetSocket(socket_id);
158 if (!socket) {
159 error_ = kSocketNotFoundError;
160 SetResult(new base::FundamentalValue(-1));
161 AsyncWorkCompleted();
162 return;
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())
180 return false;
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());
207 } else {
208 error_ = kDnsLookupFailedError;
210 AfterDnsLookup(resolve_result);
213 SocketCreateFunction::SocketCreateFunction()
214 : socket_type_(kSocketTypeInvalid) {}
216 SocketCreateFunction::~SocketCreateFunction() {}
218 bool SocketCreateFunction::Prepare() {
219 params_ = api::socket::Create::Params::Create(*args_);
220 EXTENSION_FUNCTION_VALIDATE(params_.get());
222 switch (params_->type) {
223 case extensions::api::socket::SOCKET_TYPE_TCP:
224 socket_type_ = kSocketTypeTCP;
225 break;
226 case extensions::api::socket::SOCKET_TYPE_UDP:
227 socket_type_ = kSocketTypeUDP;
228 break;
229 case extensions::api::socket::SOCKET_TYPE_NONE:
230 NOTREACHED();
231 break;
234 return true;
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());
244 DCHECK(socket);
246 base::DictionaryValue* result = new base::DictionaryValue();
247 result->SetInteger(kSocketIdKey, AddSocket(socket));
248 SetResult(result);
251 bool SocketDestroyFunction::Prepare() {
252 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
253 return true;
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_));
267 int port;
268 EXTENSION_FUNCTION_VALIDATE(
269 args_->GetInteger(2, &port) && port >= 0 && port <= 65535);
270 port_ = static_cast<uint16>(port);
271 return true;
274 void SocketConnectFunction::AsyncWorkStart() {
275 Socket* socket = GetSocket(socket_id_);
276 if (!socket) {
277 error_ = kSocketNotFoundError;
278 SetResult(new base::FundamentalValue(-1));
279 AsyncWorkCompleted();
280 return;
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;
289 break;
290 case Socket::TYPE_UDP:
291 operation_type = SocketPermissionRequest::UDP_SEND_TO;
292 break;
293 default:
294 NOTREACHED() << "Unknown socket type.";
295 operation_type = SocketPermissionRequest::NONE;
296 break;
299 SocketPermission::CheckParam param(operation_type, hostname_, port_);
300 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
301 APIPermission::kSocket, &param)) {
302 error_ = kPermissionError;
303 SetResult(new base::FundamentalValue(-1));
304 AsyncWorkCompleted();
305 return;
308 StartDnsLookup(net::HostPortPair(hostname_, port_));
311 void SocketConnectFunction::AfterDnsLookup(int lookup_result) {
312 if (lookup_result == net::OK) {
313 StartConnect();
314 } else {
315 SetResult(new base::FundamentalValue(lookup_result));
316 AsyncWorkCompleted();
320 void SocketConnectFunction::StartConnect() {
321 Socket* socket = GetSocket(socket_id_);
322 if (!socket) {
323 error_ = kSocketNotFoundError;
324 SetResult(new base::FundamentalValue(-1));
325 AsyncWorkCompleted();
326 return;
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_));
340 return true;
343 void SocketDisconnectFunction::Work() {
344 Socket* socket = GetSocket(socket_id_);
345 if (socket)
346 socket->Disconnect();
347 else
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_));
355 int port;
356 EXTENSION_FUNCTION_VALIDATE(
357 args_->GetInteger(2, &port) && port >= 0 && port <= 65535);
358 port_ = static_cast<uint16>(port);
359 return true;
362 void SocketBindFunction::AsyncWorkStart() {
363 Socket* socket = GetSocket(socket_id_);
364 if (!socket) {
365 error_ = kSocketNotFoundError;
366 SetResult(new base::FundamentalValue(-1));
367 AsyncWorkCompleted();
368 return;
371 if (socket->GetSocketType() == Socket::TYPE_TCP) {
372 error_ = kTCPSocketBindError;
373 SetResult(new base::FundamentalValue(-1));
374 AsyncWorkCompleted();
375 return;
378 CHECK(socket->GetSocketType() == Socket::TYPE_UDP);
379 SocketPermission::CheckParam param(SocketPermissionRequest::UDP_BIND,
380 address_, port_);
381 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
382 APIPermission::kSocket, &param)) {
383 error_ = kPermissionError;
384 SetResult(new base::FundamentalValue(-1));
385 AsyncWorkCompleted();
386 return;
389 int result = socket->Bind(address_, port_);
390 SetResult(new base::FundamentalValue(result));
391 if (result != net::OK) {
392 AsyncWorkCompleted();
393 return;
396 OpenFirewallHole(address_, socket_id_, socket);
399 SocketListenFunction::SocketListenFunction() {}
401 SocketListenFunction::~SocketListenFunction() {}
403 bool SocketListenFunction::Prepare() {
404 params_ = api::socket::Listen::Params::Create(*args_);
405 EXTENSION_FUNCTION_VALIDATE(params_.get());
406 return true;
409 void SocketListenFunction::AsyncWorkStart() {
410 Socket* socket = GetSocket(params_->socket_id);
411 if (!socket) {
412 error_ = kSocketNotFoundError;
413 SetResult(new base::FundamentalValue(-1));
414 AsyncWorkCompleted();
415 return;
418 SocketPermission::CheckParam param(SocketPermissionRequest::TCP_LISTEN,
419 params_->address, params_->port);
420 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
421 APIPermission::kSocket, &param)) {
422 error_ = kPermissionError;
423 SetResult(new base::FundamentalValue(-1));
424 AsyncWorkCompleted();
425 return;
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();
434 return;
437 OpenFirewallHole(params_->address, params_->socket_id, socket);
440 SocketAcceptFunction::SocketAcceptFunction() {}
442 SocketAcceptFunction::~SocketAcceptFunction() {}
444 bool SocketAcceptFunction::Prepare() {
445 params_ = api::socket::Accept::Params::Create(*args_);
446 EXTENSION_FUNCTION_VALIDATE(params_.get());
447 return true;
450 void SocketAcceptFunction::AsyncWorkStart() {
451 Socket* socket = GetSocket(params_->socket_id);
452 if (socket) {
453 socket->Accept(base::Bind(&SocketAcceptFunction::OnAccept, this));
454 } else {
455 error_ = kSocketNotFoundError;
456 OnAccept(-1, NULL);
460 void SocketAcceptFunction::OnAccept(int result_code,
461 net::TCPClientSocket* socket) {
462 base::DictionaryValue* result = new base::DictionaryValue();
463 result->SetInteger(kResultCodeKey, result_code);
464 if (socket) {
465 Socket* client_socket = new TCPSocket(socket, extension_id(), true);
466 result->SetInteger(kSocketIdKey, AddSocket(client_socket));
468 SetResult(result);
470 AsyncWorkCompleted();
473 SocketReadFunction::SocketReadFunction() {}
475 SocketReadFunction::~SocketReadFunction() {}
477 bool SocketReadFunction::Prepare() {
478 params_ = api::socket::Read::Params::Create(*args_);
479 EXTENSION_FUNCTION_VALIDATE(params_.get());
480 return true;
483 void SocketReadFunction::AsyncWorkStart() {
484 Socket* socket = GetSocket(params_->socket_id);
485 if (!socket) {
486 error_ = kSocketNotFoundError;
487 OnCompleted(-1, NULL);
488 return;
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(),
502 bytes_read));
503 } else {
504 result->Set(kDataKey, new base::BinaryValue());
506 SetResult(result);
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());
523 return true;
526 void SocketWriteFunction::AsyncWorkStart() {
527 Socket* socket = GetSocket(socket_id_);
529 if (!socket) {
530 error_ = kSocketNotFoundError;
531 OnCompleted(-1);
532 return;
535 socket->Write(io_buffer_,
536 io_buffer_size_,
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);
543 SetResult(result);
545 AsyncWorkCompleted();
548 SocketRecvFromFunction::SocketRecvFromFunction() {}
550 SocketRecvFromFunction::~SocketRecvFromFunction() {}
552 bool SocketRecvFromFunction::Prepare() {
553 params_ = api::socket::RecvFrom::Params::Create(*args_);
554 EXTENSION_FUNCTION_VALIDATE(params_.get());
555 return true;
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);
563 return;
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,
573 uint16 port) {
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(),
579 bytes_read));
580 } else {
581 result->Set(kDataKey, new base::BinaryValue());
583 result->SetString(kAddressKey, address);
584 result->SetInteger(kPortKey, port);
585 SetResult(result);
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_));
601 int port;
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());
608 return true;
611 void SocketSendToFunction::AsyncWorkStart() {
612 Socket* socket = GetSocket(socket_id_);
613 if (!socket) {
614 error_ = kSocketNotFoundError;
615 SetResult(new base::FundamentalValue(-1));
616 AsyncWorkCompleted();
617 return;
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, &param)) {
625 error_ = kPermissionError;
626 SetResult(new base::FundamentalValue(-1));
627 AsyncWorkCompleted();
628 return;
632 StartDnsLookup(net::HostPortPair(hostname_, port_));
635 void SocketSendToFunction::AfterDnsLookup(int lookup_result) {
636 if (lookup_result == net::OK) {
637 StartSendTo();
638 } else {
639 SetResult(new base::FundamentalValue(lookup_result));
640 AsyncWorkCompleted();
644 void SocketSendToFunction::StartSendTo() {
645 Socket* socket = GetSocket(socket_id_);
646 if (!socket) {
647 error_ = kSocketNotFoundError;
648 SetResult(new base::FundamentalValue(-1));
649 AsyncWorkCompleted();
650 return;
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);
660 SetResult(result);
662 AsyncWorkCompleted();
665 SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {}
667 SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {}
669 bool SocketSetKeepAliveFunction::Prepare() {
670 params_ = api::socket::SetKeepAlive::Params::Create(*args_);
671 EXTENSION_FUNCTION_VALIDATE(params_.get());
672 return true;
675 void SocketSetKeepAliveFunction::Work() {
676 bool result = false;
677 Socket* socket = GetSocket(params_->socket_id);
678 if (socket) {
679 int delay = 0;
680 if (params_->delay.get())
681 delay = *params_->delay;
682 result = socket->SetKeepAlive(params_->enable, delay);
683 } else {
684 error_ = kSocketNotFoundError;
686 SetResult(new base::FundamentalValue(result));
689 SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
691 SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {}
693 bool SocketSetNoDelayFunction::Prepare() {
694 params_ = api::socket::SetNoDelay::Params::Create(*args_);
695 EXTENSION_FUNCTION_VALIDATE(params_.get());
696 return true;
699 void SocketSetNoDelayFunction::Work() {
700 bool result = false;
701 Socket* socket = GetSocket(params_->socket_id);
702 if (socket)
703 result = socket->SetNoDelay(params_->no_delay);
704 else
705 error_ = kSocketNotFoundError;
706 SetResult(new base::FundamentalValue(result));
709 SocketGetInfoFunction::SocketGetInfoFunction() {}
711 SocketGetInfoFunction::~SocketGetInfoFunction() {}
713 bool SocketGetInfoFunction::Prepare() {
714 params_ = api::socket::GetInfo::Params::Create(*args_);
715 EXTENSION_FUNCTION_VALIDATE(params_.get());
716 return true;
719 void SocketGetInfoFunction::Work() {
720 Socket* socket = GetSocket(params_->socket_id);
721 if (!socket) {
722 error_ = kSocketNotFoundError;
723 return;
726 api::socket::SocketInfo info;
727 // This represents what we know about the socket, and does not call through
728 // to the system.
729 if (socket->GetSocketType() == Socket::TYPE_TCP)
730 info.socket_type = extensions::api::socket::SOCKET_TYPE_TCP;
731 else
732 info.socket_type = extensions::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,
760 this));
761 return true;
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,
771 interface_list));
772 return;
775 BrowserThread::PostTask(
776 BrowserThread::UI, FROM_HERE,
777 base::Bind(&SocketGetNetworkListFunction::HandleGetNetworkListError,
778 this));
781 void SocketGetNetworkListFunction::HandleGetNetworkListError() {
782 DCHECK_CURRENTLY_ON(BrowserThread::UI);
783 error_ = kNetworkListError;
784 SendResponse(false);
787 void SocketGetNetworkListFunction::SendResponseOnUIThread(
788 const net::NetworkInterfaceList& interface_list) {
789 DCHECK_CURRENTLY_ON(BrowserThread::UI);
791 std::vector<linked_ptr<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();
795 ++i) {
796 linked_ptr<api::socket::NetworkInterface> info =
797 make_linked_ptr(new 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_ = api::socket::GetNetworkList::Results::Create(create_arg);
805 SendResponse(true);
808 SocketJoinGroupFunction::SocketJoinGroupFunction() {}
810 SocketJoinGroupFunction::~SocketJoinGroupFunction() {}
812 bool SocketJoinGroupFunction::Prepare() {
813 params_ = api::socket::JoinGroup::Params::Create(*args_);
814 EXTENSION_FUNCTION_VALIDATE(params_.get());
815 return true;
818 void SocketJoinGroupFunction::Work() {
819 int result = -1;
820 Socket* socket = GetSocket(params_->socket_id);
821 if (!socket) {
822 error_ = kSocketNotFoundError;
823 SetResult(new base::FundamentalValue(result));
824 return;
827 if (socket->GetSocketType() != Socket::TYPE_UDP) {
828 error_ = kMulticastSocketTypeError;
829 SetResult(new base::FundamentalValue(result));
830 return;
833 SocketPermission::CheckParam param(
834 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
835 kWildcardAddress,
836 kWildcardPort);
838 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
839 APIPermission::kSocket, &param)) {
840 error_ = kPermissionError;
841 SetResult(new base::FundamentalValue(result));
842 return;
845 result = static_cast<UDPSocket*>(socket)->JoinGroup(params_->address);
846 if (result != 0) {
847 error_ = net::ErrorToString(result);
849 SetResult(new base::FundamentalValue(result));
852 SocketLeaveGroupFunction::SocketLeaveGroupFunction() {}
854 SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {}
856 bool SocketLeaveGroupFunction::Prepare() {
857 params_ = api::socket::LeaveGroup::Params::Create(*args_);
858 EXTENSION_FUNCTION_VALIDATE(params_.get());
859 return true;
862 void SocketLeaveGroupFunction::Work() {
863 int result = -1;
864 Socket* socket = GetSocket(params_->socket_id);
866 if (!socket) {
867 error_ = kSocketNotFoundError;
868 SetResult(new base::FundamentalValue(result));
869 return;
872 if (socket->GetSocketType() != Socket::TYPE_UDP) {
873 error_ = kMulticastSocketTypeError;
874 SetResult(new base::FundamentalValue(result));
875 return;
878 SocketPermission::CheckParam param(
879 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
880 kWildcardAddress,
881 kWildcardPort);
882 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
883 APIPermission::kSocket, &param)) {
884 error_ = kPermissionError;
885 SetResult(new base::FundamentalValue(result));
886 return;
889 result = static_cast<UDPSocket*>(socket)->LeaveGroup(params_->address);
890 if (result != 0)
891 error_ = net::ErrorToString(result);
892 SetResult(new base::FundamentalValue(result));
895 SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {}
897 SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {}
899 bool SocketSetMulticastTimeToLiveFunction::Prepare() {
900 params_ = api::socket::SetMulticastTimeToLive::Params::Create(*args_);
901 EXTENSION_FUNCTION_VALIDATE(params_.get());
902 return true;
904 void SocketSetMulticastTimeToLiveFunction::Work() {
905 int result = -1;
906 Socket* socket = GetSocket(params_->socket_id);
907 if (!socket) {
908 error_ = kSocketNotFoundError;
909 SetResult(new base::FundamentalValue(result));
910 return;
913 if (socket->GetSocketType() != Socket::TYPE_UDP) {
914 error_ = kMulticastSocketTypeError;
915 SetResult(new base::FundamentalValue(result));
916 return;
919 result =
920 static_cast<UDPSocket*>(socket)->SetMulticastTimeToLive(params_->ttl);
921 if (result != 0)
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_ = api::socket::SetMulticastLoopbackMode::Params::Create(*args_);
934 EXTENSION_FUNCTION_VALIDATE(params_.get());
935 return true;
938 void SocketSetMulticastLoopbackModeFunction::Work() {
939 int result = -1;
940 Socket* socket = GetSocket(params_->socket_id);
941 if (!socket) {
942 error_ = kSocketNotFoundError;
943 SetResult(new base::FundamentalValue(result));
944 return;
947 if (socket->GetSocketType() != Socket::TYPE_UDP) {
948 error_ = kMulticastSocketTypeError;
949 SetResult(new base::FundamentalValue(result));
950 return;
953 result = static_cast<UDPSocket*>(socket)
954 ->SetMulticastLoopbackMode(params_->enabled);
955 if (result != 0)
956 error_ = net::ErrorToString(result);
957 SetResult(new base::FundamentalValue(result));
960 SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {}
962 SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {}
964 bool SocketGetJoinedGroupsFunction::Prepare() {
965 params_ = api::socket::GetJoinedGroups::Params::Create(*args_);
966 EXTENSION_FUNCTION_VALIDATE(params_.get());
967 return true;
970 void SocketGetJoinedGroupsFunction::Work() {
971 int result = -1;
972 Socket* socket = GetSocket(params_->socket_id);
973 if (!socket) {
974 error_ = kSocketNotFoundError;
975 SetResult(new base::FundamentalValue(result));
976 return;
979 if (socket->GetSocketType() != Socket::TYPE_UDP) {
980 error_ = kMulticastSocketTypeError;
981 SetResult(new base::FundamentalValue(result));
982 return;
985 SocketPermission::CheckParam param(
986 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
987 kWildcardAddress,
988 kWildcardPort);
989 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
990 APIPermission::kSocket, &param)) {
991 error_ = kPermissionError;
992 SetResult(new base::FundamentalValue(result));
993 return;
996 base::ListValue* values = new base::ListValue();
997 values->AppendStrings((std::vector<std::string>&)static_cast<UDPSocket*>(
998 socket)->GetJoinedGroups());
999 SetResult(values);
1002 SocketSecureFunction::SocketSecureFunction() {
1005 SocketSecureFunction::~SocketSecureFunction() {
1008 bool SocketSecureFunction::Prepare() {
1009 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1010 params_ = api::socket::Secure::Params::Create(*args_);
1011 EXTENSION_FUNCTION_VALIDATE(params_.get());
1012 url_request_getter_ = browser_context()->GetRequestContext();
1013 return true;
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);
1022 if (!socket) {
1023 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
1024 error_ = kSocketNotFoundError;
1025 AsyncWorkCompleted();
1026 return;
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();
1035 return;
1038 if (!socket->IsConnected()) {
1039 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
1040 error_ = kSocketNotConnectedError;
1041 AsyncWorkCompleted();
1042 return;
1045 net::URLRequestContext* url_request_context =
1046 url_request_getter_->GetURLRequestContext();
1048 TLSSocket::UpgradeSocketToTLS(
1049 socket,
1050 url_request_context->ssl_config_service(),
1051 url_request_context->cert_verifier(),
1052 url_request_context->transport_security_state(),
1053 extension_id(),
1054 params_->options.get(),
1055 base::Bind(&SocketSecureFunction::TlsConnectDone, this));
1058 void SocketSecureFunction::TlsConnectDone(scoped_ptr<TLSSocket> socket,
1059 int result) {
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());
1065 } else {
1066 RemoveSocket(params_->socket_id);
1067 error_ = net::ErrorToString(result);
1070 results_ = api::socket::Secure::Results::Create(result);
1071 AsyncWorkCompleted();
1074 } // namespace extensions