Import Cobalt 23.master.0.309200
diff --git a/cobalt/browser/on_screen_keyboard_starboard_bridge.cc b/cobalt/browser/on_screen_keyboard_starboard_bridge.cc
index 39b998c..969f822 100644
--- a/cobalt/browser/on_screen_keyboard_starboard_bridge.cc
+++ b/cobalt/browser/on_screen_keyboard_starboard_bridge.cc
@@ -96,5 +96,34 @@
   return SbWindowSetOnScreenKeyboardKeepFocus(sb_window_provider_.Run(),
                                               keep_focus);
 }
+
+void OnScreenKeyboardStarboardBridge::SetBackgroundColor(
+    const char* background_color) {
+  const CobaltExtensionOnScreenKeyboardApi* on_screen_keyboard_extension =
+      static_cast<const CobaltExtensionOnScreenKeyboardApi*>(
+          SbSystemGetExtension(kCobaltExtensionOnScreenKeyboardName));
+
+  if (on_screen_keyboard_extension &&
+      strcmp(on_screen_keyboard_extension->name,
+             kCobaltExtensionOnScreenKeyboardName) == 0 &&
+      on_screen_keyboard_extension->version >= 1) {
+    on_screen_keyboard_extension->SetBackgroundColor(sb_window_provider_.Run(),
+                                                     background_color);
+  }
+}
+
+void OnScreenKeyboardStarboardBridge::SetDarkTheme(bool dark_theme) {
+  const CobaltExtensionOnScreenKeyboardApi* on_screen_keyboard_extension =
+      static_cast<const CobaltExtensionOnScreenKeyboardApi*>(
+          SbSystemGetExtension(kCobaltExtensionOnScreenKeyboardName));
+
+  if (on_screen_keyboard_extension &&
+      strcmp(on_screen_keyboard_extension->name,
+             kCobaltExtensionOnScreenKeyboardName) == 0 &&
+      on_screen_keyboard_extension->version >= 1) {
+    on_screen_keyboard_extension->SetDarkTheme(sb_window_provider_.Run(),
+                                               dark_theme);
+  }
+}
 }  // namespace browser
 }  // namespace cobalt
diff --git a/cobalt/browser/on_screen_keyboard_starboard_bridge.h b/cobalt/browser/on_screen_keyboard_starboard_bridge.h
index f73cc11..6ee9a70 100644
--- a/cobalt/browser/on_screen_keyboard_starboard_bridge.h
+++ b/cobalt/browser/on_screen_keyboard_starboard_bridge.h
@@ -19,6 +19,7 @@
 
 #include "base/callback.h"
 #include "cobalt/dom/on_screen_keyboard_bridge.h"
+#include "cobalt/extension/on_screen_keyboard.h"
 #include "starboard/window.h"
 
 namespace cobalt {
@@ -58,6 +59,10 @@
 
   void SetKeepFocus(bool keep_focus) override;
 
+  void SetBackgroundColor(const char* background_color) override;
+
+  void SetDarkTheme(bool dark_theme) override;
+
  private:
   base::Callback<SbWindow()> sb_window_provider_;
 };
diff --git a/cobalt/demos/content/BUILD.gn b/cobalt/demos/content/BUILD.gn
index 9e6b742..e9f5d09 100644
--- a/cobalt/demos/content/BUILD.gn
+++ b/cobalt/demos/content/BUILD.gn
@@ -111,8 +111,6 @@
 
   if (is_internal_build) {
     sources += [
-      "internal/runtime-dump.html",
-      "javascript-fuzzer/index.html",
       "media-element-demo/public/assets/ac3.mp4",
       "media-element-demo/public/assets/dash-audio.mp4",
       "media-element-demo/public/assets/dash-video-1080p.mp4",
@@ -125,86 +123,6 @@
       "media-element-demo/public/assets/progressive.mp4",
       "mtm-demo/README.txt",
       "mtm-demo/progressive.mp4",
-      "performance-spike/assets/Roboto-Regular.ttf",
-      "performance-spike/assets/banner.jpg",
-      "performance-spike/assets/banner1080.jpg",
-      "performance-spike/assets/banner1080baked.jpg",
-      "performance-spike/assets/banner1080withLinearGradient.jpg",
-      "performance-spike/assets/banner720.jpg",
-      "performance-spike/assets/banner720baked.jpg",
-      "performance-spike/assets/icons.ttf",
-      "performance-spike/css/default.css",
-      "performance-spike/css/icons-content.css",
-      "performance-spike/css/icons.css",
-      "performance-spike/di/injector.js",
-      "performance-spike/di/mapping.js",
-      "performance-spike/di/resolver.js",
-      "performance-spike/index.html",
-      "performance-spike/namespace.js",
-      "performance-spike/runtime-dump.html",
-      "performance-spike/spike/anim/_config.js",
-      "performance-spike/spike/anim/alignment.js",
-      "performance-spike/spike/anim/centering.js",
-      "performance-spike/spike/anim/cssanimations/_config.js",
-      "performance-spike/spike/anim/cssanimations/animationbuilder.js",
-      "performance-spike/spike/anim/cssanimations/centering.js",
-      "performance-spike/spike/anim/cssanimations/rows.js",
-      "performance-spike/spike/anim/csstransitions/_config.js",
-      "performance-spike/spike/anim/csstransitions/centering.js",
-      "performance-spike/spike/anim/csstransitions/rows.js",
-      "performance-spike/spike/anim/csstransitions/transitionbuilder.js",
-      "performance-spike/spike/anim/rows.js",
-      "performance-spike/spike/anim/transformer/_config.js",
-      "performance-spike/spike/anim/transformer/centering.js",
-      "performance-spike/spike/anim/transformer/ease.js",
-      "performance-spike/spike/anim/transformer/rows.js",
-      "performance-spike/spike/anim/transformer/transformer.js",
-      "performance-spike/spike/anim/tweens/_config.js",
-      "performance-spike/spike/anim/tweens/centering.js",
-      "performance-spike/spike/anim/tweens/rows.js",
-      "performance-spike/spike/anim/tweens/tweens.js",
-      "performance-spike/spike/behavior/_config.js",
-      "performance-spike/spike/behavior/body.js",
-      "performance-spike/spike/behavior/buttons.js",
-      "performance-spike/spike/behavior/column.js",
-      "performance-spike/spike/behavior/content.js",
-      "performance-spike/spike/behavior/cssfocused.js",
-      "performance-spike/spike/behavior/factory.js",
-      "performance-spike/spike/behavior/header.js",
-      "performance-spike/spike/behavior/headerbuttons.js",
-      "performance-spike/spike/behavior/item.js",
-      "performance-spike/spike/behavior/main.js",
-      "performance-spike/spike/behavior/menu.js",
-      "performance-spike/spike/behavior/navigate.js",
-      "performance-spike/spike/behavior/row.js",
-      "performance-spike/spike/core/_config.js",
-      "performance-spike/spike/core/environment.js",
-      "performance-spike/spike/core/experiments.js",
-      "performance-spike/spike/core/fps.js",
-      "performance-spike/spike/core/location.js",
-      "performance-spike/spike/core/math.js",
-      "performance-spike/spike/core/rollingmean.js",
-      "performance-spike/spike/core/styles.js",
-      "performance-spike/spike/core/throttlefactory.js",
-      "performance-spike/spike/core/ticker.js",
-      "performance-spike/spike/ctrl/_config.js",
-      "performance-spike/spike/ctrl/behaviors.js",
-      "performance-spike/spike/ctrl/factory.js",
-      "performance-spike/spike/ctrl/focuser.js",
-      "performance-spike/spike/ctrl/hbox.js",
-      "performance-spike/spike/ctrl/keyhandler.js",
-      "performance-spike/spike/ctrl/leaf.js",
-      "performance-spike/spike/ctrl/vbox.js",
-      "performance-spike/spike/data/_config.js",
-      "performance-spike/spike/data/channel_crash_course.js",
-      "performance-spike/spike/data/menu.js",
-      "performance-spike/spike/data/menu_content.js",
-      "performance-spike/spike/data/update.js",
-      "performance-spike/spike/factory/_config.js",
-      "performance-spike/spike/factory/itemfactory.js",
-      "performance-spike/spike/factory/menufactory.js",
-      "performance-spike/spike/factory/rowfactory.js",
-      "performance-spike/spike/main.js",
       "text-encoding-workaround/text-encoding-workaround.html",
     ]
   }
