Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / extensions / browser / api / socket / socket_api.cc
blob838b770481092fa6a11967c79159bcfed8f95c05
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/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"
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),
173 request_handle_(new net::HostResolver::RequestHandle),
174 addresses_(new net::AddressList) {}
176 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 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(
199 request_info,
200 net::DEFAULT_PRIORITY,
201 addresses_.get(),
202 base::Bind(&SocketExtensionWithDnsLookupFunction::OnDnsLookup, this),
203 request_handle_.get(),
204 net::BoundNetLog());
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();
214 } else {
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;
232 break;
233 case extensions::core_api::socket::SOCKET_TYPE_UDP:
234 socket_type_ = kSocketTypeUDP;
235 break;
236 case extensions::core_api::socket::SOCKET_TYPE_NONE:
237 NOTREACHED();
238 break;
241 return true;
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());
251 DCHECK(socket);
253 base::DictionaryValue* result = new base::DictionaryValue();
254 result->SetInteger(kSocketIdKey, AddSocket(socket));
255 SetResult(result);
258 bool SocketDestroyFunction::Prepare() {
259 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
260 return true;
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_));
274 int port;
275 EXTENSION_FUNCTION_VALIDATE(
276 args_->GetInteger(2, &port) && port >= 0 && port <= 65535);
277 port_ = static_cast<uint16>(port);
278 return true;
281 void SocketConnectFunction::AsyncWorkStart() {
282 Socket* socket = GetSocket(socket_id_);
283 if (!socket) {
284 error_ = kSocketNotFoundError;
285 SetResult(new base::FundamentalValue(-1));
286 AsyncWorkCompleted();
287 return;
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;
296 break;
297 case Socket::TYPE_UDP:
298 operation_type = SocketPermissionRequest::UDP_SEND_TO;
299 break;
300 default:
301 NOTREACHED() << "Unknown socket type.";
302 operation_type = SocketPermissionRequest::NONE;
303 break;
306 SocketPermission::CheckParam param(operation_type, hostname_, port_);
307 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
308 APIPermission::kSocket, &param)) {
309 error_ = kPermissionError;
310 SetResult(new base::FundamentalValue(-1));
311 AsyncWorkCompleted();
312 return;
315 StartDnsLookup(hostname_);
318 void SocketConnectFunction::AfterDnsLookup(int lookup_result) {
319 if (lookup_result == net::OK) {
320 StartConnect();
321 } else {
322 SetResult(new base::FundamentalValue(lookup_result));
323 AsyncWorkCompleted();
327 void SocketConnectFunction::StartConnect() {
328 Socket* socket = GetSocket(socket_id_);
329 if (!socket) {
330 error_ = kSocketNotFoundError;
331 SetResult(new base::FundamentalValue(-1));
332 AsyncWorkCompleted();
333 return;
336 socket->Connect(resolved_address_,
337 port_,
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_));
348 return true;
351 void SocketDisconnectFunction::Work() {
352 Socket* socket = GetSocket(socket_id_);
353 if (socket)
354 socket->Disconnect();
355 else
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_));
363 int port;
364 EXTENSION_FUNCTION_VALIDATE(
365 args_->GetInteger(2, &port) && port >= 0 && port <= 65535);
366 port_ = static_cast<uint16>(port);
367 return true;
370 void SocketBindFunction::AsyncWorkStart() {
371 Socket* socket = GetSocket(socket_id_);
372 if (!socket) {
373 error_ = kSocketNotFoundError;
374 SetResult(new base::FundamentalValue(-1));
375 AsyncWorkCompleted();
376 return;
379 if (socket->GetSocketType() == Socket::TYPE_TCP) {
380 error_ = kTCPSocketBindError;
381 SetResult(new base::FundamentalValue(-1));
382 AsyncWorkCompleted();
383 return;
386 CHECK(socket->GetSocketType() == Socket::TYPE_UDP);
387 SocketPermission::CheckParam param(SocketPermissionRequest::UDP_BIND,
388 address_, port_);
389 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
390 APIPermission::kSocket, &param)) {
391 error_ = kPermissionError;
392 SetResult(new base::FundamentalValue(-1));
393 AsyncWorkCompleted();
394 return;
397 int result = socket->Bind(address_, port_);
398 SetResult(new base::FundamentalValue(result));
399 if (result != net::OK) {
400 AsyncWorkCompleted();
401 return;
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());
414 return true;
417 void SocketListenFunction::AsyncWorkStart() {
418 Socket* socket = GetSocket(params_->socket_id);
419 if (!socket) {
420 error_ = kSocketNotFoundError;
421 SetResult(new base::FundamentalValue(-1));
422 AsyncWorkCompleted();
423 return;
426 SocketPermission::CheckParam param(SocketPermissionRequest::TCP_LISTEN,
427 params_->address, params_->port);
428 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
429 APIPermission::kSocket, &param)) {
430 error_ = kPermissionError;
431 SetResult(new base::FundamentalValue(-1));
432 AsyncWorkCompleted();
433 return;
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();
442 return;
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());
455 return true;
458 void SocketAcceptFunction::AsyncWorkStart() {
459 Socket* socket = GetSocket(params_->socket_id);
460 if (socket) {
461 socket->Accept(base::Bind(&SocketAcceptFunction::OnAccept, this));
462 } else {
463 error_ = kSocketNotFoundError;
464 OnAccept(-1, NULL);
468 void SocketAcceptFunction::OnAccept(int result_code,
469 net::TCPClientSocket* socket) {
470 base::DictionaryValue* result = new base::DictionaryValue();
471 result->SetInteger(kResultCodeKey, result_code);
472 if (socket) {
473 Socket* client_socket = new TCPSocket(socket, extension_id(), true);
474 result->SetInteger(kSocketIdKey, AddSocket(client_socket));
476 SetResult(result);
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());
488 return true;
491 void SocketReadFunction::AsyncWorkStart() {
492 Socket* socket = GetSocket(params_->socket_id);
493 if (!socket) {
494 error_ = kSocketNotFoundError;
495 OnCompleted(-1, NULL);
496 return;
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(),
510 bytes_read));
511 } else {
512 result->Set(kDataKey, new base::BinaryValue());
514 SetResult(result);
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());
531 return true;
534 void SocketWriteFunction::AsyncWorkStart() {
535 Socket* socket = GetSocket(socket_id_);
537 if (!socket) {
538 error_ = kSocketNotFoundError;
539 OnCompleted(-1);
540 return;
543 socket->Write(io_buffer_,
544 io_buffer_size_,
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);
551 SetResult(result);
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());
563 return true;
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);
571 return;
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,
581 uint16 port) {
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(),
587 bytes_read));
588 } else {
589 result->Set(kDataKey, new base::BinaryValue());
591 result->SetString(kAddressKey, address);
592 result->SetInteger(kPortKey, port);
593 SetResult(result);
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_));
609 int port;
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());
616 return true;
619 void SocketSendToFunction::AsyncWorkStart() {
620 Socket* socket = GetSocket(socket_id_);
621 if (!socket) {
622 error_ = kSocketNotFoundError;
623 SetResult(new base::FundamentalValue(-1));
624 AsyncWorkCompleted();
625 return;
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, &param)) {
633 error_ = kPermissionError;
634 SetResult(new base::FundamentalValue(-1));
635 AsyncWorkCompleted();
636 return;
640 StartDnsLookup(hostname_);
643 void SocketSendToFunction::AfterDnsLookup(int lookup_result) {
644 if (lookup_result == net::OK) {
645 StartSendTo();
646 } else {
647 SetResult(new base::FundamentalValue(lookup_result));
648 AsyncWorkCompleted();
652 void SocketSendToFunction::StartSendTo() {
653 Socket* socket = GetSocket(socket_id_);
654 if (!socket) {
655 error_ = kSocketNotFoundError;
656 SetResult(new base::FundamentalValue(-1));
657 AsyncWorkCompleted();
658 return;
661 socket->SendTo(io_buffer_,
662 io_buffer_size_,
663 resolved_address_,
664 port_,
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);
671 SetResult(result);
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());
683 return true;
686 void SocketSetKeepAliveFunction::Work() {
687 bool result = false;
688 Socket* socket = GetSocket(params_->socket_id);
689 if (socket) {
690 int delay = 0;
691 if (params_->delay.get())
692 delay = *params_->delay;
693 result = socket->SetKeepAlive(params_->enable, delay);
694 } else {
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());
707 return true;
710 void SocketSetNoDelayFunction::Work() {
711 bool result = false;
712 Socket* socket = GetSocket(params_->socket_id);
713 if (socket)
714 result = socket->SetNoDelay(params_->no_delay);
715 else
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());
727 return true;
730 void SocketGetInfoFunction::Work() {
731 Socket* socket = GetSocket(params_->socket_id);
732 if (!socket) {
733 error_ = kSocketNotFoundError;
734 return;
737 core_api::socket::SocketInfo info;
738 // This represents what we know about the socket, and does not call through
739 // to the system.
740 if (socket->GetSocketType() == Socket::TYPE_TCP)
741 info.socket_type = extensions::core_api::socket::SOCKET_TYPE_TCP;
742 else
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,
771 this));
772 return true;
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,
782 interface_list));
783 return;
786 BrowserThread::PostTask(
787 BrowserThread::UI, FROM_HERE,
788 base::Bind(&SocketGetNetworkListFunction::HandleGetNetworkListError,
789 this));
792 void SocketGetNetworkListFunction::HandleGetNetworkListError() {
793 DCHECK_CURRENTLY_ON(BrowserThread::UI);
794 error_ = kNetworkListError;
795 SendResponse(false);
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();
806 ++i) {
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);
816 SendResponse(true);
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());
826 return true;
829 void SocketJoinGroupFunction::Work() {
830 int result = -1;
831 Socket* socket = GetSocket(params_->socket_id);
832 if (!socket) {
833 error_ = kSocketNotFoundError;
834 SetResult(new base::FundamentalValue(result));
835 return;
838 if (socket->GetSocketType() != Socket::TYPE_UDP) {
839 error_ = kMulticastSocketTypeError;
840 SetResult(new base::FundamentalValue(result));
841 return;
844 SocketPermission::CheckParam param(
845 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
846 kWildcardAddress,
847 kWildcardPort);
849 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
850 APIPermission::kSocket, &param)) {
851 error_ = kPermissionError;
852 SetResult(new base::FundamentalValue(result));
853 return;
856 result = static_cast<UDPSocket*>(socket)->JoinGroup(params_->address);
857 if (result != 0) {
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());
870 return true;
873 void SocketLeaveGroupFunction::Work() {
874 int result = -1;
875 Socket* socket = GetSocket(params_->socket_id);
877 if (!socket) {
878 error_ = kSocketNotFoundError;
879 SetResult(new base::FundamentalValue(result));
880 return;
883 if (socket->GetSocketType() != Socket::TYPE_UDP) {
884 error_ = kMulticastSocketTypeError;
885 SetResult(new base::FundamentalValue(result));
886 return;
889 SocketPermission::CheckParam param(
890 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
891 kWildcardAddress,
892 kWildcardPort);
893 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
894 APIPermission::kSocket, &param)) {
895 error_ = kPermissionError;
896 SetResult(new base::FundamentalValue(result));
897 return;
900 result = static_cast<UDPSocket*>(socket)->LeaveGroup(params_->address);
901 if (result != 0)
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());
913 return true;
915 void SocketSetMulticastTimeToLiveFunction::Work() {
916 int result = -1;
917 Socket* socket = GetSocket(params_->socket_id);
918 if (!socket) {
919 error_ = kSocketNotFoundError;
920 SetResult(new base::FundamentalValue(result));
921 return;
924 if (socket->GetSocketType() != Socket::TYPE_UDP) {
925 error_ = kMulticastSocketTypeError;
926 SetResult(new base::FundamentalValue(result));
927 return;
930 result =
931 static_cast<UDPSocket*>(socket)->SetMulticastTimeToLive(params_->ttl);
932 if (result != 0)
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());
946 return true;
949 void SocketSetMulticastLoopbackModeFunction::Work() {
950 int result = -1;
951 Socket* socket = GetSocket(params_->socket_id);
952 if (!socket) {
953 error_ = kSocketNotFoundError;
954 SetResult(new base::FundamentalValue(result));
955 return;
958 if (socket->GetSocketType() != Socket::TYPE_UDP) {
959 error_ = kMulticastSocketTypeError;
960 SetResult(new base::FundamentalValue(result));
961 return;
964 result = static_cast<UDPSocket*>(socket)
965 ->SetMulticastLoopbackMode(params_->enabled);
966 if (result != 0)
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());
978 return true;
981 void SocketGetJoinedGroupsFunction::Work() {
982 int result = -1;
983 Socket* socket = GetSocket(params_->socket_id);
984 if (!socket) {
985 error_ = kSocketNotFoundError;
986 SetResult(new base::FundamentalValue(result));
987 return;
990 if (socket->GetSocketType() != Socket::TYPE_UDP) {
991 error_ = kMulticastSocketTypeError;
992 SetResult(new base::FundamentalValue(result));
993 return;
996 SocketPermission::CheckParam param(
997 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
998 kWildcardAddress,
999 kWildcardPort);
1000 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
1001 APIPermission::kSocket, &param)) {
1002 error_ = kPermissionError;
1003 SetResult(new base::FundamentalValue(result));
1004 return;
1007 base::ListValue* values = new base::ListValue();
1008 values->AppendStrings((std::vector<std::string>&)static_cast<UDPSocket*>(
1009 socket)->GetJoinedGroups());
1010 SetResult(values);
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();
1024 return true;
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);
1033 if (!socket) {
1034 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
1035 error_ = kSocketNotFoundError;
1036 AsyncWorkCompleted();
1037 return;
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();
1046 return;
1049 if (!socket->IsConnected()) {
1050 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
1051 error_ = kSocketNotConnectedError;
1052 AsyncWorkCompleted();
1053 return;
1056 net::URLRequestContext* url_request_context =
1057 url_request_getter_->GetURLRequestContext();
1059 TLSSocket::UpgradeSocketToTLS(
1060 socket,
1061 url_request_context->ssl_config_service(),
1062 url_request_context->cert_verifier(),
1063 url_request_context->transport_security_state(),
1064 extension_id(),
1065 params_->options.get(),
1066 base::Bind(&SocketSecureFunction::TlsConnectDone, this));
1069 void SocketSecureFunction::TlsConnectDone(scoped_ptr<TLSSocket> socket,
1070 int result) {
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());
1076 } else {
1077 RemoveSocket(params_->socket_id);
1078 error_ = net::ErrorToString(result);
1081 results_ = core_api::socket::Secure::Results::Create(result);
1082 AsyncWorkCompleted();
1085 } // namespace extensions