Import Cobalt 3.16138

Change-Id: Iad7893b4f903845cfb7cbda22d7f5e4153ed8dea
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc
index 7949da2..0e1bd9d 100644
--- a/src/cobalt/browser/browser_module.cc
+++ b/src/cobalt/browser/browser_module.cc
@@ -296,6 +296,8 @@
 }
 
 void BrowserModule::Navigate(const GURL& url) {
+  web_module_loaded_.Reset();
+
   // Always post this as a task in case this is being called from the WebModule.
   self_message_loop_->PostTask(
       FROM_HERE, base::Bind(&BrowserModule::NavigateInternal, weak_this_, url));
@@ -326,8 +328,6 @@
 void BrowserModule::NavigateInternal(const GURL& url) {
   DCHECK_EQ(MessageLoop::current(), self_message_loop_);
 
-  web_module_loaded_.Reset();
-
   // First try the registered handlers (e.g. for h5vcc://). If one of these
   // handles the URL, we don't use the web module.
   if (TryURLHandlers(url)) {
@@ -391,9 +391,11 @@
   web_module_loaded_.Signal();
 }
 
+#if defined(ENABLE_WEBDRIVER)
 bool BrowserModule::WaitForLoad(const base::TimeDelta& timeout) {
   return web_module_loaded_.TimedWait(timeout);
 }
+#endif
 
 #if defined(ENABLE_SCREENSHOT)
 void BrowserModule::RequestScreenshotToFile(const FilePath& path,
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h
index 5d39973..0a0584c 100644
--- a/src/cobalt/browser/browser_module.h
+++ b/src/cobalt/browser/browser_module.h
@@ -134,10 +134,12 @@
   // Called when the WebModule's Window.onload event is fired.
   void OnLoad();
 
+#if defined(ENABLE_WEBDRIVER)
   // Wait for the onload event to be fired with the specified timeout. If the
   // webmodule is not currently loading the document, this will return
   // immediately.
   bool WaitForLoad(const base::TimeDelta& timeout);
+#endif
 
   // Glue function to deal with the production of the main render tree,
   // and will manage handing it off to the renderer.
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index f9b0452..389d8f5 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-12305
\ No newline at end of file
+16138
\ No newline at end of file
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/google_logging.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/google_logging.cc
index bab22ce..bc53d2f 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/google_logging.cc
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/google_logging.cc
@@ -19,7 +19,9 @@
   base::StringAppendV(&message, format, ap);
   va_end(ap);
 
-  logging::LogMessage(file, line,
-                      fatal ? logging::LOG_FATAL : logging::LOG_INFO).stream()
-      << message;
+  if (fatal) {
+    logging::LogMessage(file, line, logging::LOG_FATAL).stream() << message;
+  } else if (DLOG_IS_ON(INFO)) {
+    logging::LogMessage(file, line, logging::LOG_INFO).stream() << message;
+  }
 }
diff --git a/src/cobalt/script/mozjs/mozjs_global_environment.cc b/src/cobalt/script/mozjs/mozjs_global_environment.cc
index 25fa34b..ebcc75f 100644
--- a/src/cobalt/script/mozjs/mozjs_global_environment.cc
+++ b/src/cobalt/script/mozjs/mozjs_global_environment.cc
@@ -238,6 +238,58 @@
   return success;
 }
 
+bool MozjsGlobalEnvironment::EvaluateScript(
+    const scoped_refptr<SourceCode>& source_code,
+    const scoped_refptr<Wrappable>& owning_object,
+    base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  JSAutoRequest auto_request(context_);
+  JSAutoCompartment auto_compartment(context_, global_object_proxy_);
+  JSExceptionState* previous_exception_state = JS_SaveExceptionState(context_);
+  JS::RootedValue result_value(context_);
+  if (!EvaluateScriptInternal(source_code, &result_value)) {
+    return false;
+  }
+  if (out_opaque_handle) {
+    JS::RootedObject js_object(context_);
+    JS_ValueToObject(context_, result_value, js_object.address());
+    MozjsObjectHandleHolder mozjs_object_holder(js_object, context_,
+                                                wrapper_factory());
+    out_opaque_handle->emplace(owning_object.get(), mozjs_object_holder);
+  }
+  JS_RestoreExceptionState(context_, previous_exception_state);
+  return true;
+}
+
+bool MozjsGlobalEnvironment::EvaluateScriptInternal(
+    const scoped_refptr<SourceCode>& source_code,
+    JS::MutableHandleValue out_result) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(global_object_proxy_);
+  MozjsSourceCode* mozjs_source_code =
+      base::polymorphic_downcast<MozjsSourceCode*>(source_code.get());
+
+  const std::string& script = mozjs_source_code->source_utf8();
+  const base::SourceLocation location = mozjs_source_code->location();
+
+  JS::RootedObject global_object(
+      context_, js::GetProxyTargetObject(global_object_proxy_));
+
+  size_t length = script.size();
+  jschar* inflated_buffer =
+      js::InflateUTF8String(context_, script.c_str(), &length);
+  DCHECK(inflated_buffer);
+  bool success = false;
+  if (inflated_buffer) {
+    success = JS_EvaluateUCScript(context_, global_object, inflated_buffer,
+                                  length, location.file_path.c_str(),
+                                  location.line_number, out_result.address());
+    js_free(inflated_buffer);
+  }
+
+  return success;
+}
+
 std::vector<StackFrame> MozjsGlobalEnvironment::GetStackTrace(int max_frames) {
   DCHECK(thread_checker_.CalledOnValidThread());
   return util::GetStackTrace(context_, max_frames);
@@ -321,7 +373,7 @@
   if (global_object_proxy_ && garbage_collection_count_ == 1) {
     DCHECK(!opaque_root_state_);
     JSAutoRequest auto_request(context_);
-    JSAutoCompartment auto_comparment(context_, global_object_proxy_);
+    JSAutoCompartment auto_compartment(context_, global_object_proxy_);
     // Get the current state of opaque root relationships. Keep this object
     // alive for the duration of the GC phase to ensure that reachability
     // between roots and reachable objects is maintained.
diff --git a/src/cobalt/script/mozjs/mozjs_global_environment.h b/src/cobalt/script/mozjs/mozjs_global_environment.h
index 54f75de..d13d7f0 100644
--- a/src/cobalt/script/mozjs/mozjs_global_environment.h
+++ b/src/cobalt/script/mozjs/mozjs_global_environment.h
@@ -56,10 +56,7 @@
   bool EvaluateScript(const scoped_refptr<SourceCode>& script_utf8,
                       const scoped_refptr<Wrappable>& owning_object,
                       base::optional<OpaqueHandleHolder::Reference>*
-                          out_opaque_handle) OVERRIDE {
-    NOTIMPLEMENTED();
-    return false;
-  }
+                          out_opaque_handle) OVERRIDE;
 
   std::vector<StackFrame> GetStackTrace(int max_frames = 0) OVERRIDE;
 
@@ -133,7 +130,10 @@
   // with an error that eval() is disabled.
   static JSBool CheckEval(JSContext* context);
 
- protected:
+ private:
+  bool EvaluateScriptInternal(const scoped_refptr<SourceCode>& source_code,
+                              JS::MutableHandleValue out_result);
+
   static void ReportErrorHandler(JSContext* context, const char* message,
                                  JSErrorReport* report);
 
diff --git a/src/nb/reuse_allocator.cc b/src/nb/reuse_allocator.cc
index 61a40a6..988d530 100644
--- a/src/nb/reuse_allocator.cc
+++ b/src/nb/reuse_allocator.cc
@@ -196,21 +196,8 @@
 }
 
 void ReuseAllocator::Free(void* memory) {
-  if (!memory) {
-    return;
-  }
-
-  AllocatedBlockMap::iterator it = allocated_blocks_.find(memory);
-  SB_DCHECK(it != allocated_blocks_.end());
-
-  // Mark this block as free and remove it from the allocated set.
-  const MemoryBlock& block = (*it).second;
-  AddFreeBlock(block.address, block.size);
-
-  SB_DCHECK(block.size <= total_allocated_);
-  total_allocated_ -= block.size;
-
-  allocated_blocks_.erase(it);
+  bool result = TryFree(memory);
+  SB_DCHECK(result);
 }
 
 void ReuseAllocator::PrintAllocations() const {
@@ -232,4 +219,25 @@
   SB_LOG(INFO) << "Total allocations: " << allocated_blocks_.size();
 }
 