diff --git a/cobalt/dom/BUILD.gn b/cobalt/dom/BUILD.gn
index 79ed564..ff47acc 100644
--- a/cobalt/dom/BUILD.gn
+++ b/cobalt/dom/BUILD.gn
@@ -261,7 +261,6 @@
     "screenshot.h",
     "screenshot_manager.cc",
     "screenshot_manager.h",
-    "serialized_algorithm_runner.cc",
     "serialized_algorithm_runner.h",
     "serializer.cc",
     "serializer.h",
diff --git a/cobalt/dom/html_script_element.cc b/cobalt/dom/html_script_element.cc
index e003c03..42f7997 100644
--- a/cobalt/dom/html_script_element.cc
+++ b/cobalt/dom/html_script_element.cc
@@ -78,6 +78,18 @@
   DCHECK(document->html_element_context()->script_runner());
 }
 
+std::string HTMLScriptElement::src() const {
+  auto src = GetAttribute("src");
+  if (!src.has_value()) {
+    return "";
+  }
+  if (!node_document()) {
+    return src.value();
+  }
+  const GURL& base_url = node_document()->location()->url();
+  return base_url.Resolve(src.value()).spec();
+}
+
 base::Optional<std::string> HTMLScriptElement::cross_origin() const {
   base::Optional<std::string> cross_origin_attribute =
       GetAttribute("crossOrigin");
@@ -217,7 +229,11 @@
   //   1. Let src be the value of the element's src attribute.
   //   2. If src is the empty string, queue a task to fire a simple event
   // named error at the element, and abort these steps.
-  if (HasAttribute("src") && src() == "") {
+  //
+  // Need to use the "src" attribute. The |src| property is fully resolved. See
+  // header file for details.
+  auto src = GetAttribute("src").value_or("");
+  if (HasAttribute("src") && src == "") {
     LOG(ERROR) << "src attribute of script element is empty.";
 
     PreventGarbageCollectionAndPostToDispatchEvent(
@@ -230,9 +246,9 @@
   //   4. If the previous step failed, queue a task to fire a simple event named
   // error at the element, and abort these steps.
   const GURL& base_url = document_->location()->url();
-  url_ = base_url.Resolve(src());
+  url_ = base_url.Resolve(src);
   if (!url_.is_valid()) {
-    LOG(ERROR) << src() << " cannot be resolved based on " << base_url << ".";
+    LOG(ERROR) << src << " cannot be resolved based on " << base_url << ".";
 
     PreventGarbageCollectionAndPostToDispatchEvent(
         FROM_HERE, base::Tokens::error(),
@@ -267,7 +283,7 @@
              "bugs, it is recommended to use JavaScript to create a "
              "script element and load it async. The <script> reference "
              "appears at: \""
-          << inline_script_location_ << "\" and its src is \"" << src() << "\"";
+          << inline_script_location_ << "\" and its src is \"" << src << "\"";
     }
 
     load_option_ = 2;
diff --git a/cobalt/dom/html_script_element.h b/cobalt/dom/html_script_element.h
index 3c9740e..f5537fd 100644
--- a/cobalt/dom/html_script_element.h
+++ b/cobalt/dom/html_script_element.h
@@ -42,7 +42,13 @@
 
   // Web API: HTMLScriptElement
   //
-  std::string src() const { return GetAttribute("src").value_or(""); }
+  // If the "src" attribute is a relative URL, the |src| property returns a
+  // fully resolved URL used the |document.location.href| as the base URL. This
+  // matches the Chrome implementation of the |src| property.
+  // See:
+  //   https://source.chromium.org/chromium/chromium/src/+/main:out/Debug/gen/third_party/blink/renderer/bindings/core/v8/v8_html_script_element.cc;l=93;drc=4f7206c7352efba617f4561cd8c95844d9e9814f
+  //   https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/dom/element.cc;l=7360;drc=5f6702f8b8f9da8510d2b3ec809e177e6db09e53
+  std::string src() const;
   void set_src(const std::string& value) { SetAttribute("src", value); }
 
   std::string type() const { return GetAttribute("type").value_or(""); }
diff --git a/cobalt/dom/media_source.cc b/cobalt/dom/media_source.cc
index f9f2c05..1dcc7d3 100644
--- a/cobalt/dom/media_source.cc
+++ b/cobalt/dom/media_source.cc
@@ -83,13 +83,14 @@
 // If the system has more processors than the specified value, SourceBuffer
 // append and remove algorithm will be offloaded to a non-web thread to reduce
 // the load on the web thread.
-// The default value is 2.  Set to a reasonably high value (say 1024) will
-// disable algorithm offloading completely.
+// The default value is 1024, which effectively disable offloading by default.
+// Setting to a reasonably low value (say 0 or 2) will enable algorithm
+// offloading.
 bool IsAlgorithmOffloadEnabled(script::EnvironmentSettings* settings) {
   int min_process_count_to_offload =
       GetMediaSettings(settings)
           ->GetMinimumProcessorCountToOffloadAlgorithm()
-          .value_or(2);
+          .value_or(1024);
   DCHECK_GE(min_process_count_to_offload, 0);
   return SbSystemGetNumberOfProcessors() >= min_process_count_to_offload;
 }
@@ -97,10 +98,10 @@
 // If this function returns true, SourceBuffer will reduce asynchronous
 // behaviors.  For example, queued events will be dispatached immediately when
 // possible.
-// The default value is true.
+// The default value is false.
 bool IsAsynchronousReductionEnabled(script::EnvironmentSettings* settings) {
   return GetMediaSettings(settings)->IsAsynchronousReductionEnabled().value_or(
-      true);
+      false);
 }
 
 // If the size of a job that is part of an algorithm is less than or equal to
@@ -390,9 +391,10 @@
 
   if (algorithm_process_thread_) {
     LOG(INFO) << "Algorithm offloading enabled.";
-    offload_algorithm_runner_.reset(new OffloadAlgorithmRunner(
-        algorithm_process_thread_->message_loop()->task_runner(),
-        base::MessageLoop::current()->task_runner()));
+    offload_algorithm_runner_.reset(
+        new OffloadAlgorithmRunner<SourceBufferAlgorithm>(
+            algorithm_process_thread_->message_loop()->task_runner(),
+            base::MessageLoop::current()->task_runner()));
   } else {
     LOG(INFO) << "Algorithm offloading disabled.";
   }
@@ -574,7 +576,8 @@
   return has_max_video_capabilities_;
 }
 
-SerializedAlgorithmRunner* MediaSource::GetAlgorithmRunner(int job_size) {
+SerializedAlgorithmRunner<SourceBufferAlgorithm>*
+MediaSource::GetAlgorithmRunner(int job_size) {
   if (!offload_algorithm_runner_) {
     return &default_algorithm_runner_;
   }
diff --git a/cobalt/dom/media_source.h b/cobalt/dom/media_source.h
index bfe0774..65ab2a8 100644
--- a/cobalt/dom/media_source.h
+++ b/cobalt/dom/media_source.h
@@ -59,6 +59,7 @@
 #include "cobalt/dom/media_source_ready_state.h"
 #include "cobalt/dom/serialized_algorithm_runner.h"
 #include "cobalt/dom/source_buffer.h"
+#include "cobalt/dom/source_buffer_algorithm.h"
 #include "cobalt/dom/source_buffer_list.h"
 #include "cobalt/dom/time_ranges.h"
 #include "cobalt/dom/video_track.h"
@@ -126,7 +127,8 @@
   void SetSourceBufferActive(SourceBuffer* source_buffer, bool is_active);
   HTMLMediaElement* GetMediaElement() const;
   bool MediaElementHasMaxVideoCapabilities() const;
-  SerializedAlgorithmRunner* GetAlgorithmRunner(int job_size);
+  SerializedAlgorithmRunner<SourceBufferAlgorithm>* GetAlgorithmRunner(
+      int job_size);
 
   DEFINE_WRAPPABLE_TYPE(MediaSource);
   void TraceMembers(script::Tracer* tracer) override;
@@ -148,9 +150,10 @@
   const int min_size_for_immediate_job_;
 
   // The default algorithm runner runs all steps on the web thread.
-  DefaultAlgorithmRunner default_algorithm_runner_;
+  DefaultAlgorithmRunner<SourceBufferAlgorithm> default_algorithm_runner_;
   // The offload algorithm runner offloads some steps to a non-web thread.
-  std::unique_ptr<OffloadAlgorithmRunner> offload_algorithm_runner_;
+  std::unique_ptr<OffloadAlgorithmRunner<SourceBufferAlgorithm>>
+      offload_algorithm_runner_;
   std::unique_ptr<base::Thread> algorithm_process_thread_;
 
   ChunkDemuxer* chunk_demuxer_;
diff --git a/cobalt/dom/on_screen_keyboard.cc b/cobalt/dom/on_screen_keyboard.cc
index 54c2242..188aa1e 100644
--- a/cobalt/dom/on_screen_keyboard.cc
+++ b/cobalt/dom/on_screen_keyboard.cc
@@ -46,6 +46,14 @@
           .second;
   DCHECK(is_emplaced);
   bridge_->Show(data_.c_str(), ticket);
+
+  if (background_color_.has_value()) {
+    bridge_->SetBackgroundColor(background_color_.value().c_str());
+  }
+  if (dark_theme_.has_value()) {
+    bridge_->SetDarkTheme(dark_theme_.value());
+  }
+
   return promise;
 }
 
diff --git a/cobalt/dom/on_screen_keyboard.h b/cobalt/dom/on_screen_keyboard.h
index 8690c95..ce7d0fa 100644
--- a/cobalt/dom/on_screen_keyboard.h
+++ b/cobalt/dom/on_screen_keyboard.h
@@ -99,6 +99,18 @@
   void set_keep_focus(bool keep_focus);
   bool keep_focus() const { return keep_focus_; }
 
+  void set_background_color(base::Optional<std::string>& background_color) {
+    background_color_ = background_color;
+  }
+  base::Optional<std::string> background_color() const {
+    return background_color_;
+  }
+
+  void set_dark_theme(base::Optional<bool> dark_theme) {
+    dark_theme_ = dark_theme;
+  }
+  base::Optional<bool> dark_theme() const { return dark_theme_; }
+
   // Called by the WebModule to dispatch DOM show, hide, focus, blur and
   // suggestions updated events.
   void DispatchHideEvent(int ticket);
@@ -135,6 +147,10 @@
 
   bool suggestions_supported_;
 
+  base::Optional<std::string> background_color_;
+
+  base::Optional<bool> dark_theme_;
+
   DISALLOW_COPY_AND_ASSIGN(OnScreenKeyboard);
 };
 }  // namespace dom
diff --git a/cobalt/dom/on_screen_keyboard.idl b/cobalt/dom/on_screen_keyboard.idl
index ebe632c..fe13887 100644
--- a/cobalt/dom/on_screen_keyboard.idl
+++ b/cobalt/dom/on_screen_keyboard.idl
@@ -43,4 +43,15 @@
   attribute EventHandler onfocus;
   attribute EventHandler onblur;
   attribute EventHandler oninput;
+
+  // This attribute overrides the background color of on-screen keyboard.
+  // The attribute is only fully supported on Apple TV at the moment.
+  // backgroundColor should be a string of below formats:
+  // 1. hex color notation #RRGGBB, e.g. "#0000FF".
+  // 2. rgb color notation rgb(R, G, B), e.g. "rgb(0, 0, 255)".
+  attribute DOMString? backgroundColor;
+
+  // This attribute overrides the dark theme of on-screen keyboard.
+  // The attribute is only fully supported on Apple TV at the moment.
+  attribute boolean? darkTheme;
 };
diff --git a/cobalt/dom/on_screen_keyboard_bridge.h b/cobalt/dom/on_screen_keyboard_bridge.h
index d58c0ad..c5623af 100644
--- a/cobalt/dom/on_screen_keyboard_bridge.h
+++ b/cobalt/dom/on_screen_keyboard_bridge.h
@@ -39,6 +39,8 @@
   virtual scoped_refptr<DOMRect> BoundingRect() const = 0;
   virtual void SetKeepFocus(bool keep_focus) = 0;
   virtual bool IsValidTicket(int ticket) const = 0;
+  virtual void SetBackgroundColor(const char* background_color) = 0;
+  virtual void SetDarkTheme(bool dark_theme) = 0;
 };
 
 }  // namespace dom
