Revert "Make PepperUdpSocketMessageFilter use NetworkService UDP API."
This reverts commit cc2b634dbe
.
Reason for revert: Multiple PPAPI tests have begun failing on different OSes after this patch lands. See crbug.com/876824
Original change's description:
> Make PepperUdpSocketMessageFilter use NetworkService UDP API.
>
> This CL moves all of the logic over to the UI thread, to keep things
> relatively simple and minimize thread hops, since that's where core
> network service objects live.
>
> It also fixes a pre-existing bug in the PPAPI UDP code, where read
> errors that occur when there's no pending read are converted into
> 0-byte read successes.
>
> Bug: 848078
> Cq-Include-Trybots: luci.chromium.try:linux_mojo
> Change-Id: Id6d23c26c1ac085211dfcfe23502a307fc29a284
> Reviewed-on: https://chromium-review.googlesource.com/1171568
> Commit-Queue: Matt Menke <mmenke@chromium.org>
> Reviewed-by: John Abd-El-Malek <jam@chromium.org>
> Reviewed-by: Ramin Halavati <rhalavati@chromium.org>
> Reviewed-by: Helen Li <xunjieli@chromium.org>
> Reviewed-by: Bill Budge <bbudge@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#585057}
TBR=bbudge@chromium.org,jam@chromium.org,mmenke@chromium.org,xunjieli@chromium.org,rhalavati@chromium.org
Change-Id: I68b625673615275c102a95aac7df7583a2f7c97d
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 848078
Cq-Include-Trybots: luci.chromium.try:linux_mojo
Reviewed-on: https://chromium-review.googlesource.com/1185682
Reviewed-by: Jonathan Ross <jonross@chromium.org>
Commit-Queue: Jonathan Ross <jonross@chromium.org>
Cr-Commit-Position: refs/heads/master@{#585196}
This commit is contained in:
chrome/test/ppapi
content
browser
renderer_host
public
ppapi
host
proxy
tests
tools/traffic_annotation/summary
@ -4,7 +4,6 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/test/test_timeouts.h"
|
||||
@ -33,19 +32,13 @@
|
||||
#include "content/public/common/url_constants.h"
|
||||
#include "content/public/test/browser_test_utils.h"
|
||||
#include "content/public/test/javascript_test_observer.h"
|
||||
#include "content/public/test/ppapi_test_utils.h"
|
||||
#include "content/public/test/test_renderer_host.h"
|
||||
#include "extensions/common/constants.h"
|
||||
#include "extensions/test/extension_test_message_listener.h"
|
||||
#include "mojo/public/cpp/bindings/binding.h"
|
||||
#include "mojo/public/cpp/bindings/interface_request.h"
|
||||
#include "net/base/net_errors.h"
|
||||
#include "ppapi/shared_impl/test_utils.h"
|
||||
#include "rlz/buildflags/buildflags.h"
|
||||
#include "services/network/public/cpp/features.h"
|
||||
#include "services/network/public/mojom/network_context.mojom.h"
|
||||
#include "services/network/public/mojom/network_service_test.mojom.h"
|
||||
#include "services/network/public/mojom/udp_socket.mojom.h"
|
||||
#include "services/service_manager/public/cpp/connector.h"
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
@ -388,228 +381,6 @@ TEST_PPAPI_NACL(UDPSocketPrivate_ConnectFailure)
|
||||
TEST_PPAPI_NACL(UDPSocketPrivate_Broadcast)
|
||||
TEST_PPAPI_NACL(UDPSocketPrivate_SetSocketFeatureErrors)
|
||||
|
||||
namespace {
|
||||
|
||||
// UDPSocket subclass that wraps a real network::mojom::UDPSocket, and can
|
||||
// simulate certain failures. Owns itself, and destroys itself when one of
|
||||
// its Mojo pipes is closed.
|
||||
class WrappedUDPSocket : public network::mojom::UDPSocket {
|
||||
public:
|
||||
// Type of failure to simulate. "DropPipe" failures correspond to dropping a
|
||||
// Mojo pipe (Which typically happens if the network service crashes, or the
|
||||
// parent NetworkContext is torn down). "Error" failures correspond to
|
||||
// returning net::ERR_FAILED.
|
||||
enum class FailureType {
|
||||
kBindError,
|
||||
kBindDropPipe,
|
||||
kBroadcastError,
|
||||
kBroadcastDropPipe,
|
||||
kSendToDropPipe,
|
||||
kSendToError,
|
||||
kDropReceiverPipeOnConstruction,
|
||||
kDropReceiverPipeOnReceiveMore,
|
||||
kReadError,
|
||||
};
|
||||
WrappedUDPSocket(FailureType failure_type,
|
||||
network::mojom::NetworkContext* network_context,
|
||||
network::mojom::UDPSocketRequest socket_request,
|
||||
network::mojom::UDPSocketReceiverPtr socket_receiver)
|
||||
: failure_type_(failure_type), binding_(this, std::move(socket_request)) {
|
||||
if (failure_type == FailureType::kDropReceiverPipeOnConstruction)
|
||||
socket_receiver.reset();
|
||||
socket_receiver_ = std::move(socket_receiver);
|
||||
network_context->CreateUDPSocket(mojo::MakeRequest(&wrapped_socket_),
|
||||
nullptr);
|
||||
binding_.set_connection_error_handler(
|
||||
base::BindOnce(&WrappedUDPSocket::Close, base::Unretained(this)));
|
||||
wrapped_socket_.set_connection_error_handler(
|
||||
base::BindOnce(&WrappedUDPSocket::Close, base::Unretained(this)));
|
||||
}
|
||||
|
||||
// network::mojom::UDPSocket implementation.
|
||||
void Connect(const net::IPEndPoint& remote_addr,
|
||||
network::mojom::UDPSocketOptionsPtr options,
|
||||
ConnectCallback callback) override {
|
||||
NOTREACHED();
|
||||
}
|
||||
void Bind(const net::IPEndPoint& local_addr,
|
||||
network::mojom::UDPSocketOptionsPtr options,
|
||||
BindCallback callback) override {
|
||||
if (failure_type_ == FailureType::kBindError) {
|
||||
std::move(callback).Run(net::ERR_FAILED, base::nullopt);
|
||||
return;
|
||||
}
|
||||
if (failure_type_ == FailureType::kBindDropPipe) {
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
wrapped_socket_->Bind(local_addr, std::move(options), std::move(callback));
|
||||
}
|
||||
void SetBroadcast(bool broadcast, SetBroadcastCallback callback) override {
|
||||
if (failure_type_ == FailureType::kBroadcastError) {
|
||||
std::move(callback).Run(net::ERR_FAILED);
|
||||
return;
|
||||
}
|
||||
if (failure_type_ == FailureType::kBroadcastDropPipe) {
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
wrapped_socket_->SetBroadcast(broadcast, std::move(callback));
|
||||
}
|
||||
void SetSendBufferSize(int32_t send_buffer_size,
|
||||
SetSendBufferSizeCallback callback) override {
|
||||
wrapped_socket_->SetSendBufferSize(send_buffer_size, std::move(callback));
|
||||
}
|
||||
void SetReceiveBufferSize(int32_t receive_buffer_size,
|
||||
SetReceiveBufferSizeCallback callback) override {
|
||||
wrapped_socket_->SetReceiveBufferSize(receive_buffer_size,
|
||||
std::move(callback));
|
||||
}
|
||||
void JoinGroup(const net::IPAddress& group_address,
|
||||
JoinGroupCallback callback) override {
|
||||
wrapped_socket_->JoinGroup(group_address, std::move(callback));
|
||||
}
|
||||
void LeaveGroup(const net::IPAddress& group_address,
|
||||
LeaveGroupCallback callback) override {
|
||||
wrapped_socket_->LeaveGroup(group_address, std::move(callback));
|
||||
}
|
||||
void ReceiveMore(uint32_t num_additional_datagrams) override {
|
||||
if (failure_type_ == FailureType::kDropReceiverPipeOnReceiveMore) {
|
||||
socket_receiver_.reset();
|
||||
return;
|
||||
}
|
||||
if (failure_type_ == FailureType::kReadError) {
|
||||
for (uint32_t i = 0; i < num_additional_datagrams; ++i) {
|
||||
socket_receiver_->OnReceived(net::ERR_FAILED, base::nullopt,
|
||||
base::nullopt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// None of the tests using this fixture expect to read anything
|
||||
// successfully, so just ignore this call if it isn't supposed to result in
|
||||
// an error of some sort.
|
||||
}
|
||||
void ReceiveMoreWithBufferSize(uint32_t num_additional_datagrams,
|
||||
uint32_t buffer_size) override {
|
||||
NOTREACHED();
|
||||
}
|
||||
void SendTo(const net::IPEndPoint& dest_addr,
|
||||
base::span<const uint8_t> data,
|
||||
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
|
||||
SendToCallback callback) override {
|
||||
if (failure_type_ == FailureType::kSendToError) {
|
||||
std::move(callback).Run(net::ERR_FAILED);
|
||||
return;
|
||||
}
|
||||
if (failure_type_ == FailureType::kSendToDropPipe) {
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
wrapped_socket_->SendTo(dest_addr, data, traffic_annotation,
|
||||
std::move(callback));
|
||||
}
|
||||
void Send(base::span<const uint8_t> data,
|
||||
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
|
||||
SendCallback callback) override {
|
||||
NOTREACHED();
|
||||
}
|
||||
void Close() override {
|
||||
// Deleting |this| before closing the bindings can cause Mojo to DCHECK if
|
||||
// there's a pending callback.
|
||||
binding_.Close();
|
||||
socket_receiver_.reset();
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
const FailureType failure_type_;
|
||||
mojo::Binding<network::mojom::UDPSocket> binding_;
|
||||
network::mojom::UDPSocketPtr wrapped_socket_;
|
||||
|
||||
// Only populated on certain read FailureTypes.
|
||||
network::mojom::UDPSocketReceiverPtr socket_receiver_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WrappedUDPSocket);
|
||||
};
|
||||
|
||||
void TestCreateUDPSocketCallback(
|
||||
WrappedUDPSocket::FailureType failure_type,
|
||||
network::mojom::NetworkContext* network_context,
|
||||
network::mojom::UDPSocketRequest socket_request,
|
||||
network::mojom::UDPSocketReceiverPtr socket_receiver) {
|
||||
// This will delete itself when one of its Mojo pipes is closed.
|
||||
new WrappedUDPSocket(failure_type, network_context, std::move(socket_request),
|
||||
std::move(socket_receiver));
|
||||
}
|
||||
|
||||
#define RUN_UDP_FAILURE_TEST(test_name, failure_type) \
|
||||
do { \
|
||||
auto callback = \
|
||||
base::BindRepeating(&TestCreateUDPSocketCallback, failure_type); \
|
||||
ppapi::SetPepperUDPSocketCallackForTesting(&callback); \
|
||||
RunTestViaHTTP(LIST_TEST(test_name)); \
|
||||
ppapi::SetPepperUDPSocketCallackForTesting(nullptr); \
|
||||
} while (false)
|
||||
|
||||
} // namespace
|
||||
|
||||
// Macro for tests that use |WrappedUDPSocket| to simulate errors. |test_name|
|
||||
// and |_test| are separate values because there are often multiple ways to get
|
||||
// the same error pattern (Dropped mojo pipe and failed call, generally).
|
||||
#define UDPSOCKET_FAILURE_TEST(test_name, _test, failure_type) \
|
||||
IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, test_name) { \
|
||||
RUN_UDP_FAILURE_TEST(_test, failure_type); \
|
||||
} \
|
||||
IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, MAYBE_PPAPI_NACL(test_name)) { \
|
||||
RUN_UDP_FAILURE_TEST(_test, failure_type); \
|
||||
} \
|
||||
IN_PROC_BROWSER_TEST_F(PPAPINaClGLibcTest, MAYBE_GLIBC(test_name)) { \
|
||||
RUN_UDP_FAILURE_TEST(_test, failure_type); \
|
||||
} \
|
||||
IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClTest, MAYBE_PPAPI_PNACL(test_name)) { \
|
||||
RUN_UDP_FAILURE_TEST(_test, failure_type); \
|
||||
} \
|
||||
IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClNonSfiTest, \
|
||||
MAYBE_PNACL_NONSFI(test_name)) { \
|
||||
RUN_UDP_FAILURE_TEST(_test, failure_type); \
|
||||
}
|
||||
|
||||
UDPSOCKET_FAILURE_TEST(UDPSocket_BindError,
|
||||
UDPSocket_BindFails,
|
||||
WrappedUDPSocket::FailureType::kBindError);
|
||||
UDPSOCKET_FAILURE_TEST(UDPSocket_BindDropPipe,
|
||||
UDPSocket_BindFails,
|
||||
WrappedUDPSocket::FailureType::kBindDropPipe);
|
||||
UDPSOCKET_FAILURE_TEST(UDPSocket_BroadcastBeforeBindError,
|
||||
UDPSocket_BroadcastBeforeBindFails,
|
||||
WrappedUDPSocket::FailureType::kBroadcastError);
|
||||
UDPSOCKET_FAILURE_TEST(UDPSocket_BroadcastBeforeBindDropPipe,
|
||||
UDPSocket_BroadcastBeforeBindFails,
|
||||
WrappedUDPSocket::FailureType::kBroadcastDropPipe);
|
||||
UDPSOCKET_FAILURE_TEST(UDPSocket_BroadcastAfterBindError,
|
||||
UDPSocket_BroadcastAfterBindFails,
|
||||
WrappedUDPSocket::FailureType::kBroadcastError);
|
||||
UDPSOCKET_FAILURE_TEST(UDPSocket_BroadcastAfterBindDropPipe,
|
||||
UDPSocket_BroadcastAfterBindFails,
|
||||
WrappedUDPSocket::FailureType::kBroadcastDropPipe);
|
||||
UDPSOCKET_FAILURE_TEST(UDPSocket_SendToBeforeDropPipeFails,
|
||||
UDPSocket_SendToFails,
|
||||
WrappedUDPSocket::FailureType::kSendToDropPipe);
|
||||
UDPSOCKET_FAILURE_TEST(UDPSocket_DropPipeAfterBindSendToFails,
|
||||
UDPSocket_SendToFails,
|
||||
WrappedUDPSocket::FailureType::kSendToError);
|
||||
UDPSOCKET_FAILURE_TEST(UDPSocket_ReadError,
|
||||
UDPSocket_ReadFails,
|
||||
WrappedUDPSocket::FailureType::kReadError);
|
||||
UDPSOCKET_FAILURE_TEST(
|
||||
UDPSocket_DropReceiverPipeOnConstruction,
|
||||
UDPSocket_ReadFails,
|
||||
WrappedUDPSocket::FailureType::kDropReceiverPipeOnConstruction);
|
||||
UDPSOCKET_FAILURE_TEST(
|
||||
UDPSocket_DropReceiverPipeOnReceiveMore,
|
||||
UDPSocket_ReadFails,
|
||||
WrappedUDPSocket::FailureType::kDropReceiverPipeOnReceiveMore);
|
||||
|
||||
// Disallowed socket tests.
|
||||
TEST_PPAPI_NACL_DISALLOWED_SOCKETS(HostResolverPrivateDisallowed)
|
||||
TEST_PPAPI_NACL_DISALLOWED_SOCKETS(TCPServerSocketPrivateDisallowed)
|
||||
|
@ -13,20 +13,15 @@
|
||||
#include "build/build_config.h"
|
||||
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
|
||||
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/content_browser_client.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/site_instance.h"
|
||||
#include "content/public/browser/storage_partition.h"
|
||||
#include "content/public/common/process_type.h"
|
||||
#include "content/public/common/socket_permission_request.h"
|
||||
#include "ipc/ipc_message_macros.h"
|
||||
#include "mojo/public/cpp/bindings/interface_request.h"
|
||||
#include "net/base/io_buffer.h"
|
||||
#include "net/base/net_errors.h"
|
||||
#include "net/log/net_log_source.h"
|
||||
#include "net/traffic_annotation/network_traffic_annotation.h"
|
||||
#include "net/socket/udp_socket.h"
|
||||
#include "ppapi/c/pp_errors.h"
|
||||
#include "ppapi/c/private/ppb_net_address_private.h"
|
||||
#include "ppapi/host/dispatch_host_message.h"
|
||||
@ -38,7 +33,6 @@
|
||||
#include "ppapi/proxy/udp_socket_resource_constants.h"
|
||||
#include "ppapi/shared_impl/private/net_address_private_impl.h"
|
||||
#include "ppapi/shared_impl/socket_option_data.h"
|
||||
#include "services/network/public/mojom/network_context.mojom.h"
|
||||
|
||||
#if defined(OS_CHROMEOS)
|
||||
#include "chromeos/network/firewall_hole.h"
|
||||
@ -48,23 +42,20 @@ using ppapi::NetAddressPrivateImpl;
|
||||
using ppapi::host::NetErrorToPepperError;
|
||||
using ppapi::proxy::UDPSocketResourceConstants;
|
||||
|
||||
namespace content {
|
||||
|
||||
namespace {
|
||||
|
||||
const PepperUDPSocketMessageFilter::CreateUDPSocketCallback*
|
||||
g_create_udp_socket_callback_for_testing = nullptr;
|
||||
|
||||
size_t g_num_udp_filter_instances = 0;
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace content {
|
||||
|
||||
PepperUDPSocketMessageFilter::PendingSend::PendingSend(
|
||||
const net::IPAddress& address,
|
||||
int port,
|
||||
std::vector<uint8_t> data,
|
||||
const scoped_refptr<net::IOBufferWithSize>& buffer,
|
||||
const ppapi::host::ReplyMessageContext& context)
|
||||
: address(address), port(port), data(std::move(data)), context(context) {}
|
||||
: address(address), port(port), buffer(buffer), context(context) {}
|
||||
|
||||
PepperUDPSocketMessageFilter::PendingSend::PendingSend(
|
||||
const PendingSend& other) = default;
|
||||
@ -89,13 +80,7 @@ PepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter(
|
||||
render_process_id_(0),
|
||||
render_frame_id_(0),
|
||||
is_potentially_secure_plugin_context_(
|
||||
host->IsPotentiallySecurePluginContext(instance)),
|
||||
binding_(this)
|
||||
#if defined(OS_CHROMEOS)
|
||||
,
|
||||
firewall_hole_weak_ptr_factory_(this)
|
||||
#endif // defined(OS_CHROMEOS)
|
||||
{
|
||||
host->IsPotentiallySecurePluginContext(instance)) {
|
||||
++g_num_udp_filter_instances;
|
||||
DCHECK(host);
|
||||
|
||||
@ -106,35 +91,15 @@ PepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter(
|
||||
}
|
||||
|
||||
PepperUDPSocketMessageFilter::~PepperUDPSocketMessageFilter() {
|
||||
DCHECK(closed_);
|
||||
DCHECK(!socket_);
|
||||
DCHECK(!binding_);
|
||||
Close();
|
||||
--g_num_udp_filter_instances;
|
||||
}
|
||||
|
||||
void PepperUDPSocketMessageFilter::SetCreateUDPSocketCallbackForTesting(
|
||||
const CreateUDPSocketCallback* create_udp_socket_callback) {
|
||||
DCHECK(!create_udp_socket_callback ||
|
||||
!g_create_udp_socket_callback_for_testing);
|
||||
g_create_udp_socket_callback_for_testing = create_udp_socket_callback;
|
||||
}
|
||||
|
||||
// static
|
||||
size_t PepperUDPSocketMessageFilter::GetNumInstances() {
|
||||
return g_num_udp_filter_instances;
|
||||
}
|
||||
|
||||
void PepperUDPSocketMessageFilter::OnFilterDestroyed() {
|
||||
ResourceMessageFilter::OnFilterDestroyed();
|
||||
// Need to close the socket on the UI thread. Calling Close() also ensures
|
||||
// that future messages will be ignored, so the mojo pipes won't be
|
||||
// re-created, so after Close() runs, |this| can be safely deleted on the IO
|
||||
// thread.
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE,
|
||||
base::BindOnce(&PepperUDPSocketMessageFilter::Close, this));
|
||||
}
|
||||
|
||||
scoped_refptr<base::TaskRunner>
|
||||
PepperUDPSocketMessageFilter::OverrideTaskRunnerForMessage(
|
||||
const IPC::Message& message) {
|
||||
@ -142,6 +107,7 @@ PepperUDPSocketMessageFilter::OverrideTaskRunnerForMessage(
|
||||
case PpapiHostMsg_UDPSocket_SetOption::ID:
|
||||
case PpapiHostMsg_UDPSocket_Close::ID:
|
||||
case PpapiHostMsg_UDPSocket_RecvSlotAvailable::ID:
|
||||
return BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
|
||||
case PpapiHostMsg_UDPSocket_Bind::ID:
|
||||
case PpapiHostMsg_UDPSocket_SendTo::ID:
|
||||
case PpapiHostMsg_UDPSocket_JoinGroup::ID:
|
||||
@ -176,14 +142,14 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
|
||||
const ppapi::host::HostMessageContext* context,
|
||||
PP_UDPSocket_Option name,
|
||||
const ppapi::SocketOptionData& value) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
if (closed_)
|
||||
return PP_ERROR_FAILED;
|
||||
|
||||
switch (name) {
|
||||
case PP_UDPSOCKET_OPTION_ADDRESS_REUSE: {
|
||||
if (socket_) {
|
||||
if (socket_.get()) {
|
||||
// AllowReuseAddress is only effective before Bind().
|
||||
// Note that this limitation originally comes from Windows, but
|
||||
// PPAPI tries to provide platform independent APIs.
|
||||
@ -206,19 +172,16 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
|
||||
if (!value.GetBool(&boolean_value))
|
||||
return PP_ERROR_BADARGUMENT;
|
||||
|
||||
// If the socket is already bound, proxy the value to UDPSocket.
|
||||
if (socket_.get())
|
||||
return NetErrorToPepperError(socket_->SetBroadcast(boolean_value));
|
||||
|
||||
// UDPSocket instance is not yet created, so remember the value here.
|
||||
if (boolean_value) {
|
||||
socket_options_ |= SOCKET_OPTION_BROADCAST;
|
||||
} else {
|
||||
socket_options_ &= ~SOCKET_OPTION_BROADCAST;
|
||||
}
|
||||
|
||||
if (socket_) {
|
||||
socket_->SetBroadcast(
|
||||
boolean_value,
|
||||
CreateCompletionCallback<PpapiPluginMsg_UDPSocket_SetOptionReply>(
|
||||
context));
|
||||
return PP_OK_COMPLETIONPENDING;
|
||||
}
|
||||
return PP_OK;
|
||||
}
|
||||
case PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE: {
|
||||
@ -227,18 +190,15 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
|
||||
integer_value > UDPSocketResourceConstants::kMaxSendBufferSize)
|
||||
return PP_ERROR_BADARGUMENT;
|
||||
|
||||
socket_options_ |= SOCKET_OPTION_SNDBUF_SIZE;
|
||||
sndbuf_size_ = integer_value;
|
||||
|
||||
// If the socket is already initialized, proxy the value to UDPSocket.
|
||||
if (socket_) {
|
||||
socket_->SetSendBufferSize(
|
||||
integer_value,
|
||||
CreateCompletionCallback<PpapiPluginMsg_UDPSocket_SetOptionReply>(
|
||||
context));
|
||||
return PP_OK_COMPLETIONPENDING;
|
||||
// If the socket is already bound, proxy the value to UDPSocket.
|
||||
if (socket_.get()) {
|
||||
return NetErrorToPepperError(
|
||||
socket_->SetSendBufferSize(integer_value));
|
||||
}
|
||||
|
||||
// UDPSocket instance is not yet created, so remember the value here.
|
||||
socket_options_ |= SOCKET_OPTION_SNDBUF_SIZE;
|
||||
sndbuf_size_ = integer_value;
|
||||
return PP_OK;
|
||||
}
|
||||
case PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE: {
|
||||
@ -247,18 +207,15 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
|
||||
integer_value > UDPSocketResourceConstants::kMaxReceiveBufferSize)
|
||||
return PP_ERROR_BADARGUMENT;
|
||||
|
||||
socket_options_ |= SOCKET_OPTION_RCVBUF_SIZE;
|
||||
rcvbuf_size_ = integer_value;
|
||||
|
||||
// If the socket is already initialized, proxy the value to UDPSocket.
|
||||
if (socket_) {
|
||||
socket_->SetReceiveBufferSize(
|
||||
integer_value,
|
||||
CreateCompletionCallback<PpapiPluginMsg_UDPSocket_SetOptionReply>(
|
||||
context));
|
||||
return PP_OK_COMPLETIONPENDING;
|
||||
// If the socket is already bound, proxy the value to UDPSocket.
|
||||
if (socket_.get()) {
|
||||
return NetErrorToPepperError(
|
||||
socket_->SetReceiveBufferSize(integer_value));
|
||||
}
|
||||
|
||||
// UDPSocket instance is not yet created, so remember the value here.
|
||||
socket_options_ |= SOCKET_OPTION_RCVBUF_SIZE;
|
||||
rcvbuf_size_ = integer_value;
|
||||
return PP_OK;
|
||||
}
|
||||
case PP_UDPSOCKET_OPTION_MULTICAST_LOOP: {
|
||||
@ -266,22 +223,21 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
|
||||
if (!value.GetBool(&boolean_value))
|
||||
return PP_ERROR_BADARGUMENT;
|
||||
|
||||
// If the socket is already bound, proxy the value to UDPSocket.
|
||||
if (socket_) {
|
||||
if (can_use_multicast_ != PP_OK)
|
||||
return can_use_multicast_;
|
||||
|
||||
return NetErrorToPepperError(
|
||||
socket_->SetMulticastLoopbackMode(boolean_value));
|
||||
}
|
||||
|
||||
// UDPSocket instance is not yet created, so remember the value here.
|
||||
if (boolean_value) {
|
||||
socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
|
||||
} else {
|
||||
socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
|
||||
}
|
||||
|
||||
// If the socket is already initialized, either fail if permissions
|
||||
// disallow multicast, or lie and claim it succeeded, to maintain previous
|
||||
// behavior.
|
||||
if (socket_) {
|
||||
if (can_use_multicast_ != PP_OK)
|
||||
return can_use_multicast_;
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
case PP_UDPSOCKET_OPTION_MULTICAST_TTL: {
|
||||
@ -290,20 +246,18 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
|
||||
integer_value < 0 || integer_value > 255)
|
||||
return PP_ERROR_BADARGUMENT;
|
||||
|
||||
// UDPSocket instance is not yet created, so remember the value here.
|
||||
socket_options_ |= SOCKET_OPTION_MULTICAST_TTL;
|
||||
multicast_ttl_ = integer_value;
|
||||
|
||||
// If the socket is already initialized, either fail if permissions
|
||||
// disallow multicast, or lie and claim it succeeded, to maintain previous
|
||||
// behavior.
|
||||
// If the socket is already bound, proxy the value to UDPSocket.
|
||||
if (socket_) {
|
||||
if (can_use_multicast_ != PP_OK)
|
||||
return can_use_multicast_;
|
||||
|
||||
return PP_OK;
|
||||
return NetErrorToPepperError(
|
||||
socket_->SetMulticastTimeToLive(integer_value));
|
||||
}
|
||||
|
||||
// UDPSocket instance is not yet created, so remember the value here.
|
||||
socket_options_ |= SOCKET_OPTION_MULTICAST_TTL;
|
||||
multicast_ttl_ = integer_value;
|
||||
return PP_OK;
|
||||
}
|
||||
default: {
|
||||
@ -319,9 +273,6 @@ int32_t PepperUDPSocketMessageFilter::OnMsgBind(
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
DCHECK(context);
|
||||
|
||||
if (closed_ || socket_)
|
||||
return PP_ERROR_FAILED;
|
||||
|
||||
// Check for permissions to use multicast APIS. This check must be done while
|
||||
// on the UI thread, so we cache the value here to be used later on.
|
||||
PP_NetAddress_Private any_addr;
|
||||
@ -339,81 +290,10 @@ int32_t PepperUDPSocketMessageFilter::OnMsgBind(
|
||||
return PP_ERROR_NOACCESS;
|
||||
}
|
||||
|
||||
net::IPAddressBytes address;
|
||||
uint16_t port;
|
||||
if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port))
|
||||
return PP_ERROR_ADDRESS_INVALID;
|
||||
net::IPEndPoint end_point(net::IPAddress(address), port);
|
||||
|
||||
network::mojom::UDPSocketOptionsPtr udp_socket_options =
|
||||
network::mojom::UDPSocketOptions::New();
|
||||
udp_socket_options->allow_address_reuse =
|
||||
!!(socket_options_ & SOCKET_OPTION_ADDRESS_REUSE);
|
||||
if (socket_options_ & SOCKET_OPTION_SNDBUF_SIZE)
|
||||
udp_socket_options->send_buffer_size = sndbuf_size_;
|
||||
if (socket_options_ & SOCKET_OPTION_RCVBUF_SIZE)
|
||||
udp_socket_options->receive_buffer_size = rcvbuf_size_;
|
||||
|
||||
if (socket_options_ & SOCKET_OPTION_MULTICAST_LOOP) {
|
||||
if (can_use_multicast_ != PP_OK) {
|
||||
// TODO(mmenke): The above line implies |can_use_multicast_| is a PP
|
||||
// error code, but the next line implies it is a net error code. Fix that.
|
||||
return NetErrorToPepperError(can_use_multicast_);
|
||||
}
|
||||
// TODO(mmenke): This doesn't seem to be doing anything - this is the
|
||||
// default behavior.
|
||||
udp_socket_options->multicast_loopback_mode = true;
|
||||
}
|
||||
if (socket_options_ & SOCKET_OPTION_MULTICAST_TTL) {
|
||||
if (can_use_multicast_ != PP_OK) {
|
||||
// TODO(mmenke): The above line implies |can_use_multicast_| is a PP
|
||||
// error code, but the next line implies it is a net error code. Fix that.
|
||||
return NetErrorToPepperError(can_use_multicast_);
|
||||
}
|
||||
|
||||
udp_socket_options->multicast_time_to_live = multicast_ttl_;
|
||||
}
|
||||
|
||||
RenderFrameHost* render_frame_host =
|
||||
RenderFrameHost::FromID(render_process_id_, render_frame_id_);
|
||||
// If the RenderFrameHost has been closed, just fail the request.
|
||||
if (!render_frame_host)
|
||||
return PP_ERROR_NOACCESS;
|
||||
|
||||
network::mojom::UDPSocketReceiverPtr udp_socket_receiver;
|
||||
// Avoid binding the receiver until the socket has been successfully Bound (in
|
||||
// a socket sense), to avoid providing read data to the caller until it has
|
||||
// been told that the socket was bound.
|
||||
network::mojom::UDPSocketReceiverRequest receiver_request =
|
||||
mojo::MakeRequest(&udp_socket_receiver);
|
||||
|
||||
SiteInstance* site_instance = render_frame_host->GetSiteInstance();
|
||||
network::mojom::NetworkContext* network_context =
|
||||
BrowserContext::GetStoragePartition(site_instance->GetBrowserContext(),
|
||||
site_instance)
|
||||
->GetNetworkContext();
|
||||
if (g_create_udp_socket_callback_for_testing) {
|
||||
g_create_udp_socket_callback_for_testing->Run(
|
||||
network_context, mojo::MakeRequest(&socket_),
|
||||
std::move(udp_socket_receiver));
|
||||
} else {
|
||||
network_context->CreateUDPSocket(mojo::MakeRequest(&socket_),
|
||||
std::move(udp_socket_receiver));
|
||||
}
|
||||
|
||||
ppapi::host::ReplyMessageContext reply_context =
|
||||
context->MakeReplyMessageContext();
|
||||
// Watch the socket for errors during the the Bind call.
|
||||
socket_.set_connection_error_handler(
|
||||
base::BindOnce(&PepperUDPSocketMessageFilter::SendBindError,
|
||||
base::Unretained(this), reply_context, PP_ERROR_FAILED));
|
||||
|
||||
// This is the actual socket Bind call (i.e., not a Mojo Bind call).
|
||||
socket_->Bind(end_point, std::move(udp_socket_options),
|
||||
base::BindOnce(&PepperUDPSocketMessageFilter::DoBindCallback,
|
||||
base::Unretained(this),
|
||||
std::move(receiver_request), reply_context));
|
||||
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&PepperUDPSocketMessageFilter::DoBind, this,
|
||||
context->MakeReplyMessageContext(), addr));
|
||||
return PP_OK_COMPLETIONPENDING;
|
||||
}
|
||||
|
||||
@ -424,11 +304,6 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSendTo(
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
DCHECK(context);
|
||||
|
||||
// Check |binding_| instead of |socket_| because |binding_| is only set
|
||||
// after the Bind() call completes.
|
||||
if (closed_ || !binding_)
|
||||
return PP_ERROR_FAILED;
|
||||
|
||||
SocketPermissionRequest request =
|
||||
pepper_socket_utils::CreateSocketPermissionRequest(
|
||||
SocketPermissionRequest::UDP_SEND_TO, addr);
|
||||
@ -440,61 +315,32 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSendTo(
|
||||
return PP_ERROR_NOACCESS;
|
||||
}
|
||||
|
||||
// Make sure a malicious plugin can't queue up an unlimited number of buffers.
|
||||
size_t num_pending_sends = pending_sends_.size();
|
||||
if (num_pending_sends == UDPSocketResourceConstants::kPluginSendBufferSlots) {
|
||||
return PP_ERROR_FAILED;
|
||||
}
|
||||
|
||||
size_t num_bytes = data.size();
|
||||
if (num_bytes == 0 ||
|
||||
num_bytes >
|
||||
static_cast<size_t>(UDPSocketResourceConstants::kMaxWriteSize)) {
|
||||
// Size of |data| is checked on the plugin side.
|
||||
NOTREACHED();
|
||||
return PP_ERROR_BADARGUMENT;
|
||||
}
|
||||
|
||||
net::IPAddressBytes address;
|
||||
uint16_t port;
|
||||
if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
|
||||
return PP_ERROR_ADDRESS_INVALID;
|
||||
}
|
||||
|
||||
const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(data.data());
|
||||
std::vector<uint8_t> data_vector(data_ptr, data_ptr + num_bytes);
|
||||
|
||||
pending_sends_.push(PendingSend(net::IPAddress(address), port,
|
||||
std::move(data_vector),
|
||||
context->MakeReplyMessageContext()));
|
||||
// Can only start the send if there isn't another send pending.
|
||||
if (num_pending_sends == 0)
|
||||
StartPendingSend();
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&PepperUDPSocketMessageFilter::DoSendTo, this,
|
||||
context->MakeReplyMessageContext(), data, addr));
|
||||
return PP_OK_COMPLETIONPENDING;
|
||||
}
|
||||
|
||||
int32_t PepperUDPSocketMessageFilter::OnMsgClose(
|
||||
const ppapi::host::HostMessageContext* context) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
Close();
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
int32_t PepperUDPSocketMessageFilter::OnMsgRecvSlotAvailable(
|
||||
const ppapi::host::HostMessageContext* context) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
if (remaining_recv_slots_ <
|
||||
UDPSocketResourceConstants::kPluginReceiveBufferSlots) {
|
||||
// If the pipe was closed, but the consumer has not yet closed the UDP
|
||||
// socket, keep the read buffer filled with errors.
|
||||
if (!binding_) {
|
||||
PepperUDPSocketMessageFilter::SendRecvFromError(PP_ERROR_FAILED);
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
remaining_recv_slots_++;
|
||||
socket_->ReceiveMore(1);
|
||||
}
|
||||
|
||||
if (!recvfrom_buffer_.get() && !closed_ && socket_.get()) {
|
||||
DCHECK_EQ(1u, remaining_recv_slots_);
|
||||
DoRecvFrom();
|
||||
}
|
||||
|
||||
return PP_OK;
|
||||
@ -518,11 +364,7 @@ int32_t PepperUDPSocketMessageFilter::OnMsgJoinGroup(
|
||||
if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &group, &port))
|
||||
return PP_ERROR_ADDRESS_INVALID;
|
||||
|
||||
socket_->JoinGroup(
|
||||
net::IPAddress(group),
|
||||
CreateCompletionCallback<PpapiPluginMsg_UDPSocket_SetOptionReply>(
|
||||
context));
|
||||
return PP_OK_COMPLETIONPENDING;
|
||||
return NetErrorToPepperError(socket_->JoinGroup(net::IPAddress(group)));
|
||||
}
|
||||
|
||||
int32_t PepperUDPSocketMessageFilter::OnMsgLeaveGroup(
|
||||
@ -543,205 +385,308 @@ int32_t PepperUDPSocketMessageFilter::OnMsgLeaveGroup(
|
||||
if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &group, &port))
|
||||
return PP_ERROR_ADDRESS_INVALID;
|
||||
|
||||
socket_->LeaveGroup(
|
||||
net::IPAddress(group),
|
||||
CreateCompletionCallback<PpapiPluginMsg_UDPSocket_LeaveGroupReply>(
|
||||
context));
|
||||
return PP_OK_COMPLETIONPENDING;
|
||||
return NetErrorToPepperError(socket_->LeaveGroup(net::IPAddress(group)));
|
||||
}
|
||||
|
||||
void PepperUDPSocketMessageFilter::DoBindCallback(
|
||||
network::mojom::UDPSocketReceiverRequest receiver_request,
|
||||
void PepperUDPSocketMessageFilter::DoBind(
|
||||
const ppapi::host::ReplyMessageContext& context,
|
||||
int result,
|
||||
const base::Optional<net::IPEndPoint>& local_addr_out) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
const PP_NetAddress_Private& addr) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
if (result != net::OK) {
|
||||
SendBindError(context, NetErrorToPepperError(result));
|
||||
if (closed_ || socket_.get()) {
|
||||
SendBindError(context, PP_ERROR_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
auto socket = std::make_unique<net::UDPSocket>(
|
||||
net::DatagramSocket::DEFAULT_BIND, nullptr, net::NetLogSource());
|
||||
|
||||
net::IPAddressBytes address;
|
||||
uint16_t port;
|
||||
if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
|
||||
SendBindError(context, PP_ERROR_ADDRESS_INVALID);
|
||||
return;
|
||||
}
|
||||
net::IPEndPoint end_point(net::IPAddress(address), port);
|
||||
{
|
||||
int net_result = socket->Open(end_point.GetFamily());
|
||||
if (net_result != net::OK) {
|
||||
SendBindError(context, NetErrorToPepperError(net_result));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (socket_options_ & SOCKET_OPTION_ADDRESS_REUSE) {
|
||||
int net_result = socket->AllowAddressReuse();
|
||||
if (net_result != net::OK) {
|
||||
SendBindError(context, NetErrorToPepperError(net_result));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (socket_options_ & SOCKET_OPTION_BROADCAST) {
|
||||
int net_result = socket->SetBroadcast(true);
|
||||
if (net_result != net::OK) {
|
||||
SendBindError(context, NetErrorToPepperError(net_result));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (socket_options_ & SOCKET_OPTION_SNDBUF_SIZE) {
|
||||
int net_result = socket->SetSendBufferSize(sndbuf_size_);
|
||||
if (net_result != net::OK) {
|
||||
SendBindError(context, NetErrorToPepperError(net_result));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (socket_options_ & SOCKET_OPTION_RCVBUF_SIZE) {
|
||||
int net_result = socket->SetReceiveBufferSize(rcvbuf_size_);
|
||||
if (net_result != net::OK) {
|
||||
SendBindError(context, NetErrorToPepperError(net_result));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (socket_options_ & SOCKET_OPTION_MULTICAST_LOOP) {
|
||||
if (can_use_multicast_ != PP_OK) {
|
||||
SendBindError(context, NetErrorToPepperError(can_use_multicast_));
|
||||
return;
|
||||
}
|
||||
|
||||
int net_result = socket->SetMulticastLoopbackMode(true);
|
||||
if (net_result != net::OK) {
|
||||
SendBindError(context, NetErrorToPepperError(net_result));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (socket_options_ & SOCKET_OPTION_MULTICAST_TTL) {
|
||||
if (can_use_multicast_ != PP_OK) {
|
||||
SendBindError(context, NetErrorToPepperError(can_use_multicast_));
|
||||
return;
|
||||
}
|
||||
|
||||
int net_result = socket->SetMulticastTimeToLive(multicast_ttl_);
|
||||
if (net_result != net::OK) {
|
||||
SendBindError(context, NetErrorToPepperError(net_result));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int net_result = socket->Bind(end_point);
|
||||
if (net_result != net::OK) {
|
||||
SendBindError(context, NetErrorToPepperError(net_result));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
net::IPEndPoint bound_address;
|
||||
{
|
||||
int net_result = socket->GetLocalAddress(&bound_address);
|
||||
if (net_result != net::OK) {
|
||||
SendBindError(context, NetErrorToPepperError(net_result));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PP_NetAddress_Private net_address = NetAddressPrivateImpl::kInvalidNetAddress;
|
||||
if (!local_addr_out || !NetAddressPrivateImpl::IPEndPointToNetAddress(
|
||||
local_addr_out->address().bytes(),
|
||||
local_addr_out->port(), &net_address)) {
|
||||
if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
|
||||
bound_address.address().bytes(), bound_address.port(),
|
||||
&net_address)) {
|
||||
SendBindError(context, PP_ERROR_ADDRESS_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (socket_options_ & SOCKET_OPTION_BROADCAST) {
|
||||
socket_->SetBroadcast(
|
||||
true, base::BindOnce(
|
||||
&PepperUDPSocketMessageFilter::OnBroadcastConfiguredAfterBind,
|
||||
base::Unretained(this), std::move(receiver_request), context,
|
||||
*local_addr_out, net_address));
|
||||
return;
|
||||
}
|
||||
|
||||
// The default value of disabled is fine, if SOCKET_OPTION_BROADCAST is not
|
||||
// set.
|
||||
OnBroadcastConfiguredAfterBind(std::move(receiver_request), context,
|
||||
*local_addr_out, net_address, net::OK);
|
||||
}
|
||||
|
||||
void PepperUDPSocketMessageFilter::OnBroadcastConfiguredAfterBind(
|
||||
network::mojom::UDPSocketReceiverRequest receiver_request,
|
||||
const ppapi::host::ReplyMessageContext& context,
|
||||
const net::IPEndPoint& ip_endpoint,
|
||||
const PP_NetAddress_Private& net_address,
|
||||
int net_result) {
|
||||
if (net_result != net::OK) {
|
||||
SendBindError(context, NetErrorToPepperError(net_result));
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(OS_CHROMEOS)
|
||||
pepper_socket_utils::OpenUDPFirewallHole(
|
||||
ip_endpoint,
|
||||
base::BindRepeating(&PepperUDPSocketMessageFilter::OnFirewallHoleOpened,
|
||||
firewall_hole_weak_ptr_factory_.GetWeakPtr(),
|
||||
base::Passed(std::move(receiver_request)), context,
|
||||
net_address));
|
||||
#else // !defined(OS_CHROMEOS)
|
||||
OnBindComplete(std::move(receiver_request), context, net_address);
|
||||
#endif // !defined(OS_CHROMEOS)
|
||||
OpenFirewallHole(
|
||||
bound_address,
|
||||
base::Bind(&PepperUDPSocketMessageFilter::OnBindComplete, this,
|
||||
base::Passed(&socket), context, net_address));
|
||||
#else
|
||||
OnBindComplete(std::move(socket), context, net_address);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PepperUDPSocketMessageFilter::OnBindComplete(
|
||||
network::mojom::UDPSocketReceiverRequest receiver_request,
|
||||
std::unique_ptr<net::UDPSocket> socket,
|
||||
const ppapi::host::ReplyMessageContext& context,
|
||||
const PP_NetAddress_Private& net_address) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
DCHECK(socket_);
|
||||
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
socket_.swap(socket);
|
||||
SendBindReply(context, PP_OK, net_address);
|
||||
|
||||
binding_.Bind(std::move(receiver_request));
|
||||
binding_.set_connection_error_handler(base::BindOnce(
|
||||
&PepperUDPSocketMessageFilter::PipeClosed, base::Unretained(this)));
|
||||
socket_.set_connection_error_handler(base::BindOnce(
|
||||
&PepperUDPSocketMessageFilter::PipeClosed, base::Unretained(this)));
|
||||
socket_->ReceiveMore(UDPSocketResourceConstants::kPluginReceiveBufferSlots);
|
||||
DoRecvFrom();
|
||||
}
|
||||
|
||||
#if defined(OS_CHROMEOS)
|
||||
void PepperUDPSocketMessageFilter::OpenFirewallHole(
|
||||
const net::IPEndPoint& local_address,
|
||||
base::Closure bind_complete) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
pepper_socket_utils::FirewallHoleOpenCallback callback = base::Bind(
|
||||
&PepperUDPSocketMessageFilter::OnFirewallHoleOpened, this, bind_complete);
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE,
|
||||
base::BindOnce(&pepper_socket_utils::OpenUDPFirewallHole, local_address,
|
||||
callback));
|
||||
}
|
||||
|
||||
void PepperUDPSocketMessageFilter::OnFirewallHoleOpened(
|
||||
network::mojom::UDPSocketReceiverRequest receiver_request,
|
||||
const ppapi::host::ReplyMessageContext& context,
|
||||
const PP_NetAddress_Private& net_address,
|
||||
base::Closure bind_complete,
|
||||
std::unique_ptr<chromeos::FirewallHole> hole) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
LOG_IF(WARNING, !hole.get()) << "Firewall hole could not be opened.";
|
||||
firewall_hole_.reset(hole.release());
|
||||
|
||||
OnBindComplete(std::move(receiver_request), context, net_address);
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, bind_complete);
|
||||
}
|
||||
#endif // defined(OS_CHROMEOS)
|
||||
|
||||
void PepperUDPSocketMessageFilter::StartPendingSend() {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
void PepperUDPSocketMessageFilter::DoRecvFrom() {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
DCHECK(!closed_);
|
||||
DCHECK(socket_.get());
|
||||
DCHECK(!recvfrom_buffer_.get());
|
||||
DCHECK_GT(remaining_recv_slots_, 0u);
|
||||
|
||||
recvfrom_buffer_ =
|
||||
new net::IOBuffer(UDPSocketResourceConstants::kMaxReadSize);
|
||||
|
||||
// Use base::Unretained(this), so that the lifespan of this object doesn't
|
||||
// have to last until the callback is called.
|
||||
// It is safe to do so because |socket_| is owned by this object. If this
|
||||
// object gets destroyed (and so does |socket_|), the callback won't be
|
||||
// called.
|
||||
int net_result = socket_->RecvFrom(
|
||||
recvfrom_buffer_.get(), UDPSocketResourceConstants::kMaxReadSize,
|
||||
&recvfrom_address_,
|
||||
base::BindOnce(&PepperUDPSocketMessageFilter::OnRecvFromCompleted,
|
||||
base::Unretained(this)));
|
||||
if (net_result != net::ERR_IO_PENDING)
|
||||
OnRecvFromCompleted(net_result);
|
||||
}
|
||||
|
||||
void PepperUDPSocketMessageFilter::DoSendTo(
|
||||
const ppapi::host::ReplyMessageContext& context,
|
||||
const std::string& data,
|
||||
const PP_NetAddress_Private& addr) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
DCHECK(socket_.get());
|
||||
|
||||
if (closed_ || !socket_.get()) {
|
||||
SendSendToError(context, PP_ERROR_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t num_bytes = data.size();
|
||||
if (num_bytes == 0 ||
|
||||
num_bytes >
|
||||
static_cast<size_t>(UDPSocketResourceConstants::kMaxWriteSize)) {
|
||||
// Size of |data| is checked on the plugin side.
|
||||
NOTREACHED();
|
||||
SendSendToError(context, PP_ERROR_BADARGUMENT);
|
||||
return;
|
||||
}
|
||||
|
||||
net::IPAddressBytes address;
|
||||
uint16_t port;
|
||||
if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
|
||||
SendSendToError(context, PP_ERROR_ADDRESS_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
scoped_refptr<net::IOBufferWithSize> buffer(
|
||||
new net::IOBufferWithSize(num_bytes));
|
||||
memcpy(buffer->data(), data.data(), num_bytes);
|
||||
|
||||
// Make sure a malicious plugin can't queue up an unlimited number of buffers.
|
||||
size_t num_pending_sends = pending_sends_.size();
|
||||
if (num_pending_sends == UDPSocketResourceConstants::kPluginSendBufferSlots) {
|
||||
SendSendToError(context, PP_ERROR_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
pending_sends_.push(
|
||||
PendingSend(net::IPAddress(address), port, buffer, context));
|
||||
// If there are other sends pending, we can't start yet.
|
||||
if (num_pending_sends)
|
||||
return;
|
||||
int net_result = StartPendingSend();
|
||||
if (net_result != net::ERR_IO_PENDING)
|
||||
FinishPendingSend(net_result);
|
||||
}
|
||||
|
||||
int PepperUDPSocketMessageFilter::StartPendingSend() {
|
||||
DCHECK(!pending_sends_.empty());
|
||||
DCHECK(socket_);
|
||||
|
||||
net::NetworkTrafficAnnotationTag annotation =
|
||||
net::DefineNetworkTrafficAnnotation("pepper_udp_socket_message_filter",
|
||||
R"(
|
||||
semantics {
|
||||
sender: "Chrome Plugin UDP Socket API"
|
||||
description:
|
||||
"Chrome plugins can use this API to send and receive data over the "
|
||||
"network using UDP connections."
|
||||
trigger: "A request from a plugin."
|
||||
data: "Any data that the plugin sends."
|
||||
destination: OTHER
|
||||
destination_other:
|
||||
"Data can be sent to any destination."
|
||||
}
|
||||
policy {
|
||||
cookies_allowed: NO
|
||||
setting:
|
||||
"The only remaining plugin is Flash, so disabling it in Content "
|
||||
"settings will prevent all use of UDP sockets by plugins."
|
||||
policy_exception_justification:
|
||||
"There is no single policy related to plugin use of UDP sockets, "
|
||||
"but there are a number of policies that allow disabling plugins."
|
||||
})");
|
||||
|
||||
const PendingSend& pending_send = pending_sends_.front();
|
||||
// See OnMsgRecvFrom() for the reason why we use base::Unretained(this)
|
||||
// when calling |socket_| methods.
|
||||
socket_->SendTo(
|
||||
int net_result = socket_->SendTo(
|
||||
pending_send.buffer.get(), pending_send.buffer->size(),
|
||||
net::IPEndPoint(pending_send.address, pending_send.port),
|
||||
pending_send.data, net::MutableNetworkTrafficAnnotationTag(annotation),
|
||||
base::BindOnce(&PepperUDPSocketMessageFilter::OnSendToCompleted,
|
||||
base::Unretained(this)));
|
||||
return net_result;
|
||||
}
|
||||
|
||||
void PepperUDPSocketMessageFilter::Close() {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
socket_.reset();
|
||||
binding_.Close();
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
if (socket_.get() && !closed_)
|
||||
socket_->Close();
|
||||
closed_ = true;
|
||||
}
|
||||
|
||||
void PepperUDPSocketMessageFilter::OnReceived(
|
||||
int result,
|
||||
const base::Optional<net::IPEndPoint>& src_addr,
|
||||
base::Optional<base::span<const uint8_t>> data) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
DCHECK(!closed_);
|
||||
void PepperUDPSocketMessageFilter::OnRecvFromCompleted(int net_result) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
DCHECK(recvfrom_buffer_.get());
|
||||
|
||||
int32_t pp_result = NetErrorToPepperError(result);
|
||||
int32_t pp_result = NetErrorToPepperError(net_result);
|
||||
|
||||
// Convert IPEndPoint we get back from RecvFrom to a PP_NetAddress_Private
|
||||
// to send back.
|
||||
PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress;
|
||||
if (pp_result == PP_OK &&
|
||||
(!src_addr ||
|
||||
!NetAddressPrivateImpl::IPEndPointToNetAddress(
|
||||
src_addr->address().bytes(), src_addr->port(), &addr))) {
|
||||
if (pp_result >= 0 &&
|
||||
!NetAddressPrivateImpl::IPEndPointToNetAddress(
|
||||
recvfrom_address_.address().bytes(), recvfrom_address_.port(),
|
||||
&addr)) {
|
||||
pp_result = PP_ERROR_ADDRESS_INVALID;
|
||||
}
|
||||
|
||||
if (pp_result == PP_OK) {
|
||||
std::string data_string;
|
||||
if (data) {
|
||||
data_string = std::string(reinterpret_cast<const char*>(data->data()),
|
||||
data->size());
|
||||
}
|
||||
SendRecvFromResult(PP_OK, data_string, addr);
|
||||
if (pp_result >= 0) {
|
||||
SendRecvFromResult(PP_OK, std::string(recvfrom_buffer_->data(), pp_result),
|
||||
addr);
|
||||
} else {
|
||||
SendRecvFromError(pp_result);
|
||||
}
|
||||
|
||||
// This should always be the case, but best to protect against a broken /
|
||||
// taken over network service.
|
||||
if (remaining_recv_slots_ > 0)
|
||||
remaining_recv_slots_--;
|
||||
recvfrom_buffer_ = nullptr;
|
||||
|
||||
DCHECK_GT(remaining_recv_slots_, 0u);
|
||||
remaining_recv_slots_--;
|
||||
|
||||
if (remaining_recv_slots_ > 0 && !closed_ && socket_.get())
|
||||
DoRecvFrom();
|
||||
}
|
||||
|
||||
void PepperUDPSocketMessageFilter::OnSendToCompleted(int net_result) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
FinishPendingSend(net_result);
|
||||
|
||||
if (!pending_sends_.empty())
|
||||
StartPendingSend();
|
||||
// Start pending sends until none are left or a send doesn't complete.
|
||||
while (!pending_sends_.empty()) {
|
||||
net_result = StartPendingSend();
|
||||
if (net_result == net::ERR_IO_PENDING)
|
||||
break;
|
||||
FinishPendingSend(net_result);
|
||||
}
|
||||
}
|
||||
|
||||
void PepperUDPSocketMessageFilter::FinishPendingSend(int net_result) {
|
||||
DCHECK(!pending_sends_.empty());
|
||||
const PendingSend& pending_send = pending_sends_.front();
|
||||
int32_t pp_result = NetErrorToPepperError(net_result);
|
||||
if (pp_result < 0) {
|
||||
if (pp_result < 0)
|
||||
SendSendToError(pending_send.context, pp_result);
|
||||
} else {
|
||||
// The cast should be safe because of the
|
||||
// UDPSocketResourceConstants::kMaxSendBufferSize before enqueuing the send.
|
||||
SendSendToReply(pending_send.context, PP_OK,
|
||||
static_cast<int>(pending_send.data.size()));
|
||||
}
|
||||
else
|
||||
SendSendToReply(pending_send.context, PP_OK, pp_result);
|
||||
|
||||
pending_sends_.pop();
|
||||
}
|
||||
@ -762,19 +707,6 @@ void PepperUDPSocketMessageFilter::SendRecvFromResult(
|
||||
int32_t result,
|
||||
const std::string& data,
|
||||
const PP_NetAddress_Private& addr) {
|
||||
// Unlike SendReply, which is safe to call on any thread, SendUnsolicitedReply
|
||||
// calls are only safe to make on the IO thread.
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(
|
||||
&PepperUDPSocketMessageFilter::SendRecvFromResultOnIOThread, this,
|
||||
result, data, addr));
|
||||
}
|
||||
|
||||
void PepperUDPSocketMessageFilter::SendRecvFromResultOnIOThread(
|
||||
int32_t result,
|
||||
const std::string& data,
|
||||
const PP_NetAddress_Private& addr) {
|
||||
if (resource_host()) {
|
||||
resource_host()->host()->SendUnsolicitedReply(
|
||||
resource_host()->pp_resource(),
|
||||
@ -794,12 +726,6 @@ void PepperUDPSocketMessageFilter::SendSendToReply(
|
||||
void PepperUDPSocketMessageFilter::SendBindError(
|
||||
const ppapi::host::ReplyMessageContext& context,
|
||||
int32_t result) {
|
||||
socket_.reset();
|
||||
#if defined(OS_CHROMEOS)
|
||||
// In the unlikely case that this is due to a Mojo error while trying to open
|
||||
// a hole in the firewall on ChromeOS, abandon opening a hole in the firewall.
|
||||
firewall_hole_weak_ptr_factory_.InvalidateWeakPtrs();
|
||||
#endif // !defined(OS_CHROMEOS)
|
||||
SendBindReply(context, result, NetAddressPrivateImpl::kInvalidNetAddress);
|
||||
}
|
||||
|
||||
@ -815,19 +741,6 @@ void PepperUDPSocketMessageFilter::SendSendToError(
|
||||
SendSendToReply(context, result, 0);
|
||||
}
|
||||
|
||||
void PepperUDPSocketMessageFilter::PipeClosed() {
|
||||
Close();
|
||||
|
||||
while (!pending_sends_.empty())
|
||||
FinishPendingSend(PP_ERROR_FAILED);
|
||||
|
||||
// Any reads should fail, after a pipe error.
|
||||
while (remaining_recv_slots_ > 0) {
|
||||
--remaining_recv_slots_;
|
||||
SendRecvFromError(PP_ERROR_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t PepperUDPSocketMessageFilter::CanUseMulticastAPI(
|
||||
const PP_NetAddress_Private& addr) {
|
||||
// Check for plugin permissions.
|
||||
@ -845,29 +758,4 @@ int32_t PepperUDPSocketMessageFilter::CanUseMulticastAPI(
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
template <class ReturnMessage>
|
||||
base::OnceCallback<void(int result)>
|
||||
PepperUDPSocketMessageFilter::CreateCompletionCallback(
|
||||
const ppapi::host::HostMessageContext* context) {
|
||||
std::unique_ptr<int> result = std::make_unique<int>(net::ERR_FAILED);
|
||||
int* result_ptr = result.get();
|
||||
base::ScopedClosureRunner closure_runner(
|
||||
base::BindOnce(&PepperUDPSocketMessageFilter::ReturnResult<ReturnMessage>,
|
||||
base::Unretained(this), context->MakeReplyMessageContext(),
|
||||
base::Passed(std::move(result))));
|
||||
return base::BindOnce(
|
||||
[](base::ScopedClosureRunner closure_runner, int* result_ptr,
|
||||
int net_result) { *result_ptr = net_result; },
|
||||
std::move(closure_runner), result_ptr);
|
||||
}
|
||||
|
||||
template <class ReturnMessage>
|
||||
void PepperUDPSocketMessageFilter::ReturnResult(
|
||||
const ppapi::host::ReplyMessageContext& context,
|
||||
std::unique_ptr<int> result) {
|
||||
ppapi::host::ReplyMessageContext reply_context(context);
|
||||
reply_context.params.set_result(NetErrorToPepperError(*result));
|
||||
SendReply(reply_context, ReturnMessage());
|
||||
}
|
||||
|
||||
} // namespace content
|
||||
|
@ -6,29 +6,26 @@
|
||||
#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_UDP_SOCKET_MESSAGE_FILTER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/containers/queue.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "build/build_config.h"
|
||||
#include "content/common/content_export.h"
|
||||
#include "content/public/common/process_type.h"
|
||||
#include "mojo/public/cpp/bindings/binding.h"
|
||||
#include "net/base/completion_callback.h"
|
||||
#include "net/base/ip_address.h"
|
||||
#include "net/base/ip_endpoint.h"
|
||||
#include "net/socket/udp_socket.h"
|
||||
#include "ppapi/c/pp_instance.h"
|
||||
#include "ppapi/c/pp_stdint.h"
|
||||
#include "ppapi/c/ppb_udp_socket.h"
|
||||
#include "ppapi/host/resource_message_filter.h"
|
||||
#include "services/network/public/mojom/udp_socket.mojom.h"
|
||||
|
||||
struct PP_NetAddress_Private;
|
||||
|
||||
@ -37,6 +34,11 @@ struct PP_NetAddress_Private;
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#endif // defined(OS_CHROMEOS)
|
||||
|
||||
namespace net {
|
||||
class IOBuffer;
|
||||
class IOBufferWithSize;
|
||||
}
|
||||
|
||||
namespace ppapi {
|
||||
|
||||
class SocketOptionData;
|
||||
@ -46,32 +48,17 @@ struct ReplyMessageContext;
|
||||
}
|
||||
}
|
||||
|
||||
namespace network {
|
||||
namespace mojom {
|
||||
class NetworkContext;
|
||||
}
|
||||
} // namespace network
|
||||
|
||||
namespace content {
|
||||
|
||||
class BrowserPpapiHostImpl;
|
||||
|
||||
class CONTENT_EXPORT PepperUDPSocketMessageFilter
|
||||
: public ppapi::host::ResourceMessageFilter,
|
||||
public network::mojom::UDPSocketReceiver {
|
||||
: public ppapi::host::ResourceMessageFilter {
|
||||
public:
|
||||
PepperUDPSocketMessageFilter(BrowserPpapiHostImpl* host,
|
||||
PP_Instance instance,
|
||||
bool private_api);
|
||||
|
||||
using CreateUDPSocketCallback = base::RepeatingCallback<void(
|
||||
network::mojom::NetworkContext* network_context,
|
||||
network::mojom::UDPSocketRequest socket_request,
|
||||
network::mojom::UDPSocketReceiverPtr socket_receiver)>;
|
||||
|
||||
static void SetCreateUDPSocketCallbackForTesting(
|
||||
const CreateUDPSocketCallback* create_udp_socket_callback);
|
||||
|
||||
static size_t GetNumInstances();
|
||||
|
||||
protected:
|
||||
@ -90,19 +77,18 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
|
||||
struct PendingSend {
|
||||
PendingSend(const net::IPAddress& address,
|
||||
int port,
|
||||
std::vector<uint8_t> data,
|
||||
const scoped_refptr<net::IOBufferWithSize>& buffer,
|
||||
const ppapi::host::ReplyMessageContext& context);
|
||||
PendingSend(const PendingSend& other);
|
||||
~PendingSend();
|
||||
|
||||
net::IPAddress address;
|
||||
int port;
|
||||
std::vector<uint8_t> data;
|
||||
scoped_refptr<net::IOBufferWithSize> buffer;
|
||||
ppapi::host::ReplyMessageContext context;
|
||||
};
|
||||
|
||||
// ppapi::host::ResourceMessageFilter overrides.
|
||||
void OnFilterDestroyed() override;
|
||||
scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
|
||||
const IPC::Message& message) override;
|
||||
int32_t OnResourceMessageReceived(
|
||||
@ -125,34 +111,25 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
|
||||
int32_t OnMsgLeaveGroup(const ppapi::host::HostMessageContext* context,
|
||||
const PP_NetAddress_Private& addr);
|
||||
|
||||
void DoBindCallback(network::mojom::UDPSocketReceiverRequest receiver_request,
|
||||
const ppapi::host::ReplyMessageContext& context,
|
||||
int result,
|
||||
const base::Optional<net::IPEndPoint>& local_addr_out);
|
||||
void OnBroadcastConfiguredAfterBind(
|
||||
network::mojom::UDPSocketReceiverRequest receiver_request,
|
||||
const ppapi::host::ReplyMessageContext& context,
|
||||
const net::IPEndPoint& ip_endpoint,
|
||||
const PP_NetAddress_Private& net_address,
|
||||
int net_result);
|
||||
void OnBindComplete(network::mojom::UDPSocketReceiverRequest receiver_request,
|
||||
void DoBind(const ppapi::host::ReplyMessageContext& context,
|
||||
const PP_NetAddress_Private& addr);
|
||||
void OnBindComplete(std::unique_ptr<net::UDPSocket> socket,
|
||||
const ppapi::host::ReplyMessageContext& context,
|
||||
const PP_NetAddress_Private& net_address);
|
||||
#if defined(OS_CHROMEOS)
|
||||
void OnFirewallHoleOpened(
|
||||
network::mojom::UDPSocketReceiverRequest receiver_request,
|
||||
const ppapi::host::ReplyMessageContext& context,
|
||||
const PP_NetAddress_Private& net_address,
|
||||
std::unique_ptr<chromeos::FirewallHole> hole);
|
||||
void OpenFirewallHole(const net::IPEndPoint& local_address,
|
||||
base::Closure bind_complete);
|
||||
void OnFirewallHoleOpened(base::Closure bind_complete,
|
||||
std::unique_ptr<chromeos::FirewallHole> hole);
|
||||
#endif // defined(OS_CHROMEOS)
|
||||
void StartPendingSend();
|
||||
void DoRecvFrom();
|
||||
void DoSendTo(const ppapi::host::ReplyMessageContext& context,
|
||||
const std::string& data,
|
||||
const PP_NetAddress_Private& addr);
|
||||
int StartPendingSend();
|
||||
void Close();
|
||||
|
||||
// network::mojom::UDPSocketReceiver override:
|
||||
void OnReceived(int result,
|
||||
const base::Optional<net::IPEndPoint>& src_addr,
|
||||
base::Optional<base::span<const uint8_t>> data) override;
|
||||
|
||||
void OnRecvFromCompleted(int net_result);
|
||||
void OnSendToCompleted(int net_result);
|
||||
void FinishPendingSend(int net_result);
|
||||
|
||||
@ -162,9 +139,6 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
|
||||
void SendRecvFromResult(int32_t result,
|
||||
const std::string& data,
|
||||
const PP_NetAddress_Private& addr);
|
||||
void SendRecvFromResultOnIOThread(int32_t result,
|
||||
const std::string& data,
|
||||
const PP_NetAddress_Private& addr);
|
||||
void SendSendToReply(const ppapi::host::ReplyMessageContext& context,
|
||||
int32_t result,
|
||||
int32_t bytes_written);
|
||||
@ -174,18 +148,9 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
|
||||
void SendRecvFromError(int32_t result);
|
||||
void SendSendToError(const ppapi::host::ReplyMessageContext& context,
|
||||
int32_t result);
|
||||
void PipeClosed();
|
||||
|
||||
int32_t CanUseMulticastAPI(const PP_NetAddress_Private& addr);
|
||||
|
||||
template <class ReturnMessage>
|
||||
base::OnceCallback<void(int result)> CreateCompletionCallback(
|
||||
const ppapi::host::HostMessageContext* context);
|
||||
|
||||
template <class ReturnMessage>
|
||||
void ReturnResult(const ppapi::host::ReplyMessageContext& context,
|
||||
std::unique_ptr<int> result);
|
||||
|
||||
// Bitwise-or of SocketOption flags. This stores the state about whether
|
||||
// each option is set before Bind() is called.
|
||||
int socket_options_;
|
||||
@ -198,10 +163,20 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
|
||||
int multicast_ttl_;
|
||||
int32_t can_use_multicast_;
|
||||
|
||||
std::unique_ptr<net::UDPSocket> socket_;
|
||||
bool closed_;
|
||||
#if defined(OS_CHROMEOS)
|
||||
std::unique_ptr<chromeos::FirewallHole,
|
||||
content::BrowserThread::DeleteOnUIThread>
|
||||
firewall_hole_;
|
||||
#endif // defined(OS_CHROMEOS)
|
||||
|
||||
scoped_refptr<net::IOBuffer> recvfrom_buffer_;
|
||||
|
||||
base::queue<PendingSend> pending_sends_;
|
||||
|
||||
net::IPEndPoint recvfrom_address_;
|
||||
|
||||
size_t remaining_recv_slots_;
|
||||
|
||||
bool external_plugin_;
|
||||
@ -212,27 +187,6 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
|
||||
|
||||
const bool is_potentially_secure_plugin_context_;
|
||||
|
||||
// Bound (in a Mojo sense) when binding (in a network sense) starts. Closed in
|
||||
// Close() and on Mojo pipe errors. Must only be accessed (and destroyed) on
|
||||
// UI thread.
|
||||
network::mojom::UDPSocketPtr socket_;
|
||||
|
||||
// Bound (in a Mojo sense) when binding (in a network sense) completes.
|
||||
// Binding late avoids receiving data when still setting up the socket. Closed
|
||||
// in Close() and on Mojo pipe errors. Must only be accessed (and destroyed)
|
||||
// on UI thread.
|
||||
mojo::Binding<network::mojom::UDPSocketReceiver> binding_;
|
||||
|
||||
#if defined(OS_CHROMEOS)
|
||||
std::unique_ptr<chromeos::FirewallHole,
|
||||
content::BrowserThread::DeleteOnUIThread>
|
||||
firewall_hole_;
|
||||
// Allows for cancellation of opening a hole in the firewall in the case the
|
||||
// network service crashes.
|
||||
base::WeakPtrFactory<PepperUDPSocketMessageFilter>
|
||||
firewall_hole_weak_ptr_factory_;
|
||||
#endif // defined(OS_CHROMEOS)
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PepperUDPSocketMessageFilter);
|
||||
};
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "base/macros.h"
|
||||
#include "base/path_service.h"
|
||||
#include "build/build_config.h"
|
||||
#include "content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h"
|
||||
#include "content/public/common/content_constants.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "ppapi/shared_impl/ppapi_constants.h"
|
||||
@ -145,10 +144,4 @@ bool RegisterBlinkTestPlugin(base::CommandLine* command_line) {
|
||||
return RegisterPlugins(command_line, plugins);
|
||||
}
|
||||
|
||||
void SetPepperUDPSocketCallackForTesting(
|
||||
const CreateUDPSocketCallback* create_udp_socket_callback) {
|
||||
content::PepperUDPSocketMessageFilter::SetCreateUDPSocketCallbackForTesting(
|
||||
create_udp_socket_callback);
|
||||
}
|
||||
|
||||
} // namespace ppapi
|
||||
|
@ -5,21 +5,13 @@
|
||||
#ifndef CONTENT_PUBLIC_TEST_PPAPI_TEST_UTILS_H_
|
||||
#define CONTENT_PUBLIC_TEST_PPAPI_TEST_UTILS_H_
|
||||
|
||||
#include "base/callback_forward.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "services/network/public/mojom/udp_socket.mojom.h"
|
||||
|
||||
namespace base {
|
||||
class CommandLine;
|
||||
}
|
||||
|
||||
namespace network {
|
||||
namespace mojom {
|
||||
class NetworkContext;
|
||||
}
|
||||
} // namespace network
|
||||
|
||||
// This file specifies utility functions used in Pepper testing in
|
||||
// browser_tests and content_browsertests.
|
||||
namespace ppapi {
|
||||
@ -43,17 +35,6 @@ bool RegisterFlashTestPlugin(base::CommandLine* command_line)
|
||||
bool RegisterBlinkTestPlugin(base::CommandLine* command_line)
|
||||
WARN_UNUSED_RESULT;
|
||||
|
||||
using CreateUDPSocketCallback = base::RepeatingCallback<void(
|
||||
network::mojom::NetworkContext* network_context,
|
||||
network::mojom::UDPSocketRequest socket_request,
|
||||
network::mojom::UDPSocketReceiverPtr socket_receiver)>;
|
||||
|
||||
// Sets callback to be invoked when creating a UDPSocket for use by pepper.
|
||||
// Passed in callback must remain valid until the method is called again with
|
||||
// a nullptr, to clear the callback.
|
||||
void SetPepperUDPSocketCallackForTesting(
|
||||
const CreateUDPSocketCallback* create_udp_socket_callback);
|
||||
|
||||
} // namespace ppapi
|
||||
|
||||
#endif // CONTENT_PUBLIC_TEST_PPAPI_TEST_UTILS_H_
|
||||
|
@ -54,7 +54,7 @@ void ResourceMessageFilter::OnFilterAdded(ResourceHost* resource_host) {
|
||||
}
|
||||
|
||||
void ResourceMessageFilter::OnFilterDestroyed() {
|
||||
resource_host_ = nullptr;
|
||||
resource_host_ = NULL;
|
||||
}
|
||||
|
||||
bool ResourceMessageFilter::HandleMessage(const IPC::Message& msg,
|
||||
|
@ -92,7 +92,7 @@ class PPAPI_HOST_EXPORT ResourceMessageFilter
|
||||
// Called when a filter is added to a ResourceHost.
|
||||
void OnFilterAdded(ResourceHost* resource_host);
|
||||
// Called when a filter is removed from a ResourceHost.
|
||||
virtual void OnFilterDestroyed();
|
||||
void OnFilterDestroyed();
|
||||
|
||||
// This will dispatch the message handler on the target thread. It returns
|
||||
// true if the message was handled by this filter and false otherwise.
|
||||
|
@ -226,11 +226,11 @@ int32_t UDPSocketFilter::RecvQueue::RequestData(
|
||||
if (static_cast<size_t>(num_bytes) < front.data.size())
|
||||
return PP_ERROR_MESSAGE_TOO_BIG;
|
||||
|
||||
int32_t result = static_cast<int32_t>(front.data.size());
|
||||
std::unique_ptr<std::string> data_to_pass(new std::string);
|
||||
data_to_pass->swap(front.data);
|
||||
int32_t result =
|
||||
SetRecvFromOutput(pp_instance_, std::move(data_to_pass), front.addr,
|
||||
buffer_out, num_bytes, addr_out, front.result);
|
||||
SetRecvFromOutput(pp_instance_, std::move(data_to_pass), front.addr,
|
||||
buffer_out, num_bytes, addr_out, PP_OK);
|
||||
last_recvfrom_addr_ = front.addr;
|
||||
recv_buffers_.pop();
|
||||
slot_available_callback_.Run();
|
||||
|
@ -104,14 +104,6 @@ void TestUDPSocket::RunTests(const std::string& filter) {
|
||||
RUN_CALLBACK_TEST(TestUDPSocket, SetOption, filter);
|
||||
RUN_CALLBACK_TEST(TestUDPSocket, ParallelSend, filter);
|
||||
RUN_CALLBACK_TEST(TestUDPSocket, Multicast, filter);
|
||||
|
||||
// Failure tests. Generally can only be run individually, since they require
|
||||
// specific socket failures to be injected into the UDP code.
|
||||
RUN_CALLBACK_TEST(TestUDPSocket, BindFails, filter);
|
||||
RUN_CALLBACK_TEST(TestUDPSocket, BroadcastBeforeBindFails, filter);
|
||||
RUN_CALLBACK_TEST(TestUDPSocket, BroadcastAfterBindFails, filter);
|
||||
RUN_CALLBACK_TEST(TestUDPSocket, SendToFails, filter);
|
||||
RUN_CALLBACK_TEST(TestUDPSocket, ReadFails, filter);
|
||||
}
|
||||
|
||||
std::string TestUDPSocket::GetLocalAddress(pp::NetAddress* address) {
|
||||
@ -524,93 +516,3 @@ std::string TestUDPSocket::TestMulticast() {
|
||||
|
||||
PASS();
|
||||
}
|
||||
|
||||
std::string TestUDPSocket::TestBindFails() {
|
||||
pp::UDPSocket socket(instance_);
|
||||
|
||||
PP_NetAddress_IPv4 any_ipv4_address = {0, {0, 0, 0, 0}};
|
||||
pp::NetAddress any_address(instance_, any_ipv4_address);
|
||||
TestCompletionCallback callback(instance_->pp_instance(), callback_type());
|
||||
callback.WaitForResult(socket.Bind(any_address, callback.GetCallback()));
|
||||
CHECK_CALLBACK_BEHAVIOR(callback);
|
||||
ASSERT_EQ(PP_ERROR_FAILED, callback.result());
|
||||
PASS();
|
||||
}
|
||||
|
||||
std::string TestUDPSocket::TestBroadcastBeforeBindFails() {
|
||||
pp::UDPSocket socket(instance_);
|
||||
ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&socket));
|
||||
|
||||
PP_NetAddress_IPv4 any_ipv4_address = {0, {0, 0, 0, 0}};
|
||||
pp::NetAddress any_address(instance_, any_ipv4_address);
|
||||
TestCompletionCallback callback(instance_->pp_instance(), callback_type());
|
||||
callback.WaitForResult(socket.Bind(any_address, callback.GetCallback()));
|
||||
CHECK_CALLBACK_BEHAVIOR(callback);
|
||||
ASSERT_EQ(PP_ERROR_FAILED, callback.result());
|
||||
PASS();
|
||||
}
|
||||
|
||||
std::string TestUDPSocket::TestBroadcastAfterBindFails() {
|
||||
pp::UDPSocket socket(instance_);
|
||||
PP_NetAddress_IPv4 any_ipv4_address = {0, {0, 0, 0, 0}};
|
||||
pp::NetAddress any_address(instance_, any_ipv4_address);
|
||||
ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&socket, any_address));
|
||||
|
||||
TestCompletionCallback callback(instance_->pp_instance(), callback_type());
|
||||
callback.WaitForResult(socket.SetOption(
|
||||
PP_UDPSOCKET_OPTION_BROADCAST, pp::Var(true), callback.GetCallback()));
|
||||
CHECK_CALLBACK_BEHAVIOR(callback);
|
||||
ASSERT_EQ(PP_ERROR_FAILED, callback.result());
|
||||
|
||||
// Setting broadcast again should also fail.
|
||||
TestCompletionCallback callback_2(instance_->pp_instance(), callback_type());
|
||||
callback_2.WaitForResult(socket.SetOption(
|
||||
PP_UDPSOCKET_OPTION_BROADCAST, pp::Var(true), callback_2.GetCallback()));
|
||||
CHECK_CALLBACK_BEHAVIOR(callback_2);
|
||||
ASSERT_EQ(PP_ERROR_FAILED, callback_2.result());
|
||||
PASS();
|
||||
}
|
||||
|
||||
std::string TestUDPSocket::TestSendToFails() {
|
||||
pp::UDPSocket socket(instance_);
|
||||
PP_NetAddress_IPv4 any_ipv4_address = {0, {0, 0, 0, 0}};
|
||||
pp::NetAddress any_address(instance_, any_ipv4_address);
|
||||
ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&socket, any_address));
|
||||
|
||||
std::vector<char> buffer(1);
|
||||
buffer[0] = 1;
|
||||
PP_NetAddress_IPv4 target_ipv4_address = {1024, {127, 0, 0, 1}};
|
||||
pp::NetAddress target_address(instance_, target_ipv4_address);
|
||||
// All writes should fail.
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
TestCompletionCallbackWithOutput<pp::NetAddress> callback(
|
||||
instance_->pp_instance(), callback_type());
|
||||
callback.WaitForResult(
|
||||
socket.SendTo(buffer.data(), static_cast<int32_t>(buffer.size()),
|
||||
target_address, callback.GetCallback()));
|
||||
CHECK_CALLBACK_BEHAVIOR(callback);
|
||||
ASSERT_EQ(PP_ERROR_FAILED, callback.result());
|
||||
}
|
||||
PASS();
|
||||
}
|
||||
|
||||
std::string TestUDPSocket::TestReadFails() {
|
||||
pp::UDPSocket socket(instance_);
|
||||
PP_NetAddress_IPv4 any_ipv4_address = {0, {0, 0, 0, 0}};
|
||||
pp::NetAddress any_address(instance_, any_ipv4_address);
|
||||
ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&socket, any_address));
|
||||
|
||||
std::vector<char> buffer(1);
|
||||
// All reads should fail. Larger number of reads increases the chance that at
|
||||
// least one read will be synchronous.
|
||||
for (int i = 0; i < 200; ++i) {
|
||||
TestCompletionCallbackWithOutput<pp::NetAddress> callback(
|
||||
instance_->pp_instance(), callback_type());
|
||||
callback.WaitForResult(socket.RecvFrom(&buffer[0],
|
||||
static_cast<int32_t>(buffer.size()),
|
||||
callback.GetCallback()));
|
||||
CHECK_CALLBACK_BEHAVIOR(callback);
|
||||
ASSERT_EQ(PP_ERROR_FAILED, callback.result());
|
||||
}
|
||||
PASS();
|
||||
}
|
||||
|
@ -63,14 +63,6 @@ class TestUDPSocket: public TestCase {
|
||||
std::string TestParallelSend();
|
||||
std::string TestMulticast();
|
||||
|
||||
// Error cases. It's up to the parent test fixture to ensure that these events
|
||||
// result in errors.
|
||||
std::string TestBindFails();
|
||||
std::string TestBroadcastBeforeBindFails();
|
||||
std::string TestBroadcastAfterBindFails();
|
||||
std::string TestSendToFails();
|
||||
std::string TestReadFails();
|
||||
|
||||
pp::NetAddress address_;
|
||||
|
||||
const PPB_UDPSocket_1_0* socket_interface_1_0_;
|
||||
|
@ -176,7 +176,6 @@ Refer to README.md for content description and update process.
|
||||
<item id="payments_sync_cards" hash_code="95588446" type="0" content_hash_code="56526513" os_list="linux,windows" file_path="components/autofill/core/browser/payments/payments_client.cc"/>
|
||||
<item id="pdf_plugin_placeholder" hash_code="56866367" type="0" content_hash_code="16907221" os_list="linux,windows" file_path="chrome/browser/plugins/pdf_plugin_placeholder_observer.cc"/>
|
||||
<item id="pepper_tcp_socket" hash_code="120623198" type="0" content_hash_code="55474823" os_list="linux,windows" file_path="content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc"/>
|
||||
<item id="pepper_udp_socket_message_filter" hash_code="19997224" type="0" content_hash_code="62688533" os_list="linux,mac,windows" file_path="content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc"/>
|
||||
<item id="per_user_topic_registration_request" hash_code="10498172" type="0" content_hash_code="32495619" os_list="linux,windows" file_path="components/invalidation/impl/per_user_topic_registration_request.cc"/>
|
||||
<item id="permission_reporting" hash_code="131741641" type="0" deprecated="2018-03-06" content_hash_code="7213535" file_path=""/>
|
||||
<item id="permission_request_creator" hash_code="43206794" type="0" content_hash_code="73571699" os_list="linux,windows" file_path="chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.cc"/>
|
||||
|
Reference in New Issue
Block a user