+bool ReuseAllocator::TryFree(void* memory) {
+  if (!memory) {
+    return true;
+  }
+
+  AllocatedBlockMap::iterator it = allocated_blocks_.find(memory);
+  if (it == allocated_blocks_.end()) {
+    return false;
+  }
+
+  // Mark this block as free and remove it from the allocated set.
+  const MemoryBlock& block = (*it).second;
+  AddFreeBlock(block.address, block.size);
+
+  SB_DCHECK(block.size <= total_allocated_);
+  total_allocated_ -= block.size;
+
+  allocated_blocks_.erase(it);
+  return true;
+}
+
 }  // namespace nb
diff --git a/src/nb/reuse_allocator.h b/src/nb/reuse_allocator.h
index 6f4f16a..942bc45 100644
--- a/src/nb/reuse_allocator.h
+++ b/src/nb/reuse_allocator.h
@@ -49,6 +49,8 @@
 
   void PrintAllocations() const;
 
+  bool TryFree(void* memory);
+
  private:
   // We will allocate from the given allocator whenever we can't find
   // pre-used memory to allocate.
diff --git a/src/net/socket/tcp_client_socket_starboard.cc b/src/net/socket/tcp_client_socket_starboard.cc
index 042acd7..516be9d 100644
--- a/src/net/socket/tcp_client_socket_starboard.cc
+++ b/src/net/socket/tcp_client_socket_starboard.cc
@@ -48,8 +48,10 @@
   SbSocketSetTcpNoDelay(socket, true);
   SbSocketSetTcpKeepAlive(socket, true, kTCPKeepAliveDuration);
   SbSocketSetTcpWindowScaling(socket, true);
