Import Cobalt 11.119147

Change-Id: Ia6c06976892b73fefb1776fad782fcbaa5c9e3ab
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc
index 2ef445e..35b7f2a 100644
--- a/src/cobalt/browser/application.cc
+++ b/src/cobalt/browser/application.cc
@@ -369,6 +369,8 @@
     "https://s.ytimg.com/yts/cobalt/ "
     "https://www.youtube.com/tv "
     "https://www.youtube.com/tv/ "
+    "https://web-green-qa.youtube.com/tv "
+    "https://web-green-qa.youtube.com/tv/ "
     "https://web-release-qa.youtube.com/tv "
     "https://web-release-qa.youtube.com/tv/ "
 #if defined(ENABLE_ABOUT_SCHEME)
@@ -494,6 +496,12 @@
     options.web_module_options.javascript_options.disable_jit = true;
   }
 
+  if (command_line->HasSwitch(
+          browser::switches::kRetainRemoteTypefaceCacheDuringSuspend)) {
+    options.web_module_options.should_retain_remote_typeface_cache_on_suspend =
+        true;
+  }
+
 #if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
   if (command_line->HasSwitch(browser::switches::kNullSavegame)) {
     options.storage_manager_options.savegame_options.factory =
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc
index bad9f37..c7b9f34 100644
--- a/src/cobalt/browser/switches.cc
+++ b/src/cobalt/browser/switches.cc
@@ -155,6 +155,11 @@
 const char kRemoteTypefaceCacheSizeInBytes[] =
     "remote_typeface_cache_size_in_bytes";
 
+// Causes the remote typeface cache to be retained when Cobalt is suspended, so
+// that they don't need to be re-downloaded when Cobalt is resumed.
+const char kRetainRemoteTypefaceCacheDuringSuspend[] =
+    "retain_remote_typeface_cache_during_suspend";
+
 // Determines the capacity of the scratch surface cache.  The scratch surface
 // cache facilitates the reuse of temporary offscreen surfaces within a single
 // frame.  This setting is only relevant when using the hardware-accelerated
diff --git a/src/cobalt/browser/switches.h b/src/cobalt/browser/switches.h
index de720e3..599da2a 100644
--- a/src/cobalt/browser/switches.h
+++ b/src/cobalt/browser/switches.h
@@ -58,6 +58,7 @@
 extern const char kLocalStoragePartitionUrl[];
 extern const char kOffscreenTargetCacheSizeInBytes[];
 extern const char kRemoteTypefaceCacheSizeInBytes[];
+extern const char kRetainRemoteTypefaceCacheDuringSuspend[];
 extern const char kScratchSurfaceCacheSizeInBytes[];
 extern const char kSkiaCacheSizeInBytes[];
 extern const char kSoftwareSurfaceCacheSizeInBytes[];
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc
index 0696278..54bf81a 100644
--- a/src/cobalt/browser/web_module.cc
+++ b/src/cobalt/browser/web_module.cc
@@ -28,6 +28,7 @@
 #include "base/stringprintf.h"
 #include "cobalt/base/startup_timer.h"
 #include "cobalt/base/tokens.h"
+#include "cobalt/base/type_id.h"
 #include "cobalt/browser/splash_screen_cache.h"
 #include "cobalt/browser/stack_size_constants.h"
 #include "cobalt/browser/switches.h"
@@ -218,7 +219,7 @@
   class DocumentLoadedObserver;
 
   // Purge all resource caches owned by the WebModule.
-  void PurgeResourceCaches();
+  void PurgeResourceCaches(bool should_retain_remote_typeface_cache);
 
   // Disable callbacks in all resource caches owned by the WebModule.
   void DisableCallbacksInResourceCaches();
@@ -272,6 +273,9 @@
 
   // Object that provides renderer resources like images and fonts.
   render_tree::ResourceProvider* resource_provider_;
+  // The type id of resource provider being used by the WebModule. Whenever this
+  // changes, the caches may have obsolete data and must be blown away.
+  base::TypeId resource_provider_type_id_;
 
   // CSS parser.
   scoped_ptr<css_parser::Parser> css_parser_;
@@ -378,6 +382,8 @@
   scoped_ptr<layout::TopmostEventTarget> topmost_event_target_;
 
   base::Closure on_before_unload_fired_but_not_handled;
+
+  bool should_retain_remote_typeface_cache_on_suspend_;
 };
 
 class WebModule::Impl::DocumentLoadedObserver : public dom::DocumentObserver {
@@ -402,7 +408,8 @@
 WebModule::Impl::Impl(const ConstructionData& data)
     : name_(data.options.name),
       is_running_(false),
-      resource_provider_(data.resource_provider) {
+      resource_provider_(data.resource_provider),
+      resource_provider_type_id_(data.resource_provider->GetTypeId()) {
   // Currently we rely on a platform to explicitly specify that it supports
   // the map-to-mesh filter via the ENABLE_MAP_TO_MESH define (and the
   // 'enable_map_to_mesh' gyp variable).  When we have better support for
@@ -445,6 +452,9 @@
   on_before_unload_fired_but_not_handled =
       data.options.on_before_unload_fired_but_not_handled;
 
+  should_retain_remote_typeface_cache_on_suspend_ =
+      data.options.should_retain_remote_typeface_cache_on_suspend;
+
   fetcher_factory_.reset(new loader::FetcherFactory(
       data.network_module, data.options.extra_web_file_dir,
       dom::URL::MakeBlobResolverCallback(blob_registry_.get()),
@@ -874,6 +884,14 @@
     render_tree::ResourceProvider* resource_provider) {
   resource_provider_ = resource_provider;
   if (resource_provider_) {
+    base::TypeId resource_provider_type_id = resource_provider_->GetTypeId();
+    // Check for if the resource provider type id has changed. If it has, then
+    // anything contained within the caches is invalid and must be purged.
+    if (resource_provider_type_id_ != resource_provider_type_id) {
+      PurgeResourceCaches(false);
+    }
+    resource_provider_type_id_ = resource_provider_type_id;
+
     loader_factory_->Resume(resource_provider_);
 
     // Permit render trees to be generated again.  Layout will have been
@@ -908,7 +926,7 @@
 
   // Purge the resource caches before running any suspend logic. This will force
   // any pending callbacks that the caches are batching to run.
-  PurgeResourceCaches();
+  PurgeResourceCaches(should_retain_remote_typeface_cache_on_suspend_);
 
   // Stop the generation of render trees.
   layout_manager_->Suspend();
@@ -937,7 +955,7 @@
   // Clear out all resource caches. We need to do this after we abort all
   // in-progress loads, and after we clear all document references, or they will
   // still be referenced and won't be cleared from the cache.
-  PurgeResourceCaches();
+  PurgeResourceCaches(should_retain_remote_typeface_cache_on_suspend_);
 
 #if defined(ENABLE_DEBUG_CONSOLE)
   // The debug overlay may be holding onto a render tree, clear that out.
@@ -965,7 +983,8 @@
     return;
   }
 
-  PurgeResourceCaches();
+  // Retain the remote typeface cache when reducing memory.
+  PurgeResourceCaches(true /*should_retain_remote_typeface_cache*/);
   window_->document()->PurgeCachedResources();
 
   // Force garbage collection in |javascript_engine_|.
@@ -1002,9 +1021,14 @@
   }
 }
 
-void WebModule::Impl::PurgeResourceCaches() {
+void WebModule::Impl::PurgeResourceCaches(
+    bool should_retain_remote_typeface_cache) {
   image_cache_->Purge();
-  remote_typeface_cache_->Purge();
+  if (should_retain_remote_typeface_cache) {
+    remote_typeface_cache_->ProcessPendingCallbacks();
+  } else {
+    remote_typeface_cache_->Purge();
+  }
   mesh_cache_->Purge();
 }
 
@@ -1036,6 +1060,7 @@
       animated_image_decode_thread_priority(base::kThreadPriority_Low),
       video_playback_rate_multiplier(1.f),
       enable_image_animations(true),
+      should_retain_remote_typeface_cache_on_suspend(false),
       can_fetch_cache(false) {}
 
 WebModule::WebModule(
diff --git a/src/cobalt/browser/web_module.h b/src/cobalt/browser/web_module.h
index e16a184..da3a9c1 100644
--- a/src/cobalt/browser/web_module.h
+++ b/src/cobalt/browser/web_module.h
@@ -183,6 +183,10 @@
     // is true to enable them.
     bool enable_image_animations;
 
+    // Whether or not to retain the remote typeface cache when the app enters
+    // the suspend state.
+    bool should_retain_remote_typeface_cache_on_suspend;
+
     // The splash screen cache object, owned by the BrowserModule.
     SplashScreenCache* splash_screen_cache;
 
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 08e5e25..9ce0c99 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-109809
\ No newline at end of file
+119147
\ No newline at end of file
diff --git a/src/cobalt/build/build_config.h b/src/cobalt/build/build_config.h
index 527f9bc..bfe3df5 100644
--- a/src/cobalt/build/build_config.h
+++ b/src/cobalt/build/build_config.h
@@ -50,11 +50,4 @@
 #endif  // COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K <
         //     COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P
 
-#if COBALT_ENCRYPTED_MEDIA_EXTENSION_ENABLE_KEY_STATUSES_UPDATE
-#if SB_API_VERSION < 6
-#error COBALT_ENCRYPTED_MEDIA_EXTENSION_ENABLE_KEY_STATUSES_UPDATE requires \
-           that SB_API_VERSION is greater than or equal to 6
-#endif  // SB_API_VERSION < 6
-#endif  // COBALT_ENCRYPTED_MEDIA_EXTENSION_ENABLE_KEY_STATUSES_UPDATE
-
 #endif  // COBALT_BUILD_BUILD_CONFIG_H_
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi
index 91a56e2..ec59efe 100644
--- a/src/cobalt/build/config/base.gypi
+++ b/src/cobalt/build/config/base.gypi
@@ -559,12 +559,6 @@
     # re-download video data.  Note that the JavaScript app may experience
     # significant difficulty if this value is too low.
     'cobalt_media_buffer_video_budget_4k%': 60 * 1024 * 1024,
-
-    # Set to 1 to enable MediaKeySession::keyStatuses and
-    # MediaKeySession::onkeystatuseschange support.  This requires that
-    # SB_API_VERSION is greater than or equal to
-    # SB_DRM_KEY_STATUSES_UPDATE_SUPPORT_API_VERSION.
-    'cobalt_encrypted_media_extension_enable_key_statuses_update%': 1,
   },
 
   'target_defaults': {
@@ -633,11 +627,6 @@
           'COBALT_MEDIA_BUFFER_STORAGE_TYPE_FILE=1',
         ],
       }],
-      ['cobalt_encrypted_media_extension_enable_key_statuses_update == 1', {
-        'defines': [
-          'COBALT_ENCRYPTED_MEDIA_EXTENSION_ENABLE_KEY_STATUSES_UPDATE=1',
-        ],
-      }],
       ['final_executable_type=="shared_library"', {
         'target_conditions': [
           ['_toolset=="target"', {
diff --git a/src/cobalt/dom/eme/media_key_session.cc b/src/cobalt/dom/eme/media_key_session.cc
index 11c2f98..46b9eb0 100644
--- a/src/cobalt/dom/eme/media_key_session.cc
+++ b/src/cobalt/dom/eme/media_key_session.cc
@@ -37,11 +37,11 @@
     : ALLOW_THIS_IN_INITIALIZER_LIST(event_queue_(this)),
       drm_system_(drm_system),
       drm_system_session_(drm_system->CreateSession(
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
           base::Bind(&MediaKeySession::OnSessionUpdateKeyStatuses,
                      base::AsWeakPtr(this))
-#endif  // SB_API_VERSION >= 6
-                     )),
+#endif  // SB_HAS(DRM_KEY_STATUSES)
+              )),  // NOLINT(whitespace/parens)
       script_value_factory_(script_value_factory),
       uninitialized_(true),
       callable_(false),
@@ -356,6 +356,8 @@
 
   // 5. Queue a task to fire a simple event named keystatuseschange at the
   //    session.
+  LOG(INFO) << "Fired 'keystatuseschange' event on MediaKeySession with "
+            << key_status_map_->size() << " keys.";
   event_queue_.Enqueue(new Event(base::Tokens::keystatuseschange()));
 
   // 6. Queue a task to run the Attempt to Resume Playback If Necessary
diff --git a/src/cobalt/dom/eme/media_key_session.idl b/src/cobalt/dom/eme/media_key_session.idl
index 3813c47..8e6ac14 100644
--- a/src/cobalt/dom/eme/media_key_session.idl
+++ b/src/cobalt/dom/eme/media_key_session.idl
@@ -19,7 +19,6 @@
   // TODO: Implement |expiration|.
   // readonly attribute unrestricted double expiration;
   readonly attribute Promise<void> closed;
-  [Conditional=COBALT_ENCRYPTED_MEDIA_EXTENSION_ENABLE_KEY_STATUSES_UPDATE]
   readonly attribute MediaKeyStatusMap keyStatuses;
   attribute EventHandler onkeystatuseschange;
   attribute EventHandler onmessage;
diff --git a/src/cobalt/dom/eme/media_key_status_map.cc b/src/cobalt/dom/eme/media_key_status_map.cc
index 33e0bcc..50063c1 100644
--- a/src/cobalt/dom/eme/media_key_status_map.cc
+++ b/src/cobalt/dom/eme/media_key_status_map.cc
@@ -24,6 +24,16 @@
 
 namespace {
 
+std::string ConvertKeyIdToAscii(const std::string& key_id) {
+  const char kHexChars[] = "0123456789ABCDEF";
+  std::string key_id_in_ascii;
+  for (auto ch : key_id) {
+    key_id_in_ascii += kHexChars[static_cast<unsigned char>(ch) / 16];
+    key_id_in_ascii += kHexChars[static_cast<unsigned char>(ch) % 16];
+  }
+  return key_id_in_ascii;
+}
+
 std::string ConvertKeyStatusToString(MediaKeyStatus key_status) {
   switch (key_status) {
     case kMediaKeyStatusUsable:
@@ -57,6 +67,13 @@
 
 }  // namespace
 
+void MediaKeyStatusMap::Add(const std::string& key_id,
+                            MediaKeyStatus key_status) {
+  LOG(INFO) << "MediaKeyStatusMap::Add()  " << ConvertKeyIdToAscii(key_id)
+            << " => " << ConvertKeyStatusToString(key_status);
+  key_statuses_[key_id] = key_status;
+}
+
 void MediaKeyStatusMap::ForEach(const ForEachCallbackArg& callback) {
   ForEachCallbackArg::Reference reference(this, callback);
 
diff --git a/src/cobalt/dom/eme/media_key_status_map.h b/src/cobalt/dom/eme/media_key_status_map.h
index a2808c6..812ad90 100644
--- a/src/cobalt/dom/eme/media_key_status_map.h
+++ b/src/cobalt/dom/eme/media_key_status_map.h
@@ -46,9 +46,7 @@
 
   void Clear() { key_statuses_.clear(); }
 
-  void Add(const std::string& key_id, MediaKeyStatus key_status) {
-    key_statuses_[key_id] = key_status;
-  }
+  void Add(const std::string& key_id, MediaKeyStatus key_status);
 
   // Web IDL: MediaKeyStatusMap.
   //
diff --git a/src/cobalt/dom/eme/media_key_status_map.idl b/src/cobalt/dom/eme/media_key_status_map.idl
index 60b1279..58a963f 100644
--- a/src/cobalt/dom/eme/media_key_status_map.idl
+++ b/src/cobalt/dom/eme/media_key_status_map.idl
@@ -14,7 +14,6 @@
 
 // https://www.w3.org/TR/encrypted-media/#mediakeystatusmap-interface
 
-[Conditional=COBALT_ENCRYPTED_MEDIA_EXTENSION_ENABLE_KEY_STATUSES_UPDATE]
 interface MediaKeyStatusMap {
   iterable<BufferSource, MediaKeyStatus>;
   readonly attribute unsigned long size;
diff --git a/src/cobalt/dom/event_queue.cc b/src/cobalt/dom/event_queue.cc
index 0090fb8..2295581 100644
--- a/src/cobalt/dom/event_queue.cc
+++ b/src/cobalt/dom/event_queue.cc
@@ -53,6 +53,10 @@
 void EventQueue::DispatchEvents() {
   DCHECK(message_loop_->BelongsToCurrentThread());
 
+  // Make sure that the event_target_ stays alive for the duration of
+  // all event dispatches.
+  scoped_refptr<EventTarget> keep_alive_reference(event_target_);
+
   Events events;
   events.swap(events_);
 
diff --git a/src/cobalt/dom/html_media_element.cc b/src/cobalt/dom/html_media_element.cc
index 006be93..2272cb8 100644
--- a/src/cobalt/dom/html_media_element.cc
+++ b/src/cobalt/dom/html_media_element.cc
@@ -1483,7 +1483,7 @@
 
 void HTMLMediaElement::MediaEngineError(scoped_refptr<MediaError> error) {
   MLOG() << error->code();
-  DLOG(WARNING) << "HTMLMediaElement::MediaEngineError " << error->code();
+  LOG(WARNING) << "HTMLMediaElement::MediaEngineError " << error->code();
 
   // 1 - The user agent should cancel the fetching process.
   StopPeriodicTimers();
diff --git a/src/cobalt/dom/html_video_element.cc b/src/cobalt/dom/html_video_element.cc
index 08bd8b5..8b63f37 100644
--- a/src/cobalt/dom/html_video_element.cc
+++ b/src/cobalt/dom/html_video_element.cc
@@ -16,6 +16,7 @@
 
 #include "base/logging.h"
 #include "base/string_number_conversions.h"
+#include "cobalt/math/size_f.h"
 
 namespace cobalt {
 namespace dom {
@@ -96,5 +97,9 @@
   return player() ? player()->GetSetBoundsCB() : WebMediaPlayer::SetBoundsCB();
 }
 
+math::SizeF HTMLVideoElement::GetVideoSize() const {
+  return math::SizeF(video_width(), video_height());
+}
+
 }  // namespace dom
 }  // namespace cobalt
diff --git a/src/cobalt/dom/html_video_element.h b/src/cobalt/dom/html_video_element.h
index 7d0e1df..45396d1 100644
--- a/src/cobalt/dom/html_video_element.h
+++ b/src/cobalt/dom/html_video_element.h
@@ -20,6 +20,7 @@
 #include "cobalt/dom/html_media_element.h"
 #include "cobalt/dom/video_playback_quality.h"
 #include "cobalt/math/rect.h"
+#include "cobalt/math/size_f.h"
 #if !defined(COBALT_MEDIA_SOURCE_2016)
 #include "media/base/shell_video_frame_provider.h"
 #endif  // !defined(COBALT_MEDIA_SOURCE_2016)
@@ -63,6 +64,8 @@
 
   WebMediaPlayer::SetBoundsCB GetSetBoundsCB();
 
+  math::SizeF GetVideoSize() const;
+
   DEFINE_WRAPPABLE_TYPE(HTMLVideoElement);
 
  private:
diff --git a/src/cobalt/layout/block_level_replaced_box.cc b/src/cobalt/layout/block_level_replaced_box.cc
index dd5f374..71c75d7 100644
--- a/src/cobalt/layout/block_level_replaced_box.cc
+++ b/src/cobalt/layout/block_level_replaced_box.cc
@@ -15,6 +15,7 @@
 #include "cobalt/layout/block_level_replaced_box.h"
 
 #include "cobalt/layout/used_style.h"
+#include "cobalt/math/size_f.h"
 
 namespace cobalt {
 namespace layout {
@@ -28,13 +29,13 @@
     const base::optional<LayoutUnit>& maybe_intrinsic_height,
     const base::optional<float>& maybe_intrinsic_ratio,
     UsedStyleProvider* used_style_provider,
-    base::optional<bool> is_video_punched_out,
+    base::optional<bool> is_video_punched_out, const math::SizeF& content_size,
     LayoutStatTracker* layout_stat_tracker)
     : ReplacedBox(css_computed_style_declaration, replace_image_cb,
                   set_bounds_cb, paragraph, text_position,
                   maybe_intrinsic_width, maybe_intrinsic_height,
                   maybe_intrinsic_ratio, used_style_provider,
-                  is_video_punched_out, layout_stat_tracker) {}
+                  is_video_punched_out, content_size, layout_stat_tracker) {}
 
 Box::Level BlockLevelReplacedBox::GetLevel() const { return kBlockLevel; }
 
diff --git a/src/cobalt/layout/block_level_replaced_box.h b/src/cobalt/layout/block_level_replaced_box.h
index 6fdda9e..bcd59c5 100644
--- a/src/cobalt/layout/block_level_replaced_box.h
+++ b/src/cobalt/layout/block_level_replaced_box.h
@@ -23,6 +23,7 @@
 #include "cobalt/layout/box.h"
 #include "cobalt/layout/paragraph.h"
 #include "cobalt/layout/replaced_box.h"
+#include "cobalt/math/size_f.h"
 
 namespace cobalt {
 namespace layout {
@@ -39,7 +40,7 @@
       const base::optional<float>& maybe_intrinsic_ratio,
       UsedStyleProvider* used_style_provider,
       base::optional<bool> is_video_punched_out,
-      LayoutStatTracker* layout_stat_tracker);
+      const math::SizeF& content_size, LayoutStatTracker* layout_stat_tracker);
 
   // From |Box|.
   Level GetLevel() const OVERRIDE;
diff --git a/src/cobalt/layout/box_generator.cc b/src/cobalt/layout/box_generator.cc
index 18bf26b..590e76b 100644
--- a/src/cobalt/layout/box_generator.cc
+++ b/src/cobalt/layout/box_generator.cc
@@ -185,7 +185,8 @@
                        const base::optional<LayoutUnit>& maybe_intrinsic_height,
                        const base::optional<float>& maybe_intrinsic_ratio,
                        const BoxGenerator::Context* context,
-                       base::optional<bool> is_video_punched_out)
+                       base::optional<bool> is_video_punched_out,
+                       math::SizeF content_size)
       : css_computed_style_declaration_(css_computed_style_declaration),
         replace_image_cb_(replace_image_cb),
         set_bounds_cb_(set_bounds_cb),
@@ -195,7 +196,8 @@
         maybe_intrinsic_height_(maybe_intrinsic_height),
         maybe_intrinsic_ratio_(maybe_intrinsic_ratio),
         context_(context),
-        is_video_punched_out_(is_video_punched_out) {}
+        is_video_punched_out_(is_video_punched_out),
+        content_size_(content_size) {}
 
   void VisitKeyword(cssom::KeywordValue* keyword) OVERRIDE;
 
@@ -213,6 +215,7 @@
   const base::optional<float> maybe_intrinsic_ratio_;
   const BoxGenerator::Context* context_;
   base::optional<bool> is_video_punched_out_;
+  math::SizeF content_size_;
 
   scoped_refptr<ReplacedBox> replaced_box_;
 };
@@ -226,7 +229,7 @@
           css_computed_style_declaration_, replace_image_cb_, set_bounds_cb_,
           paragraph_, text_position_, maybe_intrinsic_width_,
           maybe_intrinsic_height_, maybe_intrinsic_ratio_,
-          context_->used_style_provider, is_video_punched_out_,
+          context_->used_style_provider, is_video_punched_out_, content_size_,
           context_->layout_stat_tracker));
       break;
     // Generate an inline-level replaced box. There is no need to distinguish
@@ -239,7 +242,7 @@
           css_computed_style_declaration_, replace_image_cb_, set_bounds_cb_,
           paragraph_, text_position_, maybe_intrinsic_width_,
           maybe_intrinsic_height_, maybe_intrinsic_ratio_,
-          context_->used_style_provider, is_video_punched_out_,
+          context_->used_style_provider, is_video_punched_out_, content_size_,
           context_->layout_stat_tracker));
       break;
     // The element generates no boxes and has no effect on layout.
@@ -333,9 +336,6 @@
     }
   }
 
-  // Unlike in Chromium, we do not set the intrinsic width, height, or ratio
-  // based on the video frame. This allows to avoid relayout while playing
-  // adaptive videos.
   ReplacedBoxGenerator replaced_box_generator(
       video_element->css_computed_style_declaration(),
       video_element->GetVideoFrameProvider()
@@ -343,7 +343,8 @@
                        resource_provider)
           : ReplacedBox::ReplaceImageCB(),
       video_element->GetSetBoundsCB(), *paragraph_, text_position,
-      base::nullopt, base::nullopt, base::nullopt, context_, is_punch_out);
+      base::nullopt, base::nullopt, base::nullopt, context_, is_punch_out,
+      video_element->GetVideoSize());
   video_element->computed_style()->display()->Accept(&replaced_box_generator);
 
   scoped_refptr<ReplacedBox> replaced_box =
