1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h"
10 #include "base/bind.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/metrics/histogram_macros.h"
15 #include "build/build_config.h"
16 #include "build/chromeos_buildflags.h"
17 #include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
18 #include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
19 #include "content/public/browser/browser_context.h"
20 #include "content/public/browser/browser_task_traits.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/render_frame_host.h"
23 #include "content/public/browser/render_process_host.h"
24 #include "content/public/browser/storage_partition.h"
25 #include "content/public/common/socket_permission_request.h"
26 #include "mojo/public/cpp/bindings/callback_helpers.h"
27 #include "mojo/public/cpp/bindings/pending_remote.h"
28 #include "net/base/address_family.h"
29 #include "net/base/host_port_pair.h"
30 #include "net/base/io_buffer.h"
31 #include "net/base/ip_address.h"
32 #include "net/base/net_errors.h"
33 #include "net/base/network_isolation_key.h"
34 #include "net/dns/public/resolve_error_info.h"
35 #include "net/log/net_log_source.h"
36 #include "net/log/net_log_with_source.h"
37 #include "net/ssl/ssl_info.h"
38 #include "net/traffic_annotation/network_traffic_annotation.h"
39 #include "ppapi/host/dispatch_host_message.h"
40 #include "ppapi/host/error_conversion.h"
41 #include "ppapi/host/ppapi_host.h"
42 #include "ppapi/host/resource_host.h"
43 #include "ppapi/proxy/ppapi_messages.h"
44 #include "ppapi/proxy/tcp_socket_resource_constants.h"
45 #include "ppapi/shared_impl/private/net_address_private_impl.h"
46 #include "ppapi/shared_impl/private/ppb_x509_util_shared.h"
48 #if BUILDFLAG(IS_CHROMEOS_ASH)
49 #include "chromeos/ash/components/network/firewall_hole.h"
50 #endif // BUILDFLAG(IS_CHROMEOS_ASH)
52 using ppapi::NetAddressPrivateImpl;
53 using ppapi::TCPSocketState;
54 using ppapi::TCPSocketVersion;
55 using ppapi::host::NetErrorToPepperError;
56 using ppapi::proxy::TCPSocketResourceConstants;
60 size_t g_num_tcp_filter_instances = 0;
66 network::mojom::NetworkContext*
67 PepperTCPSocketMessageFilter::network_context_for_testing = nullptr;
69 PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
70 ContentBrowserPepperHostFactory* factory,
71 BrowserPpapiHostImpl* host,
73 TCPSocketVersion version)
78 external_plugin_(host->external_plugin()),
79 render_process_id_(0),
81 state_(TCPSocketState::INITIAL),
82 bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
83 socket_options_(SOCKET_OPTION_NODELAY),
86 pending_accept_(false),
87 pending_read_size_(0),
88 pending_read_pp_error_(PP_OK_COMPLETIONPENDING),
89 pending_write_bytes_written_(0),
90 pending_write_pp_error_(PP_OK_COMPLETIONPENDING),
91 is_potentially_secure_plugin_context_(
92 host->IsPotentiallySecurePluginContext(instance)) {
94 DCHECK_CURRENTLY_ON(BrowserThread::UI);
96 ++g_num_tcp_filter_instances;
97 host_->AddInstanceObserver(instance_, this);
98 if (!host->GetRenderFrameIDsForInstance(instance, &render_process_id_,
104 void PepperTCPSocketMessageFilter::SetConnectedSocket(
105 mojo::PendingRemote<network::mojom::TCPConnectedSocket> connected_socket,
106 mojo::PendingReceiver<network::mojom::SocketObserver>
107 socket_observer_receiver,
108 mojo::ScopedDataPipeConsumerHandle receive_stream,
109 mojo::ScopedDataPipeProducerHandle send_stream) {
110 DCHECK_CURRENTLY_ON(BrowserThread::UI);
111 // This method grabs a reference to |this|, and releases a reference on the UI
112 // thread, so something should be holding on to a reference on the current
113 // thread to prevent the object from being deleted before this method returns.
116 GetUIThreadTaskRunner({})->PostTask(
119 &PepperTCPSocketMessageFilter::SetConnectedSocketOnUIThread, this,
120 std::move(connected_socket), std::move(socket_observer_receiver),
121 std::move(receive_stream), std::move(send_stream)));
124 PepperTCPSocketMessageFilter::~PepperTCPSocketMessageFilter() {
125 DCHECK_CURRENTLY_ON(BrowserThread::UI);
127 host_->RemoveInstanceObserver(instance_, this);
128 #if BUILDFLAG(IS_CHROMEOS_ASH)
129 // Close the firewall hole on UI thread if there is one.
130 if (firewall_hole_) {
131 GetUIThreadTaskRunner({})->DeleteSoon(FROM_HERE, std::move(firewall_hole_));
133 #endif // BUILDFLAG(IS_CHROMEOS_ASH)
134 --g_num_tcp_filter_instances;
137 void PepperTCPSocketMessageFilter::SetConnectedSocketOnUIThread(
138 mojo::PendingRemote<network::mojom::TCPConnectedSocket> connected_socket,
139 mojo::PendingReceiver<network::mojom::SocketObserver>
140 socket_observer_receiver,
141 mojo::ScopedDataPipeConsumerHandle receive_stream,
142 mojo::ScopedDataPipeProducerHandle send_stream) {
143 DCHECK_CURRENTLY_ON(BrowserThread::UI);
144 DCHECK_EQ(state_.state(), TCPSocketState::INITIAL);
146 state_ = TCPSocketState(TCPSocketState::CONNECTED);
147 connected_socket_.Bind(std::move(connected_socket));
148 socket_observer_receiver_.Bind(std::move(socket_observer_receiver));
149 socket_observer_receiver_.set_disconnect_handler(
150 base::BindOnce(&PepperTCPSocketMessageFilter::OnSocketObserverError,
151 base::Unretained(this)));
153 SetStreams(std::move(receive_stream), std::move(send_stream));
157 void PepperTCPSocketMessageFilter::SetNetworkContextForTesting(
158 network::mojom::NetworkContext* network_context) {
159 network_context_for_testing = network_context;
163 size_t PepperTCPSocketMessageFilter::GetNumInstances() {
164 return g_num_tcp_filter_instances;
167 void PepperTCPSocketMessageFilter::OnFilterDestroyed() {
168 ResourceMessageFilter::OnFilterDestroyed();
169 // Need to close all mojo pipes the socket on the UI thread. Calling Close()
170 // also ensures that future messages will be ignored, so the mojo pipes won't
171 // be re-created, so after Close() runs, |this| can be safely deleted on the
173 GetUIThreadTaskRunner({})->PostTask(
174 FROM_HERE, base::BindOnce(&PepperTCPSocketMessageFilter::Close, this));
177 scoped_refptr<base::SequencedTaskRunner>
178 PepperTCPSocketMessageFilter::OverrideTaskRunnerForMessage(
179 const IPC::Message& message) {
180 switch (message.type()) {
181 case PpapiHostMsg_TCPSocket_Bind::ID:
182 case PpapiHostMsg_TCPSocket_Connect::ID:
183 case PpapiHostMsg_TCPSocket_ConnectWithNetAddress::ID:
184 case PpapiHostMsg_TCPSocket_Listen::ID:
185 case PpapiHostMsg_TCPSocket_SSLHandshake::ID:
186 case PpapiHostMsg_TCPSocket_Read::ID:
187 case PpapiHostMsg_TCPSocket_Write::ID:
188 case PpapiHostMsg_TCPSocket_Accept::ID:
189 case PpapiHostMsg_TCPSocket_Close::ID:
190 case PpapiHostMsg_TCPSocket_SetOption::ID:
191 return GetUIThreadTaskRunner({});
196 int32_t PepperTCPSocketMessageFilter::OnResourceMessageReceived(
197 const IPC::Message& msg,
198 ppapi::host::HostMessageContext* context) {
199 PPAPI_BEGIN_MESSAGE_MAP(PepperTCPSocketMessageFilter, msg)
200 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Bind, OnMsgBind)
201 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Connect,
203 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
204 PpapiHostMsg_TCPSocket_ConnectWithNetAddress,
205 OnMsgConnectWithNetAddress)
206 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_SSLHandshake,
208 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Read, OnMsgRead)
209 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Write, OnMsgWrite)
210 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Listen,
212 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TCPSocket_Accept,
214 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TCPSocket_Close,
216 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_SetOption,
218 PPAPI_END_MESSAGE_MAP()
219 LOG(ERROR) << "Resource message unresolved";
220 return PP_ERROR_FAILED;
223 void PepperTCPSocketMessageFilter::OnHostDestroyed() {
224 DCHECK_CURRENTLY_ON(BrowserThread::UI);
225 host_->RemoveInstanceObserver(instance_, this);
229 void PepperTCPSocketMessageFilter::OnComplete(
231 const net::ResolveErrorInfo& resolve_error_info,
232 const absl::optional<net::AddressList>& resolved_addresses,
233 const absl::optional<net::HostResolverEndpointResults>&
234 endpoint_results_with_metadata) {
235 DCHECK_CURRENTLY_ON(BrowserThread::UI);
238 if (!host_resolve_context_.is_valid())
241 ppapi::host::ReplyMessageContext context = host_resolve_context_;
242 host_resolve_context_ = ppapi::host::ReplyMessageContext();
244 if (!state_.IsPending(TCPSocketState::CONNECT)) {
245 DCHECK(state_.state() == TCPSocketState::CLOSED);
246 SendConnectError(context, PP_ERROR_FAILED);
250 if (result != net::OK) {
251 SendConnectError(context, NetErrorToPepperError(resolve_error_info.error));
252 state_.CompletePendingTransition(false);
256 StartConnect(context, resolved_addresses.value());
259 void PepperTCPSocketMessageFilter::OnReadError(int net_error) {
260 // If this method is called more than once, or |net_error| isn't an allowed
261 // value, just ignore the message.
262 if (pending_read_pp_error_ != PP_OK_COMPLETIONPENDING || net_error > 0 ||
263 net_error == net::ERR_IO_PENDING) {
267 pending_read_pp_error_ = NetErrorToPepperError(net_error);
268 // Complete pending read with the error message if there's a pending read, and
269 // the read data pipe has already been closed. If the pipe is still open, need
270 // to wait until all data has been read before can start failing reads.
271 if (pending_read_context_.is_valid() && !receive_stream_) {
276 void PepperTCPSocketMessageFilter::OnWriteError(int net_error) {
277 // If this method is called more than once, or |net_error| isn't an allowed
278 // value, just ignore the message.
279 if (pending_write_pp_error_ != PP_OK_COMPLETIONPENDING || net_error > 0 ||
280 net_error == net::ERR_IO_PENDING) {
284 pending_write_pp_error_ = NetErrorToPepperError(net_error);
285 // Complete pending write with the error message if there's a pending write,
286 // and the write data pipe has already been closed.
287 if (pending_write_context_.is_valid() && !send_stream_)
291 void PepperTCPSocketMessageFilter::OnSocketObserverError() {
292 // Note that this method may be called while a connection is still being made.
293 socket_observer_receiver_.reset();
295 // Treat this as a read and write error. If read and write errors have already
296 // been received, these calls will do nothing.
297 OnReadError(PP_ERROR_FAILED);
298 OnWriteError(PP_ERROR_FAILED);
301 int32_t PepperTCPSocketMessageFilter::OnMsgBind(
302 const ppapi::host::HostMessageContext* context,
303 const PP_NetAddress_Private& net_addr) {
304 DCHECK_CURRENTLY_ON(BrowserThread::UI);
306 // This is only supported by PPB_TCPSocket v1.1 or above.
307 if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
308 LOG(ERROR) << "Supported only by PPB_TCPSocket v1.1 or above";
310 return PP_ERROR_NOACCESS;
313 if (!pepper_socket_utils::CanUseSocketAPIs(
314 external_plugin_, false /* private_api */, nullptr,
315 render_process_id_, render_frame_id_)) {
316 LOG(ERROR) << "Cannot use Socket APIs";
317 return PP_ERROR_NOACCESS;
320 if (state_.IsPending(TCPSocketState::BIND))
321 return PP_ERROR_INPROGRESS;
323 if (!state_.IsValidTransition(TCPSocketState::BIND))
324 return PP_ERROR_FAILED;
326 DCHECK(!bound_socket_);
327 DCHECK(!connected_socket_);
328 DCHECK(!server_socket_);
331 net::IPAddressBytes address;
333 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
335 state_.DoTransition(TCPSocketState::BIND, false);
336 return PP_ERROR_ADDRESS_INVALID;
339 network::mojom::NetworkContext* network_context = GetNetworkContext();
340 if (!network_context)
341 return PP_ERROR_FAILED;
343 // The network service doesn't allow binding a socket without first
344 // specifying if it's going to be used as a read or write socket,
345 // so just hold onto the address for now, without actually binding anything.
346 bind_input_addr_ = net_addr;
348 state_.SetPendingTransition(TCPSocketState::BIND);
349 network_context->CreateTCPBoundSocket(
350 net::IPEndPoint(net::IPAddress(address), port),
351 pepper_socket_utils::PepperTCPNetworkAnnotationTag(),
352 bound_socket_.BindNewPipeAndPassReceiver(),
353 mojo::WrapCallbackWithDefaultInvokeIfNotRun(
354 base::BindOnce(&PepperTCPSocketMessageFilter::OnBindCompleted,
355 weak_ptr_factory_.GetWeakPtr(),
356 context->MakeReplyMessageContext()),
357 net::ERR_FAILED, absl::nullopt /* local_addr */));
359 return PP_OK_COMPLETIONPENDING;
362 int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
363 const ppapi::host::HostMessageContext* context,
364 const std::string& host,
366 DCHECK_CURRENTLY_ON(BrowserThread::UI);
368 // This is only supported by PPB_TCPSocket_Private.
369 if (!IsPrivateAPI()) {
371 LOG(ERROR) << "Supported only by PPB_TCPSocket_Private";
372 return PP_ERROR_NOACCESS;
375 SocketPermissionRequest request(SocketPermissionRequest::TCP_CONNECT, host,
377 if (!pepper_socket_utils::CanUseSocketAPIs(
378 external_plugin_, true /* private_api */, &request,
379 render_process_id_, render_frame_id_)) {
380 LOG(ERROR) << "Insufficient permissions";
381 return PP_ERROR_NOACCESS;
384 if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
385 NOTREACHED() << "This shouldn't be reached since the renderer only tries "
386 << "to connect once.";
387 return PP_ERROR_FAILED;
390 network::mojom::NetworkContext* network_context = GetNetworkContext();
391 if (!network_context)
392 return PP_ERROR_FAILED;
394 RenderFrameHost* render_frame_host =
395 RenderFrameHost::FromID(render_process_id_, render_frame_id_);
396 if (!render_frame_host)
397 return PP_ERROR_FAILED;
399 // Intentionally using a HostPortPair because scheme isn't specified.
400 // TODO(mmenke): Pass in correct NetworkAnonymizationKey.
401 network_context->ResolveHost(
402 network::mojom::HostResolverHost::NewHostPortPair(
403 net::HostPortPair(host, port)),
404 render_frame_host->GetIsolationInfoForSubresources()
405 .network_anonymization_key(),
406 nullptr, receiver_.BindNewPipeAndPassRemote());
407 receiver_.set_disconnect_handler(base::BindOnce(
408 &PepperTCPSocketMessageFilter::OnComplete, base::Unretained(this),
409 net::ERR_NAME_NOT_RESOLVED, net::ResolveErrorInfo(net::ERR_FAILED),
410 /*resolved_addresses=*/absl::nullopt,
411 /*endpoint_results_with_metadata=*/absl::nullopt));
413 state_.SetPendingTransition(TCPSocketState::CONNECT);
414 host_resolve_context_ = context->MakeReplyMessageContext();
415 return PP_OK_COMPLETIONPENDING;
418 int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress(
419 const ppapi::host::HostMessageContext* context,
420 const PP_NetAddress_Private& net_addr) {
421 DCHECK_CURRENTLY_ON(BrowserThread::UI);
423 SocketPermissionRequest request =
424 pepper_socket_utils::CreateSocketPermissionRequest(
425 SocketPermissionRequest::TCP_CONNECT, net_addr);
426 if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, IsPrivateAPI(),
427 &request, render_process_id_,
429 LOG(ERROR) << "Insufficient permissions: Cannot connect with NetAddress";
430 return PP_ERROR_NOACCESS;
433 if (!state_.IsValidTransition(TCPSocketState::CONNECT))
434 return PP_ERROR_FAILED;
436 state_.SetPendingTransition(TCPSocketState::CONNECT);
438 net::IPAddressBytes address;
440 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
442 state_.CompletePendingTransition(false);
443 return PP_ERROR_ADDRESS_INVALID;
447 context->MakeReplyMessageContext(),
448 net::AddressList(net::IPEndPoint(net::IPAddress(address), port)));
449 return PP_OK_COMPLETIONPENDING;
452 int32_t PepperTCPSocketMessageFilter::OnMsgSSLHandshake(
453 const ppapi::host::HostMessageContext* context,
454 const std::string& server_name,
455 uint16_t server_port,
456 const std::vector<std::vector<char>>& trusted_certs,
457 const std::vector<std::vector<char>>& untrusted_certs) {
458 DCHECK_CURRENTLY_ON(BrowserThread::UI);
460 // Allow to do SSL handshake only if currently the socket has been connected
461 // and there isn't pending read or write.
462 if (!state_.IsValidTransition(TCPSocketState::SSL_CONNECT) ||
463 pending_read_context_.is_valid() || pending_write_context_.is_valid()) {
464 LOG(ERROR) << "Socket not connected or pending read or write";
465 return PP_ERROR_FAILED;
468 // If there's a pending read or write error, fail the request with that.
469 if (pending_read_pp_error_ != PP_OK_COMPLETIONPENDING) {
470 if (pending_read_pp_error_ == PP_OK)
471 pending_read_pp_error_ = PP_ERROR_FAILED;
472 return pending_read_pp_error_;
475 if (pending_write_pp_error_ != PP_OK_COMPLETIONPENDING) {
476 if (pending_write_pp_error_ == PP_OK)
477 pending_write_pp_error_ = PP_ERROR_FAILED;
478 return pending_write_pp_error_;
481 // TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
483 // Close all Mojo pipes except |connected_socket_|.
484 receive_stream_.reset();
485 read_watcher_.reset();
486 send_stream_.reset();
487 write_watcher_.reset();
488 socket_observer_receiver_.reset();
490 state_.SetPendingTransition(TCPSocketState::SSL_CONNECT);
492 network::mojom::TLSClientSocketOptionsPtr tls_client_socket_options =
493 network::mojom::TLSClientSocketOptions::New();
494 tls_client_socket_options->send_ssl_info = true;
495 net::HostPortPair host_port_pair(server_name, server_port);
496 connected_socket_->UpgradeToTLS(
497 host_port_pair, std::move(tls_client_socket_options),
498 pepper_socket_utils::PepperTCPNetworkAnnotationTag(),
499 tls_client_socket_.BindNewPipeAndPassReceiver(),
500 socket_observer_receiver_.BindNewPipeAndPassRemote(),
501 mojo::WrapCallbackWithDefaultInvokeIfNotRun(
502 base::BindOnce(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted,
503 base::Unretained(this),
504 context->MakeReplyMessageContext()),
505 net::ERR_FAILED, mojo::ScopedDataPipeConsumerHandle(),
506 mojo::ScopedDataPipeProducerHandle(), absl::nullopt /* ssl_info */));
508 socket_observer_receiver_.set_disconnect_handler(
509 base::BindOnce(&PepperTCPSocketMessageFilter::OnSocketObserverError,
510 base::Unretained(this)));
512 return PP_OK_COMPLETIONPENDING;
515 int32_t PepperTCPSocketMessageFilter::OnMsgRead(
516 const ppapi::host::HostMessageContext* context,
517 int32_t bytes_to_read) {
518 DCHECK_CURRENTLY_ON(BrowserThread::UI);
519 // This only covers the case where the socket was explicitly closed from the
520 // caller, or the filter is being destroyed. Read errors and Mojo errors are
521 // handled in TryRead().
522 if (!state_.IsConnected()) {
523 LOG(ERROR) << "Not connected";
524 return PP_ERROR_FAILED;
526 if (pending_read_context_.is_valid())
527 return PP_ERROR_INPROGRESS;
528 if (bytes_to_read <= 0 ||
529 bytes_to_read > TCPSocketResourceConstants::kMaxReadSize) {
530 LOG(ERROR) << "Incorrect number of bytes to read - " << bytes_to_read
531 << " Should be <= " << TCPSocketResourceConstants::kMaxReadSize
533 return PP_ERROR_BADARGUMENT;
536 pending_read_context_ = context->MakeReplyMessageContext();
537 pending_read_size_ = static_cast<uint32_t>(bytes_to_read);
539 return PP_OK_COMPLETIONPENDING;
542 int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
543 const ppapi::host::HostMessageContext* context,
544 const ppapi::DataView& data) {
545 DCHECK_CURRENTLY_ON(BrowserThread::UI);
547 if (!state_.IsConnected()) {
548 LOG(ERROR) << "Not connected";
549 return PP_ERROR_FAILED;
551 if (pending_write_context_.is_valid())
552 return PP_ERROR_INPROGRESS;
554 DCHECK_EQ(0u, pending_write_data_.size);
555 DCHECK_EQ(0u, pending_write_bytes_written_);
557 size_t data_size = data.size;
558 if (data_size == 0 ||
560 static_cast<size_t>(TCPSocketResourceConstants::kMaxWriteSize)) {
561 LOG(ERROR) << "Invalid data size - " << data_size << " should be <= "
562 << static_cast<size_t>(TCPSocketResourceConstants::kMaxWriteSize)
564 return PP_ERROR_BADARGUMENT;
567 pending_write_data_ = data;
568 pending_write_context_ = context->MakeReplyMessageContext();
570 return PP_OK_COMPLETIONPENDING;
573 int32_t PepperTCPSocketMessageFilter::OnMsgListen(
574 const ppapi::host::HostMessageContext* context,
576 DCHECK_CURRENTLY_ON(BrowserThread::UI);
578 if (state_.IsPending(TCPSocketState::LISTEN))
579 return PP_ERROR_INPROGRESS;
581 if (!state_.IsValidTransition(TCPSocketState::LISTEN))
582 return PP_ERROR_FAILED;
584 // This is only supported by PPB_TCPSocket v1.1 or above.
585 if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
586 LOG(ERROR) << "Supported only by PPB_TCPSocket v1.1 or above";
588 return PP_ERROR_NOACCESS;
591 SocketPermissionRequest request =
592 pepper_socket_utils::CreateSocketPermissionRequest(
593 SocketPermissionRequest::TCP_LISTEN, bind_input_addr_);
594 if (!pepper_socket_utils::CanUseSocketAPIs(
595 external_plugin_, false /* private_api */, &request,
596 render_process_id_, render_frame_id_)) {
597 LOG(ERROR) << "Insufficient permissions";
598 return PP_ERROR_NOACCESS;
601 DCHECK(bound_socket_);
602 DCHECK(!server_socket_);
604 state_.SetPendingTransition(TCPSocketState::LISTEN);
606 bound_socket_->Listen(
607 backlog, server_socket_.BindNewPipeAndPassReceiver(),
608 mojo::WrapCallbackWithDefaultInvokeIfNotRun(
609 base::BindOnce(&PepperTCPSocketMessageFilter::OnListenCompleted,
610 base::Unretained(this),
611 context->MakeReplyMessageContext()),
613 return PP_OK_COMPLETIONPENDING;
616 int32_t PepperTCPSocketMessageFilter::OnMsgAccept(
617 const ppapi::host::HostMessageContext* context) {
618 DCHECK_CURRENTLY_ON(BrowserThread::UI);
620 if (pending_accept_) {
621 LOG(WARNING) << "Pending accept";
622 return PP_ERROR_INPROGRESS;
624 if (state_.state() != TCPSocketState::LISTENING) {
625 LOG(ERROR) << "Invalid socket state: " << static_cast<int>(state_.state());
626 return PP_ERROR_FAILED;
628 DCHECK(server_socket_);
630 pending_accept_ = true;
632 mojo::PendingRemote<network::mojom::SocketObserver> socket_observer;
633 auto socket_observer_receiver =
634 socket_observer.InitWithNewPipeAndPassReceiver();
635 server_socket_->Accept(
636 std::move(socket_observer),
637 mojo::WrapCallbackWithDefaultInvokeIfNotRun(
638 base::BindOnce(&PepperTCPSocketMessageFilter::OnAcceptCompleted,
639 base::Unretained(this),
640 context->MakeReplyMessageContext(),
641 std::move(socket_observer_receiver)),
642 net::ERR_FAILED, absl::nullopt /* remote_addr */, mojo::NullRemote(),
643 mojo::ScopedDataPipeConsumerHandle(),
644 mojo::ScopedDataPipeProducerHandle()));
645 return PP_OK_COMPLETIONPENDING;
648 int32_t PepperTCPSocketMessageFilter::OnMsgClose(
649 const ppapi::host::HostMessageContext* context) {
650 DCHECK_CURRENTLY_ON(BrowserThread::UI);
651 if (state_.state() == TCPSocketState::CLOSED)
658 int32_t PepperTCPSocketMessageFilter::OnMsgSetOption(
659 const ppapi::host::HostMessageContext* context,
660 PP_TCPSocket_Option name,
661 const ppapi::SocketOptionData& value) {
662 DCHECK_CURRENTLY_ON(BrowserThread::UI);
664 // Options are only applied if |this| is currently being used as a client
665 // socket, or is going to be used as one - they are ignored for server
668 case PP_TCPSOCKET_OPTION_NO_DELAY: {
669 bool boolean_value = false;
670 if (!value.GetBool(&boolean_value)) {
671 LOG(ERROR) << "Invalid socket option";
672 return PP_ERROR_BADARGUMENT;
674 // If |connected_socket_| is connecting or has connected, pass the setting
676 if (connected_socket_.is_bound()) {
677 connected_socket_->SetNoDelay(
679 // Callback that converts a bool to a net error code which it then
680 // passes to the common completion callback routine.
682 [](base::OnceCallback<void(int)> completion_callback,
684 std::move(completion_callback)
685 .Run(success ? net::OK : net::ERR_FAILED);
687 CreateCompletionCallback<
688 PpapiPluginMsg_TCPSocket_SetOptionReply>(context)));
689 return PP_OK_COMPLETIONPENDING;
692 // TCPConnectedSocket instance is not yet created. So remember the value
695 socket_options_ |= SOCKET_OPTION_NODELAY;
697 socket_options_ &= ~SOCKET_OPTION_NODELAY;
701 case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE: {
702 int32_t integer_value = 0;
703 if (!value.GetInt32(&integer_value) || integer_value <= 0 ||
704 integer_value > TCPSocketResourceConstants::kMaxSendBufferSize) {
705 LOG(ERROR) << "Invalid send buffer size value - " << integer_value
707 << TCPSocketResourceConstants::kMaxSendBufferSize
709 return PP_ERROR_BADARGUMENT;
712 // If |connected_socket_| is connecting or has connected, pass the setting
714 if (connected_socket_.is_bound()) {
715 connected_socket_->SetSendBufferSize(
717 CreateCompletionCallback<PpapiPluginMsg_TCPSocket_SetOptionReply>(
719 return PP_OK_COMPLETIONPENDING;
722 // TCPSocket instance is not yet created. So remember the value here.
723 socket_options_ |= SOCKET_OPTION_SNDBUF_SIZE;
724 sndbuf_size_ = integer_value;
727 case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: {
728 int32_t integer_value = 0;
729 if (!value.GetInt32(&integer_value) || integer_value <= 0 ||
730 integer_value > TCPSocketResourceConstants::kMaxReceiveBufferSize) {
731 LOG(ERROR) << "Invalid receive buffer size - " << integer_value
733 << TCPSocketResourceConstants::kMaxReceiveBufferSize
735 return PP_ERROR_BADARGUMENT;
738 // If |connected_socket_| is connecting or has connected, pass the setting
740 if (connected_socket_.is_bound()) {
741 connected_socket_->SetReceiveBufferSize(
743 CreateCompletionCallback<PpapiPluginMsg_TCPSocket_SetOptionReply>(
745 return PP_OK_COMPLETIONPENDING;
748 // TCPConnectedSocket instance is not yet created. So remember the value
750 socket_options_ |= SOCKET_OPTION_RCVBUF_SIZE;
751 rcvbuf_size_ = integer_value;
757 return PP_ERROR_BADARGUMENT;
762 void PepperTCPSocketMessageFilter::TryRead() {
763 DCHECK_CURRENTLY_ON(BrowserThread::UI);
764 DCHECK(state_.IsConnected());
765 DCHECK(pending_read_context_.is_valid());
766 DCHECK_GT(pending_read_size_, 0u);
768 // This loop's body will generally run only once, unless there's a read error,
769 // in which case, it will start over, to re-apply the initial logic.
771 // As long as the read stream is still open, try to read data, even if a
772 // read error has been received from the SocketObserver, as there may still
773 // be data on the pipe.
774 if (!receive_stream_.is_valid()) {
775 // If no read error has been received yet, wait to receive one through
776 // the SocketObserver interface.
777 if (pending_read_pp_error_ == PP_OK_COMPLETIONPENDING) {
778 DCHECK(socket_observer_receiver_.is_bound());
782 // Otherwise, pass along the read error.
783 SendReadError(pending_read_pp_error_);
784 // If the socket was closed gracefully, only return OK for a single
786 if (pending_read_pp_error_ == PP_OK)
787 pending_read_pp_error_ = PP_ERROR_FAILED;
791 DCHECK(read_watcher_);
792 const void* buffer = nullptr;
793 uint32_t num_bytes = 0;
794 int mojo_result = receive_stream_->BeginReadData(&buffer, &num_bytes,
795 MOJO_READ_DATA_FLAG_NONE);
796 if (mojo_result == MOJO_RESULT_SHOULD_WAIT) {
797 read_watcher_->ArmOrNotify();
801 // On a Mojo pipe error (which may indicate a graceful close, network error,
802 // or network service crash), close read pipe and restart the loop.
803 if (mojo_result != MOJO_RESULT_OK) {
804 read_watcher_.reset();
805 receive_stream_.reset();
809 // This is guaranteed by Mojo.
810 DCHECK_GT(num_bytes, 0u);
812 uint32_t bytes_to_copy = std::min(num_bytes, pending_read_size_);
813 SendReadReply(PP_OK, ppapi::DataView(reinterpret_cast<const char*>(buffer),
815 receive_stream_->EndReadData(bytes_to_copy);
820 void PepperTCPSocketMessageFilter::TryWrite() {
821 DCHECK_CURRENTLY_ON(BrowserThread::UI);
822 DCHECK(state_.IsConnected());
823 DCHECK(pending_write_context_.is_valid());
824 DCHECK_NE(pending_write_data_.size, 0u);
825 DCHECK_LT(pending_write_bytes_written_, pending_write_data_.size);
827 // The structure of this code largely mirrors TryRead() above, with a couple
828 // differences. The loop will repeat until all bytes are written, there's an
829 // error, or no more buffer space is available. Also, it's possible for a
830 // Mojo write to succeed, but a write to the underlying socket to fail. In
831 // that case, the failure might not be returned to the caller until it tries
832 // to write again. Since the socket APIs themselves don't guarantee that
833 // data has been successfully received by the remote server on success, this
834 // should not cause unexpected problems for consumers.
836 if (!send_stream_.is_valid()) {
837 if (pending_write_pp_error_ == PP_OK_COMPLETIONPENDING) {
838 DCHECK(socket_observer_receiver_.is_bound());
841 SendWriteReply(pending_write_pp_error_);
842 // Mirror handling of "OK" read errors, only sending "OK" for a single
843 // write, though getting "OK" from a write is probably nonsense, anyways.
844 if (pending_write_pp_error_ == PP_OK)
845 pending_write_pp_error_ = PP_ERROR_FAILED;
849 DCHECK(write_watcher_);
852 pending_write_data_.size - pending_write_bytes_written_;
853 DCHECK_GT(num_bytes, 0u);
854 int mojo_result = send_stream_->WriteData(
855 pending_write_data_.data + pending_write_bytes_written_, &num_bytes,
856 MOJO_WRITE_DATA_FLAG_NONE);
857 if (mojo_result == MOJO_RESULT_SHOULD_WAIT) {
858 write_watcher_->ArmOrNotify();
862 // On a Mojo pipe error (which may indicate a graceful close, network error,
863 // or network service crash), close write pipe and restart the loop.
864 if (mojo_result != MOJO_RESULT_OK) {
865 write_watcher_.reset();
866 send_stream_.reset();
870 // This is guaranteed by Mojo.
871 DCHECK_GT(num_bytes, 0u);
873 pending_write_bytes_written_ += num_bytes;
874 // If all bytes were written, nothing left to do.
875 if (pending_write_bytes_written_ == pending_write_data_.size) {
876 SendWriteReply(pending_write_bytes_written_);
882 void PepperTCPSocketMessageFilter::StartConnect(
883 const ppapi::host::ReplyMessageContext& context,
884 const net::AddressList& address_list) {
885 DCHECK_CURRENTLY_ON(BrowserThread::UI);
886 DCHECK(state_.IsPending(TCPSocketState::CONNECT));
887 DCHECK(!address_list.empty());
889 auto socket_observer = socket_observer_receiver_.BindNewPipeAndPassRemote();
890 socket_observer_receiver_.set_disconnect_handler(
891 base::BindOnce(&PepperTCPSocketMessageFilter::OnSocketObserverError,
892 base::Unretained(this)));
894 network::mojom::TCPConnectedSocketOptionsPtr socket_options =
895 network::mojom::TCPConnectedSocketOptions::New();
896 socket_options->no_delay = !!(socket_options_ & SOCKET_OPTION_NODELAY);
897 if (socket_options_ & SOCKET_OPTION_RCVBUF_SIZE)
898 socket_options->receive_buffer_size = rcvbuf_size_;
899 if (socket_options_ & SOCKET_OPTION_SNDBUF_SIZE)
900 socket_options->send_buffer_size = sndbuf_size_;
902 network::mojom::NetworkContext::CreateTCPConnectedSocketCallback callback =
903 mojo::WrapCallbackWithDefaultInvokeIfNotRun(
904 base::BindOnce(&PepperTCPSocketMessageFilter::OnConnectCompleted,
905 weak_ptr_factory_.GetWeakPtr(), context),
906 net::ERR_FAILED, absl::nullopt, absl::nullopt,
907 mojo::ScopedDataPipeConsumerHandle(),
908 mojo::ScopedDataPipeProducerHandle());
910 bound_socket_->Connect(address_list, std::move(socket_options),
911 connected_socket_.BindNewPipeAndPassReceiver(),
912 std::move(socket_observer), std::move(callback));
914 network::mojom::NetworkContext* network_context = GetNetworkContext();
915 if (!network_context) {
916 // This will delete |callback|, which will invoke OnConnectCompleted()
920 network_context->CreateTCPConnectedSocket(
921 absl::nullopt /* local_addr */, address_list, std::move(socket_options),
922 pepper_socket_utils::PepperTCPNetworkAnnotationTag(),
923 connected_socket_.BindNewPipeAndPassReceiver(),
924 std::move(socket_observer), std::move(callback));
928 void PepperTCPSocketMessageFilter::OnConnectCompleted(
929 const ppapi::host::ReplyMessageContext& context,
931 const absl::optional<net::IPEndPoint>& local_addr,
932 const absl::optional<net::IPEndPoint>& peer_addr,
933 mojo::ScopedDataPipeConsumerHandle receive_stream,
934 mojo::ScopedDataPipeProducerHandle send_stream) {
935 DCHECK_CURRENTLY_ON(BrowserThread::UI);
937 int32_t pp_result = NetErrorToPepperError(net_result);
939 if (state_.state() == TCPSocketState::CLOSED) {
940 // If this is called as a result of Close() being invoked and closing the
941 // pipe, fail the request without doing anything.
942 DCHECK_EQ(net_result, net::ERR_FAILED);
943 SendConnectError(context, pp_result);
947 DCHECK(state_.IsPending(TCPSocketState::CONNECT));
950 if (pp_result != PP_OK)
953 PP_NetAddress_Private pp_local_addr =
954 NetAddressPrivateImpl::kInvalidNetAddress;
955 PP_NetAddress_Private pp_remote_addr =
956 NetAddressPrivateImpl::kInvalidNetAddress;
957 if (!local_addr || !peer_addr ||
958 !NetAddressPrivateImpl::IPEndPointToNetAddress(
959 local_addr->address().bytes(), local_addr->port(),
961 !NetAddressPrivateImpl::IPEndPointToNetAddress(
962 peer_addr->address().bytes(), peer_addr->port(), &pp_remote_addr)) {
963 pp_result = PP_ERROR_ADDRESS_INVALID;
967 SetStreams(std::move(receive_stream), std::move(send_stream));
969 bound_socket_.reset();
971 SendConnectReply(context, PP_OK, pp_local_addr, pp_remote_addr);
972 state_.CompletePendingTransition(true);
978 // This can happen even when the network service is behaving correctly, as
979 // we may see the |socket_observer_receiver_| closed before receiving an
981 pending_read_pp_error_ = PP_OK_COMPLETIONPENDING;
982 pending_write_pp_error_ = PP_OK_COMPLETIONPENDING;
985 SendConnectError(context, pp_result);
987 if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
988 // In order to maintain backward compatibility, allow further attempts
989 // to connect the socket.
990 state_ = TCPSocketState(TCPSocketState::INITIAL);
994 void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted(
995 const ppapi::host::ReplyMessageContext& context,
997 mojo::ScopedDataPipeConsumerHandle receive_stream,
998 mojo::ScopedDataPipeProducerHandle send_stream,
999 const absl::optional<net::SSLInfo>& ssl_info) {
1000 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1002 int pp_result = NetErrorToPepperError(net_result);
1003 if (state_.state() == TCPSocketState::CLOSED) {
1004 // If this is called as a result of Close() being invoked and closing the
1005 // pipe, fail the request without doing anything.
1006 DCHECK_EQ(net_result, net::ERR_FAILED);
1007 SendSSLHandshakeReply(context, pp_result, absl::nullopt /* ssl_info */);
1011 DCHECK(state_.IsPending(TCPSocketState::SSL_CONNECT));
1013 if (pp_result == PP_OK && !ssl_info)
1014 pp_result = PP_ERROR_FAILED;
1016 state_.CompletePendingTransition(pp_result == PP_OK);
1018 if (pp_result != PP_OK) {
1021 SetStreams(std::move(receive_stream), std::move(send_stream));
1024 SendSSLHandshakeReply(context, pp_result, ssl_info);
1027 void PepperTCPSocketMessageFilter::OnBindCompleted(
1028 const ppapi::host::ReplyMessageContext& context,
1030 const absl::optional<net::IPEndPoint>& local_addr) {
1031 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1033 int pp_result = NetErrorToPepperError(net_result);
1034 if (state_.state() == TCPSocketState::CLOSED) {
1035 // If this is called as a result of Close() being invoked and closing the
1036 // pipe, fail the request without doing anything.
1037 DCHECK_EQ(net_result, net::ERR_FAILED);
1038 SendBindError(context, pp_result);
1042 DCHECK(bound_socket_);
1043 DCHECK(state_.IsPending(TCPSocketState::BIND));
1045 PP_NetAddress_Private bound_address =
1046 NetAddressPrivateImpl::kInvalidNetAddress;
1047 if (pp_result == PP_OK &&
1048 (!local_addr || !NetAddressPrivateImpl::IPEndPointToNetAddress(
1049 local_addr->address().bytes(), local_addr->port(),
1051 pp_result = PP_ERROR_ADDRESS_INVALID;
1054 if (pp_result != PP_OK) {
1055 bound_socket_.reset();
1057 bind_output_ip_endpoint_ = *local_addr;
1060 SendBindReply(context, pp_result, bound_address);
1061 state_.CompletePendingTransition(pp_result == PP_OK);
1064 void PepperTCPSocketMessageFilter::OnListenCompleted(
1065 const ppapi::host::ReplyMessageContext& context,
1067 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1069 int pp_result = NetErrorToPepperError(net_result);
1070 if (state_.state() == TCPSocketState::CLOSED) {
1071 // If this is called as a result of Close() being invoked and closing the
1072 // pipe, fail the request without doing anything.
1073 DCHECK_EQ(net_result, net::ERR_FAILED);
1074 SendListenReply(context, pp_result);
1078 DCHECK(state_.IsPending(TCPSocketState::LISTEN));
1080 #if BUILDFLAG(IS_CHROMEOS_ASH)
1081 if (pp_result == PP_OK) {
1082 OpenFirewallHole(context);
1085 #endif // BUILDFLAG(IS_CHROMEOS_ASH)
1087 SendListenReply(context, pp_result);
1088 state_.CompletePendingTransition(pp_result == PP_OK);
1089 if (pp_result != PP_OK)
1093 void PepperTCPSocketMessageFilter::OnAcceptCompleted(
1094 const ppapi::host::ReplyMessageContext& context,
1095 mojo::PendingReceiver<network::mojom::SocketObserver>
1096 socket_observer_receiver,
1098 const absl::optional<net::IPEndPoint>& remote_addr,
1099 mojo::PendingRemote<network::mojom::TCPConnectedSocket> connected_socket,
1100 mojo::ScopedDataPipeConsumerHandle receive_stream,
1101 mojo::ScopedDataPipeProducerHandle send_stream) {
1102 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1103 DCHECK(pending_accept_);
1105 pending_accept_ = false;
1106 if (net_result != net::OK) {
1107 SendAcceptError(context, NetErrorToPepperError(net_result));
1111 if (!remote_addr || !connected_socket.is_valid()) {
1112 SendAcceptError(context, NetErrorToPepperError(net_result));
1116 DCHECK(socket_observer_receiver.is_valid());
1118 PP_NetAddress_Private pp_remote_addr =
1119 NetAddressPrivateImpl::kInvalidNetAddress;
1121 if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
1122 remote_addr->address().bytes(), remote_addr->port(),
1124 SendAcceptError(context, PP_ERROR_ADDRESS_INVALID);
1128 PP_NetAddress_Private bound_address =
1129 NetAddressPrivateImpl::kInvalidNetAddress;
1130 bool success = NetAddressPrivateImpl::IPEndPointToNetAddress(
1131 bind_output_ip_endpoint_.address().bytes(),
1132 bind_output_ip_endpoint_.port(), &bound_address);
1133 // This conversion should succeed, since it succeeded in OnBindComplete()
1137 GetUIThreadTaskRunner({})->PostTask(
1139 base::BindOnce(&PepperTCPSocketMessageFilter::OnAcceptCompletedOnIOThread,
1140 this, context, std::move(connected_socket),
1141 std::move(socket_observer_receiver),
1142 std::move(receive_stream), std::move(send_stream),
1143 bound_address, pp_remote_addr));
1146 void PepperTCPSocketMessageFilter::OnAcceptCompletedOnIOThread(
1147 const ppapi::host::ReplyMessageContext& context,
1148 mojo::PendingRemote<network::mojom::TCPConnectedSocket> connected_socket,
1149 mojo::PendingReceiver<network::mojom::SocketObserver>
1150 socket_observer_receiver,
1151 mojo::ScopedDataPipeConsumerHandle receive_stream,
1152 mojo::ScopedDataPipeProducerHandle send_stream,
1153 PP_NetAddress_Private pp_local_addr,
1154 PP_NetAddress_Private pp_remote_addr) {
1155 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1157 if (!host_->IsValidInstance(instance_)) {
1158 // The instance has been removed while Accept was in progress. This object
1159 // should be destroyed and cleaned up after we release the reference we're
1160 // holding as a part of this function running so we just return without
1165 // |factory_| is guaranteed to be non-NULL here. Only those instances created
1166 // in CONNECTED state have a NULL |factory_|, while getting here requires
1170 std::unique_ptr<ppapi::host::ResourceHost> host =
1171 factory_->CreateAcceptedTCPSocket(
1172 instance_, version_, std::move(connected_socket),
1173 std::move(socket_observer_receiver), std::move(receive_stream),
1174 std::move(send_stream));
1176 SendAcceptError(context, PP_ERROR_NOSPACE);
1180 int pending_host_id =
1181 host_->GetPpapiHost()->AddPendingResourceHost(std::move(host));
1182 if (pending_host_id) {
1183 SendAcceptReply(context, PP_OK, pending_host_id, pp_local_addr,
1186 SendAcceptError(context, PP_ERROR_NOSPACE);
1190 void PepperTCPSocketMessageFilter::SetStreams(
1191 mojo::ScopedDataPipeConsumerHandle receive_stream,
1192 mojo::ScopedDataPipeProducerHandle send_stream) {
1193 DCHECK(!read_watcher_);
1194 DCHECK(!write_watcher_);
1196 receive_stream_ = std::move(receive_stream);
1197 read_watcher_ = std::make_unique<mojo::SimpleWatcher>(
1198 FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL);
1199 read_watcher_->Watch(
1200 receive_stream_.get(),
1201 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
1202 MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
1203 base::BindRepeating(
1204 [](PepperTCPSocketMessageFilter* message_filter,
1205 MojoResult /* result */,
1206 const mojo::HandleSignalsState& /* state */) {
1207 // TryRead will correctly handle both cases (data ready to be
1208 // read, and the pipe was closed).
1209 message_filter->TryRead();
1211 base::Unretained(this)));
1213 send_stream_ = std::move(send_stream);
1214 write_watcher_ = std::make_unique<mojo::SimpleWatcher>(
1215 FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL);
1216 write_watcher_->Watch(
1218 MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
1219 MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
1220 base::BindRepeating(
1221 [](PepperTCPSocketMessageFilter* message_filter,
1222 MojoResult /* result */,
1223 const mojo::HandleSignalsState& /* state */) {
1224 // TryRead will correctly handle both cases (data ready to be
1225 // read, and the pipe was closed).
1226 message_filter->TryWrite();
1228 base::Unretained(this)));
1231 #if BUILDFLAG(IS_CHROMEOS_ASH)
1232 void PepperTCPSocketMessageFilter::OpenFirewallHole(
1233 const ppapi::host::ReplyMessageContext& context) {
1234 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1235 pepper_socket_utils::OpenTCPFirewallHole(
1236 bind_output_ip_endpoint_,
1237 base::BindOnce(&PepperTCPSocketMessageFilter::OnFirewallHoleOpened, this,
1241 void PepperTCPSocketMessageFilter::OnFirewallHoleOpened(
1242 const ppapi::host::ReplyMessageContext& context,
1243 std::unique_ptr<ash::FirewallHole> hole) {
1244 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1245 DCHECK(state_.IsPending(TCPSocketState::LISTEN));
1246 LOG_IF(WARNING, !hole.get()) << "Firewall hole could not be opened.";
1247 firewall_hole_.reset(hole.release());
1249 SendListenReply(context, PP_OK);
1250 state_.CompletePendingTransition(true);
1252 #endif // BUILDFLAG(IS_CHROMEOS_ASH)
1254 void PepperTCPSocketMessageFilter::SendBindReply(
1255 const ppapi::host::ReplyMessageContext& context,
1257 const PP_NetAddress_Private& local_addr) {
1258 ppapi::host::ReplyMessageContext reply_context(context);
1259 reply_context.params.set_result(pp_result);
1260 SendReply(reply_context, PpapiPluginMsg_TCPSocket_BindReply(local_addr));
1263 void PepperTCPSocketMessageFilter::SendBindError(
1264 const ppapi::host::ReplyMessageContext& context,
1266 SendBindReply(context, pp_error, NetAddressPrivateImpl::kInvalidNetAddress);
1269 void PepperTCPSocketMessageFilter::SendConnectReply(
1270 const ppapi::host::ReplyMessageContext& context,
1272 const PP_NetAddress_Private& local_addr,
1273 const PP_NetAddress_Private& remote_addr) {
1274 UMA_HISTOGRAM_BOOLEAN("Pepper.PluginContextSecurity.TCPConnect",
1275 is_potentially_secure_plugin_context_);
1277 ppapi::host::ReplyMessageContext reply_context(context);
1278 reply_context.params.set_result(pp_result);
1279 SendReply(reply_context,
1280 PpapiPluginMsg_TCPSocket_ConnectReply(local_addr, remote_addr));
1283 void PepperTCPSocketMessageFilter::SendConnectError(
1284 const ppapi::host::ReplyMessageContext& context,
1286 SendConnectReply(context, pp_error, NetAddressPrivateImpl::kInvalidNetAddress,
1287 NetAddressPrivateImpl::kInvalidNetAddress);
1290 void PepperTCPSocketMessageFilter::SendSSLHandshakeReply(
1291 const ppapi::host::ReplyMessageContext& context,
1293 const absl::optional<net::SSLInfo>& ssl_info) {
1294 ppapi::host::ReplyMessageContext reply_context(context);
1295 reply_context.params.set_result(pp_result);
1296 ppapi::PPB_X509Certificate_Fields certificate_fields;
1297 if (pp_result == PP_OK) {
1299 if (ssl_info->cert.get()) {
1300 ppapi::PPB_X509Util_Shared::GetCertificateFields(*ssl_info->cert,
1301 &certificate_fields);
1304 SendReply(reply_context,
1305 PpapiPluginMsg_TCPSocket_SSLHandshakeReply(certificate_fields));
1308 void PepperTCPSocketMessageFilter::SendReadReply(int32_t pp_result,
1309 const ppapi::DataView& data) {
1310 DCHECK(pending_read_context_.is_valid());
1311 DCHECK_GT(pending_read_size_, 0u);
1313 pending_read_context_.params.set_result(pp_result);
1314 SendReply(pending_read_context_, PpapiPluginMsg_TCPSocket_ReadReply(data));
1316 pending_read_context_ = ppapi::host::ReplyMessageContext();
1317 pending_read_size_ = 0;
1320 void PepperTCPSocketMessageFilter::SendReadError(int32_t pp_error) {
1321 SendReadReply(pp_error, ppapi::DataView());
1324 void PepperTCPSocketMessageFilter::SendWriteReply(int32_t pp_result) {
1325 DCHECK(pending_write_context_.is_valid());
1326 DCHECK_NE(pending_write_data_.size, 0u);
1327 DCHECK(pp_result <= 0 ||
1328 static_cast<uint32_t>(pp_result) == pending_write_data_.size);
1329 DCHECK(pp_result <= 0 ||
1330 static_cast<uint32_t>(pp_result) == pending_write_bytes_written_);
1332 pending_write_context_.params.set_result(pp_result);
1333 SendReply(pending_write_context_, PpapiPluginMsg_TCPSocket_WriteReply());
1335 pending_write_context_ = ppapi::host::ReplyMessageContext();
1336 pending_write_data_.size = 0;
1337 pending_write_data_.data = NULL;
1338 pending_write_bytes_written_ = 0;
1341 void PepperTCPSocketMessageFilter::SendListenReply(
1342 const ppapi::host::ReplyMessageContext& context,
1343 int32_t pp_result) {
1344 ppapi::host::ReplyMessageContext reply_context(context);
1345 reply_context.params.set_result(pp_result);
1346 SendReply(reply_context, PpapiPluginMsg_TCPSocket_ListenReply());
1349 void PepperTCPSocketMessageFilter::SendAcceptReply(
1350 const ppapi::host::ReplyMessageContext& context,
1352 int pending_host_id,
1353 const PP_NetAddress_Private& local_addr,
1354 const PP_NetAddress_Private& remote_addr) {
1355 ppapi::host::ReplyMessageContext reply_context(context);
1356 reply_context.params.set_result(pp_result);
1357 SendReply(reply_context, PpapiPluginMsg_TCPSocket_AcceptReply(
1358 pending_host_id, local_addr, remote_addr));
1361 void PepperTCPSocketMessageFilter::SendAcceptError(
1362 const ppapi::host::ReplyMessageContext& context,
1364 SendAcceptReply(context, pp_error, 0,
1365 NetAddressPrivateImpl::kInvalidNetAddress,
1366 NetAddressPrivateImpl::kInvalidNetAddress);
1369 void PepperTCPSocketMessageFilter::Close() {
1370 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1372 // Need to do these first, as destroying Mojo pipes may invoke some of the
1373 // callbacks with failure messages.
1374 weak_ptr_factory_.InvalidateWeakPtrs();
1375 state_.DoTransition(TCPSocketState::CLOSE, true);
1377 #if BUILDFLAG(IS_CHROMEOS_ASH)
1378 // Close the firewall hole, it is no longer needed.
1379 firewall_hole_.reset();
1380 #endif // BUILDFLAG(IS_CHROMEOS_ASH)
1382 // Make sure there are no further callbacks from Mojo, which could end up in a
1383 // double free (Add ref on the UI thread, while a deletion is pending on the
1384 // IO thread), and that they're closed on the correct thread.
1385 bound_socket_.reset();
1386 connected_socket_.reset();
1387 tls_client_socket_.reset();
1388 server_socket_.reset();
1390 socket_observer_receiver_.reset();
1392 read_watcher_.reset();
1393 receive_stream_.reset();
1394 write_watcher_.reset();
1395 send_stream_.reset();
1398 network::mojom::NetworkContext*
1399 PepperTCPSocketMessageFilter::GetNetworkContext() const {
1400 if (network_context_for_testing)
1401 return network_context_for_testing;
1403 RenderProcessHost* render_process_host =
1404 RenderProcessHost::FromID(render_process_id_);
1405 if (!render_process_host)
1408 return render_process_host->GetStoragePartition()->GetNetworkContext();
1411 template <class ReturnMessage>
1412 base::OnceCallback<void(int result)>
1413 PepperTCPSocketMessageFilter::CreateCompletionCallback(
1414 const ppapi::host::HostMessageContext* context) {
1415 return mojo::WrapCallbackWithDefaultInvokeIfNotRun(
1416 base::BindOnce(&PepperTCPSocketMessageFilter::ReturnResult<ReturnMessage>,
1417 base::Unretained(this),
1418 context->MakeReplyMessageContext()),
1422 template <class ReturnMessage>
1423 void PepperTCPSocketMessageFilter::ReturnResult(
1424 ppapi::host::ReplyMessageContext context,
1426 context.params.set_result(NetErrorToPepperError(net_result));
1427 SendReply(context, ReturnMessage());
1430 } // namespace content