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.

This is a reland of https://chromium-review.googlesource.com/1171568,
which was reverted due to tests failing on OSX when broadcast was set
only after calling Bind, due to the Bind call failing. The new CL
uses a new UDPSocketOption to allow broadcast before calling Bind on
the underlying socket.

TBR=jam@chromium.org, rhalvati@chromium.org

Bug: 848078, 876824
Change-Id: I0e31a357eb4b80bb78bae32f2a3ea3ce331256ec
Cq-Include-Trybots: luci.chromium.try:linux_mojo
Reviewed-on: https://chromium-review.googlesource.com/1190407
Reviewed-by: Matt Menke <mmenke@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Reviewed-by: John Abd-El-Malek <jam@chromium.org>
Commit-Queue: Matt Menke <mmenke@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#586497}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 80c224c08e567070336c4762f8a56d405c134929
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..16a1a77 100644
--- a/tests/test_udp_socket.cc
+++ b/tests/test_udp_socket.cc
@@ -104,6 +104,13 @@
   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, SetBroadcastFails, filter);
+  RUN_CALLBACK_TEST(TestUDPSocket, SendToFails, filter);
+  RUN_CALLBACK_TEST(TestUDPSocket, ReadFails, filter);
 }
 
 std::string TestUDPSocket::GetLocalAddress(pp::NetAddress* address) {
@@ -516,3 +523,80 @@
 
   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::TestSetBroadcastFails() {
+  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..4df5bc2 100644
--- a/tests/test_udp_socket.h
+++ b/tests/test_udp_socket.h
@@ -63,6 +63,13 @@
   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 TestSetBroadcastFails();
+  std::string TestSendToFails();
+  std::string TestReadFails();
+
   pp::NetAddress address_;
 
   const PPB_UDPSocket_1_0* socket_interface_1_0_;