diff --git a/src/cobalt/layout/inline_level_replaced_box.cc b/src/cobalt/layout/inline_level_replaced_box.cc
index 0f2bc17..0da6991 100644
--- a/src/cobalt/layout/inline_level_replaced_box.cc
+++ b/src/cobalt/layout/inline_level_replaced_box.cc
@@ -15,6 +15,7 @@
 #include "cobalt/layout/inline_level_replaced_box.h"
 
 #include "cobalt/layout/used_style.h"
+#include "cobalt/math/size_f.h"
 
 namespace cobalt {
 namespace layout {
@@ -28,13 +29,13 @@
     const base::optional<LayoutUnit>& maybe_intrinsic_height,
     const base::optional<float>& maybe_intrinsic_ratio,
     UsedStyleProvider* used_style_provider,
-    base::optional<bool> is_video_punched_out,
+    base::optional<bool> is_video_punched_out, const math::SizeF& content_size,
     LayoutStatTracker* layout_stat_tracker)
     : ReplacedBox(css_computed_style_declaration, replace_image_cb,
                   set_bounds_cb, paragraph, text_position,
                   maybe_intrinsic_width, maybe_intrinsic_height,
                   maybe_intrinsic_ratio, used_style_provider,
-                  is_video_punched_out, layout_stat_tracker),
+                  is_video_punched_out, content_size, layout_stat_tracker),
       is_hidden_by_ellipsis_(false),
       was_hidden_by_ellipsis_(false) {}
 
diff --git a/src/cobalt/layout/inline_level_replaced_box.h b/src/cobalt/layout/inline_level_replaced_box.h
index 14fd995..d280a25 100644
--- a/src/cobalt/layout/inline_level_replaced_box.h
+++ b/src/cobalt/layout/inline_level_replaced_box.h
@@ -23,6 +23,7 @@
 #include "cobalt/layout/box.h"
 #include "cobalt/layout/paragraph.h"
 #include "cobalt/layout/replaced_box.h"
+#include "cobalt/math/size_f.h"
 
 namespace cobalt {
 namespace layout {
@@ -41,7 +42,7 @@
       const base::optional<float>& maybe_intrinsic_ratio,
       UsedStyleProvider* used_style_provider,
       base::optional<bool> is_video_punched_out,
-      LayoutStatTracker* layout_stat_tracker);
+      const math::SizeF& content_size, LayoutStatTracker* layout_stat_tracker);
 
   // From |Box|.
   Level GetLevel() const OVERRIDE;