diff --git a/cobalt/dom/on_screen_keyboard_test.cc b/cobalt/dom/on_screen_keyboard_test.cc
index 4ab1e6f..fd616a3 100644
--- a/cobalt/dom/on_screen_keyboard_test.cc
+++ b/cobalt/dom/on_screen_keyboard_test.cc
@@ -112,6 +112,10 @@
 
   void SetKeepFocus(bool keep_focus) override { SetKeepFocusMock(keep_focus); }
 
+  void SetBackgroundColor(const char* background_color) override {}
+
+  void SetDarkTheme(bool dark_theme) override {}
+
   MOCK_METHOD1(ShowMock, void(std::string));
   MOCK_METHOD0(HideMock, void());
   MOCK_METHOD0(BlurMock, void());
@@ -604,5 +608,49 @@
   EXPECT_TRUE(EvaluateScript(script, NULL));
 }
 
+TEST_F(OnScreenKeyboardTest, SetBackgroundColor) {
+  if (SkipLocale()) return;
+
+  std::string result;
+  EXPECT_TRUE(
+      EvaluateScript("window.onScreenKeyboard.backgroundColor;", &result));
+  EXPECT_EQ("null", result);
+
+  std::string color_str = "#0000FF";
+  EXPECT_TRUE(EvaluateScript("window.onScreenKeyboard.backgroundColor = '" +
+                                 color_str +
+                                 "';"
+                                 "window.onScreenKeyboard.backgroundColor",
+                             &result));
+
+  EXPECT_EQ(color_str, result);
+
+  color_str = "rgb(0, 0, 100)";
+  EXPECT_TRUE(EvaluateScript("window.onScreenKeyboard.backgroundColor = '" +
+                                 color_str +
+                                 "';"
+                                 "window.onScreenKeyboard.backgroundColor",
+                             &result));
+
+  EXPECT_EQ(color_str, result);
+}
+
+TEST_F(OnScreenKeyboardTest, SetDarkTheme) {
+  if (SkipLocale()) return;
+
+  std::string result;
+  EXPECT_TRUE(EvaluateScript("window.onScreenKeyboard.darkTheme;", &result));
+  EXPECT_EQ("null", result);
+
+  std::string dark_theme_str = "false";
+  EXPECT_TRUE(
+      EvaluateScript("window.onScreenKeyboard.darkTheme = " + dark_theme_str +
+                         ";"
+                         "window.onScreenKeyboard.darkTheme",
+                     &result));
+
+  EXPECT_EQ(dark_theme_str, result);
+}
+
 }  // namespace dom
 }  // namespace cobalt