-  SbSocketSetReceiveBufferSize(socket,
-                               TCPClientSocketStarboard::kReceiveBufferSize);
+  if (TCPClientSocketStarboard::kReceiveBufferSize != 0) {
+    SbSocketSetReceiveBufferSize(socket,
+                                 TCPClientSocketStarboard::kReceiveBufferSize);
+  }
   return 0;
 }
 
diff --git a/src/starboard/linux/shared/configuration_public.h b/src/starboard/linux/shared/configuration_public.h
index 624909f..468f0c6 100644
--- a/src/starboard/linux/shared/configuration_public.h
+++ b/src/starboard/linux/shared/configuration_public.h
@@ -340,8 +340,19 @@
 
 // --- Tuneable Parameters ---------------------------------------------------
 
-// Specifies the network receive buffer size.
-#define SB_NETWORK_RECEIVE_BUFFER_SIZE (16 * 1024)
+// Specifies the network receive buffer size in bytes, set via
+// SbSocketSetReceiveBufferSize().
+//
+// Setting this to 0 indicates that SbSocketSetReceiveBufferSize() should
+// not be called. Use this for OSs (such as Linux) where receive buffer
+// auto-tuning is better.
+//
+// On some platforms, this may affect max TCP window size which may
+// dramatically affect throughput in the presence of latency.
+//
+// If your platform does not have a good TCP auto-tuning mechanism,
+// a setting of (128 * 1024) here is recommended.
+#define SB_NETWORK_RECEIVE_BUFFER_SIZE (0)
 
 // --- User Configuration ----------------------------------------------------
 
diff --git a/src/starboard/nplb/socket_send_to_test.cc b/src/starboard/nplb/socket_send_to_test.cc
index b7b2f06..9db1d36 100644
--- a/src/starboard/nplb/socket_send_to_test.cc
+++ b/src/starboard/nplb/socket_send_to_test.cc
@@ -15,19 +15,78 @@
 // SendTo is largely tested with ReceiveFrom, so look there for more invovled
 // tests.
 
+#include "starboard/memory.h"
+#include "starboard/nplb/socket_helpers.h"
 #include "starboard/socket.h"