diff --git a/src/cobalt/layout/replaced_box.cc b/src/cobalt/layout/replaced_box.cc
index 215522e..f157541 100644
--- a/src/cobalt/layout/replaced_box.cc
+++ b/src/cobalt/layout/replaced_box.cc
@@ -42,7 +42,6 @@
 namespace cobalt {
 namespace layout {
 
-using render_tree::animations::AnimateNode;
 using render_tree::CompositionNode;
 using render_tree::FilterNode;
 using render_tree::ImageNode;
@@ -51,6 +50,7 @@
 using render_tree::PunchThroughVideoNode;
 using render_tree::RectNode;
 using render_tree::SolidColorBrush;
+using render_tree::animations::AnimateNode;
 
 namespace {
 
@@ -102,7 +102,7 @@
     const base::optional<LayoutUnit>& maybe_intrinsic_height,
     const base::optional<float>& maybe_intrinsic_ratio,
     UsedStyleProvider* used_style_provider,
-    base::optional<bool> is_video_punched_out,
+    base::optional<bool> is_video_punched_out, const math::SizeF& content_size,
     LayoutStatTracker* layout_stat_tracker)
     : Box(css_computed_style_declaration, used_style_provider,
           layout_stat_tracker),
@@ -116,7 +116,8 @@
       set_bounds_cb_(set_bounds_cb),
       paragraph_(paragraph),
       text_position_(text_position),
-      is_video_punched_out_(is_video_punched_out) {}
+      is_video_punched_out_(is_video_punched_out),
+      content_size_(content_size) {}
 
 WrapResult ReplacedBox::TryWrapAt(
     WrapAtPolicy /*wrap_at_policy*/,
@@ -230,6 +231,18 @@
   AddLetterboxFillRects(dimensions, composition_node_builder);
 }
 
+void AddLetterboxedPunchThroughVideoNodeToRenderTree(
+    const LetterboxDimensions& dimensions,
+    const ReplacedBox::SetBoundsCB& set_bounds_cb,
+    CompositionNode::Builder* border_node_builder) {
+  if (dimensions.image_rect) {
+    PunchThroughVideoNode::Builder builder(*(dimensions.image_rect),
+                                           set_bounds_cb);
+    border_node_builder->AddChild(new PunchThroughVideoNode(builder));
+  }
+  AddLetterboxFillRects(dimensions, border_node_builder);
+}
+
 void AnimateVideoImage(const ReplacedBox::ReplaceImageCB& replace_image_cb,
                        ImageNode::Builder* image_node_builder) {
   DCHECK(!replace_image_cb.is_null());
@@ -310,22 +323,30 @@
   const cssom::MapToMeshFunction* mtm_filter_function =
       cssom::MapToMeshFunction::ExtractFromFilterList(
           computed_style()->filter());
-  if (*is_video_punched_out_) {
-    DCHECK(!mtm_filter_function)
+
+  if (mtm_filter_function) {
+    DCHECK(!*is_video_punched_out_)
         << "We currently do not support punched out video with map-to-mesh "
            "filters.";
-    // For systems that have their own path to blitting video to the display, we
-    // simply punch a hole through our scene so that the video can appear there.
-    PunchThroughVideoNode::Builder builder(math::RectF(content_box_size()),
-                                           set_bounds_cb_);
-    border_node_builder->AddChild(new PunchThroughVideoNode(builder));
+    RenderAndAnimateContentWithMapToMesh(border_node_builder,
+                                         mtm_filter_function);
   } else {
-    if (mtm_filter_function) {
-      RenderAndAnimateContentWithMapToMesh(border_node_builder,
-                                           mtm_filter_function);
-    } else {
-      RenderAndAnimateContentWithLetterboxing(border_node_builder);
+#if defined(FORCE_VIDEO_EXTERNAL_MESH)
+    if (!*is_video_punched_out_) {
+      AnimateNode::Builder animate_node_builder;
+      scoped_refptr<ImageNode> image_node = new ImageNode(NULL);
+      animate_node_builder.Add(
+          image_node, base::Bind(&AnimateVideoImage, replace_image_cb_));
+
+      // Attach an empty map to mesh filter node to signal the need for an
+      // external mesh.
+      border_node_builder->AddChild(
+          new FilterNode(MapToMeshFilter(render_tree::kMono),
+                         new AnimateNode(animate_node_builder, image_node)));
+      return;
     }
+#endif
+    RenderAndAnimateContentWithLetterboxing(border_node_builder);
   }
 }
 
@@ -691,18 +712,23 @@
   CompositionNode::Builder composition_node_builder(
       math::Vector2dF((border_left_width() + padding_left()).toFloat(),
                       (border_top_width() + padding_top()).toFloat()));
-
   scoped_refptr<CompositionNode> composition_node =
       new CompositionNode(composition_node_builder);
 
-  AnimateNode::Builder animate_node_builder;
+  if (*is_video_punched_out_) {
+    LetterboxDimensions letterbox_dims =
+        GetLetterboxDimensions(content_size_, content_box_size());
+    AddLetterboxedPunchThroughVideoNodeToRenderTree(
+        letterbox_dims, set_bounds_cb_, border_node_builder);
 
-  animate_node_builder.Add(composition_node,
-                           base::Bind(&AnimateVideoWithLetterboxing,
-                                      replace_image_cb_, content_box_size()));
-
-  border_node_builder->AddChild(
-      new AnimateNode(animate_node_builder, composition_node));
+  } else {
+    AnimateNode::Builder animate_node_builder;
+    animate_node_builder.Add(composition_node,
+                             base::Bind(&AnimateVideoWithLetterboxing,
+                                        replace_image_cb_, content_box_size()));
+    border_node_builder->AddChild(
+        new AnimateNode(animate_node_builder, composition_node));
+  }
 }
 
 }  // namespace layout
diff --git a/src/cobalt/layout/replaced_box.h b/src/cobalt/layout/replaced_box.h
index 81a9b16..52e139a 100644
--- a/src/cobalt/layout/replaced_box.h
+++ b/src/cobalt/layout/replaced_box.h
@@ -24,6 +24,7 @@
 #include "cobalt/layout/box.h"
 #include "cobalt/layout/paragraph.h"
 #include "cobalt/math/rect.h"
+#include "cobalt/math/size_f.h"
 #include "cobalt/render_tree/image.h"
 #include "cobalt/render_tree/punch_through_video_node.h"
 
@@ -51,6 +52,7 @@
               const base::optional<float>& maybe_intrinsic_ratio,
               UsedStyleProvider* used_style_provider,
               base::optional<bool> is_video_punched_out,
+              const math::SizeF& content_size,
               LayoutStatTracker* layout_stat_tracker);
 
   // From |Box|.
@@ -118,6 +120,7 @@
   const scoped_refptr<Paragraph> paragraph_;
   int32 text_position_;
   base::optional<bool> is_video_punched_out_;
+  math::SizeF content_size_;
 };
 
 }  // namespace layout
diff --git a/src/cobalt/loader/resource_cache.h b/src/cobalt/loader/resource_cache.h
index 024cc55..ddb4300 100644
--- a/src/cobalt/loader/resource_cache.h
+++ b/src/cobalt/loader/resource_cache.h
@@ -421,6 +421,10 @@
 
   void Purge();
 
+  // Processes all pending callbacks regardless of the state of
+  // |callback_blocking_loading_resource_set_|.
+  void ProcessPendingCallbacks();
+
   void DisableCallbacks();
 
  private:
@@ -462,9 +466,6 @@
   // Calls ProcessPendingCallbacks() if
   // |callback_blocking_loading_resource_set_| is empty.
   void ProcessPendingCallbacksIfUnblocked();
-  // Processes all pending callbacks regardless of the state of
-  // |callback_blocking_loading_resource_set_|.
-  void ProcessPendingCallbacks();
 
   // The name of this resource cache object, useful while debugging.
   const std::string name_;
@@ -637,6 +638,30 @@
 }
 
 template <typename CacheType>
+void ResourceCache<CacheType>::ProcessPendingCallbacks() {
+  DCHECK(resource_cache_thread_checker_.CalledOnValidThread());
+
+  // If callbacks are disabled, simply return.
+  if (are_callbacks_disabled_) {
+    return;
+  }
+
+  is_processing_pending_callbacks_ = true;
+  while (!pending_callback_map_.empty()) {
+    ResourceCallbackInfo& callback_info = pending_callback_map_.front().second;
+
+    // To avoid the last reference of this object getting deleted in the
+    // callbacks.
+    scoped_refptr<CachedResourceType> holder(callback_info.cached_resource);
+    callback_info.cached_resource->RunCallbacks(callback_info.callback_type);
+
+    pending_callback_map_.erase(pending_callback_map_.begin());
+  }
+  is_processing_pending_callbacks_ = false;
+  count_pending_callbacks_ = 0;
+}
+
+template <typename CacheType>
 void ResourceCache<CacheType>::DisableCallbacks() {
   DCHECK(resource_cache_thread_checker_.CalledOnValidThread());
   are_callbacks_disabled_ = true;
@@ -783,30 +808,6 @@
   }
 }
 
-template <typename CacheType>
-void ResourceCache<CacheType>::ProcessPendingCallbacks() {
-  DCHECK(resource_cache_thread_checker_.CalledOnValidThread());
-
-  // If callbacks are disabled, simply return.
-  if (are_callbacks_disabled_) {
-    return;
-  }
-
-  is_processing_pending_callbacks_ = true;
-  while (!pending_callback_map_.empty()) {
-    ResourceCallbackInfo& callback_info = pending_callback_map_.front().second;
-
-    // To avoid the last reference of this object getting deleted in the
-    // callbacks.
-    scoped_refptr<CachedResourceType> holder(callback_info.cached_resource);
-    callback_info.cached_resource->RunCallbacks(callback_info.callback_type);
-
-    pending_callback_map_.erase(pending_callback_map_.begin());
-  }
-  is_processing_pending_callbacks_ = false;
-  count_pending_callbacks_ = 0;
-}
-
 }  // namespace loader
 }  // namespace cobalt
 
diff --git a/src/cobalt/media/base/drm_system.cc b/src/cobalt/media/base/drm_system.cc
index 8b5516b..a5f2457 100644
--- a/src/cobalt/media/base/drm_system.cc
+++ b/src/cobalt/media/base/drm_system.cc
@@ -20,7 +20,7 @@
 namespace cobalt {
 namespace media {
 
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
 DrmSystem::Session::Session(
     DrmSystem* drm_system,
     SessionUpdateKeyStatusesCallback update_key_statuses_callback)
@@ -29,10 +29,10 @@
       closed_(false) {
   DCHECK(!update_key_statuses_callback_.is_null());
 }
-#else   // SB_API_VERSION >= 6
+#else   // SB_HAS(DRM_KEY_STATUSES)
 DrmSystem::Session::Session(DrmSystem* drm_system)
     : drm_system_(drm_system), closed_(false) {}
-#endif  // SB_API_VERSION >= 6
+#endif  // SB_HAS(DRM_KEY_STATUSES)
 
 DrmSystem::Session::~Session() {
   if (id_ && !closed_) {
@@ -77,11 +77,11 @@
     : wrapped_drm_system_(SbDrmCreateSystem(key_system, this,
                                             OnSessionUpdateRequestGeneratedFunc,
                                             OnSessionUpdatedFunc
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
                                             ,
                                             OnSessionKeyStatusesChangedFunc
-#endif  // SB_API_VERSION >= 6
-                                            )),
+#endif  // SB_HAS(DRM_KEY_STATUSES)
+                                            )),  // NOLINT(whitespace/parens)
       message_loop_(MessageLoop::current()),
       ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
       weak_this_(weak_ptr_factory_.GetWeakPtr()),
@@ -92,17 +92,17 @@
 
 DrmSystem::~DrmSystem() { SbDrmDestroySystem(wrapped_drm_system_); }
 
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
 scoped_ptr<DrmSystem::Session> DrmSystem::CreateSession(
     SessionUpdateKeyStatusesCallback session_update_key_statuses_callback) {
   return make_scoped_ptr(
       new Session(this, session_update_key_statuses_callback));
 }
-#else   // SB_API_VERSION >= 6
+#else   // SB_HAS(DRM_KEY_STATUSES)
 scoped_ptr<DrmSystem::Session> DrmSystem::CreateSession() {
   return make_scoped_ptr(new Session(this));
 }
-#endif  // SB_API_VERSION >= 6
+#endif  // SB_HAS(DRM_KEY_STATUSES)
 
 void DrmSystem::GenerateSessionUpdateRequest(
     Session* session, const std::string& type, const uint8_t* init_data,
@@ -226,7 +226,7 @@
   ticket_to_session_update_map_.erase(session_update_iterator);
 }
 
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
 void DrmSystem::OnSessionKeyStatusChanged(
     const std::string& session_id, const std::vector<std::string>& key_ids,
     const std::vector<SbDrmKeyStatus>& key_statuses) {
@@ -241,7 +241,7 @@
 
   session->update_key_statuses_callback().Run(key_ids, key_statuses);
 }
-#endif  // SB_API_VERSION >= 6
+#endif  // SB_HAS(DRM_KEY_STATUSES)
 
 // static
 void DrmSystem::OnSessionUpdateRequestGeneratedFunc(
@@ -283,7 +283,7 @@
                             drm_system->weak_this_, ticket, succeeded));
 }
 
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
 // static
 void DrmSystem::OnSessionKeyStatusesChangedFunc(
     SbDrmSystem wrapped_drm_system, void* context, const void* session_id,
@@ -315,7 +315,7 @@
       base::Bind(&DrmSystem::OnSessionKeyStatusChanged, drm_system->weak_this_,
                  session_id_copy, key_ids_copy, key_statuses_copy));
 }
-#endif  // SB_API_VERSION >= 6
+#endif  // SB_HAS(DRM_KEY_STATUSES)
 
 }  // namespace media
 }  // namespace cobalt
diff --git a/src/cobalt/media/base/drm_system.h b/src/cobalt/media/base/drm_system.h
index f60ad9d..6eea0af 100644
--- a/src/cobalt/media/base/drm_system.h
+++ b/src/cobalt/media/base/drm_system.h
@@ -40,11 +40,11 @@
   typedef base::Callback<void()> SessionUpdateRequestDidNotGenerateCallback;
   typedef base::Callback<void()> SessionUpdatedCallback;
   typedef base::Callback<void()> SessionDidNotUpdateCallback;
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
   typedef base::Callback<void(const std::vector<std::string>& key_ids,
                               const std::vector<SbDrmKeyStatus>& key_statuses)>
       SessionUpdateKeyStatusesCallback;
-#endif  // SB_API_VERSION >= 6
+#endif  // SB_HAS(DRM_KEY_STATUSES)
 
   // Flyweight that provides RAII semantics for sessions.
   // Most of logic is implemented by |DrmSystem| and thus sessions must be
@@ -89,31 +89,31 @@
    private:
     // Private API for |DrmSystem|.
     Session(DrmSystem* drm_system
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
             ,
             SessionUpdateKeyStatusesCallback update_key_statuses_callback
-#endif  // SB_API_VERSION >= 6
+#endif          // SB_HAS(DRM_KEY_STATUSES)
             );  // NOLINT(whitespace/parens)
     void set_id(const std::string& id) { id_ = id; }
     const SessionUpdateRequestGeneratedCallback&
     update_request_generated_callback() const {
       return update_request_generated_callback_;
     }
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
     const SessionUpdateKeyStatusesCallback& update_key_statuses_callback()
         const {
       return update_key_statuses_callback_;
     }
-#endif  // SB_API_VERSION >= 6
+#endif  // SB_HAS(DRM_KEY_STATUSES)
 
     DrmSystem* const drm_system_;
     bool closed_;
     base::optional<std::string> id_;
     // Supports spontaneous invocations of |SbDrmSessionUpdateRequestFunc|.
     SessionUpdateRequestGeneratedCallback update_request_generated_callback_;
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
     SessionUpdateKeyStatusesCallback update_key_statuses_callback_;
