Import Cobalt 3.12305
diff --git a/src/cobalt/base/deep_link_event.h b/src/cobalt/base/deep_link_event.h
index 5e3df4b..b5c2afa 100644
--- a/src/cobalt/base/deep_link_event.h
+++ b/src/cobalt/base/deep_link_event.h
@@ -20,6 +20,7 @@
 #include <string>
 
 #include "base/compiler_specific.h"
+#include "base/string_util.h"
 #include "cobalt/base/event.h"
 
 namespace base {
@@ -28,6 +29,9 @@
  public:
   explicit DeepLinkEvent(const std::string& link) : link_(link) {}
   const std::string& link() const { return link_; }
+  bool IsH5vccLink() const {
+    return StartsWithASCII(link_, "h5vcc", true);
+  }
 
   BASE_EVENT_SUBCLASS(DeepLinkEvent);
 
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc
index 27c9f1a..b6e58dc 100644
--- a/src/cobalt/browser/application.cc
+++ b/src/cobalt/browser/application.cc
@@ -430,6 +430,10 @@
       base::Bind(&Application::OnApplicationEvent, base::Unretained(this));
   event_dispatcher_.AddEventCallback(system_window::ApplicationEvent::TypeId(),
                                      application_event_callback_);
+  deep_link_event_callback_ =
+      base::Bind(&Application::OnDeepLinkEvent, base::Unretained(this));
+  event_dispatcher_.AddEventCallback(base::DeepLinkEvent::TypeId(),
+                                     deep_link_event_callback_);
 
 #if defined(ENABLE_WEBDRIVER)
 #if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
@@ -479,6 +483,8 @@
                                         network_event_callback_);
   event_dispatcher_.RemoveEventCallback(
       system_window::ApplicationEvent::TypeId(), application_event_callback_);
+  event_dispatcher_.RemoveEventCallback(
+      base::DeepLinkEvent::TypeId(), deep_link_event_callback_);
 
   app_status_ = kShutDownAppStatus;
 }
@@ -551,6 +557,15 @@
   }
 }
 