+#include "starboard/thread.h"
+#include "starboard/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace starboard {
 namespace nplb {
 namespace {
 
+// Thread entry point to continuously write to a socket that is expected to
+// be closed on another thread.
+void* SendToServerSocketEntryPoint(void* trio_as_void_ptr) {
+  ConnectedTrio* trio = static_cast<ConnectedTrio*>(trio_as_void_ptr);
+  // The contents of this buffer are inconsequential.
+  const size_t kBufSize = 1024;
+  char* send_buf = new char[kBufSize];
+  SbMemorySet(send_buf, 0, kBufSize);
+
+  // Continue sending to the socket until it fails to send. It's expected that
+  // SbSocketSendTo will fail when the server socket closes, but the application
+  // should
+  // not terminate.
+  SbTime start = SbTimeGetNow();
+  SbTime now = start;
+  SbTime kTimeout = kSbTimeSecond;
+  int result = 0;
+  while (result >= 0 && (now - start < kTimeout)) {
+    result = SbSocketSendTo(trio->server_socket, send_buf, kBufSize, NULL);
+    now = SbTimeGetNow();
+  }
+
+  delete[] send_buf;
+  return NULL;
+}
+
 TEST(SbSocketSendToTest, RainyDayInvalidSocket) {
   char buf[16];
   int result = SbSocketSendTo(NULL, buf, sizeof(buf), NULL);
   EXPECT_EQ(-1, result);
 }
 
+TEST(SbSocketSendToTest, RainyDaySendToClosedSocket) {
+  ConnectedTrio trio =
+      CreateAndConnect(GetPortNumberForTests(), kSocketTimeout);
+  EXPECT_NE(trio.client_socket, kSbSocketInvalid);
+  EXPECT_NE(trio.server_socket, kSbSocketInvalid);
+  EXPECT_NE(trio.listen_socket, kSbSocketInvalid);
+
+  // We don't need the listen socket, so close it.
+  EXPECT_TRUE(SbSocketDestroy(trio.listen_socket));
+
+  // Start a thread to write to the client socket.
+  const bool kJoinable = true;
+  SbThread send_thread = SbThreadCreate(
+      0, kSbThreadNoPriority, kSbThreadNoAffinity, kJoinable, "SendToTest",
+      SendToServerSocketEntryPoint, static_cast<void*>(&trio));
+
+  // Close the client, which should cause writes to the server socket to fail.
+  EXPECT_TRUE(SbSocketDestroy(trio.client_socket));
+
+  // Wait for the thread to exit and check the last socket error.
+  void* thread_result;
+  EXPECT_TRUE(SbThreadJoin(send_thread, &thread_result));
+  // Check that the server_socket failed, as expected.
+  EXPECT_EQ(SbSocketGetLastError(trio.server_socket), kSbSocketErrorFailed);
+
+  // Clean up the server socket.
+  EXPECT_TRUE(SbSocketDestroy(trio.server_socket));
+}
+
 }  // namespace
 }  // namespace nplb
 }  // namespace starboard
diff --git a/src/starboard/raspi/shared/configuration_public.h b/src/starboard/raspi/shared/configuration_public.h
index b7ba3a6..a677867 100644
--- a/src/starboard/raspi/shared/configuration_public.h
+++ b/src/starboard/raspi/shared/configuration_public.h
@@ -335,8 +335,19 @@
 
 // --- Tuneable Parameters ---------------------------------------------------
 
-// Specifies the network receive buffer size.
-#define SB_NETWORK_RECEIVE_BUFFER_SIZE (16 * 1024)
+// Specifies the network receive buffer size in bytes, set via
+// SbSocketSetReceiveBufferSize().
+//
+// Setting this to 0 indicates that SbSocketSetReceiveBufferSize() should
+// not be called. Use this for OSs (such as Linux) where receive buffer
+// auto-tuning is better.
+//
+// On some platforms, this may affect max TCP window size which may
+// dramatically affect throughput in the presence of latency.
+//
+// If your platform does not have a good TCP auto-tuning mechanism,
+// a setting of (128 * 1024) here is recommended.
+#define SB_NETWORK_RECEIVE_BUFFER_SIZE (0)
 
 // --- User Configuration ----------------------------------------------------
 
diff --git a/src/starboard/shared/posix/socket_receive_from.cc b/src/starboard/shared/posix/socket_receive_from.cc
index 6acea4c..c4819b6 100644
--- a/src/starboard/shared/posix/socket_receive_from.cc
+++ b/src/starboard/shared/posix/socket_receive_from.cc
@@ -27,6 +27,12 @@
                         char* out_data,
                         int data_size,
                         SbSocketAddress* out_source) {
+#if defined(MSG_NOSIGNAL)
+  const int kRecvFlags = MSG_NOSIGNAL;
+#else
+  const int kRecvFlags = 0;
+#endif
+
   if (!SbSocketIsValid(socket)) {
     errno = EBADF;
     return -1;
@@ -52,7 +58,8 @@
       }
     }
 