diff --git a/cobalt/dom/serialized_algorithm_runner.cc b/cobalt/dom/serialized_algorithm_runner.cc
deleted file mode 100644
index 07dece0..0000000
--- a/cobalt/dom/serialized_algorithm_runner.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2022 The Cobalt Authors. 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 "cobalt/dom/serialized_algorithm_runner.h"
-
-#include "base/message_loop/message_loop.h"
-
-namespace cobalt {
-namespace dom {
-
-void DefaultAlgorithmRunner::Start(const scoped_refptr<HandleBase>& handle) {
-  DCHECK(handle);
-  TRACE_EVENT0("cobalt::dom", "DefaultAlgorithmRunner::Start()");
-
-  if (asynchronous_reduction_enabled_) {
-    Process(handle);
-    return;
-  }
-
-  auto task_runner = base::MessageLoop::current()->task_runner();
-  task_runner->PostTask(FROM_HERE,
-                        base::BindOnce(&DefaultAlgorithmRunner::Process,
-                                       base::Unretained(this), handle));
-}
-
-void DefaultAlgorithmRunner::Process(const scoped_refptr<HandleBase>& handle) {
-  DCHECK(handle);
-  TRACE_EVENT0("cobalt::dom", "DefaultAlgorithmRunner::Process()");
-
-  auto task_runner = base::MessageLoop::current()->task_runner();
-
-  bool finished = false;
-  handle->Process(&finished);
-
-  if (finished) {
-    handle->Finalize();
-    return;
-  }
-  task_runner->PostTask(FROM_HERE,
-                        base::BindOnce(&DefaultAlgorithmRunner::Process,
-                                       base::Unretained(this), handle));
-}
-
-OffloadAlgorithmRunner::OffloadAlgorithmRunner(
-    const scoped_refptr<TaskRunner>& process_task_runner,
-    const scoped_refptr<TaskRunner>& finalize_task_runner)
-    : process_task_runner_(process_task_runner),
-      finalize_task_runner_(finalize_task_runner) {
-  DCHECK(process_task_runner_);
-  DCHECK(finalize_task_runner_);
-  DCHECK_NE(process_task_runner_, finalize_task_runner_);
-}
-
-void OffloadAlgorithmRunner::Start(const scoped_refptr<HandleBase>& handle) {
-  DCHECK(handle);
-
-  TRACE_EVENT0("cobalt::dom", "OffloadAlgorithmRunner::Start()");
-
-  process_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&OffloadAlgorithmRunner::Process,
-                                base::Unretained(this), handle));
-}
-
-void OffloadAlgorithmRunner::Process(const scoped_refptr<HandleBase>& handle) {
-  DCHECK(handle);
-  DCHECK(process_task_runner_->BelongsToCurrentThread());
-
-  TRACE_EVENT0("cobalt::dom", "OffloadAlgorithmRunner::Process()");
-
-  bool finished = false;
-  handle->Process(&finished);
-
-  if (finished) {
-    finalize_task_runner_->PostTask(
-        FROM_HERE, base::BindOnce(&HandleBase::Finalize, handle));
-    return;
-  }
-  process_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&OffloadAlgorithmRunner::Process,
-                                base::Unretained(this), handle));
-}
-
-}  // namespace dom
-}  // namespace cobalt
diff --git a/cobalt/dom/serialized_algorithm_runner.h b/cobalt/dom/serialized_algorithm_runner.h
index d4c2b39..db625ad 100644
--- a/cobalt/dom/serialized_algorithm_runner.h
+++ b/cobalt/dom/serialized_algorithm_runner.h
@@ -22,6 +22,7 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/trace_event/trace_event.h"
 #include "starboard/common/mutex.h"
