Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / extensions / browser / api / socket / socket_api.cc
blobc8364fa117834d788802519ff3b12865cc8e6478
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 uint16 kWildcardPort = 0;
54 SocketAsyncApiFunction::SocketAsyncApiFunction() {}
56 SocketAsyncApiFunction::~SocketAsyncApiFunction() {}
58 bool SocketAsyncApiFunction::PrePrepare() {
59 manager_ = CreateSocketResourceManager();
60 return manager_->SetBrowserContext(browser_context());
63 bool SocketAsyncApiFunction::Respond() { return error_.empty(); }
65 scoped_ptr<SocketResourceManagerInterface>
66 SocketAsyncApiFunction::CreateSocketResourceManager() {
67 return scoped_ptr<SocketResourceManagerInterface>(
68 new SocketResourceManager<Socket>()).Pass();
71 int SocketAsyncApiFunction::AddSocket(Socket* socket) {
72 return manager_->Add(socket);
75 Socket* SocketAsyncApiFunction::GetSocket(int api_resource_id) {
76 return manager_->Get(extension_->id(), api_resource_id);
79 void SocketAsyncApiFunction::ReplaceSocket(int api_resource_id,
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 int port;
196 EXTENSION_FUNCTION_VALIDATE(
197 args_->GetInteger(2, &port) && port >= 0 && port <= 65535);
198 port_ = static_cast<uint16>(port);
199 return true;
202 void SocketConnectFunction::AsyncWorkStart() {
203 Socket* socket = GetSocket(socket_id_);
204 if (!socket) {
205 error_ = kSocketNotFoundError;
206 SetResult(new base::FundamentalValue(-1));
207 AsyncWorkCompleted();
208 return;
211 socket->set_hostname(hostname_);
213 SocketPermissionRequest::OperationType operation_type;
214 switch (socket->GetSocketType()) {
215 case Socket::TYPE_TCP:
216 operation_type = SocketPermissionRequest::TCP_CONNECT;
217 break;
218 case Socket::TYPE_UDP:
219 operation_type = SocketPermissionRequest::UDP_SEND_TO;
220 break;
221 default:
222 NOTREACHED() << "Unknown socket type.";
223 operation_type = SocketPermissionRequest::NONE;
224 break;
227 SocketPermission::CheckParam param(operation_type, hostname_, port_);
228 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
229 APIPermission::kSocket, &param)) {
230 error_ = kPermissionError;
231 SetResult(new base::FundamentalValue(-1));
232 AsyncWorkCompleted();
233 return;
236 StartDnsLookup(hostname_);
239 void SocketConnectFunction::AfterDnsLookup(int lookup_result) {
240 if (lookup_result == net::OK) {
241 StartConnect();
242 } else {
243 SetResult(new base::FundamentalValue(lookup_result));
244 AsyncWorkCompleted();
248 void SocketConnectFunction::StartConnect() {
249 Socket* socket = GetSocket(socket_id_);
250 if (!socket) {
251 error_ = kSocketNotFoundError;
252 SetResult(new base::FundamentalValue(-1));
253 AsyncWorkCompleted();
254 return;
257 socket->Connect(resolved_address_,
258 port_,
259 base::Bind(&SocketConnectFunction::OnConnect, this));
262 void SocketConnectFunction::OnConnect(int result) {
263 SetResult(new base::FundamentalValue(result));
264 AsyncWorkCompleted();
267 bool SocketDisconnectFunction::Prepare() {
268 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
269 return true;
272 void SocketDisconnectFunction::Work() {
273 Socket* socket = GetSocket(socket_id_);
274 if (socket)
275 socket->Disconnect();
276 else
277 error_ = kSocketNotFoundError;
278 SetResult(base::Value::CreateNullValue());
281 bool SocketBindFunction::Prepare() {
282 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
283 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &address_));
284 int port;
285 EXTENSION_FUNCTION_VALIDATE(
286 args_->GetInteger(2, &port) && port >= 0 && port <= 65535);
287 port_ = static_cast<uint16>(port);
288 return true;
291 void SocketBindFunction::Work() {
292 int result = -1;
293 Socket* socket = GetSocket(socket_id_);
295 if (!socket) {
296 error_ = kSocketNotFoundError;
297 SetResult(new base::FundamentalValue(result));
298 return;
301 if (socket->GetSocketType() == Socket::TYPE_UDP) {
302 SocketPermission::CheckParam param(
303 SocketPermissionRequest::UDP_BIND, address_, port_);
304 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
305 APIPermission::kSocket, &param)) {
306 error_ = kPermissionError;
307 SetResult(new base::FundamentalValue(result));
308 return;
310 } else if (socket->GetSocketType() == Socket::TYPE_TCP) {
311 error_ = kTCPSocketBindError;
312 SetResult(new base::FundamentalValue(result));
313 return;
316 result = socket->Bind(address_, port_);
317 SetResult(new base::FundamentalValue(result));
320 SocketListenFunction::SocketListenFunction() {}
322 SocketListenFunction::~SocketListenFunction() {}
324 bool SocketListenFunction::Prepare() {
325 params_ = core_api::socket::Listen::Params::Create(*args_);
326 EXTENSION_FUNCTION_VALIDATE(params_.get());
327 return true;
330 void SocketListenFunction::Work() {
331 int result = -1;
333 Socket* socket = GetSocket(params_->socket_id);
334 if (socket) {
335 SocketPermission::CheckParam param(
336 SocketPermissionRequest::TCP_LISTEN, params_->address, params_->port);
337 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
338 APIPermission::kSocket, &param)) {
339 error_ = kPermissionError;
340 SetResult(new base::FundamentalValue(result));
341 return;
344 result =
345 socket->Listen(params_->address,
346 params_->port,
347 params_->backlog.get() ? *params_->backlog.get() : 5,
348 &error_);
349 } else {
350 error_ = kSocketNotFoundError;
353 SetResult(new base::FundamentalValue(result));
356 SocketAcceptFunction::SocketAcceptFunction() {}
358 SocketAcceptFunction::~SocketAcceptFunction() {}
360 bool SocketAcceptFunction::Prepare() {
361 params_ = core_api::socket::Accept::Params::Create(*args_);
362 EXTENSION_FUNCTION_VALIDATE(params_.get());
363 return true;
366 void SocketAcceptFunction::AsyncWorkStart() {
367 Socket* socket = GetSocket(params_->socket_id);
368 if (socket) {
369 socket->Accept(base::Bind(&SocketAcceptFunction::OnAccept, this));
370 } else {
371 error_ = kSocketNotFoundError;
372 OnAccept(-1, NULL);
376 void SocketAcceptFunction::OnAccept(int result_code,
377 net::TCPClientSocket* socket) {
378 base::DictionaryValue* result = new base::DictionaryValue();
379 result->SetInteger(kResultCodeKey, result_code);
380 if (socket) {
381 Socket* client_socket = new TCPSocket(socket, extension_id(), true);
382 result->SetInteger(kSocketIdKey, AddSocket(client_socket));
384 SetResult(result);
386 AsyncWorkCompleted();
389 SocketReadFunction::SocketReadFunction() {}
391 SocketReadFunction::~SocketReadFunction() {}
393 bool SocketReadFunction::Prepare() {
394 params_ = core_api::socket::Read::Params::Create(*args_);
395 EXTENSION_FUNCTION_VALIDATE(params_.get());
396 return true;
399 void SocketReadFunction::AsyncWorkStart() {
400 Socket* socket = GetSocket(params_->socket_id);
401 if (!socket) {
402 error_ = kSocketNotFoundError;
403 OnCompleted(-1, NULL);
404 return;
407 socket->Read(params_->buffer_size.get() ? *params_->buffer_size.get() : 4096,
408 base::Bind(&SocketReadFunction::OnCompleted, this));
411 void SocketReadFunction::OnCompleted(int bytes_read,
412 scoped_refptr<net::IOBuffer> io_buffer) {
413 base::DictionaryValue* result = new base::DictionaryValue();
414 result->SetInteger(kResultCodeKey, bytes_read);
415 if (bytes_read > 0) {
416 result->Set(kDataKey,
417 base::BinaryValue::CreateWithCopiedBuffer(io_buffer->data(),
418 bytes_read));
419 } else {
420 result->Set(kDataKey, new base::BinaryValue());
422 SetResult(result);
424 AsyncWorkCompleted();
427 SocketWriteFunction::SocketWriteFunction()
428 : socket_id_(0), io_buffer_(NULL), io_buffer_size_(0) {}
430 SocketWriteFunction::~SocketWriteFunction() {}
432 bool SocketWriteFunction::Prepare() {
433 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
434 base::BinaryValue* data = NULL;
435 EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &data));
437 io_buffer_size_ = data->GetSize();
438 io_buffer_ = new net::WrappedIOBuffer(data->GetBuffer());
439 return true;
442 void SocketWriteFunction::AsyncWorkStart() {
443 Socket* socket = GetSocket(socket_id_);
445 if (!socket) {
446 error_ = kSocketNotFoundError;
447 OnCompleted(-1);
448 return;
451 socket->Write(io_buffer_,
452 io_buffer_size_,
453 base::Bind(&SocketWriteFunction::OnCompleted, this));
456 void SocketWriteFunction::OnCompleted(int bytes_written) {
457 base::DictionaryValue* result = new base::DictionaryValue();
458 result->SetInteger(kBytesWrittenKey, bytes_written);
459 SetResult(result);
461 AsyncWorkCompleted();
464 SocketRecvFromFunction::SocketRecvFromFunction() {}
466 SocketRecvFromFunction::~SocketRecvFromFunction() {}
468 bool SocketRecvFromFunction::Prepare() {
469 params_ = core_api::socket::RecvFrom::Params::Create(*args_);
470 EXTENSION_FUNCTION_VALIDATE(params_.get());
471 return true;
474 void SocketRecvFromFunction::AsyncWorkStart() {
475 Socket* socket = GetSocket(params_->socket_id);
476 if (!socket) {
477 error_ = kSocketNotFoundError;
478 OnCompleted(-1, NULL, std::string(), 0);
479 return;
482 socket->RecvFrom(params_->buffer_size.get() ? *params_->buffer_size : 4096,
483 base::Bind(&SocketRecvFromFunction::OnCompleted, this));
486 void SocketRecvFromFunction::OnCompleted(int bytes_read,
487 scoped_refptr<net::IOBuffer> io_buffer,
488 const std::string& address,
489 uint16 port) {
490 base::DictionaryValue* result = new base::DictionaryValue();
491 result->SetInteger(kResultCodeKey, bytes_read);
492 if (bytes_read > 0) {
493 result->Set(kDataKey,
494 base::BinaryValue::CreateWithCopiedBuffer(io_buffer->data(),
495 bytes_read));
496 } else {
497 result->Set(kDataKey, new base::BinaryValue());
499 result->SetString(kAddressKey, address);
500 result->SetInteger(kPortKey, port);
501 SetResult(result);
503 AsyncWorkCompleted();
506 SocketSendToFunction::SocketSendToFunction()
507 : socket_id_(0), io_buffer_(NULL), io_buffer_size_(0), port_(0) {
510 SocketSendToFunction::~SocketSendToFunction() {}
512 bool SocketSendToFunction::Prepare() {
513 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
514 base::BinaryValue* data = NULL;
515 EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &data));
516 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &hostname_));
517 int port;
518 EXTENSION_FUNCTION_VALIDATE(
519 args_->GetInteger(3, &port) && port >= 0 && port <= 65535);
520 port_ = static_cast<uint16>(port);
522 io_buffer_size_ = data->GetSize();
523 io_buffer_ = new net::WrappedIOBuffer(data->GetBuffer());
524 return true;
527 void SocketSendToFunction::AsyncWorkStart() {
528 Socket* socket = GetSocket(socket_id_);
529 if (!socket) {
530 error_ = kSocketNotFoundError;
531 SetResult(new base::FundamentalValue(-1));
532 AsyncWorkCompleted();
533 return;
536 if (socket->GetSocketType() == Socket::TYPE_UDP) {
537 SocketPermission::CheckParam param(
538 SocketPermissionRequest::UDP_SEND_TO, hostname_, port_);
539 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
540 APIPermission::kSocket, &param)) {
541 error_ = kPermissionError;
542 SetResult(new base::FundamentalValue(-1));
543 AsyncWorkCompleted();
544 return;
548 StartDnsLookup(hostname_);
551 void SocketSendToFunction::AfterDnsLookup(int lookup_result) {
552 if (lookup_result == net::OK) {
553 StartSendTo();
554 } else {
555 SetResult(new base::FundamentalValue(lookup_result));
556 AsyncWorkCompleted();
560 void SocketSendToFunction::StartSendTo() {
561 Socket* socket = GetSocket(socket_id_);
562 if (!socket) {
563 error_ = kSocketNotFoundError;
564 SetResult(new base::FundamentalValue(-1));
565 AsyncWorkCompleted();
566 return;
569 socket->SendTo(io_buffer_,
570 io_buffer_size_,
571 resolved_address_,
572 port_,
573 base::Bind(&SocketSendToFunction::OnCompleted, this));
576 void SocketSendToFunction::OnCompleted(int bytes_written) {
577 base::DictionaryValue* result = new base::DictionaryValue();
578 result->SetInteger(kBytesWrittenKey, bytes_written);
579 SetResult(result);
581 AsyncWorkCompleted();
584 SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {}
586 SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {}
588 bool SocketSetKeepAliveFunction::Prepare() {
589 params_ = core_api::socket::SetKeepAlive::Params::Create(*args_);
590 EXTENSION_FUNCTION_VALIDATE(params_.get());
591 return true;
594 void SocketSetKeepAliveFunction::Work() {
595 bool result = false;
596 Socket* socket = GetSocket(params_->socket_id);
597 if (socket) {
598 int delay = 0;
599 if (params_->delay.get())
600 delay = *params_->delay;
601 result = socket->SetKeepAlive(params_->enable, delay);
602 } else {
603 error_ = kSocketNotFoundError;
605 SetResult(new base::FundamentalValue(result));
608 SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
610 SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {}
612 bool SocketSetNoDelayFunction::Prepare() {
613 params_ = core_api::socket::SetNoDelay::Params::Create(*args_);
614 EXTENSION_FUNCTION_VALIDATE(params_.get());
615 return true;
618 void SocketSetNoDelayFunction::Work() {
619 bool result = false;
620 Socket* socket = GetSocket(params_->socket_id);
621 if (socket)
622 result = socket->SetNoDelay(params_->no_delay);
623 else
624 error_ = kSocketNotFoundError;
625 SetResult(new base::FundamentalValue(result));
628 SocketGetInfoFunction::SocketGetInfoFunction() {}
630 SocketGetInfoFunction::~SocketGetInfoFunction() {}
632 bool SocketGetInfoFunction::Prepare() {
633 params_ = core_api::socket::GetInfo::Params::Create(*args_);
634 EXTENSION_FUNCTION_VALIDATE(params_.get());
635 return true;
638 void SocketGetInfoFunction::Work() {
639 Socket* socket = GetSocket(params_->socket_id);
640 if (!socket) {
641 error_ = kSocketNotFoundError;
642 return;
645 core_api::socket::SocketInfo info;
646 // This represents what we know about the socket, and does not call through
647 // to the system.
648 if (socket->GetSocketType() == Socket::TYPE_TCP)
649 info.socket_type = extensions::core_api::socket::SOCKET_TYPE_TCP;
650 else
651 info.socket_type = extensions::core_api::socket::SOCKET_TYPE_UDP;
652 info.connected = socket->IsConnected();
654 // Grab the peer address as known by the OS. This and the call below will
655 // always succeed while the socket is connected, even if the socket has
656 // been remotely closed by the peer; only reading the socket will reveal
657 // that it should be closed locally.
658 net::IPEndPoint peerAddress;
659 if (socket->GetPeerAddress(&peerAddress)) {
660 info.peer_address.reset(new std::string(peerAddress.ToStringWithoutPort()));
661 info.peer_port.reset(new int(peerAddress.port()));
664 // Grab the local address as known by the OS.
665 net::IPEndPoint localAddress;
666 if (socket->GetLocalAddress(&localAddress)) {
667 info.local_address.reset(
668 new std::string(localAddress.ToStringWithoutPort()));
669 info.local_port.reset(new int(localAddress.port()));
672 SetResult(info.ToValue().release());
675 bool SocketGetNetworkListFunction::RunAsync() {
676 content::BrowserThread::PostTask(
677 content::BrowserThread::FILE,
678 FROM_HERE,
679 base::Bind(&SocketGetNetworkListFunction::GetNetworkListOnFileThread,
680 this));
681 return true;
684 void SocketGetNetworkListFunction::GetNetworkListOnFileThread() {
685 net::NetworkInterfaceList interface_list;
686 if (GetNetworkList(&interface_list,
687 net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) {
688 content::BrowserThread::PostTask(
689 content::BrowserThread::UI,
690 FROM_HERE,
691 base::Bind(&SocketGetNetworkListFunction::SendResponseOnUIThread,
692 this,
693 interface_list));
694 return;
697 content::BrowserThread::PostTask(
698 content::BrowserThread::UI,
699 FROM_HERE,
700 base::Bind(&SocketGetNetworkListFunction::HandleGetNetworkListError,
701 this));
704 void SocketGetNetworkListFunction::HandleGetNetworkListError() {
705 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
706 error_ = kNetworkListError;
707 SendResponse(false);
710 void SocketGetNetworkListFunction::SendResponseOnUIThread(
711 const net::NetworkInterfaceList& interface_list) {
712 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
714 std::vector<linked_ptr<core_api::socket::NetworkInterface> > create_arg;
715 create_arg.reserve(interface_list.size());
716 for (net::NetworkInterfaceList::const_iterator i = interface_list.begin();
717 i != interface_list.end();
718 ++i) {
719 linked_ptr<core_api::socket::NetworkInterface> info =
720 make_linked_ptr(new core_api::socket::NetworkInterface);
721 info->name = i->name;
722 info->address = net::IPAddressToString(i->address);
723 info->prefix_length = i->prefix_length;
724 create_arg.push_back(info);
727 results_ = core_api::socket::GetNetworkList::Results::Create(create_arg);
728 SendResponse(true);
731 SocketJoinGroupFunction::SocketJoinGroupFunction() {}
733 SocketJoinGroupFunction::~SocketJoinGroupFunction() {}
735 bool SocketJoinGroupFunction::Prepare() {
736 params_ = core_api::socket::JoinGroup::Params::Create(*args_);
737 EXTENSION_FUNCTION_VALIDATE(params_.get());
738 return true;
741 void SocketJoinGroupFunction::Work() {
742 int result = -1;
743 Socket* socket = GetSocket(params_->socket_id);
744 if (!socket) {
745 error_ = kSocketNotFoundError;
746 SetResult(new base::FundamentalValue(result));
747 return;
750 if (socket->GetSocketType() != Socket::TYPE_UDP) {
751 error_ = kMulticastSocketTypeError;
752 SetResult(new base::FundamentalValue(result));
753 return;
756 SocketPermission::CheckParam param(
757 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
758 kWildcardAddress,
759 kWildcardPort);
761 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
762 APIPermission::kSocket, &param)) {
763 error_ = kPermissionError;
764 SetResult(new base::FundamentalValue(result));
765 return;
768 result = static_cast<UDPSocket*>(socket)->JoinGroup(params_->address);
769 if (result != 0) {
770 error_ = net::ErrorToString(result);
772 SetResult(new base::FundamentalValue(result));
775 SocketLeaveGroupFunction::SocketLeaveGroupFunction() {}
777 SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {}
779 bool SocketLeaveGroupFunction::Prepare() {
780 params_ = core_api::socket::LeaveGroup::Params::Create(*args_);
781 EXTENSION_FUNCTION_VALIDATE(params_.get());
782 return true;
785 void SocketLeaveGroupFunction::Work() {
786 int result = -1;
787 Socket* socket = GetSocket(params_->socket_id);
789 if (!socket) {
790 error_ = kSocketNotFoundError;
791 SetResult(new base::FundamentalValue(result));
792 return;
795 if (socket->GetSocketType() != Socket::TYPE_UDP) {
796 error_ = kMulticastSocketTypeError;
797 SetResult(new base::FundamentalValue(result));
798 return;
801 SocketPermission::CheckParam param(
802 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
803 kWildcardAddress,
804 kWildcardPort);
805 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
806 APIPermission::kSocket, &param)) {
807 error_ = kPermissionError;
808 SetResult(new base::FundamentalValue(result));
809 return;
812 result = static_cast<UDPSocket*>(socket)->LeaveGroup(params_->address);
813 if (result != 0)
814 error_ = net::ErrorToString(result);
815 SetResult(new base::FundamentalValue(result));
818 SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {}
820 SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {}
822 bool SocketSetMulticastTimeToLiveFunction::Prepare() {
823 params_ = core_api::socket::SetMulticastTimeToLive::Params::Create(*args_);
824 EXTENSION_FUNCTION_VALIDATE(params_.get());
825 return true;
827 void SocketSetMulticastTimeToLiveFunction::Work() {
828 int result = -1;
829 Socket* socket = GetSocket(params_->socket_id);
830 if (!socket) {
831 error_ = kSocketNotFoundError;
832 SetResult(new base::FundamentalValue(result));
833 return;
836 if (socket->GetSocketType() != Socket::TYPE_UDP) {
837 error_ = kMulticastSocketTypeError;
838 SetResult(new base::FundamentalValue(result));
839 return;
842 result =
843 static_cast<UDPSocket*>(socket)->SetMulticastTimeToLive(params_->ttl);
844 if (result != 0)
845 error_ = net::ErrorToString(result);
846 SetResult(new base::FundamentalValue(result));
849 SocketSetMulticastLoopbackModeFunction::
850 SocketSetMulticastLoopbackModeFunction() {}
852 SocketSetMulticastLoopbackModeFunction::
853 ~SocketSetMulticastLoopbackModeFunction() {}
855 bool SocketSetMulticastLoopbackModeFunction::Prepare() {
856 params_ = core_api::socket::SetMulticastLoopbackMode::Params::Create(*args_);
857 EXTENSION_FUNCTION_VALIDATE(params_.get());
858 return true;
861 void SocketSetMulticastLoopbackModeFunction::Work() {
862 int result = -1;
863 Socket* socket = GetSocket(params_->socket_id);
864 if (!socket) {
865 error_ = kSocketNotFoundError;
866 SetResult(new base::FundamentalValue(result));
867 return;
870 if (socket->GetSocketType() != Socket::TYPE_UDP) {
871 error_ = kMulticastSocketTypeError;
872 SetResult(new base::FundamentalValue(result));
873 return;
876 result = static_cast<UDPSocket*>(socket)
877 ->SetMulticastLoopbackMode(params_->enabled);
878 if (result != 0)
879 error_ = net::ErrorToString(result);
880 SetResult(new base::FundamentalValue(result));
883 SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {}
885 SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {}
887 bool SocketGetJoinedGroupsFunction::Prepare() {
888 params_ = core_api::socket::GetJoinedGroups::Params::Create(*args_);
889 EXTENSION_FUNCTION_VALIDATE(params_.get());
890 return true;
893 void SocketGetJoinedGroupsFunction::Work() {
894 int result = -1;
895 Socket* socket = GetSocket(params_->socket_id);
896 if (!socket) {
897 error_ = kSocketNotFoundError;
898 SetResult(new base::FundamentalValue(result));
899 return;
902 if (socket->GetSocketType() != Socket::TYPE_UDP) {
903 error_ = kMulticastSocketTypeError;
904 SetResult(new base::FundamentalValue(result));
905 return;
908 SocketPermission::CheckParam param(
909 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
910 kWildcardAddress,
911 kWildcardPort);
912 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
913 APIPermission::kSocket, &param)) {
914 error_ = kPermissionError;
915 SetResult(new base::FundamentalValue(result));
916 return;
919 base::ListValue* values = new base::ListValue();
920 values->AppendStrings((std::vector<std::string>&)static_cast<UDPSocket*>(
921 socket)->GetJoinedGroups());
922 SetResult(values);
925 SocketSecureFunction::SocketSecureFunction() {
928 SocketSecureFunction::~SocketSecureFunction() {
931 bool SocketSecureFunction::Prepare() {
932 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
933 params_ = core_api::socket::Secure::Params::Create(*args_);
934 EXTENSION_FUNCTION_VALIDATE(params_.get());
935 url_request_getter_ = browser_context()->GetRequestContext();
936 return true;
939 // Override the regular implementation, which would call AsyncWorkCompleted
940 // immediately after Work().
941 void SocketSecureFunction::AsyncWorkStart() {
942 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
944 Socket* socket = GetSocket(params_->socket_id);
945 if (!socket) {
946 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
947 error_ = kSocketNotFoundError;
948 AsyncWorkCompleted();
949 return;
952 // Make sure that the socket is a TCP client socket.
953 if (socket->GetSocketType() != Socket::TYPE_TCP ||
954 static_cast<TCPSocket*>(socket)->ClientStream() == NULL) {
955 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
956 error_ = kSecureSocketTypeError;
957 AsyncWorkCompleted();
958 return;
961 if (!socket->IsConnected()) {
962 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
963 error_ = kSocketNotConnectedError;
964 AsyncWorkCompleted();
965 return;
968 net::URLRequestContext* url_request_context =
969 url_request_getter_->GetURLRequestContext();
971 TLSSocket::UpgradeSocketToTLS(
972 socket,
973 url_request_context->ssl_config_service(),
974 url_request_context->cert_verifier(),
975 url_request_context->transport_security_state(),
976 extension_id(),
977 params_->options.get(),
978 base::Bind(&SocketSecureFunction::TlsConnectDone, this));
981 void SocketSecureFunction::TlsConnectDone(scoped_ptr<TLSSocket> socket,
982 int result) {
983 // if an error occurred, socket MUST be NULL.
984 DCHECK(result == net::OK || socket == NULL);
986 if (socket && result == net::OK) {
987 ReplaceSocket(params_->socket_id, socket.release());
988 } else {
989 RemoveSocket(params_->socket_id);
990 error_ = net::ErrorToString(result);
993 results_ = core_api::socket::Secure::Results::Create(result);
994 AsyncWorkCompleted();
997 } // namespace extensions