-#endif  // SB_API_VERSION >= 6
+#endif  // SB_HAS(DRM_KEY_STATUSES)
 
     friend class DrmSystem;
 
@@ -126,9 +126,9 @@
   SbDrmSystem wrapped_drm_system() { return wrapped_drm_system_; }
 
   scoped_ptr<Session> CreateSession(
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
       SessionUpdateKeyStatusesCallback session_update_key_statuses_callback
-#endif  // SB_API_VERSION >= 6
+#endif    // SB_HAS(DRM_KEY_STATUSES)
       );  // NOLINT(whitespace/parens)
 
  private:
@@ -169,11 +169,11 @@
       int ticket, const base::optional<std::string>& session_id,
       scoped_array<uint8> message, int message_size);
   void OnSessionUpdated(int ticket, bool succeeded);
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
   void OnSessionKeyStatusChanged(
       const std::string& session_id, const std::vector<std::string>& key_ids,
       const std::vector<SbDrmKeyStatus>& key_statuses);
-#endif  // SB_API_VERSION >= 6
+#endif  // SB_HAS(DRM_KEY_STATUSES)
 
   // Called on any thread, parameters need to be copied immediately.
   static void OnSessionUpdateRequestGeneratedFunc(
@@ -184,12 +184,12 @@
                                    void* context, int ticket,
                                    const void* session_id,
                                    int session_id_length, bool succeeded);
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
   static void OnSessionKeyStatusesChangedFunc(
       SbDrmSystem wrapped_drm_system, void* context, const void* session_id,
       int session_id_size, int number_of_keys, const SbDrmKeyId* key_ids,
       const SbDrmKeyStatus* key_statuses);
-#endif  // SB_API_VERSION >= 6
+#endif  // SB_HAS(DRM_KEY_STATUSES)
 
   const SbDrmSystem wrapped_drm_system_;
   MessageLoop* const message_loop_;
diff --git a/src/cobalt/media/base/sbplayer_set_bounds_helper.cc b/src/cobalt/media/base/sbplayer_set_bounds_helper.cc
index 53187f2..7bec081 100644
--- a/src/cobalt/media/base/sbplayer_set_bounds_helper.cc
+++ b/src/cobalt/media/base/sbplayer_set_bounds_helper.cc
@@ -26,7 +26,7 @@
 }  // namespace
 
 void SbPlayerSetBoundsHelper::SetPlayer(StarboardPlayer* player) {
-  base::Lock lock_;
+  base::AutoLock auto_lock(lock_);
   player_ = player;
 }
 
diff --git a/src/cobalt/media/base/starboard_player.cc b/src/cobalt/media/base/starboard_player.cc
index e5b6f4f..9b30cba 100644
--- a/src/cobalt/media/base/starboard_player.cc
+++ b/src/cobalt/media/base/starboard_player.cc
@@ -333,6 +333,11 @@
   preroll_timestamp_ = SbMediaTimeToTimeDelta(info.current_media_pts);
 
   set_bounds_helper_->SetPlayer(NULL);
+  ShellMediaPlatform::Instance()->GetVideoFrameProvider()->SetOutputMode(
+      ShellVideoFrameProvider::kOutputModeInvalid);
+  ShellMediaPlatform::Instance()->GetVideoFrameProvider()
+      ->ResetGetCurrentSbDecodeTargetFunction();
+
   SbPlayerDestroy(player_);
 
   player_ = kSbPlayerInvalid;
diff --git a/src/cobalt/media/filters/source_buffer_stream.cc b/src/cobalt/media/filters/source_buffer_stream.cc
index 2602fd0..4f9ffb0 100644
--- a/src/cobalt/media/filters/source_buffer_stream.cc
+++ b/src/cobalt/media/filters/source_buffer_stream.cc
@@ -394,7 +394,8 @@
 
   DVLOG(1) << __func__ << " " << GetStreamTypeName()
            << ": done. ranges_=" << RangesToString(ranges_);
-  DCHECK(IsRangeListSorted(ranges_));
+  // TODO: Investigate if the following DCHECK should be restored.
+  // DCHECK(IsRangeListSorted(ranges_));
   DCHECK(OnlySelectedRangeIsSeeked());
   return true;
 }
diff --git a/src/cobalt/render_tree/mock_resource_provider.h b/src/cobalt/render_tree/mock_resource_provider.h
index d30b9fc..f6e0470 100644
--- a/src/cobalt/render_tree/mock_resource_provider.h
+++ b/src/cobalt/render_tree/mock_resource_provider.h
@@ -36,6 +36,10 @@
 
 class MockResourceProvider : public ResourceProvider {
  public:
+  base::TypeId GetTypeId() const OVERRIDE {
+    return base::GetTypeId<MockResourceProvider>();
+  }
+
   MOCK_METHOD0(Finish, void());
   MOCK_METHOD1(PixelFormatSupported, bool(PixelFormat pixel_format));
   MOCK_METHOD1(AlphaFormatSupported, bool(AlphaFormat alpha_format));
diff --git a/src/cobalt/render_tree/resource_provider.h b/src/cobalt/render_tree/resource_provider.h
index acbbb21..8169a7e 100644
--- a/src/cobalt/render_tree/resource_provider.h
+++ b/src/cobalt/render_tree/resource_provider.h
@@ -20,6 +20,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "cobalt/base/type_id.h"
 #include "cobalt/render_tree/font.h"
 #include "cobalt/render_tree/font_provider.h"
 #include "cobalt/render_tree/glyph_buffer.h"
@@ -50,6 +51,10 @@
 
   virtual ~ResourceProvider() {}
 
+  // Returns an ID that is unique to the ResourceProvider type.  This can be
+  // used to polymorphically identify what type of ResourceProvider this is.
+  virtual base::TypeId GetTypeId() const = 0;
+
   // Blocks until it can be guaranteed that all resource-related operations have
   // completed.  This might be important if we would like to ensure that memory
   // allocations or deallocations have occurred before proceeding with a memory
diff --git a/src/cobalt/render_tree/resource_provider_stub.h b/src/cobalt/render_tree/resource_provider_stub.h
index ab84ad4..9d44432 100644
--- a/src/cobalt/render_tree/resource_provider_stub.h
+++ b/src/cobalt/render_tree/resource_provider_stub.h
@@ -187,6 +187,10 @@
       : release_image_data_(release_image_data) {}
   ~ResourceProviderStub() OVERRIDE {}
 
+  base::TypeId GetTypeId() const OVERRIDE {
+    return base::GetTypeId<ResourceProviderStub>();
+  }
+
   void Finish() OVERRIDE {}
 
   bool PixelFormatSupported(PixelFormat pixel_format) OVERRIDE {
diff --git a/src/cobalt/renderer/rasterizer/blitter/resource_provider.h b/src/cobalt/renderer/rasterizer/blitter/resource_provider.h
index 92315fe..64610a1 100644
--- a/src/cobalt/renderer/rasterizer/blitter/resource_provider.h
+++ b/src/cobalt/renderer/rasterizer/blitter/resource_provider.h
@@ -41,6 +41,10 @@
                    SubmitOffscreenCallback submit_offscreen_callback);
   ~ResourceProvider() OVERRIDE {}
 
+  base::TypeId GetTypeId() const OVERRIDE {
+    return base::GetTypeId<ResourceProvider>();
+  }
+
   void Finish() OVERRIDE {}
 
   scoped_refptr<render_tree::Image> CreateImageFromSbDecodeTarget(
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
index de106d7..9de7ca4 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
@@ -43,6 +43,10 @@
                            bool purge_skia_font_caches_on_destruction);
   ~HardwareResourceProvider() OVERRIDE;
 
+  base::TypeId GetTypeId() const OVERRIDE {
+    return base::GetTypeId<HardwareResourceProvider>();
+  }
+
   void Finish() OVERRIDE;
 
   bool PixelFormatSupported(render_tree::PixelFormat pixel_format) OVERRIDE;
diff --git a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
index 492d3ab..c05abb5 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
+++ b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
@@ -34,6 +34,10 @@
   explicit SoftwareResourceProvider(bool purge_skia_font_caches_on_destruction);
   ~SoftwareResourceProvider() OVERRIDE;
 
+  base::TypeId GetTypeId() const OVERRIDE {
+    return base::GetTypeId<SoftwareResourceProvider>();
+  }
+
   void Finish() OVERRIDE{};
 
   bool PixelFormatSupported(render_tree::PixelFormat pixel_format) OVERRIDE;
diff --git a/src/starboard/configuration.h b/src/starboard/configuration.h
index 58d12c0..be5d02f 100644
--- a/src/starboard/configuration.h
+++ b/src/starboard/configuration.h
@@ -532,6 +532,16 @@
 #error "SB_MEDIA_GPU_BUFFER_BUDGET is deprecated."
 #endif  // defined(SB_MEDIA_GPU_BUFFER_BUDGET)
 
+#if SB_API_VERSION >= 6
+#if defined(SB_HAS_DRM_KEY_STATUSES)
+#if !SB_HAS(DRM_KEY_STATUSES)
+#error "SB_HAS_DRM_KEY_STATUSES is required for Starboard 6 or later."
+#endif  // !SB_HAS(DRM_KEY_STATUSES)
+#else   // defined(SB_HAS_DRM_KEY_STATUSES)
+#define SB_HAS_DRM_KEY_STATUSES 1
+#endif  // defined(SB_HAS_DRM_KEY_STATUSES)
+#endif  // SB_API_VERSION >= 6
+
 #if SB_API_VERSION >= 5
 #if !defined(SB_HAS_SPEECH_RECOGNIZER)
 #error "Your platform must define SB_HAS_SPEECH_RECOGNIZER."
diff --git a/src/starboard/creator/shared/configuration_public.h b/src/starboard/creator/shared/configuration_public.h
index d467efd..f3c2d81 100644
--- a/src/starboard/creator/shared/configuration_public.h
+++ b/src/starboard/creator/shared/configuration_public.h
@@ -17,6 +17,14 @@
 #ifndef STARBOARD_CREATOR_SHARED_CONFIGURATION_PUBLIC_H_
 #define STARBOARD_CREATOR_SHARED_CONFIGURATION_PUBLIC_H_
 
+// The Darwin platform doesn't have the function pthread_condattr_setclock(),
+// which is used to switch pthread condition variable timed waits to use
+// a monotonic clock instead of the system clock, which is sensitive to
+// system time adjustments.  This isn't a [huge] problem on Darwin because
+// its timed wait function immediately converts to relative wait time anyway:
+//   https://opensource.apple.com/source/Libc/Libc-167/pthreads.subproj/pthread_cond.c
+#define SB_HAS_QUIRK_NO_CONDATTR_SETCLOCK_SUPPORT 1
+
 // --- Architecture Configuration --------------------------------------------
 
 // Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be
diff --git a/src/starboard/drm.h b/src/starboard/drm.h
index 4ce3df8..fbc6ea1 100644
--- a/src/starboard/drm.h
+++ b/src/starboard/drm.h
@@ -52,14 +52,14 @@
   int32_t encrypted_byte_count;
 } SbDrmSubSampleMapping;
 
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
 typedef struct SbDrmKeyId {
   // The ID of the license (or key) required to decrypt this sample. For
   // PlayReady, this is the license GUID in packed little-endian binary form.
   uint8_t identifier[16];
   int identifier_size;
 } SbDrmKeyId;
-#endif  // SB_API_VERSION >= 6
+#endif  // SB_HAS(DRM_KEY_STATUSES)
 
 // All the optional information needed per sample for encrypted samples.
 typedef struct SbDrmSampleInfo {
@@ -121,7 +121,7 @@
 // A callback for notifications that the status of one or more keys in a session
 // has been changed.  All keys of the session and their new status will be
 // passed along.  Any keys not in the list is considered as deleted.
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
 typedef void (*SbDrmSessionKeyStatusesChangedFunc)(
     SbDrmSystem drm_system,
     void* context,
@@ -130,7 +130,7 @@
     int number_of_keys,
     const SbDrmKeyId* key_ids,
     const SbDrmKeyStatus* key_statuses);
-#endif  // SB_API_VERSION >= 6
+#endif  // SB_HAS(DRM_KEY_STATUSES)
 
 // --- Constants -------------------------------------------------------------
 
@@ -171,7 +171,7 @@
 // SbDrmGenerateSessionUpdateRequest() is called.
 // |session_updated_callback|: A function that is called every time after
 // SbDrmUpdateSession() is called.
-#if SB_API_VERSION >= 6
+#if SB_HAS(DRM_KEY_STATUSES)
 
 SB_EXPORT SbDrmSystem SbDrmCreateSystem(
     const char* key_system,
@@ -180,7 +180,7 @@
     SbDrmSessionUpdatedFunc session_updated_callback,
     SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback);
 
-#else  // SB_API_VERSION >= 6
+#else  // SB_HAS(DRM_KEY_STATUSES)
 
 SB_EXPORT SbDrmSystem
 SbDrmCreateSystem(const char* key_system,
@@ -188,7 +188,7 @@
                   SbDrmSessionUpdateRequestFunc update_request_callback,
                   SbDrmSessionUpdatedFunc session_updated_callback);
 
-#endif  // SB_API_VERSION >= SB_DRM_KEY_STATUS_UPDATE_SUPPORT_API_VERSION
+#endif  // SB_HAS(DRM_KEY_STATUSES)
 
 // Asynchronously generates a session update request payload for
 // |initialization_data|, of |initialization_data_size|, in case sensitive
diff --git a/src/starboard/linux/x64x11/mock/gyp_configuration.gypi b/src/starboard/linux/x64x11/mock/gyp_configuration.gypi
index f76e9ea..659c47d 100644
--- a/src/starboard/linux/x64x11/mock/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/mock/gyp_configuration.gypi
@@ -29,7 +29,6 @@
     'cobalt_enable_jit': 0,
 
     'cobalt_media_source_2016': 1,
-    'cobalt_encrypted_media_extension_enable_key_statuses_update': 0,
 
     'platform_libraries': [
       '-lpthread',
diff --git a/src/starboard/nplb/player_create_test.cc b/src/starboard/nplb/player_create_test.cc
index f9cbe22..cfe234e 100644
--- a/src/starboard/nplb/player_create_test.cc
+++ b/src/starboard/nplb/player_create_test.cc
@@ -30,8 +30,10 @@
     SbDecodeTargetGlesContextRunnerTarget target_function,
     void* target_function_context) {
   SB_UNREFERENCED_PARAMETER(graphics_context_provider);
-  SB_UNREFERENCED_PARAMETER(target_function);
-  SB_UNREFERENCED_PARAMETER(target_function_context);
+
+  // Just call the function directly in case the player implementation relies
+  // on this function call being made.
+  (*target_function)(target_function_context);
 }
 #endif  // SB_HAS(GLES2)
 
diff --git a/src/starboard/shared/alsa/alsa_audio_sink_type.cc b/src/starboard/shared/alsa/alsa_audio_sink_type.cc
index def4105..b9a3548 100644
--- a/src/starboard/shared/alsa/alsa_audio_sink_type.cc
+++ b/src/starboard/shared/alsa/alsa_audio_sink_type.cc
@@ -223,7 +223,11 @@
   playback_handle_ = starboard::shared::alsa::AlsaOpenPlaybackDevice(
       channels_, sampling_frequency_hz_, kFramesPerRequest,
       kALSABufferSizeInFrames, alsa_sample_type);
-  creation_signal_.Signal();
+  {
+    ScopedLock lock(mutex_);
+    creation_signal_.Signal();
+  }
+
   if (!playback_handle_) {
     return;
   }
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
index ef14ae8..2984b6a 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
@@ -62,10 +62,12 @@
   TeardownCodec();
 }
 