@@ -53,37 +54,56 @@
 // This class will keep calling Process() until |finished| becomes false, and
 // then call Finalize().  It guarantees that all calls won't be overlapped and
 // the member functions of the algorithm don't have to synchronize between them.
+template <typename SerializedAlgorithm>
 class SerializedAlgorithmRunner {
  public:
-  // Abstract the non-template part of the Handle class, and shouldn't be used
-  // directly.
-  class HandleBase : public base::RefCountedThreadSafe<HandleBase> {
-   public:
-    virtual ~HandleBase() {}
-
-    virtual void Process(bool* finished) = 0;
-    virtual void Finalize() = 0;
-  };
-
   // A handle object for a running algorithm instance, to allow for aborting and
   // access the algorithm.
-  template <typename SerializedAlgorithm>
-  class Handle : public HandleBase {
+  class Handle : public base::RefCountedThreadSafe<Handle> {
    public:
-    explicit Handle(std::unique_ptr<SerializedAlgorithm> algorithm);
-
     // Abort the algorithm and no more processing will happen on return.  It is
     // possible that Process() has already finished asynchronously, in which
     // case this function will call Finalize() instead (if it hasn't been called
     // yet).
     void Abort();
+    void Process(bool* finished);
+    void FinalizeIfNotAborted();
+
     SerializedAlgorithm* algorithm() const { return algorithm_.get(); }
 
    private:
-    void Process(bool* finished) override;
-    void Finalize() override;
+    friend class SerializedAlgorithmRunner;
 
-    // The |mutex_| is necessary as `Abort()` can be called from any thread.
+    // Provide synchronization only when |synchronization_required| is true.
+    // This allows bypassing of synchronization for algorithm runners that
+    // operate on a single thread, where a mutex could be reentrant if acquired
+    // due to nested calls.
+    class ScopedLockWhenRequired {
+     public:
+      ScopedLockWhenRequired(bool synchronization_required,
+                             const starboard::Mutex& mutex)
+          : synchronization_required_(synchronization_required), mutex_(mutex) {
+        if (synchronization_required_) {
+          mutex_.Acquire();
+        }
+      }
+      ~ScopedLockWhenRequired() {
+        if (synchronization_required_) {
+          mutex_.Release();
+        }
+      }
+
+     private:
+      const bool synchronization_required_;
+      const starboard::Mutex& mutex_;
+    };
+
+    Handle(bool synchronization_required,
+           std::unique_ptr<SerializedAlgorithm> algorithm);
+
+    // The |mutex_| is necessary for algorithm runners operate on multiple
+    // threads as `Abort()` can be called from any thread.
+    const bool synchronization_required_;
     starboard::Mutex mutex_;
     std::unique_ptr<SerializedAlgorithm> algorithm_;
     bool aborted_ = false;
@@ -93,21 +113,32 @@
 
   virtual ~SerializedAlgorithmRunner() {}
 
-  virtual void Start(const scoped_refptr<HandleBase>& handle) = 0;
+  virtual scoped_refptr<Handle> CreateHandle(
+      std::unique_ptr<SerializedAlgorithm> algorithm) = 0;
+  virtual void Start(scoped_refptr<Handle> handle) = 0;
+
+ protected:
+  scoped_refptr<Handle> CreateHandle(
+      bool synchronization_required,
+      std::unique_ptr<SerializedAlgorithm> algorithm) {
+    return new Handle(synchronization_required, std::move(algorithm));
+  }
 };
 
 template <typename SerializedAlgorithm>
-SerializedAlgorithmRunner::Handle<SerializedAlgorithm>::Handle(
+SerializedAlgorithmRunner<SerializedAlgorithm>::Handle::Handle(
+    bool synchronization_required,
     std::unique_ptr<SerializedAlgorithm> algorithm)
-    : algorithm_(std::move(algorithm)) {
+    : synchronization_required_(synchronization_required),
+      algorithm_(std::move(algorithm)) {
   DCHECK(algorithm_);
 }
 
 template <typename SerializedAlgorithm>
-void SerializedAlgorithmRunner::Handle<SerializedAlgorithm>::Abort() {
+void SerializedAlgorithmRunner<SerializedAlgorithm>::Handle::Abort() {
   TRACE_EVENT0("cobalt::dom", "SerializedAlgorithmRunner::Handle::Abort()");
 
-  starboard::ScopedLock scoped_lock(mutex_);
+  ScopedLockWhenRequired scoped_lock(synchronization_required_, mutex_);
 
   DCHECK(!aborted_);  // Abort() cannot be called twice.
 
@@ -126,18 +157,19 @@
 }
 
 template <typename SerializedAlgorithm>
-void SerializedAlgorithmRunner::Handle<SerializedAlgorithm>::Process(
+void SerializedAlgorithmRunner<SerializedAlgorithm>::Handle::Process(
     bool* finished) {
   TRACE_EVENT0("cobalt::dom", "SerializedAlgorithmRunner::Handle::Process()");
 
   DCHECK(finished);
 
-  starboard::ScopedLock scoped_lock(mutex_);
+  ScopedLockWhenRequired scoped_lock(synchronization_required_, mutex_);
 
   DCHECK(!finished_);
   DCHECK(!finalized_);
 
   if (aborted_) {
+    *finished = true;
     return;
   }
 
@@ -147,17 +179,19 @@
 }
 
 template <typename SerializedAlgorithm>
-void SerializedAlgorithmRunner::Handle<SerializedAlgorithm>::Finalize() {
+void SerializedAlgorithmRunner<
+    SerializedAlgorithm>::Handle::FinalizeIfNotAborted() {
   TRACE_EVENT0("cobalt::dom", "SerializedAlgorithmRunner::Handle::Finalize()");
-  starboard::ScopedLock scoped_lock(mutex_);
 
-  DCHECK(finished_);
+  ScopedLockWhenRequired scoped_lock(synchronization_required_, mutex_);
+
   DCHECK(!finalized_);
 
   if (aborted_) {
     return;
   }
 
+  DCHECK(finished_);
   DCHECK(algorithm_);
 
   algorithm_->Finalize();
@@ -167,14 +201,21 @@
 
 // This class runs algorithm on the task runner associated with the thread where
 // Start() is called.
-class DefaultAlgorithmRunner : public SerializedAlgorithmRunner {
+template <typename SerializedAlgorithm>
+class DefaultAlgorithmRunner
+    : public SerializedAlgorithmRunner<SerializedAlgorithm> {
  public:
   explicit DefaultAlgorithmRunner(bool asynchronous_reduction_enabled)
       : asynchronous_reduction_enabled_(asynchronous_reduction_enabled) {}
 
  private:
-  void Start(const scoped_refptr<HandleBase>& handle) override;
-  void Process(const scoped_refptr<HandleBase>& handle);
+  typedef
+      typename SerializedAlgorithmRunner<SerializedAlgorithm>::Handle Handle;
+
+  scoped_refptr<Handle> CreateHandle(
+      std::unique_ptr<SerializedAlgorithm> algorithm) override;
+  void Start(scoped_refptr<Handle> handle) override;
+  void Process(scoped_refptr<Handle> handle);
 
   const bool asynchronous_reduction_enabled_;
 };
@@ -185,7 +226,9 @@
 // This class will keep calling the Process() member function of the algorithm
 // on the process task runner, and then call Finalize() on the finalize task
 // runner when |finished| becomes true.
-class OffloadAlgorithmRunner : public SerializedAlgorithmRunner {
+template <typename SerializedAlgorithm>
+class OffloadAlgorithmRunner
+    : public SerializedAlgorithmRunner<SerializedAlgorithm> {
  public:
   typedef base::SingleThreadTaskRunner TaskRunner;
 
@@ -193,13 +236,121 @@
                          const scoped_refptr<TaskRunner>& finalize_task_runner);
 
  private:
-  void Start(const scoped_refptr<HandleBase>& handle) override;
-  void Process(const scoped_refptr<HandleBase>& handle);
+  typedef
+      typename SerializedAlgorithmRunner<SerializedAlgorithm>::Handle Handle;
+
+  scoped_refptr<Handle> CreateHandle(
+      std::unique_ptr<SerializedAlgorithm> algorithm) override;
+  void Start(scoped_refptr<Handle> handle) override;
+  void Process(scoped_refptr<Handle> handle);
 
   scoped_refptr<TaskRunner> process_task_runner_;
   scoped_refptr<TaskRunner> finalize_task_runner_;
 };
 
+template <typename SerializedAlgorithm>
+scoped_refptr<typename SerializedAlgorithmRunner<SerializedAlgorithm>::Handle>
+DefaultAlgorithmRunner<SerializedAlgorithm>::CreateHandle(
+    std::unique_ptr<SerializedAlgorithm> algorithm) {
+  TRACE_EVENT0("cobalt::dom", "DefaultAlgorithmRunner::CreateHandle()");
+
+  const bool kSynchronizationRequired = false;
+  return SerializedAlgorithmRunner<SerializedAlgorithm>::CreateHandle(
+      kSynchronizationRequired, std::move(algorithm));
+}
+
+template <typename SerializedAlgorithm>
+void DefaultAlgorithmRunner<SerializedAlgorithm>::Start(
+    scoped_refptr<Handle> handle) {
+  DCHECK(handle);
+  TRACE_EVENT0("cobalt::dom", "DefaultAlgorithmRunner::Start()");
+
+  if (asynchronous_reduction_enabled_) {
+    Process(handle);
+    return;
+  }
+
+  auto task_runner = base::MessageLoop::current()->task_runner();
+  task_runner->PostTask(FROM_HERE,
+                        base::BindOnce(&DefaultAlgorithmRunner::Process,
+                                       base::Unretained(this), handle));
+}
+
+template <typename SerializedAlgorithm>
+void DefaultAlgorithmRunner<SerializedAlgorithm>::Process(
+    scoped_refptr<Handle> handle) {
+  DCHECK(handle);
+  TRACE_EVENT0("cobalt::dom", "DefaultAlgorithmRunner::Process()");
+
+  auto task_runner = base::MessageLoop::current()->task_runner();
+
+  bool finished = false;
+  handle->Process(&finished);
+
+  if (finished) {
+    handle->FinalizeIfNotAborted();
+    return;
+  }
+  task_runner->PostTask(FROM_HERE,
+                        base::BindOnce(&DefaultAlgorithmRunner::Process,
+                                       base::Unretained(this), handle));
+}
+
+template <typename SerializedAlgorithm>
+OffloadAlgorithmRunner<SerializedAlgorithm>::OffloadAlgorithmRunner(
+    const scoped_refptr<TaskRunner>& process_task_runner,
+    const scoped_refptr<TaskRunner>& finalize_task_runner)
+    : process_task_runner_(process_task_runner),
+      finalize_task_runner_(finalize_task_runner) {
+  DCHECK(process_task_runner_);
+  DCHECK(finalize_task_runner_);
+  DCHECK_NE(process_task_runner_, finalize_task_runner_);
+}
+
+template <typename SerializedAlgorithm>
+scoped_refptr<typename SerializedAlgorithmRunner<SerializedAlgorithm>::Handle>
+OffloadAlgorithmRunner<SerializedAlgorithm>::CreateHandle(
+    std::unique_ptr<SerializedAlgorithm> algorithm) {
+  TRACE_EVENT0("cobalt::dom", "OffloadAlgorithmRunner::CreateHandle()");
+
+  const bool kSynchronizationRequired = true;
+  return SerializedAlgorithmRunner<SerializedAlgorithm>::CreateHandle(
+      kSynchronizationRequired, std::move(algorithm));
+}
+
+template <typename SerializedAlgorithm>
+void OffloadAlgorithmRunner<SerializedAlgorithm>::Start(
+    scoped_refptr<Handle> handle) {
+  DCHECK(handle);
+
+  TRACE_EVENT0("cobalt::dom", "OffloadAlgorithmRunner::Start()");
+
+  process_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&OffloadAlgorithmRunner::Process,
+                                base::Unretained(this), handle));
+}
+
+template <typename SerializedAlgorithm>
+void OffloadAlgorithmRunner<SerializedAlgorithm>::Process(
+    scoped_refptr<Handle> handle) {
+  DCHECK(handle);
+  DCHECK(process_task_runner_->BelongsToCurrentThread());
+
+  TRACE_EVENT0("cobalt::dom", "OffloadAlgorithmRunner::Process()");
+
+  bool finished = false;
+  handle->Process(&finished);
+
+  if (finished) {
+    finalize_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&Handle::FinalizeIfNotAborted, handle));
+    return;
+  }
+  process_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&OffloadAlgorithmRunner::Process,
+                                base::Unretained(this), handle));
+}
+
 }  // namespace dom
 }  // namespace cobalt
 
diff --git a/cobalt/dom/source_buffer.cc b/cobalt/dom/source_buffer.cc
index ffaee80..1f6278b 100644
--- a/cobalt/dom/source_buffer.cc
+++ b/cobalt/dom/source_buffer.cc
@@ -387,11 +387,11 @@
                      base::Unretained(this)),
           base::Bind(&SourceBuffer::OnAlgorithmFinalized,
                      base::Unretained(this))));
