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.
4 
5 #include "extensions/browser/api/socket/socket_api.h"
6 
7 #include <unordered_set>
8 #include <utility>
9 #include <vector>
10 
11 #include "base/bind.h"
12 #include "base/containers/span.h"
13 #include "base/values.h"
14 #include "build/build_config.h"
15 #include "build/chromeos_buildflags.h"
16 #include "content/public/browser/browser_context.h"
17 #include "content/public/browser/browser_task_traits.h"
18 #include "content/public/browser/network_service_instance.h"
19 #include "content/public/browser/storage_partition.h"
20 #include "extensions/browser/api/socket/socket.h"
21 #include "extensions/browser/api/socket/tcp_socket.h"
22 #include "extensions/browser/api/socket/tls_socket.h"
23 #include "extensions/browser/api/socket/udp_socket.h"
24 #include "extensions/browser/extension_system.h"
25 #include "extensions/common/extension.h"
26 #include "extensions/common/permissions/permissions_data.h"
27 #include "extensions/common/permissions/socket_permission.h"
28 #include "net/base/host_port_pair.h"
29 #include "net/base/io_buffer.h"
30 #include "net/base/ip_endpoint.h"
31 #include "net/base/net_errors.h"
32 #include "net/base/network_interfaces.h"
33 #include "net/base/network_isolation_key.h"
34 #include "net/base/url_util.h"
35 #include "net/dns/public/resolve_error_info.h"
36 #include "net/log/net_log_with_source.h"
37 
38 namespace extensions {
39 
40 namespace {
41 
42 const char kAddressKey[] = "address";
43 const char kPortKey[] = "port";
44 const char kBytesWrittenKey[] = "bytesWritten";
45 const char kDataKey[] = "data";
46 const char kResultCodeKey[] = "resultCode";
47 const char kSocketIdKey[] = "socketId";
48 
49 const char kSocketNotFoundError[] = "Socket not found";
50 const char kDnsLookupFailedError[] = "DNS resolution failed";
51 const char kPermissionError[] = "App does not have permission";
52 const char kPortInvalidError[] = "Port must be a value between 0 and 65535.";
53 const char kNetworkListError[] = "Network lookup failed or unsupported";
54 const char kTCPSocketBindError[] =
55     "TCP socket does not support bind. For TCP server please use listen.";
56 const char kMulticastSocketTypeError[] = "Only UDP socket supports multicast.";
57 const char kSecureSocketTypeError[] = "Only TCP sockets are supported for TLS.";
58 const char kSocketNotConnectedError[] = "Socket not connected";
59 const char kWildcardAddress[] = "*";
60 const uint16_t kWildcardPort = 0;
61 
62 #if BUILDFLAG(IS_CHROMEOS_ASH)
63 const char kFirewallFailure[] = "Failed to open firewall port";
64 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
65 
IsPortValid(int port)66 bool IsPortValid(int port) {
67   return port >= 0 && port <= 65535;
68 }
69 
70 }  // namespace
71 
72 using content::BrowserThread;
73 using content::SocketPermissionRequest;
74 
SocketAsyncApiFunction()75 SocketAsyncApiFunction::SocketAsyncApiFunction() {}
76 
~SocketAsyncApiFunction()77 SocketAsyncApiFunction::~SocketAsyncApiFunction() {}
78 
PrePrepare()79 bool SocketAsyncApiFunction::PrePrepare() {
80   manager_ = CreateSocketResourceManager();
81   return manager_->SetBrowserContext(browser_context());
82 }
83 
Respond()84 bool SocketAsyncApiFunction::Respond() { return error_.empty(); }
85 
86 std::unique_ptr<SocketResourceManagerInterface>
CreateSocketResourceManager()87 SocketAsyncApiFunction::CreateSocketResourceManager() {
88   return std::unique_ptr<SocketResourceManagerInterface>(
89       new SocketResourceManager<Socket>());
90 }
91 
AddSocket(Socket * socket)92 int SocketAsyncApiFunction::AddSocket(Socket* socket) {
93   return manager_->Add(socket);
94 }
95 
GetSocket(int api_resource_id)96 Socket* SocketAsyncApiFunction::GetSocket(int api_resource_id) {
97   return manager_->Get(extension_->id(), api_resource_id);
98 }
99 
ReplaceSocket(int api_resource_id,Socket * socket)100 void SocketAsyncApiFunction::ReplaceSocket(int api_resource_id,
101                                            Socket* socket) {
102   manager_->Replace(extension_->id(), api_resource_id, socket);
103 }
104 
GetSocketIds()105 std::unordered_set<int>* SocketAsyncApiFunction::GetSocketIds() {
106   return manager_->GetResourceIds(extension_->id());
107 }
108 
RemoveSocket(int api_resource_id)109 void SocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
110   manager_->Remove(extension_->id(), api_resource_id);
111 }
112 
OpenFirewallHole(const std::string & address,int socket_id,Socket * socket)113 void SocketAsyncApiFunction::OpenFirewallHole(const std::string& address,
114                                               int socket_id,
115                                               Socket* socket) {
116 #if BUILDFLAG(IS_CHROMEOS_ASH)
117   if (!net::HostStringIsLocalhost(address)) {
118     net::IPEndPoint local_address;
119     if (!socket->GetLocalAddress(&local_address)) {
120       NOTREACHED() << "Cannot get address of recently bound socket.";
121       error_ = kFirewallFailure;
122       SetResult(std::make_unique<base::Value>(-1));
123       AsyncWorkCompleted();
124       return;
125     }
126 
127     AppFirewallHole::PortType type = socket->GetSocketType() == Socket::TYPE_TCP
128                                          ? AppFirewallHole::PortType::TCP
129                                          : AppFirewallHole::PortType::UDP;
130 
131     content::GetUIThreadTaskRunner({})->PostTask(
132         FROM_HERE,
133         base::BindOnce(&SocketAsyncApiFunction::OpenFirewallHoleOnUIThread,
134                        this, type, local_address.port(), socket_id));
135     return;
136   }
137 #endif
138   AsyncWorkCompleted();
139 }
140 
141 #if BUILDFLAG(IS_CHROMEOS_ASH)
142 
OpenFirewallHoleOnUIThread(AppFirewallHole::PortType type,uint16_t port,int socket_id)143 void SocketAsyncApiFunction::OpenFirewallHoleOnUIThread(
144     AppFirewallHole::PortType type,
145     uint16_t port,
146     int socket_id) {
147   DCHECK_CURRENTLY_ON(BrowserThread::UI);
148   AppFirewallHoleManager* manager =
149       AppFirewallHoleManager::Get(browser_context());
150   std::unique_ptr<AppFirewallHole, BrowserThread::DeleteOnUIThread> hole(
151       manager->Open(type, port, extension_id()).release());
152   content::GetIOThreadTaskRunner({})->PostTask(
153       FROM_HERE, base::BindOnce(&SocketAsyncApiFunction::OnFirewallHoleOpened,
154                                 this, socket_id, std::move(hole)));
155 }
156 
OnFirewallHoleOpened(int socket_id,std::unique_ptr<AppFirewallHole,BrowserThread::DeleteOnUIThread> hole)157 void SocketAsyncApiFunction::OnFirewallHoleOpened(
158     int socket_id,
159     std::unique_ptr<AppFirewallHole, BrowserThread::DeleteOnUIThread> hole) {
160   DCHECK_CURRENTLY_ON(BrowserThread::IO);
161   if (!hole) {
162     error_ = kFirewallFailure;
163     SetResult(std::make_unique<base::Value>(-1));
164     AsyncWorkCompleted();
165     return;
166   }
167 
168   Socket* socket = GetSocket(socket_id);
169   if (!socket) {
170     error_ = kSocketNotFoundError;
171     SetResult(std::make_unique<base::Value>(-1));
172     AsyncWorkCompleted();
173     return;
174   }
175 
176   socket->set_firewall_hole(std::move(hole));
177   AsyncWorkCompleted();
178 }
179 
180 #endif  // IS_CHROMEOS_ASH
181 
182 SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction() =
183     default;
184 
~SocketExtensionWithDnsLookupFunction()185 SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() {
186 }
187 
PrePrepare()188 bool SocketExtensionWithDnsLookupFunction::PrePrepare() {
189   if (!SocketAsyncApiFunction::PrePrepare())
190     return false;
191   content::BrowserContext::GetDefaultStoragePartition(browser_context())
192       ->GetNetworkContext()
193       ->CreateHostResolver(
194           base::nullopt,
195           pending_host_resolver_.InitWithNewPipeAndPassReceiver());
196   return true;
197 }
198 
StartDnsLookup(const net::HostPortPair & host_port_pair)199 void SocketExtensionWithDnsLookupFunction::StartDnsLookup(
200     const net::HostPortPair& host_port_pair) {
201   DCHECK(pending_host_resolver_);
202   DCHECK(!receiver_.is_bound());
203   host_resolver_.Bind(std::move(pending_host_resolver_));
204   url::Origin origin = url::Origin::Create(extension_->url());
205   host_resolver_->ResolveHost(host_port_pair,
206                               net::NetworkIsolationKey(origin, origin), nullptr,
207                               receiver_.BindNewPipeAndPassRemote());
208   receiver_.set_disconnect_handler(
209       base::BindOnce(&SocketExtensionWithDnsLookupFunction::OnComplete,
210                      base::Unretained(this), net::ERR_NAME_NOT_RESOLVED,
211                      net::ResolveErrorInfo(net::ERR_FAILED), base::nullopt));
212 
213   // Balanced in OnComplete().
214   AddRef();
215 }
216 
OnComplete(int result,const net::ResolveErrorInfo & resolve_error_info,const base::Optional<net::AddressList> & resolved_addresses)217 void SocketExtensionWithDnsLookupFunction::OnComplete(
218     int result,
219     const net::ResolveErrorInfo& resolve_error_info,
220     const base::Optional<net::AddressList>& resolved_addresses) {
221   host_resolver_.reset();
222   receiver_.reset();
223   if (result == net::OK) {
224     DCHECK(resolved_addresses && !resolved_addresses->empty());
225     addresses_ = resolved_addresses.value();
226   } else {
227     error_ = kDnsLookupFailedError;
228   }
229   AfterDnsLookup(result);
230 
231   Release();  // Added in StartDnsLookup().
232 }
233 
SocketCreateFunction()234 SocketCreateFunction::SocketCreateFunction()
235     : socket_type_(kSocketTypeInvalid) {}
236 
~SocketCreateFunction()237 SocketCreateFunction::~SocketCreateFunction() {}
238 
Prepare()239 bool SocketCreateFunction::Prepare() {
240   params_ = api::socket::Create::Params::Create(*args_);
241   EXTENSION_FUNCTION_VALIDATE(params_.get());
242 
243   switch (params_->type) {
244     case extensions::api::socket::SOCKET_TYPE_TCP:
245       socket_type_ = kSocketTypeTCP;
246       break;
247     case extensions::api::socket::SOCKET_TYPE_UDP: {
248       socket_type_ = kSocketTypeUDP;
249 
250       mojo::PendingRemote<network::mojom::UDPSocketListener> listener_remote;
251       socket_listener_receiver_ =
252           listener_remote.InitWithNewPipeAndPassReceiver();
253       content::BrowserContext::GetDefaultStoragePartition(browser_context())
254           ->GetNetworkContext()
255           ->CreateUDPSocket(socket_.InitWithNewPipeAndPassReceiver(),
256                             std::move(listener_remote));
257       break;
258     }
259     case extensions::api::socket::SOCKET_TYPE_NONE:
260       NOTREACHED();
261       break;
262   }
263 
264   return true;
265 }
266 
Work()267 void SocketCreateFunction::Work() {
268   Socket* socket = nullptr;
269   if (socket_type_ == kSocketTypeTCP) {
270     socket = new TCPSocket(browser_context(), extension_->id());
271   } else if (socket_type_ == kSocketTypeUDP) {
272     socket =
273         new UDPSocket(std::move(socket_), std::move(socket_listener_receiver_),
274                       extension_->id());
275   }
276   DCHECK(socket);
277 
278   std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
279   result->SetInteger(kSocketIdKey, AddSocket(socket));
280   SetResult(std::move(result));
281 }
282 
Prepare()283 bool SocketDestroyFunction::Prepare() {
284   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
285   return true;
286 }
287 
Work()288 void SocketDestroyFunction::Work() {
289   RemoveSocket(socket_id_);
290 }
291 
SocketConnectFunction()292 SocketConnectFunction::SocketConnectFunction()
293     : socket_id_(0), hostname_(), port_(0) {
294 }
295 
~SocketConnectFunction()296 SocketConnectFunction::~SocketConnectFunction() {}
297 
Prepare()298 bool SocketConnectFunction::Prepare() {
299   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
300   EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &hostname_));
301   int port;
302   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port));
303   if (!IsPortValid(port)) {
304     error_ = kPortInvalidError;
305     return false;
306   }
307   port_ = static_cast<uint16_t>(port);
308   return true;
309 }
310 
AsyncWorkStart()311 void SocketConnectFunction::AsyncWorkStart() {
312   Socket* socket = GetSocket(socket_id_);
313   if (!socket) {
314     error_ = kSocketNotFoundError;
315     SetResult(std::make_unique<base::Value>(-1));
316     AsyncWorkCompleted();
317     return;
318   }
319 
320   socket->set_hostname(hostname_);
321 
322   SocketPermissionRequest::OperationType operation_type;
323   switch (socket->GetSocketType()) {
324     case Socket::TYPE_TCP:
325       operation_type = SocketPermissionRequest::TCP_CONNECT;
326       break;
327     case Socket::TYPE_UDP:
328       operation_type = SocketPermissionRequest::UDP_SEND_TO;
329       break;
330     default:
331       NOTREACHED() << "Unknown socket type.";
332       operation_type = SocketPermissionRequest::NONE;
333       break;
334   }
335 
336   SocketPermission::CheckParam param(operation_type, hostname_, port_);
337   if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
338           APIPermission::kSocket, &param)) {
339     error_ = kPermissionError;
340     SetResult(std::make_unique<base::Value>(-1));
341     AsyncWorkCompleted();
342     return;
343   }
344 
345   StartDnsLookup(net::HostPortPair(hostname_, port_));
346 }
347 
AfterDnsLookup(int lookup_result)348 void SocketConnectFunction::AfterDnsLookup(int lookup_result) {
349   if (lookup_result == net::OK) {
350     StartConnect();
351   } else {
352     SetResult(std::make_unique<base::Value>(lookup_result));
353     AsyncWorkCompleted();
354   }
355 }
356 
StartConnect()357 void SocketConnectFunction::StartConnect() {
358   Socket* socket = GetSocket(socket_id_);
359   if (!socket) {
360     error_ = kSocketNotFoundError;
361     SetResult(std::make_unique<base::Value>(-1));
362     AsyncWorkCompleted();
363     return;
364   }
365 
366   socket->Connect(addresses_,
367                   base::BindOnce(&SocketConnectFunction::OnConnect, this));
368 }
369 
OnConnect(int result)370 void SocketConnectFunction::OnConnect(int result) {
371   SetResult(std::make_unique<base::Value>(result));
372   AsyncWorkCompleted();
373 }
374 
Prepare()375 bool SocketDisconnectFunction::Prepare() {
376   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
377   return true;
378 }
379 
Work()380 void SocketDisconnectFunction::Work() {
381   Socket* socket = GetSocket(socket_id_);
382   if (socket)
383     socket->Disconnect(false /* socket_destroying */);
384   else
385     error_ = kSocketNotFoundError;
386   SetResult(std::make_unique<base::Value>());
387 }
388 
Prepare()389 bool SocketBindFunction::Prepare() {
390   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_));
391   EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &address_));
392   int port;
393   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port));
394   if (!IsPortValid(port)) {
395     error_ = kPortInvalidError;
396     return false;
397   }
398   port_ = static_cast<uint16_t>(port);
399   return true;
400 }
401 
AsyncWorkStart()402 void SocketBindFunction::AsyncWorkStart() {
403   Socket* socket = GetSocket(socket_id_);
404   if (!socket) {
405     error_ = kSocketNotFoundError;
406     SetResult(std::make_unique<base::Value>(-1));
407     AsyncWorkCompleted();
408     return;
409   }
410 
411   if (socket->GetSocketType() == Socket::TYPE_TCP) {
412     error_ = kTCPSocketBindError;
413     SetResult(std::make_unique<base::Value>(-1));
414     AsyncWorkCompleted();
415     return;
416   }
417 
418   CHECK(socket->GetSocketType() == Socket::TYPE_UDP);
419   SocketPermission::CheckParam param(SocketPermissionRequest::UDP_BIND,
420                                      address_, port_);
421   if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
422           APIPermission::kSocket, &param)) {
423     error_ = kPermissionError;
424     SetResult(std::make_unique<base::Value>(-1));
425     AsyncWorkCompleted();
426     return;
427   }
428 
429   socket->Bind(address_, port_,
430                base::BindOnce(&SocketBindFunction::OnCompleted, this));
431 }
OnCompleted(int net_result)432 void SocketBindFunction::OnCompleted(int net_result) {
433   Socket* socket = GetSocket(socket_id_);
434   if (!socket) {
435     error_ = kSocketNotFoundError;
436     SetResult(std::make_unique<base::Value>(-1));
437     AsyncWorkCompleted();
438     return;
439   }
440 
441   SetResult(std::make_unique<base::Value>(net_result));
442   if (net_result != net::OK) {
443     AsyncWorkCompleted();
444     return;
445   }
446 
447   OpenFirewallHole(address_, socket_id_, socket);
448 }
449 
SocketListenFunction()450 SocketListenFunction::SocketListenFunction() {}
451 
~SocketListenFunction()452 SocketListenFunction::~SocketListenFunction() {}
453 
Prepare()454 bool SocketListenFunction::Prepare() {
455   params_ = api::socket::Listen::Params::Create(*args_);
456   EXTENSION_FUNCTION_VALIDATE(params_.get());
457   return true;
458 }
459 
AsyncWorkStart()460 void SocketListenFunction::AsyncWorkStart() {
461   Socket* socket = GetSocket(params_->socket_id);
462   if (!socket) {
463     error_ = kSocketNotFoundError;
464     SetResult(std::make_unique<base::Value>(-1));
465     AsyncWorkCompleted();
466     return;
467   }
468 
469   SocketPermission::CheckParam param(SocketPermissionRequest::TCP_LISTEN,
470                                      params_->address, params_->port);
471   if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
472           APIPermission::kSocket, &param)) {
473     error_ = kPermissionError;
474     SetResult(std::make_unique<base::Value>(-1));
475     AsyncWorkCompleted();
476     return;
477   }
478 
479   socket->Listen(params_->address, params_->port,
480                  params_->backlog.get() ? *params_->backlog : 5,
481                  base::BindOnce(&SocketListenFunction::OnCompleted, this));
482 }
483 
OnCompleted(int result,const std::string & error_msg)484 void SocketListenFunction::OnCompleted(int result,
485                                        const std::string& error_msg) {
486   DCHECK_NE(net::ERR_IO_PENDING, result);
487   Socket* socket = GetSocket(params_->socket_id);
488   if (!socket) {
489     error_ = kSocketNotFoundError;
490     SetResult(std::make_unique<base::Value>(-1));
491     AsyncWorkCompleted();
492     return;
493   }
494   SetResult(std::make_unique<base::Value>(result));
495   if (result != net::OK) {
496     error_ = error_msg;
497     AsyncWorkCompleted();
498     return;
499   }
500   OpenFirewallHole(params_->address, params_->socket_id, socket);
501 }
502 
SocketAcceptFunction()503 SocketAcceptFunction::SocketAcceptFunction() {}
504 
~SocketAcceptFunction()505 SocketAcceptFunction::~SocketAcceptFunction() {}
506 
Prepare()507 bool SocketAcceptFunction::Prepare() {
508   params_ = api::socket::Accept::Params::Create(*args_);
509   EXTENSION_FUNCTION_VALIDATE(params_.get());
510   return true;
511 }
512 
AsyncWorkStart()513 void SocketAcceptFunction::AsyncWorkStart() {
514   Socket* socket = GetSocket(params_->socket_id);
515   if (socket) {
516     socket->Accept(base::BindOnce(&SocketAcceptFunction::OnAccept, this));
517   } else {
518     error_ = kSocketNotFoundError;
519     OnAccept(net::ERR_FAILED, mojo::NullRemote(), base::nullopt,
520              mojo::ScopedDataPipeConsumerHandle(),
521              mojo::ScopedDataPipeProducerHandle());
522   }
523 }
524 
OnAccept(int result_code,mojo::PendingRemote<network::mojom::TCPConnectedSocket> socket,const base::Optional<net::IPEndPoint> & remote_addr,mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,mojo::ScopedDataPipeProducerHandle send_pipe_handle)525 void SocketAcceptFunction::OnAccept(
526     int result_code,
527     mojo::PendingRemote<network::mojom::TCPConnectedSocket> socket,
528     const base::Optional<net::IPEndPoint>& remote_addr,
529     mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
530     mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
531   std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
532   result->SetInteger(kResultCodeKey, result_code);
533   if (result_code == net::OK) {
534     Socket* client_socket =
535         new TCPSocket(std::move(socket), std::move(receive_pipe_handle),
536                       std::move(send_pipe_handle), remote_addr, extension_id());
537     result->SetInteger(kSocketIdKey, AddSocket(client_socket));
538   }
539   SetResult(std::move(result));
540 
541   AsyncWorkCompleted();
542 }
543 
SocketReadFunction()544 SocketReadFunction::SocketReadFunction() {}
545 
~SocketReadFunction()546 SocketReadFunction::~SocketReadFunction() {}
547 
Prepare()548 bool SocketReadFunction::Prepare() {
549   params_ = api::socket::Read::Params::Create(*args_);
550   EXTENSION_FUNCTION_VALIDATE(params_.get());
551   return true;
552 }
553 
AsyncWorkStart()554 void SocketReadFunction::AsyncWorkStart() {
555   Socket* socket = GetSocket(params_->socket_id);
556   if (!socket) {
557     error_ = kSocketNotFoundError;
558     OnCompleted(-1, nullptr, false /* socket_destroying */);
559     return;
560   }
561 
562   socket->Read(params_->buffer_size.get() ? *params_->buffer_size : 4096,
563                base::BindOnce(&SocketReadFunction::OnCompleted, this));
564 }
565 
OnCompleted(int bytes_read,scoped_refptr<net::IOBuffer> io_buffer,bool socket_destroying)566 void SocketReadFunction::OnCompleted(int bytes_read,
567                                      scoped_refptr<net::IOBuffer> io_buffer,
568                                      bool socket_destroying) {
569   base::Value result(base::Value::Type::DICTIONARY);
570   result.SetIntKey(kResultCodeKey, bytes_read);
571   base::span<const uint8_t> data_span;
572   if (bytes_read > 0)
573     data_span = base::as_bytes(base::make_span(io_buffer->data(), bytes_read));
574   result.SetKey(kDataKey, base::Value(data_span));
575   SetResult(base::DictionaryValue::From(
576       base::Value::ToUniquePtrValue(std::move(result))));
577 
578   AsyncWorkCompleted();
579 }
580 
SocketWriteFunction()581 SocketWriteFunction::SocketWriteFunction()
582     : socket_id_(0), io_buffer_(nullptr), io_buffer_size_(0) {}
583 
~SocketWriteFunction()584 SocketWriteFunction::~SocketWriteFunction() {}
585 
Prepare()586 bool SocketWriteFunction::Prepare() {
587   const auto& list = args_->GetList();
588   EXTENSION_FUNCTION_VALIDATE(list.size() >= 2);
589   const auto& socket_id_value = list[0];
590   const auto& data_value = list[1];
591   EXTENSION_FUNCTION_VALIDATE(socket_id_value.is_int());
592   EXTENSION_FUNCTION_VALIDATE(data_value.is_blob());
593 
594   socket_id_ = socket_id_value.GetInt();
595   io_buffer_size_ = data_value.GetBlob().size();
596   io_buffer_ = base::MakeRefCounted<net::WrappedIOBuffer>(
597       reinterpret_cast<const char*>(data_value.GetBlob().data()));
598   return true;
599 }
600 
AsyncWorkStart()601 void SocketWriteFunction::AsyncWorkStart() {
602   Socket* socket = GetSocket(socket_id_);
603 
604   if (!socket) {
605     error_ = kSocketNotFoundError;
606     OnCompleted(-1);
607     return;
608   }
609 
610   socket->Write(io_buffer_, io_buffer_size_,
611                 base::BindOnce(&SocketWriteFunction::OnCompleted, this));
612 }
613 
OnCompleted(int bytes_written)614 void SocketWriteFunction::OnCompleted(int bytes_written) {
615   std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
616   result->SetInteger(kBytesWrittenKey, bytes_written);
617   SetResult(std::move(result));
618 
619   AsyncWorkCompleted();
620 }
621 
SocketRecvFromFunction()622 SocketRecvFromFunction::SocketRecvFromFunction() {}
623 
~SocketRecvFromFunction()624 SocketRecvFromFunction::~SocketRecvFromFunction() {}
625 
Prepare()626 bool SocketRecvFromFunction::Prepare() {
627   params_ = api::socket::RecvFrom::Params::Create(*args_);
628   EXTENSION_FUNCTION_VALIDATE(params_.get());
629   return true;
630 }
631 
AsyncWorkStart()632 void SocketRecvFromFunction::AsyncWorkStart() {
633   Socket* socket = GetSocket(params_->socket_id);
634   if (!socket || socket->GetSocketType() != Socket::TYPE_UDP) {
635     error_ = kSocketNotFoundError;
636     OnCompleted(-1, nullptr, false /* socket_destroying*/, std::string(), 0);
637     return;
638   }
639 
640   socket->RecvFrom(params_->buffer_size.get() ? *params_->buffer_size : 4096,
641                    base::BindOnce(&SocketRecvFromFunction::OnCompleted, this));
642 }
643 
OnCompleted(int bytes_read,scoped_refptr<net::IOBuffer> io_buffer,bool socket_destroying,const std::string & address,uint16_t port)644 void SocketRecvFromFunction::OnCompleted(int bytes_read,
645                                          scoped_refptr<net::IOBuffer> io_buffer,
646                                          bool socket_destroying,
647                                          const std::string& address,
648                                          uint16_t port) {
649   base::Value result(base::Value::Type::DICTIONARY);
650   result.SetIntKey(kResultCodeKey, bytes_read);
651   base::span<const uint8_t> data_span;
652   if (bytes_read > 0)
653     data_span = base::as_bytes(base::make_span(io_buffer->data(), bytes_read));
654   result.SetKey(kDataKey, base::Value(data_span));
655   result.SetStringKey(kAddressKey, address);
656   result.SetIntKey(kPortKey, port);
657   SetResult(base::DictionaryValue::From(
658       base::Value::ToUniquePtrValue(std::move(result))));
659 
660   AsyncWorkCompleted();
661 }
662 
SocketSendToFunction()663 SocketSendToFunction::SocketSendToFunction()
664     : socket_id_(0), io_buffer_(nullptr), io_buffer_size_(0), port_(0) {}
665 
~SocketSendToFunction()666 SocketSendToFunction::~SocketSendToFunction() {}
667 
Prepare()668 bool SocketSendToFunction::Prepare() {
669   const auto& list = args_->GetList();
670   EXTENSION_FUNCTION_VALIDATE(list.size() >= 4);
671   const auto& socket_id_value = list[0];
672   const auto& data_value = list[1];
673   const auto& hostname_value = list[2];
674   const auto& port_value = list[3];
675   EXTENSION_FUNCTION_VALIDATE(socket_id_value.is_int());
676   EXTENSION_FUNCTION_VALIDATE(data_value.is_blob());
677   EXTENSION_FUNCTION_VALIDATE(hostname_value.is_string());
678   EXTENSION_FUNCTION_VALIDATE(port_value.is_int());
679 
680   int port = port_value.GetInt();
681   if (!IsPortValid(port)) {
682     error_ = kPortInvalidError;
683     return false;
684   }
685   port_ = static_cast<uint16_t>(port);
686   socket_id_ = socket_id_value.GetInt();
687   hostname_ = hostname_value.GetString();
688 
689   io_buffer_size_ = data_value.GetBlob().size();
690   io_buffer_ = base::MakeRefCounted<net::WrappedIOBuffer>(
691       reinterpret_cast<const char*>(data_value.GetBlob().data()));
692   return true;
693 }
694 
AsyncWorkStart()695 void SocketSendToFunction::AsyncWorkStart() {
696   Socket* socket = GetSocket(socket_id_);
697   if (!socket) {
698     error_ = kSocketNotFoundError;
699     SetResult(std::make_unique<base::Value>(-1));
700     AsyncWorkCompleted();
701     return;
702   }
703 
704   if (socket->GetSocketType() == Socket::TYPE_UDP) {
705     SocketPermission::CheckParam param(
706         SocketPermissionRequest::UDP_SEND_TO, hostname_, port_);
707     if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
708             APIPermission::kSocket, &param)) {
709       error_ = kPermissionError;
710       SetResult(std::make_unique<base::Value>(-1));
711       AsyncWorkCompleted();
712       return;
713     }
714   }
715 
716   StartDnsLookup(net::HostPortPair(hostname_, port_));
717 }
718 
AfterDnsLookup(int lookup_result)719 void SocketSendToFunction::AfterDnsLookup(int lookup_result) {
720   if (lookup_result == net::OK) {
721     StartSendTo();
722   } else {
723     SetResult(std::make_unique<base::Value>(lookup_result));
724     AsyncWorkCompleted();
725   }
726 }
727 
StartSendTo()728 void SocketSendToFunction::StartSendTo() {
729   Socket* socket = GetSocket(socket_id_);
730   if (!socket) {
731     error_ = kSocketNotFoundError;
732     SetResult(std::make_unique<base::Value>(-1));
733     AsyncWorkCompleted();
734     return;
735   }
736 
737   socket->SendTo(io_buffer_, io_buffer_size_, addresses_.front(),
738                  base::BindOnce(&SocketSendToFunction::OnCompleted, this));
739 }
740 
OnCompleted(int bytes_written)741 void SocketSendToFunction::OnCompleted(int bytes_written) {
742   std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
743   result->SetInteger(kBytesWrittenKey, bytes_written);
744   SetResult(std::move(result));
745 
746   AsyncWorkCompleted();
747 }
748 
SocketSetKeepAliveFunction()749 SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {}
750 
~SocketSetKeepAliveFunction()751 SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {}
752 
Prepare()753 bool SocketSetKeepAliveFunction::Prepare() {
754   params_ = api::socket::SetKeepAlive::Params::Create(*args_);
755   EXTENSION_FUNCTION_VALIDATE(params_.get());
756   return true;
757 }
758 
AsyncWorkStart()759 void SocketSetKeepAliveFunction::AsyncWorkStart() {
760   Socket* socket = GetSocket(params_->socket_id);
761   if (!socket) {
762     SetResult(std::make_unique<base::Value>(false));
763     error_ = kSocketNotFoundError;
764     AsyncWorkCompleted();
765     return;
766   }
767   int delay = 0;
768   if (params_->delay.get())
769     delay = *params_->delay;
770   socket->SetKeepAlive(
771       params_->enable, delay,
772       base::BindOnce(&SocketSetKeepAliveFunction::OnCompleted, this));
773 }
774 
OnCompleted(bool success)775 void SocketSetKeepAliveFunction::OnCompleted(bool success) {
776   SetResult(std::make_unique<base::Value>(success));
777   AsyncWorkCompleted();
778 }
779 
SocketSetNoDelayFunction()780 SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
781 
~SocketSetNoDelayFunction()782 SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {}
783 
Prepare()784 bool SocketSetNoDelayFunction::Prepare() {
785   params_ = api::socket::SetNoDelay::Params::Create(*args_);
786   EXTENSION_FUNCTION_VALIDATE(params_.get());
787   return true;
788 }
789 
AsyncWorkStart()790 void SocketSetNoDelayFunction::AsyncWorkStart() {
791   Socket* socket = GetSocket(params_->socket_id);
792   if (!socket) {
793     error_ = kSocketNotFoundError;
794     SetResult(std::make_unique<base::Value>(false));
795     AsyncWorkCompleted();
796     return;
797   }
798   socket->SetNoDelay(
799       params_->no_delay,
800       base::BindOnce(&SocketSetNoDelayFunction::OnCompleted, this));
801 }
802 
OnCompleted(bool success)803 void SocketSetNoDelayFunction::OnCompleted(bool success) {
804   SetResult(std::make_unique<base::Value>(success));
805   AsyncWorkCompleted();
806 }
807 
SocketGetInfoFunction()808 SocketGetInfoFunction::SocketGetInfoFunction() {}
809 
~SocketGetInfoFunction()810 SocketGetInfoFunction::~SocketGetInfoFunction() {}
811 
Prepare()812 bool SocketGetInfoFunction::Prepare() {
813   params_ = api::socket::GetInfo::Params::Create(*args_);
814   EXTENSION_FUNCTION_VALIDATE(params_.get());
815   return true;
816 }
817 
Work()818 void SocketGetInfoFunction::Work() {
819   Socket* socket = GetSocket(params_->socket_id);
820   if (!socket) {
821     error_ = kSocketNotFoundError;
822     return;
823   }
824 
825   api::socket::SocketInfo info;
826   // This represents what we know about the socket, and does not call through
827   // to the system.
828   if (socket->GetSocketType() == Socket::TYPE_TCP)
829     info.socket_type = extensions::api::socket::SOCKET_TYPE_TCP;
830   else
831     info.socket_type = extensions::api::socket::SOCKET_TYPE_UDP;
832   info.connected = socket->IsConnected();
833 
834   // Grab the peer address as known by the OS. This and the call below will
835   // always succeed while the socket is connected, even if the socket has
836   // been remotely closed by the peer; only reading the socket will reveal
837   // that it should be closed locally.
838   net::IPEndPoint peerAddress;
839   if (socket->GetPeerAddress(&peerAddress)) {
840     info.peer_address.reset(new std::string(peerAddress.ToStringWithoutPort()));
841     info.peer_port.reset(new int(peerAddress.port()));
842   }
843 
844   // Grab the local address as known by the OS.
845   net::IPEndPoint localAddress;
846   if (socket->GetLocalAddress(&localAddress)) {
847     info.local_address.reset(
848         new std::string(localAddress.ToStringWithoutPort()));
849     info.local_port.reset(new int(localAddress.port()));
850   }
851 
852   SetResult(info.ToValue());
853 }
854 
Run()855 ExtensionFunction::ResponseAction SocketGetNetworkListFunction::Run() {
856   content::GetNetworkService()->GetNetworkList(
857       net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES,
858       base::BindOnce(&SocketGetNetworkListFunction::GotNetworkList, this));
859   return RespondLater();
860 }
861 
GotNetworkList(const base::Optional<net::NetworkInterfaceList> & interface_list)862 void SocketGetNetworkListFunction::GotNetworkList(
863     const base::Optional<net::NetworkInterfaceList>& interface_list) {
864   DCHECK_CURRENTLY_ON(BrowserThread::UI);
865   if (!interface_list.has_value()) {
866     Respond(Error(kNetworkListError));
867     return;
868   }
869 
870   std::vector<api::socket::NetworkInterface> create_arg;
871   create_arg.reserve(interface_list->size());
872   for (const net::NetworkInterface& interface : interface_list.value()) {
873     api::socket::NetworkInterface info;
874     info.name = interface.name;
875     info.address = interface.address.ToString();
876     info.prefix_length = interface.prefix_length;
877     create_arg.push_back(std::move(info));
878   }
879 
880   Respond(
881       ArgumentList(api::socket::GetNetworkList::Results::Create(create_arg)));
882 }
883 
SocketJoinGroupFunction()884 SocketJoinGroupFunction::SocketJoinGroupFunction() {}
885 
~SocketJoinGroupFunction()886 SocketJoinGroupFunction::~SocketJoinGroupFunction() {}
887 
Prepare()888 bool SocketJoinGroupFunction::Prepare() {
889   params_ = api::socket::JoinGroup::Params::Create(*args_);
890   EXTENSION_FUNCTION_VALIDATE(params_.get());
891   return true;
892 }
893 
AsyncWorkStart()894 void SocketJoinGroupFunction::AsyncWorkStart() {
895   int result = -1;
896   Socket* socket = GetSocket(params_->socket_id);
897   if (!socket) {
898     error_ = kSocketNotFoundError;
899     SetResult(std::make_unique<base::Value>(result));
900     AsyncWorkCompleted();
901     return;
902   }
903 
904   if (socket->GetSocketType() != Socket::TYPE_UDP) {
905     error_ = kMulticastSocketTypeError;
906     SetResult(std::make_unique<base::Value>(result));
907     AsyncWorkCompleted();
908     return;
909   }
910 
911   SocketPermission::CheckParam param(
912       SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
913       kWildcardAddress,
914       kWildcardPort);
915 
916   if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
917           APIPermission::kSocket, &param)) {
918     error_ = kPermissionError;
919     SetResult(std::make_unique<base::Value>(result));
920     AsyncWorkCompleted();
921     return;
922   }
923 
924   static_cast<UDPSocket*>(socket)->JoinGroup(
925       params_->address,
926       base::BindOnce(&SocketJoinGroupFunction::OnCompleted, this));
927 }
928 
OnCompleted(int result)929 void SocketJoinGroupFunction::OnCompleted(int result) {
930   if (result != net::OK) {
931     error_ = net::ErrorToString(result);
932   }
933   SetResult(std::make_unique<base::Value>(result));
934   AsyncWorkCompleted();
935 }
936 
SocketLeaveGroupFunction()937 SocketLeaveGroupFunction::SocketLeaveGroupFunction() {}
938 
~SocketLeaveGroupFunction()939 SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {}
940 
Prepare()941 bool SocketLeaveGroupFunction::Prepare() {
942   params_ = api::socket::LeaveGroup::Params::Create(*args_);
943   EXTENSION_FUNCTION_VALIDATE(params_.get());
944   return true;
945 }
946 
AsyncWorkStart()947 void SocketLeaveGroupFunction::AsyncWorkStart() {
948   int result = -1;
949   Socket* socket = GetSocket(params_->socket_id);
950 
951   if (!socket) {
952     error_ = kSocketNotFoundError;
953     SetResult(std::make_unique<base::Value>(result));
954     AsyncWorkCompleted();
955     return;
956   }
957 
958   if (socket->GetSocketType() != Socket::TYPE_UDP) {
959     error_ = kMulticastSocketTypeError;
960     SetResult(std::make_unique<base::Value>(result));
961     AsyncWorkCompleted();
962     return;
963   }
964 
965   SocketPermission::CheckParam param(
966       SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
967       kWildcardAddress,
968       kWildcardPort);
969   if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
970           APIPermission::kSocket, &param)) {
971     error_ = kPermissionError;
972     SetResult(std::make_unique<base::Value>(result));
973     AsyncWorkCompleted();
974     return;
975   }
976 
977   static_cast<UDPSocket*>(socket)->LeaveGroup(
978       params_->address,
979       base::BindOnce(&SocketLeaveGroupFunction::OnCompleted, this));
980 }
981 
OnCompleted(int result)982 void SocketLeaveGroupFunction::OnCompleted(int result) {
983   if (result != net::OK)
984     error_ = net::ErrorToString(result);
985   SetResult(std::make_unique<base::Value>(result));
986   AsyncWorkCompleted();
987 }
988 
SocketSetMulticastTimeToLiveFunction()989 SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {}
990 
~SocketSetMulticastTimeToLiveFunction()991 SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {}
992 
Prepare()993 bool SocketSetMulticastTimeToLiveFunction::Prepare() {
994   params_ = api::socket::SetMulticastTimeToLive::Params::Create(*args_);
995   EXTENSION_FUNCTION_VALIDATE(params_.get());
996   return true;
997 }
Work()998 void SocketSetMulticastTimeToLiveFunction::Work() {
999   int result = -1;
1000   Socket* socket = GetSocket(params_->socket_id);
1001   if (!socket) {
1002     error_ = kSocketNotFoundError;
1003     SetResult(std::make_unique<base::Value>(result));
1004     return;
1005   }
1006 
1007   if (socket->GetSocketType() != Socket::TYPE_UDP) {
1008     error_ = kMulticastSocketTypeError;
1009     SetResult(std::make_unique<base::Value>(result));
1010     return;
1011   }
1012 
1013   result =
1014       static_cast<UDPSocket*>(socket)->SetMulticastTimeToLive(params_->ttl);
1015   if (result != 0)
1016     error_ = net::ErrorToString(result);
1017   SetResult(std::make_unique<base::Value>(result));
1018 }
1019 
1020 SocketSetMulticastLoopbackModeFunction::
SocketSetMulticastLoopbackModeFunction()1021     SocketSetMulticastLoopbackModeFunction() {}
1022 
1023 SocketSetMulticastLoopbackModeFunction::
~SocketSetMulticastLoopbackModeFunction()1024     ~SocketSetMulticastLoopbackModeFunction() {}
1025 
Prepare()1026 bool SocketSetMulticastLoopbackModeFunction::Prepare() {
1027   params_ = api::socket::SetMulticastLoopbackMode::Params::Create(*args_);
1028   EXTENSION_FUNCTION_VALIDATE(params_.get());
1029   return true;
1030 }
1031 
Work()1032 void SocketSetMulticastLoopbackModeFunction::Work() {
1033   int result = -1;
1034   Socket* socket = GetSocket(params_->socket_id);
1035   if (!socket) {
1036     error_ = kSocketNotFoundError;
1037     SetResult(std::make_unique<base::Value>(result));
1038     return;
1039   }
1040 
1041   if (socket->GetSocketType() != Socket::TYPE_UDP) {
1042     error_ = kMulticastSocketTypeError;
1043     SetResult(std::make_unique<base::Value>(result));
1044     return;
1045   }
1046 
1047   result = static_cast<UDPSocket*>(socket)
1048                ->SetMulticastLoopbackMode(params_->enabled);
1049   if (result != 0)
1050     error_ = net::ErrorToString(result);
1051   SetResult(std::make_unique<base::Value>(result));
1052 }
1053 
SocketGetJoinedGroupsFunction()1054 SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {}
1055 
~SocketGetJoinedGroupsFunction()1056 SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {}
1057 
Prepare()1058 bool SocketGetJoinedGroupsFunction::Prepare() {
1059   params_ = api::socket::GetJoinedGroups::Params::Create(*args_);
1060   EXTENSION_FUNCTION_VALIDATE(params_.get());
1061   return true;
1062 }
1063 
Work()1064 void SocketGetJoinedGroupsFunction::Work() {
1065   int result = -1;
1066   Socket* socket = GetSocket(params_->socket_id);
1067   if (!socket) {
1068     error_ = kSocketNotFoundError;
1069     SetResult(std::make_unique<base::Value>(result));
1070     return;
1071   }
1072 
1073   if (socket->GetSocketType() != Socket::TYPE_UDP) {
1074     error_ = kMulticastSocketTypeError;
1075     SetResult(std::make_unique<base::Value>(result));
1076     return;
1077   }
1078 
1079   SocketPermission::CheckParam param(
1080       SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
1081       kWildcardAddress,
1082       kWildcardPort);
1083   if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
1084           APIPermission::kSocket, &param)) {
1085     error_ = kPermissionError;
1086     SetResult(std::make_unique<base::Value>(result));
1087     return;
1088   }
1089 
1090   std::unique_ptr<base::ListValue> values(new base::ListValue());
1091   values->AppendStrings((std::vector<std::string>&)static_cast<UDPSocket*>(
1092                             socket)->GetJoinedGroups());
1093   SetResult(std::move(values));
1094 }
1095 
SocketSecureFunction()1096 SocketSecureFunction::SocketSecureFunction() {
1097 }
1098 
~SocketSecureFunction()1099 SocketSecureFunction::~SocketSecureFunction() {
1100 }
1101 
Prepare()1102 bool SocketSecureFunction::Prepare() {
1103   DCHECK_CURRENTLY_ON(BrowserThread::UI);
1104   params_ = api::socket::Secure::Params::Create(*args_);
1105   EXTENSION_FUNCTION_VALIDATE(params_.get());
1106   return true;
1107 }
1108 
1109 // Override the regular implementation, which would call AsyncWorkCompleted
1110 // immediately after Work().
AsyncWorkStart()1111 void SocketSecureFunction::AsyncWorkStart() {
1112   DCHECK_CURRENTLY_ON(BrowserThread::IO);
1113 
1114   Socket* socket = GetSocket(params_->socket_id);
1115   if (!socket) {
1116     SetResult(std::make_unique<base::Value>(net::ERR_INVALID_ARGUMENT));
1117     error_ = kSocketNotFoundError;
1118     AsyncWorkCompleted();
1119     return;
1120   }
1121 
1122   // Make sure that the socket is a TCP client socket.
1123   if (socket->GetSocketType() != Socket::TYPE_TCP) {
1124     SetResult(std::make_unique<base::Value>(net::ERR_INVALID_ARGUMENT));
1125     error_ = kSecureSocketTypeError;
1126     AsyncWorkCompleted();
1127     return;
1128   }
1129 
1130   if (!socket->IsConnected()) {
1131     SetResult(std::make_unique<base::Value>(net::ERR_INVALID_ARGUMENT));
1132     error_ = kSocketNotConnectedError;
1133     AsyncWorkCompleted();
1134     return;
1135   }
1136 
1137   TCPSocket* tcp_socket = static_cast<TCPSocket*>(socket);
1138   tcp_socket->UpgradeToTLS(
1139       params_->options.get(),
1140       base::BindOnce(&SocketSecureFunction::TlsConnectDone, this));
1141 }
1142 
TlsConnectDone(int result,mojo::PendingRemote<network::mojom::TLSClientSocket> tls_socket,const net::IPEndPoint & local_addr,const net::IPEndPoint & peer_addr,mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,mojo::ScopedDataPipeProducerHandle send_pipe_handle)1143 void SocketSecureFunction::TlsConnectDone(
1144     int result,
1145     mojo::PendingRemote<network::mojom::TLSClientSocket> tls_socket,
1146     const net::IPEndPoint& local_addr,
1147     const net::IPEndPoint& peer_addr,
1148     mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
1149     mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
1150   if (result != net::OK) {
1151     RemoveSocket(params_->socket_id);
1152     error_ = net::ErrorToString(result);
1153     results_ = api::socket::Secure::Results::Create(result);
1154     AsyncWorkCompleted();
1155     return;
1156   }
1157 
1158   auto socket =
1159       std::make_unique<TLSSocket>(std::move(tls_socket), local_addr, peer_addr,
1160                                   std::move(receive_pipe_handle),
1161                                   std::move(send_pipe_handle), extension_id());
1162   ReplaceSocket(params_->socket_id, socket.release());
1163   results_ = api::socket::Secure::Results::Create(result);
1164   AsyncWorkCompleted();
1165 }
1166 
1167 }  // namespace extensions
1168