-void AudioDecoder::Initialize(const Closure& output_cb) {
+void AudioDecoder::Initialize(const Closure& output_cb,
+                              const Closure& error_cb) {
   SB_DCHECK(BelongsToCurrentThread());
   SB_DCHECK(output_cb.is_valid());
   SB_DCHECK(!output_cb_.is_valid());
+  SB_UNREFERENCED_PARAMETER(error_cb);
 
   output_cb_ = output_cb;
 }
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h
index 40bd9c8..0e5497b 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h
+++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h
@@ -36,7 +36,8 @@
                const SbMediaAudioHeader& audio_header);
   ~AudioDecoder() SB_OVERRIDE;
 
-  void Initialize(const Closure& output_cb) SB_OVERRIDE;
+  void Initialize(const Closure& output_cb,
+                  const Closure& error_cb) SB_OVERRIDE;
   void Decode(const InputBuffer& input_buffer,
               const Closure& consumed_cb) SB_OVERRIDE;
   void WriteEndOfStream() SB_OVERRIDE;
diff --git a/src/starboard/shared/libvpx/vpx_video_decoder.cc b/src/starboard/shared/libvpx/vpx_video_decoder.cc
index 14727f9..f5c561d 100644
--- a/src/starboard/shared/libvpx/vpx_video_decoder.cc
+++ b/src/starboard/shared/libvpx/vpx_video_decoder.cc
@@ -162,12 +162,17 @@
   }
 
   if (output_mode_ == kSbPlayerOutputModeDecodeToTexture) {
-    ScopedLock lock(decode_target_mutex_);
-    if (SbDecodeTargetIsValid(decode_target_)) {
-      DecodeTargetRelease(decode_target_graphics_context_provider_,
-                          decode_target_);
+    SbDecodeTarget decode_target_to_release;
+    {
+      ScopedLock lock(decode_target_mutex_);
+      decode_target_to_release = decode_target_;
       decode_target_ = kSbDecodeTargetInvalid;
     }
+
+    if (SbDecodeTargetIsValid(decode_target_to_release)) {
+      DecodeTargetRelease(decode_target_graphics_context_provider_,
+                          decode_target_to_release);
+    }
   }
 }
 
diff --git a/src/starboard/shared/pthread/condition_variable_broadcast.cc b/src/starboard/shared/pthread/condition_variable_broadcast.cc
index b0faf1d..a478e2e 100644
--- a/src/starboard/shared/pthread/condition_variable_broadcast.cc
+++ b/src/starboard/shared/pthread/condition_variable_broadcast.cc
@@ -17,11 +17,20 @@
 #include <pthread.h>
 
 #include "starboard/shared/pthread/is_success.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::IsInitialized;
 
 bool SbConditionVariableBroadcast(SbConditionVariable* condition) {
   if (!condition) {
     return false;
   }
 
-  return IsSuccess(pthread_cond_broadcast(condition));
+  if (!IsInitialized(&condition->initialized_state)) {
+    // If the condition variable is not initialized yet, then there is nothing
+    // to signal so vacuously return true.
+    return true;
+  }
+
+  return IsSuccess(pthread_cond_broadcast(&condition->condition));
 }
diff --git a/src/starboard/shared/pthread/condition_variable_create.cc b/src/starboard/shared/pthread/condition_variable_create.cc
index f5c75d7..dc9575e 100644
--- a/src/starboard/shared/pthread/condition_variable_create.cc
+++ b/src/starboard/shared/pthread/condition_variable_create.cc
@@ -17,6 +17,30 @@
 #include <pthread.h>
 
 #include "starboard/shared/pthread/is_success.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::SetInitialized;
+
+namespace {
+struct ConditionVariableAttributes {
+ public:
+  ConditionVariableAttributes() {
+    valid_ = IsSuccess(pthread_condattr_init(&attributes_));
+  }
+  ~ConditionVariableAttributes() {
+    if (valid_) {
+      SB_CHECK(IsSuccess(pthread_condattr_destroy(&attributes_)));
+    }
+  }
+
+  bool valid() const { return valid_; }
+  pthread_condattr_t* attributes() { return &attributes_; }
+
+ private:
+  bool valid_;
+  pthread_condattr_t attributes_;
+};
+}  // namespace
 
 bool SbConditionVariableCreate(SbConditionVariable* out_condition,
                                SbMutex* /*opt_mutex*/) {
@@ -24,5 +48,33 @@
     return false;
   }
 
-  return IsSuccess(pthread_cond_init(out_condition, NULL));
+  ConditionVariableAttributes attributes;
+  if (!attributes.valid()) {
+    SB_DLOG(ERROR) << "Failed to call pthread_condattr_init().";
+    return false;
+  }
+
+#if !SB_HAS_QUIRK(NO_CONDATTR_SETCLOCK_SUPPORT)
+  // Always use CLOCK_MONOTONIC so that SbConditionVariableWaitTimed() will
+  // not be based off of the system clock (which can lead to erroneous
+  // behavior if the system clock is changed while a process is running).
+  if (!IsSuccess(pthread_condattr_setclock(
+           attributes.attributes(), CLOCK_MONOTONIC))) {
+    SB_DLOG(ERROR) << "Failed to call pthread_condattr_setclock().";
+    return false;
+  }
+#endif  // !SB_HAS_QUIRK(NO_CONDATTR_SETCLOCK_SUPPORT)
+
+  bool status = IsSuccess(pthread_cond_init(
+                    &out_condition->condition, attributes.attributes()));
+
+  // We mark that we are initialized regardless of whether initialization
+  // was successful or not.
+  SetInitialized(&out_condition->initialized_state);
+
+  if (!status) {
+    SB_DLOG(ERROR) << "Failed to call pthread_cond_init().";
+  }
+
+  return status;
 }
diff --git a/src/starboard/shared/pthread/condition_variable_destroy.cc b/src/starboard/shared/pthread/condition_variable_destroy.cc
index 7a4f974..81a26da 100644
--- a/src/starboard/shared/pthread/condition_variable_destroy.cc
+++ b/src/starboard/shared/pthread/condition_variable_destroy.cc
@@ -17,11 +17,20 @@
 #include <pthread.h>
 
 #include "starboard/shared/pthread/is_success.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::IsInitialized;
 
 bool SbConditionVariableDestroy(SbConditionVariable* condition) {
   if (!condition) {
     return false;
   }
 
-  return IsSuccess(pthread_cond_destroy(condition));
+  if (!IsInitialized(&condition->initialized_state)) {
+    // If the condition variable is not initialized yet, then there is nothing
+    // to destroy so vacuously return true.
+    return true;
+  }
+
+  return IsSuccess(pthread_cond_destroy(&condition->condition));
 }
diff --git a/src/starboard/shared/pthread/condition_variable_signal.cc b/src/starboard/shared/pthread/condition_variable_signal.cc
index c1b8a58..5acc597 100644
--- a/src/starboard/shared/pthread/condition_variable_signal.cc
+++ b/src/starboard/shared/pthread/condition_variable_signal.cc
@@ -17,11 +17,20 @@
 #include <pthread.h>
 
 #include "starboard/shared/pthread/is_success.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::IsInitialized;
 
 bool SbConditionVariableSignal(SbConditionVariable* condition) {
   if (!condition) {
     return false;
   }
 
-  return IsSuccess(pthread_cond_signal(condition));
+  if (!IsInitialized(&condition->initialized_state)) {
+    // If the condition variable is not initialized yet, then there is nothing
+    // to signal so vacuously return true.
+    return true;
+  }
+
+  return IsSuccess(pthread_cond_signal(&condition->condition));
 }
diff --git a/src/starboard/shared/pthread/condition_variable_wait.cc b/src/starboard/shared/pthread/condition_variable_wait.cc
index ccdf677..41ca6bb 100644
--- a/src/starboard/shared/pthread/condition_variable_wait.cc
+++ b/src/starboard/shared/pthread/condition_variable_wait.cc
@@ -17,6 +17,9 @@
 #include <pthread.h>
 
 #include "starboard/shared/pthread/is_success.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::EnsureInitialized;
 
 SbConditionVariableResult SbConditionVariableWait(
     SbConditionVariable* condition,
@@ -25,7 +28,15 @@
     return kSbConditionVariableFailed;
   }
 