+  auto algorithm_runner =
+      media_source_->GetAlgorithmRunner(std::numeric_limits<int>::max());
   active_algorithm_handle_ =
-      new SerializedAlgorithmRunner::Handle<SourceBufferAlgorithm>(
-          std::move(algorithm));
-  media_source_->GetAlgorithmRunner(std::numeric_limits<int>::max())
-      ->Start(active_algorithm_handle_);
+      algorithm_runner->CreateHandle(std::move(algorithm));
+  algorithm_runner->Start(active_algorithm_handle_);
 }
 
 void SourceBuffer::set_track_defaults(
@@ -482,9 +482,13 @@
 }
 
 void SourceBuffer::ScheduleAndMaybeDispatchImmediately(base::Token event_name) {
+  ScheduleEvent(event_name);
+  // TODO(b/244773734): Re-enable direct event dispatching
+  /*
   scoped_refptr<web::Event> event = new web::Event(event_name);
   event->set_target(this);
   event_queue_->EnqueueAndMaybeDispatchImmediately(event);
+  */
 }
 
 bool SourceBuffer::PrepareAppend(size_t new_data_size,
@@ -509,6 +513,7 @@
     return false;
   }
 
+  metrics_.StartTracking();
   media_source_->OpenIfInEndedState();
 
   double current_time = media_source_->GetMediaElement()->current_time(NULL);