-    ssize_t bytes_read = recv(socket->socket_fd, out_data, data_size, 0);
+    ssize_t bytes_read =
+        recv(socket->socket_fd, out_data, data_size, kRecvFlags);
     if (bytes_read >= 0) {
       socket->error = kSbSocketOk;
       return static_cast<int>(bytes_read);
@@ -66,8 +73,9 @@
     return -1;
   } else if (socket->protocol == kSbSocketProtocolUdp) {
     sbposix::SockAddr sock_addr;
-    ssize_t bytes_read = recvfrom(socket->socket_fd, out_data, data_size, 0,
-                                  sock_addr.sockaddr(), &sock_addr.length);
+    ssize_t bytes_read =
+        recvfrom(socket->socket_fd, out_data, data_size, kRecvFlags,
+                 sock_addr.sockaddr(), &sock_addr.length);
 
     if (bytes_read >= 0) {
       if (out_source) {
diff --git a/src/starboard/shared/posix/socket_send_to.cc b/src/starboard/shared/posix/socket_send_to.cc
index 23e134d..6cd0c70 100644
--- a/src/starboard/shared/posix/socket_send_to.cc
+++ b/src/starboard/shared/posix/socket_send_to.cc
@@ -26,6 +26,11 @@
                    const char* data,
                    int data_size,
                    const SbSocketAddress* destination) {
+#if defined(MSG_NOSIGNAL)
+  const int kSendFlags = MSG_NOSIGNAL;
+#else
+  const int kSendFlags = 0;
+#endif
   if (!SbSocketIsValid(socket)) {
     errno = EBADF;
     return -1;
@@ -39,7 +44,8 @@
       return -1;
     }
 
-    ssize_t bytes_written = send(socket->socket_fd, data, data_size, 0);
+    ssize_t bytes_written =
+        send(socket->socket_fd, data, data_size, kSendFlags);
     if (bytes_written >= 0) {
       socket->error = kSbSocketOk;
       return static_cast<int>(bytes_written);
@@ -70,8 +76,8 @@
       sockaddr_length = sock_addr.length;
     }
 
-    ssize_t bytes_written = sendto(socket->socket_fd, data, data_size, 0,
-                                   sockaddr, sockaddr_length);
+    ssize_t bytes_written = sendto(socket->socket_fd, data, data_size,
+                                   kSendFlags, sockaddr, sockaddr_length);
     if (bytes_written >= 0) {
       socket->error = kSbSocketOk;
       return static_cast<int>(bytes_written);
diff --git a/src/starboard/shared/starboard/log_message.cc b/src/starboard/shared/starboard/log_message.cc
index 8e654b4..444bcd6 100644
--- a/src/starboard/shared/starboard/log_message.cc
+++ b/src/starboard/shared/starboard/log_message.cc
@@ -51,7 +51,11 @@
 }
 
 SbLogPriority GetMinLogLevel() {
+#if SB_LOGGING_IS_OFFICIAL_BUILD
+  return SB_LOG_FATAL;
+#else
   return g_min_log_level;
+#endif
 }
 
 void Break() {
diff --git a/src/starboard/stub/configuration_public.h b/src/starboard/stub/configuration_public.h
index af9c671..792ecbb 100644
--- a/src/starboard/stub/configuration_public.h
+++ b/src/starboard/stub/configuration_public.h
@@ -408,8 +408,19 @@
 
 // --- Tuneable Parameters ---------------------------------------------------
 
-// Specifies the network receive buffer size.
-#define SB_NETWORK_RECEIVE_BUFFER_SIZE (16 * 1024)
+// Specifies the network receive buffer size in bytes, set via
+// SbSocketSetReceiveBufferSize().
+//
+// Setting this to 0 indicates that SbSocketSetReceiveBufferSize() should
+// not be called. Use this for OSs (such as Linux) where receive buffer
+// auto-tuning is better.
+//
+// On some platforms, this may affect max TCP window size which may
+// dramatically affect throughput in the presence of latency.
+//
+// If your platform does not have a good TCP auto-tuning mechanism,
+// a setting of (128 * 1024) here is recommended.
+#define SB_NETWORK_RECEIVE_BUFFER_SIZE (0)
 
 // --- User Configuration ----------------------------------------------------