-  if (IsSuccess(pthread_cond_wait(condition, mutex))) {
+  if (!EnsureInitialized(&condition->initialized_state)) {
+    // The condition variable is set to SB_CONDITION_VARIABLE_INITIALIZER and
+    // is uninitialized, so call SbConditionVariableCreate() to initialize the
+    // condition variable. SbConditionVariableCreate() is responsible for
+    // marking the variable as initialized.
+    SbConditionVariableCreate(condition, mutex);
+  }
+
+  if (IsSuccess(pthread_cond_wait(&condition->condition, mutex))) {
     return kSbConditionVariableSignaled;
   }
 
diff --git a/src/starboard/shared/pthread/condition_variable_wait_timed.cc b/src/starboard/shared/pthread/condition_variable_wait_timed.cc
index fd63f63..dcabd46 100644
--- a/src/starboard/shared/pthread/condition_variable_wait_timed.cc
+++ b/src/starboard/shared/pthread/condition_variable_wait_timed.cc
@@ -20,8 +20,11 @@
 
 #include "starboard/shared/posix/time_internal.h"
 #include "starboard/shared/pthread/is_success.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
 #include "starboard/time.h"
 
+using starboard::shared::starboard::EnsureInitialized;
+
 SbConditionVariableResult SbConditionVariableWaitTimed(
     SbConditionVariable* condition,
     SbMutex* mutex,
@@ -34,19 +37,33 @@
     timeout = 0;
   }
 
+#if !SB_HAS_QUIRK(NO_CONDATTR_SETCLOCK_SUPPORT)
+  SbTime timeout_time = SbTimeGetMonotonicNow() + timeout;
+#else  // !SB_HAS_QUIRK(NO_CONDATTR_SETCLOCK_SUPPORT)
+  int64_t timeout_time = SbTimeToPosix(SbTimeGetNow()) + timeout;
+#endif  // !SB_HAS_QUIRK(NO_CONDATTR_SETCLOCK_SUPPORT)
+
   // Detect overflow if timeout is near kSbTimeMax. Since timeout can't be
   // negative at this point, if it goes negative after adding now, we know we've
   // gone over. Especially posix now, which has a 400 year advantage over
   // Chromium (Windows) now.
-  int64_t posix_time = SbTimeToPosix(SbTimeGetNow()) + timeout;
-  if (posix_time < 0) {
-    posix_time = kSbInt64Max;
+  if (timeout_time < 0) {
+    timeout_time = kSbInt64Max;
   }
 
   struct timespec timeout_ts;
-  ToTimespec(&timeout_ts, posix_time);
+  ToTimespec(&timeout_ts, timeout_time);
 
-  int result = pthread_cond_timedwait(condition, mutex, &timeout_ts);
+  if (!EnsureInitialized(&condition->initialized_state)) {
+    // The condition variable is set to SB_CONDITION_VARIABLE_INITIALIZER and
+    // is uninitialized, so call SbConditionVariableCreate() to initialize the
+    // condition variable. SbConditionVariableCreate() is responsible for
+    // marking the variable as initialized.
+    SbConditionVariableCreate(condition, mutex);
+  }
+
+  int result =
+      pthread_cond_timedwait(&condition->condition, mutex, &timeout_ts);
   if (IsSuccess(result)) {
     return kSbConditionVariableSignaled;
   }
diff --git a/src/starboard/shared/pthread/types_public.h b/src/starboard/shared/pthread/types_public.h
index 59ee65e..4e19c63 100644
--- a/src/starboard/shared/pthread/types_public.h
+++ b/src/starboard/shared/pthread/types_public.h
@@ -22,13 +22,23 @@
 
 #include <pthread.h>
 
+#include "starboard/shared/starboard/lazy_initialization_public.h"
+
 // --- SbConditionVariable ---
 
 // Transparent Condition Variable handle.
-typedef pthread_cond_t SbConditionVariable;
+// It is customized from the plain pthread_cont_t object because we
+// need to ensure that each condition variable is initialized to use
+// CLOCK_MONOTONIC, which is not the default (and the default is used
+// when PTHREAD_COND_INITIALIZER is set).
+typedef struct SbConditionVariable {
+  InitializedState initialized_state;
+  pthread_cond_t condition;
+} SbConditionVariable;
 
 // Condition Variable static initializer.
-#define SB_CONDITION_VARIABLE_INITIALIZER PTHREAD_COND_INITIALIZER
+#define SB_CONDITION_VARIABLE_INITIALIZER \
+  { INITIALIZED_STATE_UNINITIALIZED, 0 }
 
 // --- SbMutex ---
 
diff --git a/src/starboard/shared/starboard/lazy_initialization_internal.cc b/src/starboard/shared/starboard/lazy_initialization_internal.cc
deleted file mode 100644
index f108899..0000000
--- a/src/starboard/shared/starboard/lazy_initialization_internal.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "starboard/shared/starboard/lazy_initialization_internal.h"
-
-#include "starboard/log.h"
-#include "starboard/thread.h"
-
-// INITIALIZED_STATE_UNINITIALIZED is defined in the header.
-#define INITIALIZED_STATE_INITIALIZING 2
-#define INITIALIZED_STATE_INITIALIZED 3
-
-namespace starboard {
-namespace shared {
-namespace starboard {
-
-bool EnsureInitialized(InitializedState* state) {
-  // Check what state we're in, and if we find that we are uninitialized,
-  // simultaneously mark us as initializing and return to the caller.
-  InitializedState original = SbAtomicNoBarrier_CompareAndSwap(
-      state, INITIALIZED_STATE_UNINITIALIZED, INITIALIZED_STATE_INITIALIZING);
-  if (original == INITIALIZED_STATE_UNINITIALIZED) {
-    // If we were uninitialized, we are now marked as initializing and so
-    // we relay this information to the caller, so that they may initialize.
-    return false;
-  } else if (original == INITIALIZED_STATE_INITIALIZING) {
-    // If the current state is that we are being initialized, spin until
-    // initialization is complete, then return.
-    do {
-      SbThreadYield();
-    } while (SbAtomicAcquire_Load(state) != INITIALIZED_STATE_INITIALIZED);
-  } else {
-    SB_DCHECK(original == INITIALIZED_STATE_INITIALIZED);
-  }
-
-  return true;
-}
-
-bool IsInitialized(InitializedState* state) {
-  return SbAtomicNoBarrier_Load(state) == INITIALIZED_STATE_INITIALIZED;
-}
-
-void SetInitialized(InitializedState* state) {
-  // Mark that we are initialized now.
-  SbAtomicRelease_Store(state, INITIALIZED_STATE_INITIALIZED);
-}
-
-}  // namespace starboard
-}  // namespace shared
-}  // namespace starboard
diff --git a/src/starboard/shared/starboard/lazy_initialization_internal.h b/src/starboard/shared/starboard/lazy_initialization_internal.h
index f1cd603..f3d8f49 100644
--- a/src/starboard/shared/starboard/lazy_initialization_internal.h
+++ b/src/starboard/shared/starboard/lazy_initialization_internal.h
@@ -16,8 +16,14 @@
 #define STARBOARD_SHARED_STARBOARD_LAZY_INITIALIZATION_INTERNAL_H_
 
 #include "starboard/atomic.h"
+#include "starboard/log.h"
 #include "starboard/shared/internal_only.h"
 #include "starboard/shared/starboard/lazy_initialization_public.h"
+#include "starboard/thread.h"
+
+// INITIALIZED_STATE_UNINITIALIZED is defined in the header.
+#define INITIALIZED_STATE_INITIALIZING 2
+#define INITIALIZED_STATE_INITIALIZED 3
 
 namespace starboard {
 namespace shared {
@@ -30,15 +36,40 @@
 // If false is returned, you must initialize the state (e.g. by eventually
 // calling SetInitialized() or else other threads waiting for initialization
 // to complete will wait forever.)
-bool EnsureInitialized(InitializedState* state);
+static SB_C_INLINE bool EnsureInitialized(InitializedState* state) {
+  // Check what state we're in, and if we find that we are uninitialized,
+  // simultaneously mark us as initializing and return to the caller.
+  InitializedState original = SbAtomicNoBarrier_CompareAndSwap(
+      state, INITIALIZED_STATE_UNINITIALIZED, INITIALIZED_STATE_INITIALIZING);
+  if (original == INITIALIZED_STATE_UNINITIALIZED) {
+    // If we were uninitialized, we are now marked as initializing and so
+    // we relay this information to the caller, so that they may initialize.
+    return false;
+  } else if (original == INITIALIZED_STATE_INITIALIZING) {
+    // If the current state is that we are being initialized, spin until
+    // initialization is complete, then return.
+    do {
+      SbThreadYield();
+    } while (SbAtomicAcquire_Load(state) != INITIALIZED_STATE_INITIALIZED);
+  } else {
+    SB_DCHECK(original == INITIALIZED_STATE_INITIALIZED);
+  }
+
+  return true;
+}
 
 // Returns true if the state is initialized, false otherwise.  Do not
 // use the outcome of this function to make a decision on whether to initialize
 // or not, use EnsureInitialized() for that.
-bool IsInitialized(InitializedState* state);
+static SB_C_INLINE bool IsInitialized(InitializedState* state) {
+  return SbAtomicNoBarrier_Load(state) == INITIALIZED_STATE_INITIALIZED;
+}
 
 // Sets the state as being initialized.
-void SetInitialized(InitializedState* state);
+static SB_C_INLINE void SetInitialized(InitializedState* state) {
+  // Mark that we are initialized now.
+  SbAtomicRelease_Store(state, INITIALIZED_STATE_INITIALIZED);
+}
 
 }  // namespace starboard
 }  // namespace shared
diff --git a/src/starboard/shared/starboard/lazy_initialization_public.h b/src/starboard/shared/starboard/lazy_initialization_public.h
index c4d7f8f..06d11e0 100644
--- a/src/starboard/shared/starboard/lazy_initialization_public.h
+++ b/src/starboard/shared/starboard/lazy_initialization_public.h
@@ -15,7 +15,7 @@
 #ifndef STARBOARD_SHARED_STARBOARD_LAZY_INITIALIZATION_PUBLIC_H_
 #define STARBOARD_SHARED_STARBOARD_LAZY_INITIALIZATION_PUBLIC_H_
 
-#include "starboard/atomic.h"
+#include "starboard/types.h"
 
 // The utility functions defined here use atomics and spin-locks to allow for
 // easy lazy initialization in a thread-safe way.
@@ -23,8 +23,10 @@
 // An InitializedState should be treated as an opaque type that can be
 // initialized to kInitializedStateUninitialized and then passed into the
 // functions in this file to transition it first to a "initializing" state and
-// then an "initialized" state.
-typedef SbAtomic32 InitializedState;
+// then an "initialized" state.  Note that this is intended to be used as a
+// SbAtomic32, however due to technical reasons we can't include
+// "starboard/atomic.h".
+typedef int32_t InitializedState;
 #define INITIALIZED_STATE_UNINITIALIZED 1
 
 #endif  // STARBOARD_SHARED_STARBOARD_LAZY_INITIALIZATION_PUBLIC_H_
diff --git a/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h b/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h
index 78f8fd0..265b64c 100644
--- a/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h
+++ b/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h
@@ -45,7 +45,8 @@
   // that a further call of Read() returns valid output until Reset() is called.
   // Note that |output_cb| is always called asynchronously on the calling job
   // queue.
-  virtual void Initialize(const Closure& output_cb) = 0;
+  virtual void Initialize(const Closure& output_cb,
+                          const Closure& error_cb) = 0;
 
   // Decode the encoded audio data stored in |input_buffer|.  Whenever the input
   // is consumed and the decoder is ready to accept a new input, it calls
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
index 18527b5..0b81764 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
@@ -106,8 +106,6 @@
     Schedule(log_frames_consumed_closure_, kSbTimeSecond);
   }
 
-  decoder_->Initialize(Bind(&AudioRendererImpl::OnDecoderOutput, this));
-
   // TODO: Initialize |time_stretcher_| after the first decoded audio output to
   // ensure that implicit HEAAC is properly handled.
   int source_sample_rate = decoder_->GetSamplesPerSecond();
@@ -124,6 +122,11 @@
   }
 }
 
+void AudioRendererImpl::Initialize(const Closure& error_cb) {
+  decoder_->Initialize(Bind(&AudioRendererImpl::OnDecoderOutput, this),
+                       error_cb);
+}
+
 void AudioRendererImpl::WriteSample(const InputBuffer& input_buffer) {
   SB_DCHECK(BelongsToCurrentThread());
   SB_DCHECK(can_accept_more_data_);
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
index ff4c29c..7ab3a0a 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
@@ -48,6 +48,7 @@
                     const SbMediaAudioHeader& audio_header);
   ~AudioRendererImpl() SB_OVERRIDE;
 
+  void Initialize(const Closure& error_cb) SB_OVERRIDE;
   void WriteSample(const InputBuffer& input_buffer) SB_OVERRIDE;
   void WriteEndOfStream() SB_OVERRIDE;
 
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal_test.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal_test.cc
index 3d387c5..9a53cb1 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal_test.cc
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal_test.cc
@@ -64,11 +64,12 @@
     storage_type_ = storage_type;
     audio_decoder_ = new MockAudioDecoder(sample_type_, storage_type_,
                                           kDefaultSamplesPerSecond);
-    EXPECT_CALL(*audio_decoder_, Initialize(_))
+    EXPECT_CALL(*audio_decoder_, Initialize(_, _))
         .WillOnce(SaveArg<0>(&output_cb_));
     audio_renderer_.reset(
         new AudioRendererImpl(make_scoped_ptr<AudioDecoder>(audio_decoder_),
                               GetDefaultAudioHeader()));
+    audio_renderer_->Initialize(Bind(&AudioRendererImplTest::OnError, this));
   }
 
   void WriteSample(InputBuffer input_buffer) {
@@ -127,6 +128,8 @@
     return decoded_audio;
   }
 
+  void OnError() {}
+
   SbMediaAudioSampleType sample_type_;
   SbMediaAudioFrameStorageType storage_type_;
 
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
index 17ff5d5..7bc93c9 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
@@ -15,8 +15,8 @@
 #ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_H_
 #define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_H_
 
-#include <vector>
-
+#include "starboard/common/ref_counted.h"
+#include "starboard/configuration.h"
 #include "starboard/media.h"
 #include "starboard/shared/internal_only.h"
 #include "starboard/shared/starboard/player/filter/audio_decoder_internal.h"
@@ -32,6 +32,9 @@
  public:
   virtual ~AudioRenderer() {}
 
+  virtual void Initialize(const Closure& error_cb) {
+    SB_UNREFERENCED_PARAMETER(error_cb);
+  }
   virtual void WriteSample(const InputBuffer& input_buffer) = 0;
   virtual void WriteEndOfStream() = 0;
   virtual void Play() = 0;
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
index 7f1825e..57e353b 100644
--- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
+++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
@@ -119,6 +119,10 @@
 
   audio_renderer_->SetPlaybackRate(playback_rate_);
   audio_renderer_->SetVolume(volume_);
+  audio_renderer_->Initialize(
+      Bind(&FilterBasedPlayerWorkerHandler::OnError, this));
+  video_renderer_->Initialize(
+      Bind(&FilterBasedPlayerWorkerHandler::OnError, this));
 
   job_queue_->Schedule(update_closure_, kUpdateInterval);
 
@@ -139,8 +143,8 @@
   }
 
   audio_renderer_->Pause();
-  audio_renderer_->Seek(seek_to_pts);
   video_renderer_->Seek(seek_to_pts);
+  audio_renderer_->Seek(seek_to_pts);
   return true;
 }
 
@@ -282,6 +286,15 @@
   return true;
 }
 
