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-Original-Commit-Position: refs/heads/master@{#585057}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: cc2b634dbe8b987c9946689b6d8c2388cd5466ea
diff --git a/host/resource_message_filter.cc b/host/resource_message_filter.cc
index cea9f9f..2821b8d 100644
--- a/host/resource_message_filter.cc
+++ b/host/resource_message_filter.cc
@@ -54,7 +54,7 @@
 }
 
 void ResourceMessageFilter::OnFilterDestroyed() {
-  resource_host_ = NULL;
+  resource_host_ = nullptr;
 }
 
 bool ResourceMessageFilter::HandleMessage(const IPC::Message& msg,
diff --git a/host/resource_message_filter.h b/host/resource_message_filter.h
index 42658ea..932d29e 100644
--- a/host/resource_message_filter.h
+++ b/host/resource_message_filter.h
@@ -92,7 +92,7 @@
   // Called when a filter is added to a ResourceHost.
   void OnFilterAdded(ResourceHost* resource_host);
   // Called when a filter is removed from a ResourceHost.
-  void OnFilterDestroyed();
+  virtual 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.
diff --git a/proxy/udp_socket_filter.cc b/proxy/udp_socket_filter.cc
index ae96c89..8563286 100644
--- a/proxy/udp_socket_filter.cc
+++ b/proxy/udp_socket_filter.cc
@@ -226,11 +226,11 @@
     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);
-    SetRecvFromOutput(pp_instance_, std::move(data_to_pass), front.addr,
-                      buffer_out, num_bytes, addr_out, PP_OK);
+    int32_t result =
+        SetRecvFromOutput(pp_instance_, std::move(data_to_pass), front.addr,
+                          buffer_out, num_bytes, addr_out, front.result);
     last_recvfrom_addr_ = front.addr;
     recv_buffers_.pop();
     slot_available_callback_.Run();
diff --git a/tests/test_udp_socket.cc b/tests/test_udp_socket.cc
index b82019e..29c422b 100644
--- a/tests/test_udp_socket.cc
+++ b/tests/test_udp_socket.cc
@@ -104,6 +104,14 @@
   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) {
@@ -516,3 +524,93 @@
 
   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();
+}
diff --git a/tests/test_udp_socket.h b/tests/test_udp_socket.h
index 5307b39..0ac8482 100644
--- a/tests/test_udp_socket.h
+++ b/tests/test_udp_socket.h
@@ -63,6 +63,14 @@
   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_;