Add testing/scripts/OWNERS
[chromium-blink-merge.git] / extensions / browser / api / socket / socket_api.cc
blob509b060a1b20d6ae02e13d67491bede13f8aa318
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_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 int 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,
80 Socket* socket) {
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())
101 return false;
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(
120 request_info,
121 net::DEFAULT_PRIORITY,
122 addresses_.get(),
123 base::Bind(&SocketExtensionWithDnsLookupFunction::OnDnsLookup, this),
124 request_handle_.get(),
125 net::BoundNetLog());
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();
135 } else {
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;
153 break;
154 case extensions::core_api::socket::SOCKET_TYPE_UDP:
155 socket_type_ = kSocketTypeUDP;
156 break;
157 case extensions::core_api::socket::SOCKET_TYPE_NONE:
158 NOTREACHED();
159 break;
162 return true;
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());
172 DCHECK(socket);
174 base::DictionaryValue* result = new base::DictionaryValue();
175 result->SetInteger(kSocketIdKey, AddSocket(socket));
176 SetResult(result);
179 bool SocketDestroyFunction::Prepare() {
180 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
181 return true;
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_));
195 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port_));
196 return true;
199 void SocketConnectFunction::AsyncWorkStart() {
200 Socket* socket = GetSocket(socket_id_);
201 if (!socket) {
202 error_ = kSocketNotFoundError;
203 SetResult(new base::FundamentalValue(-1));
204 AsyncWorkCompleted();
205 return;
208 socket->set_hostname(hostname_);
210 SocketPermissionRequest::OperationType operation_type;
211 switch (socket->GetSocketType()) {
212 case Socket::TYPE_TCP:
213 operation_type = SocketPermissionRequest::TCP_CONNECT;
214 break;
215 case Socket::TYPE_UDP:
216 operation_type = SocketPermissionRequest::UDP_SEND_TO;
217 break;
218 default:
219 NOTREACHED() << "Unknown socket type.";
220 operation_type = SocketPermissionRequest::NONE;
221 break;
224 SocketPermission::CheckParam param(operation_type, hostname_, port_);
225 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
226 APIPermission::kSocket, &param)) {
227 error_ = kPermissionError;
228 SetResult(new base::FundamentalValue(-1));
229 AsyncWorkCompleted();
230 return;
233 StartDnsLookup(hostname_);
236 void SocketConnectFunction::AfterDnsLookup(int lookup_result) {
237 if (lookup_result == net::OK) {
238 StartConnect();
239 } else {
240 SetResult(new base::FundamentalValue(lookup_result));
241 AsyncWorkCompleted();
245 void SocketConnectFunction::StartConnect() {
246 Socket* socket = GetSocket(socket_id_);
247 if (!socket) {
248 error_ = kSocketNotFoundError;
249 SetResult(new base::FundamentalValue(-1));
250 AsyncWorkCompleted();
251 return;
254 socket->Connect(resolved_address_,
255 port_,
256 base::Bind(&SocketConnectFunction::OnConnect, this));
259 void SocketConnectFunction::OnConnect(int result) {
260 SetResult(new base::FundamentalValue(result));
261 AsyncWorkCompleted();
264 bool SocketDisconnectFunction::Prepare() {
265 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
266 return true;
269 void SocketDisconnectFunction::Work() {
270 Socket* socket = GetSocket(socket_id_);
271 if (socket)
272 socket->Disconnect();
273 else
274 error_ = kSocketNotFoundError;
275 SetResult(base::Value::CreateNullValue());
278 bool SocketBindFunction::Prepare() {
279 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
280 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &address_));
281 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port_));
282 return true;
285 void SocketBindFunction::Work() {
286 int result = -1;
287 Socket* socket = GetSocket(socket_id_);
289 if (!socket) {
290 error_ = kSocketNotFoundError;
291 SetResult(new base::FundamentalValue(result));
292 return;
295 if (socket->GetSocketType() == Socket::TYPE_UDP) {
296 SocketPermission::CheckParam param(
297 SocketPermissionRequest::UDP_BIND, address_, port_);
298 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
299 APIPermission::kSocket, &param)) {
300 error_ = kPermissionError;
301 SetResult(new base::FundamentalValue(result));
302 return;
304 } else if (socket->GetSocketType() == Socket::TYPE_TCP) {
305 error_ = kTCPSocketBindError;
306 SetResult(new base::FundamentalValue(result));
307 return;
310 result = socket->Bind(address_, port_);
311 SetResult(new base::FundamentalValue(result));
314 SocketListenFunction::SocketListenFunction() {}
316 SocketListenFunction::~SocketListenFunction() {}
318 bool SocketListenFunction::Prepare() {
319 params_ = core_api::socket::Listen::Params::Create(*args_);
320 EXTENSION_FUNCTION_VALIDATE(params_.get());
321 return true;
324 void SocketListenFunction::Work() {
325 int result = -1;
327 Socket* socket = GetSocket(params_->socket_id);
328 if (socket) {
329 SocketPermission::CheckParam param(
330 SocketPermissionRequest::TCP_LISTEN, params_->address, params_->port);
331 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
332 APIPermission::kSocket, &param)) {
333 error_ = kPermissionError;
334 SetResult(new base::FundamentalValue(result));
335 return;
338 result =
339 socket->Listen(params_->address,
340 params_->port,
341 params_->backlog.get() ? *params_->backlog.get() : 5,
342 &error_);
343 } else {
344 error_ = kSocketNotFoundError;
347 SetResult(new base::FundamentalValue(result));
350 SocketAcceptFunction::SocketAcceptFunction() {}
352 SocketAcceptFunction::~SocketAcceptFunction() {}
354 bool SocketAcceptFunction::Prepare() {
355 params_ = core_api::socket::Accept::Params::Create(*args_);
356 EXTENSION_FUNCTION_VALIDATE(params_.get());
357 return true;
360 void SocketAcceptFunction::AsyncWorkStart() {
361 Socket* socket = GetSocket(params_->socket_id);
362 if (socket) {
363 socket->Accept(base::Bind(&SocketAcceptFunction::OnAccept, this));
364 } else {
365 error_ = kSocketNotFoundError;
366 OnAccept(-1, NULL);
370 void SocketAcceptFunction::OnAccept(int result_code,
371 net::TCPClientSocket* socket) {
372 base::DictionaryValue* result = new base::DictionaryValue();
373 result->SetInteger(kResultCodeKey, result_code);
374 if (socket) {
375 Socket* client_socket = new TCPSocket(socket, extension_id(), true);
376 result->SetInteger(kSocketIdKey, AddSocket(client_socket));
378 SetResult(result);
380 AsyncWorkCompleted();
383 SocketReadFunction::SocketReadFunction() {}
385 SocketReadFunction::~SocketReadFunction() {}
387 bool SocketReadFunction::Prepare() {
388 params_ = core_api::socket::Read::Params::Create(*args_);
389 EXTENSION_FUNCTION_VALIDATE(params_.get());
390 return true;
393 void SocketReadFunction::AsyncWorkStart() {
394 Socket* socket = GetSocket(params_->socket_id);
395 if (!socket) {
396 error_ = kSocketNotFoundError;
397 OnCompleted(-1, NULL);
398 return;
401 socket->Read(params_->buffer_size.get() ? *params_->buffer_size.get() : 4096,
402 base::Bind(&SocketReadFunction::OnCompleted, this));
405 void SocketReadFunction::OnCompleted(int bytes_read,
406 scoped_refptr<net::IOBuffer> io_buffer) {
407 base::DictionaryValue* result = new base::DictionaryValue();
408 result->SetInteger(kResultCodeKey, bytes_read);
409 if (bytes_read > 0) {
410 result->Set(kDataKey,
411 base::BinaryValue::CreateWithCopiedBuffer(io_buffer->data(),
412 bytes_read));
413 } else {
414 result->Set(kDataKey, new base::BinaryValue());
416 SetResult(result);
418 AsyncWorkCompleted();
421 SocketWriteFunction::SocketWriteFunction()
422 : socket_id_(0), io_buffer_(NULL), io_buffer_size_(0) {}
424 SocketWriteFunction::~SocketWriteFunction() {}
426 bool SocketWriteFunction::Prepare() {
427 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
428 base::BinaryValue* data = NULL;
429 EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &data));
431 io_buffer_size_ = data->GetSize();
432 io_buffer_ = new net::WrappedIOBuffer(data->GetBuffer());
433 return true;
436 void SocketWriteFunction::AsyncWorkStart() {
437 Socket* socket = GetSocket(socket_id_);
439 if (!socket) {
440 error_ = kSocketNotFoundError;
441 OnCompleted(-1);
442 return;
445 socket->Write(io_buffer_,
446 io_buffer_size_,
447 base::Bind(&SocketWriteFunction::OnCompleted, this));
450 void SocketWriteFunction::OnCompleted(int bytes_written) {
451 base::DictionaryValue* result = new base::DictionaryValue();
452 result->SetInteger(kBytesWrittenKey, bytes_written);
453 SetResult(result);
455 AsyncWorkCompleted();
458 SocketRecvFromFunction::SocketRecvFromFunction() {}
460 SocketRecvFromFunction::~SocketRecvFromFunction() {}
462 bool SocketRecvFromFunction::Prepare() {
463 params_ = core_api::socket::RecvFrom::Params::Create(*args_);
464 EXTENSION_FUNCTION_VALIDATE(params_.get());
465 return true;
468 void SocketRecvFromFunction::AsyncWorkStart() {
469 Socket* socket = GetSocket(params_->socket_id);
470 if (!socket) {
471 error_ = kSocketNotFoundError;
472 OnCompleted(-1, NULL, std::string(), 0);
473 return;
476 socket->RecvFrom(params_->buffer_size.get() ? *params_->buffer_size : 4096,
477 base::Bind(&SocketRecvFromFunction::OnCompleted, this));
480 void SocketRecvFromFunction::OnCompleted(int bytes_read,
481 scoped_refptr<net::IOBuffer> io_buffer,
482 const std::string& address,
483 int port) {
484 base::DictionaryValue* result = new base::DictionaryValue();
485 result->SetInteger(kResultCodeKey, bytes_read);
486 if (bytes_read > 0) {
487 result->Set(kDataKey,
488 base::BinaryValue::CreateWithCopiedBuffer(io_buffer->data(),
489 bytes_read));
490 } else {
491 result->Set(kDataKey, new base::BinaryValue());
493 result->SetString(kAddressKey, address);
494 result->SetInteger(kPortKey, port);
495 SetResult(result);
497 AsyncWorkCompleted();
500 SocketSendToFunction::SocketSendToFunction()
501 : socket_id_(0), io_buffer_(NULL), io_buffer_size_(0), port_(0) {
504 SocketSendToFunction::~SocketSendToFunction() {}
506 bool SocketSendToFunction::Prepare() {
507 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
508 base::BinaryValue* data = NULL;
509 EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &data));
510 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &hostname_));
511 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(3, &port_));
513 io_buffer_size_ = data->GetSize();
514 io_buffer_ = new net::WrappedIOBuffer(data->GetBuffer());
515 return true;
518 void SocketSendToFunction::AsyncWorkStart() {
519 Socket* socket = GetSocket(socket_id_);
520 if (!socket) {
521 error_ = kSocketNotFoundError;
522 SetResult(new base::FundamentalValue(-1));
523 AsyncWorkCompleted();
524 return;
527 if (socket->GetSocketType() == Socket::TYPE_UDP) {
528 SocketPermission::CheckParam param(
529 SocketPermissionRequest::UDP_SEND_TO, hostname_, port_);
530 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
531 APIPermission::kSocket, &param)) {
532 error_ = kPermissionError;
533 SetResult(new base::FundamentalValue(-1));
534 AsyncWorkCompleted();
535 return;
539 StartDnsLookup(hostname_);
542 void SocketSendToFunction::AfterDnsLookup(int lookup_result) {
543 if (lookup_result == net::OK) {
544 StartSendTo();
545 } else {
546 SetResult(new base::FundamentalValue(lookup_result));
547 AsyncWorkCompleted();
551 void SocketSendToFunction::StartSendTo() {
552 Socket* socket = GetSocket(socket_id_);
553 if (!socket) {
554 error_ = kSocketNotFoundError;
555 SetResult(new base::FundamentalValue(-1));
556 AsyncWorkCompleted();
557 return;
560 socket->SendTo(io_buffer_,
561 io_buffer_size_,
562 resolved_address_,
563 port_,
564 base::Bind(&SocketSendToFunction::OnCompleted, this));
567 void SocketSendToFunction::OnCompleted(int bytes_written) {
568 base::DictionaryValue* result = new base::DictionaryValue();
569 result->SetInteger(kBytesWrittenKey, bytes_written);
570 SetResult(result);
572 AsyncWorkCompleted();
575 SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {}
577 SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {}
579 bool SocketSetKeepAliveFunction::Prepare() {
580 params_ = core_api::socket::SetKeepAlive::Params::Create(*args_);
581 EXTENSION_FUNCTION_VALIDATE(params_.get());
582 return true;
585 void SocketSetKeepAliveFunction::Work() {
586 bool result = false;
587 Socket* socket = GetSocket(params_->socket_id);
588 if (socket) {
589 int delay = 0;
590 if (params_->delay.get())
591 delay = *params_->delay;
592 result = socket->SetKeepAlive(params_->enable, delay);
593 } else {
594 error_ = kSocketNotFoundError;
596 SetResult(new base::FundamentalValue(result));
599 SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
601 SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {}
603 bool SocketSetNoDelayFunction::Prepare() {
604 params_ = core_api::socket::SetNoDelay::Params::Create(*args_);
605 EXTENSION_FUNCTION_VALIDATE(params_.get());
606 return true;
609 void SocketSetNoDelayFunction::Work() {
610 bool result = false;
611 Socket* socket = GetSocket(params_->socket_id);
612 if (socket)
613 result = socket->SetNoDelay(params_->no_delay);
614 else
615 error_ = kSocketNotFoundError;
616 SetResult(new base::FundamentalValue(result));
619 SocketGetInfoFunction::SocketGetInfoFunction() {}
621 SocketGetInfoFunction::~SocketGetInfoFunction() {}
623 bool SocketGetInfoFunction::Prepare() {
624 params_ = core_api::socket::GetInfo::Params::Create(*args_);
625 EXTENSION_FUNCTION_VALIDATE(params_.get());
626 return true;
629 void SocketGetInfoFunction::Work() {
630 Socket* socket = GetSocket(params_->socket_id);
631 if (!socket) {
632 error_ = kSocketNotFoundError;
633 return;
636 core_api::socket::SocketInfo info;
637 // This represents what we know about the socket, and does not call through
638 // to the system.
639 if (socket->GetSocketType() == Socket::TYPE_TCP)
640 info.socket_type = extensions::core_api::socket::SOCKET_TYPE_TCP;
641 else
642 info.socket_type = extensions::core_api::socket::SOCKET_TYPE_UDP;
643 info.connected = socket->IsConnected();
645 // Grab the peer address as known by the OS. This and the call below will
646 // always succeed while the socket is connected, even if the socket has
647 // been remotely closed by the peer; only reading the socket will reveal
648 // that it should be closed locally.
649 net::IPEndPoint peerAddress;
650 if (socket->GetPeerAddress(&peerAddress)) {
651 info.peer_address.reset(new std::string(peerAddress.ToStringWithoutPort()));
652 info.peer_port.reset(new int(peerAddress.port()));
655 // Grab the local address as known by the OS.
656 net::IPEndPoint localAddress;
657 if (socket->GetLocalAddress(&localAddress)) {
658 info.local_address.reset(
659 new std::string(localAddress.ToStringWithoutPort()));
660 info.local_port.reset(new int(localAddress.port()));
663 SetResult(info.ToValue().release());
666 bool SocketGetNetworkListFunction::RunAsync() {
667 content::BrowserThread::PostTask(
668 content::BrowserThread::FILE,
669 FROM_HERE,
670 base::Bind(&SocketGetNetworkListFunction::GetNetworkListOnFileThread,
671 this));
672 return true;
675 void SocketGetNetworkListFunction::GetNetworkListOnFileThread() {
676 net::NetworkInterfaceList interface_list;
677 if (GetNetworkList(&interface_list,
678 net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) {
679 content::BrowserThread::PostTask(
680 content::BrowserThread::UI,
681 FROM_HERE,
682 base::Bind(&SocketGetNetworkListFunction::SendResponseOnUIThread,
683 this,
684 interface_list));
685 return;
688 content::BrowserThread::PostTask(
689 content::BrowserThread::UI,
690 FROM_HERE,
691 base::Bind(&SocketGetNetworkListFunction::HandleGetNetworkListError,
692 this));
695 void SocketGetNetworkListFunction::HandleGetNetworkListError() {
696 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
697 error_ = kNetworkListError;
698 SendResponse(false);
701 void SocketGetNetworkListFunction::SendResponseOnUIThread(
702 const net::NetworkInterfaceList& interface_list) {
703 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
705 std::vector<linked_ptr<core_api::socket::NetworkInterface> > create_arg;
706 create_arg.reserve(interface_list.size());
707 for (net::NetworkInterfaceList::const_iterator i = interface_list.begin();
708 i != interface_list.end();
709 ++i) {
710 linked_ptr<core_api::socket::NetworkInterface> info =
711 make_linked_ptr(new core_api::socket::NetworkInterface);
712 info->name = i->name;
713 info->address = net::IPAddressToString(i->address);
714 info->prefix_length = i->network_prefix;
715 create_arg.push_back(info);
718 results_ = core_api::socket::GetNetworkList::Results::Create(create_arg);
719 SendResponse(true);
722 SocketJoinGroupFunction::SocketJoinGroupFunction() {}
724 SocketJoinGroupFunction::~SocketJoinGroupFunction() {}
726 bool SocketJoinGroupFunction::Prepare() {
727 params_ = core_api::socket::JoinGroup::Params::Create(*args_);
728 EXTENSION_FUNCTION_VALIDATE(params_.get());
729 return true;
732 void SocketJoinGroupFunction::Work() {
733 int result = -1;
734 Socket* socket = GetSocket(params_->socket_id);
735 if (!socket) {
736 error_ = kSocketNotFoundError;
737 SetResult(new base::FundamentalValue(result));
738 return;
741 if (socket->GetSocketType() != Socket::TYPE_UDP) {
742 error_ = kMulticastSocketTypeError;
743 SetResult(new base::FundamentalValue(result));
744 return;
747 SocketPermission::CheckParam param(
748 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
749 kWildcardAddress,
750 kWildcardPort);
752 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
753 APIPermission::kSocket, &param)) {
754 error_ = kPermissionError;
755 SetResult(new base::FundamentalValue(result));
756 return;
759 result = static_cast<UDPSocket*>(socket)->JoinGroup(params_->address);
760 if (result != 0) {
761 error_ = net::ErrorToString(result);
763 SetResult(new base::FundamentalValue(result));
766 SocketLeaveGroupFunction::SocketLeaveGroupFunction() {}
768 SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {}
770 bool SocketLeaveGroupFunction::Prepare() {
771 params_ = core_api::socket::LeaveGroup::Params::Create(*args_);
772 EXTENSION_FUNCTION_VALIDATE(params_.get());
773 return true;
776 void SocketLeaveGroupFunction::Work() {
777 int result = -1;
778 Socket* socket = GetSocket(params_->socket_id);
780 if (!socket) {
781 error_ = kSocketNotFoundError;
782 SetResult(new base::FundamentalValue(result));
783 return;
786 if (socket->GetSocketType() != Socket::TYPE_UDP) {
787 error_ = kMulticastSocketTypeError;
788 SetResult(new base::FundamentalValue(result));
789 return;
792 SocketPermission::CheckParam param(
793 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
794 kWildcardAddress,
795 kWildcardPort);
796 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
797 APIPermission::kSocket, &param)) {
798 error_ = kPermissionError;
799 SetResult(new base::FundamentalValue(result));
800 return;
803 result = static_cast<UDPSocket*>(socket)->LeaveGroup(params_->address);
804 if (result != 0)
805 error_ = net::ErrorToString(result);
806 SetResult(new base::FundamentalValue(result));
809 SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {}
811 SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {}
813 bool SocketSetMulticastTimeToLiveFunction::Prepare() {
814 params_ = core_api::socket::SetMulticastTimeToLive::Params::Create(*args_);
815 EXTENSION_FUNCTION_VALIDATE(params_.get());
816 return true;
818 void SocketSetMulticastTimeToLiveFunction::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 result =
834 static_cast<UDPSocket*>(socket)->SetMulticastTimeToLive(params_->ttl);
835 if (result != 0)
836 error_ = net::ErrorToString(result);
837 SetResult(new base::FundamentalValue(result));
840 SocketSetMulticastLoopbackModeFunction::
841 SocketSetMulticastLoopbackModeFunction() {}
843 SocketSetMulticastLoopbackModeFunction::
844 ~SocketSetMulticastLoopbackModeFunction() {}
846 bool SocketSetMulticastLoopbackModeFunction::Prepare() {
847 params_ = core_api::socket::SetMulticastLoopbackMode::Params::Create(*args_);
848 EXTENSION_FUNCTION_VALIDATE(params_.get());
849 return true;
852 void SocketSetMulticastLoopbackModeFunction::Work() {
853 int result = -1;
854 Socket* socket = GetSocket(params_->socket_id);
855 if (!socket) {
856 error_ = kSocketNotFoundError;
857 SetResult(new base::FundamentalValue(result));
858 return;
861 if (socket->GetSocketType() != Socket::TYPE_UDP) {
862 error_ = kMulticastSocketTypeError;
863 SetResult(new base::FundamentalValue(result));
864 return;
867 result = static_cast<UDPSocket*>(socket)
868 ->SetMulticastLoopbackMode(params_->enabled);
869 if (result != 0)
870 error_ = net::ErrorToString(result);
871 SetResult(new base::FundamentalValue(result));
874 SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {}
876 SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {}
878 bool SocketGetJoinedGroupsFunction::Prepare() {
879 params_ = core_api::socket::GetJoinedGroups::Params::Create(*args_);
880 EXTENSION_FUNCTION_VALIDATE(params_.get());
881 return true;
884 void SocketGetJoinedGroupsFunction::Work() {
885 int result = -1;
886 Socket* socket = GetSocket(params_->socket_id);
887 if (!socket) {
888 error_ = kSocketNotFoundError;
889 SetResult(new base::FundamentalValue(result));
890 return;
893 if (socket->GetSocketType() != Socket::TYPE_UDP) {
894 error_ = kMulticastSocketTypeError;
895 SetResult(new base::FundamentalValue(result));
896 return;
899 SocketPermission::CheckParam param(
900 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
901 kWildcardAddress,
902 kWildcardPort);
903 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
904 APIPermission::kSocket, &param)) {
905 error_ = kPermissionError;
906 SetResult(new base::FundamentalValue(result));
907 return;
910 base::ListValue* values = new base::ListValue();
911 values->AppendStrings((std::vector<std::string>&)static_cast<UDPSocket*>(
912 socket)->GetJoinedGroups());
913 SetResult(values);
916 SocketSecureFunction::SocketSecureFunction() {
919 SocketSecureFunction::~SocketSecureFunction() {
922 bool SocketSecureFunction::Prepare() {
923 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
924 params_ = core_api::socket::Secure::Params::Create(*args_);
925 EXTENSION_FUNCTION_VALIDATE(params_.get());
926 url_request_getter_ = browser_context()->GetRequestContext();
927 return true;
930 // Override the regular implementation, which would call AsyncWorkCompleted
931 // immediately after Work().
932 void SocketSecureFunction::AsyncWorkStart() {
933 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
935 Socket* socket = GetSocket(params_->socket_id);
936 if (!socket) {
937 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
938 error_ = kSocketNotFoundError;
939 AsyncWorkCompleted();
940 return;
943 // Make sure that the socket is a TCP client socket.
944 if (socket->GetSocketType() != Socket::TYPE_TCP ||
945 static_cast<TCPSocket*>(socket)->ClientStream() == NULL) {
946 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
947 error_ = kSecureSocketTypeError;
948 AsyncWorkCompleted();
949 return;
952 if (!socket->IsConnected()) {
953 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
954 error_ = kSocketNotConnectedError;
955 AsyncWorkCompleted();
956 return;
959 net::URLRequestContext* url_request_context =
960 url_request_getter_->GetURLRequestContext();
962 TLSSocket::UpgradeSocketToTLS(
963 socket,
964 url_request_context->ssl_config_service(),
965 url_request_context->cert_verifier(),
966 url_request_context->transport_security_state(),
967 extension_id(),
968 params_->options.get(),
969 base::Bind(&SocketSecureFunction::TlsConnectDone, this));
972 void SocketSecureFunction::TlsConnectDone(scoped_ptr<TLSSocket> socket,
973 int result) {
974 // if an error occurred, socket MUST be NULL.
975 DCHECK(result == net::OK || socket == NULL);
977 if (socket && result == net::OK) {
978 ReplaceSocket(params_->socket_id, socket.release());
979 } else {
980 RemoveSocket(params_->socket_id);
981 error_ = net::ErrorToString(result);
984 results_ = core_api::socket::Secure::Results::Create(result);
985 AsyncWorkCompleted();
988 } // namespace extensions