+void FilterBasedPlayerWorkerHandler::OnError() {
+  if (!job_queue_->BelongsToCurrentThread()) {
+    job_queue_->Schedule(Bind(&FilterBasedPlayerWorkerHandler::OnError, this));
+    return;
+  }
+
+  (*player_worker_.*update_player_state_cb_)(kSbPlayerStateError);
+}
+
 // TODO: This should be driven by callbacks instead polling.
 void FilterBasedPlayerWorkerHandler::Update() {
   SB_DCHECK(job_queue_->BelongsToCurrentThread());
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h
index e0d537f..7a3d2dd 100644
--- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h
+++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h
@@ -61,6 +61,7 @@
   void Stop() SB_OVERRIDE;
 
   void Update();
+  void OnError();
 
   SbDecodeTarget GetCurrentDecodeTarget() SB_OVERRIDE;
 
diff --git a/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h b/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h
index d1726c2..63ff9cf 100644
--- a/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h
+++ b/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h
@@ -42,7 +42,7 @@
         storage_type_(storage_type),
         samples_per_second_(sample_per_second) {}
 
-  MOCK_METHOD1(Initialize, void(const Closure&));
+  MOCK_METHOD2(Initialize, void(const Closure&, const Closure&));
   MOCK_METHOD2(Decode, void(const InputBuffer&, const Closure&));
   MOCK_METHOD0(WriteEndOfStream, void());
   MOCK_METHOD0(Read, scoped_refptr<DecodedAudio>());
diff --git a/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc b/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc
index 71f7aee..70a7fdb 100644
--- a/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc
+++ b/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc
@@ -46,7 +46,9 @@
       : sample_type_(GetSupportedSampleType()),
         audio_header_(audio_header),
         stream_ended_(false) {}
-  void Initialize(const Closure& output_cb) SB_OVERRIDE {
+  void Initialize(const Closure& output_cb,
+                  const Closure& error_cb) SB_OVERRIDE {
+    SB_UNREFERENCED_PARAMETER(error_cb);
     output_cb_ = output_cb;
   }
   void Decode(const InputBuffer& input_buffer,
diff --git a/src/starboard/shared/starboard/player/filter/video_decoder_internal.h b/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
index a5ac2be..ba3da5e 100644
--- a/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
@@ -15,8 +15,11 @@
 #ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_DECODER_INTERNAL_H_
 #define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_DECODER_INTERNAL_H_
 
+#include "starboard/common/ref_counted.h"
+#include "starboard/configuration.h"
 #include "starboard/player.h"
 #include "starboard/shared/internal_only.h"
+#include "starboard/shared/starboard/player/closure.h"
 #include "starboard/shared/starboard/player/input_buffer_internal.h"
 #include "starboard/shared/starboard/player/job_queue.h"
 #include "starboard/shared/starboard/player/video_frame_internal.h"
@@ -30,10 +33,16 @@
 // This class decodes encoded video stream into video frames.
 class VideoDecoder {
  public:
+  typedef ::starboard::shared::starboard::player::Closure Closure;
+
   enum Status { kNeedMoreInput, kBufferFull, kFatalError };
 
   virtual ~VideoDecoder() {}
 
+  virtual void Initialize(const Closure& error_cb) {
+    SB_UNREFERENCED_PARAMETER(error_cb);
+  }
+
   // Send encoded video frame stored in |input_buffer| to decode.
   virtual void WriteInputBuffer(const InputBuffer& input_buffer) = 0;
   // Note that there won't be more input data unless Reset() is called.
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
index bf6d1d4..1bbc5c2 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
@@ -15,11 +15,13 @@
 #ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_RENDERER_INTERNAL_H_
 #define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_RENDERER_INTERNAL_H_
 
-#include "starboard/common/scoped_ptr.h"
+#include "starboard/common/ref_counted.h"
+#include "starboard/configuration.h"
 #include "starboard/log.h"
 #include "starboard/media.h"
 #include "starboard/mutex.h"
 #include "starboard/shared/internal_only.h"
+#include "starboard/shared/starboard/player/closure.h"
 #include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
 #include "starboard/shared/starboard/player/input_buffer_internal.h"
 #include "starboard/shared/starboard/player/video_frame_internal.h"
@@ -33,8 +35,15 @@
 
 class VideoRenderer {
  public:
+  typedef ::starboard::shared::starboard::player::Closure Closure;
+
   virtual ~VideoRenderer() {}
 
+  // TODO: Refactor video pipeline error handling once VideoRenderers are
+  // unified.
+  virtual void Initialize(const Closure& error_cb) {
+    SB_UNREFERENCED_PARAMETER(error_cb);
+  }
   virtual int GetDroppedFrames() const = 0;
   virtual void WriteSample(const InputBuffer& input_buffer) = 0;
   virtual void WriteEndOfStream() = 0;
diff --git a/src/third_party/freetype2/src/cff/cffgload.c b/src/third_party/freetype2/src/cff/cffgload.c
index f7b5f9d..1b664c3 100644
--- a/src/third_party/freetype2/src/cff/cffgload.c
+++ b/src/third_party/freetype2/src/cff/cffgload.c
@@ -280,9 +280,11 @@
       {

         CFF_Internal  internal = (CFF_Internal)size->root.internal;

 

-

-        builder->hints_globals = (void *)internal->topfont;

-        builder->hints_funcs   = glyph->root.internal->glyph_hints;

+        if (internal)

+        {

+          builder->hints_globals = (void *)internal->topfont;

+          builder->hints_funcs   = glyph->root.internal->glyph_hints;

+        }

       }

     }

 

diff --git a/src/third_party/freetype2/src/psaux/psobjs.c b/src/third_party/freetype2/src/psaux/psobjs.c
index 2322667..3413da5 100644
--- a/src/third_party/freetype2/src/psaux/psobjs.c
+++ b/src/third_party/freetype2/src/psaux/psobjs.c
@@ -1718,6 +1718,14 @@
     first = outline->n_contours <= 1

             ? 0 : outline->contours[outline->n_contours - 2] + 1;

 

+    /* in malformed fonts it can happen that a contour was started */

+    /* but no points were added                                    */

+    if ( outline->n_contours && first == outline->n_points )

+    {

+      outline->n_contours--;

+      return;

+    }

+

     /* We must not include the last point in the path if it */

     /* is located on the first point.                       */

     if ( outline->n_points > 1 )

diff --git a/src/third_party/libxml/src/HTMLparser.c b/src/third_party/libxml/src/HTMLparser.c
index c7a0658..4421645 100644
--- a/src/third_party/libxml/src/HTMLparser.c
+++ b/src/third_party/libxml/src/HTMLparser.c
@@ -308,6 +308,7 @@
 #define UPP(val) (XML_TOUPPER(ctxt->input->cur[(val)]))
 
 #define CUR_PTR ctxt->input->cur
+#define BASE_PTR ctxt->input->base
 
 #define SHRINK if ((ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
 		   (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
@@ -2480,6 +2481,10 @@
 	       (*in == '_') || (*in == '-') ||
 	       (*in == ':') || (*in == '.'))
 	    in++;
+
+    if (in == ctxt->input->end)
+        return(NULL);
+
 	if ((*in > 0) && (*in < 0x80)) {
 	    count = in - ctxt->input->cur;
 	    ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
@@ -2523,6 +2528,10 @@
 	NEXTL(l);
 	c = CUR_CHAR(l);
     }
+
+    if (ctxt->input->base > ctxt->input->cur - len)
+        return(NULL);
+
     return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
 }
 
@@ -2774,31 +2783,43 @@
 
 static xmlChar *
 htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) {
-    const xmlChar *q;
+    size_t len = 0, startPosition = 0;
     xmlChar *ret = NULL;
 
     if (CUR == '"') {
         NEXT;
-	q = CUR_PTR;
-	while ((IS_CHAR_CH(CUR)) && (CUR != '"'))
-	    NEXT;
+
+    if (CUR_PTR < BASE_PTR)
+        return(ret);
+    startPosition = CUR_PTR - BASE_PTR;
+
+    while ((IS_CHAR_CH(CUR)) && (CUR != '"')) {
+        NEXT;
+        len++;
+    }
+
 	if (!IS_CHAR_CH(CUR)) {
 	    htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
 			 "Unfinished SystemLiteral\n", NULL, NULL);
 	} else {
-	    ret = xmlStrndup(q, CUR_PTR - q);
+	    ret = xmlStrndup((BASE_PTR+startPosition), len);
 	    NEXT;
         }
     } else if (CUR == '\'') {
         NEXT;
-	q = CUR_PTR;
-	while ((IS_CHAR_CH(CUR)) && (CUR != '\''))
-	    NEXT;
+	if (CUR_PTR < BASE_PTR)
+        return(ret);
+    startPosition = CUR_PTR - BASE_PTR;
+
+    while ((IS_CHAR_CH(CUR)) && (CUR != '\'')) {
+        NEXT;
+        len++;
+    }
 	if (!IS_CHAR_CH(CUR)) {
 	    htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
 			 "Unfinished SystemLiteral\n", NULL, NULL);
 	} else {
-	    ret = xmlStrndup(q, CUR_PTR - q);
+	    ret = xmlStrndup((BASE_PTR+startPosition), len);
 	    NEXT;
         }
     } else {
@@ -2822,32 +2843,44 @@
 
 static xmlChar *
 htmlParsePubidLiteral(htmlParserCtxtPtr ctxt) {
-    const xmlChar *q;
+    size_t len = 0, startPosition = 0;
     xmlChar *ret = NULL;
     /*
      * Name ::= (Letter | '_') (NameChar)*
      */
     if (CUR == '"') {
+    NEXT;
+	if (CUR_PTR < BASE_PTR)
+        return(ret);
+    startPosition = CUR_PTR - BASE_PTR;
+
+    while (IS_PUBIDCHAR_CH(CUR)) {
+        len++;
         NEXT;
-	q = CUR_PTR;
-	while (IS_PUBIDCHAR_CH(CUR)) NEXT;
-	if (CUR != '"') {
-	    htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
-	                 "Unfinished PubidLiteral\n", NULL, NULL);
-	} else {
-	    ret = xmlStrndup(q, CUR_PTR - q);
-	    NEXT;
-	}
+    }
+
+    if (CUR != '"') {
+       htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
+                    "Unfinished PubidLiteral\n", NULL, NULL);
+    } else {
+       ret = xmlStrndup((BASE_PTR + startPosition), len);
+       NEXT;
+    }
     } else if (CUR == '\'') {
         NEXT;
-	q = CUR_PTR;
-	while ((IS_PUBIDCHAR_CH(CUR)) && (CUR != '\''))
-	    NEXT;
+	if (CUR_PTR < BASE_PTR)
+            return(ret);
+        startPosition = CUR_PTR - BASE_PTR;
+
+        while ((IS_PUBIDCHAR_CH(CUR)) && (CUR != '\'')){
+            len++;
+            NEXT;
+        }
 	if (CUR != '\'') {
 	    htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
 	                 "Unfinished PubidLiteral\n", NULL, NULL);
 	} else {
-	    ret = xmlStrndup(q, CUR_PTR - q);
+	    ret = xmlStrndup((BASE_PTR + startPosition), len);
 	    NEXT;
 	}
     } else {
diff --git a/src/third_party/libxml/src/include/libxml/xmlstring.h b/src/third_party/libxml/src/include/libxml/xmlstring.h
index 2036236..eeaacb9 100644
--- a/src/third_party/libxml/src/include/libxml/xmlstring.h
+++ b/src/third_party/libxml/src/include/libxml/xmlstring.h
@@ -97,7 +97,7 @@
 XMLPUBFUN int XMLCALL
                 xmlStrPrintf             (xmlChar *buf,
                                          int len,
-                                         const xmlChar *msg,
+                                         const char *msg,
                                          ...);
 XMLPUBFUN int XMLCALL
                 xmlStrVPrintf                (xmlChar *buf,
diff --git a/src/third_party/libxml/src/parser.c b/src/third_party/libxml/src/parser.c
index b9e55aa..855b5ea 100644
--- a/src/third_party/libxml/src/parser.c
+++ b/src/third_party/libxml/src/parser.c
@@ -348,7 +348,6 @@
 xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
 {
     const char *errmsg;
-    char errstr[129] = "";
 
     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
         (ctxt->instate == XML_PARSER_EOF))
@@ -535,15 +534,17 @@
         default:
             errmsg = "Unregistered error message";
     }
-    if (info == NULL)
-        XML_SNPRINTF(errstr, 128, "%s\n", errmsg);
-    else
-        XML_SNPRINTF(errstr, 128, "%s: %%s\n", errmsg);
     if (ctxt != NULL)
 	ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
-                    XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, &errstr[0],
-                    info);
+    if (info == NULL) {
+        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
+                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s\n",
+                        errmsg);
+    } else {
+        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
+                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s: %s\n",
+                        errmsg, info);
+    }
     if (ctxt != NULL) {
 	ctxt->wellFormed = 0;
 	if (ctxt->recovery == 0)
@@ -559,7 +560,7 @@
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                const char *msg)
 {
@@ -587,7 +588,7 @@
  *
  * Handle a warning.
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
               const char *msg, const xmlChar *str1, const xmlChar *str2)
 {
@@ -625,7 +626,7 @@
  *
  * Handle a validity error.
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
               const char *msg, const xmlChar *str1, const xmlChar *str2)
 {
@@ -665,7 +666,7 @@
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, int val)
 {
@@ -695,7 +696,7 @@
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, const xmlChar *str1, int val,
 		  const xmlChar *str2)
@@ -725,7 +726,7 @@
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, const xmlChar * val)
 {
@@ -754,7 +755,7 @@
  *
  * Handle a non fatal parser error
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, const xmlChar * val)
 {
@@ -779,7 +780,7 @@
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
          const char *msg,
          const xmlChar * info1, const xmlChar * info2,
@@ -808,7 +809,7 @@
  *
  * Handle a namespace warning error
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
          const char *msg,
          const xmlChar * info1, const xmlChar * info2,
@@ -5481,7 +5482,7 @@
 	    skipped = SKIP_BLANKS;
 	    if (skipped == 0) {
 		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
-			       "Space required after '%'\n");
+			       "Space required after '%%'\n");
 	    }
 	    isParameter = 1;
 	}
@@ -6960,6 +6961,14 @@
 	    xmlParsePI(ctxt);
 	}
     }
+
+    /*
+     * detect requirement to exit there and act accordingly
+     * and avoid having instate overriden later on
+     */
+    if (ctxt->instate == XML_PARSER_EOF)
+        return;
+
     /*
      * This is only for internal subset. On external entities,
      * the replacement is done before parsing stage
@@ -7721,7 +7730,7 @@
      * not contain a <.
      */
     else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
