Unregister from GCM when the only GCM app is removed
[chromium-blink-merge.git] / extensions / browser / api / socket / socket_api.cc
blobdca379ab144f381e4f4db4720eeeb230ac7b914a
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 "base/profiler/scoped_tracker.h"
12 #include "content/public/browser/browser_context.h"
13 #include "content/public/browser/resource_context.h"
14 #include "extensions/browser/api/dns/host_resolver_wrapper.h"
15 #include "extensions/browser/api/socket/socket.h"
16 #include "extensions/browser/api/socket/tcp_socket.h"
17 #include "extensions/browser/api/socket/tls_socket.h"
18 #include "extensions/browser/api/socket/udp_socket.h"
19 #include "extensions/browser/extension_system.h"
20 #include "extensions/common/extension.h"
21 #include "extensions/common/permissions/permissions_data.h"
22 #include "extensions/common/permissions/socket_permission.h"
23 #include "net/base/host_port_pair.h"
24 #include "net/base/io_buffer.h"
25 #include "net/base/ip_endpoint.h"
26 #include "net/base/net_errors.h"
27 #include "net/base/net_log.h"
28 #include "net/base/net_util.h"
29 #include "net/url_request/url_request_context.h"
30 #include "net/url_request/url_request_context_getter.h"
32 namespace extensions {
34 using content::SocketPermissionRequest;
36 const char kAddressKey[] = "address";
37 const char kPortKey[] = "port";
38 const char kBytesWrittenKey[] = "bytesWritten";
39 const char kDataKey[] = "data";
40 const char kResultCodeKey[] = "resultCode";
41 const char kSocketIdKey[] = "socketId";
43 const char kSocketNotFoundError[] = "Socket not found";
44 const char kDnsLookupFailedError[] = "DNS resolution failed";
45 const char kPermissionError[] = "App does not have permission";
46 const char kNetworkListError[] = "Network lookup failed or unsupported";
47 const char kTCPSocketBindError[] =
48 "TCP socket does not support bind. For TCP server please use listen.";
49 const char kMulticastSocketTypeError[] = "Only UDP socket supports multicast.";
50 const char kSecureSocketTypeError[] = "Only TCP sockets are supported for TLS.";
51 const char kSocketNotConnectedError[] = "Socket not connected";
52 const char kWildcardAddress[] = "*";
53 const uint16 kWildcardPort = 0;
55 SocketAsyncApiFunction::SocketAsyncApiFunction() {}
57 SocketAsyncApiFunction::~SocketAsyncApiFunction() {}
59 bool SocketAsyncApiFunction::PrePrepare() {
60 manager_ = CreateSocketResourceManager();
61 return manager_->SetBrowserContext(browser_context());
64 bool SocketAsyncApiFunction::Respond() { return error_.empty(); }
66 scoped_ptr<SocketResourceManagerInterface>
67 SocketAsyncApiFunction::CreateSocketResourceManager() {
68 return scoped_ptr<SocketResourceManagerInterface>(
69 new SocketResourceManager<Socket>()).Pass();
72 int SocketAsyncApiFunction::AddSocket(Socket* socket) {
73 return manager_->Add(socket);
76 Socket* SocketAsyncApiFunction::GetSocket(int api_resource_id) {
77 return manager_->Get(extension_->id(), api_resource_id);
80 void SocketAsyncApiFunction::ReplaceSocket(int api_resource_id,
81 Socket* socket) {
82 manager_->Replace(extension_->id(), api_resource_id, socket);
85 base::hash_set<int>* SocketAsyncApiFunction::GetSocketIds() {
86 return manager_->GetResourceIds(extension_->id());
89 void SocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
90 manager_->Remove(extension_->id(), api_resource_id);
93 SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction()
94 : resource_context_(NULL),
95 request_handle_(new net::HostResolver::RequestHandle),
96 addresses_(new net::AddressList) {}
98 SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() {}
100 bool SocketExtensionWithDnsLookupFunction::PrePrepare() {
101 if (!SocketAsyncApiFunction::PrePrepare())
102 return false;
103 resource_context_ = browser_context()->GetResourceContext();
104 return resource_context_ != NULL;
107 void SocketExtensionWithDnsLookupFunction::StartDnsLookup(
108 const std::string& hostname) {
109 net::HostResolver* host_resolver =
110 HostResolverWrapper::GetInstance()->GetHostResolver(resource_context_);
111 DCHECK(host_resolver);
113 // Yes, we are passing zero as the port. There are some interesting but not
114 // presently relevant reasons why HostResolver asks for the port of the
115 // hostname you'd like to resolve, even though it doesn't use that value in
116 // determining its answer.
117 net::HostPortPair host_port_pair(hostname, 0);
119 net::HostResolver::RequestInfo request_info(host_port_pair);
120 int resolve_result = host_resolver->Resolve(
121 request_info,
122 net::DEFAULT_PRIORITY,
123 addresses_.get(),
124 base::Bind(&SocketExtensionWithDnsLookupFunction::OnDnsLookup, this),
125 request_handle_.get(),
126 net::BoundNetLog());
128 if (resolve_result != net::ERR_IO_PENDING)
129 OnDnsLookup(resolve_result);
132 void SocketExtensionWithDnsLookupFunction::OnDnsLookup(int resolve_result) {
133 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed.
134 tracked_objects::ScopedTracker tracking_profile(
135 FROM_HERE_WITH_EXPLICIT_FUNCTION(
136 "436634 SocketExtensionWithDnsLookupFunction::OnDnsLookup"));
138 if (resolve_result == net::OK) {
139 DCHECK(!addresses_->empty());
140 resolved_address_ = addresses_->front().ToStringWithoutPort();
141 } else {
142 error_ = kDnsLookupFailedError;
144 AfterDnsLookup(resolve_result);
147 SocketCreateFunction::SocketCreateFunction()
148 : socket_type_(kSocketTypeInvalid) {}
150 SocketCreateFunction::~SocketCreateFunction() {}
152 bool SocketCreateFunction::Prepare() {
153 params_ = core_api::socket::Create::Params::Create(*args_);
154 EXTENSION_FUNCTION_VALIDATE(params_.get());
156 switch (params_->type) {
157 case extensions::core_api::socket::SOCKET_TYPE_TCP:
158 socket_type_ = kSocketTypeTCP;
159 break;
160 case extensions::core_api::socket::SOCKET_TYPE_UDP:
161 socket_type_ = kSocketTypeUDP;
162 break;
163 case extensions::core_api::socket::SOCKET_TYPE_NONE:
164 NOTREACHED();
165 break;
168 return true;
171 void SocketCreateFunction::Work() {
172 Socket* socket = NULL;
173 if (socket_type_ == kSocketTypeTCP) {
174 socket = new TCPSocket(extension_->id());
175 } else if (socket_type_ == kSocketTypeUDP) {
176 socket = new UDPSocket(extension_->id());
178 DCHECK(socket);
180 base::DictionaryValue* result = new base::DictionaryValue();
181 result->SetInteger(kSocketIdKey, AddSocket(socket));
182 SetResult(result);
185 bool SocketDestroyFunction::Prepare() {
186 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
187 return true;
190 void SocketDestroyFunction::Work() { RemoveSocket(socket_id_); }
192 SocketConnectFunction::SocketConnectFunction()
193 : socket_id_(0), hostname_(), port_(0) {
196 SocketConnectFunction::~SocketConnectFunction() {}
198 bool SocketConnectFunction::Prepare() {
199 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
200 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &hostname_));
201 int port;
202 EXTENSION_FUNCTION_VALIDATE(
203 args_->GetInteger(2, &port) && port >= 0 && port <= 65535);
204 port_ = static_cast<uint16>(port);
205 return true;
208 void SocketConnectFunction::AsyncWorkStart() {
209 Socket* socket = GetSocket(socket_id_);
210 if (!socket) {
211 error_ = kSocketNotFoundError;
212 SetResult(new base::FundamentalValue(-1));
213 AsyncWorkCompleted();
214 return;
217 socket->set_hostname(hostname_);
219 SocketPermissionRequest::OperationType operation_type;
220 switch (socket->GetSocketType()) {
221 case Socket::TYPE_TCP:
222 operation_type = SocketPermissionRequest::TCP_CONNECT;
223 break;
224 case Socket::TYPE_UDP:
225 operation_type = SocketPermissionRequest::UDP_SEND_TO;
226 break;
227 default:
228 NOTREACHED() << "Unknown socket type.";
229 operation_type = SocketPermissionRequest::NONE;
230 break;
233 SocketPermission::CheckParam param(operation_type, hostname_, port_);
234 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
235 APIPermission::kSocket, &param)) {
236 error_ = kPermissionError;
237 SetResult(new base::FundamentalValue(-1));
238 AsyncWorkCompleted();
239 return;
242 StartDnsLookup(hostname_);
245 void SocketConnectFunction::AfterDnsLookup(int lookup_result) {
246 if (lookup_result == net::OK) {
247 StartConnect();
248 } else {
249 SetResult(new base::FundamentalValue(lookup_result));
250 AsyncWorkCompleted();
254 void SocketConnectFunction::StartConnect() {
255 Socket* socket = GetSocket(socket_id_);
256 if (!socket) {
257 error_ = kSocketNotFoundError;
258 SetResult(new base::FundamentalValue(-1));
259 AsyncWorkCompleted();
260 return;
263 socket->Connect(resolved_address_,
264 port_,
265 base::Bind(&SocketConnectFunction::OnConnect, this));
268 void SocketConnectFunction::OnConnect(int result) {
269 SetResult(new base::FundamentalValue(result));
270 AsyncWorkCompleted();
273 bool SocketDisconnectFunction::Prepare() {
274 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
275 return true;
278 void SocketDisconnectFunction::Work() {
279 Socket* socket = GetSocket(socket_id_);
280 if (socket)
281 socket->Disconnect();
282 else
283 error_ = kSocketNotFoundError;
284 SetResult(base::Value::CreateNullValue());
287 bool SocketBindFunction::Prepare() {
288 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
289 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &address_));
290 int port;
291 EXTENSION_FUNCTION_VALIDATE(
292 args_->GetInteger(2, &port) && port >= 0 && port <= 65535);
293 port_ = static_cast<uint16>(port);
294 return true;
297 void SocketBindFunction::Work() {
298 int result = -1;
299 Socket* socket = GetSocket(socket_id_);
301 if (!socket) {
302 error_ = kSocketNotFoundError;
303 SetResult(new base::FundamentalValue(result));
304 return;
307 if (socket->GetSocketType() == Socket::TYPE_UDP) {
308 SocketPermission::CheckParam param(
309 SocketPermissionRequest::UDP_BIND, address_, port_);
310 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
311 APIPermission::kSocket, &param)) {
312 error_ = kPermissionError;
313 SetResult(new base::FundamentalValue(result));
314 return;
316 } else if (socket->GetSocketType() == Socket::TYPE_TCP) {
317 error_ = kTCPSocketBindError;
318 SetResult(new base::FundamentalValue(result));
319 return;
322 result = socket->Bind(address_, port_);
323 SetResult(new base::FundamentalValue(result));
326 SocketListenFunction::SocketListenFunction() {}
328 SocketListenFunction::~SocketListenFunction() {}
330 bool SocketListenFunction::Prepare() {
331 params_ = core_api::socket::Listen::Params::Create(*args_);
332 EXTENSION_FUNCTION_VALIDATE(params_.get());
333 return true;
336 void SocketListenFunction::Work() {
337 int result = -1;
339 Socket* socket = GetSocket(params_->socket_id);
340 if (socket) {
341 SocketPermission::CheckParam param(
342 SocketPermissionRequest::TCP_LISTEN, params_->address, params_->port);
343 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
344 APIPermission::kSocket, &param)) {
345 error_ = kPermissionError;
346 SetResult(new base::FundamentalValue(result));
347 return;
350 result =
351 socket->Listen(params_->address,
352 params_->port,
353 params_->backlog.get() ? *params_->backlog.get() : 5,
354 &error_);
355 } else {
356 error_ = kSocketNotFoundError;
359 SetResult(new base::FundamentalValue(result));
362 SocketAcceptFunction::SocketAcceptFunction() {}
364 SocketAcceptFunction::~SocketAcceptFunction() {}
366 bool SocketAcceptFunction::Prepare() {
367 params_ = core_api::socket::Accept::Params::Create(*args_);
368 EXTENSION_FUNCTION_VALIDATE(params_.get());
369 return true;
372 void SocketAcceptFunction::AsyncWorkStart() {
373 Socket* socket = GetSocket(params_->socket_id);
374 if (socket) {
375 socket->Accept(base::Bind(&SocketAcceptFunction::OnAccept, this));
376 } else {
377 error_ = kSocketNotFoundError;
378 OnAccept(-1, NULL);
382 void SocketAcceptFunction::OnAccept(int result_code,
383 net::TCPClientSocket* socket) {
384 base::DictionaryValue* result = new base::DictionaryValue();
385 result->SetInteger(kResultCodeKey, result_code);
386 if (socket) {
387 Socket* client_socket = new TCPSocket(socket, extension_id(), true);
388 result->SetInteger(kSocketIdKey, AddSocket(client_socket));
390 SetResult(result);
392 AsyncWorkCompleted();
395 SocketReadFunction::SocketReadFunction() {}
397 SocketReadFunction::~SocketReadFunction() {}
399 bool SocketReadFunction::Prepare() {
400 params_ = core_api::socket::Read::Params::Create(*args_);
401 EXTENSION_FUNCTION_VALIDATE(params_.get());
402 return true;
405 void SocketReadFunction::AsyncWorkStart() {
406 Socket* socket = GetSocket(params_->socket_id);
407 if (!socket) {
408 error_ = kSocketNotFoundError;
409 OnCompleted(-1, NULL);
410 return;
413 socket->Read(params_->buffer_size.get() ? *params_->buffer_size.get() : 4096,
414 base::Bind(&SocketReadFunction::OnCompleted, this));
417 void SocketReadFunction::OnCompleted(int bytes_read,
418 scoped_refptr<net::IOBuffer> io_buffer) {
419 base::DictionaryValue* result = new base::DictionaryValue();
420 result->SetInteger(kResultCodeKey, bytes_read);
421 if (bytes_read > 0) {
422 result->Set(kDataKey,
423 base::BinaryValue::CreateWithCopiedBuffer(io_buffer->data(),
424 bytes_read));
425 } else {
426 result->Set(kDataKey, new base::BinaryValue());
428 SetResult(result);
430 AsyncWorkCompleted();
433 SocketWriteFunction::SocketWriteFunction()
434 : socket_id_(0), io_buffer_(NULL), io_buffer_size_(0) {}
436 SocketWriteFunction::~SocketWriteFunction() {}
438 bool SocketWriteFunction::Prepare() {
439 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
440 base::BinaryValue* data = NULL;
441 EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &data));
443 io_buffer_size_ = data->GetSize();
444 io_buffer_ = new net::WrappedIOBuffer(data->GetBuffer());
445 return true;
448 void SocketWriteFunction::AsyncWorkStart() {
449 Socket* socket = GetSocket(socket_id_);
451 if (!socket) {
452 error_ = kSocketNotFoundError;
453 OnCompleted(-1);
454 return;
457 socket->Write(io_buffer_,
458 io_buffer_size_,
459 base::Bind(&SocketWriteFunction::OnCompleted, this));
462 void SocketWriteFunction::OnCompleted(int bytes_written) {
463 base::DictionaryValue* result = new base::DictionaryValue();
464 result->SetInteger(kBytesWrittenKey, bytes_written);
465 SetResult(result);
467 AsyncWorkCompleted();
470 SocketRecvFromFunction::SocketRecvFromFunction() {}
472 SocketRecvFromFunction::~SocketRecvFromFunction() {}
474 bool SocketRecvFromFunction::Prepare() {
475 params_ = core_api::socket::RecvFrom::Params::Create(*args_);
476 EXTENSION_FUNCTION_VALIDATE(params_.get());
477 return true;
480 void SocketRecvFromFunction::AsyncWorkStart() {
481 Socket* socket = GetSocket(params_->socket_id);
482 if (!socket || socket->GetSocketType() != Socket::TYPE_UDP) {
483 error_ = kSocketNotFoundError;
484 OnCompleted(-1, NULL, std::string(), 0);
485 return;
488 socket->RecvFrom(params_->buffer_size.get() ? *params_->buffer_size : 4096,
489 base::Bind(&SocketRecvFromFunction::OnCompleted, this));
492 void SocketRecvFromFunction::OnCompleted(int bytes_read,
493 scoped_refptr<net::IOBuffer> io_buffer,
494 const std::string& address,
495 uint16 port) {
496 base::DictionaryValue* result = new base::DictionaryValue();
497 result->SetInteger(kResultCodeKey, bytes_read);
498 if (bytes_read > 0) {
499 result->Set(kDataKey,
500 base::BinaryValue::CreateWithCopiedBuffer(io_buffer->data(),
501 bytes_read));
502 } else {
503 result->Set(kDataKey, new base::BinaryValue());
505 result->SetString(kAddressKey, address);
506 result->SetInteger(kPortKey, port);
507 SetResult(result);
509 AsyncWorkCompleted();
512 SocketSendToFunction::SocketSendToFunction()
513 : socket_id_(0), io_buffer_(NULL), io_buffer_size_(0), port_(0) {
516 SocketSendToFunction::~SocketSendToFunction() {}
518 bool SocketSendToFunction::Prepare() {
519 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
520 base::BinaryValue* data = NULL;
521 EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &data));
522 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &hostname_));
523 int port;
524 EXTENSION_FUNCTION_VALIDATE(
525 args_->GetInteger(3, &port) && port >= 0 && port <= 65535);
526 port_ = static_cast<uint16>(port);
528 io_buffer_size_ = data->GetSize();
529 io_buffer_ = new net::WrappedIOBuffer(data->GetBuffer());
530 return true;
533 void SocketSendToFunction::AsyncWorkStart() {
534 Socket* socket = GetSocket(socket_id_);
535 if (!socket) {
536 error_ = kSocketNotFoundError;
537 SetResult(new base::FundamentalValue(-1));
538 AsyncWorkCompleted();
539 return;
542 if (socket->GetSocketType() == Socket::TYPE_UDP) {
543 SocketPermission::CheckParam param(
544 SocketPermissionRequest::UDP_SEND_TO, hostname_, port_);
545 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
546 APIPermission::kSocket, &param)) {
547 error_ = kPermissionError;
548 SetResult(new base::FundamentalValue(-1));
549 AsyncWorkCompleted();
550 return;
554 StartDnsLookup(hostname_);
557 void SocketSendToFunction::AfterDnsLookup(int lookup_result) {
558 if (lookup_result == net::OK) {
559 StartSendTo();
560 } else {
561 SetResult(new base::FundamentalValue(lookup_result));
562 AsyncWorkCompleted();
566 void SocketSendToFunction::StartSendTo() {
567 Socket* socket = GetSocket(socket_id_);
568 if (!socket) {
569 error_ = kSocketNotFoundError;
570 SetResult(new base::FundamentalValue(-1));
571 AsyncWorkCompleted();
572 return;
575 socket->SendTo(io_buffer_,
576 io_buffer_size_,
577 resolved_address_,
578 port_,
579 base::Bind(&SocketSendToFunction::OnCompleted, this));
582 void SocketSendToFunction::OnCompleted(int bytes_written) {
583 base::DictionaryValue* result = new base::DictionaryValue();
584 result->SetInteger(kBytesWrittenKey, bytes_written);
585 SetResult(result);
587 AsyncWorkCompleted();
590 SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {}
592 SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {}
594 bool SocketSetKeepAliveFunction::Prepare() {
595 params_ = core_api::socket::SetKeepAlive::Params::Create(*args_);
596 EXTENSION_FUNCTION_VALIDATE(params_.get());
597 return true;
600 void SocketSetKeepAliveFunction::Work() {
601 bool result = false;
602 Socket* socket = GetSocket(params_->socket_id);
603 if (socket) {
604 int delay = 0;
605 if (params_->delay.get())
606 delay = *params_->delay;
607 result = socket->SetKeepAlive(params_->enable, delay);
608 } else {
609 error_ = kSocketNotFoundError;
611 SetResult(new base::FundamentalValue(result));
614 SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
616 SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {}
618 bool SocketSetNoDelayFunction::Prepare() {
619 params_ = core_api::socket::SetNoDelay::Params::Create(*args_);
620 EXTENSION_FUNCTION_VALIDATE(params_.get());
621 return true;
624 void SocketSetNoDelayFunction::Work() {
625 bool result = false;
626 Socket* socket = GetSocket(params_->socket_id);
627 if (socket)
628 result = socket->SetNoDelay(params_->no_delay);
629 else
630 error_ = kSocketNotFoundError;
631 SetResult(new base::FundamentalValue(result));
634 SocketGetInfoFunction::SocketGetInfoFunction() {}
636 SocketGetInfoFunction::~SocketGetInfoFunction() {}
638 bool SocketGetInfoFunction::Prepare() {
639 params_ = core_api::socket::GetInfo::Params::Create(*args_);
640 EXTENSION_FUNCTION_VALIDATE(params_.get());
641 return true;
644 void SocketGetInfoFunction::Work() {
645 Socket* socket = GetSocket(params_->socket_id);
646 if (!socket) {
647 error_ = kSocketNotFoundError;
648 return;
651 core_api::socket::SocketInfo info;
652 // This represents what we know about the socket, and does not call through
653 // to the system.
654 if (socket->GetSocketType() == Socket::TYPE_TCP)
655 info.socket_type = extensions::core_api::socket::SOCKET_TYPE_TCP;
656 else
657 info.socket_type = extensions::core_api::socket::SOCKET_TYPE_UDP;
658 info.connected = socket->IsConnected();
660 // Grab the peer address as known by the OS. This and the call below will
661 // always succeed while the socket is connected, even if the socket has
662 // been remotely closed by the peer; only reading the socket will reveal
663 // that it should be closed locally.
664 net::IPEndPoint peerAddress;
665 if (socket->GetPeerAddress(&peerAddress)) {
666 info.peer_address.reset(new std::string(peerAddress.ToStringWithoutPort()));
667 info.peer_port.reset(new int(peerAddress.port()));
670 // Grab the local address as known by the OS.
671 net::IPEndPoint localAddress;
672 if (socket->GetLocalAddress(&localAddress)) {
673 info.local_address.reset(
674 new std::string(localAddress.ToStringWithoutPort()));
675 info.local_port.reset(new int(localAddress.port()));
678 SetResult(info.ToValue().release());
681 bool SocketGetNetworkListFunction::RunAsync() {
682 content::BrowserThread::PostTask(
683 content::BrowserThread::FILE,
684 FROM_HERE,
685 base::Bind(&SocketGetNetworkListFunction::GetNetworkListOnFileThread,
686 this));
687 return true;
690 void SocketGetNetworkListFunction::GetNetworkListOnFileThread() {
691 net::NetworkInterfaceList interface_list;
692 if (GetNetworkList(&interface_list,
693 net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) {
694 content::BrowserThread::PostTask(
695 content::BrowserThread::UI,
696 FROM_HERE,
697 base::Bind(&SocketGetNetworkListFunction::SendResponseOnUIThread,
698 this,
699 interface_list));
700 return;
703 content::BrowserThread::PostTask(
704 content::BrowserThread::UI,
705 FROM_HERE,
706 base::Bind(&SocketGetNetworkListFunction::HandleGetNetworkListError,
707 this));
710 void SocketGetNetworkListFunction::HandleGetNetworkListError() {
711 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
712 error_ = kNetworkListError;
713 SendResponse(false);
716 void SocketGetNetworkListFunction::SendResponseOnUIThread(
717 const net::NetworkInterfaceList& interface_list) {
718 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
720 std::vector<linked_ptr<core_api::socket::NetworkInterface> > create_arg;
721 create_arg.reserve(interface_list.size());
722 for (net::NetworkInterfaceList::const_iterator i = interface_list.begin();
723 i != interface_list.end();
724 ++i) {
725 linked_ptr<core_api::socket::NetworkInterface> info =
726 make_linked_ptr(new core_api::socket::NetworkInterface);
727 info->name = i->name;
728 info->address = net::IPAddressToString(i->address);
729 info->prefix_length = i->prefix_length;
730 create_arg.push_back(info);
733 results_ = core_api::socket::GetNetworkList::Results::Create(create_arg);
734 SendResponse(true);
737 SocketJoinGroupFunction::SocketJoinGroupFunction() {}
739 SocketJoinGroupFunction::~SocketJoinGroupFunction() {}
741 bool SocketJoinGroupFunction::Prepare() {
742 params_ = core_api::socket::JoinGroup::Params::Create(*args_);
743 EXTENSION_FUNCTION_VALIDATE(params_.get());
744 return true;
747 void SocketJoinGroupFunction::Work() {
748 int result = -1;
749 Socket* socket = GetSocket(params_->socket_id);
750 if (!socket) {
751 error_ = kSocketNotFoundError;
752 SetResult(new base::FundamentalValue(result));
753 return;
756 if (socket->GetSocketType() != Socket::TYPE_UDP) {
757 error_ = kMulticastSocketTypeError;
758 SetResult(new base::FundamentalValue(result));
759 return;
762 SocketPermission::CheckParam param(
763 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
764 kWildcardAddress,
765 kWildcardPort);
767 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
768 APIPermission::kSocket, &param)) {
769 error_ = kPermissionError;
770 SetResult(new base::FundamentalValue(result));
771 return;
774 result = static_cast<UDPSocket*>(socket)->JoinGroup(params_->address);
775 if (result != 0) {
776 error_ = net::ErrorToString(result);
778 SetResult(new base::FundamentalValue(result));
781 SocketLeaveGroupFunction::SocketLeaveGroupFunction() {}
783 SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {}
785 bool SocketLeaveGroupFunction::Prepare() {
786 params_ = core_api::socket::LeaveGroup::Params::Create(*args_);
787 EXTENSION_FUNCTION_VALIDATE(params_.get());
788 return true;
791 void SocketLeaveGroupFunction::Work() {
792 int result = -1;
793 Socket* socket = GetSocket(params_->socket_id);
795 if (!socket) {
796 error_ = kSocketNotFoundError;
797 SetResult(new base::FundamentalValue(result));
798 return;
801 if (socket->GetSocketType() != Socket::TYPE_UDP) {
802 error_ = kMulticastSocketTypeError;
803 SetResult(new base::FundamentalValue(result));
804 return;
807 SocketPermission::CheckParam param(
808 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
809 kWildcardAddress,
810 kWildcardPort);
811 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
812 APIPermission::kSocket, &param)) {
813 error_ = kPermissionError;
814 SetResult(new base::FundamentalValue(result));
815 return;
818 result = static_cast<UDPSocket*>(socket)->LeaveGroup(params_->address);
819 if (result != 0)
820 error_ = net::ErrorToString(result);
821 SetResult(new base::FundamentalValue(result));
824 SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {}
826 SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {}
828 bool SocketSetMulticastTimeToLiveFunction::Prepare() {
829 params_ = core_api::socket::SetMulticastTimeToLive::Params::Create(*args_);
830 EXTENSION_FUNCTION_VALIDATE(params_.get());
831 return true;
833 void SocketSetMulticastTimeToLiveFunction::Work() {
834 int result = -1;
835 Socket* socket = GetSocket(params_->socket_id);
836 if (!socket) {
837 error_ = kSocketNotFoundError;
838 SetResult(new base::FundamentalValue(result));
839 return;
842 if (socket->GetSocketType() != Socket::TYPE_UDP) {
843 error_ = kMulticastSocketTypeError;
844 SetResult(new base::FundamentalValue(result));
845 return;
848 result =
849 static_cast<UDPSocket*>(socket)->SetMulticastTimeToLive(params_->ttl);
850 if (result != 0)
851 error_ = net::ErrorToString(result);
852 SetResult(new base::FundamentalValue(result));
855 SocketSetMulticastLoopbackModeFunction::
856 SocketSetMulticastLoopbackModeFunction() {}
858 SocketSetMulticastLoopbackModeFunction::
859 ~SocketSetMulticastLoopbackModeFunction() {}
861 bool SocketSetMulticastLoopbackModeFunction::Prepare() {
862 params_ = core_api::socket::SetMulticastLoopbackMode::Params::Create(*args_);
863 EXTENSION_FUNCTION_VALIDATE(params_.get());
864 return true;
867 void SocketSetMulticastLoopbackModeFunction::Work() {
868 int result = -1;
869 Socket* socket = GetSocket(params_->socket_id);
870 if (!socket) {
871 error_ = kSocketNotFoundError;
872 SetResult(new base::FundamentalValue(result));
873 return;
876 if (socket->GetSocketType() != Socket::TYPE_UDP) {
877 error_ = kMulticastSocketTypeError;
878 SetResult(new base::FundamentalValue(result));
879 return;
882 result = static_cast<UDPSocket*>(socket)
883 ->SetMulticastLoopbackMode(params_->enabled);
884 if (result != 0)
885 error_ = net::ErrorToString(result);
886 SetResult(new base::FundamentalValue(result));
889 SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {}
891 SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {}
893 bool SocketGetJoinedGroupsFunction::Prepare() {
894 params_ = core_api::socket::GetJoinedGroups::Params::Create(*args_);
895 EXTENSION_FUNCTION_VALIDATE(params_.get());
896 return true;
899 void SocketGetJoinedGroupsFunction::Work() {
900 int result = -1;
901 Socket* socket = GetSocket(params_->socket_id);
902 if (!socket) {
903 error_ = kSocketNotFoundError;
904 SetResult(new base::FundamentalValue(result));
905 return;
908 if (socket->GetSocketType() != Socket::TYPE_UDP) {
909 error_ = kMulticastSocketTypeError;
910 SetResult(new base::FundamentalValue(result));
911 return;
914 SocketPermission::CheckParam param(
915 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
916 kWildcardAddress,
917 kWildcardPort);
918 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
919 APIPermission::kSocket, &param)) {
920 error_ = kPermissionError;
921 SetResult(new base::FundamentalValue(result));
922 return;
925 base::ListValue* values = new base::ListValue();
926 values->AppendStrings((std::vector<std::string>&)static_cast<UDPSocket*>(
927 socket)->GetJoinedGroups());
928 SetResult(values);
931 SocketSecureFunction::SocketSecureFunction() {
934 SocketSecureFunction::~SocketSecureFunction() {
937 bool SocketSecureFunction::Prepare() {
938 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
939 params_ = core_api::socket::Secure::Params::Create(*args_);
940 EXTENSION_FUNCTION_VALIDATE(params_.get());
941 url_request_getter_ = browser_context()->GetRequestContext();
942 return true;
945 // Override the regular implementation, which would call AsyncWorkCompleted
946 // immediately after Work().
947 void SocketSecureFunction::AsyncWorkStart() {
948 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
950 Socket* socket = GetSocket(params_->socket_id);
951 if (!socket) {
952 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
953 error_ = kSocketNotFoundError;
954 AsyncWorkCompleted();
955 return;
958 // Make sure that the socket is a TCP client socket.
959 if (socket->GetSocketType() != Socket::TYPE_TCP ||
960 static_cast<TCPSocket*>(socket)->ClientStream() == NULL) {
961 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
962 error_ = kSecureSocketTypeError;
963 AsyncWorkCompleted();
964 return;
967 if (!socket->IsConnected()) {
968 SetResult(new base::FundamentalValue(net::ERR_INVALID_ARGUMENT));
969 error_ = kSocketNotConnectedError;
970 AsyncWorkCompleted();
971 return;
974 net::URLRequestContext* url_request_context =
975 url_request_getter_->GetURLRequestContext();
977 TLSSocket::UpgradeSocketToTLS(
978 socket,
979 url_request_context->ssl_config_service(),
980 url_request_context->cert_verifier(),
981 url_request_context->transport_security_state(),
982 extension_id(),
983 params_->options.get(),
984 base::Bind(&SocketSecureFunction::TlsConnectDone, this));
987 void SocketSecureFunction::TlsConnectDone(scoped_ptr<TLSSocket> socket,
988 int result) {
989 // if an error occurred, socket MUST be NULL.
990 DCHECK(result == net::OK || socket == NULL);
992 if (socket && result == net::OK) {
993 ReplaceSocket(params_->socket_id, socket.release());
994 } else {
995 RemoveSocket(params_->socket_id);
996 error_ = net::ErrorToString(result);
999 results_ = core_api::socket::Secure::Results::Create(result);
1000 AsyncWorkCompleted();
1003 } // namespace extensions