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, ¶m)) {
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, ¶m)) {
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, ¶m)) {
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, ¶m)) {
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, ¶m)) {
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, ¶m)) {
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, ¶m)) {
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