-	     (ent != NULL) && 
+	     (ent != NULL) &&
 	     (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
 	if (((ent->checked & 1) || (ent->checked == 0)) &&
 	     (ent->content != NULL) && (xmlStrchr(ent->content, '<'))) {
@@ -8431,7 +8440,8 @@
      * We should be at the end of the DOCTYPE declaration.
      */
     if (RAW != '>') {
-	xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
+    	xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
+        return;
     }
     NEXT;
 }
@@ -9764,6 +9774,7 @@
 xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
                 const xmlChar *URI, int line, int nsNr, int tlen) {
     const xmlChar *name;
+    size_t curLength;
 
     GROW;
     if ((RAW != '<') || (NXT(1) != '/')) {
@@ -9772,8 +9783,11 @@
     }
     SKIP(2);
 
-    if ((tlen > 0) && (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
-        if (ctxt->input->cur[tlen] == '>') {
+    curLength = ctxt->input->end - ctxt->input->cur;
+    if ((tlen > 0) && (curLength >= (size_t)tlen) &&
+        (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
+        if ((curLength >= (size_t)(tlen + 1)) &&
+       (ctxt->input->cur[tlen] == '>')) {
 	    ctxt->input->cur += tlen + 1;
 	    ctxt->input->col += tlen + 1;
 	    goto done;
diff --git a/src/third_party/libxml/src/runtest.c b/src/third_party/libxml/src/runtest.c
index 02fe09a..2170449 100644
--- a/src/third_party/libxml/src/runtest.c
+++ b/src/third_party/libxml/src/runtest.c
@@ -1827,7 +1827,7 @@
     ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename);
     xmlCtxtUseOptions(ctxt, options);
     cur += 4;
-    while (cur < size) {
+    do {
         if (cur + 1024 >= size) {
 #ifdef LIBXML_HTML_ENABLED
 	    if (options & XML_PARSE_HTML)
@@ -1845,7 +1845,7 @@
 	    xmlParseChunk(ctxt, base + cur, 1024, 0);
 	    cur += 1024;
 	}
-    }
+    } while (cur < size);
     doc = ctxt->myDoc;
 #ifdef LIBXML_HTML_ENABLED
     if (options & XML_PARSE_HTML)
diff --git a/src/third_party/libxml/src/testModule.c b/src/third_party/libxml/src/testModule.c
index e399f5c..77b7ba1 100644
--- a/src/third_party/libxml/src/testModule.c
+++ b/src/third_party/libxml/src/testModule.c
@@ -47,7 +47,7 @@
 
     /* build the module filename, and confirm the module exists */
     xmlStrPrintf(filename, sizeof(filename),
-                 (const xmlChar*) "%s/testdso%s",
+                 "%s/testdso%s",
                  (const xmlChar*)MODULE_PATH,
 		 (const xmlChar*)LIBXML_MODULE_EXTENSION);
 
diff --git a/src/third_party/libxml/src/xmlIO.c b/src/third_party/libxml/src/xmlIO.c
index f0c0929..6d1fd67 100644
--- a/src/third_party/libxml/src/xmlIO.c
+++ b/src/third_party/libxml/src/xmlIO.c
@@ -1636,7 +1636,7 @@
 	xmlFreeZMemBuff( buff );
 	buff = NULL;
 	xmlStrPrintf(msg, 500,
-		    (const xmlChar *) "xmlCreateZMemBuff:  %s %d\n",
+		    "xmlCreateZMemBuff:  %s %d\n",
 		    "Error initializing compression context.  ZLIB error:",
 		    z_err );
 	xmlIOErr(XML_IO_WRITE, (const char *) msg);
diff --git a/src/third_party/libxml/src/xmlstring.c b/src/third_party/libxml/src/xmlstring.c
index 7b612bb..0a268fc 100644
--- a/src/third_party/libxml/src/xmlstring.c
+++ b/src/third_party/libxml/src/xmlstring.c
@@ -542,7 +542,7 @@
  * Returns the number of characters written to @buf or -1 if an error occurs.
  */
 int XMLCDECL
-xmlStrPrintf(xmlChar *buf, int len, const xmlChar *msg, ...) {
+xmlStrPrintf(xmlChar *buf, int len, const char *msg, ...) {
     va_list args;
     int ret;
 
diff --git a/src/third_party/libxml/src/xpath.c b/src/third_party/libxml/src/xpath.c
index 28d59a4..3f86055 100644
--- a/src/third_party/libxml/src/xpath.c
+++ b/src/third_party/libxml/src/xpath.c
@@ -641,7 +641,7 @@
             xmlChar buf[200];
 
             xmlStrPrintf(buf, 200,
-                         BAD_CAST "Memory allocation failed : %s\n",
+                         "Memory allocation failed : %s\n",
                          extra);
             ctxt->lastError.message = (char *) xmlStrdup(buf);
         } else {
diff --git a/src/third_party/openssl/openssl/crypto/asn1/a_type.c b/src/third_party/openssl/openssl/crypto/asn1/a_type.c
index 07164f1..2b84a77 100644
--- a/src/third_party/openssl/openssl/crypto/asn1/a_type.c
+++ b/src/third_party/openssl/openssl/crypto/asn1/a_type.c
@@ -129,9 +129,7 @@
         result = 0;             /* They do not have content. */
         break;
     case V_ASN1_INTEGER:
-    case V_ASN1_NEG_INTEGER:
     case V_ASN1_ENUMERATED:
-    case V_ASN1_NEG_ENUMERATED:
     case V_ASN1_BIT_STRING:
     case V_ASN1_OCTET_STRING:
     case V_ASN1_SEQUENCE:
diff --git a/src/third_party/openssl/openssl/crypto/asn1/tasn_dec.c b/src/third_party/openssl/openssl/crypto/asn1/tasn_dec.c
index 3dce02f..ee69b8f 100644
--- a/src/third_party/openssl/openssl/crypto/asn1/tasn_dec.c
+++ b/src/third_party/openssl/openssl/crypto/asn1/tasn_dec.c
@@ -906,9 +906,7 @@
         break;
 
     case V_ASN1_INTEGER:
-    case V_ASN1_NEG_INTEGER:
     case V_ASN1_ENUMERATED:
-    case V_ASN1_NEG_ENUMERATED:
         tint = (ASN1_INTEGER **)pval;
         if (!c2i_ASN1_INTEGER(tint, &cont, len))
             goto err;
diff --git a/src/third_party/openssl/openssl/crypto/asn1/tasn_enc.c b/src/third_party/openssl/openssl/crypto/asn1/tasn_enc.c
index 3ff086b..b257526 100644
--- a/src/third_party/openssl/openssl/crypto/asn1/tasn_enc.c
+++ b/src/third_party/openssl/openssl/crypto/asn1/tasn_enc.c
@@ -614,9 +614,7 @@
         break;
 
     case V_ASN1_INTEGER:
-    case V_ASN1_NEG_INTEGER:
     case V_ASN1_ENUMERATED:
-    case V_ASN1_NEG_ENUMERATED:
         /*
          * These are all have the same content format as ASN1_INTEGER
          */
diff --git a/src/third_party/openssl/openssl/crypto/bio/b_print.c b/src/third_party/openssl/openssl/crypto/bio/b_print.c
index a038966..5614ba9 100644
--- a/src/third_party/openssl/openssl/crypto/bio/b_print.c
+++ b/src/third_party/openssl/openssl/crypto/bio/b_print.c
@@ -73,9 +73,9 @@
 #include <ctype.h>
 #include <limits.h>
 #include <stdio.h>
-#include <string.h>
 #endif  // !defined(OPENSSL_SYS_STARBOARD)
 #include "cryptlib.h"
+#include <string.h>
 #ifndef NO_SYS_TYPES_H
 # include <sys/types.h>
 #endif
@@ -128,14 +128,14 @@
 # define LLONG long
 #endif
 
-static void fmtstr(char **, char **, size_t *, size_t *,
+static int fmtstr(char **, char **, size_t *, size_t *,
                    const char *, int, int, int);
-static void fmtint(char **, char **, size_t *, size_t *,
+static int fmtint(char **, char **, size_t *, size_t *,
                    LLONG, int, int, int, int);
-static void fmtfp(char **, char **, size_t *, size_t *,
+static int fmtfp(char **, char **, size_t *, size_t *,
                   LDOUBLE, int, int, int);
-static void doapr_outch(char **, char **, size_t *, size_t *, int);
-static void _dopr(char **sbuffer, char **buffer,
+static int doapr_outch(char **, char **, size_t *, size_t *, int);
+static int _dopr(char **sbuffer, char **buffer,
                   size_t *maxlen, size_t *retlen, int *truncated,
                   const char *format, va_list args);
 
@@ -168,7 +168,7 @@
 #define char_to_int(p) (p - '0')
 #define OSSL_MAX(p,q) ((p >= q) ? p : q)
 
-static void
+static int
 _dopr(char **sbuffer,
       char **buffer,
       size_t *maxlen,
@@ -199,7 +199,8 @@
             if (ch == '%')
                 state = DP_S_FLAGS;
             else
-                doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
+                if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
+                    return 0;
             ch = *format++;
             break;
         case DP_S_FLAGS:
@@ -305,8 +306,9 @@
                     value = va_arg(args, int);
                     break;
                 }
-                fmtint(sbuffer, buffer, &currlen, maxlen,
-                       value, 10, min, max, flags);
+                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
+                            max, flags))
+                    return 0;
                 break;
             case 'X':
                 flags |= DP_F_UP;
@@ -329,17 +331,19 @@
                     value = (LLONG) va_arg(args, unsigned int);
                     break;
                 }
-                fmtint(sbuffer, buffer, &currlen, maxlen, value,
-                       ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
-                       min, max, flags);
+                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
+                            ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
+                            min, max, flags))
+                    return 0;
                 break;
             case 'f':
                 if (cflags == DP_C_LDOUBLE)
                     fvalue = va_arg(args, LDOUBLE);
                 else
                     fvalue = va_arg(args, double);
-                fmtfp(sbuffer, buffer, &currlen, maxlen,
-                      fvalue, min, max, flags);
+                if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
+                           flags))
+                    return 0;
                 break;
             case 'E':
                 flags |= DP_F_UP;
@@ -358,8 +362,9 @@
                     fvalue = va_arg(args, double);
                 break;
             case 'c':
-                doapr_outch(sbuffer, buffer, &currlen, maxlen,
-                            va_arg(args, int));
+                if(!doapr_outch(sbuffer, buffer, &currlen, maxlen,
+                            va_arg(args, int)))
+                    return 0;
                 break;
             case 's':
                 strvalue = va_arg(args, char *);
@@ -369,13 +374,15 @@
                     else
                         max = *maxlen;
                 }
-                fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
-                       flags, min, max);
+                if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
+                            flags, min, max))
+                    return 0;
                 break;
             case 'p':
                 value = (long)va_arg(args, void *);
-                fmtint(sbuffer, buffer, &currlen, maxlen,
-                       value, 16, min, max, flags | DP_F_NUM);
+                if (!fmtint(sbuffer, buffer, &currlen, maxlen,
+                            value, 16, min, max, flags | DP_F_NUM))
+                    return 0;
                 break;
             case 'n':          /* XXX */
                 if (cflags == DP_C_SHORT) {
@@ -397,7 +404,8 @@
                 }
                 break;
             case '%':
-                doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
+                if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
+                    return 0;
                 break;
             case 'w':
                 /* not supported yet, treat as next char */
@@ -421,46 +429,56 @@
     *truncated = (currlen > *maxlen - 1);
     if (*truncated)
         currlen = *maxlen - 1;
-    doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0');
+    if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
+        return 0;
     *retlen = currlen - 1;
-    return;
+    return 1;
 }
 
-static void
+static int
 fmtstr(char **sbuffer,
        char **buffer,
        size_t *currlen,
        size_t *maxlen, const char *value, int flags, int min, int max)
 {
-    int padlen, strln;
+    int padlen;
+    size_t strln;
     int cnt = 0;
 
     if (value == 0)
         value = "<NULL>";
-    for (strln = 0; value[strln]; ++strln) ;
+
+    strln = strlen(value);
+    if (strln > INT_MAX)
+        strln = INT_MAX;
+
     padlen = min - strln;
-    if (padlen < 0)
+    if (min<0 || padlen < 0)
         padlen = 0;
     if (flags & DP_F_MINUS)
         padlen = -padlen;
 
     while ((padlen > 0) && (cnt < max)) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
+        if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
         --padlen;
         ++cnt;
     }
     while (*value && (cnt < max)) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, *value++);
+        if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
+            return 0;
         ++cnt;
     }
     while ((padlen < 0) && (cnt < max)) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
+        if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
         ++padlen;
         ++cnt;
     }
+    return 1;
 }
 
-static void
+static int
 fmtint(char **sbuffer,
        char **buffer,
        size_t *currlen,
@@ -520,37 +538,44 @@
 
     /* spaces */
     while (spadlen > 0) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
+        if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
         --spadlen;
     }
 
     /* sign */
     if (signvalue)
-        doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
+        if(!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
+            return 0;
 
     /* prefix */
     while (*prefix) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix);
+        if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
+            return 0;
         prefix++;
     }
 
     /* zeros */
     if (zpadlen > 0) {
         while (zpadlen > 0) {
-            doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
+            if(!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
+                return 0;
             --zpadlen;
         }
     }
     /* digits */
-    while (place > 0)
-        doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]);
+    while (place > 0) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
+            return 0;
+    }
 
     /* left justified spaces */
     while (spadlen < 0) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
         ++spadlen;
     }
-    return;
+    return 1;
 }
 
 static LDOUBLE abs_val(LDOUBLE value)
@@ -581,7 +606,7 @@
     return intpart;
 }
 
-static void
+static int
 fmtfp(char **sbuffer,
       char **buffer,
       size_t *currlen,
@@ -660,47 +685,62 @@
 
     if ((flags & DP_F_ZERO) && (padlen > 0)) {
         if (signvalue) {
-            doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
+            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
+                return 0;
             --padlen;
             signvalue = 0;
         }
         while (padlen > 0) {
-            doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
+            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
+                return 0;
             --padlen;
         }
     }
     while (padlen > 0) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
         --padlen;
     }
     if (signvalue)
-        doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
+            return 0;
 
-    while (iplace > 0)
-        doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]);
+    while (iplace > 0){
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]))
+            return 0;
+    }
 
     /*
      * Decimal point. This should probably use locale to find the correct
      * char to print out.
      */
     if (max > 0 || (flags & DP_F_NUM)) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, '.');
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.'))
+            return 0;
 
-        while (fplace > 0)
-            doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]);
+        while (fplace > 0) {
+            if(!doapr_outch(sbuffer, buffer, currlen, maxlen,
+                            fconvert[--fplace]))
+                return 0;
+        }
     }
     while (zpadlen > 0) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
+            return 0;
         --zpadlen;
     }
 
     while (padlen < 0) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
         ++padlen;
     }
+    return 1;
 }
 
-static void
+#define BUFFER_INC  1024
+
+static int
 doapr_outch(char **sbuffer,
             char **buffer, size_t *currlen, size_t *maxlen, int c)
 {
@@ -711,24 +751,25 @@
     OPENSSL_port_assert(*currlen <= *maxlen);
 
     if (buffer && *currlen == *maxlen) {
-        *maxlen += 1024;
+        if (*maxlen > INT_MAX - BUFFER_INC)
+            return 0;
+
+        *maxlen += BUFFER_INC;
         if (*buffer == NULL) {
             *buffer = OPENSSL_malloc(*maxlen);
-            if (!*buffer) {
-                /* Panic! Can't really do anything sensible. Just return */
-                return;
-            }
+            if (*buffer == NULL)
+                return 0;
             if (*currlen > 0) {
                 OPENSSL_port_assert(*sbuffer != NULL);
                 OPENSSL_port_memcpy(*buffer, *sbuffer, *currlen);
             }
             *sbuffer = NULL;
         } else {
-            *buffer = OPENSSL_realloc(*buffer, *maxlen);
-            if (!*buffer) {
-                /* Panic! Can't really do anything sensible. Just return */
-                return;
-            }
+            char *tmpbuf;
+            tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
+            if (tmpbuf == NULL)
+                return 0;
+            *buffer = tmpbuf;
         }
     }
 
@@ -739,7 +780,7 @@
             (*buffer)[(*currlen)++] = (char)c;
     }
 
-    return;
+    return 1;
 }
 
 /***************************************************************************/
@@ -771,7 +812,11 @@
 
     dynbuf = NULL;
     CRYPTO_push_info("doapr()");
-    _dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, args);
+    if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
+                args)) {
+        OPENSSL_free(dynbuf);
+        return -1;
+    }
     if (dynbuf) {
         ret = BIO_write(bio, dynbuf, (int)retlen);
         OPENSSL_free(dynbuf);
@@ -806,7 +851,8 @@
     size_t retlen;
     int truncated;
 
-    _dopr(&buf, NULL, &n, &retlen, &truncated, format, args);
+    if(!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
+        return -1;
 
     if (truncated)
         /*
diff --git a/src/third_party/openssl/openssl/crypto/mdc2/mdc2dgst.c b/src/third_party/openssl/openssl/crypto/mdc2/mdc2dgst.c
index 6615cf8..2dce493 100644
--- a/src/third_party/openssl/openssl/crypto/mdc2/mdc2dgst.c
+++ b/src/third_party/openssl/openssl/crypto/mdc2/mdc2dgst.c
@@ -91,7 +91,7 @@
 
     i = c->num;
     if (i != 0) {
-        if (i + len < MDC2_BLOCK) {
+        if (len < MDC2_BLOCK - i) {
             /* partial block */
             memcpy(&(c->data[i]), in, len);
             c->num += (int)len;