@@ -517,9 +522,11 @@
           new_data_size + evict_extra_in_bytes_)) {
     web::DOMException::Raise(web::DOMException::kQuotaExceededErr,
                              exception_state);
+    metrics_.EndTracking(0);
     return false;
   }
 
+  metrics_.EndTracking(0);
   return true;
 }
 
@@ -528,11 +535,9 @@
     script::ExceptionState* exception_state) {
   TRACE_EVENT1("cobalt::dom", "SourceBuffer::AppendBufferInternal()", "size",
                size);
-  metrics_.StartTracking();
   if (!PrepareAppend(size, exception_state)) {
     return;
   }
-  metrics_.EndTracking(0);
 
   DCHECK(data || size == 0);
 
@@ -562,10 +567,10 @@
           base::Bind(&SourceBuffer::OnAlgorithmFinalized,
                      base::Unretained(this)),
           &metrics_));
+  auto algorithm_runner = media_source_->GetAlgorithmRunner(size);
   active_algorithm_handle_ =
-      new SerializedAlgorithmRunner::Handle<SourceBufferAlgorithm>(
-          std::move(algorithm));
-  media_source_->GetAlgorithmRunner(size)->Start(active_algorithm_handle_);
+      algorithm_runner->CreateHandle(std::move(algorithm));
+  algorithm_runner->Start(active_algorithm_handle_);
 }
 
 void SourceBuffer::OnAlgorithmFinalized() {
diff --git a/cobalt/dom/source_buffer.h b/cobalt/dom/source_buffer.h
index 0cf7f28..c7336e6 100644
--- a/cobalt/dom/source_buffer.h
+++ b/cobalt/dom/source_buffer.h
@@ -204,7 +204,7 @@
   starboard::Mutex timestamp_offset_mutex_;
   double timestamp_offset_ = 0;
 
-  scoped_refptr<SerializedAlgorithmRunner::Handle<SourceBufferAlgorithm>>
+  scoped_refptr<SerializedAlgorithmRunner<SourceBufferAlgorithm>::Handle>
       active_algorithm_handle_;
   double append_window_start_ = 0;
   double append_window_end_ = std::numeric_limits<double>::infinity();
diff --git a/cobalt/extension/on_screen_keyboard.h b/cobalt/extension/on_screen_keyboard.h
new file mode 100644
index 0000000..a1d922d
--- /dev/null
+++ b/cobalt/extension/on_screen_keyboard.h
@@ -0,0 +1,57 @@
+// Copyright 2022 The Cobalt Authors. 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.
+
+#ifndef COBALT_EXTENSION_ON_SCREEN_KEYBOARD_H_
+#define COBALT_EXTENSION_ON_SCREEN_KEYBOARD_H_
+
+#include <stdint.h>
+
+#include "starboard/system.h"
+#include "starboard/window.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define kCobaltExtensionOnScreenKeyboardName \
+  "dev.cobalt.extension.OnScreenKeyboard"
+
+typedef struct CobaltExtensionOnScreenKeyboardApi {
+  // Name should be the string
+  // |kCobaltExtensionOnScreenKeyboardName|. This helps to validate that
+  // the extension API is correct.
+  const char* name;
+
+  // This specifies the version of the API that is implemented.
+  uint32_t version;
+
+  // The fields below this point were added in version 1 or later.
+
+  // This function overrides the background color of on-screen keyboard.
+  // The function is only enabled for Apple TV at the moment.
+  // background_color should be a string of below formats:
+  // 1. hex color notation #RRGGBB, e.g. "#0000FF".
+  // 2. rgb color notation rgb(R, G, B), e.g. "rgb(0, 0, 255)".
+  void (*SetBackgroundColor)(SbWindow window, const char* background_color);
+
+  // This function overrides the dark theme of on-screen keyboard.
+  // The function is only enabled for Apple TV at the moment.
+  void (*SetDarkTheme)(SbWindow window, bool dark_theme);
+} CobaltExtensionOnScreenKeyboardApi;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // COBALT_EXTENSION_ON_SCREEN_KEYBOARD_H_
diff --git a/cobalt/media_session/media_session_client.cc b/cobalt/media_session/media_session_client.cc
index e668cae..c8290cf 100644
--- a/cobalt/media_session/media_session_client.cc
+++ b/cobalt/media_session/media_session_client.cc
@@ -331,7 +331,7 @@
           ext_image.src = media_image.src().c_str();
           if (ext_image.src == nullptr) {
             // src() is required, but Cobalt IDL parser doesn't enforce it.
-            // http://cs/cobalt/cobalt/media_session/media_image.idl?l=19
+            // See cobalt/media_session/media_image.idl for more info.
             // https://wicg.github.io/mediasession/#dictdef-mediaimage
             LOG(ERROR) << "Required src string for MediaImage is missing.";
           }
diff --git a/starboard/CHANGELOG.md b/starboard/CHANGELOG.md
index 69ca601..fddc2c3 100644
--- a/starboard/CHANGELOG.md
+++ b/starboard/CHANGELOG.md
@@ -15,6 +15,9 @@
 [configuration.h](configuration.h).
 
 ## Version 14
+### Require kSbSystemPathStorageDirectory on all platforms.
+Path to directory for permanent persistent storage.
+
 ### Add MP3, FLAC, and PCM values to SbMediaAudioCodec.
 This makes it possible to support these codecs in the future.
 
diff --git a/starboard/android/apk/app/src/app/AndroidManifest.xml b/starboard/android/apk/app/src/app/AndroidManifest.xml
index 42d8bc0..9c4e11a 100644
--- a/starboard/android/apk/app/src/app/AndroidManifest.xml
+++ b/starboard/android/apk/app/src/app/AndroidManifest.xml
@@ -32,7 +32,7 @@
   <!-- This is needed when targeting API 28+ to use foreground services -->
   <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
 
-  <!-- Used for go/cobalt-ifa and AdvertisingIdClient.Info.getId() -->
+  <!-- https://iabtechlab.com/OTT-IFA, AdvertisingIdClient.Info.getId() -->
   <uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
 
   <application
diff --git a/starboard/android/apk/app/src/main/java/dev/cobalt/libraries/services/clientloginfo/ClientLogInfo.java b/starboard/android/apk/app/src/main/java/dev/cobalt/libraries/services/clientloginfo/ClientLogInfo.java
index 57c39ad..7628f93 100644
--- a/starboard/android/apk/app/src/main/java/dev/cobalt/libraries/services/clientloginfo/ClientLogInfo.java
+++ b/starboard/android/apk/app/src/main/java/dev/cobalt/libraries/services/clientloginfo/ClientLogInfo.java
@@ -6,10 +6,7 @@
 import dev.cobalt.coat.CobaltService;
 import dev.cobalt.util.Log;
 
-/**
- * ClientLogInfo to report Android API support on android devices, read go/coat-api-support for more
- * info.
- */
+/** ClientLogInfo to report Android API support on android devices. */
 public class ClientLogInfo extends CobaltService {
   public static final String TAG = "ClientLogInfo";
 
diff --git a/starboard/nplb/system_get_path_test.cc b/starboard/nplb/system_get_path_test.cc
index e320737..44f4e00 100644
--- a/starboard/nplb/system_get_path_test.cc
+++ b/starboard/nplb/system_get_path_test.cc
@@ -69,6 +69,9 @@
 TEST(SbSystemGetPathTest, ReturnsRequiredPaths) {
   BasicTest(kSbSystemPathContentDirectory, true, true, __LINE__);
   BasicTest(kSbSystemPathCacheDirectory, true, true, __LINE__);
+#if SB_API_VERSION >= 14
+  BasicTest(kSbSystemPathStorageDirectory, true, true, __LINE__);
+#endif  // SB_API_VERSION >= 14
 }
 
 TEST(SbSystemGetPathTest, FailsGracefullyZeroBufferLength) {
diff --git a/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h b/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h
index 3f6e7c0..8a997a8 100644
--- a/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h
+++ b/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h
@@ -62,9 +62,6 @@
   void Reset() override;
 
  private:
-  void ProcessOneInputBuffer(const scoped_refptr<InputBuffer>& input_buffer,
-                             const ConsumedCB& consumed_cb);
-
   void InitializeAudioDecoder(const SbMediaAudioSampleInfo& audio_sample_info);
   void TeardownAudioDecoder();
   void OnDecoderOutput();