+void Application::OnDeepLinkEvent(const base::Event* event) {
+  const base::DeepLinkEvent* deep_link_event =
+      base::polymorphic_downcast<const base::DeepLinkEvent*>(event);
+  // TODO: Remove this when terminal application states are properly handled.
+  if (deep_link_event->IsH5vccLink()) {
+    browser_module_->Navigate(GURL(deep_link_event->link()));
+  }
+}
+
 void Application::WebModuleRecreated() {
 #if defined(ENABLE_WEBDRIVER)
   if (web_driver_module_) {
diff --git a/src/cobalt/browser/application.h b/src/cobalt/browser/application.h
index 3b5189a..d3a1f9f 100644
--- a/src/cobalt/browser/application.h
+++ b/src/cobalt/browser/application.h
@@ -67,6 +67,9 @@
   // Called to handle an application event.
   void OnApplicationEvent(const base::Event* event);
 
+  // Called to handle a deep link event.
+  void OnDeepLinkEvent(const base::Event* event);
+
   // Called when a navigation occurs in the BrowserModule.
   void WebModuleRecreated();
 
@@ -88,6 +91,7 @@
   base::EventCallback account_event_callback_;
   base::EventCallback network_event_callback_;
   base::EventCallback application_event_callback_;
+  base::EventCallback deep_link_event_callback_;
 
   // Thread checkers to ensure that callbacks for network and application events
   // always occur on the same thread.
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc
index da20704..7949da2 100644
--- a/src/cobalt/browser/browser_module.cc
+++ b/src/cobalt/browser/browser_module.cc
@@ -21,11 +21,13 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/debug/trace_event.h"
+#include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/path_service.h"
 #include "base/stl_util.h"
 #include "base/string_number_conversions.h"
 #include "base/string_split.h"
+#include "base/time.h"
 #include "cobalt/base/cobalt_paths.h"
 #include "cobalt/base/source_location.h"
 #include "cobalt/base/tokens.h"
@@ -36,11 +38,70 @@
 #include "cobalt/dom/keycode.h"
 #include "cobalt/h5vcc/h5vcc.h"
 #include "cobalt/input/input_device_manager_fuzzer.h"
+#include "starboard/atomic.h"
+#include "starboard/system.h"
+#include "starboard/time.h"
+
+#if defined(OS_STARBOARD)
+#include "starboard/configuration.h"
+#if SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
+#define HANDLE_CORE_DUMP
+#include "starboard/ps4/core_dump_handler.h"
+#endif  // SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
+#endif  // OS_STARBOARD
 
 namespace cobalt {
+
+#if defined(COBALT_CHECK_SUBMITDONE_TIMEOUT)
+namespace timestamp {
+// This is a temporary workaround.
+extern SbAtomic64 g_last_submit_done_timestamp;
+}  // namespace timestamp
+
+namespace {
+struct NonTrivialGlobalVariables {
+  NonTrivialGlobalVariables();
+
+  SbAtomic64* last_submit_done_timestamp;
+};
+
+NonTrivialGlobalVariables::NonTrivialGlobalVariables() {
+  last_submit_done_timestamp = &cobalt::timestamp::g_last_submit_done_timestamp;
+  SbAtomicNoBarrier_Exchange64(last_submit_done_timestamp,
+                               static_cast<SbAtomic64>(SbTimeGetNow()));
+}
+
+base::LazyInstance<NonTrivialGlobalVariables> non_trivial_global_variables =
+    LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+#endif
+
 namespace browser {
 namespace {
 
+#if defined(COBALT_CHECK_SUBMITDONE_TIMEOUT)
+// Timeout for last submitDone().
+const int kLastSubmitDoneTimeoutSeconds = 15;
+
+// Polling interval for timeout_polling_thread_.
+const int kRenderTimeOutPollingDelaySeconds = 1;
+
+// Minimum number of continuous times the timeout expirations. This is used to
+// prevent unintended behavior in situations such as when returning from
+// suspended state. Note that the timeout response trigger will be delayed
+// after the actual timeout expiration by this value times the polling delay.
+const int kMinimumContinuousRenderTimeoutExpirations = 2;
+
+// Name for timeout_polling_thread_.
+const char* kTimeoutPollingThreadName = "TimeoutPolling";
+
+// This specifies the percentage of calls to OnRenderTimeout() that result in a
+// call to OnError().
+const int kRenderTimeoutErrorPercentage = 99;
+
+#endif
+
 // This constant defines the maximum rate at which the layout engine will
 // refresh over time.  Since there is little benefit in performing a layout
 // faster than the display's refresh rate, we set this to 60Hz.
@@ -165,7 +226,25 @@
           h5vcc_url_handler_(this, system_window, account_manager)),
       web_module_options_(options.web_module_options),
       has_resumed_(true, false),
+#if defined(COBALT_CHECK_SUBMITDONE_TIMEOUT)
+      timeout_polling_thread_(kTimeoutPollingThreadName),
+      render_timeout_count_(0),
+#endif
       will_quit_(false) {
+#if defined(HANDLE_CORE_DUMP)
+  on_error_triggered_count_ = 0;
+  recovery_mechanism_triggered_count_ = 0;
+  submit_done_timeout_count_ = 0;
+  SbCoreDumpRegisterHandler(BrowserModule::CoreDumpHandler, this);
+#endif
+#if defined(COBALT_CHECK_SUBMITDONE_TIMEOUT)
+  timeout_polling_thread_.Start();
+  timeout_polling_thread_.message_loop()->PostDelayedTask(
+      FROM_HERE, base::Bind(&BrowserModule::OnPollForRenderTimeout,
+                            base::Unretained(this), url),
+      base::TimeDelta::FromSeconds(kRenderTimeOutPollingDelaySeconds));
+#endif
+
   // Setup our main web module to have the H5VCC API injected into it.
   DCHECK(!ContainsKey(web_module_options_.injected_window_attributes, "h5vcc"));
   h5vcc::H5vcc::Settings h5vcc_settings;
@@ -211,6 +290,9 @@
 
 BrowserModule::~BrowserModule() {
   DCHECK_EQ(MessageLoop::current(), self_message_loop_);
+#if defined(HANDLE_CORE_DUMP)
+  SbCoreDumpUnregisterHandler(BrowserModule::CoreDumpHandler, this);
+#endif
 }
 
 void BrowserModule::Navigate(const GURL& url) {
@@ -227,6 +309,20 @@
       base::SourceLocation("[object BrowserModule]", 1, 1));
 }
 
+#if defined(HANDLE_CORE_DUMP)
+// static
+void BrowserModule::CoreDumpHandler(void* browser_module_as_void) {
+  BrowserModule* browser_module =
+      static_cast<BrowserModule*>(browser_module_as_void);
+  SbCoreDumpLogInteger("BrowserModule.on_error_triggered_count_",
+                       browser_module->on_error_triggered_count_);
+  SbCoreDumpLogInteger("BrowserModule.recovery_mechanism_triggered_count_",
+                       browser_module->recovery_mechanism_triggered_count_);
+  SbCoreDumpLogInteger("BrowserModule.submit_done_timeout_count_",
+                       browser_module->submit_done_timeout_count_);
+}
+#endif
+
 void BrowserModule::NavigateInternal(const GURL& url) {
   DCHECK_EQ(MessageLoop::current(), self_message_loop_);
 
@@ -454,6 +550,9 @@
 }
 
 void BrowserModule::OnError(const GURL& url, const std::string& error) {
+#if defined(HANDLE_CORE_DUMP)
+  on_error_triggered_count_++;
+#endif
   LOG(ERROR) << error;
   std::string url_string = "h5vcc://network-failure";
 
@@ -610,5 +709,52 @@
 }
 #endif  // OS_STARBOARD
 
+#if defined(COBALT_CHECK_SUBMITDONE_TIMEOUT)
+void BrowserModule::OnPollForRenderTimeout(const GURL& url) {
+  SbTime last_submitdone_timestamp = static_cast<SbTime>(SbAtomicAcquire_Load64(
+      non_trivial_global_variables.Get().last_submit_done_timestamp));
+  base::Time last_submitdone =
+      base::Time::FromSbTime(last_submitdone_timestamp);
+  bool timeout_expiration =
+      base::Time::Now() -
+          base::TimeDelta::FromSeconds(kLastSubmitDoneTimeoutSeconds) >
+      last_submitdone;
+  bool timeout_response_trigger = false;
+  if (timeout_expiration) {
+    // The timeout only triggers if the timeout expiration has been detected
+    // without interruption at least kMinimumContinuousRenderTimeoutExpirations
+    // times.
+    ++render_timeout_count_;
+    timeout_response_trigger =
+        render_timeout_count_ >= kMinimumContinuousRenderTimeoutExpirations;
+  } else {
+    render_timeout_count_ = 0;
+  }
+
+  if (timeout_response_trigger) {
+#if defined(HANDLE_CORE_DUMP)
+    submit_done_timeout_count_++;
+#endif
+    SbAtomicNoBarrier_Exchange64(
+        non_trivial_global_variables.Get().last_submit_done_timestamp,
+        static_cast<SbAtomic64>(kSbTimeMax));
+    if (SbSystemGetRandomUInt64() <
+        kRenderTimeoutErrorPercentage * (UINT64_MAX / 100)) {
+      OnError(url, std::string("Rendering Timeout"));
+#if defined(HANDLE_CORE_DUMP)
+      recovery_mechanism_triggered_count_++;
+#endif
+    } else {
+      SB_DLOG(INFO) << "Received OnRenderTimeout, ignoring by random chance.";
+    }
+  } else {
+    timeout_polling_thread_.message_loop()->PostDelayedTask(
+        FROM_HERE, base::Bind(&BrowserModule::OnPollForRenderTimeout,
+                              base::Unretained(this), url),
+        base::TimeDelta::FromSeconds(kRenderTimeOutPollingDelaySeconds));
+  }
+}
+#endif
+
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h
index d00a3fb..5d39973 100644
--- a/src/cobalt/browser/browser_module.h
+++ b/src/cobalt/browser/browser_module.h
@@ -23,6 +23,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
 #include "cobalt/account/account_manager.h"
 #include "cobalt/base/message_queue.h"
 #include "cobalt/browser/h5vcc_url_handler.h"
@@ -48,6 +49,10 @@
 #include "cobalt/debug/debug_server.h"
 #endif  // ENABLE_DEBUG_CONSOLE
 
+#if defined(OS_STARBOARD)
+#include "starboard/configuration.h"
+#endif
+
 namespace cobalt {
 namespace browser {
 
@@ -114,6 +119,15 @@
   void SetProxy(const std::string& proxy_rules);
 
  private:
+#if defined(OS_STARBOARD)
+#if SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
+  static void CoreDumpHandler(void* browser_module_as_void);
+  int on_error_triggered_count_;
+  int recovery_mechanism_triggered_count_;
+  int submit_done_timeout_count_;
+#endif
+#endif
+
   // Recreates web module with the given URL.
   void NavigateInternal(const GURL& url);
 
@@ -200,6 +214,11 @@
   // Process all messages queued into the |render_tree_submission_queue_|.
   void ProcessRenderTreeSubmissionQueue();
 
+#if defined(COBALT_CHECK_SUBMITDONE_TIMEOUT)
+  // Poll for render timeout. Called from timeout_polling_thread_.
+  void OnPollForRenderTimeout(const GURL& url);
+#endif
+
   // TODO:
   //     WeakPtr usage here can be avoided if BrowserModule has a thread to
   //     own where it can ensure that its tasks are all resolved when it is
@@ -316,6 +335,14 @@
   // Reset when the browser is paused, signalled to resume.
   base::WaitableEvent has_resumed_;
 
+#if defined(COBALT_CHECK_SUBMITDONE_TIMEOUT)
+  base::Thread timeout_polling_thread_;
+
+  // Counts the number of continuous render timeout expirations. This value is
+  // updated and used from OnPollForRenderTimeout.
+  int render_timeout_count_;
+#endif
+
   // Set when the application is about to quit. May be set from a thread other
   // than the one hosting this object, and read from another.
   bool will_quit_;
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index fa37d0f..f9b0452 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-11764
\ No newline at end of file
+12305
\ No newline at end of file
diff --git a/src/cobalt/dom/node.cc b/src/cobalt/dom/node.cc
index 59aed34..6ce2955 100644
--- a/src/cobalt/dom/node.cc
+++ b/src/cobalt/dom/node.cc
@@ -37,6 +37,13 @@
 #include "cobalt/dom/node_list_live.h"
 #include "cobalt/dom/rule_matching.h"
 #include "cobalt/dom/text.h"
+#if defined(OS_STARBOARD)
+#include "starboard/configuration.h"
+#if SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
+#define HANDLE_CORE_DUMP
+#include "starboard/ps4/core_dump_handler.h"
+#endif  // SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
+#endif  // defined(OS_STARBOARD)
 
 namespace cobalt {
 namespace dom {
@@ -49,8 +56,25 @@
   NodeCountLog() : count(0) {
     base::UserLog::Register(base::UserLog::kNodeCountIndex, "NodeCnt", &count,
                             sizeof(count));
+#if defined(HANDLE_CORE_DUMP)
+    SbCoreDumpRegisterHandler(CoreDumpHandler, this);
+#endif
   }
-  ~NodeCountLog() { base::UserLog::Deregister(base::UserLog::kNodeCountIndex); }
+
+  ~NodeCountLog() {
+#if defined(HANDLE_CORE_DUMP)
+    SbCoreDumpUnregisterHandler(CoreDumpHandler, this);
+#endif
+    base::UserLog::Deregister(base::UserLog::kNodeCountIndex);
+  }
+
+#if defined(HANDLE_CORE_DUMP)
+  static void CoreDumpHandler(void* context) {
+    SbCoreDumpLogInteger(
+        "Total number of nodes",
+        static_cast<NodeCountLog*>(context)->count);
+  }
+#endif
 
   int count;
 
diff --git a/src/cobalt/dom_parser/libxml_html_parser_wrapper.cc b/src/cobalt/dom_parser/libxml_html_parser_wrapper.cc
index 75e760b..968dbe5 100644
--- a/src/cobalt/dom_parser/libxml_html_parser_wrapper.cc
+++ b/src/cobalt/dom_parser/libxml_html_parser_wrapper.cc
@@ -110,7 +110,7 @@
     return;
   }
 
-  if (CheckInputAndUpdateSeverity(data, size) >= kError) {
+  if (CheckInputAndUpdateSeverity(data, size) == kFatal) {
     return;
   }
 
diff --git a/src/cobalt/dom_parser/libxml_parser_wrapper.cc b/src/cobalt/dom_parser/libxml_parser_wrapper.cc
index ec05383..3550e78 100644
--- a/src/cobalt/dom_parser/libxml_parser_wrapper.cc
+++ b/src/cobalt/dom_parser/libxml_parser_wrapper.cc
@@ -23,11 +23,81 @@
 #include "cobalt/dom/comment.h"
 #include "cobalt/dom/element.h"
 #include "cobalt/dom/text.h"
+#if defined(OS_STARBOARD)
+#include "starboard/configuration.h"
+#if SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
+#define HANDLE_CORE_DUMP
+#include "base/lazy_instance.h"
+#include "starboard/ps4/core_dump_handler.h"
+#endif  // SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
+#endif  // defined(OS_STARBOARD)
 
 namespace cobalt {
 namespace dom_parser {
 namespace {
 
+#if defined(HANDLE_CORE_DUMP)
+
+class LibxmlParserWrapperLog {
+ public:
+  LibxmlParserWrapperLog()
+      : total_parsed_bytes_(0),
+        total_warning_count_(0),
+        total_error_count_(0),
+        total_fatal_count_(0) {
+    SbCoreDumpRegisterHandler(CoreDumpHandler, this);
+  }
+  ~LibxmlParserWrapperLog() {
+    SbCoreDumpUnregisterHandler(CoreDumpHandler, this);
+  }
+
+  static void CoreDumpHandler(void* context) {
+    SbCoreDumpLogInteger(
+        "LibxmlParserWrapper total parsed bytes",
+        static_cast<LibxmlParserWrapperLog*>(context)->total_parsed_bytes_);
+    SbCoreDumpLogInteger(
+        "LibxmlParserWrapper total warning count",
+        static_cast<LibxmlParserWrapperLog*>(context)->total_warning_count_);
+    SbCoreDumpLogInteger(
+        "LibxmlParserWrapper total error count",
+        static_cast<LibxmlParserWrapperLog*>(context)->total_error_count_);
+    SbCoreDumpLogInteger(
+        "LibxmlParserWrapper total fatal error count",
+        static_cast<LibxmlParserWrapperLog*>(context)->total_fatal_count_);
+    SbCoreDumpLogString("LibxmlParserWrapper last fatal error",
+                        static_cast<LibxmlParserWrapperLog*>(context)
+                            ->last_fatal_message_.c_str());
+  }
+
+  void IncrementParsedBytes(int length) { total_parsed_bytes_ += length; }
+  void LogParsingIssue(LibxmlParserWrapper::IssueSeverity severity,
+                       const std::string& message) {
+    if (severity == LibxmlParserWrapper::kWarning) {
+      total_warning_count_++;
+    } else if (severity == LibxmlParserWrapper::kError) {
+      total_error_count_++;
+    } else if (severity == LibxmlParserWrapper::kFatal) {
+      total_fatal_count_++;
+      last_fatal_message_ = message;
+    } else {
+      NOTREACHED();
+    }
+  }
+
+ private:
+  int total_parsed_bytes_;
+  int total_warning_count_;
+  int total_error_count_;
+  int total_fatal_count_;
+  std::string last_fatal_message_;
+  DISALLOW_COPY_AND_ASSIGN(LibxmlParserWrapperLog);
+};
+
+base::LazyInstance<LibxmlParserWrapperLog> libxml_parser_wrapper_log =
+    LAZY_INSTANCE_INITIALIZER;
+
+#endif  // defined(HANDLE_CORE_DUMP)
+
 /////////////////////////////////////////////////////////////////////////////
 // Helpers
 /////////////////////////////////////////////////////////////////////////////
@@ -214,16 +284,25 @@
 
 void LibxmlParserWrapper::OnParsingIssue(IssueSeverity severity,
                                          const std::string& message) {
+  DCHECK(severity >= kWarning && severity <= kFatal);
   if (severity > max_severity_) {
     max_severity_ = severity;
   }
   if (severity < LibxmlParserWrapper::kFatal) {
-    LOG(WARNING) << message;
-  } else {
+    LOG(WARNING) << "Libxml "
+                 << (severity == kWarning ? "Warning: " : "Error: ") << message;
+  } else if (severity == LibxmlParserWrapper::kFatal) {
+    LOG(ERROR) << "Libxml Fatal Error: " << message;
     if (!error_callback_.is_null()) {
       error_callback_.Run(message);
     }
+  } else {
+    NOTREACHED();
   }
+
+#if defined(HANDLE_CORE_DUMP)
+  libxml_parser_wrapper_log.Get().LogParsingIssue(severity, message);
+#endif
 }
 
 void LibxmlParserWrapper::OnCDATABlock(const std::string& value) {
@@ -233,26 +312,30 @@
 LibxmlParserWrapper::IssueSeverity
 LibxmlParserWrapper::CheckInputAndUpdateSeverity(const char* data,
                                                  size_t size) {
-  if (max_severity_ >= kError) {
+  if (max_severity_ == kFatal) {
     return max_severity_;
   }
 
   // Check the total input size.
   total_input_size_ += size;
   if (total_input_size_ > kMaxTotalInputSize) {
-    static const char kErrorTooLong[] = "Parser input is too long.";
-    OnParsingIssue(kError, kErrorTooLong);
+    static const char kMessageInputTooLong[] = "Parser input is too long.";
+    OnParsingIssue(kFatal, kMessageInputTooLong);
     return max_severity_;
   }
 
   // Check the encoding of the input.
   if (!IsStringUTF8(std::string(data, size))) {
-    static const char kErrorNotUTF8[] =
+    static const char kMessageInputNotUTF8[] =
         "Parser input contains non-UTF8 characters.";
-    OnParsingIssue(kError, kErrorNotUTF8);
+    OnParsingIssue(kFatal, kMessageInputNotUTF8);
     return max_severity_;
   }
 
+#if defined(HANDLE_CORE_DUMP)
+  libxml_parser_wrapper_log.Get().IncrementParsedBytes(static_cast<int>(size));
+#endif
+
   return max_severity_;
 }
 
diff --git a/src/cobalt/dom_parser/libxml_parser_wrapper.h b/src/cobalt/dom_parser/libxml_parser_wrapper.h
index c391fab..98d210e 100644
--- a/src/cobalt/dom_parser/libxml_parser_wrapper.h
+++ b/src/cobalt/dom_parser/libxml_parser_wrapper.h
@@ -61,9 +61,9 @@
  public:
   enum IssueSeverity {
     kNoIssue,
-    kWarning,
-    kError,
-    kFatal,
+    kWarning,  // A simple warning
+    kError,    // A recoverable error
+    kFatal,    // A fatal error
     kIssueSeverityCount,
   };
 
@@ -137,8 +137,9 @@
   }
 
  private:
-  // Maximum total input size, 1MB.
-  static const size_t kMaxTotalInputSize = 1 << 16;
+  // Maximum total input size, as specified in Libxml's value
+  // XML_MAX_TEXT_LENGTH in parserInternals.h.
+  static const size_t kMaxTotalInputSize = 10000000;
 
   const scoped_refptr<dom::Document> document_;
   const scoped_refptr<dom::Node> parent_node_;
diff --git a/src/cobalt/dom_parser/libxml_xml_parser_wrapper.cc b/src/cobalt/dom_parser/libxml_xml_parser_wrapper.cc
index c933f5e..787970d 100644
--- a/src/cobalt/dom_parser/libxml_xml_parser_wrapper.cc
+++ b/src/cobalt/dom_parser/libxml_xml_parser_wrapper.cc
@@ -79,7 +79,7 @@
     return;
   }
 
-  if (CheckInputAndUpdateSeverity(data, size) >= kError) {
+  if (CheckInputAndUpdateSeverity(data, size) == kFatal) {
     return;
   }
 
diff --git a/src/cobalt/h5vcc/h5vcc_runtime.cc b/src/cobalt/h5vcc/h5vcc_runtime.cc
index 8b0f871..e7e3748 100644
--- a/src/cobalt/h5vcc/h5vcc_runtime.cc
+++ b/src/cobalt/h5vcc/h5vcc_runtime.cc
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
+#include "cobalt/h5vcc/h5vcc_runtime.h"
+
 #include "cobalt/base/deep_link_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
-#include "cobalt/h5vcc/h5vcc_runtime.h"
 #include "cobalt/system_window/application_event.h"
 
 namespace cobalt {
@@ -79,8 +80,10 @@
 void H5vccRuntime::OnDeepLinkEvent(const base::Event* event) {
   const base::DeepLinkEvent* deep_link_event =
       base::polymorphic_downcast<const base::DeepLinkEvent*>(event);
-  DLOG(INFO) << "Got deep link event: " << deep_link_event->link();
-  on_deep_link()->DispatchEvent(deep_link_event->link());
+  if (!deep_link_event->IsH5vccLink()) {
+    DLOG(INFO) << "Got deep link event: " << deep_link_event->link();
+    on_deep_link()->DispatchEvent(deep_link_event->link());
+  }
 }
 }  // namespace h5vcc
 }  // namespace cobalt
diff --git a/src/cobalt/loader/net_fetcher.cc b/src/cobalt/loader/net_fetcher.cc
index 4ba9d17..0f60e72 100644
--- a/src/cobalt/loader/net_fetcher.cc
+++ b/src/cobalt/loader/net_fetcher.cc
@@ -21,12 +21,46 @@
 #include "base/stringprintf.h"
 #include "cobalt/network/network_module.h"
 #include "net/url_request/url_fetcher.h"
+#if defined(OS_STARBOARD)
+#include "starboard/configuration.h"
+#if SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
+#define HANDLE_CORE_DUMP
+#include "base/lazy_instance.h"
+#include "starboard/ps4/core_dump_handler.h"
+#endif  // SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
+#endif  // OS_STARBOARD
 
 namespace cobalt {
 namespace loader {
 
 namespace {
 
+#if defined(HANDLE_CORE_DUMP)
+
+class NetFetcherLog {
+ public:
+  NetFetcherLog() : total_fetched_bytes_(0) {
+    SbCoreDumpRegisterHandler(CoreDumpHandler, this);
+  }
+  ~NetFetcherLog() { SbCoreDumpUnregisterHandler(CoreDumpHandler, this); }
+
+  static void CoreDumpHandler(void* context) {
+    SbCoreDumpLogInteger(
+        "NetFetcher total fetched bytes",
+        static_cast<NetFetcherLog*>(context)->total_fetched_bytes_);
+  }
+
+  void IncrementFetchedBytes(int length) { total_fetched_bytes_ += length; }
+
+ private:
+  int total_fetched_bytes_;
+  DISALLOW_COPY_AND_ASSIGN(NetFetcherLog);
+};
+
+base::LazyInstance<NetFetcherLog> net_fetcher_log = LAZY_INSTANCE_INITIALIZER;
+
+#endif  // defined(HANDLE_CORE_DUMP)
+
 bool IsResponseCodeSuccess(int response_code) {
   // NetFetcher only considers success to be if the network request
   // was successful *and* we get a 2xx response back.
@@ -118,6 +152,10 @@
 void NetFetcher::OnURLFetchDownloadData(const net::URLFetcher* source,
                                         scoped_ptr<std::string> download_data) {
   if (IsResponseCodeSuccess(source->GetResponseCode())) {
+#if defined(HANDLE_CORE_DUMP)
+    net_fetcher_log.Get().IncrementFetchedBytes(
+        static_cast<int>(download_data->length()));
+#endif
     handler()->OnReceived(this, download_data->data(), download_data->length());
   }
 }
diff --git a/src/cobalt/script/script_runner.cc b/src/cobalt/script/script_runner.cc
index d680966..3900885 100644
--- a/src/cobalt/script/script_runner.cc
+++ b/src/cobalt/script/script_runner.cc
@@ -19,12 +19,51 @@
 #include "base/logging.h"
 #include "cobalt/script/global_environment.h"
 #include "cobalt/script/source_code.h"
+#if defined(OS_STARBOARD)
+#include "starboard/configuration.h"
+#if SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
+#define HANDLE_CORE_DUMP
+#include "base/lazy_instance.h"
+#include "starboard/ps4/core_dump_handler.h"
+#endif  // SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
+#endif  // defined(OS_STARBOARD)
 
 namespace cobalt {
 namespace script {
 
 namespace {
 
+#if defined(HANDLE_CORE_DUMP)
+
+class ScriptRunnerLog {
+ public:
+  ScriptRunnerLog() : success_count_(0), fail_count_(0) {
+    SbCoreDumpRegisterHandler(CoreDumpHandler, this);
+  }
+  ~ScriptRunnerLog() { SbCoreDumpUnregisterHandler(CoreDumpHandler, this); }
+
+  static void CoreDumpHandler(void* context) {
+    SbCoreDumpLogInteger(
+        "ScriptRunner successful executions",
+        static_cast<ScriptRunnerLog*>(context)->success_count_);
+    SbCoreDumpLogInteger("ScriptRunner failed executions",
+                         static_cast<ScriptRunnerLog*>(context)->fail_count_);
+  }
+
+  void IncrementSuccessCount() { success_count_++; }
+  void IncrementFailCount() { fail_count_++; }
+
+ private:
+  int success_count_;
+  int fail_count_;
+  DISALLOW_COPY_AND_ASSIGN(ScriptRunnerLog);
+};
+
+base::LazyInstance<ScriptRunnerLog> script_runner_log =
+    LAZY_INSTANCE_INITIALIZER;
+
+#endif  // defined(HANDLE_CORE_DUMP)
+
 class ScriptRunnerImpl : public ScriptRunner {
  public:
   explicit ScriptRunnerImpl(
@@ -53,8 +92,14 @@
   std::string result;
   if (!global_environment_->EvaluateScript(source_code, &result)) {
     DLOG(WARNING) << "Failed to execute JavaScript: " << result;
+#if defined(HANDLE_CORE_DUMP)
+    script_runner_log.Get().IncrementFailCount();
+#endif
     return "";
   }
+#if defined(HANDLE_CORE_DUMP)
+  script_runner_log.Get().IncrementSuccessCount();
+#endif
   return result;
 }