Import Cobalt 13.108984

Change-Id: Ic087ddd013d13dfaf3cb3a7dd34c5ddb72c85d7c
diff --git a/src/cobalt/accessibility/screen_reader_tests.cc b/src/cobalt/accessibility/screen_reader_tests.cc
index 714f243..611d7ed 100644
--- a/src/cobalt/accessibility/screen_reader_tests.cc
+++ b/src/cobalt/accessibility/screen_reader_tests.cc
@@ -173,9 +173,9 @@
       base::Bind(&LiveRegionMutationTest::OnError, base::Unretained(this)),
       base::Bind(&LiveRegionMutationTest::OnClose, base::Unretained(this)),
       base::Closure(), /* window_minimize_callback */
-      NULL /* media_module */, &network_module, kDefaultViewportSize,
-      kDefaultVideoPixelRatio, &resource_provider, kRefreshRate,
-      web_module_options);
+      NULL /* can_play_type_handler */, NULL /* web_media_player_factory */,
+      &network_module, kDefaultViewportSize, kDefaultVideoPixelRatio,
+      &resource_provider, kRefreshRate, web_module_options);
 
   // Wait for the test to quit.
   quit_event_.Wait();
diff --git a/src/cobalt/base/c_val.cc b/src/cobalt/base/c_val.cc
index f0c9a84..d44f9fa 100644
--- a/src/cobalt/base/c_val.cc
+++ b/src/cobalt/base/c_val.cc
@@ -48,7 +48,9 @@
   delete registered_vars_;
 }
 
-void CValManager::RegisterCVal(const CValDetail::CValBase* cval) {
+void CValManager::RegisterCVal(
+    const CValDetail::CValBase* cval,
+    scoped_refptr<base::RefCountedThreadSafeLock>* value_lock) {
   base::AutoLock auto_lock(cvals_lock_);
 
   // CVals cannot share name.  If this assert is triggered, we are trying to
@@ -57,6 +59,7 @@
   DCHECK(registered_vars_->find(cval->GetName()) == registered_vars_->end());
 
   (*registered_vars_)[cval->GetName()] = cval;
+  *value_lock = value_lock_refptr_;
 }
 
 void CValManager::UnregisterCVal(const CValDetail::CValBase* cval) {
diff --git a/src/cobalt/base/c_val.h b/src/cobalt/base/c_val.h
index a589822..b399965 100644
--- a/src/cobalt/base/c_val.h
+++ b/src/cobalt/base/c_val.h
@@ -437,8 +437,10 @@
   ~CValManager();
 
   // Called in CVal constructors to register/deregister themselves with the
-  // system.
-  void RegisterCVal(const CValDetail::CValBase* cval);
+  // system.  Registering a CVal will also provide that CVal with a value lock
+  // to lock when it modifies its value.
+  void RegisterCVal(const CValDetail::CValBase* cval,
+                    scoped_refptr<base::RefCountedThreadSafeLock>* value_lock);
   void UnregisterCVal(const CValDetail::CValBase* cval);
 
 #if defined(ENABLE_DEBUG_C_VAL)
@@ -523,7 +525,6 @@
     CommonConstructor();
   }
   virtual ~CValImpl() {
-    base::AutoLock auto_lock(value_lock_refptr_->GetLock());
     if (registered_) {
       CValManager::GetInstance()->UnregisterCVal(this);
     }
@@ -610,8 +611,7 @@
   void RegisterWithManager() {
     if (!registered_) {
       CValManager* manager = CValManager::GetInstance();
-      manager->RegisterCVal(this);
-      value_lock_refptr_ = manager->value_lock_refptr_;
+      manager->RegisterCVal(this, &value_lock_refptr_);
       registered_ = true;
     }
   }
diff --git a/src/cobalt/base/c_val_test.cc b/src/cobalt/base/c_val_test.cc
index 1087ad2..9729480 100644
--- a/src/cobalt/base/c_val_test.cc
+++ b/src/cobalt/base/c_val_test.cc
@@ -13,7 +13,10 @@
 // limitations under the License.
 
 #include <limits>
+#include <utility>
 
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/simple_thread.h"
 #include "base/time.h"
 #include "cobalt/base/c_val.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -584,4 +587,113 @@
   EXPECT_EQ(test_hook.value_changed_count_, 1);
 }
 
+namespace {
+// Helper class for the RemoveAndRead test defined below.
+class ReadCValThread : public base::SimpleThread {
+ public:
+  ReadCValThread(const char* test_cval_name, int num_read_cycles,
+                 std::pair<std::string, std::string> valid_values,
+                 base::WaitableEvent* thread_ready_event,
+                 base::WaitableEvent* start_processing_event)
+      : base::SimpleThread("ReadCValThread"),
+        test_cval_name_(test_cval_name),
+        num_read_cycles_(num_read_cycles),
+        valid_values_(valid_values),
+        thread_ready_event_(thread_ready_event),
+        start_processing_event_(start_processing_event) {}
+
+  void Run() OVERRIDE {
+    thread_ready_event_->Signal();
+    start_processing_event_->Wait();
+
+    base::CValManager* cvm = base::CValManager::GetInstance();
+    for (int i = 0; i < num_read_cycles_; ++i) {
+      base::optional<std::string> result =
+          cvm->GetValueAsString(test_cval_name_);
+      if (result) {
+        EXPECT_TRUE(*result == valid_values_.first ||
+                    *result == valid_values_.second);
+      }
+    }
+  }
+
+ private:
+  const char* test_cval_name_;
+  int num_read_cycles_;
+  std::pair<std::string, std::string> valid_values_;
+  base::WaitableEvent* thread_ready_event_;
+  base::WaitableEvent* start_processing_event_;
+};
+
+// Helper class for the RemoveAndRead test defined below.
+class CreateDestroyCValThread : public base::SimpleThread {
+ public:
+  CreateDestroyCValThread(const char* test_cval_name,
+                          int num_create_destroy_cycles,
+                          std::pair<std::string, std::string> valid_values,
+                          base::WaitableEvent* thread_ready_event,
+                          base::WaitableEvent* start_processing_event)
+      : base::SimpleThread("CreateDestroyCValThread"),
+        test_cval_name_(test_cval_name),
+        num_create_destroy_cycles_(num_create_destroy_cycles),
+        valid_values_(valid_values),
+        thread_ready_event_(thread_ready_event),
+        start_processing_event_(start_processing_event) {}
+
+  void Run() OVERRIDE {
+    thread_ready_event_->Signal();
+    start_processing_event_->Wait();
+
+    for (int i = 0; i < num_create_destroy_cycles_; ++i) {
+      base::CVal<std::string> test_cval(test_cval_name_, valid_values_.first,
+                                        "Description");
+      test_cval = valid_values_.second;
+    }
+  }
+
+ private:
+  const char* test_cval_name_;
+  int num_create_destroy_cycles_;
+  std::pair<std::string, std::string> valid_values_;
+  base::WaitableEvent* thread_ready_event_;
+  base::WaitableEvent* start_processing_event_;
+};
+
+}  // namespace
+
+// Tests that we can create and destroy cvals no problem while simultaneously
+// reading from them.  The test creates two threads, a reader thread and a
+// creater/destroyer (and writer) thread.  These both attempt to access the same
+// cval as fast as possible.
+TEST(CValTest, RemoveAndRead) {
+  const char* kTestCValName = "TestCVal";
+  const int kNumReadCycles = 10000;
+  const int kNuMCreateDestroyCycles = 10000;
+  const std::pair<std::string, std::string> valid_values("hello", "66");
+  base::WaitableEvent read_cval_thread_ready(true, false);
+  base::WaitableEvent create_destroy_cval_thread_ready(true, false);
+  base::WaitableEvent start_processing_event(true, false);
+
+  // Create and start both threads.
+  ReadCValThread read_cval_thread(kTestCValName, kNumReadCycles, valid_values,
+                                  &read_cval_thread_ready,
+                                  &start_processing_event);
+  CreateDestroyCValThread create_destroy_cval_thread(
+      kTestCValName, kNuMCreateDestroyCycles, valid_values,
+      &create_destroy_cval_thread_ready, &start_processing_event);
+  read_cval_thread.Start();
+  create_destroy_cval_thread.Start();
+
+  // Wait until both threads are initialized and ready.
+  read_cval_thread_ready.Wait();
+  create_destroy_cval_thread_ready.Wait();
+
+  // Signal for the processing/testing to begin.
+  start_processing_event.Signal();
+
+  // Wait for both threads to complete.
+  read_cval_thread.Join();
+  create_destroy_cval_thread.Join();
+}
+
 }  // namespace base
diff --git a/src/cobalt/bindings/bindings.gypi b/src/cobalt/bindings/bindings.gypi
index 9260d08..0db0d57 100644
--- a/src/cobalt/bindings/bindings.gypi
+++ b/src/cobalt/bindings/bindings.gypi
@@ -64,6 +64,20 @@
       '../script/engine_variables.gypi',
       '../../third_party/blink/Source/bindings/scripts/scripts.gypi',
     ],
+    'variables': {
+      # Legend has it that experienced Chrome developers can actually nest
+      # variables up to four levels.  Here, we keep things simple and only do
+      # three.  We do this because "engine_variables.gypi" will create another
+      # variables scope and then branch on |javascript_engine|, which requires
+      # a default value to be provided one level lower.
+      'variables': {
+        'javascript_engine%': '<(default_javascript_engine)',
+      },
+      # Specify a default component for generated window IDL. This should be
+      # removed when the concept of 'components' in the blink IDL parsing scripts
+      # is refactored out, since it doesn't really apply to Cobalt.
+      'window_component%': 'dom',
+    },
 
     # Define these variables in the including .gyp file and their lists will get
     # merged in, giving some control to how the bindings are built.
@@ -104,12 +118,6 @@
     # Constructors will be an event in the unsupported property mechanism.
     'unsupported_interface_idl_files': [],
 
-    # Specify a default component for generated window IDL. This should be
-    # removed when the concept of 'components' in the blink IDL parsing scripts
-    # is refactored out, since it doesn't really apply to Cobalt.
-    'variables': {
-      'window_component%': 'dom',
-    },
     'window_component%': '<(window_component)',
 
     'prefix': '<(generated_bindings_prefix)',
diff --git a/src/cobalt/bindings/contexts.py b/src/cobalt/bindings/contexts.py
index 702090e..d779ec5 100644
--- a/src/cobalt/bindings/contexts.py
+++ b/src/cobalt/bindings/contexts.py
@@ -86,6 +86,19 @@
   return type_map[idl_type.base_type]
 
 
+def idl_string_type_to_cobalt(idl_type):
+  """Map IDL string type to C++ type."""
+  type_map = {
+      'ByteString': 'std::vector<uint8_t>',
+      'DOMString': 'std::string',
+      'String': 'std::string',
+      'StringOrNull': 'std::string',
+      'USVString': 'std::string',
+  }
+  assert idl_type.is_string_type, 'Expected string type.'
+  return type_map[idl_type.name]
+
+
 def cobalt_type_is_optional(idl_type):
   """Return True iff the idl_type should be wrapped by a base::optional<>.
 
@@ -235,7 +248,7 @@
     if idl_type.is_primitive_type:
       cobalt_type = idl_primitive_type_to_cobalt(idl_type)
     elif idl_type.is_string_type:
-      cobalt_type = 'std::string'
+      cobalt_type = idl_string_type_to_cobalt(idl_type)
     elif idl_type.is_callback_interface:
       cobalt_type = '::cobalt::script::CallbackInterfaceTraits<%s >' % (
           get_interface_name(idl_type))
@@ -436,8 +449,9 @@
 
   def attribute_context(self, interface, attribute, definitions):
     """Create template values for attribute bindings."""
-    cobalt_name = attribute.extended_attributes.get(
-        'ImplementedAs', convert_to_cobalt_name(attribute.name))
+    cobalt_name = attribute.extended_attributes.get('ImplementedAs',
+                                                    convert_to_cobalt_name(
+                                                        attribute.name))
     context = {
         'idl_name':
             attribute.name,
@@ -495,8 +509,10 @@
     return {
         'enumeration_name':
             enumeration.name,
-        'value_pairs': [(convert_to_cobalt_enumeration_value(
-            enumeration.name, value), value,) for value in enumeration.values],
+        'value_pairs': [(
+            convert_to_cobalt_enumeration_value(enumeration.name, value),
+            value,
+        ) for value in enumeration.values],
     }
 
   def constant_context(self, constant):
@@ -538,9 +554,9 @@
         [m for m in methods if m['is_static']])
     non_static_method_overloads = method_overloads_by_name(
         [m for m in methods if not m['is_static']])
-    static_overload_contexts = get_overload_contexts(expression_generator, [
-        contexts for _, contexts in static_method_overloads
-    ])
+    static_overload_contexts = get_overload_contexts(
+        expression_generator,
+        [contexts for _, contexts in static_method_overloads])
     non_static_overload_contexts = get_overload_contexts(
         expression_generator,
         [contexts for _, contexts in non_static_method_overloads])
diff --git a/src/cobalt/bindings/testing/bindings_test_base.h b/src/cobalt/bindings/testing/bindings_test_base.h
index ddb7ca5..f37639b 100644
--- a/src/cobalt/bindings/testing/bindings_test_base.h
+++ b/src/cobalt/bindings/testing/bindings_test_base.h
@@ -67,8 +67,8 @@
     scoped_refptr<script::SourceCode> source =
         script::SourceCode::CreateSourceCode(
             script, base::SourceLocation("[object BindingsTestBase]", 1, 1));
-    return global_environment_->EvaluateScript(source, out_result,
-                                               false /*mute_errors*/);
+    return global_environment_->EvaluateScript(source, false /*mute_errors*/,
+                                               out_result);
   }
 
   bool EvaluateScript(const std::string& script,
@@ -79,7 +79,7 @@
         script::SourceCode::CreateSourceCode(
             script, base::SourceLocation("[object BindingsTestBase]", 1, 1));
     return global_environment_->EvaluateScript(
-        source, owning_object, out_opaque_handle, false /*mute_errors*/);
+        source, owning_object, false /*mute_errors*/, out_opaque_handle);
   }
 
   void CollectGarbage() { engine_->CollectGarbage(); }
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc
index 636ebf5..81c407e 100644
--- a/src/cobalt/browser/application.cc
+++ b/src/cobalt/browser/application.cc
@@ -363,21 +363,6 @@
                           &options->scratch_surface_cache_size_in_bytes);
 }
 
-// Restrict navigation to a couple of whitelisted URLs by default.
-const char kYouTubeTvLocationPolicy[] =
-    "h5vcc-location-src "
-    "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)
-    "about: "
-#endif
-    "h5vcc:";
-
 struct NonTrivialStaticFields {
   NonTrivialStaticFields() : system_language(base::GetSystemLanguage()) {}
 
@@ -516,7 +501,6 @@
   // User can specify an extra search path entry for files loaded via file://.
   options.web_module_options.extra_web_file_dir = GetExtraWebFileDir();
   SecurityFlags security_flags{csp::kCSPRequired, network::kHTTPSRequired};
-  options.web_module_options.location_policy = kYouTubeTvLocationPolicy;
   // Set callback to be notified when a navigation occurs that destroys the
   // underlying WebModule.
   options.web_module_recreated_callback =
@@ -610,13 +594,6 @@
   options.web_module_options.require_csp = security_flags.csp_header_policy;
   options.web_module_options.csp_enforcement_mode = dom::kCspEnforcementEnable;
 
-  if (command_line->HasSwitch(browser::switches::kDisableNavigationWhitelist)) {
-    LOG(ERROR) << "\n"
-               << "  *** Disabling the default navigation whitelist! ***\n"
-               << "  *** Do not run in this mode in production!      ***";
-    options.web_module_options.location_policy = "h5vcc-location-src *";
-  }
-
   options.requested_viewport_size = requested_viewport_size;
   account_manager_.reset(new account::AccountManager());
   browser_module_.reset(
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc
index a1f944d..b1d2a9e 100644
--- a/src/cobalt/browser/browser_module.cc
+++ b/src/cobalt/browser/browser_module.cc
@@ -223,6 +223,7 @@
           new ResourceProviderArrayBufferAllocator(GetResourceProvider())),
       array_buffer_cache_(new dom::ArrayBuffer::Cache(3 * 1024 * 1024)),
 #endif  // defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR)
+      can_play_type_handler_(media::MediaModule::CreateCanPlayTypeHandler()),
       network_module_(&storage_manager_, event_dispatcher_,
                       options_.network_module_options),
       web_module_loaded_(true /* manually_reset */,
@@ -255,6 +256,7 @@
       render_timeout_count_(0),
 #endif
       on_error_retry_count_(0),
+      waiting_for_error_retry_(false),
       will_quit_(false),
       application_state_(initial_application_state),
       splash_screen_cache_(new SplashScreenCache()),
@@ -354,9 +356,7 @@
 
 BrowserModule::~BrowserModule() {
   DCHECK_EQ(MessageLoop::current(), self_message_loop_);
-  if (on_error_retry_timer_.IsRunning()) {
-    on_error_retry_timer_.Stop();
-  }
+  on_error_retry_timer_.Stop();
 #if SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
   SbCoreDumpUnregisterHandler(BrowserModule::CoreDumpHandler, this);
 #endif
@@ -384,9 +384,10 @@
     return;
   }
 
-  if (on_error_retry_timer_.IsRunning()) {
-    on_error_retry_timer_.Stop();
-  }
+  // Clear error handling once we're told to navigate, either because it's the
+  // retry from the error or something decided we should navigate elsewhere.
+  on_error_retry_timer_.Stop();
+  waiting_for_error_retry_ = false;
 
   // Navigations aren't allowed if the app is suspended. If this is the case,
   // simply set the pending navigate url, which will cause the navigation to
@@ -483,8 +484,9 @@
       base::Bind(&BrowserModule::OnError, base::Unretained(this)),
       base::Bind(&BrowserModule::OnWindowClose, base::Unretained(this)),
       base::Bind(&BrowserModule::OnWindowMinimize, base::Unretained(this)),
-      media_module_.get(), &network_module_, viewport_size, video_pixel_ratio,
-      GetResourceProvider(), kLayoutMaxRefreshFrequencyInHz, options));
+      can_play_type_handler_.get(), media_module_.get(), &network_module_,
+      viewport_size, video_pixel_ratio, GetResourceProvider(),
+      kLayoutMaxRefreshFrequencyInHz, options));
   lifecycle_observers_.AddObserver(web_module_.get());
   if (!web_module_recreated_callback_.is_null()) {
     web_module_recreated_callback_.Run();
@@ -891,6 +893,7 @@
 void BrowserModule::OnErrorRetry() {
   ++on_error_retry_count_;
   on_error_retry_time_ = base::TimeTicks::Now();
+  waiting_for_error_retry_ = true;
   TryURLHandlers(
       GURL("h5vcc://network-failure?retry-url=" + pending_navigate_url_));
 }
@@ -1236,7 +1239,7 @@
 
   if (web_module_) {
     web_module_->SetCamera3D(input_device_manager_->camera_3d());
-    web_module_->SetMediaModule(media_module_.get());
+    web_module_->SetWebMediaPlayerFactory(media_module_.get());
     web_module_->SetSize(size, video_pixel_ratio);
   }
 }
@@ -1335,8 +1338,8 @@
   TRACE_EVENT0("cobalt::browser",
                "BrowserModule::StartOrResumeInternalPostStateUpdate");
   // If there's a navigation that's pending, then attempt to navigate to its
-  // specified URL now.
-  if (!pending_navigate_url_.empty()) {
+  // specified URL now, unless we're still waiting for an error retry.
+  if (!pending_navigate_url_.empty() && !waiting_for_error_retry_) {
     Navigate(GURL(pending_navigate_url_));
   }
 }
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h
index 2ecdbcf..f3cf4a2 100644
--- a/src/cobalt/browser/browser_module.h
+++ b/src/cobalt/browser/browser_module.h
@@ -44,6 +44,8 @@
 #include "cobalt/dom/wheel_event_init.h"
 #include "cobalt/input/input_device_manager.h"
 #include "cobalt/layout/layout_manager.h"
+#include "cobalt/media/can_play_type_handler.h"
+#include "cobalt/media/media_module.h"
 #include "cobalt/network/network_module.h"
 #include "cobalt/render_tree/resource_provider.h"
 #include "cobalt/render_tree/resource_provider_stub.h"
@@ -390,6 +392,9 @@
   // Controls all media playback related objects/resources.
   scoped_ptr<media::MediaModule> media_module_;
 
+  // Allows checking if particular media type can be played.
+  scoped_ptr<media::CanPlayTypeHandler> can_play_type_handler_;
+
   // Sets up the network component for requesting internet resources.
   network::NetworkModule network_module_;
 
@@ -496,6 +501,11 @@
   // when it is not already active.
   base::OneShotTimer<BrowserModule> on_error_retry_timer_;
 
+  // Set when we've posted a system error for network failure until we receive
+  // the next navigation. This is used to suppress retrying the current URL on
+  // resume until the error retry occurs.
+  bool waiting_for_error_retry_;
+
   // Set when the application is about to quit. May be set from a thread other
   // than the one hosting this object, and read from another.
   bool will_quit_;
diff --git a/src/cobalt/browser/debug_console.cc b/src/cobalt/browser/debug_console.cc
index ec0aba7..2f99e6f 100644
--- a/src/cobalt/browser/debug_console.cc
+++ b/src/cobalt/browser/debug_console.cc
@@ -188,15 +188,15 @@
       base::Bind(&CreateDebugHub,
                  base::Bind(&DebugConsole::GetMode, base::Unretained(this)),
                  get_debug_server_callback);
-  web_module_.reset(
-      new WebModule(GURL(kInitialDebugConsoleUrl), initial_application_state,
-                    render_tree_produced_callback,
-                    base::Bind(&DebugConsole::OnError, base::Unretained(this)),
-                    WebModule::CloseCallback(), /* window_close_callback */
-                    base::Closure(),            /* window_minimize_callback */
-                    &stub_media_module_, network_module, window_dimensions,
-                    1.f /*video_pixel_ratio*/, resource_provider,
-                    layout_refresh_rate, web_module_options));
+  web_module_.reset(new WebModule(
+      GURL(kInitialDebugConsoleUrl), initial_application_state,
+      render_tree_produced_callback,
+      base::Bind(&DebugConsole::OnError, base::Unretained(this)),
+      WebModule::CloseCallback(), /* window_close_callback */
+      base::Closure(),            /* window_minimize_callback */
+      NULL /* can_play_type_handler */, NULL /* web_media_player_factory */,
+      network_module, window_dimensions, 1.f /*video_pixel_ratio*/,
+      resource_provider, layout_refresh_rate, web_module_options));
 }
 
 DebugConsole::~DebugConsole() {}
diff --git a/src/cobalt/browser/debug_console.h b/src/cobalt/browser/debug_console.h
index 3889f9a..7d50520 100644
--- a/src/cobalt/browser/debug_console.h
+++ b/src/cobalt/browser/debug_console.h
@@ -26,7 +26,6 @@
 #include "cobalt/browser/web_module.h"
 #include "cobalt/debug/debug_hub.h"
 #include "cobalt/dom/keyboard_event_init.h"
-#include "cobalt/media/media_module_stub.h"
 #include "googleurl/src/gurl.h"
 
 namespace cobalt {
@@ -86,8 +85,6 @@
     LOG(ERROR) << error;
   }
 
-  media::MediaModuleStub stub_media_module_;
-
   // The current console visibility mode.  The mutex is required since the debug
   // console's visibility mode may be accessed from both the WebModule thread
   // and the DebugConsole's host thread.
diff --git a/src/cobalt/browser/lib/cobalt.def b/src/cobalt/browser/lib/cobalt.def
index 7a73eb4..845c307 100644
--- a/src/cobalt/browser/lib/cobalt.def
+++ b/src/cobalt/browser/lib/cobalt.def
@@ -12,6 +12,7 @@
     CbLibMainSetCallbackRegistrationReadyCallback
     CbLibMainSetOnCobaltInitializedCallback
     CbLibMainSetHandleEventCallback
+    CbLibMainGetSbWindow
 
     ; From cobalt/render/rasterizer/lib/exported/graphics.h:
     CbLibGraphicsSetContextCreatedCallback
@@ -21,10 +22,10 @@
     CbLibGraphicsSetTargetMainTextureSize
 
     ; From cobalt/render/rasterizer/lib/exported/video.h:
-    CbLibVideoSetOnUpdateProjectionType
+    CbLibVideoSetOnUpdateProjectionTypeAndStereoMode
     CbLibVideoSetOnUpdateMeshes
-    CbLibVideoSetOnUpdateStereoMode
     CbLibVideoSetOnUpdateRgbTextureId
+    CbLibVideoSetOnUpdateAspectRatio
 
     ; Following GL functions are copied from libGLESv2.def and EGL from
     ; libEGL.def. We export these so that host-applications may use the same
diff --git a/src/cobalt/browser/lib/exported/main.h b/src/cobalt/browser/lib/exported/main.h
index 087cb52..ba867bf 100644
--- a/src/cobalt/browser/lib/exported/main.h
+++ b/src/cobalt/browser/lib/exported/main.h
@@ -20,6 +20,7 @@
 
 #include "starboard/event.h"
 #include "starboard/export.h"
+#include "starboard/window.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -46,6 +47,16 @@
 SB_EXPORT_PLATFORM void CbLibMainSetHandleEventCallback(
     void* context, CbLibMainHandleEventCallback callback);
 
+// Returns a reference to the system window's underlying Starboard window, or
+// nullptr if the system window does not exist.
+//
+// The system window may be destroyed and recreated during Cobalt's application
+// life-cycle E.G. if a Suspend/Resume event occurs.  For this reason, clients
+// should not cache references returned by this call.  A client which requires
+// long-term access to the system window should re-query the reference each time
+// it is needed.
+SB_EXPORT_PLATFORM SbWindow CbLibMainGetSbWindow();
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/src/cobalt/browser/lib/main.cc b/src/cobalt/browser/lib/main.cc
index 5e82dab..1780b3a 100644
--- a/src/cobalt/browser/lib/main.cc
+++ b/src/cobalt/browser/lib/main.cc
@@ -46,6 +46,8 @@
   LOG(INFO) << "Preloading application.";
   DCHECK(!g_application);
   CHECK(g_callback_registration_ready);
+  // Register a default event handler up front.
+  CbLibMainSetHandleEventCallback(nullptr, nullptr);
   g_callback_registration_ready(g_registration_ready_context);
   g_application =
       new cobalt::browser::Application(quit_closure, true /*should_preload*/);
@@ -57,6 +59,8 @@
   LOG(INFO) << "Starting application.";
   if (!g_application) {
     CHECK(g_callback_registration_ready);
+    // Register a default event handler up front.
+    CbLibMainSetHandleEventCallback(nullptr, nullptr);
     g_callback_registration_ready(g_registration_ready_context);
     g_application = new cobalt::browser::Application(quit_closure,
                                                      false /*should_preload*/);
@@ -77,8 +81,17 @@
 }
 
 void HandleStarboardEvent(const SbEvent* starboard_event) {
-  if (g_application && (g_handle_event_callback.Get().is_null() ||
-                        !g_handle_event_callback.Get().Run(starboard_event))) {
+  if (!g_application) {
+    return;
+  }
+
+  // TODO(dworsham): Host-generated input events will also be fed through the
+  // host callback, leading to re-entrancy issues.  Set up a way of filtering
+  // them somehow.
+  //
+  // For now, works fine with YTVR as only input events are generated by the
+  // host and the host also ignores all input events sent its way.
+  if (!g_handle_event_callback.Get().Run(starboard_event)) {
     g_application->HandleStarboardEvent(starboard_event);
   }
 }
@@ -102,6 +115,16 @@
 
 void CbLibMainSetHandleEventCallback(void* context,
                                      CbLibMainHandleEventCallback callback) {
-  g_handle_event_callback.Get() =
-      callback ? base::Bind(callback, context) : HandleEventCallback();
+  // If the user passes nullptr, provide a default event handler so that it is
+  // never actually null.
+  g_handle_event_callback.Get() = callback ?
+      base::Bind(callback, context) :
+      base::Bind([](const SbEvent*) {
+        return false;
+      });
+}
+
+SbWindow CbLibMainGetSbWindow() {
+  auto* primary_window = cobalt::system_window::SystemWindow::PrimaryWindow();
+  return primary_window ? primary_window->GetSbWindow() : nullptr;
 }
diff --git a/src/cobalt/browser/splash_screen.cc b/src/cobalt/browser/splash_screen.cc
index 811baa0..0c4026b 100644
--- a/src/cobalt/browser/splash_screen.cc
+++ b/src/cobalt/browser/splash_screen.cc
@@ -100,9 +100,9 @@
       *url_to_pass, initial_application_state, render_tree_produced_callback_,
       base::Bind(&OnError), on_window_close,
       base::Closure(),  // window_minimize_callback
-      &stub_media_module_, network_module, window_dimensions,
-      1.f /*video_pixel_ratio*/, resource_provider, layout_refresh_rate,
-      web_module_options));
+      NULL /* can_play_type_handler */, NULL /* web_media_player_factory */,
+      network_module, window_dimensions, 1.f /*video_pixel_ratio*/,
+      resource_provider, layout_refresh_rate, web_module_options));
 }
 
 SplashScreen::~SplashScreen() {
diff --git a/src/cobalt/browser/splash_screen.h b/src/cobalt/browser/splash_screen.h
index f9315d2..bc21bbe 100644
--- a/src/cobalt/browser/splash_screen.h
+++ b/src/cobalt/browser/splash_screen.h
@@ -23,7 +23,6 @@
 #include "cobalt/browser/lifecycle_observer.h"
 #include "cobalt/browser/splash_screen_cache.h"
 #include "cobalt/browser/web_module.h"
-#include "cobalt/media/media_module_stub.h"
 #include "googleurl/src/gurl.h"
 
 namespace cobalt {
@@ -80,8 +79,6 @@
   void OnWindowClosed();
   void OnWindowClosedInternal();
 
-  media::MediaModuleStub stub_media_module_;
-
   WebModule::OnRenderTreeProducedCallback render_tree_produced_callback_;
 
   scoped_ptr<WebModule> web_module_;
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc
index 12bbc04..def7e22 100644
--- a/src/cobalt/browser/switches.cc
+++ b/src/cobalt/browser/switches.cc
@@ -137,10 +137,6 @@
 // frames has been collected.
 const char kFPSOverlay[] = "fps_overlay";
 
-// Disables the hard-coded navigation whitelist without disabling any other
-// security checks. This is enabled in production(gold) builds.
-const char kDisableNavigationWhitelist[] = "disable_navigation_whitelist";
-
 // Determines the capacity of the image cache which manages image surfaces
 // downloaded from a web page.  While it depends on the platform, often (and
 // ideally) these images are cached within GPU memory.
diff --git a/src/cobalt/browser/switches.h b/src/cobalt/browser/switches.h
index dd36528..812b1bc 100644
--- a/src/cobalt/browser/switches.h
+++ b/src/cobalt/browser/switches.h
@@ -48,7 +48,6 @@
 extern const char kWebDriverPort[];
 #endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
 
-extern const char kDisableNavigationWhitelist[];
 extern const char kFPSPrint[];
 extern const char kFPSOverlay[];
 extern const char kImageCacheSizeInBytes[];
diff --git a/src/cobalt/browser/testdata/mtm-demo/mtm.html b/src/cobalt/browser/testdata/mtm-demo/mtm.html
index e91a3cc..eeee431 100644
--- a/src/cobalt/browser/testdata/mtm-demo/mtm.html
+++ b/src/cobalt/browser/testdata/mtm-demo/mtm.html
@@ -21,6 +21,28 @@
       background-color: white;
       color: black;
     }
+
+    @keyframes blink {
+      from {background-color: white;}
+      to {background-color: black;}
+    }
+
+    .spinner {
+      position: absolute;
+      left: 0;
+      bottom: 0;
+      animation: blink 1s infinite alternate;
+      width: 20px;
+      height: 20px;
+    }
+
+    #fps {
+      position: absolute;
+      left: 50px;
+      bottom: 0;
+      background-color: white;
+      color: black;
+    }
   </style>
 
   <script>
@@ -63,6 +85,37 @@
         0x8017, camera3D.DOM_CAMERA_YAW, degreesPerSecond);
     camera3D.createKeyMapping(
         0x8018, camera3D.DOM_CAMERA_YAW, -degreesPerSecond);
+
+    // Update the frame rate counter at a regular interval.
+    function UpdateFPS() {
+      if ('h5vcc' in window && 'cVal' in window.h5vcc) {
+        // Query Cobalt for the average amount of time between the start of
+        // each frame.  Translate that into a framerate and then update a
+        // framerate counter on the window.
+        var average_frame_time_in_us = window.h5vcc.cVal.getValue(
+            'Renderer.Rasterize.DurationInterval.Avg');
+        if (!average_frame_time_in_us || average_frame_time_in_us <= 0) {
+          // In older versions of Cobalt use a different name for the framerate
+          // counter, so try falling back to that if the first fails.
+          average_frame_time_in_us = window.h5vcc.cVal.getValue(
+              'Renderer.Rasterize.Duration.Avg');
+        }
+
+        if (average_frame_time_in_us && average_frame_time_in_us > 0) {
+          // Convert frame time into frame rate (by taking the inverse).
+          // We also multiply by 1000000 to convert from microseconds to
+          // seconds.
+          var average_frames_per_second =
+              Math.round(1000000.0 / average_frame_time_in_us);
+
+          // Update the display with our calculated frame rate.
+          var fps_counter = document.getElementById('fps');
+          fps_counter.innerHTML = 'FPS: ' + average_frames_per_second;
+        }
+      }
+      window.setTimeout(UpdateFPS, 1000);
+    }
+    window.setTimeout(UpdateFPS, 1000);
   </script>
 </head>
 
@@ -72,6 +125,14 @@
     Use either the keyboard keys, direction keys, or analog joystick/thumbstick
     to look around.
   </div>
+  <!-- The spinner is required in order to get around an implementation detail
+       of the 'Renderer.Rasterize.DurationInterval.Avg' cval that we rely on
+       for measuring the framerate.  In a nutshell, that cval is only updated
+       when a CSS animation is active, but not when a video is playing, even
+       though both of these things result in a continual re-rasterization of
+       the UI/video. -->
+  <div class="spinner"></div>
+  <div id="fps"></div>
 </body>
 
 </html>
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc
index 4026fb1..6a5599a 100644
--- a/src/cobalt/browser/web_module.cc
+++ b/src/cobalt/browser/web_module.cc
@@ -184,7 +184,8 @@
 
   void SetSize(math::Size window_dimensions, float video_pixel_ratio);
   void SetCamera3D(const scoped_refptr<input::Camera3D>& camera_3d);
-  void SetMediaModule(media::MediaModule* media_module);
+  void SetWebMediaPlayerFactory(
+      media::WebMediaPlayerFactory* web_media_player_factory);
   void SetImageCacheCapacity(int64_t bytes);
   void SetRemoteTypefaceCacheCapacity(int64_t bytes);
   void SetJavascriptGcThreshold(int64_t bytes);
@@ -527,8 +528,9 @@
       dom_parser_.get(), fetcher_factory_.get(), &resource_provider_,
       animated_image_tracker_.get(), image_cache_.get(),
       reduced_image_cache_capacity_manager_.get(), remote_typeface_cache_.get(),
-      mesh_cache_.get(), local_storage_database_.get(), data.media_module,
-      data.media_module, execution_state_.get(), script_runner_.get(),
+      mesh_cache_.get(), local_storage_database_.get(),
+      data.can_play_type_handler, data.web_media_player_factory,
+      execution_state_.get(), script_runner_.get(),
       global_environment_->script_value_factory(), media_source_registry_.get(),
       web_module_stat_tracker_->dom_stat_tracker(), data.initial_url,
       data.network_module->GetUserAgent(),
@@ -536,8 +538,7 @@
       data.options.navigation_callback,
       base::Bind(&WebModule::Impl::OnError, base::Unretained(this)),
       data.network_module->cookie_jar(), data.network_module->GetPostSender(),
-      data.options.location_policy, data.options.require_csp,
-      data.options.csp_enforcement_mode,
+      data.options.require_csp, data.options.csp_enforcement_mode,
       base::Bind(&WebModule::Impl::OnCspPolicyChanged, base::Unretained(this)),
       base::Bind(&WebModule::Impl::OnRanAnimationFrameCallbacks,
                  base::Unretained(this)),
@@ -559,9 +560,9 @@
   DCHECK(window_weak_);
 
   environment_settings_.reset(new dom::DOMSettings(
-      kDOMMaxElementDepth, fetcher_factory_.get(), data.network_module,
-      data.media_module, window_, media_source_registry_.get(),
-      blob_registry_.get(), data.media_module, javascript_engine_.get(),
+      kDOMMaxElementDepth, fetcher_factory_.get(), data.network_module, window_,
+      media_source_registry_.get(), blob_registry_.get(),
+      data.can_play_type_handler, javascript_engine_.get(),
       global_environment_.get(), &mutation_observer_task_manager_,
       data.options.dom_settings_options));
   DCHECK(environment_settings_);
@@ -713,9 +714,10 @@
   // JavaScript is being run. Track it in the global stats.
   dom::GlobalStats::GetInstance()->StartJavaScriptEvent();
 
-  // This should only be called for Cobalt javascript, errors not expected.
-  *result = script_runner_->Execute(script_utf8, script_location, out_succeeded,
-                                    true /*mute error reports*/);
+  // This should only be called for Cobalt JavaScript, error reports are
+  // allowed.
+  *result = script_runner_->Execute(script_utf8, script_location,
+                                    false /*mute_errors*/, out_succeeded);
 
   // JavaScript is done running. Stop tracking it in the global stats.
   dom::GlobalStats::GetInstance()->StopJavaScriptEvent();
@@ -863,11 +865,9 @@
   window_->SetCamera3D(camera_3d);
 }
 
-void WebModule::Impl::SetMediaModule(media::MediaModule* media_module) {
-  window_->set_can_play_type_handler(media_module);
-  window_->set_web_media_player_factory(media_module);
-  environment_settings_->set_media_module(media_module);
-  environment_settings_->set_can_play_type_handler(media_module);
+void WebModule::Impl::SetWebMediaPlayerFactory(
+    media::WebMediaPlayerFactory* web_media_player_factory) {
+  window_->set_web_media_player_factory(web_media_player_factory);
 }
 
 void WebModule::Impl::SetApplicationState(base::ApplicationState state) {
@@ -1048,16 +1048,18 @@
     const OnErrorCallback& error_callback,
     const CloseCallback& window_close_callback,
     const base::Closure& window_minimize_callback,
-    media::MediaModule* media_module, network::NetworkModule* network_module,
-    const math::Size& window_dimensions, float video_pixel_ratio,
-    render_tree::ResourceProvider* resource_provider, float layout_refresh_rate,
-    const Options& options)
+    media::CanPlayTypeHandler* can_play_type_handler,
+    media::WebMediaPlayerFactory* web_media_player_factory,
+    network::NetworkModule* network_module, const math::Size& window_dimensions,
+    float video_pixel_ratio, render_tree::ResourceProvider* resource_provider,
+    float layout_refresh_rate, const Options& options)
     : thread_(options.name.c_str()) {
   ConstructionData construction_data(
       initial_url, initial_application_state, render_tree_produced_callback,
       error_callback, window_close_callback, window_minimize_callback,
-      media_module, network_module, window_dimensions, video_pixel_ratio,
-      resource_provider, kDOMMaxElementDepth, layout_refresh_rate, options);
+      can_play_type_handler, web_media_player_factory, network_module,
+      window_dimensions, video_pixel_ratio, resource_provider,
+      kDOMMaxElementDepth, layout_refresh_rate, options);
 
   // Start the dedicated thread and create the internal implementation
   // object on that thread.
@@ -1258,10 +1260,12 @@
                             base::Unretained(impl_.get()), camera_3d));
 }
 
-void WebModule::SetMediaModule(media::MediaModule* media_module) {
+void WebModule::SetWebMediaPlayerFactory(
+    media::WebMediaPlayerFactory* web_media_player_factory) {
   message_loop()->PostTask(
-      FROM_HERE, base::Bind(&WebModule::Impl::SetMediaModule,
-                            base::Unretained(impl_.get()), media_module));
+      FROM_HERE,
+      base::Bind(&WebModule::Impl::SetWebMediaPlayerFactory,
+                 base::Unretained(impl_.get()), web_media_player_factory));
 }
 
 void WebModule::SetImageCacheCapacity(int64_t bytes) {
diff --git a/src/cobalt/browser/web_module.h b/src/cobalt/browser/web_module.h
index 281664b..b46056f 100644
--- a/src/cobalt/browser/web_module.h
+++ b/src/cobalt/browser/web_module.h
@@ -49,7 +49,8 @@
 #include "cobalt/layout/layout_manager.h"
 #include "cobalt/loader/fetcher_factory.h"
 #include "cobalt/math/size.h"
-#include "cobalt/media/media_module.h"
+#include "cobalt/media/can_play_type_handler.h"
+#include "cobalt/media/web_media_player_factory.h"
 #include "cobalt/network/network_module.h"
 #include "cobalt/render_tree/resource_provider.h"
 #include "cobalt/script/global_environment.h"
@@ -122,12 +123,6 @@
     // Options to customize DOMSettings.
     dom::DOMSettings::Options dom_settings_options;
 
-    // Location policy to enforce, formatted as a Content Security Policy
-    // directive, e.g. "h5vcc-location-src 'self'"
-    // This is used to implement a navigation jail, so that location
-    // can't be changed from the whitelisted origins.
-    std::string location_policy;
-
     // Whether Cobalt is forbidden to render without receiving CSP headers.
     csp::CSPHeaderPolicy require_csp;
 
@@ -213,7 +208,8 @@
             const OnErrorCallback& error_callback,
             const CloseCallback& window_close_callback,
             const base::Closure& window_minimize_callback,
-            media::MediaModule* media_module,
+            media::CanPlayTypeHandler* can_play_type_handler,
+            media::WebMediaPlayerFactory* web_media_player_factory,
             network::NetworkModule* network_module,
             const math::Size& window_dimensions, float video_pixel_ratio,
             render_tree::ResourceProvider* resource_provider,
@@ -266,7 +262,8 @@
   void SetSize(const math::Size& window_dimensions, float video_pixel_ratio);
 
   void SetCamera3D(const scoped_refptr<input::Camera3D>& camera_3d);
-  void SetMediaModule(media::MediaModule* media_module);
+  void SetWebMediaPlayerFactory(
+      media::WebMediaPlayerFactory* web_media_player_factory);
   void SetImageCacheCapacity(int64_t bytes);
   void SetRemoteTypefaceCacheCapacity(int64_t bytes);
   void SetJavascriptGcThreshold(int64_t bytes);
@@ -294,7 +291,8 @@
         const OnErrorCallback& error_callback,
         const CloseCallback& window_close_callback,
         const base::Closure& window_minimize_callback,
-        media::MediaModule* media_module,
+        media::CanPlayTypeHandler* can_play_type_handler,
+        media::WebMediaPlayerFactory* web_media_player_factory,
         network::NetworkModule* network_module,
         const math::Size& window_dimensions, float video_pixel_ratio,
         render_tree::ResourceProvider* resource_provider,
@@ -306,7 +304,8 @@
           error_callback(error_callback),
           window_close_callback(window_close_callback),
           window_minimize_callback(window_minimize_callback),
-          media_module(media_module),
+          can_play_type_handler(can_play_type_handler),
+          web_media_player_factory(web_media_player_factory),
           network_module(network_module),
           window_dimensions(window_dimensions),
           video_pixel_ratio(video_pixel_ratio),
@@ -321,7 +320,8 @@
     OnErrorCallback error_callback;
     const CloseCallback& window_close_callback;
     const base::Closure& window_minimize_callback;
-    media::MediaModule* media_module;
+    media::CanPlayTypeHandler* can_play_type_handler;
+    media::WebMediaPlayerFactory* web_media_player_factory;
     network::NetworkModule* network_module;
     math::Size window_dimensions;
     float video_pixel_ratio;
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 6125516..d0d80b7 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-104689
\ No newline at end of file
+108984
\ No newline at end of file
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi
index 867adb5..056ae29 100644
--- a/src/cobalt/build/config/base.gypi
+++ b/src/cobalt/build/config/base.gypi
@@ -462,9 +462,8 @@
     'platform_libraries%': [],
 
     # The only currently-supported Javascript engine is 'mozjs-45'.
-    # TODO: Figure out how to massage gyp the right way to make this work
-    # as expected, rather than requiring it to be set for each platform.
-    #'javascript_engine%': 'mozjs-45',
+    'default_javascript_engine': 'mozjs-45',
+    'javascript_engine%': '<(default_javascript_engine)',
 
     # Disable JIT and run in interpreter-only mode by default. It can be set
     # to 1 to run in JIT mode.  For SpiderMonkey in particular, we have found
diff --git a/src/cobalt/build/config/starboard.py b/src/cobalt/build/config/starboard.py
index 2af50cd..fdef871 100644
--- a/src/cobalt/build/config/starboard.py
+++ b/src/cobalt/build/config/starboard.py
@@ -16,6 +16,7 @@
 import logging
 import os
 
+import cobalt.tools.webdriver_benchmark_config as wb_config
 from config.base import Configs
 from config.base import PlatformConfigBase
 
@@ -89,3 +90,22 @@
         'enable_vr': vr_enabled,
     }
     return variables
+
+  def WebdriverBenchmarksEnabled(self):
+    """Determines if webdriver benchmarks are enabled or not.
+
+    Returns:
+      True if webdriver benchmarks can run on this platform, False if not.
+    """
+    return False
+
+  def GetDefaultSampleSize(self):
+    return wb_config.STANDARD_SIZE
+
+  def GetWebdriverBenchmarksTargetParams(self):
+    """Gets command line params to pass to the Cobalt executable."""
+    return []
+
+  def GetWebdriverBenchmarksParams(self):
+    """Gets command line params to pass to the webdriver benchmark script."""
+    return []
diff --git a/src/cobalt/csp/content_security_policy.cc b/src/cobalt/csp/content_security_policy.cc
index 302af17..68163e5 100644
--- a/src/cobalt/csp/content_security_policy.cc
+++ b/src/cobalt/csp/content_security_policy.cc
@@ -212,11 +212,6 @@
   AddPolicyFromHeaderValue(header, type, source);
 }
 
-void ContentSecurityPolicy::SetNavigationPolicy(const std::string& policy) {
-  navigation_policy_.reset(new DirectiveList(
-      this, base::StringPiece(policy), kHeaderTypeEnforce, kHeaderSourceHTTP));
-}
-
 bool ContentSecurityPolicy::UrlMatchesSelf(const GURL& url) const {
   return self_source_->Matches(url, kDidNotRedirect);
 }
@@ -493,16 +488,9 @@
     const GURL& url, ContentSecurityPolicy::RedirectStatus redirect_status,
     ContentSecurityPolicy::ReportingStatus reporting_status) const {
   // Note that this is a Cobalt-specific policy to prevent navigation
-  // to any unexpected URLs. Navigation is restrictive by default, as
-  // opposed to the permissive policy for other directives.
-
-  if (!navigation_policy_) {
-    DLOG(ERROR) << "SetNavigationFallbackPolicy() was not called.";
-    return false;
-  }
-  // TODO: Re-enable respecting the navigation whitelist.
-  return navigation_policy_->AllowNavigateToSource(url, redirect_status,
-                                                   reporting_status);
+  // to any unexpected URLs.
+  FOR_ALL_POLICIES_3(AllowNavigateToSource, url, redirect_status,
+                     reporting_status);
 }
 
 bool ContentSecurityPolicy::AllowStyleFromSource(
diff --git a/src/cobalt/csp/content_security_policy.h b/src/cobalt/csp/content_security_policy.h
index 95789a1..bb2e883 100644
--- a/src/cobalt/csp/content_security_policy.h
+++ b/src/cobalt/csp/content_security_policy.h
@@ -140,7 +140,6 @@
   void OnReceiveHeaders(const ResponseHeaders& headers);
   void OnReceiveHeader(const std::string& header, HeaderType header_type,
                        HeaderSource header_source);
-  void SetNavigationPolicy(const std::string& header);
 
   bool UrlMatchesSelf(const GURL& url) const;
   bool SchemeMatchesSelf(const GURL& url) const;
@@ -261,7 +260,6 @@
                                 HeaderSource source);
 
   PolicyList policies_;
-  scoped_ptr<DirectiveList> navigation_policy_;
   scoped_ptr<Source> self_source_;
   std::string self_scheme_;
   std::string disable_eval_error_message_;
diff --git a/src/cobalt/debug/content/devtools/components_lazy_module.js b/src/cobalt/debug/content/devtools/components_lazy_module.js
index b81ba09..6aa87c5 100644
--- a/src/cobalt/debug/content/devtools/components_lazy_module.js
+++ b/src/cobalt/debug/content/devtools/components_lazy_module.js
@@ -101,7 +101,7 @@
 WebInspector.FilmStripView.Dialog.prototype={_resize:function()
 {if(!this._dialog){this._dialog=new WebInspector.Dialog();this.show(this._dialog.element);this._dialog.setWrapsContent(true);this._dialog.show();}
 this._dialog.contentResized();},_keyDown:function(event)
-{switch(event.keyIdentifier){case"Left":if(WebInspector.isMac()&&event.metaKey)
+{switch(event.key){case"Left":if(WebInspector.isMac()&&event.metaKey)
 this._onFirstFrame();else
 this._onPrevFrame();break;case"Right":if(WebInspector.isMac()&&event.metaKey)
 this._onLastFrame();else
diff --git a/src/cobalt/debug/content/devtools/devices_module.js b/src/cobalt/debug/content/devtools/devices_module.js
index ee075ba..dad1a0f 100644
--- a/src/cobalt/debug/content/devtools/devices_module.js
+++ b/src/cobalt/debug/content/devtools/devices_module.js
@@ -62,7 +62,7 @@
 function updateViewMoreTitle()
 {viewMore.textContent=pages.classList.contains("device-view-more-toggled")?WebInspector.UIString("View less tabs\u2026"):WebInspector.UIString("View more tabs\u2026");}
 function newTabKeyDown(event)
-{if(event.keyIdentifier==="Enter"){event.consume(true);openNewTab();}}
+{if(event.key==="Enter"){event.consume(true);openNewTab();}}
 function openNewTab()
 {if(section.browser){InspectorFrontendHost.openRemotePage(section.browser.id,newTabInput.value.trim()||"about:blank");newTabInput.value="";}}},_updateBrowserSection:function(section,browser)
 {if(!section.browser||section.browser.adbBrowserName!==browser.adbBrowserName||section.browser.adbBrowserVersion!==browser.adbBrowserVersion){if(browser.adbBrowserVersion)
diff --git a/src/cobalt/debug/content/devtools/devtools.js b/src/cobalt/debug/content/devtools/devtools.js
index 05c2b25..3faa580 100644
--- a/src/cobalt/debug/content/devtools/devtools.js
+++ b/src/cobalt/debug/content/devtools/devtools.js
@@ -219,7 +219,7 @@
     },
 
     /**
-     * @param {{type: string, keyIdentifier: string, keyCode: number, modifiers: number}} event
+     * @param {{type: string, key: string, keyCode: number, modifiers: number}} event
      */
     keyEventUnhandled: function(event)
     {
diff --git a/src/cobalt/debug/content/devtools/devtools_extension_api.js b/src/cobalt/debug/content/devtools/devtools_extension_api.js
index b409652..9b575f7 100644
--- a/src/cobalt/debug/content/devtools/devtools_extension_api.js
+++ b/src/cobalt/debug/content/devtools/devtools_extension_api.js
@@ -805,14 +805,14 @@
 {
     const Esc = "U+001B";
     // We only care about global hotkeys, not about random text
-    if (!event.ctrlKey && !event.altKey && !event.metaKey && !/^F\d+$/.test(event.keyIdentifier) && event.keyIdentifier !== Esc)
+    if (!event.ctrlKey && !event.altKey && !event.metaKey && !/^F\d+$/.test(event.key) && event.key !== Esc)
         return;
     var requestPayload = {
         eventType: event.type,
         ctrlKey: event.ctrlKey,
         altKey: event.altKey,
         metaKey: event.metaKey,
-        keyIdentifier: event.keyIdentifier,
+        key: event.key,
         location: event.location,
         keyCode: event.keyCode
     };
diff --git a/src/cobalt/debug/content/devtools/elements_module.js b/src/cobalt/debug/content/devtools/elements_module.js
index cb6558d..53917ab 100644
--- a/src/cobalt/debug/content/devtools/elements_module.js
+++ b/src/cobalt/debug/content/devtools/elements_module.js
@@ -58,8 +58,8 @@
 return;var document=this._popover.element.ownerDocument;this._isHidden=true;this._popover.hide();if(this._scrollerElement)
 this._scrollerElement.removeEventListener("scroll",this._repositionBound,false);document.removeEventListener("mousedown",this._hideProxy,false);document.defaultView.removeEventListener("resize",this._hideProxy,false);if(this._hiddenCallback)
 this._hiddenCallback.call(null,!!commitEdit);WebInspector.setCurrentFocusElement(this._previousFocusElement);delete this._previousFocusElement;delete this._anchorElement;if(this._view){this._view.detach();this._view.contentElement.removeEventListener("keydown",this._boundOnKeyDown,false);this._view.contentElement.removeEventListener("focusout",this._boundFocusOut,false);delete this._view;}},_onKeyDown:function(event)
-{if(event.keyIdentifier==="Enter"){this.hide(true);event.consume(true);return;}
-if(event.keyIdentifier==="U+001B"){this.hide(false);event.consume(true);}},__proto__:WebInspector.Object.prototype}
+{if(event.key==="Enter"){this.hide(true);event.consume(true);return;}
+if(event.key==="U+001B"){this.hide(false);event.consume(true);}},__proto__:WebInspector.Object.prototype}
 WebInspector.BezierPopoverIcon=function(treeElement,stylesPopoverHelper,text)
 {this._treeElement=treeElement;this._stylesPopoverHelper=stylesPopoverHelper;this._createDOM(text);this._boundBezierChanged=this._bezierChanged.bind(this);}
 WebInspector.BezierPopoverIcon.prototype={element:function()
@@ -220,7 +220,7 @@
 format=this._originalFormat===cf.ShortHEX?cf.ShortHEX:cf.HEX;this._innerSetColor(undefined,"",format,WebInspector.Spectrum._ChangeSource.Other);},_inputChanged:function(event)
 {function elementValue(element)
 {return element.value;}
-var inputElement=(event.currentTarget);var arrowKeyOrMouseWheelEvent=(event.keyIdentifier==="Up"||event.keyIdentifier==="Down"||event.type==="mousewheel");var pageKeyPressed=(event.keyIdentifier==="PageUp"||event.keyIdentifier==="PageDown");if(arrowKeyOrMouseWheelEvent||pageKeyPressed){var newValue=WebInspector.createReplacementString(inputElement.value,event);if(newValue){inputElement.value=newValue;inputElement.selectionStart=0;inputElement.selectionEnd=newValue.length;}
+var inputElement=(event.currentTarget);var arrowKeyOrMouseWheelEvent=(event.key==="Up"||event.key==="Down"||event.type==="mousewheel");var pageKeyPressed=(event.key==="PageUp"||event.key==="PageDown");if(arrowKeyOrMouseWheelEvent||pageKeyPressed){var newValue=WebInspector.createReplacementString(inputElement.value,event);if(newValue){inputElement.value=newValue;inputElement.selectionStart=0;inputElement.selectionEnd=newValue.length;}
 event.consume(true);}
 const cf=WebInspector.Color.Format;var colorString;if(this._colorFormat===cf.HEX||this._colorFormat===cf.ShortHEX){colorString=this._hexValue.value;}else{var format=this._colorFormat===cf.RGB?"rgba":"hsla";var values=this._textValues.map(elementValue).join(",");colorString=String.sprintf("%s(%s)",format,values);}
 var color=WebInspector.Color.parse(colorString);if(!color)
@@ -775,8 +775,8 @@
 {this._updateModifiedNodes();},handleShortcut:function(event)
 {var node=this.selectedDOMNode();if(!node)
 return;var treeElement=node[this._treeElementSymbol];if(!treeElement)
-return;if(WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event)&&node.parentNode){if(event.keyIdentifier==="Up"&&node.previousSibling){node.moveTo(node.parentNode,node.previousSibling,this.selectNodeAfterEdit.bind(this,treeElement.expanded));event.handled=true;return;}
-if(event.keyIdentifier==="Down"&&node.nextSibling){node.moveTo(node.parentNode,node.nextSibling.nextSibling,this.selectNodeAfterEdit.bind(this,treeElement.expanded));event.handled=true;return;}}},toggleEditAsHTML:function(node,startEditing,callback)
+return;if(WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event)&&node.parentNode){if(event.key==="Up"&&node.previousSibling){node.moveTo(node.parentNode,node.previousSibling,this.selectNodeAfterEdit.bind(this,treeElement.expanded));event.handled=true;return;}
+if(event.key==="Down"&&node.nextSibling){node.moveTo(node.parentNode,node.nextSibling.nextSibling,this.selectNodeAfterEdit.bind(this,treeElement.expanded));event.handled=true;return;}}},toggleEditAsHTML:function(node,startEditing,callback)
 {var treeElement=node[this._treeElementSymbol];if(!treeElement||!treeElement.hasEditableNode())
 return;if(node.pseudoType())
 return;var parentNode=node.parentNode;var index=node.index;var wasExpanded=treeElement.expanded;treeElement.toggleEditAsHTML(editingFinished.bind(this),startEditing);function editingFinished(success)
@@ -1177,7 +1177,7 @@
 {var input=createElement("input");input.placeholder=placeholder;function searchHandler()
 {var regex=input.value?new RegExp(input.value.escapeForRegExp(),"i"):null;filterCallback(regex);container.classList.toggle("styles-filter-engaged",!!input.value);}
 input.addEventListener("input",searchHandler,false);function keydownHandler(event)
-{var Esc="U+001B";if(event.keyIdentifier!==Esc||!input.value)
+{var Esc="U+001B";if(event.key!==Esc||!input.value)
 return;event.consume(true);input.value="";searchHandler();}
 input.addEventListener("keydown",keydownHandler,false);input.setFilterValue=setFilterValue;function setFilterValue(value)
 {input.value=value;input.focus();searchHandler();}
@@ -1441,8 +1441,8 @@
 var proxyElement=this._prompt.attachAndStartEditing(selectElement,blurListener.bind(this,context));proxyElement.addEventListener("keydown",this._editingNameValueKeyDown.bind(this,context),false);proxyElement.addEventListener("keypress",this._editingNameValueKeyPress.bind(this,context),false);proxyElement.addEventListener("input",this._editingNameValueInput.bind(this,context),false);if(isEditingName)
 proxyElement.addEventListener("paste",pasteHandler.bind(this,context),false);selectElement.getComponentSelection().setBaseAndExtent(selectElement,0,selectElement,1);},_editingNameValueKeyDown:function(context,event)
 {if(event.handled)
-return;var result;if(isEnterKey(event)){event.preventDefault();result="forward";}else if(event.keyCode===WebInspector.KeyboardShortcut.Keys.Esc.code||event.keyIdentifier==="U+001B")
-result="cancel";else if(!context.isEditingName&&this._newProperty&&event.keyCode===WebInspector.KeyboardShortcut.Keys.Backspace.code){var selection=event.target.getComponentSelection();if(selection.isCollapsed&&!selection.focusOffset){event.preventDefault();result="backward";}}else if(event.keyIdentifier==="U+0009"){result=event.shiftKey?"backward":"forward";event.preventDefault();}
+return;var result;if(isEnterKey(event)){event.preventDefault();result="forward";}else if(event.keyCode===WebInspector.KeyboardShortcut.Keys.Esc.code||event.key==="U+001B")
+result="cancel";else if(!context.isEditingName&&this._newProperty&&event.keyCode===WebInspector.KeyboardShortcut.Keys.Backspace.code){var selection=event.target.getComponentSelection();if(selection.isCollapsed&&!selection.focusOffset){event.preventDefault();result="backward";}}else if(event.key==="U+0009"){result=event.shiftKey?"backward":"forward";event.preventDefault();}
 if(result){switch(result){case"cancel":this.editingCancelled(null,context);break;case"forward":case"backward":this.editingCommitted(event.target.textContent,context,result);break;}
 event.consume();return;}},_editingNameValueKeyPress:function(context,event)
 {function shouldCommitValueSemicolon(text,cursorPosition)
@@ -1510,7 +1510,7 @@
 {WebInspector.TextPrompt.call(this,this._buildPropertyCompletions.bind(this),WebInspector.StyleValueDelimiters);this.setSuggestBoxEnabled(true);this._cssCompletions=cssCompletions;this._treeElement=treeElement;this._isEditingName=isEditingName;if(!isEditingName)
 this.disableDefaultSuggestionForEmptyInput();}
 WebInspector.StylesSidebarPane.CSSPropertyPrompt.prototype={onKeyDown:function(event)
-{switch(event.keyIdentifier){case"Up":case"Down":case"PageUp":case"PageDown":if(this._handleNameOrValueUpDown(event)){event.preventDefault();return;}
+{switch(event.key){case"Up":case"Down":case"PageUp":case"PageDown":if(this._handleNameOrValueUpDown(event)){event.preventDefault();return;}
 break;case"Enter":if(this.autoCompleteElement&&!this.autoCompleteElement.textContent.length){this.tabKeyPressed();return;}
 break;}
 WebInspector.TextPrompt.prototype.onKeyDown.call(this,event);},onMouseWheel:function(event)
@@ -1697,8 +1697,8 @@
 {var nodes=(event.data);this._breadcrumbs.updateNodes(nodes);},_crumbNodeSelected:function(event)
 {var node=(event.data);this.selectDOMNode(node,true);},handleShortcut:function(event)
 {function handleUndoRedo(treeOutline)
-{if(WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event)&&!event.shiftKey&&event.keyIdentifier==="U+005A"){treeOutline.domModel().undo();event.handled=true;return;}
-var isRedoKey=WebInspector.isMac()?event.metaKey&&event.shiftKey&&event.keyIdentifier==="U+005A":event.ctrlKey&&event.keyIdentifier==="U+0059";if(isRedoKey){treeOutline.domModel().redo();event.handled=true;}}
+{if(WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event)&&!event.shiftKey&&event.key==="U+005A"){treeOutline.domModel().undo();event.handled=true;return;}
+var isRedoKey=WebInspector.isMac()?event.metaKey&&event.shiftKey&&event.key==="U+005A":event.ctrlKey&&event.key==="U+0059";if(isRedoKey){treeOutline.domModel().redo();event.handled=true;}}
 if(WebInspector.isEditing()&&event.keyCode!==WebInspector.KeyboardShortcut.Keys.F2.code)
 return;var treeOutline=null;for(var i=0;i<this._treeOutlines.length;++i){if(this._treeOutlines[i].selectedDOMNode()===this._lastValidSelectedNode)
 treeOutline=this._treeOutlines[i];}
diff --git a/src/cobalt/debug/content/devtools/inspector.js b/src/cobalt/debug/content/devtools/inspector.js
index 9f07d27..fd09fea 100644
--- a/src/cobalt/debug/content/devtools/inspector.js
+++ b/src/cobalt/debug/content/devtools/inspector.js
@@ -683,7 +683,7 @@
 {var node=this.elementFromPoint(x,y);while(node&&node.shadowRoot)
 node=node.shadowRoot.elementFromPoint(x,y);return node;}
 function isEnterKey(event)
-{return event.keyCode!==229&&event.keyIdentifier==="Enter";}
+{return event.keyCode!==229&&event.key==="Enter";}
 function isEscKey(event)
 {return event.keyCode===27;}
 function consumeEvent(e)
@@ -1683,11 +1683,11 @@
 return false;},_treeKeyDown:function(event)
 {if(event.target!==this._contentElement)
 return;if(!this.selectedTreeElement||event.shiftKey||event.metaKey||event.ctrlKey)
-return;var handled=false;var nextSelectedElement;if(event.keyIdentifier==="Up"&&!event.altKey){handled=this.selectPrevious();}else if(event.keyIdentifier==="Down"&&!event.altKey){handled=this.selectNext();}else if(event.keyIdentifier==="Left"){if(this.selectedTreeElement.expanded){if(event.altKey)
+return;var handled=false;var nextSelectedElement;if(event.key==="Up"&&!event.altKey){handled=this.selectPrevious();}else if(event.key==="Down"&&!event.altKey){handled=this.selectNext();}else if(event.key==="Left"){if(this.selectedTreeElement.expanded){if(event.altKey)
 this.selectedTreeElement.collapseRecursively();else
 this.selectedTreeElement.collapse();handled=true;}else if(this.selectedTreeElement.parent&&!this.selectedTreeElement.parent.root){handled=true;if(this.selectedTreeElement.parent.selectable){nextSelectedElement=this.selectedTreeElement.parent;while(nextSelectedElement&&!nextSelectedElement.selectable)
 nextSelectedElement=nextSelectedElement.parent;handled=nextSelectedElement?true:false;}else if(this.selectedTreeElement.parent)
-this.selectedTreeElement.parent.collapse();}}else if(event.keyIdentifier==="Right"){if(!this.selectedTreeElement.revealed()){this.selectedTreeElement.reveal();handled=true;}else if(this.selectedTreeElement._expandable){handled=true;if(this.selectedTreeElement.expanded){nextSelectedElement=this.selectedTreeElement.firstChild();while(nextSelectedElement&&!nextSelectedElement.selectable)
+this.selectedTreeElement.parent.collapse();}}else if(event.key==="Right"){if(!this.selectedTreeElement.revealed()){this.selectedTreeElement.reveal();handled=true;}else if(this.selectedTreeElement._expandable){handled=true;if(this.selectedTreeElement.expanded){nextSelectedElement=this.selectedTreeElement.firstChild();while(nextSelectedElement&&!nextSelectedElement.selectable)
 nextSelectedElement=nextSelectedElement.nextSibling;handled=nextSelectedElement?true:false;}else{if(event.altKey)
 this.selectedTreeElement.expandRecursively();else
 this.selectedTreeElement.expand();}}}else if(event.keyCode===8||event.keyCode===46)
@@ -1907,7 +1907,7 @@
 return result;},shortcutTitleForAction:function(actionId)
 {var descriptors=this.shortcutDescriptorsForAction(actionId);if(descriptors.length)
 return descriptors[0].name;},handleShortcut:function(event)
-{this.handleKey(WebInspector.KeyboardShortcut.makeKeyFromEvent(event),event.keyIdentifier,event);},handleKey:function(key,keyIdentifier,event)
+{this.handleKey(WebInspector.KeyboardShortcut.makeKeyFromEvent(event),event.key,event);},handleKey:function(key,key,event)
 {var keyModifiers=key>>8;var actions=this._applicableActions(key);if(!actions.length)
 return;if(WebInspector.GlassPane.DefaultFocusedViewStack.length>1){if(event&&!isPossiblyInputKey())
 event.consume(true);return;}
@@ -1917,7 +1917,7 @@
 {delete this._pendingActionTimer;var action=actions.shift();if(!action||handled)
 return;action.execute().then(processNextAction.bind(this));}
 function isPossiblyInputKey()
-{if(!event||!WebInspector.isEditing()||/^F\d+|Control|Shift|Alt|Meta|Win|U\+001B$/.test(keyIdentifier))
+{if(!event||!WebInspector.isEditing()||/^F\d+|Control|Shift|Alt|Meta|Win|U\+001B$/.test(key))
 return false;if(!keyModifiers)
 return true;var modifiers=WebInspector.KeyboardShortcut.Modifiers;if((keyModifiers&(modifiers.Ctrl|modifiers.Alt))===(modifiers.Ctrl|modifiers.Alt))
 return WebInspector.isWin();return!hasModifier(modifiers.Ctrl)&&!hasModifier(modifiers.Alt)&&!hasModifier(modifiers.Meta);}
@@ -2165,7 +2165,7 @@
 this._suggestBox.hide();var filterQuery=this.value();this._regex=null;this._filterInputElement.classList.remove("filter-text-invalid");if(filterQuery){if(this._supportRegex&&this._regexCheckBox.checked){try{this._regex=new RegExp(filterQuery,"i");}catch(e){this._filterInputElement.classList.add("filter-text-invalid");}}else{this._regex=createPlainTextSearchRegex(filterQuery,"i");}}
 this._dispatchFilterChanged();},_dispatchFilterChanged:function()
 {this.dispatchEventToListeners(WebInspector.FilterUI.Events.FilterChanged,null);},_onInputKeyDown:function(event)
-{var handled=false;if(event.keyIdentifier==="U+0008"){this._suppressSuggestion=true;}else if(this._suggestBox.visible()){if(event.keyIdentifier==="U+001B"){this._cancelSuggestion();handled=true;}else if(event.keyIdentifier==="U+0009"){this._suggestBox.acceptSuggestion();this._valueChanged(true);handled=true;}else{handled=this._suggestBox.keyPressed((event));}}
+{var handled=false;if(event.key==="U+0008"){this._suppressSuggestion=true;}else if(this._suggestBox.visible()){if(event.key==="U+001B"){this._cancelSuggestion();handled=true;}else if(event.key==="U+0009"){this._suggestBox.acceptSuggestion();this._valueChanged(true);handled=true;}else{handled=this._suggestBox.keyPressed((event));}}
 if(handled)
 event.consume(true);return handled;},applySuggestion:function(suggestion,isIntermediateSuggestion)
 {if(!this._suggestionBuilder)
@@ -2221,8 +2221,8 @@
 {this._label.backgroundColor=backgroundColor;this._label.borderColor=borderColor;},__proto__:WebInspector.Object.prototype};WebInspector.ForwardedInputEventHandler=function()
 {InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.KeyEventUnhandled,this._onKeyEventUnhandled,this);}
 WebInspector.ForwardedInputEventHandler.prototype={_onKeyEventUnhandled:function(event)
-{var data=event.data;var type=(data.type);var keyIdentifier=(data.keyIdentifier);var keyCode=(data.keyCode);var modifiers=(data.modifiers);if(type!=="keydown")
-return;WebInspector.context.setFlavor(WebInspector.ShortcutRegistry.ForwardedShortcut,WebInspector.ShortcutRegistry.ForwardedShortcut.instance);WebInspector.shortcutRegistry.handleKey(WebInspector.KeyboardShortcut.makeKey(keyCode,modifiers),keyIdentifier);WebInspector.context.setFlavor(WebInspector.ShortcutRegistry.ForwardedShortcut,null);}}
+{var data=event.data;var type=(data.type);var key=(data.key);var keyCode=(data.keyCode);var modifiers=(data.modifiers);if(type!=="keydown")
+return;WebInspector.context.setFlavor(WebInspector.ShortcutRegistry.ForwardedShortcut,WebInspector.ShortcutRegistry.ForwardedShortcut.instance);WebInspector.shortcutRegistry.handleKey(WebInspector.KeyboardShortcut.makeKey(keyCode,modifiers),key);WebInspector.context.setFlavor(WebInspector.ShortcutRegistry.ForwardedShortcut,null);}}
 WebInspector.forwardedEventHandler=new WebInspector.ForwardedInputEventHandler();;WebInspector.HistoryInput=function()
 {}
 WebInspector.HistoryInput.create=function()
@@ -2286,11 +2286,11 @@
 {cleanUpAfterEditing();committedCallback(this,self.editorContent(editingContext),editingContext.oldText,context,moveDirection);}
 function defaultFinishHandler(event)
 {var isMetaOrCtrl=WebInspector.isMac()?event.metaKey&&!event.shiftKey&&!event.ctrlKey&&!event.altKey:event.ctrlKey&&!event.shiftKey&&!event.metaKey&&!event.altKey;if(isEnterKey(event)&&(event.isMetaOrCtrlForTest||!isMultiline||isMetaOrCtrl))
-return"commit";else if(event.keyCode===WebInspector.KeyboardShortcut.Keys.Esc.code||event.keyIdentifier==="U+001B")
-return"cancel";else if(!isMultiline&&event.keyIdentifier==="U+0009")
+return"commit";else if(event.keyCode===WebInspector.KeyboardShortcut.Keys.Esc.code||event.key==="U+001B")
+return"cancel";else if(!isMultiline&&event.key==="U+0009")
 return"move-"+(event.shiftKey?"backward":"forward");return"";}
 function handleEditingResult(result,event)
-{if(result==="commit"){editingCommitted.call(element);event.consume(true);}else if(result==="cancel"){editingCancelled.call(element);event.consume(true);}else if(result&&result.startsWith("move-")){moveDirection=result.substring(5);if(event.keyIdentifier!=="U+0009")
+{if(result==="commit"){editingCommitted.call(element);event.consume(true);}else if(result==="cancel"){editingCancelled.call(element);event.consume(true);}else if(result&&result.startsWith("move-")){moveDirection=result.substring(5);if(event.key!=="U+0009")
 blurEventListener();}}
 function pasteEventListener(event)
 {var result=pasteCallback(event);handleEditingResult(result,event);}
@@ -2680,7 +2680,7 @@
 apply();incrementForArrows(event);}
 function incrementForArrows(event)
 {if(!numeric)
-return;var increment=event.keyIdentifier==="Up"?1:event.keyIdentifier==="Down"?-1:0;if(!increment)
+return;var increment=event.key==="Up"?1:event.key==="Down"?-1:0;if(!increment)
 return;if(event.shiftKey)
 increment*=10;var value=inputElement.value;if(validatorCallback&&validatorCallback(value))
 return;value=Number(value);if(clearForZero&&!value)
@@ -2789,7 +2789,7 @@
 {var menuItemElement=this._highlightedMenuItemElement?this._highlightedMenuItemElement.nextSibling:this._contextMenuElement.firstChild;while(menuItemElement&&(menuItemElement._isSeparator||menuItemElement._isCustom))
 menuItemElement=menuItemElement.nextSibling;if(menuItemElement)
 this._highlightMenuItem(menuItemElement,false);},_menuKeyDown:function(event)
-{switch(event.keyIdentifier){case"Up":this._highlightPrevious();break;case"Down":this._highlightNext();break;case"Left":if(this._parentMenu){this._highlightMenuItem(null,false);this._parentMenu._hideSubMenu();}
+{switch(event.key){case"Up":this._highlightPrevious();break;case"Down":this._highlightNext();break;case"Left":if(this._parentMenu){this._highlightMenuItem(null,false);this._parentMenu._hideSubMenu();}
 break;case"Right":if(!this._highlightedMenuItemElement)
 break;if(this._highlightedMenuItemElement._subItems){this._showSubMenu(this._highlightedMenuItemElement);this._subMenu._focus();this._subMenu._highlightNext();}
 break;case"U+001B":this._discardMenu(false,event);break;case"Enter":if(!isEnterKey(event))
@@ -3174,7 +3174,7 @@
 return;this._rowCountPerViewport=Math.floor(this._element.offsetHeight/this._element.firstChild.offsetHeight);},updateSuggestions:function(anchorBox,completions,selectedIndex,canShowForSingleItem,userEnteredText,asyncDetails)
 {if(this._canShowBox(completions,canShowForSingleItem,userEnteredText)){this._updateItems(completions,userEnteredText,asyncDetails);this._show();this._updateBoxPosition(anchorBox);this._selectItem(selectedIndex,selectedIndex>0);delete this._rowCountPerViewport;}else
 this.hide();},keyPressed:function(event)
-{switch(event.keyIdentifier){case"Up":return this.upKeyPressed();case"Down":return this.downKeyPressed();case"PageUp":return this.pageUpKeyPressed();case"PageDown":return this.pageDownKeyPressed();case"Enter":return this.enterKeyPressed();}
+{switch(event.key){case"Up":return this.upKeyPressed();case"Down":return this.downKeyPressed();case"PageUp":return this.pageUpKeyPressed();case"PageDown":return this.pageDownKeyPressed();case"Enter":return this.enterKeyPressed();}
 return false;},upKeyPressed:function()
 {return this._selectClosest(-1,true);},downKeyPressed:function()
 {return this._selectClosest(1,true);},pageUpKeyPressed:function()
@@ -3488,7 +3488,7 @@
 this._selectionTimeout=setTimeout(moveBackIfOutside.bind(this),100);},_updateAutoComplete:function(force)
 {this.clearAutoComplete();this.autoCompleteSoon(force);},onMouseWheel:function(event)
 {},onKeyDown:function(event)
-{var handled=false;delete this._needUpdateAutocomplete;switch(event.keyIdentifier){case"U+0009":handled=this.tabKeyPressed(event);break;case"Left":case"Home":this._removeSuggestionAids();break;case"Right":case"End":if(this.isCaretAtEndOfPrompt())
+{var handled=false;delete this._needUpdateAutocomplete;switch(event.key){case"U+0009":handled=this.tabKeyPressed(event);break;case"Left":case"Home":this._removeSuggestionAids();break;case"Right":case"End":if(this.isCaretAtEndOfPrompt())
 handled=this.acceptAutoComplete();else
 this._removeSuggestionAids();break;case"U+001B":if(this.isSuggestBoxVisible()){this._removeSuggestionAids();handled=true;}
 break;case"U+0020":if(event.ctrlKey&&!event.metaKey&&!event.altKey&&!event.shiftKey){this._updateAutoComplete(true);handled=true;}
@@ -3588,7 +3588,7 @@
 {if(this._historyOffset===1)
 return undefined;--this._historyOffset;return this._currentHistoryItem();},_currentHistoryItem:function()
 {return this._data[this._data.length-this._historyOffset];},onKeyDown:function(event)
-{var newText;var isPrevious;switch(event.keyIdentifier){case"Up":if(!this.isCaretOnFirstLine()||this.isSuggestBoxVisible())
+{var newText;var isPrevious;switch(event.key){case"Up":if(!this.isCaretOnFirstLine()||this.isSuggestBoxVisible())
 break;newText=this._previous();isPrevious=true;break;case"Down":if(!this.isCaretOnLastLine()||this.isSuggestBoxVisible())
 break;newText=this._next();break;case"U+0050":if(WebInspector.isMac()&&event.ctrlKey&&!event.metaKey&&!event.altKey&&!event.shiftKey){newText=this._previous();isPrevious=true;}
 break;case"U+004E":if(WebInspector.isMac()&&event.ctrlKey&&!event.metaKey&&!event.altKey&&!event.shiftKey)
@@ -3660,23 +3660,23 @@
 WebInspector.CSSNumberRegex=/^(-?(?:\d+(?:\.\d+)?|\.\d+))$/;WebInspector.StyleValueDelimiters=" \xA0\t\n\"':;,/()";WebInspector._valueModificationDirection=function(event)
 {var direction=null;if(event.type==="mousewheel"){if(event.wheelDeltaY>0)
 direction="Up";else if(event.wheelDeltaY<0)
-direction="Down";}else{if(event.keyIdentifier==="Up"||event.keyIdentifier==="PageUp")
-direction="Up";else if(event.keyIdentifier==="Down"||event.keyIdentifier==="PageDown")
+direction="Down";}else{if(event.key==="Up"||event.key==="PageUp")
+direction="Up";else if(event.key==="Down"||event.key==="PageDown")
 direction="Down";}
 return direction;}
 WebInspector._modifiedHexValue=function(hexString,event)
 {var direction=WebInspector._valueModificationDirection(event);if(!direction)
 return hexString;var number=parseInt(hexString,16);if(isNaN(number)||!isFinite(number))
-return hexString;var maxValue=Math.pow(16,hexString.length)-1;var arrowKeyOrMouseWheelEvent=(event.keyIdentifier==="Up"||event.keyIdentifier==="Down"||event.type==="mousewheel");var delta;if(arrowKeyOrMouseWheelEvent)
+return hexString;var maxValue=Math.pow(16,hexString.length)-1;var arrowKeyOrMouseWheelEvent=(event.key==="Up"||event.key==="Down"||event.type==="mousewheel");var delta;if(arrowKeyOrMouseWheelEvent)
 delta=(direction==="Up")?1:-1;else
-delta=(event.keyIdentifier==="PageUp")?16:-16;if(event.shiftKey)
+delta=(event.key==="PageUp")?16:-16;if(event.shiftKey)
 delta*=16;var result=number+delta;if(result<0)
 result=0;else if(result>maxValue)
 return hexString;var resultString=result.toString(16).toUpperCase();for(var i=0,lengthDelta=hexString.length-resultString.length;i<lengthDelta;++i)
 resultString="0"+resultString;return resultString;}
 WebInspector._modifiedFloatNumber=function(number,event)
 {var direction=WebInspector._valueModificationDirection(event);if(!direction)
-return number;var arrowKeyOrMouseWheelEvent=(event.keyIdentifier==="Up"||event.keyIdentifier==="Down"||event.type==="mousewheel");var changeAmount=1;if(event.shiftKey&&!arrowKeyOrMouseWheelEvent)
+return number;var arrowKeyOrMouseWheelEvent=(event.key==="Up"||event.key==="Down"||event.type==="mousewheel");var changeAmount=1;if(event.shiftKey&&!arrowKeyOrMouseWheelEvent)
 changeAmount=100;else if(event.shiftKey||!arrowKeyOrMouseWheelEvent)
 changeAmount=10;else if(event.altKey)
 changeAmount=0.1;if(direction==="Down")
@@ -3689,7 +3689,7 @@
 WebInspector.handleElementValueModifications=function(event,element,finishHandler,suggestionHandler,customNumberHandler)
 {function createRange()
 {return document.createRange();}
-var arrowKeyOrMouseWheelEvent=(event.keyIdentifier==="Up"||event.keyIdentifier==="Down"||event.type==="mousewheel");var pageKeyPressed=(event.keyIdentifier==="PageUp"||event.keyIdentifier==="PageDown");if(!arrowKeyOrMouseWheelEvent&&!pageKeyPressed)
+var arrowKeyOrMouseWheelEvent=(event.key==="Up"||event.key==="Down"||event.type==="mousewheel");var pageKeyPressed=(event.key==="PageUp"||event.key==="PageDown");if(!arrowKeyOrMouseWheelEvent&&!pageKeyPressed)
 return false;var selection=element.getComponentSelection();if(!selection.rangeCount)
 return false;var selectionRange=selection.getRangeAt(0);if(!selectionRange.commonAncestorContainer.isSelfOrDescendant(element))
 return false;var originalValue=element.textContent;var wordRange=selectionRange.startContainer.rangeOfWord(selectionRange.startOffset,WebInspector.StyleValueDelimiters,element);var wordString=wordRange.toString();if(suggestionHandler&&suggestionHandler(wordString))
@@ -4140,7 +4140,7 @@
 processingStartTime=Date.now();this._dispatcher[functionName].apply(this._dispatcher,params);if(InspectorBackendClass.Options.dumpInspectorTimeStats)
 console.log("time-stats: "+messageObject.method+" = "+(Date.now()-processingStartTime));}}
 InspectorBackendClass.Options={dumpInspectorTimeStats:false,dumpInspectorProtocolMessages:false,suppressRequestErrors:false}
-InspectorBackend=new InspectorBackendClass();;InspectorBackend.registerEvent("Inspector.evaluateForTestInFrontend",["testCallId","script"]);InspectorBackend.registerEvent("Inspector.inspect",["object","hints"]);InspectorBackend.registerEvent("Inspector.detached",["reason"]);InspectorBackend.registerEvent("Inspector.targetCrashed",[]);InspectorBackend.registerCommand("Inspector.enable",[],[],false);InspectorBackend.registerCommand("Inspector.disable",[],[],false);InspectorBackend.registerEnum("Memory.PressureLevel",{Moderate:"moderate",Critical:"critical"});InspectorBackend.registerCommand("Memory.getDOMCounters",[],["documents","nodes","jsEventListeners"],false);InspectorBackend.registerCommand("Memory.setPressureNotificationsSuppressed",[{"name":"suppressed","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Memory.simulatePressureNotification",[{"name":"level","type":"string","optional":false}],[],false);InspectorBackend.registerEnum("Page.ResourceType",{Document:"Document",Stylesheet:"Stylesheet",Image:"Image",Media:"Media",Font:"Font",Script:"Script",TextTrack:"TextTrack",XHR:"XHR",Fetch:"Fetch",EventSource:"EventSource",WebSocket:"WebSocket",Manifest:"Manifest",Other:"Other"});InspectorBackend.registerEnum("Page.DialogType",{Alert:"alert",Confirm:"confirm",Prompt:"prompt",Beforeunload:"beforeunload"});InspectorBackend.registerEvent("Page.domContentEventFired",["timestamp"]);InspectorBackend.registerEvent("Page.loadEventFired",["timestamp"]);InspectorBackend.registerEvent("Page.frameAttached",["frameId","parentFrameId"]);InspectorBackend.registerEvent("Page.frameNavigated",["frame"]);InspectorBackend.registerEvent("Page.frameDetached",["frameId"]);InspectorBackend.registerEvent("Page.frameStartedLoading",["frameId"]);InspectorBackend.registerEvent("Page.frameStoppedLoading",["frameId"]);InspectorBackend.registerEvent("Page.frameScheduledNavigation",["frameId","delay"]);InspectorBackend.registerEvent("Page.frameClearedScheduledNavigation",["frameId"]);InspectorBackend.registerEvent("Page.frameResized",[]);InspectorBackend.registerEvent("Page.javascriptDialogOpening",["message","type"]);InspectorBackend.registerEvent("Page.javascriptDialogClosed",["result"]);InspectorBackend.registerEvent("Page.screencastFrame",["data","metadata","sessionId"]);InspectorBackend.registerEvent("Page.screencastVisibilityChanged",["visible"]);InspectorBackend.registerEvent("Page.colorPicked",["color"]);InspectorBackend.registerEvent("Page.interstitialShown",[]);InspectorBackend.registerEvent("Page.interstitialHidden",[]);InspectorBackend.registerCommand("Page.enable",[],[],false);InspectorBackend.registerCommand("Page.disable",[],[],false);InspectorBackend.registerCommand("Page.addScriptToEvaluateOnLoad",[{"name":"scriptSource","type":"string","optional":false}],["identifier"],false);InspectorBackend.registerCommand("Page.removeScriptToEvaluateOnLoad",[{"name":"identifier","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Page.reload",[{"name":"ignoreCache","type":"boolean","optional":true},{"name":"scriptToEvaluateOnLoad","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Page.navigate",[{"name":"url","type":"string","optional":false}],["frameId"],false);InspectorBackend.registerCommand("Page.getNavigationHistory",[],["currentIndex","entries"],false);InspectorBackend.registerCommand("Page.navigateToHistoryEntry",[{"name":"entryId","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Page.getCookies",[],["cookies"],false);InspectorBackend.registerCommand("Page.deleteCookie",[{"name":"cookieName","type":"string","optional":false},{"name":"url","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Page.getResourceTree",[],["frameTree"],false);InspectorBackend.registerCommand("Page.getResourceContent",[{"name":"frameId","type":"string","optional":false},{"name":"url","type":"string","optional":false}],["content","base64Encoded"],false);InspectorBackend.registerCommand("Page.searchInResource",[{"name":"frameId","type":"string","optional":false},{"name":"url","type":"string","optional":false},{"name":"query","type":"string","optional":false},{"name":"caseSensitive","type":"boolean","optional":true},{"name":"isRegex","type":"boolean","optional":true}],["result"],false);InspectorBackend.registerCommand("Page.setDocumentContent",[{"name":"frameId","type":"string","optional":false},{"name":"html","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Page.setDeviceMetricsOverride",[{"name":"width","type":"number","optional":false},{"name":"height","type":"number","optional":false},{"name":"deviceScaleFactor","type":"number","optional":false},{"name":"mobile","type":"boolean","optional":false},{"name":"fitWindow","type":"boolean","optional":false},{"name":"scale","type":"number","optional":true},{"name":"offsetX","type":"number","optional":true},{"name":"offsetY","type":"number","optional":true},{"name":"screenWidth","type":"number","optional":true},{"name":"screenHeight","type":"number","optional":true},{"name":"positionX","type":"number","optional":true},{"name":"positionY","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Page.clearDeviceMetricsOverride",[],[],false);InspectorBackend.registerCommand("Page.setGeolocationOverride",[{"name":"latitude","type":"number","optional":true},{"name":"longitude","type":"number","optional":true},{"name":"accuracy","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Page.clearGeolocationOverride",[],[],false);InspectorBackend.registerCommand("Page.setDeviceOrientationOverride",[{"name":"alpha","type":"number","optional":false},{"name":"beta","type":"number","optional":false},{"name":"gamma","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Page.clearDeviceOrientationOverride",[],[],false);InspectorBackend.registerCommand("Page.setTouchEmulationEnabled",[{"name":"enabled","type":"boolean","optional":false},{"name":"configuration","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Page.captureScreenshot",[],["data"],false);InspectorBackend.registerCommand("Page.startScreencast",[{"name":"format","type":"string","optional":true},{"name":"quality","type":"number","optional":true},{"name":"maxWidth","type":"number","optional":true},{"name":"maxHeight","type":"number","optional":true},{"name":"everyNthFrame","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Page.stopScreencast",[],[],false);InspectorBackend.registerCommand("Page.screencastFrameAck",[{"name":"sessionId","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Page.handleJavaScriptDialog",[{"name":"accept","type":"boolean","optional":false},{"name":"promptText","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Page.setColorPickerEnabled",[{"name":"enabled","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Page.setOverlayMessage",[{"name":"message","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Rendering.setShowPaintRects",[{"name":"result","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Rendering.setShowDebugBorders",[{"name":"show","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Rendering.setShowFPSCounter",[{"name":"show","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Rendering.setShowScrollBottleneckRects",[{"name":"show","type":"boolean","optional":false}],[],false);InspectorBackend.registerEvent("Emulation.viewportChanged",["viewport"]);InspectorBackend.registerCommand("Emulation.setDeviceMetricsOverride",[{"name":"width","type":"number","optional":false},{"name":"height","type":"number","optional":false},{"name":"deviceScaleFactor","type":"number","optional":false},{"name":"mobile","type":"boolean","optional":false},{"name":"fitWindow","type":"boolean","optional":false},{"name":"scale","type":"number","optional":true},{"name":"offsetX","type":"number","optional":true},{"name":"offsetY","type":"number","optional":true},{"name":"screenWidth","type":"number","optional":true},{"name":"screenHeight","type":"number","optional":true},{"name":"positionX","type":"number","optional":true},{"name":"positionY","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Emulation.clearDeviceMetricsOverride",[],[],false);InspectorBackend.registerCommand("Emulation.resetScrollAndPageScaleFactor",[],[],false);InspectorBackend.registerCommand("Emulation.setPageScaleFactor",[{"name":"pageScaleFactor","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Emulation.setScriptExecutionDisabled",[{"name":"value","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Emulation.setGeolocationOverride",[{"name":"latitude","type":"number","optional":true},{"name":"longitude","type":"number","optional":true},{"name":"accuracy","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Emulation.clearGeolocationOverride",[],[],false);InspectorBackend.registerCommand("Emulation.setTouchEmulationEnabled",[{"name":"enabled","type":"boolean","optional":false},{"name":"configuration","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Emulation.setEmulatedMedia",[{"name":"media","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Emulation.setCPUThrottlingRate",[{"name":"rate","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Emulation.canEmulate",[],["result"],false);InspectorBackend.registerEnum("Runtime.RemoteObjectType",{Object:"object",Function:"function",Undefined:"undefined",String:"string",Number:"number",Boolean:"boolean",Symbol:"symbol"});InspectorBackend.registerEnum("Runtime.RemoteObjectSubtype",{Array:"array",Null:"null",Node:"node",Regexp:"regexp",Date:"date",Map:"map",Set:"set",Iterator:"iterator",Generator:"generator",Error:"error"});InspectorBackend.registerEnum("Runtime.ObjectPreviewType",{Object:"object",Function:"function",Undefined:"undefined",String:"string",Number:"number",Boolean:"boolean",Symbol:"symbol"});InspectorBackend.registerEnum("Runtime.ObjectPreviewSubtype",{Array:"array",Null:"null",Node:"node",Regexp:"regexp",Date:"date",Map:"map",Set:"set",Iterator:"iterator",Generator:"generator",Error:"error"});InspectorBackend.registerEnum("Runtime.PropertyPreviewType",{Object:"object",Function:"function",Undefined:"undefined",String:"string",Number:"number",Boolean:"boolean",Symbol:"symbol",Accessor:"accessor"});InspectorBackend.registerEnum("Runtime.PropertyPreviewSubtype",{Array:"array",Null:"null",Node:"node",Regexp:"regexp",Date:"date",Map:"map",Set:"set",Iterator:"iterator",Generator:"generator",Error:"error"});InspectorBackend.registerEnum("Runtime.CallArgumentType",{Object:"object",Function:"function",Undefined:"undefined",String:"string",Number:"number",Boolean:"boolean",Symbol:"symbol"});InspectorBackend.registerEvent("Runtime.executionContextCreated",["context"]);InspectorBackend.registerEvent("Runtime.executionContextDestroyed",["executionContextId"]);InspectorBackend.registerEvent("Runtime.executionContextsCleared",[]);InspectorBackend.registerCommand("Runtime.evaluate",[{"name":"expression","type":"string","optional":false},{"name":"objectGroup","type":"string","optional":true},{"name":"includeCommandLineAPI","type":"boolean","optional":true},{"name":"doNotPauseOnExceptionsAndMuteConsole","type":"boolean","optional":true},{"name":"contextId","type":"number","optional":true},{"name":"returnByValue","type":"boolean","optional":true},{"name":"generatePreview","type":"boolean","optional":true}],["result","wasThrown","exceptionDetails"],false);InspectorBackend.registerCommand("Runtime.callFunctionOn",[{"name":"objectId","type":"string","optional":false},{"name":"functionDeclaration","type":"string","optional":false},{"name":"arguments","type":"object","optional":true},{"name":"doNotPauseOnExceptionsAndMuteConsole","type":"boolean","optional":true},{"name":"returnByValue","type":"boolean","optional":true},{"name":"generatePreview","type":"boolean","optional":true}],["result","wasThrown"],false);InspectorBackend.registerCommand("Runtime.getProperties",[{"name":"objectId","type":"string","optional":false},{"name":"ownProperties","type":"boolean","optional":true},{"name":"accessorPropertiesOnly","type":"boolean","optional":true},{"name":"generatePreview","type":"boolean","optional":true}],["result","internalProperties","exceptionDetails"],false);InspectorBackend.registerCommand("Runtime.releaseObject",[{"name":"objectId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Runtime.releaseObjectGroup",[{"name":"objectGroup","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Runtime.run",[],[],false);InspectorBackend.registerCommand("Runtime.enable",[],[],false);InspectorBackend.registerCommand("Runtime.disable",[],[],false);InspectorBackend.registerCommand("Runtime.isRunRequired",[],["result"],false);InspectorBackend.registerCommand("Runtime.setCustomObjectFormatterEnabled",[{"name":"enabled","type":"boolean","optional":false}],[],false);InspectorBackend.registerEnum("Console.ConsoleMessageSource",{XML:"xml",Javascript:"javascript",Network:"network",ConsoleAPI:"console-api",Storage:"storage",Appcache:"appcache",Rendering:"rendering",Security:"security",Other:"other",Deprecation:"deprecation"});InspectorBackend.registerEnum("Console.ConsoleMessageLevel",{Log:"log",Warning:"warning",Error:"error",Debug:"debug",Info:"info",RevokedError:"revokedError"});InspectorBackend.registerEnum("Console.ConsoleMessageType",{Log:"log",Dir:"dir",DirXML:"dirxml",Table:"table",Trace:"trace",Clear:"clear",StartGroup:"startGroup",StartGroupCollapsed:"startGroupCollapsed",EndGroup:"endGroup",Assert:"assert",Profile:"profile",ProfileEnd:"profileEnd"});InspectorBackend.registerEvent("Console.messageAdded",["message"]);InspectorBackend.registerEvent("Console.messageRepeatCountUpdated",["count","timestamp"]);InspectorBackend.registerEvent("Console.messagesCleared",[]);InspectorBackend.registerCommand("Console.enable",[],[],false);InspectorBackend.registerCommand("Console.disable",[],[],false);InspectorBackend.registerCommand("Console.clearMessages",[],[],false);InspectorBackend.registerEnum("Security.SecurityState",{Unknown:"unknown",Neutral:"neutral",Insecure:"insecure",Warning:"warning",Secure:"secure",Info:"info"});InspectorBackend.registerEvent("Security.securityStateChanged",["securityState","explanations","mixedContentStatus","schemeIsCryptographic"]);InspectorBackend.registerCommand("Security.enable",[],[],false);InspectorBackend.registerCommand("Security.disable",[],[],false);InspectorBackend.registerEnum("Network.ResourcePriority",{VeryLow:"VeryLow",Low:"Low",Medium:"Medium",High:"High",VeryHigh:"VeryHigh"});InspectorBackend.registerEnum("Network.RequestMixedContentType",{Blockable:"blockable",OptionallyBlockable:"optionally-blockable",None:"none"});InspectorBackend.registerEnum("Network.BlockedReason",{Csp:"csp",MixedContent:"mixed-content",Origin:"origin",Inspector:"inspector",Other:"other"});InspectorBackend.registerEnum("Network.InitiatorType",{Parser:"parser",Script:"script",Other:"other"});InspectorBackend.registerEvent("Network.requestWillBeSent",["requestId","frameId","loaderId","documentURL","request","timestamp","wallTime","initiator","redirectResponse","type"]);InspectorBackend.registerEvent("Network.requestServedFromCache",["requestId"]);InspectorBackend.registerEvent("Network.responseReceived",["requestId","frameId","loaderId","timestamp","type","response"]);InspectorBackend.registerEvent("Network.dataReceived",["requestId","timestamp","dataLength","encodedDataLength"]);InspectorBackend.registerEvent("Network.loadingFinished",["requestId","timestamp","encodedDataLength"]);InspectorBackend.registerEvent("Network.loadingFailed",["requestId","timestamp","type","errorText","canceled","blockedReason"]);InspectorBackend.registerEvent("Network.webSocketWillSendHandshakeRequest",["requestId","timestamp","wallTime","request"]);InspectorBackend.registerEvent("Network.webSocketHandshakeResponseReceived",["requestId","timestamp","response"]);InspectorBackend.registerEvent("Network.webSocketCreated",["requestId","url"]);InspectorBackend.registerEvent("Network.webSocketClosed",["requestId","timestamp"]);InspectorBackend.registerEvent("Network.webSocketFrameReceived",["requestId","timestamp","response"]);InspectorBackend.registerEvent("Network.webSocketFrameError",["requestId","timestamp","errorMessage"]);InspectorBackend.registerEvent("Network.webSocketFrameSent",["requestId","timestamp","response"]);InspectorBackend.registerEvent("Network.eventSourceMessageReceived",["requestId","timestamp","eventName","eventId","data"]);InspectorBackend.registerCommand("Network.enable",[],[],false);InspectorBackend.registerCommand("Network.disable",[],[],false);InspectorBackend.registerCommand("Network.setUserAgentOverride",[{"name":"userAgent","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Network.setExtraHTTPHeaders",[{"name":"headers","type":"object","optional":false}],[],false);InspectorBackend.registerCommand("Network.getResponseBody",[{"name":"requestId","type":"string","optional":false}],["body","base64Encoded"],false);InspectorBackend.registerCommand("Network.addBlockedURL",[{"name":"url","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Network.removeBlockedURL",[{"name":"url","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Network.replayXHR",[{"name":"requestId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Network.setMonitoringXHREnabled",[{"name":"enabled","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Network.canClearBrowserCache",[],["result"],false);InspectorBackend.registerCommand("Network.clearBrowserCache",[],[],false);InspectorBackend.registerCommand("Network.canClearBrowserCookies",[],["result"],false);InspectorBackend.registerCommand("Network.clearBrowserCookies",[],[],false);InspectorBackend.registerCommand("Network.getCookies",[],["cookies"],false);InspectorBackend.registerCommand("Network.deleteCookie",[{"name":"cookieName","type":"string","optional":false},{"name":"url","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Network.canEmulateNetworkConditions",[],["result"],false);InspectorBackend.registerCommand("Network.emulateNetworkConditions",[{"name":"offline","type":"boolean","optional":false},{"name":"latency","type":"number","optional":false},{"name":"downloadThroughput","type":"number","optional":false},{"name":"uploadThroughput","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Network.setCacheDisabled",[{"name":"cacheDisabled","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Network.setDataSizeLimitsForTest",[{"name":"maxTotalSize","type":"number","optional":false},{"name":"maxResourceSize","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Network.getCertificateDetails",[{"name":"certificateId","type":"number","optional":false}],["result"],false);InspectorBackend.registerCommand("Network.showCertificateViewer",[{"name":"certificateId","type":"number","optional":false}],[],false);InspectorBackend.registerEvent("Database.addDatabase",["database"]);InspectorBackend.registerCommand("Database.enable",[],[],false);InspectorBackend.registerCommand("Database.disable",[],[],false);InspectorBackend.registerCommand("Database.getDatabaseTableNames",[{"name":"databaseId","type":"string","optional":false}],["tableNames"],false);InspectorBackend.registerCommand("Database.executeSQL",[{"name":"databaseId","type":"string","optional":false},{"name":"query","type":"string","optional":false}],["columnNames","values","sqlError"],false);InspectorBackend.registerEnum("IndexedDB.KeyType",{Number:"number",String:"string",Date:"date",Array:"array"});InspectorBackend.registerEnum("IndexedDB.KeyPathType",{Null:"null",String:"string",Array:"array"});InspectorBackend.registerCommand("IndexedDB.enable",[],[],false);InspectorBackend.registerCommand("IndexedDB.disable",[],[],false);InspectorBackend.registerCommand("IndexedDB.requestDatabaseNames",[{"name":"securityOrigin","type":"string","optional":false}],["databaseNames"],false);InspectorBackend.registerCommand("IndexedDB.requestDatabase",[{"name":"securityOrigin","type":"string","optional":false},{"name":"databaseName","type":"string","optional":false}],["databaseWithObjectStores"],false);InspectorBackend.registerCommand("IndexedDB.requestData",[{"name":"securityOrigin","type":"string","optional":false},{"name":"databaseName","type":"string","optional":false},{"name":"objectStoreName","type":"string","optional":false},{"name":"indexName","type":"string","optional":false},{"name":"skipCount","type":"number","optional":false},{"name":"pageSize","type":"number","optional":false},{"name":"keyRange","type":"object","optional":true}],["objectStoreDataEntries","hasMore"],false);InspectorBackend.registerCommand("IndexedDB.clearObjectStore",[{"name":"securityOrigin","type":"string","optional":false},{"name":"databaseName","type":"string","optional":false},{"name":"objectStoreName","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("CacheStorage.requestCacheNames",[{"name":"securityOrigin","type":"string","optional":false}],["caches"],false);InspectorBackend.registerCommand("CacheStorage.requestEntries",[{"name":"cacheId","type":"string","optional":false},{"name":"skipCount","type":"number","optional":false},{"name":"pageSize","type":"number","optional":false}],["cacheDataEntries","hasMore"],false);InspectorBackend.registerCommand("CacheStorage.deleteCache",[{"name":"cacheId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("CacheStorage.deleteEntry",[{"name":"cacheId","type":"string","optional":false},{"name":"request","type":"string","optional":false}],[],false);InspectorBackend.registerEvent("DOMStorage.domStorageItemsCleared",["storageId"]);InspectorBackend.registerEvent("DOMStorage.domStorageItemRemoved",["storageId","key"]);InspectorBackend.registerEvent("DOMStorage.domStorageItemAdded",["storageId","key","newValue"]);InspectorBackend.registerEvent("DOMStorage.domStorageItemUpdated",["storageId","key","oldValue","newValue"]);InspectorBackend.registerCommand("DOMStorage.enable",[],[],false);InspectorBackend.registerCommand("DOMStorage.disable",[],[],false);InspectorBackend.registerCommand("DOMStorage.getDOMStorageItems",[{"name":"storageId","type":"object","optional":false}],["entries"],false);InspectorBackend.registerCommand("DOMStorage.setDOMStorageItem",[{"name":"storageId","type":"object","optional":false},{"name":"key","type":"string","optional":false},{"name":"value","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOMStorage.removeDOMStorageItem",[{"name":"storageId","type":"object","optional":false},{"name":"key","type":"string","optional":false}],[],false);InspectorBackend.registerEvent("ApplicationCache.applicationCacheStatusUpdated",["frameId","manifestURL","status"]);InspectorBackend.registerEvent("ApplicationCache.networkStateUpdated",["isNowOnline"]);InspectorBackend.registerCommand("ApplicationCache.getFramesWithManifests",[],["frameIds"],false);InspectorBackend.registerCommand("ApplicationCache.enable",[],[],false);InspectorBackend.registerCommand("ApplicationCache.getManifestForFrame",[{"name":"frameId","type":"string","optional":false}],["manifestURL"],false);InspectorBackend.registerCommand("ApplicationCache.getApplicationCacheForFrame",[{"name":"frameId","type":"string","optional":false}],["applicationCache"],false);InspectorBackend.registerCommand("FileSystem.enable",[],[],false);InspectorBackend.registerCommand("FileSystem.disable",[],[],false);InspectorBackend.registerCommand("FileSystem.requestFileSystemRoot",[{"name":"origin","type":"string","optional":false},{"name":"type","type":"string","optional":false}],["errorCode","root"],false);InspectorBackend.registerCommand("FileSystem.requestDirectoryContent",[{"name":"url","type":"string","optional":false}],["errorCode","entries"],false);InspectorBackend.registerCommand("FileSystem.requestMetadata",[{"name":"url","type":"string","optional":false}],["errorCode","metadata"],false);InspectorBackend.registerCommand("FileSystem.requestFileContent",[{"name":"url","type":"string","optional":false},{"name":"readAsText","type":"boolean","optional":false},{"name":"start","type":"number","optional":true},{"name":"end","type":"number","optional":true},{"name":"charset","type":"string","optional":true}],["errorCode","content","charset"],false);InspectorBackend.registerCommand("FileSystem.deleteEntry",[{"name":"url","type":"string","optional":false}],["errorCode"],false);InspectorBackend.registerEnum("DOM.PseudoType",{FirstLine:"first-line",FirstLetter:"first-letter",Before:"before",After:"after",Backdrop:"backdrop",Selection:"selection",FirstLineInherited:"first-line-inherited",Scrollbar:"scrollbar",ScrollbarThumb:"scrollbar-thumb",ScrollbarButton:"scrollbar-button",ScrollbarTrack:"scrollbar-track",ScrollbarTrackPiece:"scrollbar-track-piece",ScrollbarCorner:"scrollbar-corner",Resizer:"resizer",InputListButton:"input-list-button"});InspectorBackend.registerEnum("DOM.ShadowRootType",{UserAgent:"user-agent",Open:"open",Closed:"closed"});InspectorBackend.registerEnum("DOM.InspectMode",{SearchForNode:"searchForNode",SearchForUAShadowDOM:"searchForUAShadowDOM",ShowLayoutEditor:"showLayoutEditor",None:"none"});InspectorBackend.registerEvent("DOM.documentUpdated",[]);InspectorBackend.registerEvent("DOM.inspectNodeRequested",["backendNodeId"]);InspectorBackend.registerEvent("DOM.setChildNodes",["parentId","nodes"]);InspectorBackend.registerEvent("DOM.attributeModified",["nodeId","name","value"]);InspectorBackend.registerEvent("DOM.attributeRemoved",["nodeId","name"]);InspectorBackend.registerEvent("DOM.inlineStyleInvalidated",["nodeIds"]);InspectorBackend.registerEvent("DOM.characterDataModified",["nodeId","characterData"]);InspectorBackend.registerEvent("DOM.childNodeCountUpdated",["nodeId","childNodeCount"]);InspectorBackend.registerEvent("DOM.childNodeInserted",["parentNodeId","previousNodeId","node"]);InspectorBackend.registerEvent("DOM.childNodeRemoved",["parentNodeId","nodeId"]);InspectorBackend.registerEvent("DOM.shadowRootPushed",["hostId","root"]);InspectorBackend.registerEvent("DOM.shadowRootPopped",["hostId","rootId"]);InspectorBackend.registerEvent("DOM.pseudoElementAdded",["parentId","pseudoElement"]);InspectorBackend.registerEvent("DOM.pseudoElementRemoved",["parentId","pseudoElementId"]);InspectorBackend.registerEvent("DOM.distributedNodesUpdated",["insertionPointId","distributedNodes"]);InspectorBackend.registerEvent("DOM.nodeHighlightRequested",["nodeId"]);InspectorBackend.registerCommand("DOM.enable",[],[],false);InspectorBackend.registerCommand("DOM.disable",[],[],false);InspectorBackend.registerCommand("DOM.getDocument",[],["root"],false);InspectorBackend.registerCommand("DOM.requestChildNodes",[{"name":"nodeId","type":"number","optional":false},{"name":"depth","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("DOM.querySelector",[{"name":"nodeId","type":"number","optional":false},{"name":"selector","type":"string","optional":false}],["nodeId"],false);InspectorBackend.registerCommand("DOM.querySelectorAll",[{"name":"nodeId","type":"number","optional":false},{"name":"selector","type":"string","optional":false}],["nodeIds"],false);InspectorBackend.registerCommand("DOM.setNodeName",[{"name":"nodeId","type":"number","optional":false},{"name":"name","type":"string","optional":false}],["nodeId"],false);InspectorBackend.registerCommand("DOM.setNodeValue",[{"name":"nodeId","type":"number","optional":false},{"name":"value","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOM.removeNode",[{"name":"nodeId","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("DOM.setAttributeValue",[{"name":"nodeId","type":"number","optional":false},{"name":"name","type":"string","optional":false},{"name":"value","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOM.setAttributesAsText",[{"name":"nodeId","type":"number","optional":false},{"name":"text","type":"string","optional":false},{"name":"name","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("DOM.removeAttribute",[{"name":"nodeId","type":"number","optional":false},{"name":"name","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOM.getOuterHTML",[{"name":"nodeId","type":"number","optional":false}],["outerHTML"],false);InspectorBackend.registerCommand("DOM.setOuterHTML",[{"name":"nodeId","type":"number","optional":false},{"name":"outerHTML","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOM.performSearch",[{"name":"query","type":"string","optional":false},{"name":"includeUserAgentShadowDOM","type":"boolean","optional":true}],["searchId","resultCount"],false);InspectorBackend.registerCommand("DOM.getSearchResults",[{"name":"searchId","type":"string","optional":false},{"name":"fromIndex","type":"number","optional":false},{"name":"toIndex","type":"number","optional":false}],["nodeIds"],false);InspectorBackend.registerCommand("DOM.discardSearchResults",[{"name":"searchId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOM.requestNode",[{"name":"objectId","type":"string","optional":false}],["nodeId"],false);InspectorBackend.registerCommand("DOM.setInspectMode",[{"name":"mode","type":"string","optional":false},{"name":"highlightConfig","type":"object","optional":true}],[],false);InspectorBackend.registerCommand("DOM.highlightRect",[{"name":"x","type":"number","optional":false},{"name":"y","type":"number","optional":false},{"name":"width","type":"number","optional":false},{"name":"height","type":"number","optional":false},{"name":"color","type":"object","optional":true},{"name":"outlineColor","type":"object","optional":true}],[],false);InspectorBackend.registerCommand("DOM.highlightQuad",[{"name":"quad","type":"object","optional":false},{"name":"color","type":"object","optional":true},{"name":"outlineColor","type":"object","optional":true}],[],false);InspectorBackend.registerCommand("DOM.highlightNode",[{"name":"highlightConfig","type":"object","optional":false},{"name":"nodeId","type":"number","optional":true},{"name":"backendNodeId","type":"number","optional":true},{"name":"objectId","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("DOM.hideHighlight",[],[],false);InspectorBackend.registerCommand("DOM.highlightFrame",[{"name":"frameId","type":"string","optional":false},{"name":"contentColor","type":"object","optional":true},{"name":"contentOutlineColor","type":"object","optional":true}],[],false);InspectorBackend.registerCommand("DOM.pushNodeByPathToFrontend",[{"name":"path","type":"string","optional":false}],["nodeId"],false);InspectorBackend.registerCommand("DOM.pushNodesByBackendIdsToFrontend",[{"name":"backendNodeIds","type":"object","optional":false}],["nodeIds"],false);InspectorBackend.registerCommand("DOM.setInspectedNode",[{"name":"nodeId","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("DOM.resolveNode",[{"name":"nodeId","type":"number","optional":false},{"name":"objectGroup","type":"string","optional":true}],["object"],false);InspectorBackend.registerCommand("DOM.getAttributes",[{"name":"nodeId","type":"number","optional":false}],["attributes"],false);InspectorBackend.registerCommand("DOM.copyTo",[{"name":"nodeId","type":"number","optional":false},{"name":"targetNodeId","type":"number","optional":false},{"name":"insertBeforeNodeId","type":"number","optional":true}],["nodeId"],false);InspectorBackend.registerCommand("DOM.moveTo",[{"name":"nodeId","type":"number","optional":false},{"name":"targetNodeId","type":"number","optional":false},{"name":"insertBeforeNodeId","type":"number","optional":true}],["nodeId"],false);InspectorBackend.registerCommand("DOM.undo",[],[],false);InspectorBackend.registerCommand("DOM.redo",[],[],false);InspectorBackend.registerCommand("DOM.markUndoableState",[],[],false);InspectorBackend.registerCommand("DOM.focus",[{"name":"nodeId","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("DOM.setFileInputFiles",[{"name":"nodeId","type":"number","optional":false},{"name":"files","type":"object","optional":false}],[],false);InspectorBackend.registerCommand("DOM.getBoxModel",[{"name":"nodeId","type":"number","optional":false}],["model"],false);InspectorBackend.registerCommand("DOM.getNodeForLocation",[{"name":"x","type":"number","optional":false},{"name":"y","type":"number","optional":false}],["nodeId"],false);InspectorBackend.registerCommand("DOM.getRelayoutBoundary",[{"name":"nodeId","type":"number","optional":false}],["nodeId"],false);InspectorBackend.registerCommand("DOM.getHighlightObjectForTest",[{"name":"nodeId","type":"number","optional":false}],["highlight"],false);InspectorBackend.registerEnum("CSS.StyleSheetOrigin",{Injected:"injected",UserAgent:"user-agent",Inspector:"inspector",Regular:"regular"});InspectorBackend.registerEnum("CSS.CSSMediaSource",{MediaRule:"mediaRule",ImportRule:"importRule",LinkedSheet:"linkedSheet",InlineSheet:"inlineSheet"});InspectorBackend.registerEvent("CSS.mediaQueryResultChanged",[]);InspectorBackend.registerEvent("CSS.styleSheetChanged",["styleSheetId"]);InspectorBackend.registerEvent("CSS.styleSheetAdded",["header"]);InspectorBackend.registerEvent("CSS.styleSheetRemoved",["styleSheetId"]);InspectorBackend.registerEvent("CSS.layoutEditorChange",["styleSheetId","changeRange"]);InspectorBackend.registerCommand("CSS.enable",[],[],false);InspectorBackend.registerCommand("CSS.disable",[],[],false);InspectorBackend.registerCommand("CSS.getMatchedStylesForNode",[{"name":"nodeId","type":"number","optional":false}],["inlineStyle","attributesStyle","matchedCSSRules","pseudoElements","inherited"],false);InspectorBackend.registerCommand("CSS.getInlineStylesForNode",[{"name":"nodeId","type":"number","optional":false}],["inlineStyle","attributesStyle"],false);InspectorBackend.registerCommand("CSS.getComputedStyleForNode",[{"name":"nodeId","type":"number","optional":false}],["computedStyle"],false);InspectorBackend.registerCommand("CSS.getPlatformFontsForNode",[{"name":"nodeId","type":"number","optional":false}],["fonts"],false);InspectorBackend.registerCommand("CSS.getCSSAnimationsForNode",[{"name":"nodeId","type":"number","optional":false}],["cssKeyframesRules"],false);InspectorBackend.registerCommand("CSS.getStyleSheetText",[{"name":"styleSheetId","type":"string","optional":false}],["text"],false);InspectorBackend.registerCommand("CSS.setStyleSheetText",[{"name":"styleSheetId","type":"string","optional":false},{"name":"text","type":"string","optional":false}],["sourceMapURL"],false);InspectorBackend.registerCommand("CSS.setRuleSelector",[{"name":"styleSheetId","type":"string","optional":false},{"name":"range","type":"object","optional":false},{"name":"selector","type":"string","optional":false}],["selectorList"],false);InspectorBackend.registerCommand("CSS.setStyleText",[{"name":"styleSheetId","type":"string","optional":false},{"name":"range","type":"object","optional":false},{"name":"text","type":"string","optional":false}],["style"],false);InspectorBackend.registerCommand("CSS.setMediaText",[{"name":"styleSheetId","type":"string","optional":false},{"name":"range","type":"object","optional":false},{"name":"text","type":"string","optional":false}],["media"],false);InspectorBackend.registerCommand("CSS.createStyleSheet",[{"name":"frameId","type":"string","optional":false}],["styleSheetId"],false);InspectorBackend.registerCommand("CSS.addRule",[{"name":"styleSheetId","type":"string","optional":false},{"name":"ruleText","type":"string","optional":false},{"name":"location","type":"object","optional":false}],["rule"],false);InspectorBackend.registerCommand("CSS.forcePseudoState",[{"name":"nodeId","type":"number","optional":false},{"name":"forcedPseudoClasses","type":"object","optional":false}],[],false);InspectorBackend.registerCommand("CSS.getMediaQueries",[],["medias"],false);InspectorBackend.registerCommand("CSS.setEffectivePropertyValueForNode",[{"name":"nodeId","type":"number","optional":false},{"name":"propertyName","type":"string","optional":false},{"name":"value","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("CSS.getBackgroundColors",[{"name":"nodeId","type":"number","optional":false}],["backgroundColors"],false);InspectorBackend.registerCommand("IO.read",[{"name":"handle","type":"string","optional":false},{"name":"offset","type":"number","optional":true},{"name":"size","type":"number","optional":true}],["data","eof"],false);InspectorBackend.registerCommand("IO.close",[{"name":"handle","type":"string","optional":false}],[],false);InspectorBackend.registerEvent("Timeline.eventRecorded",["record"]);InspectorBackend.registerCommand("Timeline.enable",[],[],false);InspectorBackend.registerCommand("Timeline.disable",[],[],false);InspectorBackend.registerCommand("Timeline.start",[{"name":"maxCallStackDepth","type":"number","optional":true},{"name":"bufferEvents","type":"boolean","optional":true},{"name":"liveEvents","type":"string","optional":true},{"name":"includeCounters","type":"boolean","optional":true},{"name":"includeGPUEvents","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("Timeline.stop",[],[],false);InspectorBackend.registerEnum("Debugger.GeneratorObjectDetailsStatus",{Running:"running",Suspended:"suspended",Closed:"closed"});InspectorBackend.registerEnum("Debugger.ScopeType",{Global:"global",Local:"local",With:"with",Closure:"closure",Catch:"catch",Block:"block",Script:"script"});InspectorBackend.registerEnum("Debugger.PromiseDetailsStatus",{Pending:"pending",Resolved:"resolved",Rejected:"rejected"});InspectorBackend.registerEvent("Debugger.globalObjectCleared",[]);InspectorBackend.registerEvent("Debugger.scriptParsed",["scriptId","url","startLine","startColumn","endLine","endColumn","executionContextId","isContentScript","isInternalScript","isLiveEdit","sourceMapURL","hasSourceURL"]);InspectorBackend.registerEvent("Debugger.scriptFailedToParse",["scriptId","url","startLine","startColumn","endLine","endColumn","executionContextId","isContentScript","isInternalScript","sourceMapURL","hasSourceURL"]);InspectorBackend.registerEvent("Debugger.breakpointResolved",["breakpointId","location"]);InspectorBackend.registerEvent("Debugger.paused",["callFrames","reason","data","hitBreakpoints","asyncStackTrace"]);InspectorBackend.registerEvent("Debugger.resumed",[]);InspectorBackend.registerEvent("Debugger.promiseUpdated",["eventType","promise"]);InspectorBackend.registerEvent("Debugger.asyncOperationStarted",["operation"]);InspectorBackend.registerEvent("Debugger.asyncOperationCompleted",["id"]);InspectorBackend.registerCommand("Debugger.enable",[],[],false);InspectorBackend.registerCommand("Debugger.disable",[],[],false);InspectorBackend.registerCommand("Debugger.setBreakpointsActive",[{"name":"active","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Debugger.setSkipAllPauses",[{"name":"skipped","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Debugger.setBreakpointByUrl",[{"name":"lineNumber","type":"number","optional":false},{"name":"url","type":"string","optional":true},{"name":"urlRegex","type":"string","optional":true},{"name":"columnNumber","type":"number","optional":true},{"name":"condition","type":"string","optional":true}],["breakpointId","locations"],false);InspectorBackend.registerCommand("Debugger.setBreakpoint",[{"name":"location","type":"object","optional":false},{"name":"condition","type":"string","optional":true}],["breakpointId","actualLocation"],false);InspectorBackend.registerCommand("Debugger.removeBreakpoint",[{"name":"breakpointId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Debugger.continueToLocation",[{"name":"location","type":"object","optional":false},{"name":"interstatementLocation","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("Debugger.stepOver",[],[],false);InspectorBackend.registerCommand("Debugger.stepInto",[],[],false);InspectorBackend.registerCommand("Debugger.stepOut",[],[],false);InspectorBackend.registerCommand("Debugger.pause",[],[],false);InspectorBackend.registerCommand("Debugger.resume",[],[],false);InspectorBackend.registerCommand("Debugger.stepIntoAsync",[],[],false);InspectorBackend.registerCommand("Debugger.searchInContent",[{"name":"scriptId","type":"string","optional":false},{"name":"query","type":"string","optional":false},{"name":"caseSensitive","type":"boolean","optional":true},{"name":"isRegex","type":"boolean","optional":true}],["result"],false);InspectorBackend.registerCommand("Debugger.canSetScriptSource",[],["result"],false);InspectorBackend.registerCommand("Debugger.setScriptSource",[{"name":"scriptId","type":"string","optional":false},{"name":"scriptSource","type":"string","optional":false},{"name":"preview","type":"boolean","optional":true}],["callFrames","stackChanged","asyncStackTrace"],true);InspectorBackend.registerCommand("Debugger.restartFrame",[{"name":"callFrameId","type":"string","optional":false}],["callFrames","asyncStackTrace"],false);InspectorBackend.registerCommand("Debugger.getScriptSource",[{"name":"scriptId","type":"string","optional":false}],["scriptSource"],false);InspectorBackend.registerCommand("Debugger.getFunctionDetails",[{"name":"functionId","type":"string","optional":false}],["details"],false);InspectorBackend.registerCommand("Debugger.getGeneratorObjectDetails",[{"name":"objectId","type":"string","optional":false}],["details"],false);InspectorBackend.registerCommand("Debugger.getCollectionEntries",[{"name":"objectId","type":"string","optional":false}],["entries"],false);InspectorBackend.registerCommand("Debugger.setPauseOnExceptions",[{"name":"state","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Debugger.evaluateOnCallFrame",[{"name":"callFrameId","type":"string","optional":false},{"name":"expression","type":"string","optional":false},{"name":"objectGroup","type":"string","optional":true},{"name":"includeCommandLineAPI","type":"boolean","optional":true},{"name":"doNotPauseOnExceptionsAndMuteConsole","type":"boolean","optional":true},{"name":"returnByValue","type":"boolean","optional":true},{"name":"generatePreview","type":"boolean","optional":true}],["result","wasThrown","exceptionDetails"],false);InspectorBackend.registerCommand("Debugger.compileScript",[{"name":"expression","type":"string","optional":false},{"name":"sourceURL","type":"string","optional":false},{"name":"persistScript","type":"boolean","optional":false},{"name":"executionContextId","type":"number","optional":false}],["scriptId","exceptionDetails"],false);InspectorBackend.registerCommand("Debugger.runScript",[{"name":"scriptId","type":"string","optional":false},{"name":"executionContextId","type":"number","optional":false},{"name":"objectGroup","type":"string","optional":true},{"name":"doNotPauseOnExceptionsAndMuteConsole","type":"boolean","optional":true}],["result","exceptionDetails"],false);InspectorBackend.registerCommand("Debugger.setVariableValue",[{"name":"scopeNumber","type":"number","optional":false},{"name":"variableName","type":"string","optional":false},{"name":"newValue","type":"object","optional":false},{"name":"callFrameId","type":"string","optional":true},{"name":"functionObjectId","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Debugger.getStepInPositions",[{"name":"callFrameId","type":"string","optional":false}],["stepInPositions"],false);InspectorBackend.registerCommand("Debugger.getBacktrace",[],["callFrames","asyncStackTrace"],false);InspectorBackend.registerCommand("Debugger.skipStackFrames",[{"name":"script","type":"string","optional":true},{"name":"skipContentScripts","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("Debugger.setAsyncCallStackDepth",[{"name":"maxDepth","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Debugger.enablePromiseTracker",[{"name":"captureStacks","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("Debugger.disablePromiseTracker",[],[],false);InspectorBackend.registerCommand("Debugger.getPromiseById",[{"name":"promiseId","type":"number","optional":false},{"name":"objectGroup","type":"string","optional":true}],["promise"],false);InspectorBackend.registerCommand("Debugger.flushAsyncOperationEvents",[],[],false);InspectorBackend.registerCommand("Debugger.setAsyncOperationBreakpoint",[{"name":"operationId","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Debugger.removeAsyncOperationBreakpoint",[{"name":"operationId","type":"number","optional":false}],[],false);InspectorBackend.registerEnum("DOMDebugger.DOMBreakpointType",{SubtreeModified:"subtree-modified",AttributeModified:"attribute-modified",NodeRemoved:"node-removed"});InspectorBackend.registerCommand("DOMDebugger.setDOMBreakpoint",[{"name":"nodeId","type":"number","optional":false},{"name":"type","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOMDebugger.removeDOMBreakpoint",[{"name":"nodeId","type":"number","optional":false},{"name":"type","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOMDebugger.setEventListenerBreakpoint",[{"name":"eventName","type":"string","optional":false},{"name":"targetName","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("DOMDebugger.removeEventListenerBreakpoint",[{"name":"eventName","type":"string","optional":false},{"name":"targetName","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("DOMDebugger.setInstrumentationBreakpoint",[{"name":"eventName","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOMDebugger.removeInstrumentationBreakpoint",[{"name":"eventName","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOMDebugger.setXHRBreakpoint",[{"name":"url","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOMDebugger.removeXHRBreakpoint",[{"name":"url","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOMDebugger.getEventListeners",[{"name":"objectId","type":"string","optional":false}],["listeners"],false);InspectorBackend.registerEvent("Profiler.consoleProfileStarted",["id","location","title"]);InspectorBackend.registerEvent("Profiler.consoleProfileFinished",["id","location","profile","title"]);InspectorBackend.registerCommand("Profiler.enable",[],[],false);InspectorBackend.registerCommand("Profiler.disable",[],[],false);InspectorBackend.registerCommand("Profiler.setSamplingInterval",[{"name":"interval","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Profiler.start",[],[],false);InspectorBackend.registerCommand("Profiler.stop",[],["profile"],false);InspectorBackend.registerEvent("HeapProfiler.addHeapSnapshotChunk",["chunk"]);InspectorBackend.registerEvent("HeapProfiler.resetProfiles",[]);InspectorBackend.registerEvent("HeapProfiler.reportHeapSnapshotProgress",["done","total","finished"]);InspectorBackend.registerEvent("HeapProfiler.lastSeenObjectId",["lastSeenObjectId","timestamp"]);InspectorBackend.registerEvent("HeapProfiler.heapStatsUpdate",["statsUpdate"]);InspectorBackend.registerCommand("HeapProfiler.enable",[],[],false);InspectorBackend.registerCommand("HeapProfiler.disable",[],[],false);InspectorBackend.registerCommand("HeapProfiler.startTrackingHeapObjects",[{"name":"trackAllocations","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("HeapProfiler.stopTrackingHeapObjects",[{"name":"reportProgress","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("HeapProfiler.takeHeapSnapshot",[{"name":"reportProgress","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("HeapProfiler.collectGarbage",[],[],false);InspectorBackend.registerCommand("HeapProfiler.getObjectByHeapObjectId",[{"name":"objectId","type":"string","optional":false},{"name":"objectGroup","type":"string","optional":true}],["result"],false);InspectorBackend.registerCommand("HeapProfiler.addInspectedHeapObject",[{"name":"heapObjectId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("HeapProfiler.getHeapObjectId",[{"name":"objectId","type":"string","optional":false}],["heapSnapshotObjectId"],false);InspectorBackend.registerEvent("Worker.workerCreated",["workerId","url","inspectorConnected"]);InspectorBackend.registerEvent("Worker.workerTerminated",["workerId"]);InspectorBackend.registerEvent("Worker.dispatchMessageFromWorker",["workerId","message"]);InspectorBackend.registerCommand("Worker.enable",[],[],false);InspectorBackend.registerCommand("Worker.disable",[],[],false);InspectorBackend.registerCommand("Worker.sendMessageToWorker",[{"name":"workerId","type":"string","optional":false},{"name":"message","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Worker.connectToWorker",[{"name":"workerId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Worker.disconnectFromWorker",[{"name":"workerId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Worker.setAutoconnectToWorkers",[{"name":"value","type":"boolean","optional":false}],[],false);InspectorBackend.registerEnum("ServiceWorker.ServiceWorkerVersionRunningStatus",{Stopped:"stopped",Starting:"starting",Running:"running",Stopping:"stopping"});InspectorBackend.registerEnum("ServiceWorker.ServiceWorkerVersionStatus",{New:"new",Installing:"installing",Installed:"installed",Activating:"activating",Activated:"activated",Redundant:"redundant"});InspectorBackend.registerEvent("ServiceWorker.workerCreated",["workerId","url","versionId"]);InspectorBackend.registerEvent("ServiceWorker.workerTerminated",["workerId"]);InspectorBackend.registerEvent("ServiceWorker.dispatchMessage",["workerId","message"]);InspectorBackend.registerEvent("ServiceWorker.workerRegistrationUpdated",["registrations"]);InspectorBackend.registerEvent("ServiceWorker.workerVersionUpdated",["versions"]);InspectorBackend.registerEvent("ServiceWorker.workerErrorReported",["errorMessage"]);InspectorBackend.registerEvent("ServiceWorker.debugOnStartUpdated",["debugOnStart"]);InspectorBackend.registerCommand("ServiceWorker.enable",[],[],false);InspectorBackend.registerCommand("ServiceWorker.disable",[],[],false);InspectorBackend.registerCommand("ServiceWorker.sendMessage",[{"name":"workerId","type":"string","optional":false},{"name":"message","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.stop",[{"name":"workerId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.unregister",[{"name":"scopeURL","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.updateRegistration",[{"name":"scopeURL","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.startWorker",[{"name":"scopeURL","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.stopWorker",[{"name":"versionId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.inspectWorker",[{"name":"versionId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.setDebugOnStart",[{"name":"debugOnStart","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.setForceUpdateOnPageLoad",[{"name":"registrationId","type":"string","optional":false},{"name":"forceUpdateOnPageLoad","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.deliverPushMessage",[{"name":"origin","type":"string","optional":false},{"name":"registrationId","type":"string","optional":false},{"name":"data","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.getTargetInfo",[{"name":"targetId","type":"string","optional":false}],["targetInfo"],false);InspectorBackend.registerCommand("ServiceWorker.activateTarget",[{"name":"targetId","type":"string","optional":false}],[],false);InspectorBackend.registerEnum("Input.TouchPointState",{TouchPressed:"touchPressed",TouchReleased:"touchReleased",TouchMoved:"touchMoved",TouchStationary:"touchStationary",TouchCancelled:"touchCancelled"});InspectorBackend.registerEnum("Input.GestureSourceType",{Default:"default",Touch:"touch",Mouse:"mouse"});InspectorBackend.registerCommand("Input.dispatchKeyEvent",[{"name":"type","type":"string","optional":false},{"name":"modifiers","type":"number","optional":true},{"name":"timestamp","type":"number","optional":true},{"name":"text","type":"string","optional":true},{"name":"unmodifiedText","type":"string","optional":true},{"name":"keyIdentifier","type":"string","optional":true},{"name":"code","type":"string","optional":true},{"name":"key","type":"string","optional":true},{"name":"windowsVirtualKeyCode","type":"number","optional":true},{"name":"nativeVirtualKeyCode","type":"number","optional":true},{"name":"autoRepeat","type":"boolean","optional":true},{"name":"isKeypad","type":"boolean","optional":true},{"name":"isSystemKey","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("Input.dispatchMouseEvent",[{"name":"type","type":"string","optional":false},{"name":"x","type":"number","optional":false},{"name":"y","type":"number","optional":false},{"name":"modifiers","type":"number","optional":true},{"name":"timestamp","type":"number","optional":true},{"name":"button","type":"string","optional":true},{"name":"clickCount","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Input.dispatchTouchEvent",[{"name":"type","type":"string","optional":false},{"name":"touchPoints","type":"object","optional":false},{"name":"modifiers","type":"number","optional":true},{"name":"timestamp","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Input.emulateTouchFromMouseEvent",[{"name":"type","type":"string","optional":false},{"name":"x","type":"number","optional":false},{"name":"y","type":"number","optional":false},{"name":"timestamp","type":"number","optional":false},{"name":"button","type":"string","optional":false},{"name":"deltaX","type":"number","optional":true},{"name":"deltaY","type":"number","optional":true},{"name":"modifiers","type":"number","optional":true},{"name":"clickCount","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Input.synthesizePinchGesture",[{"name":"x","type":"number","optional":false},{"name":"y","type":"number","optional":false},{"name":"scaleFactor","type":"number","optional":false},{"name":"relativeSpeed","type":"number","optional":true},{"name":"gestureSourceType","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Input.synthesizeScrollGesture",[{"name":"x","type":"number","optional":false},{"name":"y","type":"number","optional":false},{"name":"xDistance","type":"number","optional":true},{"name":"yDistance","type":"number","optional":true},{"name":"xOverscroll","type":"number","optional":true},{"name":"yOverscroll","type":"number","optional":true},{"name":"preventFling","type":"boolean","optional":true},{"name":"speed","type":"number","optional":true},{"name":"gestureSourceType","type":"string","optional":true},{"name":"repeatCount","type":"number","optional":true},{"name":"repeatDelayMs","type":"number","optional":true},{"name":"interactionMarkerName","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Input.synthesizeTapGesture",[{"name":"x","type":"number","optional":false},{"name":"y","type":"number","optional":false},{"name":"duration","type":"number","optional":true},{"name":"tapCount","type":"number","optional":true},{"name":"gestureSourceType","type":"string","optional":true}],[],false);InspectorBackend.registerEnum("LayerTree.ScrollRectType",{RepaintsOnScroll:"RepaintsOnScroll",TouchEventHandler:"TouchEventHandler",WheelEventHandler:"WheelEventHandler"});InspectorBackend.registerEvent("LayerTree.layerTreeDidChange",["layers"]);InspectorBackend.registerEvent("LayerTree.layerPainted",["layerId","clip"]);InspectorBackend.registerCommand("LayerTree.enable",[],[],false);InspectorBackend.registerCommand("LayerTree.disable",[],[],false);InspectorBackend.registerCommand("LayerTree.compositingReasons",[{"name":"layerId","type":"string","optional":false}],["compositingReasons"],false);InspectorBackend.registerCommand("LayerTree.makeSnapshot",[{"name":"layerId","type":"string","optional":false}],["snapshotId"],false);InspectorBackend.registerCommand("LayerTree.loadSnapshot",[{"name":"tiles","type":"object","optional":false}],["snapshotId"],false);InspectorBackend.registerCommand("LayerTree.releaseSnapshot",[{"name":"snapshotId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("LayerTree.profileSnapshot",[{"name":"snapshotId","type":"string","optional":false},{"name":"minRepeatCount","type":"number","optional":true},{"name":"minDuration","type":"number","optional":true},{"name":"clipRect","type":"object","optional":true}],["timings"],false);InspectorBackend.registerCommand("LayerTree.replaySnapshot",[{"name":"snapshotId","type":"string","optional":false},{"name":"fromStep","type":"number","optional":true},{"name":"toStep","type":"number","optional":true},{"name":"scale","type":"number","optional":true}],["dataURL"],false);InspectorBackend.registerCommand("LayerTree.snapshotCommandLog",[{"name":"snapshotId","type":"string","optional":false}],["commandLog"],false);InspectorBackend.registerCommand("DeviceOrientation.setDeviceOrientationOverride",[{"name":"alpha","type":"number","optional":false},{"name":"beta","type":"number","optional":false},{"name":"gamma","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("DeviceOrientation.clearDeviceOrientationOverride",[],[],false);InspectorBackend.registerEnum("ScreenOrientation.OrientationType",{PortraitPrimary:"portraitPrimary",PortraitSecondary:"portraitSecondary",LandscapePrimary:"landscapePrimary",LandscapeSecondary:"landscapeSecondary"});InspectorBackend.registerCommand("ScreenOrientation.setScreenOrientationOverride",[{"name":"angle","type":"number","optional":false},{"name":"type","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ScreenOrientation.clearScreenOrientationOverride",[],[],false);InspectorBackend.registerEvent("Tracing.dataCollected",["value"]);InspectorBackend.registerEvent("Tracing.tracingComplete",["stream"]);InspectorBackend.registerEvent("Tracing.bufferUsage",["percentFull","eventCount","value"]);InspectorBackend.registerCommand("Tracing.start",[{"name":"categories","type":"string","optional":true},{"name":"options","type":"string","optional":true},{"name":"bufferUsageReportingInterval","type":"number","optional":true},{"name":"transferMode","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Tracing.end",[],[],false);InspectorBackend.registerCommand("Tracing.getCategories",[],["categories"],false);InspectorBackend.registerCommand("Tracing.requestMemoryDump",[],["dumpGuid","success"],false);InspectorBackend.registerEnum("Animation.AnimationType",{CSSTransition:"CSSTransition",CSSAnimation:"CSSAnimation",WebAnimation:"WebAnimation"});InspectorBackend.registerEvent("Animation.animationCreated",["id"]);InspectorBackend.registerEvent("Animation.animationStarted",["animation"]);InspectorBackend.registerEvent("Animation.animationCanceled",["id"]);InspectorBackend.registerCommand("Animation.enable",[],[],false);InspectorBackend.registerCommand("Animation.disable",[],[],false);InspectorBackend.registerCommand("Animation.getPlaybackRate",[],["playbackRate"],false);InspectorBackend.registerCommand("Animation.setPlaybackRate",[{"name":"playbackRate","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Animation.getCurrentTime",[{"name":"id","type":"string","optional":false}],["currentTime"],false);InspectorBackend.registerCommand("Animation.setPaused",[{"name":"animations","type":"object","optional":false},{"name":"paused","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Animation.setTiming",[{"name":"animationId","type":"string","optional":false},{"name":"duration","type":"number","optional":false},{"name":"delay","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Animation.seekAnimations",[{"name":"animations","type":"object","optional":false},{"name":"currentTime","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Animation.releaseAnimations",[{"name":"animations","type":"object","optional":false}],[],false);InspectorBackend.registerCommand("Animation.resolveAnimation",[{"name":"animationId","type":"string","optional":false}],["remoteObject"],false);InspectorBackend.registerEnum("Accessibility.AXValueType",{Boolean:"boolean",Tristate:"tristate",BooleanOrUndefined:"booleanOrUndefined",Idref:"idref",IdrefList:"idrefList",Integer:"integer",Node:"node",NodeList:"nodeList",Number:"number",String:"string",ComputedString:"computedString",Token:"token",TokenList:"tokenList",DomRelation:"domRelation",Role:"role",InternalRole:"internalRole",ValueUndefined:"valueUndefined"});InspectorBackend.registerEnum("Accessibility.AXValueSourceType",{Attribute:"attribute",Implicit:"implicit",Style:"style",Contents:"contents",Placeholder:"placeholder",RelatedElement:"relatedElement"});InspectorBackend.registerEnum("Accessibility.AXValueNativeSourceType",{Figcaption:"figcaption",Label:"label",Labelfor:"labelfor",Labelwrapped:"labelwrapped",Legend:"legend",Tablecaption:"tablecaption",Title:"title",Other:"other"});InspectorBackend.registerEnum("Accessibility.AXGlobalStates",{Disabled:"disabled",Hidden:"hidden",HiddenRoot:"hiddenRoot",Invalid:"invalid"});InspectorBackend.registerEnum("Accessibility.AXLiveRegionAttributes",{Live:"live",Atomic:"atomic",Relevant:"relevant",Busy:"busy",Root:"root"});InspectorBackend.registerEnum("Accessibility.AXWidgetAttributes",{Autocomplete:"autocomplete",Haspopup:"haspopup",Level:"level",Multiselectable:"multiselectable",Orientation:"orientation",Multiline:"multiline",Readonly:"readonly",Required:"required",Valuemin:"valuemin",Valuemax:"valuemax",Valuetext:"valuetext"});InspectorBackend.registerEnum("Accessibility.AXWidgetStates",{Checked:"checked",Expanded:"expanded",Pressed:"pressed",Selected:"selected"});InspectorBackend.registerEnum("Accessibility.AXRelationshipAttributes",{Activedescendant:"activedescendant",Flowto:"flowto",Controls:"controls",Describedby:"describedby",Labelledby:"labelledby",Owns:"owns"});InspectorBackend.registerCommand("Accessibility.getAXNode",[{"name":"nodeId","type":"number","optional":false}],["accessibilityNode"],false);;WebInspector.InspectorBackendHostedMode={};WebInspector.InspectorBackendHostedMode.loadFromJSONIfNeeded=function(jsonUrl)
+InspectorBackend=new InspectorBackendClass();;InspectorBackend.registerEvent("Inspector.evaluateForTestInFrontend",["testCallId","script"]);InspectorBackend.registerEvent("Inspector.inspect",["object","hints"]);InspectorBackend.registerEvent("Inspector.detached",["reason"]);InspectorBackend.registerEvent("Inspector.targetCrashed",[]);InspectorBackend.registerCommand("Inspector.enable",[],[],false);InspectorBackend.registerCommand("Inspector.disable",[],[],false);InspectorBackend.registerEnum("Memory.PressureLevel",{Moderate:"moderate",Critical:"critical"});InspectorBackend.registerCommand("Memory.getDOMCounters",[],["documents","nodes","jsEventListeners"],false);InspectorBackend.registerCommand("Memory.setPressureNotificationsSuppressed",[{"name":"suppressed","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Memory.simulatePressureNotification",[{"name":"level","type":"string","optional":false}],[],false);InspectorBackend.registerEnum("Page.ResourceType",{Document:"Document",Stylesheet:"Stylesheet",Image:"Image",Media:"Media",Font:"Font",Script:"Script",TextTrack:"TextTrack",XHR:"XHR",Fetch:"Fetch",EventSource:"EventSource",WebSocket:"WebSocket",Manifest:"Manifest",Other:"Other"});InspectorBackend.registerEnum("Page.DialogType",{Alert:"alert",Confirm:"confirm",Prompt:"prompt",Beforeunload:"beforeunload"});InspectorBackend.registerEvent("Page.domContentEventFired",["timestamp"]);InspectorBackend.registerEvent("Page.loadEventFired",["timestamp"]);InspectorBackend.registerEvent("Page.frameAttached",["frameId","parentFrameId"]);InspectorBackend.registerEvent("Page.frameNavigated",["frame"]);InspectorBackend.registerEvent("Page.frameDetached",["frameId"]);InspectorBackend.registerEvent("Page.frameStartedLoading",["frameId"]);InspectorBackend.registerEvent("Page.frameStoppedLoading",["frameId"]);InspectorBackend.registerEvent("Page.frameScheduledNavigation",["frameId","delay"]);InspectorBackend.registerEvent("Page.frameClearedScheduledNavigation",["frameId"]);InspectorBackend.registerEvent("Page.frameResized",[]);InspectorBackend.registerEvent("Page.javascriptDialogOpening",["message","type"]);InspectorBackend.registerEvent("Page.javascriptDialogClosed",["result"]);InspectorBackend.registerEvent("Page.screencastFrame",["data","metadata","sessionId"]);InspectorBackend.registerEvent("Page.screencastVisibilityChanged",["visible"]);InspectorBackend.registerEvent("Page.colorPicked",["color"]);InspectorBackend.registerEvent("Page.interstitialShown",[]);InspectorBackend.registerEvent("Page.interstitialHidden",[]);InspectorBackend.registerCommand("Page.enable",[],[],false);InspectorBackend.registerCommand("Page.disable",[],[],false);InspectorBackend.registerCommand("Page.addScriptToEvaluateOnLoad",[{"name":"scriptSource","type":"string","optional":false}],["identifier"],false);InspectorBackend.registerCommand("Page.removeScriptToEvaluateOnLoad",[{"name":"identifier","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Page.reload",[{"name":"ignoreCache","type":"boolean","optional":true},{"name":"scriptToEvaluateOnLoad","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Page.navigate",[{"name":"url","type":"string","optional":false}],["frameId"],false);InspectorBackend.registerCommand("Page.getNavigationHistory",[],["currentIndex","entries"],false);InspectorBackend.registerCommand("Page.navigateToHistoryEntry",[{"name":"entryId","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Page.getCookies",[],["cookies"],false);InspectorBackend.registerCommand("Page.deleteCookie",[{"name":"cookieName","type":"string","optional":false},{"name":"url","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Page.getResourceTree",[],["frameTree"],false);InspectorBackend.registerCommand("Page.getResourceContent",[{"name":"frameId","type":"string","optional":false},{"name":"url","type":"string","optional":false}],["content","base64Encoded"],false);InspectorBackend.registerCommand("Page.searchInResource",[{"name":"frameId","type":"string","optional":false},{"name":"url","type":"string","optional":false},{"name":"query","type":"string","optional":false},{"name":"caseSensitive","type":"boolean","optional":true},{"name":"isRegex","type":"boolean","optional":true}],["result"],false);InspectorBackend.registerCommand("Page.setDocumentContent",[{"name":"frameId","type":"string","optional":false},{"name":"html","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Page.setDeviceMetricsOverride",[{"name":"width","type":"number","optional":false},{"name":"height","type":"number","optional":false},{"name":"deviceScaleFactor","type":"number","optional":false},{"name":"mobile","type":"boolean","optional":false},{"name":"fitWindow","type":"boolean","optional":false},{"name":"scale","type":"number","optional":true},{"name":"offsetX","type":"number","optional":true},{"name":"offsetY","type":"number","optional":true},{"name":"screenWidth","type":"number","optional":true},{"name":"screenHeight","type":"number","optional":true},{"name":"positionX","type":"number","optional":true},{"name":"positionY","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Page.clearDeviceMetricsOverride",[],[],false);InspectorBackend.registerCommand("Page.setGeolocationOverride",[{"name":"latitude","type":"number","optional":true},{"name":"longitude","type":"number","optional":true},{"name":"accuracy","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Page.clearGeolocationOverride",[],[],false);InspectorBackend.registerCommand("Page.setDeviceOrientationOverride",[{"name":"alpha","type":"number","optional":false},{"name":"beta","type":"number","optional":false},{"name":"gamma","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Page.clearDeviceOrientationOverride",[],[],false);InspectorBackend.registerCommand("Page.setTouchEmulationEnabled",[{"name":"enabled","type":"boolean","optional":false},{"name":"configuration","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Page.captureScreenshot",[],["data"],false);InspectorBackend.registerCommand("Page.startScreencast",[{"name":"format","type":"string","optional":true},{"name":"quality","type":"number","optional":true},{"name":"maxWidth","type":"number","optional":true},{"name":"maxHeight","type":"number","optional":true},{"name":"everyNthFrame","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Page.stopScreencast",[],[],false);InspectorBackend.registerCommand("Page.screencastFrameAck",[{"name":"sessionId","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Page.handleJavaScriptDialog",[{"name":"accept","type":"boolean","optional":false},{"name":"promptText","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Page.setColorPickerEnabled",[{"name":"enabled","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Page.setOverlayMessage",[{"name":"message","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Rendering.setShowPaintRects",[{"name":"result","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Rendering.setShowDebugBorders",[{"name":"show","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Rendering.setShowFPSCounter",[{"name":"show","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Rendering.setShowScrollBottleneckRects",[{"name":"show","type":"boolean","optional":false}],[],false);InspectorBackend.registerEvent("Emulation.viewportChanged",["viewport"]);InspectorBackend.registerCommand("Emulation.setDeviceMetricsOverride",[{"name":"width","type":"number","optional":false},{"name":"height","type":"number","optional":false},{"name":"deviceScaleFactor","type":"number","optional":false},{"name":"mobile","type":"boolean","optional":false},{"name":"fitWindow","type":"boolean","optional":false},{"name":"scale","type":"number","optional":true},{"name":"offsetX","type":"number","optional":true},{"name":"offsetY","type":"number","optional":true},{"name":"screenWidth","type":"number","optional":true},{"name":"screenHeight","type":"number","optional":true},{"name":"positionX","type":"number","optional":true},{"name":"positionY","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Emulation.clearDeviceMetricsOverride",[],[],false);InspectorBackend.registerCommand("Emulation.resetScrollAndPageScaleFactor",[],[],false);InspectorBackend.registerCommand("Emulation.setPageScaleFactor",[{"name":"pageScaleFactor","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Emulation.setScriptExecutionDisabled",[{"name":"value","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Emulation.setGeolocationOverride",[{"name":"latitude","type":"number","optional":true},{"name":"longitude","type":"number","optional":true},{"name":"accuracy","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Emulation.clearGeolocationOverride",[],[],false);InspectorBackend.registerCommand("Emulation.setTouchEmulationEnabled",[{"name":"enabled","type":"boolean","optional":false},{"name":"configuration","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Emulation.setEmulatedMedia",[{"name":"media","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Emulation.setCPUThrottlingRate",[{"name":"rate","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Emulation.canEmulate",[],["result"],false);InspectorBackend.registerEnum("Runtime.RemoteObjectType",{Object:"object",Function:"function",Undefined:"undefined",String:"string",Number:"number",Boolean:"boolean",Symbol:"symbol"});InspectorBackend.registerEnum("Runtime.RemoteObjectSubtype",{Array:"array",Null:"null",Node:"node",Regexp:"regexp",Date:"date",Map:"map",Set:"set",Iterator:"iterator",Generator:"generator",Error:"error"});InspectorBackend.registerEnum("Runtime.ObjectPreviewType",{Object:"object",Function:"function",Undefined:"undefined",String:"string",Number:"number",Boolean:"boolean",Symbol:"symbol"});InspectorBackend.registerEnum("Runtime.ObjectPreviewSubtype",{Array:"array",Null:"null",Node:"node",Regexp:"regexp",Date:"date",Map:"map",Set:"set",Iterator:"iterator",Generator:"generator",Error:"error"});InspectorBackend.registerEnum("Runtime.PropertyPreviewType",{Object:"object",Function:"function",Undefined:"undefined",String:"string",Number:"number",Boolean:"boolean",Symbol:"symbol",Accessor:"accessor"});InspectorBackend.registerEnum("Runtime.PropertyPreviewSubtype",{Array:"array",Null:"null",Node:"node",Regexp:"regexp",Date:"date",Map:"map",Set:"set",Iterator:"iterator",Generator:"generator",Error:"error"});InspectorBackend.registerEnum("Runtime.CallArgumentType",{Object:"object",Function:"function",Undefined:"undefined",String:"string",Number:"number",Boolean:"boolean",Symbol:"symbol"});InspectorBackend.registerEvent("Runtime.executionContextCreated",["context"]);InspectorBackend.registerEvent("Runtime.executionContextDestroyed",["executionContextId"]);InspectorBackend.registerEvent("Runtime.executionContextsCleared",[]);InspectorBackend.registerCommand("Runtime.evaluate",[{"name":"expression","type":"string","optional":false},{"name":"objectGroup","type":"string","optional":true},{"name":"includeCommandLineAPI","type":"boolean","optional":true},{"name":"doNotPauseOnExceptionsAndMuteConsole","type":"boolean","optional":true},{"name":"contextId","type":"number","optional":true},{"name":"returnByValue","type":"boolean","optional":true},{"name":"generatePreview","type":"boolean","optional":true}],["result","wasThrown","exceptionDetails"],false);InspectorBackend.registerCommand("Runtime.callFunctionOn",[{"name":"objectId","type":"string","optional":false},{"name":"functionDeclaration","type":"string","optional":false},{"name":"arguments","type":"object","optional":true},{"name":"doNotPauseOnExceptionsAndMuteConsole","type":"boolean","optional":true},{"name":"returnByValue","type":"boolean","optional":true},{"name":"generatePreview","type":"boolean","optional":true}],["result","wasThrown"],false);InspectorBackend.registerCommand("Runtime.getProperties",[{"name":"objectId","type":"string","optional":false},{"name":"ownProperties","type":"boolean","optional":true},{"name":"accessorPropertiesOnly","type":"boolean","optional":true},{"name":"generatePreview","type":"boolean","optional":true}],["result","internalProperties","exceptionDetails"],false);InspectorBackend.registerCommand("Runtime.releaseObject",[{"name":"objectId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Runtime.releaseObjectGroup",[{"name":"objectGroup","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Runtime.run",[],[],false);InspectorBackend.registerCommand("Runtime.enable",[],[],false);InspectorBackend.registerCommand("Runtime.disable",[],[],false);InspectorBackend.registerCommand("Runtime.isRunRequired",[],["result"],false);InspectorBackend.registerCommand("Runtime.setCustomObjectFormatterEnabled",[{"name":"enabled","type":"boolean","optional":false}],[],false);InspectorBackend.registerEnum("Console.ConsoleMessageSource",{XML:"xml",Javascript:"javascript",Network:"network",ConsoleAPI:"console-api",Storage:"storage",Appcache:"appcache",Rendering:"rendering",Security:"security",Other:"other",Deprecation:"deprecation"});InspectorBackend.registerEnum("Console.ConsoleMessageLevel",{Log:"log",Warning:"warning",Error:"error",Debug:"debug",Info:"info",RevokedError:"revokedError"});InspectorBackend.registerEnum("Console.ConsoleMessageType",{Log:"log",Dir:"dir",DirXML:"dirxml",Table:"table",Trace:"trace",Clear:"clear",StartGroup:"startGroup",StartGroupCollapsed:"startGroupCollapsed",EndGroup:"endGroup",Assert:"assert",Profile:"profile",ProfileEnd:"profileEnd"});InspectorBackend.registerEvent("Console.messageAdded",["message"]);InspectorBackend.registerEvent("Console.messageRepeatCountUpdated",["count","timestamp"]);InspectorBackend.registerEvent("Console.messagesCleared",[]);InspectorBackend.registerCommand("Console.enable",[],[],false);InspectorBackend.registerCommand("Console.disable",[],[],false);InspectorBackend.registerCommand("Console.clearMessages",[],[],false);InspectorBackend.registerEnum("Security.SecurityState",{Unknown:"unknown",Neutral:"neutral",Insecure:"insecure",Warning:"warning",Secure:"secure",Info:"info"});InspectorBackend.registerEvent("Security.securityStateChanged",["securityState","explanations","mixedContentStatus","schemeIsCryptographic"]);InspectorBackend.registerCommand("Security.enable",[],[],false);InspectorBackend.registerCommand("Security.disable",[],[],false);InspectorBackend.registerEnum("Network.ResourcePriority",{VeryLow:"VeryLow",Low:"Low",Medium:"Medium",High:"High",VeryHigh:"VeryHigh"});InspectorBackend.registerEnum("Network.RequestMixedContentType",{Blockable:"blockable",OptionallyBlockable:"optionally-blockable",None:"none"});InspectorBackend.registerEnum("Network.BlockedReason",{Csp:"csp",MixedContent:"mixed-content",Origin:"origin",Inspector:"inspector",Other:"other"});InspectorBackend.registerEnum("Network.InitiatorType",{Parser:"parser",Script:"script",Other:"other"});InspectorBackend.registerEvent("Network.requestWillBeSent",["requestId","frameId","loaderId","documentURL","request","timestamp","wallTime","initiator","redirectResponse","type"]);InspectorBackend.registerEvent("Network.requestServedFromCache",["requestId"]);InspectorBackend.registerEvent("Network.responseReceived",["requestId","frameId","loaderId","timestamp","type","response"]);InspectorBackend.registerEvent("Network.dataReceived",["requestId","timestamp","dataLength","encodedDataLength"]);InspectorBackend.registerEvent("Network.loadingFinished",["requestId","timestamp","encodedDataLength"]);InspectorBackend.registerEvent("Network.loadingFailed",["requestId","timestamp","type","errorText","canceled","blockedReason"]);InspectorBackend.registerEvent("Network.webSocketWillSendHandshakeRequest",["requestId","timestamp","wallTime","request"]);InspectorBackend.registerEvent("Network.webSocketHandshakeResponseReceived",["requestId","timestamp","response"]);InspectorBackend.registerEvent("Network.webSocketCreated",["requestId","url"]);InspectorBackend.registerEvent("Network.webSocketClosed",["requestId","timestamp"]);InspectorBackend.registerEvent("Network.webSocketFrameReceived",["requestId","timestamp","response"]);InspectorBackend.registerEvent("Network.webSocketFrameError",["requestId","timestamp","errorMessage"]);InspectorBackend.registerEvent("Network.webSocketFrameSent",["requestId","timestamp","response"]);InspectorBackend.registerEvent("Network.eventSourceMessageReceived",["requestId","timestamp","eventName","eventId","data"]);InspectorBackend.registerCommand("Network.enable",[],[],false);InspectorBackend.registerCommand("Network.disable",[],[],false);InspectorBackend.registerCommand("Network.setUserAgentOverride",[{"name":"userAgent","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Network.setExtraHTTPHeaders",[{"name":"headers","type":"object","optional":false}],[],false);InspectorBackend.registerCommand("Network.getResponseBody",[{"name":"requestId","type":"string","optional":false}],["body","base64Encoded"],false);InspectorBackend.registerCommand("Network.addBlockedURL",[{"name":"url","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Network.removeBlockedURL",[{"name":"url","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Network.replayXHR",[{"name":"requestId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Network.setMonitoringXHREnabled",[{"name":"enabled","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Network.canClearBrowserCache",[],["result"],false);InspectorBackend.registerCommand("Network.clearBrowserCache",[],[],false);InspectorBackend.registerCommand("Network.canClearBrowserCookies",[],["result"],false);InspectorBackend.registerCommand("Network.clearBrowserCookies",[],[],false);InspectorBackend.registerCommand("Network.getCookies",[],["cookies"],false);InspectorBackend.registerCommand("Network.deleteCookie",[{"name":"cookieName","type":"string","optional":false},{"name":"url","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Network.canEmulateNetworkConditions",[],["result"],false);InspectorBackend.registerCommand("Network.emulateNetworkConditions",[{"name":"offline","type":"boolean","optional":false},{"name":"latency","type":"number","optional":false},{"name":"downloadThroughput","type":"number","optional":false},{"name":"uploadThroughput","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Network.setCacheDisabled",[{"name":"cacheDisabled","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Network.setDataSizeLimitsForTest",[{"name":"maxTotalSize","type":"number","optional":false},{"name":"maxResourceSize","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Network.getCertificateDetails",[{"name":"certificateId","type":"number","optional":false}],["result"],false);InspectorBackend.registerCommand("Network.showCertificateViewer",[{"name":"certificateId","type":"number","optional":false}],[],false);InspectorBackend.registerEvent("Database.addDatabase",["database"]);InspectorBackend.registerCommand("Database.enable",[],[],false);InspectorBackend.registerCommand("Database.disable",[],[],false);InspectorBackend.registerCommand("Database.getDatabaseTableNames",[{"name":"databaseId","type":"string","optional":false}],["tableNames"],false);InspectorBackend.registerCommand("Database.executeSQL",[{"name":"databaseId","type":"string","optional":false},{"name":"query","type":"string","optional":false}],["columnNames","values","sqlError"],false);InspectorBackend.registerEnum("IndexedDB.KeyType",{Number:"number",String:"string",Date:"date",Array:"array"});InspectorBackend.registerEnum("IndexedDB.KeyPathType",{Null:"null",String:"string",Array:"array"});InspectorBackend.registerCommand("IndexedDB.enable",[],[],false);InspectorBackend.registerCommand("IndexedDB.disable",[],[],false);InspectorBackend.registerCommand("IndexedDB.requestDatabaseNames",[{"name":"securityOrigin","type":"string","optional":false}],["databaseNames"],false);InspectorBackend.registerCommand("IndexedDB.requestDatabase",[{"name":"securityOrigin","type":"string","optional":false},{"name":"databaseName","type":"string","optional":false}],["databaseWithObjectStores"],false);InspectorBackend.registerCommand("IndexedDB.requestData",[{"name":"securityOrigin","type":"string","optional":false},{"name":"databaseName","type":"string","optional":false},{"name":"objectStoreName","type":"string","optional":false},{"name":"indexName","type":"string","optional":false},{"name":"skipCount","type":"number","optional":false},{"name":"pageSize","type":"number","optional":false},{"name":"keyRange","type":"object","optional":true}],["objectStoreDataEntries","hasMore"],false);InspectorBackend.registerCommand("IndexedDB.clearObjectStore",[{"name":"securityOrigin","type":"string","optional":false},{"name":"databaseName","type":"string","optional":false},{"name":"objectStoreName","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("CacheStorage.requestCacheNames",[{"name":"securityOrigin","type":"string","optional":false}],["caches"],false);InspectorBackend.registerCommand("CacheStorage.requestEntries",[{"name":"cacheId","type":"string","optional":false},{"name":"skipCount","type":"number","optional":false},{"name":"pageSize","type":"number","optional":false}],["cacheDataEntries","hasMore"],false);InspectorBackend.registerCommand("CacheStorage.deleteCache",[{"name":"cacheId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("CacheStorage.deleteEntry",[{"name":"cacheId","type":"string","optional":false},{"name":"request","type":"string","optional":false}],[],false);InspectorBackend.registerEvent("DOMStorage.domStorageItemsCleared",["storageId"]);InspectorBackend.registerEvent("DOMStorage.domStorageItemRemoved",["storageId","key"]);InspectorBackend.registerEvent("DOMStorage.domStorageItemAdded",["storageId","key","newValue"]);InspectorBackend.registerEvent("DOMStorage.domStorageItemUpdated",["storageId","key","oldValue","newValue"]);InspectorBackend.registerCommand("DOMStorage.enable",[],[],false);InspectorBackend.registerCommand("DOMStorage.disable",[],[],false);InspectorBackend.registerCommand("DOMStorage.getDOMStorageItems",[{"name":"storageId","type":"object","optional":false}],["entries"],false);InspectorBackend.registerCommand("DOMStorage.setDOMStorageItem",[{"name":"storageId","type":"object","optional":false},{"name":"key","type":"string","optional":false},{"name":"value","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOMStorage.removeDOMStorageItem",[{"name":"storageId","type":"object","optional":false},{"name":"key","type":"string","optional":false}],[],false);InspectorBackend.registerEvent("ApplicationCache.applicationCacheStatusUpdated",["frameId","manifestURL","status"]);InspectorBackend.registerEvent("ApplicationCache.networkStateUpdated",["isNowOnline"]);InspectorBackend.registerCommand("ApplicationCache.getFramesWithManifests",[],["frameIds"],false);InspectorBackend.registerCommand("ApplicationCache.enable",[],[],false);InspectorBackend.registerCommand("ApplicationCache.getManifestForFrame",[{"name":"frameId","type":"string","optional":false}],["manifestURL"],false);InspectorBackend.registerCommand("ApplicationCache.getApplicationCacheForFrame",[{"name":"frameId","type":"string","optional":false}],["applicationCache"],false);InspectorBackend.registerCommand("FileSystem.enable",[],[],false);InspectorBackend.registerCommand("FileSystem.disable",[],[],false);InspectorBackend.registerCommand("FileSystem.requestFileSystemRoot",[{"name":"origin","type":"string","optional":false},{"name":"type","type":"string","optional":false}],["errorCode","root"],false);InspectorBackend.registerCommand("FileSystem.requestDirectoryContent",[{"name":"url","type":"string","optional":false}],["errorCode","entries"],false);InspectorBackend.registerCommand("FileSystem.requestMetadata",[{"name":"url","type":"string","optional":false}],["errorCode","metadata"],false);InspectorBackend.registerCommand("FileSystem.requestFileContent",[{"name":"url","type":"string","optional":false},{"name":"readAsText","type":"boolean","optional":false},{"name":"start","type":"number","optional":true},{"name":"end","type":"number","optional":true},{"name":"charset","type":"string","optional":true}],["errorCode","content","charset"],false);InspectorBackend.registerCommand("FileSystem.deleteEntry",[{"name":"url","type":"string","optional":false}],["errorCode"],false);InspectorBackend.registerEnum("DOM.PseudoType",{FirstLine:"first-line",FirstLetter:"first-letter",Before:"before",After:"after",Backdrop:"backdrop",Selection:"selection",FirstLineInherited:"first-line-inherited",Scrollbar:"scrollbar",ScrollbarThumb:"scrollbar-thumb",ScrollbarButton:"scrollbar-button",ScrollbarTrack:"scrollbar-track",ScrollbarTrackPiece:"scrollbar-track-piece",ScrollbarCorner:"scrollbar-corner",Resizer:"resizer",InputListButton:"input-list-button"});InspectorBackend.registerEnum("DOM.ShadowRootType",{UserAgent:"user-agent",Open:"open",Closed:"closed"});InspectorBackend.registerEnum("DOM.InspectMode",{SearchForNode:"searchForNode",SearchForUAShadowDOM:"searchForUAShadowDOM",ShowLayoutEditor:"showLayoutEditor",None:"none"});InspectorBackend.registerEvent("DOM.documentUpdated",[]);InspectorBackend.registerEvent("DOM.inspectNodeRequested",["backendNodeId"]);InspectorBackend.registerEvent("DOM.setChildNodes",["parentId","nodes"]);InspectorBackend.registerEvent("DOM.attributeModified",["nodeId","name","value"]);InspectorBackend.registerEvent("DOM.attributeRemoved",["nodeId","name"]);InspectorBackend.registerEvent("DOM.inlineStyleInvalidated",["nodeIds"]);InspectorBackend.registerEvent("DOM.characterDataModified",["nodeId","characterData"]);InspectorBackend.registerEvent("DOM.childNodeCountUpdated",["nodeId","childNodeCount"]);InspectorBackend.registerEvent("DOM.childNodeInserted",["parentNodeId","previousNodeId","node"]);InspectorBackend.registerEvent("DOM.childNodeRemoved",["parentNodeId","nodeId"]);InspectorBackend.registerEvent("DOM.shadowRootPushed",["hostId","root"]);InspectorBackend.registerEvent("DOM.shadowRootPopped",["hostId","rootId"]);InspectorBackend.registerEvent("DOM.pseudoElementAdded",["parentId","pseudoElement"]);InspectorBackend.registerEvent("DOM.pseudoElementRemoved",["parentId","pseudoElementId"]);InspectorBackend.registerEvent("DOM.distributedNodesUpdated",["insertionPointId","distributedNodes"]);InspectorBackend.registerEvent("DOM.nodeHighlightRequested",["nodeId"]);InspectorBackend.registerCommand("DOM.enable",[],[],false);InspectorBackend.registerCommand("DOM.disable",[],[],false);InspectorBackend.registerCommand("DOM.getDocument",[],["root"],false);InspectorBackend.registerCommand("DOM.requestChildNodes",[{"name":"nodeId","type":"number","optional":false},{"name":"depth","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("DOM.querySelector",[{"name":"nodeId","type":"number","optional":false},{"name":"selector","type":"string","optional":false}],["nodeId"],false);InspectorBackend.registerCommand("DOM.querySelectorAll",[{"name":"nodeId","type":"number","optional":false},{"name":"selector","type":"string","optional":false}],["nodeIds"],false);InspectorBackend.registerCommand("DOM.setNodeName",[{"name":"nodeId","type":"number","optional":false},{"name":"name","type":"string","optional":false}],["nodeId"],false);InspectorBackend.registerCommand("DOM.setNodeValue",[{"name":"nodeId","type":"number","optional":false},{"name":"value","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOM.removeNode",[{"name":"nodeId","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("DOM.setAttributeValue",[{"name":"nodeId","type":"number","optional":false},{"name":"name","type":"string","optional":false},{"name":"value","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOM.setAttributesAsText",[{"name":"nodeId","type":"number","optional":false},{"name":"text","type":"string","optional":false},{"name":"name","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("DOM.removeAttribute",[{"name":"nodeId","type":"number","optional":false},{"name":"name","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOM.getOuterHTML",[{"name":"nodeId","type":"number","optional":false}],["outerHTML"],false);InspectorBackend.registerCommand("DOM.setOuterHTML",[{"name":"nodeId","type":"number","optional":false},{"name":"outerHTML","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOM.performSearch",[{"name":"query","type":"string","optional":false},{"name":"includeUserAgentShadowDOM","type":"boolean","optional":true}],["searchId","resultCount"],false);InspectorBackend.registerCommand("DOM.getSearchResults",[{"name":"searchId","type":"string","optional":false},{"name":"fromIndex","type":"number","optional":false},{"name":"toIndex","type":"number","optional":false}],["nodeIds"],false);InspectorBackend.registerCommand("DOM.discardSearchResults",[{"name":"searchId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOM.requestNode",[{"name":"objectId","type":"string","optional":false}],["nodeId"],false);InspectorBackend.registerCommand("DOM.setInspectMode",[{"name":"mode","type":"string","optional":false},{"name":"highlightConfig","type":"object","optional":true}],[],false);InspectorBackend.registerCommand("DOM.highlightRect",[{"name":"x","type":"number","optional":false},{"name":"y","type":"number","optional":false},{"name":"width","type":"number","optional":false},{"name":"height","type":"number","optional":false},{"name":"color","type":"object","optional":true},{"name":"outlineColor","type":"object","optional":true}],[],false);InspectorBackend.registerCommand("DOM.highlightQuad",[{"name":"quad","type":"object","optional":false},{"name":"color","type":"object","optional":true},{"name":"outlineColor","type":"object","optional":true}],[],false);InspectorBackend.registerCommand("DOM.highlightNode",[{"name":"highlightConfig","type":"object","optional":false},{"name":"nodeId","type":"number","optional":true},{"name":"backendNodeId","type":"number","optional":true},{"name":"objectId","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("DOM.hideHighlight",[],[],false);InspectorBackend.registerCommand("DOM.highlightFrame",[{"name":"frameId","type":"string","optional":false},{"name":"contentColor","type":"object","optional":true},{"name":"contentOutlineColor","type":"object","optional":true}],[],false);InspectorBackend.registerCommand("DOM.pushNodeByPathToFrontend",[{"name":"path","type":"string","optional":false}],["nodeId"],false);InspectorBackend.registerCommand("DOM.pushNodesByBackendIdsToFrontend",[{"name":"backendNodeIds","type":"object","optional":false}],["nodeIds"],false);InspectorBackend.registerCommand("DOM.setInspectedNode",[{"name":"nodeId","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("DOM.resolveNode",[{"name":"nodeId","type":"number","optional":false},{"name":"objectGroup","type":"string","optional":true}],["object"],false);InspectorBackend.registerCommand("DOM.getAttributes",[{"name":"nodeId","type":"number","optional":false}],["attributes"],false);InspectorBackend.registerCommand("DOM.copyTo",[{"name":"nodeId","type":"number","optional":false},{"name":"targetNodeId","type":"number","optional":false},{"name":"insertBeforeNodeId","type":"number","optional":true}],["nodeId"],false);InspectorBackend.registerCommand("DOM.moveTo",[{"name":"nodeId","type":"number","optional":false},{"name":"targetNodeId","type":"number","optional":false},{"name":"insertBeforeNodeId","type":"number","optional":true}],["nodeId"],false);InspectorBackend.registerCommand("DOM.undo",[],[],false);InspectorBackend.registerCommand("DOM.redo",[],[],false);InspectorBackend.registerCommand("DOM.markUndoableState",[],[],false);InspectorBackend.registerCommand("DOM.focus",[{"name":"nodeId","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("DOM.setFileInputFiles",[{"name":"nodeId","type":"number","optional":false},{"name":"files","type":"object","optional":false}],[],false);InspectorBackend.registerCommand("DOM.getBoxModel",[{"name":"nodeId","type":"number","optional":false}],["model"],false);InspectorBackend.registerCommand("DOM.getNodeForLocation",[{"name":"x","type":"number","optional":false},{"name":"y","type":"number","optional":false}],["nodeId"],false);InspectorBackend.registerCommand("DOM.getRelayoutBoundary",[{"name":"nodeId","type":"number","optional":false}],["nodeId"],false);InspectorBackend.registerCommand("DOM.getHighlightObjectForTest",[{"name":"nodeId","type":"number","optional":false}],["highlight"],false);InspectorBackend.registerEnum("CSS.StyleSheetOrigin",{Injected:"injected",UserAgent:"user-agent",Inspector:"inspector",Regular:"regular"});InspectorBackend.registerEnum("CSS.CSSMediaSource",{MediaRule:"mediaRule",ImportRule:"importRule",LinkedSheet:"linkedSheet",InlineSheet:"inlineSheet"});InspectorBackend.registerEvent("CSS.mediaQueryResultChanged",[]);InspectorBackend.registerEvent("CSS.styleSheetChanged",["styleSheetId"]);InspectorBackend.registerEvent("CSS.styleSheetAdded",["header"]);InspectorBackend.registerEvent("CSS.styleSheetRemoved",["styleSheetId"]);InspectorBackend.registerEvent("CSS.layoutEditorChange",["styleSheetId","changeRange"]);InspectorBackend.registerCommand("CSS.enable",[],[],false);InspectorBackend.registerCommand("CSS.disable",[],[],false);InspectorBackend.registerCommand("CSS.getMatchedStylesForNode",[{"name":"nodeId","type":"number","optional":false}],["inlineStyle","attributesStyle","matchedCSSRules","pseudoElements","inherited"],false);InspectorBackend.registerCommand("CSS.getInlineStylesForNode",[{"name":"nodeId","type":"number","optional":false}],["inlineStyle","attributesStyle"],false);InspectorBackend.registerCommand("CSS.getComputedStyleForNode",[{"name":"nodeId","type":"number","optional":false}],["computedStyle"],false);InspectorBackend.registerCommand("CSS.getPlatformFontsForNode",[{"name":"nodeId","type":"number","optional":false}],["fonts"],false);InspectorBackend.registerCommand("CSS.getCSSAnimationsForNode",[{"name":"nodeId","type":"number","optional":false}],["cssKeyframesRules"],false);InspectorBackend.registerCommand("CSS.getStyleSheetText",[{"name":"styleSheetId","type":"string","optional":false}],["text"],false);InspectorBackend.registerCommand("CSS.setStyleSheetText",[{"name":"styleSheetId","type":"string","optional":false},{"name":"text","type":"string","optional":false}],["sourceMapURL"],false);InspectorBackend.registerCommand("CSS.setRuleSelector",[{"name":"styleSheetId","type":"string","optional":false},{"name":"range","type":"object","optional":false},{"name":"selector","type":"string","optional":false}],["selectorList"],false);InspectorBackend.registerCommand("CSS.setStyleText",[{"name":"styleSheetId","type":"string","optional":false},{"name":"range","type":"object","optional":false},{"name":"text","type":"string","optional":false}],["style"],false);InspectorBackend.registerCommand("CSS.setMediaText",[{"name":"styleSheetId","type":"string","optional":false},{"name":"range","type":"object","optional":false},{"name":"text","type":"string","optional":false}],["media"],false);InspectorBackend.registerCommand("CSS.createStyleSheet",[{"name":"frameId","type":"string","optional":false}],["styleSheetId"],false);InspectorBackend.registerCommand("CSS.addRule",[{"name":"styleSheetId","type":"string","optional":false},{"name":"ruleText","type":"string","optional":false},{"name":"location","type":"object","optional":false}],["rule"],false);InspectorBackend.registerCommand("CSS.forcePseudoState",[{"name":"nodeId","type":"number","optional":false},{"name":"forcedPseudoClasses","type":"object","optional":false}],[],false);InspectorBackend.registerCommand("CSS.getMediaQueries",[],["medias"],false);InspectorBackend.registerCommand("CSS.setEffectivePropertyValueForNode",[{"name":"nodeId","type":"number","optional":false},{"name":"propertyName","type":"string","optional":false},{"name":"value","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("CSS.getBackgroundColors",[{"name":"nodeId","type":"number","optional":false}],["backgroundColors"],false);InspectorBackend.registerCommand("IO.read",[{"name":"handle","type":"string","optional":false},{"name":"offset","type":"number","optional":true},{"name":"size","type":"number","optional":true}],["data","eof"],false);InspectorBackend.registerCommand("IO.close",[{"name":"handle","type":"string","optional":false}],[],false);InspectorBackend.registerEvent("Timeline.eventRecorded",["record"]);InspectorBackend.registerCommand("Timeline.enable",[],[],false);InspectorBackend.registerCommand("Timeline.disable",[],[],false);InspectorBackend.registerCommand("Timeline.start",[{"name":"maxCallStackDepth","type":"number","optional":true},{"name":"bufferEvents","type":"boolean","optional":true},{"name":"liveEvents","type":"string","optional":true},{"name":"includeCounters","type":"boolean","optional":true},{"name":"includeGPUEvents","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("Timeline.stop",[],[],false);InspectorBackend.registerEnum("Debugger.GeneratorObjectDetailsStatus",{Running:"running",Suspended:"suspended",Closed:"closed"});InspectorBackend.registerEnum("Debugger.ScopeType",{Global:"global",Local:"local",With:"with",Closure:"closure",Catch:"catch",Block:"block",Script:"script"});InspectorBackend.registerEnum("Debugger.PromiseDetailsStatus",{Pending:"pending",Resolved:"resolved",Rejected:"rejected"});InspectorBackend.registerEvent("Debugger.globalObjectCleared",[]);InspectorBackend.registerEvent("Debugger.scriptParsed",["scriptId","url","startLine","startColumn","endLine","endColumn","executionContextId","isContentScript","isInternalScript","isLiveEdit","sourceMapURL","hasSourceURL"]);InspectorBackend.registerEvent("Debugger.scriptFailedToParse",["scriptId","url","startLine","startColumn","endLine","endColumn","executionContextId","isContentScript","isInternalScript","sourceMapURL","hasSourceURL"]);InspectorBackend.registerEvent("Debugger.breakpointResolved",["breakpointId","location"]);InspectorBackend.registerEvent("Debugger.paused",["callFrames","reason","data","hitBreakpoints","asyncStackTrace"]);InspectorBackend.registerEvent("Debugger.resumed",[]);InspectorBackend.registerEvent("Debugger.promiseUpdated",["eventType","promise"]);InspectorBackend.registerEvent("Debugger.asyncOperationStarted",["operation"]);InspectorBackend.registerEvent("Debugger.asyncOperationCompleted",["id"]);InspectorBackend.registerCommand("Debugger.enable",[],[],false);InspectorBackend.registerCommand("Debugger.disable",[],[],false);InspectorBackend.registerCommand("Debugger.setBreakpointsActive",[{"name":"active","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Debugger.setSkipAllPauses",[{"name":"skipped","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Debugger.setBreakpointByUrl",[{"name":"lineNumber","type":"number","optional":false},{"name":"url","type":"string","optional":true},{"name":"urlRegex","type":"string","optional":true},{"name":"columnNumber","type":"number","optional":true},{"name":"condition","type":"string","optional":true}],["breakpointId","locations"],false);InspectorBackend.registerCommand("Debugger.setBreakpoint",[{"name":"location","type":"object","optional":false},{"name":"condition","type":"string","optional":true}],["breakpointId","actualLocation"],false);InspectorBackend.registerCommand("Debugger.removeBreakpoint",[{"name":"breakpointId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Debugger.continueToLocation",[{"name":"location","type":"object","optional":false},{"name":"interstatementLocation","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("Debugger.stepOver",[],[],false);InspectorBackend.registerCommand("Debugger.stepInto",[],[],false);InspectorBackend.registerCommand("Debugger.stepOut",[],[],false);InspectorBackend.registerCommand("Debugger.pause",[],[],false);InspectorBackend.registerCommand("Debugger.resume",[],[],false);InspectorBackend.registerCommand("Debugger.stepIntoAsync",[],[],false);InspectorBackend.registerCommand("Debugger.searchInContent",[{"name":"scriptId","type":"string","optional":false},{"name":"query","type":"string","optional":false},{"name":"caseSensitive","type":"boolean","optional":true},{"name":"isRegex","type":"boolean","optional":true}],["result"],false);InspectorBackend.registerCommand("Debugger.canSetScriptSource",[],["result"],false);InspectorBackend.registerCommand("Debugger.setScriptSource",[{"name":"scriptId","type":"string","optional":false},{"name":"scriptSource","type":"string","optional":false},{"name":"preview","type":"boolean","optional":true}],["callFrames","stackChanged","asyncStackTrace"],true);InspectorBackend.registerCommand("Debugger.restartFrame",[{"name":"callFrameId","type":"string","optional":false}],["callFrames","asyncStackTrace"],false);InspectorBackend.registerCommand("Debugger.getScriptSource",[{"name":"scriptId","type":"string","optional":false}],["scriptSource"],false);InspectorBackend.registerCommand("Debugger.getFunctionDetails",[{"name":"functionId","type":"string","optional":false}],["details"],false);InspectorBackend.registerCommand("Debugger.getGeneratorObjectDetails",[{"name":"objectId","type":"string","optional":false}],["details"],false);InspectorBackend.registerCommand("Debugger.getCollectionEntries",[{"name":"objectId","type":"string","optional":false}],["entries"],false);InspectorBackend.registerCommand("Debugger.setPauseOnExceptions",[{"name":"state","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Debugger.evaluateOnCallFrame",[{"name":"callFrameId","type":"string","optional":false},{"name":"expression","type":"string","optional":false},{"name":"objectGroup","type":"string","optional":true},{"name":"includeCommandLineAPI","type":"boolean","optional":true},{"name":"doNotPauseOnExceptionsAndMuteConsole","type":"boolean","optional":true},{"name":"returnByValue","type":"boolean","optional":true},{"name":"generatePreview","type":"boolean","optional":true}],["result","wasThrown","exceptionDetails"],false);InspectorBackend.registerCommand("Debugger.compileScript",[{"name":"expression","type":"string","optional":false},{"name":"sourceURL","type":"string","optional":false},{"name":"persistScript","type":"boolean","optional":false},{"name":"executionContextId","type":"number","optional":false}],["scriptId","exceptionDetails"],false);InspectorBackend.registerCommand("Debugger.runScript",[{"name":"scriptId","type":"string","optional":false},{"name":"executionContextId","type":"number","optional":false},{"name":"objectGroup","type":"string","optional":true},{"name":"doNotPauseOnExceptionsAndMuteConsole","type":"boolean","optional":true}],["result","exceptionDetails"],false);InspectorBackend.registerCommand("Debugger.setVariableValue",[{"name":"scopeNumber","type":"number","optional":false},{"name":"variableName","type":"string","optional":false},{"name":"newValue","type":"object","optional":false},{"name":"callFrameId","type":"string","optional":true},{"name":"functionObjectId","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Debugger.getStepInPositions",[{"name":"callFrameId","type":"string","optional":false}],["stepInPositions"],false);InspectorBackend.registerCommand("Debugger.getBacktrace",[],["callFrames","asyncStackTrace"],false);InspectorBackend.registerCommand("Debugger.skipStackFrames",[{"name":"script","type":"string","optional":true},{"name":"skipContentScripts","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("Debugger.setAsyncCallStackDepth",[{"name":"maxDepth","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Debugger.enablePromiseTracker",[{"name":"captureStacks","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("Debugger.disablePromiseTracker",[],[],false);InspectorBackend.registerCommand("Debugger.getPromiseById",[{"name":"promiseId","type":"number","optional":false},{"name":"objectGroup","type":"string","optional":true}],["promise"],false);InspectorBackend.registerCommand("Debugger.flushAsyncOperationEvents",[],[],false);InspectorBackend.registerCommand("Debugger.setAsyncOperationBreakpoint",[{"name":"operationId","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Debugger.removeAsyncOperationBreakpoint",[{"name":"operationId","type":"number","optional":false}],[],false);InspectorBackend.registerEnum("DOMDebugger.DOMBreakpointType",{SubtreeModified:"subtree-modified",AttributeModified:"attribute-modified",NodeRemoved:"node-removed"});InspectorBackend.registerCommand("DOMDebugger.setDOMBreakpoint",[{"name":"nodeId","type":"number","optional":false},{"name":"type","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOMDebugger.removeDOMBreakpoint",[{"name":"nodeId","type":"number","optional":false},{"name":"type","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOMDebugger.setEventListenerBreakpoint",[{"name":"eventName","type":"string","optional":false},{"name":"targetName","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("DOMDebugger.removeEventListenerBreakpoint",[{"name":"eventName","type":"string","optional":false},{"name":"targetName","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("DOMDebugger.setInstrumentationBreakpoint",[{"name":"eventName","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOMDebugger.removeInstrumentationBreakpoint",[{"name":"eventName","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOMDebugger.setXHRBreakpoint",[{"name":"url","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOMDebugger.removeXHRBreakpoint",[{"name":"url","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("DOMDebugger.getEventListeners",[{"name":"objectId","type":"string","optional":false}],["listeners"],false);InspectorBackend.registerEvent("Profiler.consoleProfileStarted",["id","location","title"]);InspectorBackend.registerEvent("Profiler.consoleProfileFinished",["id","location","profile","title"]);InspectorBackend.registerCommand("Profiler.enable",[],[],false);InspectorBackend.registerCommand("Profiler.disable",[],[],false);InspectorBackend.registerCommand("Profiler.setSamplingInterval",[{"name":"interval","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Profiler.start",[],[],false);InspectorBackend.registerCommand("Profiler.stop",[],["profile"],false);InspectorBackend.registerEvent("HeapProfiler.addHeapSnapshotChunk",["chunk"]);InspectorBackend.registerEvent("HeapProfiler.resetProfiles",[]);InspectorBackend.registerEvent("HeapProfiler.reportHeapSnapshotProgress",["done","total","finished"]);InspectorBackend.registerEvent("HeapProfiler.lastSeenObjectId",["lastSeenObjectId","timestamp"]);InspectorBackend.registerEvent("HeapProfiler.heapStatsUpdate",["statsUpdate"]);InspectorBackend.registerCommand("HeapProfiler.enable",[],[],false);InspectorBackend.registerCommand("HeapProfiler.disable",[],[],false);InspectorBackend.registerCommand("HeapProfiler.startTrackingHeapObjects",[{"name":"trackAllocations","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("HeapProfiler.stopTrackingHeapObjects",[{"name":"reportProgress","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("HeapProfiler.takeHeapSnapshot",[{"name":"reportProgress","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("HeapProfiler.collectGarbage",[],[],false);InspectorBackend.registerCommand("HeapProfiler.getObjectByHeapObjectId",[{"name":"objectId","type":"string","optional":false},{"name":"objectGroup","type":"string","optional":true}],["result"],false);InspectorBackend.registerCommand("HeapProfiler.addInspectedHeapObject",[{"name":"heapObjectId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("HeapProfiler.getHeapObjectId",[{"name":"objectId","type":"string","optional":false}],["heapSnapshotObjectId"],false);InspectorBackend.registerEvent("Worker.workerCreated",["workerId","url","inspectorConnected"]);InspectorBackend.registerEvent("Worker.workerTerminated",["workerId"]);InspectorBackend.registerEvent("Worker.dispatchMessageFromWorker",["workerId","message"]);InspectorBackend.registerCommand("Worker.enable",[],[],false);InspectorBackend.registerCommand("Worker.disable",[],[],false);InspectorBackend.registerCommand("Worker.sendMessageToWorker",[{"name":"workerId","type":"string","optional":false},{"name":"message","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Worker.connectToWorker",[{"name":"workerId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Worker.disconnectFromWorker",[{"name":"workerId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("Worker.setAutoconnectToWorkers",[{"name":"value","type":"boolean","optional":false}],[],false);InspectorBackend.registerEnum("ServiceWorker.ServiceWorkerVersionRunningStatus",{Stopped:"stopped",Starting:"starting",Running:"running",Stopping:"stopping"});InspectorBackend.registerEnum("ServiceWorker.ServiceWorkerVersionStatus",{New:"new",Installing:"installing",Installed:"installed",Activating:"activating",Activated:"activated",Redundant:"redundant"});InspectorBackend.registerEvent("ServiceWorker.workerCreated",["workerId","url","versionId"]);InspectorBackend.registerEvent("ServiceWorker.workerTerminated",["workerId"]);InspectorBackend.registerEvent("ServiceWorker.dispatchMessage",["workerId","message"]);InspectorBackend.registerEvent("ServiceWorker.workerRegistrationUpdated",["registrations"]);InspectorBackend.registerEvent("ServiceWorker.workerVersionUpdated",["versions"]);InspectorBackend.registerEvent("ServiceWorker.workerErrorReported",["errorMessage"]);InspectorBackend.registerEvent("ServiceWorker.debugOnStartUpdated",["debugOnStart"]);InspectorBackend.registerCommand("ServiceWorker.enable",[],[],false);InspectorBackend.registerCommand("ServiceWorker.disable",[],[],false);InspectorBackend.registerCommand("ServiceWorker.sendMessage",[{"name":"workerId","type":"string","optional":false},{"name":"message","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.stop",[{"name":"workerId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.unregister",[{"name":"scopeURL","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.updateRegistration",[{"name":"scopeURL","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.startWorker",[{"name":"scopeURL","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.stopWorker",[{"name":"versionId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.inspectWorker",[{"name":"versionId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.setDebugOnStart",[{"name":"debugOnStart","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.setForceUpdateOnPageLoad",[{"name":"registrationId","type":"string","optional":false},{"name":"forceUpdateOnPageLoad","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.deliverPushMessage",[{"name":"origin","type":"string","optional":false},{"name":"registrationId","type":"string","optional":false},{"name":"data","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ServiceWorker.getTargetInfo",[{"name":"targetId","type":"string","optional":false}],["targetInfo"],false);InspectorBackend.registerCommand("ServiceWorker.activateTarget",[{"name":"targetId","type":"string","optional":false}],[],false);InspectorBackend.registerEnum("Input.TouchPointState",{TouchPressed:"touchPressed",TouchReleased:"touchReleased",TouchMoved:"touchMoved",TouchStationary:"touchStationary",TouchCancelled:"touchCancelled"});InspectorBackend.registerEnum("Input.GestureSourceType",{Default:"default",Touch:"touch",Mouse:"mouse"});InspectorBackend.registerCommand("Input.dispatchKeyEvent",[{"name":"type","type":"string","optional":false},{"name":"modifiers","type":"number","optional":true},{"name":"timestamp","type":"number","optional":true},{"name":"text","type":"string","optional":true},{"name":"unmodifiedText","type":"string","optional":true},{"name":"key","type":"string","optional":true},{"name":"code","type":"string","optional":true},{"name":"key","type":"string","optional":true},{"name":"windowsVirtualKeyCode","type":"number","optional":true},{"name":"nativeVirtualKeyCode","type":"number","optional":true},{"name":"autoRepeat","type":"boolean","optional":true},{"name":"isKeypad","type":"boolean","optional":true},{"name":"isSystemKey","type":"boolean","optional":true}],[],false);InspectorBackend.registerCommand("Input.dispatchMouseEvent",[{"name":"type","type":"string","optional":false},{"name":"x","type":"number","optional":false},{"name":"y","type":"number","optional":false},{"name":"modifiers","type":"number","optional":true},{"name":"timestamp","type":"number","optional":true},{"name":"button","type":"string","optional":true},{"name":"clickCount","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Input.dispatchTouchEvent",[{"name":"type","type":"string","optional":false},{"name":"touchPoints","type":"object","optional":false},{"name":"modifiers","type":"number","optional":true},{"name":"timestamp","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Input.emulateTouchFromMouseEvent",[{"name":"type","type":"string","optional":false},{"name":"x","type":"number","optional":false},{"name":"y","type":"number","optional":false},{"name":"timestamp","type":"number","optional":false},{"name":"button","type":"string","optional":false},{"name":"deltaX","type":"number","optional":true},{"name":"deltaY","type":"number","optional":true},{"name":"modifiers","type":"number","optional":true},{"name":"clickCount","type":"number","optional":true}],[],false);InspectorBackend.registerCommand("Input.synthesizePinchGesture",[{"name":"x","type":"number","optional":false},{"name":"y","type":"number","optional":false},{"name":"scaleFactor","type":"number","optional":false},{"name":"relativeSpeed","type":"number","optional":true},{"name":"gestureSourceType","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Input.synthesizeScrollGesture",[{"name":"x","type":"number","optional":false},{"name":"y","type":"number","optional":false},{"name":"xDistance","type":"number","optional":true},{"name":"yDistance","type":"number","optional":true},{"name":"xOverscroll","type":"number","optional":true},{"name":"yOverscroll","type":"number","optional":true},{"name":"preventFling","type":"boolean","optional":true},{"name":"speed","type":"number","optional":true},{"name":"gestureSourceType","type":"string","optional":true},{"name":"repeatCount","type":"number","optional":true},{"name":"repeatDelayMs","type":"number","optional":true},{"name":"interactionMarkerName","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Input.synthesizeTapGesture",[{"name":"x","type":"number","optional":false},{"name":"y","type":"number","optional":false},{"name":"duration","type":"number","optional":true},{"name":"tapCount","type":"number","optional":true},{"name":"gestureSourceType","type":"string","optional":true}],[],false);InspectorBackend.registerEnum("LayerTree.ScrollRectType",{RepaintsOnScroll:"RepaintsOnScroll",TouchEventHandler:"TouchEventHandler",WheelEventHandler:"WheelEventHandler"});InspectorBackend.registerEvent("LayerTree.layerTreeDidChange",["layers"]);InspectorBackend.registerEvent("LayerTree.layerPainted",["layerId","clip"]);InspectorBackend.registerCommand("LayerTree.enable",[],[],false);InspectorBackend.registerCommand("LayerTree.disable",[],[],false);InspectorBackend.registerCommand("LayerTree.compositingReasons",[{"name":"layerId","type":"string","optional":false}],["compositingReasons"],false);InspectorBackend.registerCommand("LayerTree.makeSnapshot",[{"name":"layerId","type":"string","optional":false}],["snapshotId"],false);InspectorBackend.registerCommand("LayerTree.loadSnapshot",[{"name":"tiles","type":"object","optional":false}],["snapshotId"],false);InspectorBackend.registerCommand("LayerTree.releaseSnapshot",[{"name":"snapshotId","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("LayerTree.profileSnapshot",[{"name":"snapshotId","type":"string","optional":false},{"name":"minRepeatCount","type":"number","optional":true},{"name":"minDuration","type":"number","optional":true},{"name":"clipRect","type":"object","optional":true}],["timings"],false);InspectorBackend.registerCommand("LayerTree.replaySnapshot",[{"name":"snapshotId","type":"string","optional":false},{"name":"fromStep","type":"number","optional":true},{"name":"toStep","type":"number","optional":true},{"name":"scale","type":"number","optional":true}],["dataURL"],false);InspectorBackend.registerCommand("LayerTree.snapshotCommandLog",[{"name":"snapshotId","type":"string","optional":false}],["commandLog"],false);InspectorBackend.registerCommand("DeviceOrientation.setDeviceOrientationOverride",[{"name":"alpha","type":"number","optional":false},{"name":"beta","type":"number","optional":false},{"name":"gamma","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("DeviceOrientation.clearDeviceOrientationOverride",[],[],false);InspectorBackend.registerEnum("ScreenOrientation.OrientationType",{PortraitPrimary:"portraitPrimary",PortraitSecondary:"portraitSecondary",LandscapePrimary:"landscapePrimary",LandscapeSecondary:"landscapeSecondary"});InspectorBackend.registerCommand("ScreenOrientation.setScreenOrientationOverride",[{"name":"angle","type":"number","optional":false},{"name":"type","type":"string","optional":false}],[],false);InspectorBackend.registerCommand("ScreenOrientation.clearScreenOrientationOverride",[],[],false);InspectorBackend.registerEvent("Tracing.dataCollected",["value"]);InspectorBackend.registerEvent("Tracing.tracingComplete",["stream"]);InspectorBackend.registerEvent("Tracing.bufferUsage",["percentFull","eventCount","value"]);InspectorBackend.registerCommand("Tracing.start",[{"name":"categories","type":"string","optional":true},{"name":"options","type":"string","optional":true},{"name":"bufferUsageReportingInterval","type":"number","optional":true},{"name":"transferMode","type":"string","optional":true}],[],false);InspectorBackend.registerCommand("Tracing.end",[],[],false);InspectorBackend.registerCommand("Tracing.getCategories",[],["categories"],false);InspectorBackend.registerCommand("Tracing.requestMemoryDump",[],["dumpGuid","success"],false);InspectorBackend.registerEnum("Animation.AnimationType",{CSSTransition:"CSSTransition",CSSAnimation:"CSSAnimation",WebAnimation:"WebAnimation"});InspectorBackend.registerEvent("Animation.animationCreated",["id"]);InspectorBackend.registerEvent("Animation.animationStarted",["animation"]);InspectorBackend.registerEvent("Animation.animationCanceled",["id"]);InspectorBackend.registerCommand("Animation.enable",[],[],false);InspectorBackend.registerCommand("Animation.disable",[],[],false);InspectorBackend.registerCommand("Animation.getPlaybackRate",[],["playbackRate"],false);InspectorBackend.registerCommand("Animation.setPlaybackRate",[{"name":"playbackRate","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Animation.getCurrentTime",[{"name":"id","type":"string","optional":false}],["currentTime"],false);InspectorBackend.registerCommand("Animation.setPaused",[{"name":"animations","type":"object","optional":false},{"name":"paused","type":"boolean","optional":false}],[],false);InspectorBackend.registerCommand("Animation.setTiming",[{"name":"animationId","type":"string","optional":false},{"name":"duration","type":"number","optional":false},{"name":"delay","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Animation.seekAnimations",[{"name":"animations","type":"object","optional":false},{"name":"currentTime","type":"number","optional":false}],[],false);InspectorBackend.registerCommand("Animation.releaseAnimations",[{"name":"animations","type":"object","optional":false}],[],false);InspectorBackend.registerCommand("Animation.resolveAnimation",[{"name":"animationId","type":"string","optional":false}],["remoteObject"],false);InspectorBackend.registerEnum("Accessibility.AXValueType",{Boolean:"boolean",Tristate:"tristate",BooleanOrUndefined:"booleanOrUndefined",Idref:"idref",IdrefList:"idrefList",Integer:"integer",Node:"node",NodeList:"nodeList",Number:"number",String:"string",ComputedString:"computedString",Token:"token",TokenList:"tokenList",DomRelation:"domRelation",Role:"role",InternalRole:"internalRole",ValueUndefined:"valueUndefined"});InspectorBackend.registerEnum("Accessibility.AXValueSourceType",{Attribute:"attribute",Implicit:"implicit",Style:"style",Contents:"contents",Placeholder:"placeholder",RelatedElement:"relatedElement"});InspectorBackend.registerEnum("Accessibility.AXValueNativeSourceType",{Figcaption:"figcaption",Label:"label",Labelfor:"labelfor",Labelwrapped:"labelwrapped",Legend:"legend",Tablecaption:"tablecaption",Title:"title",Other:"other"});InspectorBackend.registerEnum("Accessibility.AXGlobalStates",{Disabled:"disabled",Hidden:"hidden",HiddenRoot:"hiddenRoot",Invalid:"invalid"});InspectorBackend.registerEnum("Accessibility.AXLiveRegionAttributes",{Live:"live",Atomic:"atomic",Relevant:"relevant",Busy:"busy",Root:"root"});InspectorBackend.registerEnum("Accessibility.AXWidgetAttributes",{Autocomplete:"autocomplete",Haspopup:"haspopup",Level:"level",Multiselectable:"multiselectable",Orientation:"orientation",Multiline:"multiline",Readonly:"readonly",Required:"required",Valuemin:"valuemin",Valuemax:"valuemax",Valuetext:"valuetext"});InspectorBackend.registerEnum("Accessibility.AXWidgetStates",{Checked:"checked",Expanded:"expanded",Pressed:"pressed",Selected:"selected"});InspectorBackend.registerEnum("Accessibility.AXRelationshipAttributes",{Activedescendant:"activedescendant",Flowto:"flowto",Controls:"controls",Describedby:"describedby",Labelledby:"labelledby",Owns:"owns"});InspectorBackend.registerCommand("Accessibility.getAXNode",[{"name":"nodeId","type":"number","optional":false}],["accessibilityNode"],false);;WebInspector.InspectorBackendHostedMode={};WebInspector.InspectorBackendHostedMode.loadFromJSONIfNeeded=function(jsonUrl)
 {if(InspectorBackend.isInitialized())
 return;var xhr=new XMLHttpRequest();xhr.open("GET",jsonUrl,false);xhr.send(null);var schema=JSON.parse(xhr.responseText);var code=WebInspector.InspectorBackendHostedMode.generateCommands(schema);eval(code);}
 WebInspector.InspectorBackendHostedMode.generateCommands=function(schema)
@@ -8829,11 +8829,11 @@
 panelIndex=event.keyCode-0x61;if(panelIndex!==-1){var panelName=this._tabbedPane.allTabs()[panelIndex];if(panelName){if(!WebInspector.Dialog.hasInstance()&&!this._currentPanelLocked)
 this.showPanel(panelName);event.consume(true);}
 return;}}
-if(!WebInspector.isWin()||(!this._openBracketIdentifiers[event.keyIdentifier]&&!this._closeBracketIdentifiers[event.keyIdentifier])){this._keyDownInternal(event);return;}
+if(!WebInspector.isWin()||(!this._openBracketIdentifiers[event.key]&&!this._closeBracketIdentifiers[event.key])){this._keyDownInternal(event);return;}
 this._keyDownTimer=setTimeout(this._keyDownInternal.bind(this,event),0);},_keyDownInternal:function(event)
 {if(this._currentPanelLocked)
-return;var direction=0;if(this._openBracketIdentifiers[event.keyIdentifier])
-direction=-1;if(this._closeBracketIdentifiers[event.keyIdentifier])
+return;var direction=0;if(this._openBracketIdentifiers[event.key])
+direction=-1;if(this._closeBracketIdentifiers[event.key])
 direction=1;if(!direction)
 return;if(!event.shiftKey&&!event.altKey){if(!WebInspector.Dialog.hasInstance())
 this._changePanelInDirection(direction);event.consume(true);return;}
@@ -9052,7 +9052,7 @@
 {var userInput=this._prompt.text();if(userInput===originalContent){this._editingCancelled();return;}
 this._editingEnded();this._applyExpression(userInput);},_promptKeyDown:function(originalContent,event)
 {if(isEnterKey(event)){event.consume(true);this._editingCommitted(originalContent);return;}
-if(event.keyIdentifier==="U+001B"){event.consume();this._editingCancelled();return;}},_applyExpression:function(expression)
+if(event.key==="U+001B"){event.consume();this._editingCancelled();return;}},_applyExpression:function(expression)
 {var property=WebInspector.RemoteObject.toCallArgument(this.property.symbol||this.property.name);expression=expression.trim();if(expression)
 this.property.parentObject.setPropertyValue(property,expression,callback.bind(this));else
 this.property.parentObject.deleteProperty(property,callback.bind(this));function callback(error)
@@ -9577,8 +9577,8 @@
 extensionServer.sendRequest({command:commands.GetResourceContent,url:this._url},callback&&callbackWrapper);},setContent:function(content,commit,callback)
 {extensionServer.sendRequest({command:commands.SetResourceContent,url:this._url,content:content,commit:commit},callback);}}
 var keyboardEventRequestQueue=[];var forwardTimer=null;function forwardKeyboardEvent(event)
-{const Esc="U+001B";if(!event.ctrlKey&&!event.altKey&&!event.metaKey&&!/^F\d+$/.test(event.keyIdentifier)&&event.keyIdentifier!==Esc)
-return;var requestPayload={eventType:event.type,ctrlKey:event.ctrlKey,altKey:event.altKey,metaKey:event.metaKey,keyIdentifier:event.keyIdentifier,location:event.location,keyCode:event.keyCode};keyboardEventRequestQueue.push(requestPayload);if(!forwardTimer)
+{const Esc="U+001B";if(!event.ctrlKey&&!event.altKey&&!event.metaKey&&!/^F\d+$/.test(event.key)&&event.key!==Esc)
+return;var requestPayload={eventType:event.type,ctrlKey:event.ctrlKey,altKey:event.altKey,metaKey:event.metaKey,key:event.key,location:event.location,keyCode:event.keyCode};keyboardEventRequestQueue.push(requestPayload);if(!forwardTimer)
 forwardTimer=setTimeout(forwardEventQueue,0);}
 function forwardEventQueue()
 {forwardTimer=null;var request={command:commands.ForwardKeyboardEvent,entries:keyboardEventRequestQueue};extensionServer.sendRequest(request);keyboardEventRequestQueue=[];}
@@ -9735,10 +9735,10 @@
 {var auditRun=(this._clientObjects[message.resultId]);if(!auditRun)
 return this._status.E_NOTFOUND(message.resultId);auditRun.done();},_onForwardKeyboardEvent:function(message)
 {const Esc="U+001B";message.entries.forEach(handleEventEntry);function handleEventEntry(entry)
-{if(!entry.ctrlKey&&!entry.altKey&&!entry.metaKey&&!/^F\d+$/.test(entry.keyIdentifier)&&entry.keyIdentifier!==Esc)
-return;var event=new window.KeyboardEvent(entry.eventType,{keyIdentifier:entry.keyIdentifier,location:entry.location,ctrlKey:entry.ctrlKey,altKey:entry.altKey,shiftKey:entry.shiftKey,metaKey:entry.metaKey});event.__keyCode=keyCodeForEntry(entry);document.dispatchEvent(event);}
+{if(!entry.ctrlKey&&!entry.altKey&&!entry.metaKey&&!/^F\d+$/.test(entry.key)&&entry.key!==Esc)
+return;var event=new window.KeyboardEvent(entry.eventType,{key:entry.key,location:entry.location,ctrlKey:entry.ctrlKey,altKey:entry.altKey,shiftKey:entry.shiftKey,metaKey:entry.metaKey});event.__keyCode=keyCodeForEntry(entry);document.dispatchEvent(event);}
 function keyCodeForEntry(entry)
-{var keyCode=entry.keyCode;if(!keyCode){var match=entry.keyIdentifier.match(/^U\+([\dA-Fa-f]+)$/);if(match)
+{var keyCode=entry.keyCode;if(!keyCode){var match=entry.key.match(/^U\+([\dA-Fa-f]+)$/);if(match)
 keyCode=parseInt(match[1],16);}
 return keyCode||0;}},_dispatchCallback:function(requestId,port,result)
 {if(requestId)
@@ -10806,8 +10806,8 @@
 {if(WebInspector.targetManager.targets().length>=n)
 callback.call(null);else
 this.addSniffer(WebInspector.TargetManager.prototype,"addTarget",checkTargets.bind(this));}}
-TestSuite.createKeyEvent=function(keyIdentifier)
-{var evt=document.createEvent("KeyboardEvent");evt.initKeyboardEvent("keydown",true,true,null,keyIdentifier,"");return evt;};return new TestSuite();}
+TestSuite.createKeyEvent=function(key)
+{var evt=document.createEvent("KeyboardEvent");evt.initKeyboardEvent("keydown",true,true,null,key,"");return evt;};return new TestSuite();}
 if(window.uiTests){WebInspector.notifications.addEventListener(WebInspector.NotificationService.Events.InspectorAgentEnabledForTests,window.uiTests.testSuiteReady.bind(null,createTestSuite));};WebInspector.OverlayController=function()
 {WebInspector.moduleSetting("disablePausedStateOverlay").addChangeListener(this._updateOverlayMessage,this);WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel,WebInspector.DebuggerModel.Events.DebuggerPaused,this._updateOverlayMessage,this);WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel,WebInspector.DebuggerModel.Events.DebuggerResumed,this._updateOverlayMessage,this);WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel,WebInspector.DebuggerModel.Events.GlobalObjectCleared,this._updateOverlayMessage,this);}
 WebInspector.OverlayController.prototype={_updateOverlayMessage:function(event)
diff --git a/src/cobalt/debug/content/devtools/network_module.js b/src/cobalt/debug/content/devtools/network_module.js
index 45c3ed8..563bdd6 100644
--- a/src/cobalt/debug/content/devtools/network_module.js
+++ b/src/cobalt/debug/content/devtools/network_module.js
@@ -11,7 +11,7 @@
 onAccept(text);else
 this._update();}
 function keydown(event)
-{if(isEnterKey(event)){event.consume();commit.call(this);}else if(event.keyCode===WebInspector.KeyboardShortcut.Keys.Esc.code||event.keyIdentifier==="U+001B"){event.consume();finish.call(this);this._update();}}},_addBlockedURL:function(url)
+{if(isEnterKey(event)){event.consume();commit.call(this);}else if(event.keyCode===WebInspector.KeyboardShortcut.Keys.Esc.code||event.key==="U+001B"){event.consume();finish.call(this);this._update();}}},_addBlockedURL:function(url)
 {var blocked=this._blockedURLsSetting.get();blocked.push(url);this._blockedURLsSetting.set(blocked);},_removeBlockedURL:function(index)
 {var blocked=this._blockedURLsSetting.get();blocked.splice(index,1);this._blockedURLsSetting.set(blocked);},_changeBlockedURL:function(index,url)
 {var blocked=this._blockedURLsSetting.get();blocked.splice(index,1,url);this._blockedURLsSetting.set(blocked);},_removeAll:function()
@@ -678,7 +678,7 @@
 WebInspector.RequestHeadersView.prototype={_updateFilter:function()
 {var text=this._filterInput.value;this._requestHeaderFilterSetting.set(text);this._filterRegex=text?new RegExp(text.escapeForRegExp(),"i"):null;this._updateHeaders();},_onFilterKeyDown:function(event)
 {var text=this._filterInput.value;if(!text)
-return;if(event.keyCode===WebInspector.KeyboardShortcut.Keys.Esc.code||event.keyIdentifier==="U+001B"){event.consume(true);this._filterInput.value="";this._updateFilter();}},_updateHeaders:function()
+return;if(event.keyCode===WebInspector.KeyboardShortcut.Keys.Esc.code||event.key==="U+001B"){event.consume(true);this._filterInput.value="";this._updateFilter();}},_updateHeaders:function()
 {this._refreshRequestHeaders();this._refreshResponseHeaders();},wasShown:function()
 {this._request.addEventListener(WebInspector.NetworkRequest.Events.RemoteAddressChanged,this._refreshRemoteAddress,this);this._request.addEventListener(WebInspector.NetworkRequest.Events.RequestHeadersChanged,this._refreshRequestHeaders,this);this._request.addEventListener(WebInspector.NetworkRequest.Events.ResponseHeadersChanged,this._refreshResponseHeaders,this);this._request.addEventListener(WebInspector.NetworkRequest.Events.FinishedLoading,this._refreshHTTPInformation,this);this._refreshURL();this._refreshQueryString();this._updateHeaders();this._refreshHTTPInformation();this._refreshRemoteAddress();},willHide:function()
 {this._request.removeEventListener(WebInspector.NetworkRequest.Events.RemoteAddressChanged,this._refreshRemoteAddress,this);this._request.removeEventListener(WebInspector.NetworkRequest.Events.RequestHeadersChanged,this._refreshRequestHeaders,this);this._request.removeEventListener(WebInspector.NetworkRequest.Events.ResponseHeadersChanged,this._refreshResponseHeaders,this);this._request.removeEventListener(WebInspector.NetworkRequest.Events.FinishedLoading,this._refreshHTTPInformation,this);},_formatHeader:function(name,value)
diff --git a/src/cobalt/debug/content/devtools/profiler_module.js b/src/cobalt/debug/content/devtools/profiler_module.js
index 912654d..c234603 100644
--- a/src/cobalt/debug/content/devtools/profiler_module.js
+++ b/src/cobalt/debug/content/devtools/profiler_module.js
@@ -62,8 +62,8 @@
 {WebInspector.PanelWithSidebar.call(this,"profiles");this.registerRequiredCSS("ui/panelEnablerView.css");this.registerRequiredCSS("profiler/heapProfiler.css");this.registerRequiredCSS("profiler/profilesPanel.css");this.registerRequiredCSS("components/objectValue.css");var mainContainer=new WebInspector.VBox();this.splitWidget().setMainWidget(mainContainer);this.profilesItemTreeElement=new WebInspector.ProfilesSidebarTreeElement(this);this._sidebarTree=new TreeOutline();this._sidebarTree.element.classList.add("sidebar-tree");this.panelSidebarElement().appendChild(this._sidebarTree.element);this.setDefaultFocusedElement(this._sidebarTree.element);this._sidebarTree.appendChild(this.profilesItemTreeElement);this.profileViews=createElement("div");this.profileViews.id="profile-views";this.profileViews.classList.add("vbox");mainContainer.element.appendChild(this.profileViews);this._toolbarElement=createElementWithClass("div","profiles-toolbar");mainContainer.element.insertBefore(this._toolbarElement,mainContainer.element.firstChild);this.panelSidebarElement().classList.add("profiles-sidebar-tree-box");var toolbarContainerLeft=createElementWithClass("div","profiles-toolbar");this.panelSidebarElement().insertBefore(toolbarContainerLeft,this.panelSidebarElement().firstChild);var toolbar=new WebInspector.Toolbar("",toolbarContainerLeft);this._toggleRecordAction=WebInspector.actionRegistry.action("profiler.toggle-recording");toolbar.appendToolbarItem(WebInspector.Toolbar.createActionButton(this._toggleRecordAction));this.clearResultsButton=new WebInspector.ToolbarButton(WebInspector.UIString("Clear all profiles"),"clear-toolbar-item");this.clearResultsButton.addEventListener("click",this._reset,this);toolbar.appendToolbarItem(this.clearResultsButton);this._profileTypeToolbar=new WebInspector.Toolbar("",this._toolbarElement);this._profileViewToolbar=new WebInspector.Toolbar("",this._toolbarElement);this._profileGroups={};this._launcherView=new WebInspector.MultiProfileLauncherView(this);this._launcherView.addEventListener(WebInspector.MultiProfileLauncherView.EventTypes.ProfileTypeSelected,this._onProfileTypeSelected,this);this._profileToView=[];this._typeIdToSidebarSection={};var types=WebInspector.ProfileTypeRegistry.instance.profileTypes();for(var i=0;i<types.length;i++)
 this._registerProfileType(types[i]);this._launcherView.restoreSelectedProfileType();this.profilesItemTreeElement.select();this._showLauncherView();this._createFileSelectorElement();this.element.addEventListener("contextmenu",this._handleContextMenuEvent.bind(this),true);this.contentElement.addEventListener("keydown",this._onKeyDown.bind(this),false);WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Events.SuspendStateChanged,this._onSuspendStateChanged,this);}
 WebInspector.ProfilesPanel.prototype={_onKeyDown:function(event)
-{var handled=false;if(event.keyIdentifier==="Down"&&!event.altKey)
-handled=this._sidebarTree.selectNext();else if(event.keyIdentifier==="Up"&&!event.altKey)
+{var handled=false;if(event.key==="Down"&&!event.altKey)
+handled=this._sidebarTree.selectNext();else if(event.key==="Up"&&!event.altKey)
 handled=this._sidebarTree.selectPrevious();if(handled)
 event.consume(true);},searchableView:function()
 {return this.visibleView&&this.visibleView.searchableView?this.visibleView.searchableView():null;},_createFileSelectorElement:function()
diff --git a/src/cobalt/debug/content/devtools/sources_module.js b/src/cobalt/debug/content/devtools/sources_module.js
index 427b837..dfe1b58 100644
--- a/src/cobalt/debug/content/devtools/sources_module.js
+++ b/src/cobalt/debug/content/devtools/sources_module.js
@@ -156,7 +156,7 @@
 {if(!this._statusMessageElement)
 this._statusMessageElement=this.element.createChild("div","callstack-info status");if(typeof status==="string"){this._statusMessageElement.textContent=status;}else{this._statusMessageElement.removeChildren();this._statusMessageElement.appendChild(status);}},_keyDown:function(event)
 {if(event.altKey||event.shiftKey||event.metaKey||event.ctrlKey)
-return;if(event.keyIdentifier==="Up"&&this._selectPreviousCallFrameOnStack()||event.keyIdentifier==="Down"&&this._selectNextCallFrameOnStack())
+return;if(event.key==="Up"&&this._selectPreviousCallFrameOnStack()||event.key==="Down"&&this._selectNextCallFrameOnStack())
 event.consume(true);},__proto__:WebInspector.SidebarPane.prototype}
 WebInspector.CallStackSidebarPane.CallFrame=function(callFrame,asyncCallFrame)
 {WebInspector.UIList.Item.call(this,WebInspector.beautifyFunctionName(callFrame.functionName),"");WebInspector.debuggerWorkspaceBinding.createCallFrameLiveLocation(callFrame,this._update.bind(this));this._callFrame=callFrame;this._asyncCallFrame=asyncCallFrame;}
@@ -549,7 +549,7 @@
 this.textEditor.removeHighlight(this._popoverAnchorBox._highlightDescriptor);delete this._popoverAnchorBox;},_addBreakpointDecoration:function(lineNumber,columnNumber,condition,enabled,mutedWhileEditing)
 {var breakpoint={condition:condition,enabled:enabled,columnNumber:columnNumber};this.textEditor.setAttribute(lineNumber,"breakpoint",breakpoint);var disabled=!enabled||mutedWhileEditing;this.textEditor.addBreakpoint(lineNumber,disabled,!!condition);},_removeBreakpointDecoration:function(lineNumber)
 {this.textEditor.removeAttribute(lineNumber,"breakpoint");this.textEditor.removeBreakpoint(lineNumber);},_onKeyDown:function(event)
-{if(event.keyIdentifier==="U+001B"){if(this._popoverHelper.isPopoverVisible()){this._popoverHelper.hidePopover();event.consume();}}},_editBreakpointCondition:function(lineNumber,breakpoint)
+{if(event.key==="U+001B"){if(this._popoverHelper.isPopoverVisible()){this._popoverHelper.hidePopover();event.consume();}}},_editBreakpointCondition:function(lineNumber,breakpoint)
 {this._conditionElement=this._createConditionElement(lineNumber);this.textEditor.addDecoration(lineNumber,this._conditionElement);function finishEditing(committed,element,newText)
 {this.textEditor.removeDecoration(lineNumber,this._conditionElement);delete this._conditionEditorElement;delete this._conditionElement;if(!committed)
 return;if(breakpoint)
diff --git a/src/cobalt/debug/content/devtools/toolbox.js b/src/cobalt/debug/content/devtools/toolbox.js
index 4a470cb..33deec8 100644
--- a/src/cobalt/debug/content/devtools/toolbox.js
+++ b/src/cobalt/debug/content/devtools/toolbox.js
@@ -683,7 +683,7 @@
 {var node=this.elementFromPoint(x,y);while(node&&node.shadowRoot)
 node=node.shadowRoot.elementFromPoint(x,y);return node;}
 function isEnterKey(event)
-{return event.keyCode!==229&&event.keyIdentifier==="Enter";}
+{return event.keyCode!==229&&event.key==="Enter";}
 function isEscKey(event)
 {return event.keyCode===27;}
 function consumeEvent(e)
diff --git a/src/cobalt/debug/content/devtools/ui_lazy_module.js b/src/cobalt/debug/content/devtools/ui_lazy_module.js
index a980922..9c76e80 100644
--- a/src/cobalt/debug/content/devtools/ui_lazy_module.js
+++ b/src/cobalt/debug/content/devtools/ui_lazy_module.js
@@ -111,12 +111,12 @@
 this.creationNode.makeNormal();var emptyData={};for(var column in this._columns)
 emptyData[column]=null;this.creationNode=new WebInspector.CreationDataGridNode(emptyData,hasChildren);this.rootNode().appendChild(this.creationNode);},_keyDown:function(event)
 {if(!this.selectedNode||event.shiftKey||event.metaKey||event.ctrlKey||this._editing)
-return;var handled=false;var nextSelectedNode;if(event.keyIdentifier==="Up"&&!event.altKey){nextSelectedNode=this.selectedNode.traversePreviousNode(true);while(nextSelectedNode&&!nextSelectedNode.selectable)
-nextSelectedNode=nextSelectedNode.traversePreviousNode(true);handled=nextSelectedNode?true:false;}else if(event.keyIdentifier==="Down"&&!event.altKey){nextSelectedNode=this.selectedNode.traverseNextNode(true);while(nextSelectedNode&&!nextSelectedNode.selectable)
-nextSelectedNode=nextSelectedNode.traverseNextNode(true);handled=nextSelectedNode?true:false;}else if(event.keyIdentifier==="Left"){if(this.selectedNode.expanded){if(event.altKey)
+return;var handled=false;var nextSelectedNode;if(event.key==="Up"&&!event.altKey){nextSelectedNode=this.selectedNode.traversePreviousNode(true);while(nextSelectedNode&&!nextSelectedNode.selectable)
+nextSelectedNode=nextSelectedNode.traversePreviousNode(true);handled=nextSelectedNode?true:false;}else if(event.key==="Down"&&!event.altKey){nextSelectedNode=this.selectedNode.traverseNextNode(true);while(nextSelectedNode&&!nextSelectedNode.selectable)
+nextSelectedNode=nextSelectedNode.traverseNextNode(true);handled=nextSelectedNode?true:false;}else if(event.key==="Left"){if(this.selectedNode.expanded){if(event.altKey)
 this.selectedNode.collapseRecursively();else
 this.selectedNode.collapse();handled=true;}else if(this.selectedNode.parent&&!this.selectedNode.parent._isRoot){handled=true;if(this.selectedNode.parent.selectable){nextSelectedNode=this.selectedNode.parent;handled=nextSelectedNode?true:false;}else if(this.selectedNode.parent)
-this.selectedNode.parent.collapse();}}else if(event.keyIdentifier==="Right"){if(!this.selectedNode.revealed){this.selectedNode.reveal();handled=true;}else if(this.selectedNode.hasChildren){handled=true;if(this.selectedNode.expanded){nextSelectedNode=this.selectedNode.children[0];handled=nextSelectedNode?true:false;}else{if(event.altKey)
+this.selectedNode.parent.collapse();}}else if(event.key==="Right"){if(!this.selectedNode.revealed){this.selectedNode.reveal();handled=true;}else if(this.selectedNode.hasChildren){handled=true;if(this.selectedNode.expanded){nextSelectedNode=this.selectedNode.children[0];handled=nextSelectedNode?true:false;}else{if(event.altKey)
 this.selectedNode.expandRecursively();else
 this.selectedNode.expand();}}}else if(event.keyCode===8||event.keyCode===46){if(this._deleteCallback){handled=true;this._deleteCallback(this.selectedNode);}}else if(isEnterKey(event)){if(this._editCallback){handled=true;this._startEditing(this.selectedNode._element.children[this._nextEditableColumn(-1)]);}}
 if(nextSelectedNode){nextSelectedNode.reveal();nextSelectedNode.select();}
diff --git a/src/cobalt/debug/debug_script_runner.cc b/src/cobalt/debug/debug_script_runner.cc
index 36a44ca..833d5ca 100644
--- a/src/cobalt/debug/debug_script_runner.cc
+++ b/src/cobalt/debug/debug_script_runner.cc
@@ -82,8 +82,8 @@
       script::SourceCode::CreateSourceCode(js_code, GetInlineSourceLocation());
 
   ForceEnableEval();
-  bool succeeded = global_environment_->EvaluateScript(source_code, result,
-                                                       false /*mute_errors*/);
+  bool succeeded = global_environment_->EvaluateScript(
+      source_code, false /*mute_errors*/, result);
   SetEvalAllowedFromCsp();
   return succeeded;
 }
diff --git a/src/cobalt/dom/csp_delegate.cc b/src/cobalt/dom/csp_delegate.cc
index 0bcf6f0..b9afec6 100644
--- a/src/cobalt/dom/csp_delegate.cc
+++ b/src/cobalt/dom/csp_delegate.cc
@@ -25,9 +25,8 @@
 
 CspDelegateSecure::CspDelegateSecure(
     scoped_ptr<CspViolationReporter> violation_reporter, const GURL& url,
-    const std::string& location_policy, csp::CSPHeaderPolicy require_csp,
+    csp::CSPHeaderPolicy require_csp,
     const base::Closure& policy_changed_callback) {
-  location_policy_ = location_policy;
   require_csp_ = require_csp;
   was_header_received_ = false;
   policy_changed_callback_ = policy_changed_callback;
@@ -39,7 +38,6 @@
                                     base::Unretained(reporter_.get()));
   }
   csp_.reset(new csp::ContentSecurityPolicy(url, violation_callback));
-  SetLocationPolicy(location_policy_);
 }
 
 CspDelegateSecure::~CspDelegateSecure() {}
@@ -177,18 +175,5 @@
   }
 }
 
-void CspDelegateSecure::SetLocationPolicy(const std::string& policy) {
-  if (!policy.length()) {
-    return;
-  }
-
-  if (policy.find(csp::ContentSecurityPolicy::kLocationSrc) ==
-      std::string::npos) {
-    LOG(FATAL) << csp::ContentSecurityPolicy::kLocationSrc << " not found in "
-               << policy;
-  }
-  csp_->SetNavigationPolicy(policy);
-}
-
 }  // namespace dom
 }  // namespace cobalt
diff --git a/src/cobalt/dom/csp_delegate.h b/src/cobalt/dom/csp_delegate.h
index 17a797c..af05789 100644
--- a/src/cobalt/dom/csp_delegate.h
+++ b/src/cobalt/dom/csp_delegate.h
@@ -104,8 +104,7 @@
 class CspDelegateSecure : public CspDelegate {
  public:
   CspDelegateSecure(scoped_ptr<CspViolationReporter> violation_reporter,
-                    const GURL& url, const std::string& location_policy,
-                    csp::CSPHeaderPolicy require_csp,
+                    const GURL& url, csp::CSPHeaderPolicy require_csp,
                     const base::Closure& policy_changed_callback);
   ~CspDelegateSecure();
 
@@ -142,9 +141,6 @@
 
   scoped_ptr<csp::ContentSecurityPolicy> csp_;
 
-  // Hardcoded policy to restrict navigation.
-  std::string location_policy_;
-
   // Helper class to send violation events to any reporting endpoints.
   scoped_ptr<CspViolationReporter> reporter_;
 
diff --git a/src/cobalt/dom/csp_delegate_factory.cc b/src/cobalt/dom/csp_delegate_factory.cc
index e20c061..83c7f19 100644
--- a/src/cobalt/dom/csp_delegate_factory.cc
+++ b/src/cobalt/dom/csp_delegate_factory.cc
@@ -45,8 +45,7 @@
 
 CspDelegate* CreateInsecureDelegate(
     scoped_ptr<CspViolationReporter> /*violation_reporter*/,
-    const GURL& /*url*/, const std::string& /*location_policy*/,
-    csp::CSPHeaderPolicy /*requre_csp*/,
+    const GURL& /*url*/, csp::CSPHeaderPolicy /*requre_csp*/,
     const base::Closure& /*policy_changed_callback*/,
     int insecure_allowed_token) {
   if (InsecureAllowed(insecure_allowed_token)) {
@@ -59,11 +58,11 @@
 
 CspDelegate* CreateSecureDelegate(
     scoped_ptr<CspViolationReporter> violation_reporter, const GURL& url,
-    const std::string& location_policy, csp::CSPHeaderPolicy require_csp,
+    csp::CSPHeaderPolicy require_csp,
     const base::Closure& policy_changed_callback,
     int /*insecure_allowed_token*/) {
-  return new CspDelegateSecure(violation_reporter.Pass(), url, location_policy,
-                               require_csp, policy_changed_callback);
+  return new CspDelegateSecure(violation_reporter.Pass(), url, require_csp,
+                               policy_changed_callback);
 }
 }  // namespace
 
@@ -87,11 +86,11 @@
 scoped_ptr<CspDelegate> CspDelegateFactory::Create(
     CspEnforcementType type,
     scoped_ptr<CspViolationReporter> violation_reporter, const GURL& url,
-    const std::string& location_policy, csp::CSPHeaderPolicy require_csp,
+    csp::CSPHeaderPolicy require_csp,
     const base::Closure& policy_changed_callback, int insecure_allowed_token) {
-  scoped_ptr<CspDelegate> delegate(method_[type](
-      violation_reporter.Pass(), url, location_policy, require_csp,
-      policy_changed_callback, insecure_allowed_token));
+  scoped_ptr<CspDelegate> delegate(
+      method_[type](violation_reporter.Pass(), url, require_csp,
+                    policy_changed_callback, insecure_allowed_token));
   return delegate.Pass();
 }
 
diff --git a/src/cobalt/dom/csp_delegate_factory.h b/src/cobalt/dom/csp_delegate_factory.h
index c732d37..c3d8953 100644
--- a/src/cobalt/dom/csp_delegate_factory.h
+++ b/src/cobalt/dom/csp_delegate_factory.h
@@ -44,13 +44,14 @@
   scoped_ptr<CspDelegate> Create(
       CspEnforcementType type,
       scoped_ptr<CspViolationReporter> violation_reporter, const GURL& url,
-      const std::string& location_policy, csp::CSPHeaderPolicy require_csp,
+      csp::CSPHeaderPolicy require_csp,
       const base::Closure& policy_changed_callback,
       int insecure_allowed_token = 0);
 
   typedef CspDelegate* (*CspDelegateCreator)(
-      scoped_ptr<CspViolationReporter> violation_reporter, const GURL&,
-      const std::string&, csp::CSPHeaderPolicy, const base::Closure&, int);
+      scoped_ptr<CspViolationReporter> violation_reporter, const GURL& url,
+      csp::CSPHeaderPolicy require_csp,
+      const base::Closure& policy_chagned_callback, int insecure_allowed_token);
 
 #if !defined(COBALT_FORCE_CSP)
   // Allow tests to have the factory create a different delegate type.
diff --git a/src/cobalt/dom/csp_delegate_test.cc b/src/cobalt/dom/csp_delegate_test.cc
index f1df142..1eb815a 100644
--- a/src/cobalt/dom/csp_delegate_test.cc
+++ b/src/cobalt/dom/csp_delegate_test.cc
@@ -107,9 +107,8 @@
   mock_reporter_ = new StrictMock<MockViolationReporter>();
   scoped_ptr<CspViolationReporter> reporter(mock_reporter_);
 
-  csp_delegate_.reset(
-      new CspDelegateSecure(reporter.Pass(), origin, default_navigation_policy,
-                            csp::kCSPRequired, base::Closure()));
+  csp_delegate_.reset(new CspDelegateSecure(
+      reporter.Pass(), origin, csp::kCSPRequired, base::Closure()));
   std::string policy =
       base::StringPrintf("default-src none; %s 'self'", GetParam().directive);
   csp_delegate_->OnReceiveHeader(policy, csp::kHeaderTypeEnforce,
@@ -139,7 +138,7 @@
 TEST(CspDelegateFactoryTest, Secure) {
   scoped_ptr<CspDelegate> delegate = CspDelegateFactory::GetInstance()->Create(
       kCspEnforcementEnable, scoped_ptr<CspViolationReporter>(), GURL(),
-      std::string(), csp::kCSPRequired, base::Closure());
+      csp::kCSPRequired, base::Closure());
   EXPECT_TRUE(delegate != NULL);
 }
 
@@ -152,7 +151,7 @@
     scoped_ptr<CspDelegate> delegate =
         CspDelegateFactory::GetInstance()->Create(
             kCspEnforcementDisable, scoped_ptr<CspViolationReporter>(), GURL(),
-            std::string(), csp::kCSPRequired, base::Closure());
+            csp::kCSPRequired, base::Closure());
 
     scoped_ptr<CspDelegate> empty_delegate;
     EXPECT_EQ(empty_delegate, delegate.get());
@@ -166,7 +165,7 @@
   int token = CspDelegateFactory::GetInstance()->GetInsecureAllowedToken();
   scoped_ptr<CspDelegate> delegate = CspDelegateFactory::GetInstance()->Create(
       kCspEnforcementDisable, scoped_ptr<CspViolationReporter>(), GURL(),
-      std::string(), csp::kCSPRequired, base::Closure(), token);
+      csp::kCSPRequired, base::Closure(), token);
   EXPECT_TRUE(delegate != NULL);
 }
 
diff --git a/src/cobalt/dom/custom_event_test.cc b/src/cobalt/dom/custom_event_test.cc
index 6712aff..3f87356 100644
--- a/src/cobalt/dom/custom_event_test.cc
+++ b/src/cobalt/dom/custom_event_test.cc
@@ -26,7 +26,6 @@
 #include "cobalt/dom/window.h"
 #include "cobalt/dom_parser/parser.h"
 #include "cobalt/loader/fetcher_factory.h"
-#include "cobalt/media/media_module_stub.h"
 #include "cobalt/media_session/media_session.h"
 #include "cobalt/network/network_module.h"
 #include "cobalt/script/global_environment.h"
@@ -59,18 +58,15 @@
         dom_parser_(new dom_parser::Parser(mock_error_callback_)),
         fetcher_factory_(new loader::FetcherFactory(&network_module_)),
         local_storage_database_(NULL),
-        stub_media_module_(new media::MediaModuleStub()),
         url_("about:blank"),
         window_(new Window(
             1920, 1080, 1.f, base::kApplicationStateStarted, css_parser_.get(),
             dom_parser_.get(), fetcher_factory_.get(), NULL, NULL, NULL, NULL,
-            NULL, NULL, &local_storage_database_, stub_media_module_.get(),
-            stub_media_module_.get(), NULL, NULL, NULL, NULL, NULL, url_, "",
-            "en-US", base::Callback<void(const GURL&)>(),
+            NULL, NULL, &local_storage_database_, NULL, NULL, NULL, NULL, NULL,
+            NULL, NULL, url_, "", "en-US", base::Callback<void(const GURL&)>(),
             base::Bind(&MockErrorCallback::Run,
                        base::Unretained(&mock_error_callback_)),
-            NULL, network_bridge::PostSender(),
-            std::string() /* default security policy */, csp::kCSPRequired,
+            NULL, network_bridge::PostSender(), csp::kCSPRequired,
             kCspEnforcementEnable, base::Closure() /* csp_policy_changed */,
             base::Closure() /* ran_animation_frame_callbacks */,
             dom::Window::CloseCallback() /* window_close */,
@@ -95,7 +91,6 @@
   network::NetworkModule network_module_;
   scoped_ptr<loader::FetcherFactory> fetcher_factory_;
   dom::LocalStorageDatabase local_storage_database_;
-  scoped_ptr<media::MediaModule> stub_media_module_;
   GURL url_;
   const scoped_refptr<Window> window_;
 };
@@ -110,8 +105,8 @@
 
   global_environment_->EnableEval();
   global_environment_->SetReportEvalCallback(base::Closure());
-  bool succeeded = global_environment_->EvaluateScript(source_code, result,
-                                                       false /*mute_errors*/);
+  bool succeeded = global_environment_->EvaluateScript(
+      source_code, false /*mute_errors*/, result);
   return succeeded;
 }
 }  // namespace
diff --git a/src/cobalt/dom/document.cc b/src/cobalt/dom/document.cc
index 3249b8c..dd57f18 100644
--- a/src/cobalt/dom/document.cc
+++ b/src/cobalt/dom/document.cc
@@ -107,7 +107,7 @@
   csp_delegate_ =
       CspDelegateFactory::GetInstance()
           ->Create(options.csp_enforcement_mode, violation_reporter.Pass(),
-                   options.url, options.location_policy, options.require_csp,
+                   options.url, options.require_csp,
                    options.csp_policy_changed_callback,
                    options.csp_insecure_allowed_token)
           .Pass();
@@ -123,7 +123,7 @@
       html_element_context_->resource_provider(),
       html_element_context_->remote_typeface_cache(),
       base::Bind(&Document::OnTypefaceLoadEvent, base::Unretained(this)),
-      html_element_context_->language()));
+      html_element_context_->language(), location_));
 
   if (HasBrowsingContext()) {
     if (html_element_context_->remote_typeface_cache()) {
diff --git a/src/cobalt/dom/document.h b/src/cobalt/dom/document.h
index 52a5d30..d9097bf 100644
--- a/src/cobalt/dom/document.h
+++ b/src/cobalt/dom/document.h
@@ -110,7 +110,6 @@
             const base::optional<math::Size>& viewport_size,
             network_bridge::CookieJar* cookie_jar,
             const network_bridge::PostSender& post_sender,
-            const std::string& location_policy,
             csp::CSPHeaderPolicy require_csp,
             CspEnforcementType csp_enforcement_mode,
             const base::Closure& csp_policy_changed_callback,
@@ -124,7 +123,6 @@
           viewport_size(viewport_size),
           cookie_jar(cookie_jar),
           post_sender(post_sender),
-          location_policy(location_policy),
           require_csp(require_csp),
           csp_enforcement_mode(csp_enforcement_mode),
           csp_policy_changed_callback(csp_policy_changed_callback),
@@ -140,7 +138,6 @@
     base::optional<math::Size> viewport_size;
     network_bridge::CookieJar* cookie_jar;
     network_bridge::PostSender post_sender;
-    std::string location_policy;
     csp::CSPHeaderPolicy require_csp;
     CspEnforcementType csp_enforcement_mode;
     base::Closure csp_policy_changed_callback;
diff --git a/src/cobalt/dom/dom_exception.cc b/src/cobalt/dom/dom_exception.cc
index e299285..a1ec7fb 100644
--- a/src/cobalt/dom/dom_exception.cc
+++ b/src/cobalt/dom/dom_exception.cc
@@ -25,7 +25,9 @@
       return "";
     case DOMException::kIndexSizeErr:
       return "IndexSizeError";
-    case DOMException::kNoModificationAllowedError:
+    case DOMException::kInvalidCharacterErr:
+      return "InvalidCharacterError";
+    case DOMException::kNoModificationAllowedErr:
       return "NoModificationAllowedError";
     case DOMException::kNotFoundErr:
       return "NotFoundError";
diff --git a/src/cobalt/dom/dom_exception.h b/src/cobalt/dom/dom_exception.h
index ad45aca..a4d283c 100644
--- a/src/cobalt/dom/dom_exception.h
+++ b/src/cobalt/dom/dom_exception.h
@@ -32,7 +32,8 @@
     // If the error name does not have a corresponding code, set the code to 0.
     kNone = 0,
     kIndexSizeErr = 1,
-    kNoModificationAllowedError = 7,
+    kInvalidCharacterErr = 5,
+    kNoModificationAllowedErr = 7,
     kNotFoundErr = 8,
     kNotSupportedErr = 9,
     kInvalidStateErr = 11,
diff --git a/src/cobalt/dom/dom_settings.cc b/src/cobalt/dom/dom_settings.cc
index fab84d0..7558525 100644
--- a/src/cobalt/dom/dom_settings.cc
+++ b/src/cobalt/dom/dom_settings.cc
@@ -23,8 +23,7 @@
 
 DOMSettings::DOMSettings(
     const int max_dom_element_depth, loader::FetcherFactory* fetcher_factory,
-    network::NetworkModule* network_module, media::MediaModule* media_module,
-    const scoped_refptr<Window>& window,
+    network::NetworkModule* network_module, const scoped_refptr<Window>& window,
     MediaSourceRegistry* media_source_registry, Blob::Registry* blob_registry,
     media::CanPlayTypeHandler* can_play_type_handler,
     script::JavaScriptEngine* engine,
@@ -35,7 +34,6 @@
       microphone_options_(options.microphone_options),
       fetcher_factory_(fetcher_factory),
       network_module_(network_module),
-      media_module_(media_module),
       window_(window),
       array_buffer_allocator_(options.array_buffer_allocator),
       array_buffer_cache_(options.array_buffer_cache),
diff --git a/src/cobalt/dom/dom_settings.h b/src/cobalt/dom/dom_settings.h
index 6d9d65e..689987f 100644
--- a/src/cobalt/dom/dom_settings.h
+++ b/src/cobalt/dom/dom_settings.h
@@ -23,7 +23,6 @@
 #include "cobalt/dom/url_registry.h"
 #include "cobalt/dom/url_utils.h"
 #include "cobalt/media/can_play_type_handler.h"
-#include "cobalt/media/media_module.h"
 #include "cobalt/script/environment_settings.h"
 #include "cobalt/speech/microphone.h"
 
@@ -68,7 +67,6 @@
   DOMSettings(const int max_dom_element_depth,
               loader::FetcherFactory* fetcher_factory,
               network::NetworkModule* network_module,
-              media::MediaModule* media_module,
               const scoped_refptr<Window>& window,
               MediaSourceRegistry* media_source_registry,
               Blob::Registry* blob_registry,
@@ -101,10 +99,6 @@
     network_module_ = network_module;
   }
   network::NetworkModule* network_module() const { return network_module_; }
-  media::MediaModule* media_module() const { return media_module_; }
-  void set_media_module(media::MediaModule* media_module) {
-    media_module_ = media_module;
-  }
   script::JavaScriptEngine* javascript_engine() const {
     return javascript_engine_;
   }
@@ -117,10 +111,6 @@
   media::CanPlayTypeHandler* can_play_type_handler() const {
     return can_play_type_handler_;
   }
-  void set_can_play_type_handler(
-      media::CanPlayTypeHandler* can_play_type_handler) {
-    can_play_type_handler_ = can_play_type_handler;
-  }
   MutationObserverTaskManager* mutation_observer_task_manager() const {
     return mutation_observer_task_manager_;
   }
@@ -137,7 +127,6 @@
   const speech::Microphone::Options microphone_options_;
   loader::FetcherFactory* fetcher_factory_;
   network::NetworkModule* network_module_;
-  media::MediaModule* media_module_;
   scoped_refptr<Window> window_;
   ArrayBuffer::Allocator* array_buffer_allocator_;
   ArrayBuffer::Cache* array_buffer_cache_;
diff --git a/src/cobalt/dom/error_event_test.cc b/src/cobalt/dom/error_event_test.cc
index 7995e45..8134972 100644
--- a/src/cobalt/dom/error_event_test.cc
+++ b/src/cobalt/dom/error_event_test.cc
@@ -26,7 +26,6 @@
 #include "cobalt/dom/window.h"
 #include "cobalt/dom_parser/parser.h"
 #include "cobalt/loader/fetcher_factory.h"
-#include "cobalt/media/media_module_stub.h"
 #include "cobalt/media_session/media_session.h"
 #include "cobalt/network/network_module.h"
 #include "cobalt/script/global_environment.h"
@@ -59,18 +58,15 @@
         dom_parser_(new dom_parser::Parser(mock_error_callback_)),
         fetcher_factory_(new loader::FetcherFactory(&network_module_)),
         local_storage_database_(NULL),
-        stub_media_module_(new media::MediaModuleStub()),
         url_("about:blank"),
         window_(new Window(
             1920, 1080, 1.f, base::kApplicationStateStarted, css_parser_.get(),
             dom_parser_.get(), fetcher_factory_.get(), NULL, NULL, NULL, NULL,
-            NULL, NULL, &local_storage_database_, stub_media_module_.get(),
-            stub_media_module_.get(), NULL, NULL, NULL, NULL, NULL, url_, "",
-            "en-US", base::Callback<void(const GURL&)>(),
+            NULL, NULL, &local_storage_database_, NULL, NULL, NULL, NULL, NULL,
+            NULL, NULL, url_, "", "en-US", base::Callback<void(const GURL&)>(),
             base::Bind(&MockErrorCallback::Run,
                        base::Unretained(&mock_error_callback_)),
-            NULL, network_bridge::PostSender(),
-            std::string() /* default security policy */, csp::kCSPRequired,
+            NULL, network_bridge::PostSender(), csp::kCSPRequired,
             kCspEnforcementEnable, base::Closure() /* csp_policy_changed */,
             base::Closure() /* ran_animation_frame_callbacks */,
             dom::Window::CloseCallback() /* window_close */,
@@ -95,7 +91,6 @@
   network::NetworkModule network_module_;
   scoped_ptr<loader::FetcherFactory> fetcher_factory_;
   dom::LocalStorageDatabase local_storage_database_;
-  scoped_ptr<media::MediaModule> stub_media_module_;
   GURL url_;
   const scoped_refptr<Window> window_;
 };
@@ -110,8 +105,8 @@
 
   global_environment_->EnableEval();
   global_environment_->SetReportEvalCallback(base::Closure());
-  bool succeeded = global_environment_->EvaluateScript(source_code, result,
-                                                       false /*mute_errors*/);
+  bool succeeded = global_environment_->EvaluateScript(
+      source_code, false /*mute_errors*/, result);
   return succeeded;
 }
 }  // namespace
diff --git a/src/cobalt/dom/event.h b/src/cobalt/dom/event.h
index 62c00ac..99c125b 100644
--- a/src/cobalt/dom/event.h
+++ b/src/cobalt/dom/event.h
@@ -40,7 +40,13 @@
   // Web API: Event
   // EventPhase values as defined by Web API Event.eventPhase.
   //
-  enum EventPhase { kNone, kCapturingPhase, kAtTarget, kBubblingPhase };
+  typedef uint16 EventPhase;
+  enum EventPhaseInternal : uint16 {
+    kNone,
+    kCapturingPhase,
+    kAtTarget,
+    kBubblingPhase
+  };
 
   // Custom, not in any spec.
   //
diff --git a/src/cobalt/dom/font_cache.cc b/src/cobalt/dom/font_cache.cc
index 4fff414..4709e95 100644
--- a/src/cobalt/dom/font_cache.cc
+++ b/src/cobalt/dom/font_cache.cc
@@ -43,14 +43,16 @@
 FontCache::FontCache(render_tree::ResourceProvider** resource_provider,
                      loader::font::RemoteTypefaceCache* remote_typeface_cache,
                      const base::Closure& external_typeface_load_event_callback,
-                     const std::string& language)
+                     const std::string& language,
+                     scoped_refptr<Location> document_location)
     : resource_provider_(resource_provider),
       remote_typeface_cache_(remote_typeface_cache),
       external_typeface_load_event_callback_(
           external_typeface_load_event_callback),
       language_(language),
       font_face_map_(new FontFaceMap()),
-      last_inactive_process_time_(base::TimeTicks::Now()) {}
+      last_inactive_process_time_(base::TimeTicks::Now()),
+      document_location_(document_location) {}
 
 void FontCache::SetFontFaceMap(scoped_ptr<FontFaceMap> font_face_map) {
   DCHECK(thread_checker_.CalledOnValidThread());
@@ -308,7 +310,9 @@
   // Retrieve the font from the remote typeface cache, potentially triggering a
   // load.
   scoped_refptr<loader::font::CachedRemoteTypeface> cached_remote_typeface =
-      remote_typeface_cache_->CreateCachedResource(url);
+      remote_typeface_cache_->CreateCachedResource(
+          url, document_location_ ? document_location_->OriginObject()
+                                  : loader::Origin());
 
   RequestedRemoteTypefaceMap::iterator requested_remote_typeface_iterator =
       requested_remote_typeface_cache_.find(url);
diff --git a/src/cobalt/dom/font_cache.h b/src/cobalt/dom/font_cache.h
index e90adf9..048e50b 100644
--- a/src/cobalt/dom/font_cache.h
+++ b/src/cobalt/dom/font_cache.h
@@ -27,6 +27,7 @@
 #include "base/timer.h"
 #include "cobalt/dom/font_face.h"
 #include "cobalt/dom/font_list.h"
+#include "cobalt/dom/location.h"
 #include "cobalt/loader/font/remote_typeface_cache.h"
 #include "cobalt/render_tree/font.h"
 #include "cobalt/render_tree/glyph.h"
@@ -173,7 +174,8 @@
   FontCache(render_tree::ResourceProvider** resource_provider,
             loader::font::RemoteTypefaceCache* remote_typeface_cache,
             const base::Closure& external_typeface_load_event_callback,
-            const std::string& language);
+            const std::string& language,
+            scoped_refptr<Location> document_location);
 
   // Set a new font face map. If it matches the old font face map then nothing
   // is done. Otherwise, it is updated with the new value and the remote
@@ -324,6 +326,10 @@
 
   // Thread checker used to verify safe thread usage of the font cache.
   base::ThreadChecker thread_checker_;
+
+  // Font cache's corresponding document's location object. It can provide
+  // document's origin.
+  scoped_refptr<Location> document_location_;
 };
 
 }  // namespace dom
diff --git a/src/cobalt/dom/font_cache_test.cc b/src/cobalt/dom/font_cache_test.cc
index 0f1f1dd..3e0cd89 100644
--- a/src/cobalt/dom/font_cache_test.cc
+++ b/src/cobalt/dom/font_cache_test.cc
@@ -87,7 +87,7 @@
                              ALLOW_THIS_IN_INITIALIZER_LIST(base::Bind(
                                  &FontCacheTest::DummyOnTypefaceLoadEvent,
                                  base::Unretained(this))),
-                             "en-US")) {}
+                             "en-US", NULL)) {}
 
 TEST_F(FontCacheTest, FindPostscriptFont) {
   const std::string family_name("Dancing Script");
diff --git a/src/cobalt/dom/html_element.cc b/src/cobalt/dom/html_element.cc
index 4bb3606..e82e801 100644
--- a/src/cobalt/dom/html_element.cc
+++ b/src/cobalt/dom/html_element.cc
@@ -1408,7 +1408,7 @@
 
       scoped_refptr<loader::image::CachedImage> cached_image =
           html_element_context()->image_cache()->CreateCachedResource(
-              absolute_url);
+              absolute_url, loader::Origin());
       base::Closure loaded_callback = base::Bind(
           &HTMLElement::OnBackgroundImageLoaded, base::Unretained(this));
       cached_images.push_back(
diff --git a/src/cobalt/dom/html_element_context.h b/src/cobalt/dom/html_element_context.h
index d7054db..7847423 100644
--- a/src/cobalt/dom/html_element_context.h
+++ b/src/cobalt/dom/html_element_context.h
@@ -77,10 +77,6 @@
   media::CanPlayTypeHandler* can_play_type_handler() {
     return can_play_type_handler_;
   }
-  void set_can_play_type_handler(
-      media::CanPlayTypeHandler* can_play_type_handler) {
-    can_play_type_handler_ = can_play_type_handler;
-  }
   media::WebMediaPlayerFactory* web_media_player_factory() {
     return web_media_player_factory_;
   }
diff --git a/src/cobalt/dom/html_image_element.cc b/src/cobalt/dom/html_image_element.cc
index 4d8dfce..ffd4b5a 100644
--- a/src/cobalt/dom/html_image_element.cc
+++ b/src/cobalt/dom/html_image_element.cc
@@ -112,10 +112,11 @@
     // the img element to the completely available state, update the
     // presentation of the image appropriately, queue a task to fire a simple
     // event named load at the img element, and abort these steps.
-    cached_image = node_document()
-                       ->html_element_context()
-                       ->image_cache()
-                       ->CreateCachedResource(selected_source);
+    cached_image =
+        node_document()
+            ->html_element_context()
+            ->image_cache()
+            ->CreateCachedResource(selected_source, loader::Origin());
     if (cached_image->TryGetResource()) {
       PreventGarbageCollectionUntilEventIsDispatched(base::Tokens::load());
       return;
diff --git a/src/cobalt/dom/html_link_element.cc b/src/cobalt/dom/html_link_element.cc
index e18a057..90f006c 100644
--- a/src/cobalt/dom/html_link_element.cc
+++ b/src/cobalt/dom/html_link_element.cc
@@ -140,7 +140,7 @@
       base::Bind(
           &loader::FetcherFactory::CreateSecureFetcher,
           base::Unretained(document->html_element_context()->fetcher_factory()),
-          absolute_url_, csp_callback),
+          absolute_url_, csp_callback, loader::kNoCORSMode, loader::Origin()),
       scoped_ptr<loader::Decoder>(new loader::TextDecoder(
           base::Bind(&HTMLLinkElement::OnLoadingDone, base::Unretained(this)))),
       base::Bind(&HTMLLinkElement::OnLoadingError, base::Unretained(this))));
diff --git a/src/cobalt/dom/html_media_element.cc b/src/cobalt/dom/html_media_element.cc
index 429e3e3..9ee8083 100644
--- a/src/cobalt/dom/html_media_element.cc
+++ b/src/cobalt/dom/html_media_element.cc
@@ -207,11 +207,7 @@
 
 std::string HTMLMediaElement::CanPlayType(const std::string& mime_type,
                                           const std::string& key_system) {
-  if (!html_element_context()->can_play_type_handler()) {
-    DLOG(ERROR) << __FUNCTION__ << "(" << mime_type << ", " << key_system
-                << "): Media playback in PRELOADING is not supported.";
-    return "";
-  }
+  DCHECK(html_element_context()->can_play_type_handler());
 
 #if defined(COBALT_MEDIA_SOURCE_2016)
   DLOG_IF(ERROR, !key_system.empty())
@@ -953,6 +949,10 @@
   if (url.is_empty()) {
     return;
   }
+#if SB_HAS(PLAYER_WITH_URL)
+  // TODO: Investigate if we have to support csp for url player.
+  player_->LoadUrl(url);
+#else   // SB_HAS(PLAYER_WITH_URL)
   if (url.spec() == SourceURL()) {
     player_->LoadMediaSource();
   } else {
@@ -966,6 +966,7 @@
     player_->LoadProgressive(url, data_source.Pass(),
                              WebMediaPlayer::kCORSModeUnspecified);
   }
+#endif  // SB_HAS(PLAYER_WITH_URL)
 }
 
 void HTMLMediaElement::ClearMediaPlayer() {
@@ -1125,6 +1126,8 @@
 }
 
 void HTMLMediaElement::ScheduleOwnEvent(base::Token event_name) {
+  LOG_IF(INFO, event_name == base::Tokens::error())
+      << "onerror event fired with error " << (error_ ? error_->code() : 0);
   MLOG() << event_name;
   scoped_refptr<Event> event =
       new Event(event_name, Event::kNotBubbles, Event::kCancelable);
@@ -1528,7 +1531,7 @@
   EndProcessingMediaPlayerCallback();
 }
 
-void HTMLMediaElement::TimeChanged() {
+void HTMLMediaElement::TimeChanged(bool eos_played) {
   DCHECK(player_);
   if (!player_) {
     return;
@@ -1554,8 +1557,9 @@
   // When the current playback position reaches the end of the media resource
   // when the direction of playback is forwards, then the user agent must follow
   // these steps:
-  if (!SbDoubleIsNan(dur) && (0.0f != dur) && now >= dur &&
-      playback_rate_ > 0) {
+  eos_played |=
+      !SbDoubleIsNan(dur) && (0.0f != dur) && now >= dur && playback_rate_ > 0;
+  if (eos_played) {
     // If the media element has a loop attribute specified and does not have a
     // current media controller,
     if (loop()) {
@@ -1689,12 +1693,14 @@
 // https://www.w3.org/TR/eme-initdata-registry/#registry.
 std::string ToInitDataTypeString(media::EmeInitDataType init_data_type) {
   switch (init_data_type) {
-    case media::kEmeInitDataTypeWebM:
-      return "webm";
     case media::kEmeInitDataTypeCenc:
       return "cenc";
+    case media::kEmeInitDataTypeFairplay:
+      return "fairplay";
     case media::kEmeInitDataTypeKeyIds:
       return "keyids";
+    case media::kEmeInitDataTypeWebM:
+      return "webm";
     default:
       LOG(WARNING) << "Unknown EME initialization data type.";
       return "";
diff --git a/src/cobalt/dom/html_media_element.h b/src/cobalt/dom/html_media_element.h
index b3d1f0d..31314e3 100644
--- a/src/cobalt/dom/html_media_element.h
+++ b/src/cobalt/dom/html_media_element.h
@@ -231,7 +231,7 @@
   // WebMediaPlayerClient methods
   void NetworkStateChanged() OVERRIDE;
   void ReadyStateChanged() OVERRIDE;
-  void TimeChanged() OVERRIDE;
+  void TimeChanged(bool eos_played) OVERRIDE;
   void DurationChanged() OVERRIDE;
   void OutputModeChanged() OVERRIDE;
   void PlaybackStateChanged() OVERRIDE;
diff --git a/src/cobalt/dom/html_script_element.cc b/src/cobalt/dom/html_script_element.cc
index 3baa07f..fd4a4b7 100644
--- a/src/cobalt/dom/html_script_element.cc
+++ b/src/cobalt/dom/html_script_element.cc
@@ -257,7 +257,7 @@
           base::Bind(
               &loader::FetcherFactory::CreateSecureFetcher,
               base::Unretained(html_element_context()->fetcher_factory()), url_,
-              csp_callback),
+              csp_callback, loader::kNoCORSMode, loader::Origin()),
           base::Bind(&loader::TextDecoder::Create,
                      base::Bind(&HTMLScriptElement::OnSyncLoadingDone,
                                 base::Unretained(this))),
@@ -298,7 +298,7 @@
           base::Bind(
               &loader::FetcherFactory::CreateSecureFetcher,
               base::Unretained(html_element_context()->fetcher_factory()), url_,
-              csp_callback),
+              csp_callback, loader::kNoCORSMode, loader::Origin()),
           scoped_ptr<loader::Decoder>(new loader::TextDecoder(base::Bind(
               &HTMLScriptElement::OnLoadingDone, base::Unretained(this)))),
           base::Bind(&HTMLScriptElement::OnLoadingError,
@@ -323,7 +323,7 @@
           base::Bind(
               &loader::FetcherFactory::CreateSecureFetcher,
               base::Unretained(html_element_context()->fetcher_factory()), url_,
-              csp_callback),
+              csp_callback, loader::kNoCORSMode, loader::Origin()),
           scoped_ptr<loader::Decoder>(new loader::TextDecoder(base::Bind(
               &HTMLScriptElement::OnLoadingDone, base::Unretained(this)))),
           base::Bind(&HTMLScriptElement::OnLoadingError,
@@ -533,7 +533,7 @@
   bool mute_errors =
       fetched_last_url_origin_ != document_->location()->OriginObject();
   html_element_context()->script_runner()->Execute(
-      content, script_location, NULL /* output: succeeded */, mute_errors);
+      content, script_location, mute_errors, NULL /*out_succeeded*/);
 
   // 5. 6. Not needed by Cobalt.
 
diff --git a/src/cobalt/dom/node.h b/src/cobalt/dom/node.h
index c1ceb48..ff2f36c 100644
--- a/src/cobalt/dom/node.h
+++ b/src/cobalt/dom/node.h
@@ -91,10 +91,10 @@
  public:
   // Web API: Node
   // NodeType values as defined by Web API Node.nodeType.
-  typedef uint16 NodeType;  // Work around lack of strongly-typed enums
-                            // in C++03.
-  enum NodeTypeInternal {   // A name is given only to pacify the compiler.
-                            // Use |NodeType| instead.
+  // Work around lack of strongly-typed enums in C++03.
+  typedef uint16 NodeType;
+  // A name that is given only to pacify the compiler. Use |NodeType| instead.
+  enum NodeTypeInternal : uint16 {
     kElementNode = 1,
     kTextNode = 3,
     kCdataSectionNode = 4,
diff --git a/src/cobalt/dom/testing/stub_script_runner.cc b/src/cobalt/dom/testing/stub_script_runner.cc
index 8ad635a..9158225 100644
--- a/src/cobalt/dom/testing/stub_script_runner.cc
+++ b/src/cobalt/dom/testing/stub_script_runner.cc
@@ -20,7 +20,7 @@
 
 std::string StubScriptRunner::Execute(
     const std::string& script_utf8, const base::SourceLocation& script_location,
-    bool* out_succeeded, bool mute_errors) {
+    bool mute_errors, bool* out_succeeded) {
   UNREFERENCED_PARAMETER(script_utf8);
   UNREFERENCED_PARAMETER(script_location);
   UNREFERENCED_PARAMETER(mute_errors);
diff --git a/src/cobalt/dom/testing/stub_script_runner.h b/src/cobalt/dom/testing/stub_script_runner.h
index fb42205..8b74fc7 100644
--- a/src/cobalt/dom/testing/stub_script_runner.h
+++ b/src/cobalt/dom/testing/stub_script_runner.h
@@ -27,7 +27,7 @@
  public:
   std::string Execute(const std::string& script_utf8,
                       const base::SourceLocation& script_location,
-                      bool* out_succeeded, bool mute_errors) OVERRIDE;
+                      bool mute_errors, bool* out_succeeded) OVERRIDE;
 };
 
 }  // namespace testing
diff --git a/src/cobalt/dom/testing/stub_window.h b/src/cobalt/dom/testing/stub_window.h
index 32ef4f9..c437133 100644
--- a/src/cobalt/dom/testing/stub_window.h
+++ b/src/cobalt/dom/testing/stub_window.h
@@ -25,7 +25,6 @@
 #include "cobalt/dom/window.h"
 #include "cobalt/dom_parser/parser.h"
 #include "cobalt/loader/fetcher_factory.h"
-#include "cobalt/media/media_module_stub.h"
 #include "cobalt/media_session/media_session.h"
 #include "cobalt/network/network_module.h"
 #include "cobalt/script/global_environment.h"
@@ -46,7 +45,6 @@
         dom_parser_(new dom_parser::Parser(base::Bind(&StubErrorCallback))),
         fetcher_factory_(new loader::FetcherFactory(&network_module_)),
         local_storage_database_(NULL),
-        stub_media_module_(new media::MediaModuleStub()),
         url_("about:blank"),
         dom_stat_tracker_(new dom::DomStatTracker("StubWindow")) {
     engine_ = script::JavaScriptEngine::CreateEngine();
@@ -54,12 +52,10 @@
     window_ = new dom::Window(
         1920, 1080, 1.f, base::kApplicationStateStarted, css_parser_.get(),
         dom_parser_.get(), fetcher_factory_.get(), NULL, NULL, NULL, NULL, NULL,
-        NULL, &local_storage_database_, stub_media_module_.get(),
-        stub_media_module_.get(), NULL, NULL, NULL, NULL,
+        NULL, &local_storage_database_, NULL, NULL, NULL, NULL, NULL, NULL,
         dom_stat_tracker_.get(), url_, "", "en-US",
         base::Callback<void(const GURL&)>(), base::Bind(&StubErrorCallback),
-        NULL, network_bridge::PostSender(),
-        std::string() /* default security policy */, csp::kCSPRequired,
+        NULL, network_bridge::PostSender(), csp::kCSPRequired,
         dom::kCspEnforcementEnable, base::Closure() /* csp_policy_changed */,
         base::Closure() /* ran_animation_frame_callbacks */,
         dom::Window::CloseCallback() /* window_close */,
@@ -82,7 +78,6 @@
   network::NetworkModule network_module_;
   scoped_ptr<loader::FetcherFactory> fetcher_factory_;
   dom::LocalStorageDatabase local_storage_database_;
-  scoped_ptr<media::MediaModule> stub_media_module_;
   GURL url_;
   scoped_ptr<dom::DomStatTracker> dom_stat_tracker_;
   script::EnvironmentSettings environment_settings_;
diff --git a/src/cobalt/dom/window.cc b/src/cobalt/dom/window.cc
index e5a0eda..9d0a291 100644
--- a/src/cobalt/dom/window.cc
+++ b/src/cobalt/dom/window.cc
@@ -98,7 +98,6 @@
                const base::Callback<void(const std::string&)>& error_callback,
                network_bridge::CookieJar* cookie_jar,
                const network_bridge::PostSender& post_sender,
-               const std::string& default_security_policy,
                csp::CSPHeaderPolicy require_csp,
                CspEnforcementType csp_enforcement_mode,
                const base::Closure& csp_policy_changed_callback,
@@ -137,10 +136,9 @@
               base::Bind(&Window::FireHashChangeEvent, base::Unretained(this)),
               performance_->timing()->GetNavigationStartClock(),
               navigation_callback, ParseUserAgentStyleSheet(css_parser),
-              math::Size(width_, height_), cookie_jar, post_sender,
-              default_security_policy, require_csp, csp_enforcement_mode,
-              csp_policy_changed_callback, csp_insecure_allowed_token,
-              dom_max_element_depth)))),
+              math::Size(width_, height_), cookie_jar, post_sender, require_csp,
+              csp_enforcement_mode, csp_policy_changed_callback,
+              csp_insecure_allowed_token, dom_max_element_depth)))),
       document_loader_(NULL),
       history_(new History()),
       navigator_(new Navigator(user_agent, language, media_session,
@@ -291,16 +289,24 @@
 
 scoped_refptr<Crypto> Window::crypto() const { return crypto_; }
 
-std::string Window::Btoa(const std::string& string_to_encode) {
+std::string Window::Btoa(const std::string& string_to_encode,
+                         script::ExceptionState* exception_state) {
   std::string output;
-  base::Base64Encode(string_to_encode, &output);
+  if (!base::Base64Encode(string_to_encode, &output)) {
+    DOMException::Raise(DOMException::kInvalidCharacterErr, exception_state);
+    return std::string();
+  }
   return output;
 }
 
-std::string Window::Atob(const std::string& encoded_string) {
+std::vector<uint8_t> Window::Atob(const std::string& encoded_string,
+                                  script::ExceptionState* exception_state) {
   std::string output;
-  base::Base64Decode(encoded_string, &output);
-  return output;
+  if (!base::Base64Decode(encoded_string, &output)) {
+    DOMException::Raise(DOMException::kInvalidCharacterErr, exception_state);
+    return {};
+  }
+  return {output.begin(), output.end()};
 }
 
 int Window::SetTimeout(const WindowTimers::TimerCallbackArg& handler,
diff --git a/src/cobalt/dom/window.h b/src/cobalt/dom/window.h
index b1fa459..93c0e32 100644
--- a/src/cobalt/dom/window.h
+++ b/src/cobalt/dom/window.h
@@ -16,6 +16,7 @@
 #define COBALT_DOM_WINDOW_H_
 
 #include <string>
+#include <vector>
 
 #include "base/callback.h"
 #include "base/hash_tables.h"
@@ -110,10 +111,7 @@
   typedef base::Callback<void(base::TimeDelta)> CloseCallback;
   typedef UrlRegistry<MediaSource> MediaSourceRegistry;
   typedef base::Callback<bool(const GURL&, const std::string&)> CacheCallback;
-  enum ClockType {
-    kClockTypeTestRunner,
-    kClockTypeSystemTime
-  };
+  enum ClockType { kClockTypeTestRunner, kClockTypeSystemTime };
 
   Window(
       int width, int height, float device_pixel_ratio,
@@ -140,7 +138,6 @@
       const base::Callback<void(const std::string&)>& error_callback,
       network_bridge::CookieJar* cookie_jar,
       const network_bridge::PostSender& post_sender,
-      const std::string& default_security_policy,
       csp::CSPHeaderPolicy require_csp,
       dom::CspEnforcementType csp_enforcement_mode,
       const base::Closure& csp_policy_changed_callback,
@@ -235,9 +232,11 @@
   scoped_refptr<Crypto> crypto() const;
 
   // base64 encoding and decoding
-  std::string Btoa(const std::string& string_to_encode);
+  std::string Btoa(const std::string& string_to_encode,
+                   script::ExceptionState* exception_state);
 
-  std::string Atob(const std::string& encoded_string);
+  std::vector<uint8_t> Atob(const std::string& encoded_string,
+                            script::ExceptionState* exception_state);
 
   // Web API: WindowTimers (implements)
   //   https://www.w3.org/TR/html5/webappapis.html#timers
@@ -306,11 +305,6 @@
 
   void SetCamera3D(const scoped_refptr<input::Camera3D>& camera_3d);
 
-  void set_can_play_type_handler(
-      media::CanPlayTypeHandler* can_play_type_handler) {
-    html_element_context_->set_can_play_type_handler(can_play_type_handler);
-  }
-
   void set_web_media_player_factory(
       media::WebMediaPlayerFactory* web_media_player_factory) {
     html_element_context_->set_web_media_player_factory(
diff --git a/src/cobalt/dom/window.idl b/src/cobalt/dom/window.idl
index 8749653..77a3df6 100644
--- a/src/cobalt/dom/window.idl
+++ b/src/cobalt/dom/window.idl
@@ -36,9 +36,10 @@
   // the user agent
   readonly attribute Navigator navigator;
 
-  // base64 encoding and decoding
-  DOMString btoa(DOMString string_to_encode);
-  DOMString atob(DOMString encoded_string);
+  // https://html.spec.whatwg.org/multipage/webappapis.html#dom-btoa
+  [RaisesException] DOMString btoa(DOMString stringToEncode);
+  // https://html.spec.whatwg.org/multipage/webappapis.html#dom-atob
+  [RaisesException] ByteString atob(DOMString encodedString);
 
   // Custom, not in any spec.
   //
diff --git a/src/cobalt/dom/window_test.cc b/src/cobalt/dom/window_test.cc
index 65a8c1d..04b2ef9 100644
--- a/src/cobalt/dom/window_test.cc
+++ b/src/cobalt/dom/window_test.cc
@@ -24,7 +24,6 @@
 #include "cobalt/dom/screen.h"
 #include "cobalt/dom_parser/parser.h"
 #include "cobalt/loader/fetcher_factory.h"
-#include "cobalt/media/media_module_stub.h"
 #include "cobalt/media_session/media_session.h"
 #include "cobalt/network/network_module.h"
 #include "cobalt/network_bridge/net_poster.h"
@@ -48,18 +47,15 @@
         dom_parser_(new dom_parser::Parser(mock_error_callback_)),
         fetcher_factory_(new loader::FetcherFactory(&network_module_)),
         local_storage_database_(NULL),
-        stub_media_module_(new media::MediaModuleStub()),
         url_("about:blank"),
         window_(new Window(
             1920, 1080, 1.f, base::kApplicationStateStarted, css_parser_.get(),
             dom_parser_.get(), fetcher_factory_.get(), NULL, NULL, NULL, NULL,
-            NULL, NULL, &local_storage_database_, stub_media_module_.get(),
-            stub_media_module_.get(), NULL, NULL, NULL, NULL, NULL, url_, "",
-            "en-US", base::Callback<void(const GURL &)>(),
+            NULL, NULL, &local_storage_database_, NULL, NULL, NULL, NULL, NULL,
+            NULL, NULL, url_, "", "en-US", base::Callback<void(const GURL &)>(),
             base::Bind(&MockErrorCallback::Run,
                        base::Unretained(&mock_error_callback_)),
-            NULL, network_bridge::PostSender(),
-            std::string() /* default security policy */, csp::kCSPRequired,
+            NULL, network_bridge::PostSender(), csp::kCSPRequired,
             kCspEnforcementEnable, base::Closure() /* csp_policy_changed */,
             base::Closure() /* ran_animation_frame_callbacks */,
             dom::Window::CloseCallback() /* window_close */,
@@ -74,7 +70,6 @@
   network::NetworkModule network_module_;
   scoped_ptr<loader::FetcherFactory> fetcher_factory_;
   dom::LocalStorageDatabase local_storage_database_;
-  scoped_ptr<media::MediaModule> stub_media_module_;
   GURL url_;
   scoped_refptr<Window> window_;
 };
diff --git a/src/cobalt/layout/box.cc b/src/cobalt/layout/box.cc
index c8ed055..1453801 100644
--- a/src/cobalt/layout/box.cc
+++ b/src/cobalt/layout/box.cc
@@ -1357,9 +1357,10 @@
 }
 
 namespace {
-bool AllBorderSidesShareSameProperties(const Border& border) {
-  return border.left == border.top && border.left == border.right &&
-         border.left == border.bottom;
+bool AllBorderSidesShareSameStyle(const Border& border) {
+  return border.left.style == border.top.style &&
+         border.left.style == border.right.style &&
+         border.left.style == border.bottom.style;
 }
 }  // namespace
 
@@ -1381,10 +1382,10 @@
                            &rect_node_builder);
 
   if (rounded_corners &&
-      !AllBorderSidesShareSameProperties(*rect_node_builder.border)) {
+      !AllBorderSidesShareSameStyle(*rect_node_builder.border)) {
     LOG(WARNING)
         << "Cobalt does not support rounded corners borders whose edges do not "
-           "all share the same properties.";
+           "all share the same style.";
     return;
   }
 
diff --git a/src/cobalt/layout/topmost_event_target.cc b/src/cobalt/layout/topmost_event_target.cc
index f825db7..502701e 100644
--- a/src/cobalt/layout/topmost_event_target.cc
+++ b/src/cobalt/layout/topmost_event_target.cc
@@ -362,7 +362,7 @@
       pointer_state->ClearPendingPointerCaptureTargetOverride(
           pointer_event->pointer_id());
     }
-    if (target_element) {
+    if (target_element && !is_touchpad_event) {
       SendCompatibilityMappingMouseEvent(target_element, event, pointer_event,
                                          event_init,
                                          &mouse_event_prevent_flags_);
diff --git a/src/cobalt/layout/used_style.cc b/src/cobalt/layout/used_style.cc
index 323425d..ecb861e 100644
--- a/src/cobalt/layout/used_style.cc
+++ b/src/cobalt/layout/used_style.cc
@@ -472,7 +472,8 @@
   DCHECK(animated_image_tracker_);
   DCHECK(image_cache_);
   scoped_refptr<loader::image::Image> image =
-      image_cache_->CreateCachedResource(url)->TryGetResource();
+      image_cache_->CreateCachedResource(url, loader::Origin())
+          ->TryGetResource();
   if (image && image->IsAnimated()) {
     loader::image::AnimatedImage* animated_image =
         base::polymorphic_downcast<loader::image::AnimatedImage*>(image.get());
@@ -484,7 +485,8 @@
 scoped_refptr<loader::mesh::MeshProjection>
 UsedStyleProvider::ResolveURLToMeshProjection(const GURL& url) {
   DCHECK(mesh_cache_);
-  return mesh_cache_->CreateCachedResource(url)->TryGetResource();
+  return mesh_cache_->CreateCachedResource(url, loader::Origin())
+      ->TryGetResource();
 }
 
 void UsedStyleProvider::UpdateAnimatedImages() {
diff --git a/src/cobalt/layout_tests/layout_snapshot.cc b/src/cobalt/layout_tests/layout_snapshot.cc
index 1fe1c7e..49c1a6f 100644
--- a/src/cobalt/layout_tests/layout_snapshot.cc
+++ b/src/cobalt/layout_tests/layout_snapshot.cc
@@ -20,7 +20,6 @@
 #include "base/run_loop.h"
 #include "base/synchronization/waitable_event.h"
 #include "cobalt/browser/web_module.h"
-#include "cobalt/media/media_module_stub.h"
 #include "cobalt/network/network_module.h"
 #include "cobalt/render_tree/resource_provider.h"
 
@@ -64,10 +63,6 @@
   net_options.https_requirement = network::kHTTPSOptional;
   network::NetworkModule network_module(net_options);
 
-  // We do not support a media module in this mode.
-  scoped_ptr<media::MediaModule> stub_media_module(
-      new media::MediaModuleStub());
-
   // Use 128M of image cache to minimize the effect of image loading.
   const size_t kImageCacheCapacity = 128 * 1024 * 1024;
 
@@ -87,7 +82,8 @@
                  MessageLoop::current()),
       base::Bind(&WebModuleErrorCallback, &run_loop, MessageLoop::current()),
       browser::WebModule::CloseCallback() /* window_close_callback */,
-      base::Closure() /* window_minimize_callback */, stub_media_module.get(),
+      base::Closure() /* window_minimize_callback */,
+      NULL /* can_play_type_handler */, NULL /* web_media_player_factory */,
       &network_module, viewport_size, 1.f, resource_provider, 60.0f,
       web_module_options);
 
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-2-values-with-rounded-corners-expected.png b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-2-values-with-rounded-corners-expected.png
new file mode 100644
index 0000000..de9ab45
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-2-values-with-rounded-corners-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-2-values-with-rounded-corners.html b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-2-values-with-rounded-corners.html
new file mode 100644
index 0000000..1fc226b
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-2-values-with-rounded-corners.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!--
+ | Setting 2 different color values for the edges of a rounded corners border.
+ |   https://www.w3.org/TR/css3-background/#the-border-color
+ -->
+<html>
+<head>
+  <style>
+    div {
+      border: 25px solid;
+      border-color: #00FFFF #FF7F50;
+      border-radius: 50%;
+      height: 200px;
+      width: 400px;
+    }
+  </style>
+</head>
+<body>
+  <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-3-values-with-rounded-corners-expected.png b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-3-values-with-rounded-corners-expected.png
new file mode 100644
index 0000000..ebf6ff0
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-3-values-with-rounded-corners-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-3-values-with-rounded-corners.html b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-3-values-with-rounded-corners.html
new file mode 100644
index 0000000..eb6b3e8
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-3-values-with-rounded-corners.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!--
+ | Setting 3 different color values for the edges of a rounded corners border.
+ |   https://www.w3.org/TR/css3-background/#the-border-color
+ -->
+<html>
+<head>
+  <style>
+    div {
+      border: 25px solid;
+      border-color: #00FFFF #FF7F50 #FF69B4;
+      border-radius: 50%;
+      height: 200px;
+      width: 400px;
+    }
+  </style>
+</head>
+<body>
+  <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-different-rounded-corners-and-different-border-widths-expected.png b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-different-rounded-corners-and-different-border-widths-expected.png
new file mode 100644
index 0000000..2d7ff36
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-different-rounded-corners-and-different-border-widths-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-different-rounded-corners-and-different-border-widths.html b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-different-rounded-corners-and-different-border-widths.html
new file mode 100644
index 0000000..9de0f5d
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-different-rounded-corners-and-different-border-widths.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!--
+ | Setting 4 different color values, width values and radius values for the edges
+ | of a rounded corners border.
+ |   https://www.w3.org/TR/css3-background/#the-border-color
+ |   https://www.w3.org/TR/css3-background/#the-border-width
+ |   https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+  <style>
+    div {
+      border: solid;
+      border-color: #00FFFF #FF7F50 #FF69B4 #FAFAD2;
+      border-width: 10px 50px 30px 80px;
+      border-radius: 30px 80px 100px 150px;
+      height: 200px;
+      width: 400px;
+    }
+  </style>
+</head>
+<body>
+  <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-different-rounded-corners-expected.png b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-different-rounded-corners-expected.png
new file mode 100644
index 0000000..2f4ba67
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-different-rounded-corners-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-different-rounded-corners.html b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-different-rounded-corners.html
new file mode 100644
index 0000000..071f22c
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-different-rounded-corners.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!--
+ | Setting 4 different color values and radius values for the edges of a
+ | rounded corners border.
+ |   https://www.w3.org/TR/css3-background/#the-border-color
+ |   https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+  <style>
+    div {
+      border: 25px solid;
+      border-color: #00FFFF #FF7F50 #FF69B4 #FAFAD2;
+      border-radius: 30px 80px 100px 150px;
+      height: 200px;
+      width: 400px;
+    }
+  </style>
+</head>
+<body>
+  <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-rounded-corners-and-different-border-widths-expected.png b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-rounded-corners-and-different-border-widths-expected.png
new file mode 100644
index 0000000..06f8d8b
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-rounded-corners-and-different-border-widths-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-rounded-corners-and-different-border-widths.html b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-rounded-corners-and-different-border-widths.html
new file mode 100644
index 0000000..c841fa5
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-rounded-corners-and-different-border-widths.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!--
+ | Setting 4 different color values and width values for the edges of a rounded
+ | corners border.
+ |   https://www.w3.org/TR/css3-background/#the-border-color
+ |   https://www.w3.org/TR/css3-background/#the-border-width
+ -->
+<html>
+<head>
+  <style>
+    div {
+      border: solid;
+      border-color: #00FFFF #FF7F50 #FF69B4 #FAFAD2;
+      border-width: 10px 50px 30px 80px;
+      border-radius: 50%;
+      height: 200px;
+      width: 400px;
+    }
+  </style>
+</head>
+<body>
+  <div></div>
+</body>
+</html>
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-rounded-corners-expected.png b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-rounded-corners-expected.png
new file mode 100644
index 0000000..7349035
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-rounded-corners-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-rounded-corners.html b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-rounded-corners.html
new file mode 100644
index 0000000..76c10f5
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-1-border-color-4-values-with-rounded-corners.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!--
+ | Setting 4 different color values for the edges of a rounded corners border.
+ |   https://www.w3.org/TR/css3-background/#the-border-color
+ -->
+<html>
+<head>
+  <style>
+    div {
+      border: 25px solid;
+      border-color: #00FFFF #FF7F50 #FF69B4 #FAFAD2;
+      border-radius: 50%;
+      height: 200px;
+      width: 400px;
+    }
+  </style>
+</head>
+<body>
+  <div></div>
+</body>
+</html>
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-2-values-with-rounded-corners-expected.png b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-2-values-with-rounded-corners-expected.png
new file mode 100644
index 0000000..6172080
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-2-values-with-rounded-corners-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-2-values-with-rounded-corners.html b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-2-values-with-rounded-corners.html
new file mode 100644
index 0000000..c092ca5
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-2-values-with-rounded-corners.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!--
+ | Setting 2 different width values for a rounded corners border.
+ |   https://www.w3.org/TR/css3-background/#the-border-width
+ -->
+<html>
+<head>
+  <style>
+    div {
+      border: solid #00FFFF;
+      border-width: 80px 10px;
+      border-radius: 50%;
+      height: 200px;
+      width: 400px;
+    }
+  </style>
+</head>
+<body>
+  <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-3-values-with-rounded-corners-expected.png b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-3-values-with-rounded-corners-expected.png
new file mode 100644
index 0000000..b193ed0
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-3-values-with-rounded-corners-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-3-values-with-rounded-corners.html b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-3-values-with-rounded-corners.html
new file mode 100644
index 0000000..7693fff
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-3-values-with-rounded-corners.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!--
+ | Setting 3 different width values for a rounded corners border.
+ |   https://www.w3.org/TR/css3-background/#the-border-width
+ -->
+<html>
+<head>
+  <style>
+    div {
+      border: solid #00FFFF;
+      border-width: 80px 50px 10px;
+      border-radius: 50%;
+      height: 200px;
+      width: 400px;
+    }
+  </style>
+</head>
+<body>
+  <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-4-values-with-different-rounded-corners-expected.png b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-4-values-with-different-rounded-corners-expected.png
new file mode 100644
index 0000000..3da6c2c
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-4-values-with-different-rounded-corners-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-4-values-with-different-rounded-corners.html b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-4-values-with-different-rounded-corners.html
new file mode 100644
index 0000000..4a33512
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-4-values-with-different-rounded-corners.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!--
+ | Setting 4 different width values and radius values for the edges of a
+ | rounded corners border.
+ |   https://www.w3.org/TR/css3-background/#the-border-width
+ |   https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+  <style>
+    div {
+      border: solid #00FFFF;
+      border-width: 10px 50px 30px 80px;
+      border-radius: 30px 80px 100px 150px;
+      height: 200px;
+      width: 400px;
+    }
+  </style>
+</head>
+<body>
+  <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-4-values-with-rounded-corners-expected.png b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-4-values-with-rounded-corners-expected.png
new file mode 100644
index 0000000..2786077
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-4-values-with-rounded-corners-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-4-values-with-rounded-corners.html b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-4-values-with-rounded-corners.html
new file mode 100644
index 0000000..0fb7b3f
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/4-3-border-width-4-values-with-rounded-corners.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!--
+ | Setting 4 different width values for a rounded corners border.
+ |   https://www.w3.org/TR/css3-background/#the-border-width
+ -->
+<html>
+<head>
+  <style>
+    div {
+      border: solid #00FFFF;
+      border-width: 10px 50px 30px 80px;
+      border-radius: 50%;
+      height: 200px;
+      width: 400px;
+    }
+  </style>
+</head>
+<body>
+  <div></div>
+</body>
+</html>
diff --git a/src/cobalt/layout_tests/testdata/css3-background/layout_tests.txt b/src/cobalt/layout_tests/testdata/css3-background/layout_tests.txt
index 03230b9..9b39a9e 100644
--- a/src/cobalt/layout_tests/testdata/css3-background/layout_tests.txt
+++ b/src/cobalt/layout_tests/testdata/css3-background/layout_tests.txt
@@ -73,6 +73,16 @@
 4-0-border-width-with-solid-border-style
 4-0-different-border-styles-with-different-border-widths
 4-0-different-border-widths-with-solid-border-style
+4-1-border-color-2-values-with-rounded-corners
+4-1-border-color-3-values-with-rounded-corners
+4-1-border-color-4-values-with-different-rounded-corners
+4-1-border-color-4-values-with-different-rounded-corners-and-different-border-widths
+4-1-border-color-4-values-with-rounded-corners
+4-1-border-color-4-values-with-rounded-corners-and-different-border-widths
+4-3-border-width-2-values-with-rounded-corners
+4-3-border-width-3-values-with-rounded-corners
+4-3-border-width-4-values-with-different-rounded-corners
+4-3-border-width-4-values-with-rounded-corners
 5-0-border-radius-2-values-with-background-color
 5-0-border-radius-2-values-with-border-only
 5-0-border-radius-3-values-with-background-color
diff --git a/src/cobalt/layout_tests/web_platform_test_parser.cc b/src/cobalt/layout_tests/web_platform_test_parser.cc
index 83dc8bb..68e7185 100644
--- a/src/cobalt/layout_tests/web_platform_test_parser.cc
+++ b/src/cobalt/layout_tests/web_platform_test_parser.cc
@@ -110,7 +110,7 @@
     bool success = global_environment->EvaluateScript(
         script::SourceCode::CreateSourceCode(
             precondition, base::SourceLocation(__FILE__, __LINE__, 1)),
-        &result, false /*mute_errors*/);
+        false /*mute_errors*/, &result);
 
     if (!success) {
       DLOG(ERROR) << "Failed to evaluate precondition: "
diff --git a/src/cobalt/layout_tests/web_platform_tests.cc b/src/cobalt/layout_tests/web_platform_tests.cc
index 2b0a60a..2199ea1 100644
--- a/src/cobalt/layout_tests/web_platform_tests.cc
+++ b/src/cobalt/layout_tests/web_platform_tests.cc
@@ -46,23 +46,22 @@
  public:
   CspDelegatePermissive(
       scoped_ptr<dom::CspViolationReporter> violation_reporter, const GURL& url,
-      const std::string& location_policy, csp::CSPHeaderPolicy require_csp,
+      csp::CSPHeaderPolicy require_csp,
       const base::Closure& policy_changed_callback)
-      : dom::CspDelegateSecure(violation_reporter.Pass(), url, location_policy,
-                               require_csp, policy_changed_callback) {
+      : dom::CspDelegateSecure(violation_reporter.Pass(), url, require_csp,
+                               policy_changed_callback) {
     // Lies, but some checks in our parent require this.
     was_header_received_ = true;
   }
 
   static CspDelegate* Create(
       scoped_ptr<dom::CspViolationReporter> violation_reporter, const GURL& url,
-      const std::string& location_policy, csp::CSPHeaderPolicy require_csp,
+      csp::CSPHeaderPolicy require_csp,
       const base::Closure& policy_changed_callback,
       int insecure_allowed_token) {
     UNREFERENCED_PARAMETER(insecure_allowed_token);
     return new CspDelegatePermissive(violation_reporter.Pass(), url,
-                                     location_policy, require_csp,
-                                     policy_changed_callback);
+                                     require_csp, policy_changed_callback);
   }
 
   bool OnReceiveHeaders(const csp::ResponseHeaders& headers) OVERRIDE {
@@ -160,6 +159,8 @@
   options.output_resolution_override = kDefaultViewportSize;
   scoped_ptr<media::MediaModule> media_module(
       media::MediaModule::Create(NULL, &resource_provider, options));
+  scoped_ptr<media::CanPlayTypeHandler> can_play_type_handler(
+      media::MediaModule::CreateCanPlayTypeHandler());
 
   dom::CspDelegateFactory::GetInstance()->OverrideCreator(
       dom::kCspEnforcementEnable, CspDelegatePermissive::Create);
@@ -179,9 +180,9 @@
                  MessageLoop::current()),
       base::Bind(&WebModuleErrorCallback, &run_loop, MessageLoop::current()),
       browser::WebModule::CloseCallback() /* window_close_callback */,
-      base::Closure() /* window_minimize_callback */, media_module.get(),
-      &network_module, kDefaultViewportSize, 1.f, &resource_provider, 60.0f,
-      web_module_options);
+      base::Closure() /* window_minimize_callback */,
+      can_play_type_handler.get(), media_module.get(), &network_module,
+      kDefaultViewportSize, 1.f, &resource_provider, 60.0f, web_module_options);
   run_loop.Run();
   const std::string extract_results =
       "document.getElementById(\"__testharness__results__\").textContent;";
@@ -324,17 +325,15 @@
 
 INSTANTIATE_TEST_CASE_P(
     fetch, WebPlatformTest,
-    ::testing::ValuesIn(EnumerateWebPlatformTests("fetch",
-        "'fetch' in this")));
+    ::testing::ValuesIn(EnumerateWebPlatformTests("fetch", "'fetch' in this")));
 
 INSTANTIATE_TEST_CASE_P(
     mediasession, WebPlatformTest,
     ::testing::ValuesIn(EnumerateWebPlatformTests("mediasession")));
 
-INSTANTIATE_TEST_CASE_P(
-    streams, WebPlatformTest,
-    ::testing::ValuesIn(EnumerateWebPlatformTests("streams",
-        "'ReadableStream' in this")));
+INSTANTIATE_TEST_CASE_P(streams, WebPlatformTest,
+                        ::testing::ValuesIn(EnumerateWebPlatformTests(
+                            "streams", "'ReadableStream' in this")));
 
 INSTANTIATE_TEST_CASE_P(
     cobalt_special, WebPlatformTest,
diff --git a/src/cobalt/loader/decoder.h b/src/cobalt/loader/decoder.h
index 1f51912..6e08643 100644
--- a/src/cobalt/loader/decoder.h
+++ b/src/cobalt/loader/decoder.h
@@ -69,7 +69,7 @@
 
   // Provides textdecoder with last url to prevent security leak if resource is
   // cross-origin.
-  virtual void SetLastURLOrigin(const loader::Origin&) {}
+  virtual void SetLastURLOrigin(const Origin&) {}
 };
 
 }  // namespace loader
diff --git a/src/cobalt/loader/fetcher.h b/src/cobalt/loader/fetcher.h
index 6ce28cf..9288081 100644
--- a/src/cobalt/loader/fetcher.h
+++ b/src/cobalt/loader/fetcher.h
@@ -26,6 +26,13 @@
 namespace cobalt {
 namespace loader {
 
+// https://fetch.spec.whatwg.org/#concept-request-mode
+// Right now Cobalt only needs two modes.
+enum RequestMode {
+  kNoCORSMode,
+  kCORSMode,
+};
+
 class Fetcher {
  public:
   class Handler {
@@ -64,7 +71,7 @@
   // Concrete Fetcher subclass should start fetching immediately in constructor.
   explicit Fetcher(Handler* handler) : handler_(handler) {}
 
-  const loader::Origin& last_url_origin() { return last_url_origin_; }
+  const Origin& last_url_origin() { return last_url_origin_; }
 
   // Concrete Fetcher subclass should cancel fetching in destructor.
   virtual ~Fetcher() = 0;
@@ -73,7 +80,7 @@
   Handler* handler() const { return handler_; }
 
   // used by html elements to check if resource is cross-origin.
-  loader::Origin last_url_origin_;
+  Origin last_url_origin_;
 
  private:
   Handler* handler_;
diff --git a/src/cobalt/loader/fetcher_factory.cc b/src/cobalt/loader/fetcher_factory.cc
index 9776365..d582d15 100644
--- a/src/cobalt/loader/fetcher_factory.cc
+++ b/src/cobalt/loader/fetcher_factory.cc
@@ -92,12 +92,14 @@
 
 scoped_ptr<Fetcher> FetcherFactory::CreateFetcher(const GURL& url,
                                                   Fetcher::Handler* handler) {
-  return CreateSecureFetcher(url, csp::SecurityCallback(), handler).Pass();
+  return CreateSecureFetcher(url, csp::SecurityCallback(), kNoCORSMode,
+                             Origin(), handler)
+      .Pass();
 }
 
 scoped_ptr<Fetcher> FetcherFactory::CreateSecureFetcher(
     const GURL& url, const csp::SecurityCallback& url_security_callback,
-    Fetcher::Handler* handler) {
+    RequestMode request_mode, const Origin& origin, Fetcher::Handler* handler) {
   DLOG(INFO) << "Fetching: " << ClipUrl(url, 60);
 
   if (!url.is_valid()) {
@@ -111,8 +113,8 @@
       network_module_) {
     NetFetcher::Options options;
     return scoped_ptr<Fetcher>(new NetFetcher(url, url_security_callback,
-                                              handler, network_module_,
-                                              options));
+                                              handler, network_module_, options,
+                                              request_mode, origin));
   }
 
   if (url.SchemeIs("blob") && !blob_resolver_.is_null()) {
diff --git a/src/cobalt/loader/fetcher_factory.h b/src/cobalt/loader/fetcher_factory.h
index a367df7..1278350 100644
--- a/src/cobalt/loader/fetcher_factory.h
+++ b/src/cobalt/loader/fetcher_factory.h
@@ -50,6 +50,7 @@
 
   scoped_ptr<Fetcher> CreateSecureFetcher(
       const GURL& url, const csp::SecurityCallback& url_security_callback,
+      RequestMode request_mode, const Origin& origin,
       Fetcher::Handler* handler);
 
   network::NetworkModule* network_module() const { return network_module_; }
diff --git a/src/cobalt/loader/loader.cc b/src/cobalt/loader/loader.cc
index 58c1ca9..bc07421 100644
--- a/src/cobalt/loader/loader.cc
+++ b/src/cobalt/loader/loader.cc
@@ -57,7 +57,6 @@
     decoder_->DecodeChunkPassed(data.Pass());
   }
   void OnDone(Fetcher* fetcher) OVERRIDE {
-    UNREFERENCED_PARAMETER(fetcher);
     DCHECK(fetcher);
     decoder_->SetLastURLOrigin(fetcher->last_url_origin());
     decoder_->Finish();
diff --git a/src/cobalt/loader/loader_factory.cc b/src/cobalt/loader/loader_factory.cc
index d65a87b..c5c9890 100644
--- a/src/cobalt/loader/loader_factory.cc
+++ b/src/cobalt/loader/loader_factory.cc
@@ -43,11 +43,12 @@
 scoped_ptr<Loader> LoaderFactory::CreateImageLoader(
     const GURL& url, const csp::SecurityCallback& url_security_callback,
     const image::ImageDecoder::SuccessCallback& success_callback,
-    const image::ImageDecoder::ErrorCallback& error_callback) {
+    const image::ImageDecoder::ErrorCallback& error_callback,
+    const Origin& origin) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   scoped_ptr<Loader> loader(new Loader(
-      MakeFetcherCreator(url, url_security_callback),
+      MakeFetcherCreator(url, url_security_callback, kNoCORSMode, origin),
       scoped_ptr<Decoder>(new image::ThreadedImageDecoderProxy(
           resource_provider_, success_callback, error_callback,
           load_thread_.message_loop())),
@@ -61,11 +62,12 @@
 scoped_ptr<Loader> LoaderFactory::CreateTypefaceLoader(
     const GURL& url, const csp::SecurityCallback& url_security_callback,
     const font::TypefaceDecoder::SuccessCallback& success_callback,
-    const font::TypefaceDecoder::ErrorCallback& error_callback) {
+    const font::TypefaceDecoder::ErrorCallback& error_callback,
+    const Origin& origin) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   scoped_ptr<Loader> loader(new Loader(
-      MakeFetcherCreator(url, url_security_callback),
+      MakeFetcherCreator(url, url_security_callback, kCORSMode, origin),
       scoped_ptr<Decoder>(new font::TypefaceDecoder(
           resource_provider_, success_callback, error_callback)),
       error_callback,
@@ -79,11 +81,12 @@
 scoped_ptr<Loader> LoaderFactory::CreateMeshLoader(
     const GURL& url, const csp::SecurityCallback& url_security_callback,
     const mesh::MeshDecoder::SuccessCallback& success_callback,
-    const mesh::MeshDecoder::ErrorCallback& error_callback) {
+    const mesh::MeshDecoder::ErrorCallback& error_callback,
+    const Origin& origin) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   scoped_ptr<Loader> loader(new Loader(
-      MakeFetcherCreator(url, url_security_callback),
+      MakeFetcherCreator(url, url_security_callback, kNoCORSMode, origin),
       scoped_ptr<Decoder>(new mesh::MeshDecoder(
           resource_provider_, success_callback, error_callback)),
       error_callback,
@@ -94,12 +97,13 @@
 }
 
 Loader::FetcherCreator LoaderFactory::MakeFetcherCreator(
-    const GURL& url, const csp::SecurityCallback& url_security_callback) {
+    const GURL& url, const csp::SecurityCallback& url_security_callback,
+    RequestMode request_mode, const Origin& origin) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   return base::Bind(&FetcherFactory::CreateSecureFetcher,
                     base::Unretained(fetcher_factory_), url,
-                    url_security_callback);
+                    url_security_callback, request_mode, origin);
 }
 
 void LoaderFactory::Suspend() {
diff --git a/src/cobalt/loader/loader_factory.h b/src/cobalt/loader/loader_factory.h
index 4cd8b25..019bc45 100644
--- a/src/cobalt/loader/loader_factory.h
+++ b/src/cobalt/loader/loader_factory.h
@@ -43,19 +43,22 @@
   scoped_ptr<Loader> CreateImageLoader(
       const GURL& url, const csp::SecurityCallback& url_security_callback,
       const image::ImageDecoder::SuccessCallback& success_callback,
-      const image::ImageDecoder::ErrorCallback& error_callback);
+      const image::ImageDecoder::ErrorCallback& error_callback,
+      const Origin& origin);
 
   // Creates a loader that fetches and decodes a render_tree::Typeface.
   scoped_ptr<Loader> CreateTypefaceLoader(
       const GURL& url, const csp::SecurityCallback& url_security_callback,
       const font::TypefaceDecoder::SuccessCallback& success_callback,
-      const font::TypefaceDecoder::ErrorCallback& error_callback);
+      const font::TypefaceDecoder::ErrorCallback& error_callback,
+      const Origin& orgin);
 
   // Creates a loader that fetches and decodes a Mesh.
   scoped_ptr<Loader> CreateMeshLoader(
       const GURL& url, const csp::SecurityCallback& url_security_callback,
       const mesh::MeshDecoder::SuccessCallback& success_callback,
-      const mesh::MeshDecoder::ErrorCallback& error_callback);
+      const mesh::MeshDecoder::ErrorCallback& error_callback,
+      const Origin& origin);
 
   // Clears out the loader factory's resource provider, aborting any in-progress
   // loads.
@@ -70,7 +73,8 @@
   void OnLoaderDestroyed(Loader* loader);
 
   Loader::FetcherCreator MakeFetcherCreator(
-      const GURL& url, const csp::SecurityCallback& url_security_callback);
+      const GURL& url, const csp::SecurityCallback& url_security_callback,
+      RequestMode request_mode, const Origin& origin);
 
   // Ensures that the LoaderFactory methods are only called from the same
   // thread.
diff --git a/src/cobalt/loader/loader_test.cc b/src/cobalt/loader/loader_test.cc
index 0c8d736..46cf4fe 100644
--- a/src/cobalt/loader/loader_test.cc
+++ b/src/cobalt/loader/loader_test.cc
@@ -41,7 +41,7 @@
  public:
   explicit TextDecoderCallback(base::RunLoop* run_loop) : run_loop_(run_loop) {}
 
-  void OnDone(const std::string& text, const loader::Origin&) {
+  void OnDone(const std::string& text, const Origin&) {
     text_ = text;
     MessageLoop::current()->PostTask(FROM_HERE, run_loop_->QuitClosure());
   }
diff --git a/src/cobalt/loader/mock_loader_factory.h b/src/cobalt/loader/mock_loader_factory.h
index c680190..d6fa51b 100644
--- a/src/cobalt/loader/mock_loader_factory.h
+++ b/src/cobalt/loader/mock_loader_factory.h
@@ -51,7 +51,7 @@
   scoped_ptr<Loader> CreateImageLoader(
       const GURL& url, const csp::SecurityCallback& url_security_callback,
       const image::ImageDecoder::SuccessCallback& success_callback,
-      const image::ImageDecoder::ErrorCallback& error_callback) {
+      const image::ImageDecoder::ErrorCallback& error_callback, const Origin&) {
     return scoped_ptr<Loader>(
         CreateImageLoaderMock(url, url_security_callback, success_callback,
                               error_callback));
@@ -60,7 +60,8 @@
   scoped_ptr<Loader> CreateTypefaceLoader(
       const GURL& url, const csp::SecurityCallback& url_security_callback,
       const font::TypefaceDecoder::SuccessCallback& success_callback,
-      const font::TypefaceDecoder::ErrorCallback& error_callback) {
+      const font::TypefaceDecoder::ErrorCallback& error_callback,
+      const Origin&) {
     return scoped_ptr<Loader>(
         CreateTypefaceLoaderMock(url, url_security_callback, success_callback,
                                  error_callback));
diff --git a/src/cobalt/loader/net_fetcher.cc b/src/cobalt/loader/net_fetcher.cc
index 5c904ed..29a21c5 100644
--- a/src/cobalt/loader/net_fetcher.cc
+++ b/src/cobalt/loader/net_fetcher.cc
@@ -17,6 +17,7 @@
 #include <string>
 
 #include "base/stringprintf.h"
+#include "cobalt/loader/cors_preflight.h"
 #include "cobalt/network/network_module.h"
 #include "net/url_request/url_fetcher.h"
 #if defined(OS_STARBOARD)
@@ -72,15 +73,23 @@
                        const csp::SecurityCallback& security_callback,
                        Handler* handler,
                        const network::NetworkModule* network_module,
-                       const Options& options)
+                       const Options& options, RequestMode request_mode,
+                       const Origin& origin)
     : Fetcher(handler),
       security_callback_(security_callback),
       ALLOW_THIS_IN_INITIALIZER_LIST(start_callback_(
-          base::Bind(&NetFetcher::Start, base::Unretained(this)))) {
+          base::Bind(&NetFetcher::Start, base::Unretained(this)))),
+      request_cross_origin_(false),
+      origin_(origin) {
   url_fetcher_.reset(
       net::URLFetcher::Create(url, options.request_method, this));
   url_fetcher_->SetRequestContext(network_module->url_request_context_getter());
   url_fetcher_->DiscardResponse();
+  if (request_mode == kCORSMode && !url.SchemeIs("data") &&
+      origin != Origin(url)) {
+    request_cross_origin_ = true;
+    url_fetcher_->AddExtraRequestHeader("Origin:" + origin.SerializedOrigin());
+  }
 
   // Delay the actual start until this function is complete. Otherwise we might
   // call handler's callbacks at an unexpected time- e.g. receiving OnError()
@@ -124,6 +133,19 @@
       return HandleError(msg).InvalidateThis();
     }
   }
+
+  // net::URLFetcher can not guarantee GetResponseHeaders() always return
+  // non-null pointer.
+  if (request_cross_origin_ &&
+      (!source->GetResponseHeaders() ||
+       !CORSPreflight::CORSCheck(*source->GetResponseHeaders(),
+                                 origin_.SerializedOrigin(), false))) {
+    std::string msg(base::StringPrintf(
+        "Cross origin request to %s was rejected by Same-Origin-Policy",
+        source->GetURL().spec().c_str()));
+    return HandleError(msg).InvalidateThis();
+  }
+
   last_url_origin_ = Origin(source->GetURL());
 }
 
diff --git a/src/cobalt/loader/net_fetcher.h b/src/cobalt/loader/net_fetcher.h
index 6f1f5f5..baaae2c 100644
--- a/src/cobalt/loader/net_fetcher.h
+++ b/src/cobalt/loader/net_fetcher.h
@@ -44,7 +44,8 @@
 
   NetFetcher(const GURL& url, const csp::SecurityCallback& security_callback,
              Handler* handler, const network::NetworkModule* network_module,
-             const Options& options);
+             const Options& options, RequestMode request_mode,
+             const Origin& origin);
   ~NetFetcher() OVERRIDE;
 
   // net::URLFetcherDelegate interface
@@ -86,6 +87,12 @@
   // after being constructed, but before Start() runs.
   base::CancelableClosure start_callback_;
 
+  // True if request mode is CORS and request URL's origin is different from
+  // request's origin.
+  bool request_cross_origin_;
+  // The request's origin.
+  Origin origin_;
+
   DISALLOW_COPY_AND_ASSIGN(NetFetcher);
 };
 
diff --git a/src/cobalt/loader/resource_cache.h b/src/cobalt/loader/resource_cache.h
index 024cc55..805a0c5 100644
--- a/src/cobalt/loader/resource_cache.h
+++ b/src/cobalt/loader/resource_cache.h
@@ -68,7 +68,8 @@
   typedef base::Callback<scoped_ptr<Loader>(
       const GURL&, const csp::SecurityCallback&,
       const base::Callback<void(const scoped_refptr<ResourceType>&)>&,
-      const base::Callback<void(const std::string&)>&)> CreateLoaderFunction;
+      const base::Callback<void(const std::string&)>&, const Origin&)>
+      CreateLoaderFunction;
 
   // This class can be used to attach success or error callbacks to
   // CachedResource objects that are executed when the resource finishes
@@ -100,7 +101,7 @@
   CachedResource(const GURL& url,
                  const csp::SecurityCallback& security_callback,
                  const CreateLoaderFunction& create_loader_function,
-                 ResourceCacheType* resource_cache);
+                 ResourceCacheType* resource_cache, const Origin& origin);
 
   // Resource is available. CachedResource is a wrapper of the resource
   // and there is no need to fetch or load this resource again. |loader_|
@@ -214,7 +215,7 @@
 CachedResource<CacheType>::CachedResource(
     const GURL& url, const csp::SecurityCallback& security_callback,
     const CreateLoaderFunction& create_loader_function,
-    ResourceCacheType* resource_cache)
+    ResourceCacheType* resource_cache, const Origin& origin)
     : url_(url),
       resource_cache_(resource_cache),
       completion_callbacks_enabled_(false) {
@@ -223,7 +224,8 @@
   loader_ = create_loader_function.Run(
       url, security_callback,
       base::Bind(&CachedResource::OnLoadingSuccess, base::Unretained(this)),
-      base::Bind(&CachedResource::OnLoadingError, base::Unretained(this)));
+      base::Bind(&CachedResource::OnLoadingError, base::Unretained(this)),
+      origin);
 }
 
 template <typename CacheType>
@@ -405,7 +407,8 @@
   // |unreference_cached_resource_map_|, creates a CachedResource with a loader
   // for it. If the CachedResource is in the cache map, return the
   // CachedResource or wrap the resource if necessary.
-  scoped_refptr<CachedResourceType> CreateCachedResource(const GURL& url);
+  scoped_refptr<CachedResourceType> CreateCachedResource(const GURL& url,
+                                                         const Origin& origin);
 
   // Set a callback that the loader will query to determine if the URL is safe
   // according to our document's security policy.
@@ -568,7 +571,8 @@
 
 template <typename CacheType>
 scoped_refptr<CachedResource<CacheType> >
-ResourceCache<CacheType>::CreateCachedResource(const GURL& url) {
+ResourceCache<CacheType>::CreateCachedResource(const GURL& url,
+                                               const Origin& origin) {
   DCHECK(resource_cache_thread_checker_.CalledOnValidThread());
   DCHECK(url.is_valid());
 
@@ -609,7 +613,7 @@
 
   // Create the cached resource and fetch its resource based on the url.
   scoped_refptr<CachedResourceType> cached_resource(new CachedResourceType(
-      url, security_callback_, create_loader_function_, this));
+      url, security_callback_, create_loader_function_, this, origin));
   cached_resource_map_.insert(
       std::make_pair(url.spec(), cached_resource.get()));
 
diff --git a/src/cobalt/loader/sync_loader.cc b/src/cobalt/loader/sync_loader.cc
index e8d45f9..e26698e 100644
--- a/src/cobalt/loader/sync_loader.cc
+++ b/src/cobalt/loader/sync_loader.cc
@@ -72,7 +72,8 @@
     decoder_->DecodeChunk(data, size);
   }
   void OnDone(Fetcher* fetcher) OVERRIDE {
-    UNREFERENCED_PARAMETER(fetcher);
+    DCHECK(fetcher);
+    decoder_->SetLastURLOrigin(fetcher->last_url_origin());
     decoder_->Finish();
     loader_on_thread_->Signal();
   }
diff --git a/src/cobalt/loader/text_decoder_test.cc b/src/cobalt/loader/text_decoder_test.cc
index 90e8824..b6ddb19 100644
--- a/src/cobalt/loader/text_decoder_test.cc
+++ b/src/cobalt/loader/text_decoder_test.cc
@@ -23,13 +23,12 @@
 namespace {
 
 struct TextDecoderCallback {
-  void Callback(const std::string& value,
-                const loader::Origin& last_url_origin) {
+  void Callback(const std::string& value, const Origin& last_url_origin) {
     text = value;
     last_url_origin_ = last_url_origin;
   }
   std::string text;
-  loader::Origin last_url_origin_;
+  Origin last_url_origin_;
 };
 
 }  // namespace
diff --git a/src/cobalt/media/base/audio_block_fifo.cc b/src/cobalt/media/base/audio_block_fifo.cc
deleted file mode 100644
index b2ac5da..0000000
--- a/src/cobalt/media/base/audio_block_fifo.cc
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_block_fifo.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-AudioBlockFifo::AudioBlockFifo(int channels, int frames, int blocks)
-    : channels_(channels),
-      block_frames_(frames),
-      write_block_(0),
-      read_block_(0),
-      available_blocks_(0),
-      write_pos_(0) {
-  IncreaseCapacity(blocks);
-}
-
-AudioBlockFifo::~AudioBlockFifo() {}
-
-void AudioBlockFifo::Push(const void* source, int frames,
-                          int bytes_per_sample) {
-  DCHECK(source);
-  DCHECK_GT(frames, 0);
-  DCHECK_GT(bytes_per_sample, 0);
-  DCHECK_LT(available_blocks_, static_cast<int>(audio_blocks_.size()));
-  CHECK_LE(frames, GetUnfilledFrames());
-
-  const uint8_t* source_ptr = static_cast<const uint8_t*>(source);
-  int frames_to_push = frames;
-  while (frames_to_push) {
-    // Get the current write block.
-    AudioBus* current_block = audio_blocks_[write_block_];
-
-    // Figure out what segment sizes we need when adding the new content to
-    // the FIFO.
-    const int push_frames =
-        std::min(block_frames_ - write_pos_, frames_to_push);
-
-    // Deinterleave the content to the FIFO and update the |write_pos_|.
-    current_block->FromInterleavedPartial(source_ptr, write_pos_, push_frames,
-                                          bytes_per_sample);
-    write_pos_ = (write_pos_ + push_frames) % block_frames_;
-    if (!write_pos_) {
-      // The current block is completely filled, increment |write_block_| and
-      // |available_blocks_|.
-      write_block_ = (write_block_ + 1) % audio_blocks_.size();
-      ++available_blocks_;
-    }
-
-    source_ptr += push_frames * bytes_per_sample * channels_;
-    frames_to_push -= push_frames;
-    DCHECK_GE(frames_to_push, 0);
-  }
-}
-
-const AudioBus* AudioBlockFifo::Consume() {
-  DCHECK(available_blocks_);
-  AudioBus* audio_bus = audio_blocks_[read_block_];
-  read_block_ = (read_block_ + 1) % audio_blocks_.size();
-  --available_blocks_;
-  return audio_bus;
-}
-
-void AudioBlockFifo::Clear() {
-  write_pos_ = 0;
-  write_block_ = 0;
-  read_block_ = 0;
-  available_blocks_ = 0;
-}
-
-int AudioBlockFifo::GetAvailableFrames() const {
-  return available_blocks_ * block_frames_ + write_pos_;
-}
-
-int AudioBlockFifo::GetUnfilledFrames() const {
-  const int unfilled_frames =
-      (audio_blocks_.size() - available_blocks_ * block_frames_ - write_pos_);
-  DCHECK_GE(unfilled_frames, 0);
-  return unfilled_frames;
-}
-
-void AudioBlockFifo::IncreaseCapacity(int blocks) {
-  DCHECK_GT(blocks, 0);
-
-  // Create |blocks| of audio buses and insert them to the containers.
-  audio_blocks_.reserve(audio_blocks_.size() + blocks);
-
-  const int original_size = audio_blocks_.size();
-  for (int i = 0; i < blocks; ++i) {
-    audio_blocks_.push_back(
-        AudioBus::Create(channels_, block_frames_).release());
-  }
-
-  if (!original_size) return;
-
-  std::rotate(audio_blocks_.begin() + read_block_,
-              audio_blocks_.begin() + original_size, audio_blocks_.end());
-
-  // Update the write pointer if it is on top of the new inserted blocks.
-  if (write_block_ >= read_block_) write_block_ += blocks;
-
-  // Update the read pointers correspondingly.
-  read_block_ += blocks;
-
-  DCHECK_LT(read_block_, static_cast<int>(audio_blocks_.size()));
-  DCHECK_LT(write_block_, static_cast<int>(audio_blocks_.size()));
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_block_fifo.h b/src/cobalt/media/base/audio_block_fifo.h
deleted file mode 100644
index 5eb2bdf..0000000
--- a/src/cobalt/media/base/audio_block_fifo.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_BLOCK_FIFO_H_
-#define COBALT_MEDIA_BASE_AUDIO_BLOCK_FIFO_H_
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_vector.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "cobalt/media/base/media_export.h"
-
-namespace cobalt {
-namespace media {
-
-// First-in first-out container for AudioBus elements.
-// The FIFO is composed of blocks of AudioBus elements, it accepts interleaved
-// data as input and will deinterleave it into the FIFO, and it only allows
-// consuming a whole block of AudioBus element.
-// This class is thread-unsafe.
-class MEDIA_EXPORT AudioBlockFifo {
- public:
-  // Creates a new AudioBlockFifo and allocates |blocks| memory, each block
-  // of memory can store |channels| of length |frames| data.
-  AudioBlockFifo(int channels, int frames, int blocks);
-  virtual ~AudioBlockFifo();
-
-  // Pushes interleaved audio data from |source| to the FIFO.
-  // The method will deinterleave the data into a audio bus.
-  // Push() will crash if the allocated space is insufficient.
-  void Push(const void* source, int frames, int bytes_per_sample);
-
-  // Consumes a block of audio from the FIFO.  Returns an AudioBus which
-  // contains the consumed audio data to avoid copying.
-  // Consume() will crash if the FIFO does not contain a block of data.
-  const AudioBus* Consume();
-
-  // Empties the FIFO without deallocating any memory.
-  void Clear();
-
-  // Number of available block of memory ready to be consumed in the FIFO.
-  int available_blocks() const { return available_blocks_; }
-
-  // Number of available frames of data in the FIFO.
-  int GetAvailableFrames() const;
-
-  // Number of unfilled frames in the whole FIFO.
-  int GetUnfilledFrames() const;
-
-  // Dynamically increase |blocks| of memory to the FIFO.
-  void IncreaseCapacity(int blocks);
-
- private:
-  // The actual FIFO is a vector of audio buses.
-  ScopedVector<AudioBus> audio_blocks_;
-
-  // Number of channels in AudioBus.
-  const int channels_;
-
-  // Maximum number of frames of data one block of memory can contain.
-  // This value is set by |frames| in the constructor.
-  const int block_frames_;
-
-  // Used to keep track which block of memory to be written.
-  int write_block_;
-
-  // Used to keep track which block of memory to be consumed.
-  int read_block_;
-
-  // Number of available blocks of memory to be consumed.
-  int available_blocks_;
-
-  // Current write position in the current written block.
-  int write_pos_;
-
-  DISALLOW_COPY_AND_ASSIGN(AudioBlockFifo);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_BLOCK_FIFO_H_
diff --git a/src/cobalt/media/base/audio_buffer.cc b/src/cobalt/media/base/audio_buffer.cc
deleted file mode 100644
index dec746f..0000000
--- a/src/cobalt/media/base/audio_buffer.cc
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_buffer.h"
-
-#include <cmath>
-#include <limits>
-
-#include "base/logging.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "cobalt/media/base/limits.h"
-#include "cobalt/media/base/timestamp_constants.h"
-#include "starboard/memory.h"
-
-namespace cobalt {
-namespace media {
-
-static base::TimeDelta CalculateDuration(int frames, double sample_rate) {
-  DCHECK_GT(sample_rate, 0);
-  return base::TimeDelta::FromMicroseconds(
-      frames * base::Time::kMicrosecondsPerSecond / sample_rate);
-}
-
-AudioBuffer::AudioBuffer(SampleFormat sample_format,
-                         ChannelLayout channel_layout, int channel_count,
-                         int sample_rate, int frame_count, bool create_buffer,
-                         const uint8_t* const* data,
-                         const base::TimeDelta timestamp)
-    : sample_format_(sample_format),
-      channel_layout_(channel_layout),
-      channel_count_(channel_count),
-      sample_rate_(sample_rate),
-      adjusted_frame_count_(frame_count),
-      end_of_stream_(!create_buffer && data == NULL && frame_count == 0),
-      timestamp_(timestamp),
-      duration_(end_of_stream_
-                    ? base::TimeDelta()
-                    : CalculateDuration(adjusted_frame_count_, sample_rate_)),
-      data_size_(0) {
-  CHECK_GE(channel_count_, 0);
-  CHECK_LE(channel_count_, limits::kMaxChannels);
-  CHECK_GE(frame_count, 0);
-  DCHECK(channel_layout == CHANNEL_LAYOUT_DISCRETE ||
-         ChannelLayoutToChannelCount(channel_layout) == channel_count);
-
-  int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format);
-  DCHECK_LE(bytes_per_channel, kChannelAlignment);
-
-  // Empty buffer?
-  if (!create_buffer) return;
-
-  int data_size_per_channel = frame_count * bytes_per_channel;
-  if (IsPlanar(sample_format)) {
-    // Planar data, so need to allocate buffer for each channel.
-    // Determine per channel data size, taking into account alignment.
-    int block_size_per_channel =
-        (data_size_per_channel + kChannelAlignment - 1) &
-        ~(kChannelAlignment - 1);
-    DCHECK_GE(block_size_per_channel, data_size_per_channel);
-
-    // Allocate a contiguous buffer for all the channel data.
-    data_size_ = channel_count_ * block_size_per_channel;
-    data_.reset(static_cast<uint8_t*>(
-        base::AlignedAlloc(data_size_, kChannelAlignment)));
-    channel_data_.reserve(channel_count_);
-
-    // Copy each channel's data into the appropriate spot.
-    for (int i = 0; i < channel_count_; ++i) {
-      channel_data_.push_back(data_.get() + i * block_size_per_channel);
-      if (data) SbMemoryCopy(channel_data_[i], data[i], data_size_per_channel);
-    }
-    return;
-  }
-
-  // Remaining formats are interleaved data.
-  DCHECK(IsInterleaved(sample_format)) << sample_format_;
-  // Allocate our own buffer and copy the supplied data into it. Buffer must
-  // contain the data for all channels.
-  data_size_ = data_size_per_channel * channel_count_;
-  data_.reset(
-      static_cast<uint8_t*>(base::AlignedAlloc(data_size_, kChannelAlignment)));
-  channel_data_.reserve(1);
-  channel_data_.push_back(data_.get());
-  if (data) SbMemoryCopy(data_.get(), data[0], data_size_);
-}
-
-AudioBuffer::~AudioBuffer() {}
-
-// static
-scoped_refptr<AudioBuffer> AudioBuffer::CopyFrom(
-    SampleFormat sample_format, ChannelLayout channel_layout, int channel_count,
-    int sample_rate, int frame_count, const uint8_t* const* data,
-    const base::TimeDelta timestamp) {
-  // If you hit this CHECK you likely have a bug in a demuxer. Go fix it.
-  CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
-  CHECK(data[0]);
-  return make_scoped_refptr(
-      new AudioBuffer(sample_format, channel_layout, channel_count, sample_rate,
-                      frame_count, true, data, timestamp));
-}
-
-// static
-scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer(
-    SampleFormat sample_format, ChannelLayout channel_layout, int channel_count,
-    int sample_rate, int frame_count) {
-  CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
-  return make_scoped_refptr(
-      new AudioBuffer(sample_format, channel_layout, channel_count, sample_rate,
-                      frame_count, true, NULL, kNoTimestamp));
-}
-
-// static
-scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer(
-    ChannelLayout channel_layout, int channel_count, int sample_rate,
-    int frame_count, const base::TimeDelta timestamp) {
-  CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
-  // Since data == NULL, format doesn't matter.
-  return make_scoped_refptr(
-      new AudioBuffer(kSampleFormatF32, channel_layout, channel_count,
-                      sample_rate, frame_count, false, NULL, timestamp));
-}
-
-// static
-scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() {
-  return make_scoped_refptr(new AudioBuffer(kUnknownSampleFormat,
-                                            CHANNEL_LAYOUT_NONE, 0, 0, 0, false,
-                                            NULL, kNoTimestamp));
-}
-
-// Convert int16_t values in the range [INT16_MIN, INT16_MAX] to [-1.0, 1.0].
-inline float ConvertSample(int16_t value) {
-  return value * (value < 0 ? -1.0f / std::numeric_limits<int16_t>::min()
-                            : 1.0f / std::numeric_limits<int16_t>::max());
-}
-
-void AudioBuffer::AdjustSampleRate(int sample_rate) {
-  DCHECK(!end_of_stream_);
-  sample_rate_ = sample_rate;
-  duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_);
-}
-
-void AudioBuffer::ReadFrames(int frames_to_copy, int source_frame_offset,
-                             int dest_frame_offset, AudioBus* dest) {
-  // Deinterleave each channel (if necessary) and convert to 32bit
-  // floating-point with nominal range -1.0 -> +1.0 (if necessary).
-
-  // |dest| must have the same number of channels, and the number of frames
-  // specified must be in range.
-  DCHECK(!end_of_stream());
-  DCHECK_EQ(dest->channels(), channel_count_);
-  DCHECK_LE(source_frame_offset + frames_to_copy, adjusted_frame_count_);
-  DCHECK_LE(dest_frame_offset + frames_to_copy, dest->frames());
-
-  if (!data_) {
-    // Special case for an empty buffer.
-    dest->ZeroFramesPartial(dest_frame_offset, frames_to_copy);
-    return;
-  }
-
-  if (sample_format_ == kSampleFormatPlanarF32) {
-    // Format is planar float32. Copy the data from each channel as a block.
-    for (int ch = 0; ch < channel_count_; ++ch) {
-      const float* source_data =
-          reinterpret_cast<const float*>(channel_data_[ch]) +
-          source_frame_offset;
-      SbMemoryCopy(dest->channel(ch) + dest_frame_offset, source_data,
-                   sizeof(float) * frames_to_copy);
-    }
-    return;
-  }
-
-  if (sample_format_ == kSampleFormatPlanarS16) {
-    // Format is planar signed16. Convert each value into float and insert into
-    // output channel data.
-    for (int ch = 0; ch < channel_count_; ++ch) {
-      const int16_t* source_data =
-          reinterpret_cast<const int16_t*>(channel_data_[ch]) +
-          source_frame_offset;
-      float* dest_data = dest->channel(ch) + dest_frame_offset;
-      for (int i = 0; i < frames_to_copy; ++i) {
-        dest_data[i] = ConvertSample(source_data[i]);
-      }
-    }
-    return;
-  }
-
-  if (sample_format_ == kSampleFormatF32) {
-    // Format is interleaved float32. Copy the data into each channel.
-    const float* source_data = reinterpret_cast<const float*>(data_.get()) +
-                               source_frame_offset * channel_count_;
-    for (int ch = 0; ch < channel_count_; ++ch) {
-      float* dest_data = dest->channel(ch) + dest_frame_offset;
-      for (int i = 0, offset = ch; i < frames_to_copy;
-           ++i, offset += channel_count_) {
-        dest_data[i] = source_data[offset];
-      }
-    }
-    return;
-  }
-
-  // Remaining formats are integer interleaved data. Use the deinterleaving code
-  // in AudioBus to copy the data.
-  DCHECK(
-      sample_format_ == kSampleFormatU8 || sample_format_ == kSampleFormatS16 ||
-      sample_format_ == kSampleFormatS24 || sample_format_ == kSampleFormatS32);
-  int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_);
-  int frame_size = channel_count_ * bytes_per_channel;
-  const uint8_t* source_data = data_.get() + source_frame_offset * frame_size;
-  dest->FromInterleavedPartial(source_data, dest_frame_offset, frames_to_copy,
-                               bytes_per_channel);
-}
-
-void AudioBuffer::TrimStart(int frames_to_trim) {
-  CHECK_GE(frames_to_trim, 0);
-  CHECK_LE(frames_to_trim, adjusted_frame_count_);
-
-  TrimRange(0, frames_to_trim);
-}
-
-void AudioBuffer::TrimEnd(int frames_to_trim) {
-  CHECK_GE(frames_to_trim, 0);
-  CHECK_LE(frames_to_trim, adjusted_frame_count_);
-
-  // Adjust the number of frames and duration for this buffer.
-  adjusted_frame_count_ -= frames_to_trim;
-  duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_);
-}
-
-void AudioBuffer::TrimRange(int start, int end) {
-  CHECK_GE(start, 0);
-  CHECK_LE(end, adjusted_frame_count_);
-
-  const int frames_to_trim = end - start;
-  CHECK_GE(frames_to_trim, 0);
-  CHECK_LE(frames_to_trim, adjusted_frame_count_);
-
-  const int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_);
-  const int frames_to_copy = adjusted_frame_count_ - end;
-  if (frames_to_copy > 0) {
-    switch (sample_format_) {
-      case kSampleFormatPlanarS16:
-      case kSampleFormatPlanarF32:
-      case kSampleFormatPlanarS32:
-        // Planar data must be shifted per channel.
-        for (int ch = 0; ch < channel_count_; ++ch) {
-          SbMemoryMove(channel_data_[ch] + start * bytes_per_channel,
-                       channel_data_[ch] + end * bytes_per_channel,
-                       bytes_per_channel * frames_to_copy);
-        }
-        break;
-      case kSampleFormatU8:
-      case kSampleFormatS16:
-      case kSampleFormatS24:
-      case kSampleFormatS32:
-      case kSampleFormatF32: {
-        // Interleaved data can be shifted all at once.
-        const int frame_size = channel_count_ * bytes_per_channel;
-        SbMemoryMove(channel_data_[0] + start * frame_size,
-                     channel_data_[0] + end * frame_size,
-                     frame_size * frames_to_copy);
-        break;
-      }
-      case kUnknownSampleFormat:
-        NOTREACHED() << "Invalid sample format!";
-    }
-  } else {
-    CHECK_EQ(frames_to_copy, 0);
-  }
-
-  // Trim the leftover data off the end of the buffer and update duration.
-  TrimEnd(frames_to_trim);
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_buffer.h b/src/cobalt/media/base/audio_buffer.h
deleted file mode 100644
index a5e3d03..0000000
--- a/src/cobalt/media/base/audio_buffer.h
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_BUFFER_H_
-#define COBALT_MEDIA_BASE_AUDIO_BUFFER_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/aligned_memory.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/time.h"
-#include "cobalt/media/base/channel_layout.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/sample_format.h"
-#include "starboard/types.h"
-
-namespace mojo {
-template <typename T, typename U>
-struct TypeConverter;
-template <typename T>
-class StructPtr;
-};
-
-namespace cobalt {
-namespace media {
-class AudioBus;
-
-namespace mojom {
-class AudioBuffer;
-}
-
-// An audio buffer that takes a copy of the data passed to it, holds it, and
-// copies it into an AudioBus when needed. Also supports an end of stream
-// marker.
-class MEDIA_EXPORT AudioBuffer
-    : public base::RefCountedThreadSafe<AudioBuffer> {
- public:
-  // Alignment of each channel's data; this must match what ffmpeg expects
-  // (which may be 0, 16, or 32, depending on the processor). Selecting 32 in
-  // order to work on all processors.
-  enum { kChannelAlignment = 32 };
-
-  // Create an AudioBuffer whose channel data is copied from |data|. For
-  // interleaved data, only the first buffer is used. For planar data, the
-  // number of buffers must be equal to |channel_count|. |frame_count| is the
-  // number of frames in each buffer. |data| must not be null and |frame_count|
-  // must be >= 0.
-  static scoped_refptr<AudioBuffer> CopyFrom(SampleFormat sample_format,
-                                             ChannelLayout channel_layout,
-                                             int channel_count, int sample_rate,
-                                             int frame_count,
-                                             const uint8_t* const* data,
-                                             const base::TimeDelta timestamp);
-
-  // Create an AudioBuffer with |frame_count| frames. Buffer is allocated, but
-  // not initialized. Timestamp and duration are set to kNoTimestamp.
-  static scoped_refptr<AudioBuffer> CreateBuffer(SampleFormat sample_format,
-                                                 ChannelLayout channel_layout,
-                                                 int channel_count,
-                                                 int sample_rate,
-                                                 int frame_count);
-
-  // Create an empty AudioBuffer with |frame_count| frames.
-  static scoped_refptr<AudioBuffer> CreateEmptyBuffer(
-      ChannelLayout channel_layout, int channel_count, int sample_rate,
-      int frame_count, const base::TimeDelta timestamp);
-
-  // Create a AudioBuffer indicating we've reached end of stream.
-  // Calling any method other than end_of_stream() on the resulting buffer
-  // is disallowed.
-  static scoped_refptr<AudioBuffer> CreateEOSBuffer();
-
-  // Update sample rate and computed duration.
-  // TODO(chcunningham): Remove this upon patching FFmpeg's AAC decoder to
-  // provide the correct sample rate at the boundary of an implicit config
-  // change.
-  void AdjustSampleRate(int sample_rate);
-
-  // Copy frames into |dest|. |frames_to_copy| is the number of frames to copy.
-  // |source_frame_offset| specifies how many frames in the buffer to skip
-  // first. |dest_frame_offset| is the frame offset in |dest|. The frames are
-  // converted from their source format into planar float32 data (which is all
-  // that AudioBus handles).
-  void ReadFrames(int frames_to_copy, int source_frame_offset,
-                  int dest_frame_offset, AudioBus* dest);
-
-  // Trim an AudioBuffer by removing |frames_to_trim| frames from the start.
-  // Timestamp and duration are adjusted to reflect the fewer frames.
-  // Note that repeated calls to TrimStart() may result in timestamp() and
-  // duration() being off by a few microseconds due to rounding issues.
-  void TrimStart(int frames_to_trim);
-
-  // Trim an AudioBuffer by removing |frames_to_trim| frames from the end.
-  // Duration is adjusted to reflect the fewer frames.
-  void TrimEnd(int frames_to_trim);
-
-  // Trim an AudioBuffer by removing |end - start| frames from [|start|, |end|).
-  // Even if |start| is zero, timestamp() is not adjusted, only duration().
-  void TrimRange(int start, int end);
-
-  // Return the number of channels.
-  int channel_count() const { return channel_count_; }
-
-  // Return the number of frames held.
-  int frame_count() const { return adjusted_frame_count_; }
-
-  // Return the sample rate.
-  int sample_rate() const { return sample_rate_; }
-
-  // Return the channel layout.
-  ChannelLayout channel_layout() const { return channel_layout_; }
-
-  base::TimeDelta timestamp() const { return timestamp_; }
-  base::TimeDelta duration() const { return duration_; }
-  void set_timestamp(base::TimeDelta timestamp) { timestamp_ = timestamp; }
-
-  // If there's no data in this buffer, it represents end of stream.
-  bool end_of_stream() const { return end_of_stream_; }
-
-  // Access to the raw buffer for ffmpeg and Android MediaCodec decoders to
-  // write directly to. For planar formats the vector elements correspond to
-  // the channels. For interleaved formats the resulting vector has exactly
-  // one element which contains the buffer pointer.
-  const std::vector<uint8_t*>& channel_data() const { return channel_data_; }
-
-  // The size of allocated data memory block. For planar formats channels go
-  // sequentially in this block.
-  size_t data_size() const { return data_size_; }
-
- private:
-  friend class base::RefCountedThreadSafe<AudioBuffer>;
-
-  // mojo::TypeConverter added as a friend so that AudioBuffer can be
-  // transferred across a mojo connection.
-  friend struct mojo::TypeConverter<mojo::StructPtr<mojom::AudioBuffer>,
-                                    scoped_refptr<AudioBuffer> >;
-
-  // Allocates aligned contiguous buffer to hold all channel data (1 block for
-  // interleaved data, |channel_count| blocks for planar data), copies
-  // [data,data+data_size) to the allocated buffer(s). If |data| is null, no
-  // data is copied. If |create_buffer| is false, no data buffer is created (or
-  // copied to).
-  AudioBuffer(SampleFormat sample_format, ChannelLayout channel_layout,
-              int channel_count, int sample_rate, int frame_count,
-              bool create_buffer, const uint8_t* const* data,
-              const base::TimeDelta timestamp);
-
-  virtual ~AudioBuffer();
-
-  const SampleFormat sample_format_;
-  const ChannelLayout channel_layout_;
-  const int channel_count_;
-  int sample_rate_;
-  int adjusted_frame_count_;
-  const bool end_of_stream_;
-  base::TimeDelta timestamp_;
-  base::TimeDelta duration_;
-
-  // Contiguous block of channel data.
-  scoped_ptr_malloc<uint8_t, base::ScopedPtrAlignedFree> data_;
-  size_t data_size_;
-
-  // For planar data, points to each channels data.
-  std::vector<uint8_t*> channel_data_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(AudioBuffer);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_BUFFER_H_
diff --git a/src/cobalt/media/base/audio_buffer_converter.cc b/src/cobalt/media/base/audio_buffer_converter.cc
deleted file mode 100644
index 2aa57fd..0000000
--- a/src/cobalt/media/base/audio_buffer_converter.cc
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_buffer_converter.h"
-
-#include <algorithm>
-#include <cmath>
-
-#include "base/logging.h"
-#include "cobalt/media/base/audio_buffer.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "cobalt/media/base/audio_decoder_config.h"
-#include "cobalt/media/base/audio_timestamp_helper.h"
-#include "cobalt/media/base/sinc_resampler.h"
-#include "cobalt/media/base/timestamp_constants.h"
-#include "cobalt/media/base/vector_math.h"
-
-namespace cobalt {
-namespace media {
-
-// Is the config presented by |buffer| a config change from |params|?
-static bool IsConfigChange(const AudioParameters& params,
-                           const scoped_refptr<AudioBuffer>& buffer) {
-  return buffer->sample_rate() != params.sample_rate() ||
-         buffer->channel_count() != params.channels() ||
-         buffer->channel_layout() != params.channel_layout();
-}
-
-AudioBufferConverter::AudioBufferConverter(const AudioParameters& output_params)
-    : output_params_(output_params),
-      input_params_(output_params),
-      last_input_buffer_offset_(0),
-      input_frames_(0),
-      buffered_input_frames_(0.0),
-      io_sample_rate_ratio_(1.0),
-      timestamp_helper_(output_params_.sample_rate()),
-      is_flushing_(false) {}
-
-AudioBufferConverter::~AudioBufferConverter() {}
-
-void AudioBufferConverter::AddInput(const scoped_refptr<AudioBuffer>& buffer) {
-  // On EOS flush any remaining buffered data.
-  if (buffer->end_of_stream()) {
-    Flush();
-    queued_outputs_.push_back(buffer);
-    return;
-  }
-
-  // We'll need a new |audio_converter_| if there was a config change.
-  if (IsConfigChange(input_params_, buffer)) ResetConverter(buffer);
-
-  // Pass straight through if there's no work to be done.
-  if (!audio_converter_) {
-    queued_outputs_.push_back(buffer);
-    return;
-  }
-
-  if (timestamp_helper_.base_timestamp() == kNoTimestamp)
-    timestamp_helper_.SetBaseTimestamp(buffer->timestamp());
-
-  queued_inputs_.push_back(buffer);
-  input_frames_ += buffer->frame_count();
-
-  ConvertIfPossible();
-}
-
-bool AudioBufferConverter::HasNextBuffer() { return !queued_outputs_.empty(); }
-
-scoped_refptr<AudioBuffer> AudioBufferConverter::GetNextBuffer() {
-  DCHECK(!queued_outputs_.empty());
-  scoped_refptr<AudioBuffer> out = queued_outputs_.front();
-  queued_outputs_.pop_front();
-  return out;
-}
-
-void AudioBufferConverter::Reset() {
-  audio_converter_.reset();
-  queued_inputs_.clear();
-  queued_outputs_.clear();
-  timestamp_helper_.SetBaseTimestamp(kNoTimestamp);
-  input_params_ = output_params_;
-  input_frames_ = 0;
-  buffered_input_frames_ = 0.0;
-  last_input_buffer_offset_ = 0;
-}
-
-void AudioBufferConverter::ResetTimestampState() {
-  Flush();
-  timestamp_helper_.SetBaseTimestamp(kNoTimestamp);
-}
-
-double AudioBufferConverter::ProvideInput(AudioBus* audio_bus,
-                                          uint32_t frames_delayed) {
-  DCHECK(is_flushing_ || input_frames_ >= audio_bus->frames());
-
-  int requested_frames_left = audio_bus->frames();
-  int dest_index = 0;
-
-  while (requested_frames_left > 0 && !queued_inputs_.empty()) {
-    scoped_refptr<AudioBuffer> input_buffer = queued_inputs_.front();
-
-    int frames_to_read =
-        std::min(requested_frames_left,
-                 input_buffer->frame_count() - last_input_buffer_offset_);
-    input_buffer->ReadFrames(frames_to_read, last_input_buffer_offset_,
-                             dest_index, audio_bus);
-    last_input_buffer_offset_ += frames_to_read;
-
-    if (last_input_buffer_offset_ == input_buffer->frame_count()) {
-      // We've consumed all the frames in |input_buffer|.
-      queued_inputs_.pop_front();
-      last_input_buffer_offset_ = 0;
-    }
-
-    requested_frames_left -= frames_to_read;
-    dest_index += frames_to_read;
-  }
-
-  // If we're flushing, zero any extra space, otherwise we should always have
-  // enough data to completely fulfill the request.
-  if (is_flushing_ && requested_frames_left > 0) {
-    audio_bus->ZeroFramesPartial(audio_bus->frames() - requested_frames_left,
-                                 requested_frames_left);
-  } else {
-    DCHECK_EQ(requested_frames_left, 0);
-  }
-
-  input_frames_ -= audio_bus->frames() - requested_frames_left;
-  DCHECK_GE(input_frames_, 0);
-
-  buffered_input_frames_ += audio_bus->frames() - requested_frames_left;
-
-  // Full volume.
-  return 1.0;
-}
-
-void AudioBufferConverter::ResetConverter(
-    const scoped_refptr<AudioBuffer>& buffer) {
-  Flush();
-  audio_converter_.reset();
-  input_params_.Reset(
-      input_params_.format(), buffer->channel_layout(), buffer->sample_rate(),
-      input_params_.bits_per_sample(),
-      // If resampling is needed and the FIFO disabled, the AudioConverter will
-      // always request SincResampler::kDefaultRequestSize frames.  Otherwise it
-      // will use the output frame size.
-      buffer->sample_rate() == output_params_.sample_rate()
-          ? output_params_.frames_per_buffer()
-          : SincResampler::kDefaultRequestSize);
-  input_params_.set_channels_for_discrete(buffer->channel_count());
-
-  io_sample_rate_ratio_ = static_cast<double>(input_params_.sample_rate()) /
-                          output_params_.sample_rate();
-
-  // If |buffer| matches |output_params_| we don't need an AudioConverter at
-  // all, and can early-out here.
-  if (!IsConfigChange(output_params_, buffer)) return;
-
-  // Note: The FIFO is disabled to avoid extraneous memcpy().
-  audio_converter_.reset(
-      new AudioConverter(input_params_, output_params_, true));
-  audio_converter_->AddInput(this);
-}
-
-void AudioBufferConverter::ConvertIfPossible() {
-  DCHECK(audio_converter_);
-
-  int request_frames = 0;
-
-  if (is_flushing_) {
-    // If we're flushing we want to convert *everything* even if this means
-    // we'll have to pad some silence in ProvideInput().
-    request_frames =
-        ceil((buffered_input_frames_ + input_frames_) / io_sample_rate_ratio_);
-  } else {
-    // How many calls to ProvideInput() we can satisfy completely.
-    int chunks = input_frames_ / input_params_.frames_per_buffer();
-
-    // How many output frames that corresponds to:
-    request_frames = chunks * audio_converter_->ChunkSize();
-  }
-
-  if (!request_frames) return;
-
-  scoped_refptr<AudioBuffer> output_buffer = AudioBuffer::CreateBuffer(
-      kSampleFormatPlanarF32, output_params_.channel_layout(),
-      output_params_.channels(), output_params_.sample_rate(), request_frames);
-  std::unique_ptr<AudioBus> output_bus =
-      AudioBus::CreateWrapper(output_buffer->channel_count());
-
-  int frames_remaining = request_frames;
-
-  // The AudioConverter wants requests of a fixed size, so we'll slide an
-  // AudioBus of that size across the |output_buffer|.
-  while (frames_remaining != 0) {
-    // It's important that this is a multiple of AudioBus::kChannelAlignment in
-    // all requests except for the last, otherwise downstream SIMD optimizations
-    // will crash on unaligned data.
-    const int frames_this_iteration = std::min(
-        static_cast<int>(SincResampler::kDefaultRequestSize), frames_remaining);
-    const int offset_into_buffer =
-        output_buffer->frame_count() - frames_remaining;
-
-    // Wrap the portion of the AudioBuffer in an AudioBus so the AudioConverter
-    // can fill it.
-    output_bus->set_frames(frames_this_iteration);
-    for (int ch = 0; ch < output_buffer->channel_count(); ++ch) {
-      output_bus->SetChannelData(
-          ch, reinterpret_cast<float*>(output_buffer->channel_data()[ch]) +
-                  offset_into_buffer);
-    }
-
-    // Do the actual conversion.
-    audio_converter_->Convert(output_bus.get());
-    frames_remaining -= frames_this_iteration;
-    buffered_input_frames_ -= frames_this_iteration * io_sample_rate_ratio_;
-  }
-
-  // Compute the timestamp.
-  output_buffer->set_timestamp(timestamp_helper_.GetTimestamp());
-  timestamp_helper_.AddFrames(request_frames);
-
-  queued_outputs_.push_back(output_buffer);
-}
-
-void AudioBufferConverter::Flush() {
-  if (!audio_converter_) return;
-  is_flushing_ = true;
-  ConvertIfPossible();
-  is_flushing_ = false;
-  audio_converter_->Reset();
-  DCHECK_EQ(input_frames_, 0);
-  DCHECK_EQ(last_input_buffer_offset_, 0);
-  DCHECK_LT(buffered_input_frames_, 1.0);
-  DCHECK(queued_inputs_.empty());
-  buffered_input_frames_ = 0.0;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_buffer_converter.h b/src/cobalt/media/base/audio_buffer_converter.h
deleted file mode 100644
index ea118c4..0000000
--- a/src/cobalt/media/base/audio_buffer_converter.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_BUFFER_CONVERTER_H_
-#define COBALT_MEDIA_BASE_AUDIO_BUFFER_CONVERTER_H_
-
-#include <deque>
-#include <memory>
-
-#include "base/memory/ref_counted.h"
-#include "base/time.h"
-#include "cobalt/media/base/audio_converter.h"
-#include "cobalt/media/base/audio_parameters.h"
-#include "cobalt/media/base/audio_timestamp_helper.h"
-#include "cobalt/media/base/media_export.h"
-
-namespace cobalt {
-namespace media {
-
-class AudioBuffer;
-class AudioBus;
-
-// Takes AudioBuffers in any format and uses an AudioConverter to convert them
-// to a common format (usually the hardware output format).
-class MEDIA_EXPORT AudioBufferConverter : public AudioConverter::InputCallback {
- public:
-  explicit AudioBufferConverter(const AudioParameters& output_params);
-  ~AudioBufferConverter() OVERRIDE;
-
-  void AddInput(const scoped_refptr<AudioBuffer>& buffer);
-
-  // Is an output buffer available via GetNextBuffer()?
-  bool HasNextBuffer();
-
-  // This should only be called this is HasNextBuffer() returns true.
-  scoped_refptr<AudioBuffer> GetNextBuffer();
-
-  // Reset internal state.
-  void Reset();
-
-  // Reset internal timestamp state. Upon the next AddInput() call, our base
-  // timestamp will be set to match the input buffer.
-  void ResetTimestampState();
-
-  int input_buffer_size_for_testing() const {
-    return input_params_.frames_per_buffer();
-  }
-  int input_frames_left_for_testing() const { return input_frames_; }
-
- private:
-  // Callback to provide data to the AudioConverter
-  double ProvideInput(AudioBus* audio_bus, uint32_t frames_delayed) OVERRIDE;
-
-  // Reset the converter in response to a configuration change.
-  void ResetConverter(const scoped_refptr<AudioBuffer>& input_buffer);
-
-  // Perform conversion if we have enough data.
-  void ConvertIfPossible();
-
-  // Flush remaining output
-  void Flush();
-
-  // The output parameters.
-  AudioParameters output_params_;
-
-  // The current input parameters (we cache these to detect configuration
-  // changes, so we know when to reset the AudioConverter).
-  AudioParameters input_params_;
-
-  typedef std::deque<scoped_refptr<AudioBuffer> > BufferQueue;
-
-  // Queued up inputs (there will never be all that much data stored here, as
-  // soon as there's enough here to produce an output buffer we will do so).
-  BufferQueue queued_inputs_;
-
-  // Offset into the front element of |queued_inputs_|. A ProvideInput() call
-  // doesn't necessarily always consume an entire buffer.
-  int last_input_buffer_offset_;
-
-  // Buffer of output frames, to be returned by GetNextBuffer().
-  BufferQueue queued_outputs_;
-
-  // How many frames of input we have in |queued_inputs_|.
-  int input_frames_;
-
-  // Input frames in the AudioConverter's internal buffers.
-  double buffered_input_frames_;
-
-  // Ratio of sample rates, in/out.
-  double io_sample_rate_ratio_;
-
-  // Computes timestamps in terms of the output sample rate.
-  AudioTimestampHelper timestamp_helper_;
-
-  // Are we flushing everything, without regard for providing AudioConverter
-  // full AudioBuses in ProvideInput()?
-  bool is_flushing_;
-
-  // The AudioConverter which does the real work here.
-  std::unique_ptr<AudioConverter> audio_converter_;
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_BUFFER_CONVERTER_H_
diff --git a/src/cobalt/media/base/audio_buffer_converter_unittest.cc b/src/cobalt/media/base/audio_buffer_converter_unittest.cc
deleted file mode 100644
index 408e95a..0000000
--- a/src/cobalt/media/base/audio_buffer_converter_unittest.cc
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_buffer_converter.h"
-
-#include <memory>
-
-#include "cobalt/media/base/audio_buffer.h"
-#include "cobalt/media/base/sinc_resampler.h"
-#include "cobalt/media/base/test_helpers.h"
-#include "starboard/types.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cobalt {
-namespace media {
-
-// Important: Use an odd buffer size here so SIMD issues are caught.
-const int kOutFrameSize = 441;
-const int kOutSampleRate = 44100;
-const ChannelLayout kOutChannelLayout = CHANNEL_LAYOUT_STEREO;
-const int kOutChannelCount = 2;
-
-static scoped_refptr<AudioBuffer> MakeTestBuffer(int sample_rate,
-                                                 ChannelLayout channel_layout,
-                                                 int channel_count,
-                                                 int frames) {
-  return MakeAudioBuffer<uint8_t>(kSampleFormatU8, channel_layout,
-                                  channel_count, sample_rate, 0, 1, frames,
-                                  base::TimeDelta::FromSeconds(0));
-}
-
-class AudioBufferConverterTest : public ::testing::Test {
- public:
-  AudioBufferConverterTest()
-      : input_frames_(0),
-        expected_output_frames_(0.0),
-        output_frames_(0),
-        output_params_(AudioParameters::AUDIO_PCM_LOW_LATENCY,
-                       kOutChannelLayout, kOutSampleRate, 16, kOutFrameSize) {
-    audio_buffer_converter_.reset(new AudioBufferConverter(output_params_));
-  }
-
-  void Reset() {
-    audio_buffer_converter_->Reset();
-    output_frames_ = expected_output_frames_ = input_frames_ = 0;
-  }
-
-  void AddInput(const scoped_refptr<AudioBuffer>& in) {
-    if (!in->end_of_stream()) {
-      input_frames_ += in->frame_count();
-      expected_output_frames_ +=
-          in->frame_count() *
-          (static_cast<double>(output_params_.sample_rate()) /
-           in->sample_rate());
-    }
-    audio_buffer_converter_->AddInput(in);
-  }
-
-  void ConsumeOutput() {
-    ASSERT_TRUE(audio_buffer_converter_->HasNextBuffer());
-    scoped_refptr<AudioBuffer> out = audio_buffer_converter_->GetNextBuffer();
-    if (!out->end_of_stream()) {
-      output_frames_ += out->frame_count();
-      EXPECT_EQ(out->sample_rate(), output_params_.sample_rate());
-      EXPECT_EQ(out->channel_layout(), output_params_.channel_layout());
-      EXPECT_EQ(out->channel_count(), output_params_.channels());
-    } else {
-      EXPECT_FALSE(audio_buffer_converter_->HasNextBuffer());
-    }
-  }
-
-  void ConsumeAllOutput() {
-    AddInput(AudioBuffer::CreateEOSBuffer());
-    while (audio_buffer_converter_->HasNextBuffer()) ConsumeOutput();
-    EXPECT_EQ(output_frames_, ceil(expected_output_frames_));
-  }
-
- protected:
-  std::unique_ptr<AudioBufferConverter> audio_buffer_converter_;
-
-  int input_frames_;
-  double expected_output_frames_;
-  int output_frames_;
-  int input_buffers_;
-  AudioParameters output_params_;
-};
-
-TEST_F(AudioBufferConverterTest, PassThrough) {
-  scoped_refptr<AudioBuffer> in =
-      MakeTestBuffer(kOutSampleRate, kOutChannelLayout, kOutChannelCount, 512);
-  AddInput(in);
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, Downsample) {
-  scoped_refptr<AudioBuffer> in =
-      MakeTestBuffer(48000, kOutChannelLayout, kOutChannelCount, 512);
-  AddInput(in);
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, Upsample) {
-  scoped_refptr<AudioBuffer> in =
-      MakeTestBuffer(8000, kOutChannelLayout, kOutChannelCount, 512);
-  AddInput(in);
-  ConsumeAllOutput();
-}
-
-// Test resampling a buffer smaller than the SincResampler's kernel size.
-TEST_F(AudioBufferConverterTest, Resample_TinyBuffer) {
-  AddInput(MakeTestBuffer(48000, CHANNEL_LAYOUT_STEREO, 2,
-                          SincResampler::kKernelSize - 1));
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, Resample_DifferingBufferSizes) {
-  const int input_sample_rate = 48000;
-  AddInput(MakeTestBuffer(input_sample_rate, kOutChannelLayout,
-                          kOutChannelCount, 100));
-  AddInput(MakeTestBuffer(input_sample_rate, kOutChannelLayout,
-                          kOutChannelCount, 200));
-  AddInput(MakeTestBuffer(input_sample_rate, kOutChannelLayout,
-                          kOutChannelCount, 300));
-  AddInput(MakeTestBuffer(input_sample_rate, kOutChannelLayout,
-                          kOutChannelCount, 400));
-  AddInput(MakeTestBuffer(input_sample_rate, kOutChannelLayout,
-                          kOutChannelCount, 500));
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, ChannelDownmix) {
-  scoped_refptr<AudioBuffer> in =
-      MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_MONO, 1, 512);
-  AddInput(in);
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, ChannelUpmix) {
-  scoped_refptr<AudioBuffer> in =
-      MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_5_1, 6, 512);
-  AddInput(in);
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, ResampleAndRemix) {
-  scoped_refptr<AudioBuffer> in =
-      MakeTestBuffer(48000, CHANNEL_LAYOUT_5_1, 6, 512);
-  AddInput(in);
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, ConfigChange_SampleRate) {
-  AddInput(MakeTestBuffer(48000, kOutChannelLayout, kOutChannelCount, 512));
-  AddInput(MakeTestBuffer(44100, kOutChannelLayout, kOutChannelCount, 512));
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, ConfigChange_ChannelLayout) {
-  AddInput(MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_STEREO, 2, 512));
-  AddInput(MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_MONO, 1, 512));
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, ConfigChange_SampleRateAndChannelLayout) {
-  AddInput(MakeTestBuffer(44100, CHANNEL_LAYOUT_STEREO, 2, 512));
-  AddInput(MakeTestBuffer(48000, CHANNEL_LAYOUT_MONO, 1, 512));
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, ConfigChange_Multiple) {
-  AddInput(MakeTestBuffer(44100, CHANNEL_LAYOUT_STEREO, 2, 512));
-  AddInput(MakeTestBuffer(48000, CHANNEL_LAYOUT_MONO, 1, 512));
-  AddInput(MakeTestBuffer(44100, CHANNEL_LAYOUT_5_1, 6, 512));
-  AddInput(MakeTestBuffer(22050, CHANNEL_LAYOUT_STEREO, 2, 512));
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, Reset) {
-  AddInput(MakeTestBuffer(44100, CHANNEL_LAYOUT_STEREO, 2, 512));
-  Reset();
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, ResampleThenReset) {
-  // Resampling is likely to leave some data buffered in AudioConverter's
-  // fifo or resampler, so make sure Reset() cleans that all up.
-  AddInput(MakeTestBuffer(48000, CHANNEL_LAYOUT_STEREO, 2, 512));
-  Reset();
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, ResetThenConvert) {
-  AddInput(
-      MakeTestBuffer(kOutSampleRate, kOutChannelLayout, kOutChannelCount, 512));
-  Reset();
-  // Make sure we can keep using the AudioBufferConverter after we've Reset().
-  AddInput(
-      MakeTestBuffer(kOutSampleRate, kOutChannelLayout, kOutChannelCount, 512));
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, DiscreteChannelLayout) {
-  output_params_ =
-      AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
-                      CHANNEL_LAYOUT_DISCRETE, kOutSampleRate, 16, 512);
-  output_params_.set_channels_for_discrete(2);
-  audio_buffer_converter_.reset(new AudioBufferConverter(output_params_));
-  AddInput(MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_STEREO, 2, 512));
-  ConsumeAllOutput();
-}
-
-TEST_F(AudioBufferConverterTest, LargeBuffersResampling) {
-  output_params_ = AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
-                                   kOutChannelLayout, kOutSampleRate, 16, 2048);
-
-  audio_buffer_converter_.reset(new AudioBufferConverter(output_params_));
-  const int kInputSampleRate = 48000;
-  const int kInputFrameSize = 8192;
-  ASSERT_NE(kInputSampleRate, kOutSampleRate);
-
-  const int kInputBuffers = 3;
-  for (int i = 0; i < kInputBuffers; ++i) {
-    AddInput(MakeTestBuffer(kInputSampleRate, kOutChannelLayout,
-                            kOutChannelCount, kInputFrameSize));
-  }
-
-  // Do not add an EOS packet here, as it will invoke flushing.
-  while (audio_buffer_converter_->HasNextBuffer()) ConsumeOutput();
-
-  // Since the input buffer size is a multiple of the input request size there
-  // should never be any frames remaining at this point.
-  ASSERT_EQ(kInputFrameSize %
-                audio_buffer_converter_->input_buffer_size_for_testing(),
-            0);
-  EXPECT_EQ(0, audio_buffer_converter_->input_frames_left_for_testing());
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_buffer_queue.cc b/src/cobalt/media/base/audio_buffer_queue.cc
deleted file mode 100644
index 69cf82d..0000000
--- a/src/cobalt/media/base/audio_buffer_queue.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_buffer_queue.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "cobalt/media/base/audio_bus.h"
-
-namespace cobalt {
-namespace media {
-
-AudioBufferQueue::AudioBufferQueue() { Clear(); }
-AudioBufferQueue::~AudioBufferQueue() {}
-
-void AudioBufferQueue::Clear() {
-  buffers_.clear();
-  current_buffer_ = buffers_.begin();
-  current_buffer_offset_ = 0;
-  frames_ = 0;
-}
-
-void AudioBufferQueue::Append(const scoped_refptr<AudioBuffer>& buffer_in) {
-  // Add the buffer to the queue. Inserting into deque invalidates all
-  // iterators, so point to the first buffer.
-  buffers_.push_back(buffer_in);
-  current_buffer_ = buffers_.begin();
-
-  // Update the |frames_| counter since we have added frames.
-  frames_ += buffer_in->frame_count();
-  CHECK_GT(frames_, 0);  // make sure it doesn't overflow.
-}
-
-int AudioBufferQueue::ReadFrames(int frames, int dest_frame_offset,
-                                 AudioBus* dest) {
-  DCHECK_GE(dest->frames(), frames + dest_frame_offset);
-  return InternalRead(frames, true, 0, dest_frame_offset, dest);
-}
-
-int AudioBufferQueue::PeekFrames(int frames, int source_frame_offset,
-                                 int dest_frame_offset, AudioBus* dest) {
-  DCHECK_GE(dest->frames(), frames);
-  return InternalRead(frames, false, source_frame_offset, dest_frame_offset,
-                      dest);
-}
-
-void AudioBufferQueue::SeekFrames(int frames) {
-  // Perform seek only if we have enough bytes in the queue.
-  CHECK_LE(frames, frames_);
-  int taken = InternalRead(frames, true, 0, 0, NULL);
-  DCHECK_EQ(taken, frames);
-}
-
-int AudioBufferQueue::InternalRead(int frames, bool advance_position,
-                                   int source_frame_offset,
-                                   int dest_frame_offset, AudioBus* dest) {
-  // Counts how many frames are actually read from the buffer queue.
-  int taken = 0;
-  BufferQueue::iterator current_buffer = current_buffer_;
-  int current_buffer_offset = current_buffer_offset_;
-
-  int frames_to_skip = source_frame_offset;
-  while (taken < frames) {
-    // |current_buffer| is valid since the first time this buffer is appended
-    // with data. Make sure there is data to be processed.
-    if (current_buffer == buffers_.end()) break;
-
-    scoped_refptr<AudioBuffer> buffer = *current_buffer;
-
-    int remaining_frames_in_buffer =
-        buffer->frame_count() - current_buffer_offset;
-
-    if (frames_to_skip > 0) {
-      // If there are frames to skip, do it first. May need to skip into
-      // subsequent buffers.
-      int skipped = std::min(remaining_frames_in_buffer, frames_to_skip);
-      current_buffer_offset += skipped;
-      frames_to_skip -= skipped;
-    } else {
-      // Find the right amount to copy from the current buffer. We shall copy no
-      // more than |frames| frames in total and each single step copies no more
-      // than the current buffer size.
-      int copied = std::min(frames - taken, remaining_frames_in_buffer);
-
-      // if |dest| is NULL, there's no need to copy.
-      if (dest) {
-        buffer->ReadFrames(copied, current_buffer_offset,
-                           dest_frame_offset + taken, dest);
-      }
-
-      // Increase total number of frames copied, which regulates when to end
-      // this loop.
-      taken += copied;
-
-      // We have read |copied| frames from the current buffer. Advance the
-      // offset.
-      current_buffer_offset += copied;
-    }
-
-    // Has the buffer has been consumed?
-    if (current_buffer_offset == buffer->frame_count()) {
-      // If we are at the last buffer, no more data to be copied, so stop.
-      BufferQueue::iterator next = current_buffer + 1;
-      if (next == buffers_.end()) break;
-
-      // Advances the iterator.
-      current_buffer = next;
-      current_buffer_offset = 0;
-    }
-  }
-
-  if (advance_position) {
-    // Update the appropriate values since |taken| frames have been copied out.
-    frames_ -= taken;
-    DCHECK_GE(frames_, 0);
-    DCHECK(current_buffer_ != buffers_.end() || frames_ == 0);
-
-    // Remove any buffers before the current buffer as there is no going
-    // backwards.
-    buffers_.erase(buffers_.begin(), current_buffer);
-    current_buffer_ = buffers_.begin();
-    current_buffer_offset_ = current_buffer_offset;
-  }
-
-  return taken;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_buffer_queue.h b/src/cobalt/media/base/audio_buffer_queue.h
deleted file mode 100644
index 37881bb..0000000
--- a/src/cobalt/media/base/audio_buffer_queue.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_BUFFER_QUEUE_H_
-#define COBALT_MEDIA_BASE_AUDIO_BUFFER_QUEUE_H_
-
-#include <deque>
-
-#include "base/basictypes.h"
-#include "cobalt/media/base/audio_buffer.h"
-#include "cobalt/media/base/media_export.h"
-
-namespace cobalt {
-namespace media {
-
-class AudioBus;
-
-// A queue of AudioBuffers to support reading of arbitrary chunks of a media
-// data source. Audio data can be copied into an AudioBus for output. The
-// current position can be forwarded to anywhere in the buffered data.
-//
-// This class is not inherently thread-safe. Concurrent access must be
-// externally serialized.
-class MEDIA_EXPORT AudioBufferQueue {
- public:
-  AudioBufferQueue();
-  ~AudioBufferQueue();
-
-  // Clears the buffer queue.
-  void Clear();
-
-  // Appends |buffer_in| to this queue.
-  void Append(const scoped_refptr<AudioBuffer>& buffer_in);
-
-  // Reads a maximum of |frames| frames into |dest| from the current position.
-  // Returns the number of frames read. The current position will advance by the
-  // amount of frames read. |dest_frame_offset| specifies a starting offset into
-  // |dest|. On each call, the frames are converted from their source format
-  // into the destination AudioBus.
-  int ReadFrames(int frames, int dest_frame_offset, AudioBus* dest);
-
-  // Copies up to |frames| frames from current position to |dest|. Returns
-  // number of frames copied. Doesn't advance current position. Starts at
-  // |source_frame_offset| from current position. |dest_frame_offset| specifies
-  // a starting offset into |dest|. On each call, the frames are converted from
-  // their source format into the destination AudioBus.
-  int PeekFrames(int frames, int source_frame_offset, int dest_frame_offset,
-                 AudioBus* dest);
-
-  // Moves the current position forward by |frames| frames. If |frames| exceeds
-  // frames available, the seek operation will fail.
-  void SeekFrames(int frames);
-
-  // Returns the number of frames buffered beyond the current position.
-  int frames() const { return frames_; }
-
- private:
-  // Definition of the buffer queue.
-  typedef std::deque<scoped_refptr<AudioBuffer> > BufferQueue;
-
-  // An internal method shared by ReadFrames() and SeekFrames() that actually
-  // does reading. It reads a maximum of |frames| frames into |dest|. Returns
-  // the number of frames read. The current position will be moved forward by
-  // the number of frames read if |advance_position| is set. If |dest| is NULL,
-  // only the current position will advance but no data will be copied.
-  // |source_frame_offset| can be used to skip frames before reading.
-  // |dest_frame_offset| specifies a starting offset into |dest|.
-  int InternalRead(int frames, bool advance_position, int source_frame_offset,
-                   int dest_frame_offset, AudioBus* dest);
-
-  BufferQueue::iterator current_buffer_;
-  BufferQueue buffers_;
-  int current_buffer_offset_;
-
-  // Number of frames available to be read in the buffer.
-  int frames_;
-
-  DISALLOW_COPY_AND_ASSIGN(AudioBufferQueue);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_BUFFER_QUEUE_H_
diff --git a/src/cobalt/media/base/audio_buffer_queue_unittest.cc b/src/cobalt/media/base/audio_buffer_queue_unittest.cc
deleted file mode 100644
index 27829ab..0000000
--- a/src/cobalt/media/base/audio_buffer_queue_unittest.cc
+++ /dev/null
@@ -1,348 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_buffer_queue.h"
-
-#include <limits>
-#include <memory>
-
-#include "base/logging.h"
-#include "base/time.h"
-#include "cobalt/media/base/audio_buffer.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "cobalt/media/base/test_helpers.h"
-#include "cobalt/media/base/timestamp_constants.h"
-#include "starboard/types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cobalt {
-namespace media {
-
-const int kSampleRate = 44100;
-
-static void VerifyBus(AudioBus* bus, int offset, int frames, int buffer_size,
-                      float start, float increment) {
-  for (int ch = 0; ch < bus->channels(); ++ch) {
-    const float v = start + ch * buffer_size * increment;
-    for (int i = offset; i < offset + frames; ++i) {
-      ASSERT_FLOAT_EQ(v + (i - offset) * increment, bus->channel(ch)[i])
-          << "i=" << i << ", ch=" << ch;
-    }
-  }
-}
-
-template <typename T>
-static scoped_refptr<AudioBuffer> MakeTestBuffer(SampleFormat format,
-                                                 ChannelLayout channel_layout,
-                                                 T start, T step, int frames) {
-  return MakeAudioBuffer<T>(format, channel_layout,
-                            ChannelLayoutToChannelCount(channel_layout),
-                            kSampleRate, start, step, frames, kNoTimestamp);
-}
-
-TEST(AudioBufferQueueTest, AppendAndClear) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_MONO;
-  AudioBufferQueue buffer;
-  EXPECT_EQ(0, buffer.frames());
-  buffer.Append(
-      MakeTestBuffer<uint8_t>(kSampleFormatU8, channel_layout, 10, 1, 8));
-  EXPECT_EQ(8, buffer.frames());
-  buffer.Clear();
-  EXPECT_EQ(0, buffer.frames());
-  buffer.Append(
-      MakeTestBuffer<uint8_t>(kSampleFormatU8, channel_layout, 20, 1, 8));
-  EXPECT_EQ(8, buffer.frames());
-}
-
-TEST(AudioBufferQueueTest, MultipleAppend) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_MONO;
-  AudioBufferQueue buffer;
-  buffer.Append(
-      MakeTestBuffer<uint8_t>(kSampleFormatU8, channel_layout, 10, 1, 8));
-  EXPECT_EQ(8, buffer.frames());
-  buffer.Append(
-      MakeTestBuffer<uint8_t>(kSampleFormatU8, channel_layout, 10, 1, 8));
-  EXPECT_EQ(16, buffer.frames());
-  buffer.Append(
-      MakeTestBuffer<uint8_t>(kSampleFormatU8, channel_layout, 10, 1, 8));
-  EXPECT_EQ(24, buffer.frames());
-  buffer.Append(
-      MakeTestBuffer<uint8_t>(kSampleFormatU8, channel_layout, 10, 1, 8));
-  EXPECT_EQ(32, buffer.frames());
-  buffer.Append(
-      MakeTestBuffer<uint8_t>(kSampleFormatU8, channel_layout, 10, 1, 8));
-  EXPECT_EQ(40, buffer.frames());
-}
-
-TEST(AudioBufferQueueTest, IteratorCheck) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_MONO;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  AudioBufferQueue buffer;
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, 100);
-
-  // Append 40 frames in 5 buffers. Intersperse ReadFrames() to make the
-  // iterator is pointing to the correct position.
-  buffer.Append(
-      MakeTestBuffer<float>(kSampleFormatF32, channel_layout, 10.0f, 1.0f, 8));
-  EXPECT_EQ(8, buffer.frames());
-
-  EXPECT_EQ(4, buffer.ReadFrames(4, 0, bus.get()));
-  EXPECT_EQ(4, buffer.frames());
-  VerifyBus(bus.get(), 0, 4, bus->frames(), 10, 1);
-
-  buffer.Append(
-      MakeTestBuffer<float>(kSampleFormatF32, channel_layout, 20.0f, 1.0f, 8));
-  EXPECT_EQ(12, buffer.frames());
-  buffer.Append(
-      MakeTestBuffer<float>(kSampleFormatF32, channel_layout, 30.0f, 1.0f, 8));
-  EXPECT_EQ(20, buffer.frames());
-
-  buffer.SeekFrames(16);
-  EXPECT_EQ(4, buffer.ReadFrames(4, 0, bus.get()));
-  EXPECT_EQ(0, buffer.frames());
-  VerifyBus(bus.get(), 0, 4, bus->frames(), 34, 1);
-
-  buffer.Append(
-      MakeTestBuffer<float>(kSampleFormatF32, channel_layout, 40.0f, 1.0f, 8));
-  EXPECT_EQ(8, buffer.frames());
-  buffer.Append(
-      MakeTestBuffer<float>(kSampleFormatF32, channel_layout, 50.0f, 1.0f, 8));
-  EXPECT_EQ(16, buffer.frames());
-
-  EXPECT_EQ(4, buffer.ReadFrames(4, 0, bus.get()));
-  VerifyBus(bus.get(), 0, 4, bus->frames(), 40, 1);
-
-  // Read off the end of the buffer.
-  EXPECT_EQ(12, buffer.frames());
-  buffer.SeekFrames(8);
-  EXPECT_EQ(4, buffer.ReadFrames(100, 0, bus.get()));
-  VerifyBus(bus.get(), 0, 4, bus->frames(), 54, 1);
-}
-
-TEST(AudioBufferQueueTest, Seek) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
-  AudioBufferQueue buffer;
-
-  // Add 6 frames of data.
-  buffer.Append(
-      MakeTestBuffer<float>(kSampleFormatF32, channel_layout, 1.0f, 1.0f, 6));
-  EXPECT_EQ(6, buffer.frames());
-
-  // Seek past 2 frames.
-  buffer.SeekFrames(2);
-  EXPECT_EQ(4, buffer.frames());
-
-  // Seek to end of data.
-  buffer.SeekFrames(4);
-  EXPECT_EQ(0, buffer.frames());
-
-  // At end, seek now fails unless 0 specified.
-  buffer.SeekFrames(0);
-}
-
-TEST(AudioBufferQueueTest, ReadF32) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  AudioBufferQueue buffer;
-
-  // Add 76 frames of data.
-  buffer.Append(
-      MakeTestBuffer<float>(kSampleFormatF32, channel_layout, 1.0f, 1.0f, 6));
-  buffer.Append(
-      MakeTestBuffer<float>(kSampleFormatF32, channel_layout, 13.0f, 1.0f, 10));
-  buffer.Append(
-      MakeTestBuffer<float>(kSampleFormatF32, channel_layout, 33.0f, 1.0f, 60));
-  EXPECT_EQ(76, buffer.frames());
-
-  // Read 3 frames from the buffer.
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, 100);
-  EXPECT_EQ(3, buffer.ReadFrames(3, 0, bus.get()));
-  EXPECT_EQ(73, buffer.frames());
-  VerifyBus(bus.get(), 0, 3, 6, 1, 1);
-
-  // Now read 5 frames, which will span buffers. Append the data into AudioBus.
-  EXPECT_EQ(5, buffer.ReadFrames(5, 3, bus.get()));
-  EXPECT_EQ(68, buffer.frames());
-  VerifyBus(bus.get(), 0, 6, 6, 1, 1);
-  VerifyBus(bus.get(), 6, 2, 10, 13, 1);
-
-  // Now skip into the third buffer.
-  buffer.SeekFrames(20);
-  EXPECT_EQ(48, buffer.frames());
-
-  // Now read 2 frames, which are in the third buffer.
-  EXPECT_EQ(2, buffer.ReadFrames(2, 0, bus.get()));
-  VerifyBus(bus.get(), 0, 2, 60, 45, 1);
-}
-
-TEST(AudioBufferQueueTest, ReadU8) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_4_0;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  const int frames = 4;
-  AudioBufferQueue buffer;
-
-  // Add 4 frames of data.
-  buffer.Append(
-      MakeTestBuffer<uint8_t>(kSampleFormatU8, channel_layout, 128, 1, frames));
-
-  // Read all 4 frames from the buffer.
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, frames);
-  EXPECT_EQ(frames, buffer.ReadFrames(frames, 0, bus.get()));
-  EXPECT_EQ(0, buffer.frames());
-  VerifyBus(bus.get(), 0, frames, bus->frames(), 0, 1.0f / 127.0f);
-}
-
-TEST(AudioBufferQueueTest, ReadS16) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  AudioBufferQueue buffer;
-
-  // Add 24 frames of data.
-  buffer.Append(
-      MakeTestBuffer<int16_t>(kSampleFormatS16, channel_layout, 1, 1, 4));
-  buffer.Append(
-      MakeTestBuffer<int16_t>(kSampleFormatS16, channel_layout, 9, 1, 20));
-  EXPECT_EQ(24, buffer.frames());
-
-  // Read 6 frames from the buffer.
-  const int frames = 6;
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, buffer.frames());
-  EXPECT_EQ(frames, buffer.ReadFrames(frames, 0, bus.get()));
-  EXPECT_EQ(18, buffer.frames());
-  VerifyBus(bus.get(), 0, 4, 4, 1.0f / std::numeric_limits<int16_t>::max(),
-            1.0f / std::numeric_limits<int16_t>::max());
-  VerifyBus(bus.get(), 4, 2, 20, 9.0f / std::numeric_limits<int16_t>::max(),
-            1.0f / std::numeric_limits<int16_t>::max());
-}
-
-TEST(AudioBufferQueueTest, ReadS32) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  AudioBufferQueue buffer;
-
-  // Add 24 frames of data.
-  buffer.Append(
-      MakeTestBuffer<int32_t>(kSampleFormatS32, channel_layout, 1, 1, 4));
-  buffer.Append(
-      MakeTestBuffer<int32_t>(kSampleFormatS32, channel_layout, 9, 1, 20));
-  EXPECT_EQ(24, buffer.frames());
-
-  // Read 6 frames from the buffer.
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, 100);
-  EXPECT_EQ(6, buffer.ReadFrames(6, 0, bus.get()));
-  EXPECT_EQ(18, buffer.frames());
-  VerifyBus(bus.get(), 0, 4, 4, 1.0f / std::numeric_limits<int32_t>::max(),
-            1.0f / std::numeric_limits<int32_t>::max());
-  VerifyBus(bus.get(), 4, 2, 20, 9.0f / std::numeric_limits<int32_t>::max(),
-            1.0f / std::numeric_limits<int32_t>::max());
-
-  // Read the next 2 frames.
-  EXPECT_EQ(2, buffer.ReadFrames(2, 0, bus.get()));
-  EXPECT_EQ(16, buffer.frames());
-  VerifyBus(bus.get(), 0, 2, 20, 11.0f / std::numeric_limits<int32_t>::max(),
-            1.0f / std::numeric_limits<int32_t>::max());
-}
-
-TEST(AudioBufferQueueTest, ReadF32Planar) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  AudioBufferQueue buffer;
-
-  // Add 14 frames of data.
-  buffer.Append(MakeTestBuffer<float>(kSampleFormatPlanarF32, channel_layout,
-                                      1.0f, 1.0f, 4));
-  buffer.Append(MakeTestBuffer<float>(kSampleFormatPlanarF32, channel_layout,
-                                      50.0f, 1.0f, 10));
-  EXPECT_EQ(14, buffer.frames());
-
-  // Read 6 frames from the buffer.
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, 100);
-  EXPECT_EQ(6, buffer.ReadFrames(6, 0, bus.get()));
-  EXPECT_EQ(8, buffer.frames());
-  VerifyBus(bus.get(), 0, 4, 4, 1, 1);
-  VerifyBus(bus.get(), 4, 2, 10, 50, 1);
-}
-
-TEST(AudioBufferQueueTest, ReadS16Planar) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  AudioBufferQueue buffer;
-
-  // Add 24 frames of data.
-  buffer.Append(
-      MakeTestBuffer<int16_t>(kSampleFormatPlanarS16, channel_layout, 1, 1, 4));
-  buffer.Append(MakeTestBuffer<int16_t>(kSampleFormatPlanarS16, channel_layout,
-                                        5, 1, 20));
-  EXPECT_EQ(24, buffer.frames());
-
-  // Read 6 frames from the buffer.
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, 100);
-  EXPECT_EQ(6, buffer.ReadFrames(6, 0, bus.get()));
-  EXPECT_EQ(18, buffer.frames());
-  VerifyBus(bus.get(), 0, 4, 4, 1.0f / std::numeric_limits<int16_t>::max(),
-            1.0f / std::numeric_limits<int16_t>::max());
-  VerifyBus(bus.get(), 4, 2, 20, 5.0f / std::numeric_limits<int16_t>::max(),
-            1.0f / std::numeric_limits<int16_t>::max());
-}
-
-TEST(AudioBufferQueueTest, ReadManyChannels) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_OCTAGONAL;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  AudioBufferQueue buffer;
-
-  // Add 76 frames of data.
-  buffer.Append(
-      MakeTestBuffer<float>(kSampleFormatF32, channel_layout, 0.0f, 1.0f, 6));
-  buffer.Append(MakeTestBuffer<float>(kSampleFormatF32, channel_layout,
-                                      6.0f * channels, 1.0f, 10));
-  buffer.Append(MakeTestBuffer<float>(kSampleFormatF32, channel_layout,
-                                      16.0f * channels, 1.0f, 60));
-  EXPECT_EQ(76, buffer.frames());
-
-  // Read 3 frames from the buffer.
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, 100);
-  EXPECT_EQ(30, buffer.ReadFrames(30, 0, bus.get()));
-  EXPECT_EQ(46, buffer.frames());
-  VerifyBus(bus.get(), 0, 6, 6, 0, 1);
-  VerifyBus(bus.get(), 6, 10, 10, 6 * channels, 1);
-  VerifyBus(bus.get(), 16, 14, 60, 16 * channels, 1);
-}
-
-TEST(AudioBufferQueueTest, Peek) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_4_0;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  AudioBufferQueue buffer;
-
-  // Add 60 frames of data.
-  const int frames = 60;
-  buffer.Append(MakeTestBuffer<float>(kSampleFormatF32, channel_layout, 0.0f,
-                                      1.0f, frames));
-  EXPECT_EQ(frames, buffer.frames());
-
-  // Peek at the first 30 frames.
-  std::unique_ptr<AudioBus> bus1 = AudioBus::Create(channels, frames);
-  EXPECT_EQ(frames, buffer.frames());
-  EXPECT_EQ(frames, buffer.PeekFrames(60, 0, 0, bus1.get()));
-  EXPECT_EQ(30, buffer.PeekFrames(30, 0, 0, bus1.get()));
-  EXPECT_EQ(frames, buffer.frames());
-  VerifyBus(bus1.get(), 0, 30, bus1->frames(), 0, 1);
-
-  // Now read the next 30 frames (which should be the same as those peeked at).
-  std::unique_ptr<AudioBus> bus2 = AudioBus::Create(channels, frames);
-  EXPECT_EQ(30, buffer.ReadFrames(30, 0, bus2.get()));
-  VerifyBus(bus2.get(), 0, 30, bus2->frames(), 0, 1);
-
-  // Peek 10 frames forward
-  bus1->Zero();
-  EXPECT_EQ(5, buffer.PeekFrames(5, 10, 0, bus1.get()));
-  VerifyBus(bus1.get(), 0, 5, bus1->frames(), 40, 1);
-
-  // Peek to the end of the buffer.
-  EXPECT_EQ(30, buffer.frames());
-  EXPECT_EQ(30, buffer.PeekFrames(60, 0, 0, bus1.get()));
-  EXPECT_EQ(30, buffer.PeekFrames(30, 0, 0, bus1.get()));
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_buffer_unittest.cc b/src/cobalt/media/base/audio_buffer_unittest.cc
deleted file mode 100644
index 2e3cf5d..0000000
--- a/src/cobalt/media/base/audio_buffer_unittest.cc
+++ /dev/null
@@ -1,376 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <limits>
-#include <memory>
-
-#include "cobalt/media/base/audio_buffer.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "cobalt/media/base/test_helpers.h"
-#include "starboard/types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cobalt {
-namespace media {
-
-static const int kSampleRate = 4800;
-
-static void VerifyBusWithOffset(AudioBus* bus, int offset, int frames,
-                                float start, float start_offset,
-                                float increment) {
-  for (int ch = 0; ch < bus->channels(); ++ch) {
-    const float v = start_offset + start + ch * bus->frames() * increment;
-    for (int i = offset; i < offset + frames; ++i) {
-      ASSERT_FLOAT_EQ(v + i * increment, bus->channel(ch)[i]) << "i=" << i
-                                                              << ", ch=" << ch;
-    }
-  }
-}
-
-static void VerifyBus(AudioBus* bus, int frames, float start, float increment) {
-  VerifyBusWithOffset(bus, 0, frames, start, 0, increment);
-}
-
-static void TrimRangeTest(SampleFormat sample_format) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_4_0;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  const int frames = kSampleRate / 10;
-  const base::TimeDelta timestamp = base::TimeDelta();
-  const base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
-  scoped_refptr<AudioBuffer> buffer =
-      MakeAudioBuffer<float>(sample_format, channel_layout, channels,
-                             kSampleRate, 0, 1, frames, timestamp);
-  EXPECT_EQ(frames, buffer->frame_count());
-  EXPECT_EQ(timestamp, buffer->timestamp());
-  EXPECT_EQ(duration, buffer->duration());
-
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, frames);
-
-  // Verify all frames before trimming.
-  buffer->ReadFrames(frames, 0, 0, bus.get());
-  VerifyBus(bus.get(), frames, 0, 1);
-
-  // Trim 10ms of frames from the middle of the buffer.
-  int trim_start = frames / 2;
-  const int trim_length = kSampleRate / 100;
-  const base::TimeDelta trim_duration = base::TimeDelta::FromMilliseconds(10);
-  buffer->TrimRange(trim_start, trim_start + trim_length);
-  EXPECT_EQ(frames - trim_length, buffer->frame_count());
-  EXPECT_EQ(timestamp, buffer->timestamp());
-  EXPECT_EQ(duration - trim_duration, buffer->duration());
-  bus->Zero();
-  buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get());
-  VerifyBus(bus.get(), trim_start, 0, 1);
-  VerifyBusWithOffset(bus.get(), trim_start, buffer->frame_count() - trim_start,
-                      0, trim_length, 1);
-
-  // Trim 10ms of frames from the start, which just adjusts the buffer's
-  // internal start offset.
-  buffer->TrimStart(trim_length);
-  trim_start -= trim_length;
-  EXPECT_EQ(frames - 2 * trim_length, buffer->frame_count());
-  EXPECT_EQ(timestamp, buffer->timestamp());
-  EXPECT_EQ(duration - 2 * trim_duration, buffer->duration());
-  bus->Zero();
-  buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get());
-  VerifyBus(bus.get(), trim_start, trim_length, 1);
-  VerifyBusWithOffset(bus.get(), trim_start, buffer->frame_count() - trim_start,
-                      trim_length, trim_length, 1);
-
-  // Trim 10ms of frames from the end, which just adjusts the buffer's frame
-  // count.
-  buffer->TrimEnd(trim_length);
-  EXPECT_EQ(frames - 3 * trim_length, buffer->frame_count());
-  EXPECT_EQ(timestamp, buffer->timestamp());
-  EXPECT_EQ(duration - 3 * trim_duration, buffer->duration());
-  bus->Zero();
-  buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get());
-  VerifyBus(bus.get(), trim_start, trim_length, 1);
-  VerifyBusWithOffset(bus.get(), trim_start, buffer->frame_count() - trim_start,
-                      trim_length, trim_length, 1);
-
-  // Trim another 10ms from the inner portion of the buffer.
-  buffer->TrimRange(trim_start, trim_start + trim_length);
-  EXPECT_EQ(frames - 4 * trim_length, buffer->frame_count());
-  EXPECT_EQ(timestamp, buffer->timestamp());
-  EXPECT_EQ(duration - 4 * trim_duration, buffer->duration());
-  bus->Zero();
-  buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get());
-  VerifyBus(bus.get(), trim_start, trim_length, 1);
-  VerifyBusWithOffset(bus.get(), trim_start, buffer->frame_count() - trim_start,
-                      trim_length, trim_length * 2, 1);
-
-  // Trim off the end using TrimRange() to ensure end index is exclusive.
-  buffer->TrimRange(buffer->frame_count() - trim_length, buffer->frame_count());
-  EXPECT_EQ(frames - 5 * trim_length, buffer->frame_count());
-  EXPECT_EQ(timestamp, buffer->timestamp());
-  EXPECT_EQ(duration - 5 * trim_duration, buffer->duration());
-  bus->Zero();
-  buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get());
-  VerifyBus(bus.get(), trim_start, trim_length, 1);
-  VerifyBusWithOffset(bus.get(), trim_start, buffer->frame_count() - trim_start,
-                      trim_length, trim_length * 2, 1);
-
-  // Trim off the start using TrimRange() to ensure start index is inclusive.
-  buffer->TrimRange(0, trim_length);
-  trim_start -= trim_length;
-  EXPECT_EQ(frames - 6 * trim_length, buffer->frame_count());
-  EXPECT_EQ(timestamp, buffer->timestamp());
-  EXPECT_EQ(duration - 6 * trim_duration, buffer->duration());
-  bus->Zero();
-  buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get());
-  VerifyBus(bus.get(), trim_start, 2 * trim_length, 1);
-  VerifyBusWithOffset(bus.get(), trim_start, buffer->frame_count() - trim_start,
-                      trim_length * 2, trim_length * 2, 1);
-}
-
-TEST(AudioBufferTest, CopyFrom) {
-  const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_MONO;
-  scoped_refptr<AudioBuffer> original_buffer = MakeAudioBuffer<uint8_t>(
-      kSampleFormatU8, kChannelLayout,
-      ChannelLayoutToChannelCount(kChannelLayout), kSampleRate, 1, 1,
-      kSampleRate / 100, base::TimeDelta());
-  scoped_refptr<AudioBuffer> new_buffer = AudioBuffer::CopyFrom(
-      kSampleFormatU8, original_buffer->channel_layout(),
-      original_buffer->channel_count(), original_buffer->sample_rate(),
-      original_buffer->frame_count(), &original_buffer->channel_data()[0],
-      original_buffer->timestamp());
-  EXPECT_EQ(original_buffer->frame_count(), new_buffer->frame_count());
-  EXPECT_EQ(original_buffer->timestamp(), new_buffer->timestamp());
-  EXPECT_EQ(original_buffer->duration(), new_buffer->duration());
-  EXPECT_EQ(original_buffer->sample_rate(), new_buffer->sample_rate());
-  EXPECT_EQ(original_buffer->channel_count(), new_buffer->channel_count());
-  EXPECT_EQ(original_buffer->channel_layout(), new_buffer->channel_layout());
-  EXPECT_FALSE(original_buffer->end_of_stream());
-}
-
-TEST(AudioBufferTest, CreateEOSBuffer) {
-  scoped_refptr<AudioBuffer> buffer = AudioBuffer::CreateEOSBuffer();
-  EXPECT_TRUE(buffer->end_of_stream());
-}
-
-TEST(AudioBufferTest, FrameSize) {
-  const uint8_t kTestData[] = {0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10,
-                               11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
-                               22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
-  const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(1337);
-
-  const uint8_t* const data[] = {kTestData};
-  scoped_refptr<AudioBuffer> buffer =
-      AudioBuffer::CopyFrom(kSampleFormatU8, CHANNEL_LAYOUT_STEREO, 2,
-                            kSampleRate, 16, data, kTimestamp);
-  EXPECT_EQ(16, buffer->frame_count());  // 2 channels of 8-bit data
-
-  buffer = AudioBuffer::CopyFrom(kSampleFormatF32, CHANNEL_LAYOUT_4_0, 4,
-                                 kSampleRate, 2, data, kTimestamp);
-  EXPECT_EQ(2, buffer->frame_count());  // now 4 channels of 32-bit data
-}
-
-TEST(AudioBufferTest, ReadU8) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_4_0;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  const int frames = 10;
-  const base::TimeDelta start_time;
-  scoped_refptr<AudioBuffer> buffer =
-      MakeAudioBuffer<uint8_t>(kSampleFormatU8, channel_layout, channels,
-                               kSampleRate, 128, 1, frames, start_time);
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, frames);
-  buffer->ReadFrames(frames, 0, 0, bus.get());
-  VerifyBus(bus.get(), frames, 0, 1.0f / 127.0f);
-
-  // Now read the same data one frame at a time.
-  bus->Zero();
-  for (int i = 0; i < frames; ++i) buffer->ReadFrames(1, i, i, bus.get());
-  VerifyBus(bus.get(), frames, 0, 1.0f / 127.0f);
-}
-
-TEST(AudioBufferTest, ReadS16) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  const int frames = 10;
-  const base::TimeDelta start_time;
-  scoped_refptr<AudioBuffer> buffer =
-      MakeAudioBuffer<int16_t>(kSampleFormatS16, channel_layout, channels,
-                               kSampleRate, 1, 1, frames, start_time);
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, frames);
-  buffer->ReadFrames(frames, 0, 0, bus.get());
-  VerifyBus(bus.get(), frames, 1.0f / std::numeric_limits<int16_t>::max(),
-            1.0f / std::numeric_limits<int16_t>::max());
-
-  // Now read the same data one frame at a time.
-  bus->Zero();
-  for (int i = 0; i < frames; ++i) buffer->ReadFrames(1, i, i, bus.get());
-  VerifyBus(bus.get(), frames, 1.0f / std::numeric_limits<int16_t>::max(),
-            1.0f / std::numeric_limits<int16_t>::max());
-}
-
-TEST(AudioBufferTest, ReadS32) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  const int frames = 20;
-  const base::TimeDelta start_time;
-  scoped_refptr<AudioBuffer> buffer =
-      MakeAudioBuffer<int32_t>(kSampleFormatS32, channel_layout, channels,
-                               kSampleRate, 1, 1, frames, start_time);
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, frames);
-  buffer->ReadFrames(frames, 0, 0, bus.get());
-  VerifyBus(bus.get(), frames, 1.0f / std::numeric_limits<int32_t>::max(),
-            1.0f / std::numeric_limits<int32_t>::max());
-
-  // Read second 10 frames.
-  bus->Zero();
-  buffer->ReadFrames(10, 10, 0, bus.get());
-  VerifyBus(bus.get(), 10, 11.0f / std::numeric_limits<int32_t>::max(),
-            1.0f / std::numeric_limits<int32_t>::max());
-}
-
-TEST(AudioBufferTest, ReadF32) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  const int frames = 20;
-  const base::TimeDelta start_time;
-  scoped_refptr<AudioBuffer> buffer =
-      MakeAudioBuffer<float>(kSampleFormatF32, channel_layout, channels,
-                             kSampleRate, 1.0f, 1.0f, frames, start_time);
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, frames);
-  buffer->ReadFrames(10, 0, 0, bus.get());
-  VerifyBus(bus.get(), 10, 1, 1);
-
-  // Read second 10 frames.
-  bus->Zero();
-  buffer->ReadFrames(10, 10, 0, bus.get());
-  VerifyBus(bus.get(), 10, 11, 1);
-}
-
-TEST(AudioBufferTest, ReadS16Planar) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  const int frames = 20;
-  const base::TimeDelta start_time;
-  scoped_refptr<AudioBuffer> buffer =
-      MakeAudioBuffer<int16_t>(kSampleFormatPlanarS16, channel_layout, channels,
-                               kSampleRate, 1, 1, frames, start_time);
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, frames);
-  buffer->ReadFrames(10, 0, 0, bus.get());
-  VerifyBus(bus.get(), 10, 1.0f / std::numeric_limits<int16_t>::max(),
-            1.0f / std::numeric_limits<int16_t>::max());
-
-  // Read all the frames backwards, one by one. ch[0] should be 20, 19, ...
-  bus->Zero();
-  for (int i = frames - 1; i >= 0; --i) buffer->ReadFrames(1, i, i, bus.get());
-  VerifyBus(bus.get(), frames, 1.0f / std::numeric_limits<int16_t>::max(),
-            1.0f / std::numeric_limits<int16_t>::max());
-
-  // Read 0 frames with different offsets. Existing data in AudioBus should be
-  // unchanged.
-  buffer->ReadFrames(0, 0, 0, bus.get());
-  VerifyBus(bus.get(), frames, 1.0f / std::numeric_limits<int16_t>::max(),
-            1.0f / std::numeric_limits<int16_t>::max());
-  buffer->ReadFrames(0, 0, 10, bus.get());
-  VerifyBus(bus.get(), frames, 1.0f / std::numeric_limits<int16_t>::max(),
-            1.0f / std::numeric_limits<int16_t>::max());
-  buffer->ReadFrames(0, 10, 0, bus.get());
-  VerifyBus(bus.get(), frames, 1.0f / std::numeric_limits<int16_t>::max(),
-            1.0f / std::numeric_limits<int16_t>::max());
-}
-
-TEST(AudioBufferTest, ReadF32Planar) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_4_0;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  const int frames = 100;
-  const base::TimeDelta start_time;
-  scoped_refptr<AudioBuffer> buffer =
-      MakeAudioBuffer<float>(kSampleFormatPlanarF32, channel_layout, channels,
-                             kSampleRate, 1.0f, 1.0f, frames, start_time);
-
-  // Read all 100 frames from the buffer. F32 is planar, so ch[0] should be 1,
-  // 2, 3, 4, ..., ch[1] should be 101, 102, 103, ..., and so on for all 4
-  // channels.
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, 100);
-  buffer->ReadFrames(frames, 0, 0, bus.get());
-  VerifyBus(bus.get(), frames, 1, 1);
-
-  // Now read 20 frames from the middle of the buffer.
-  bus->Zero();
-  buffer->ReadFrames(20, 50, 0, bus.get());
-  VerifyBus(bus.get(), 20, 51, 1);
-}
-
-TEST(AudioBufferTest, EmptyBuffer) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_4_0;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  const int frames = kSampleRate / 100;
-  const base::TimeDelta start_time;
-  scoped_refptr<AudioBuffer> buffer = AudioBuffer::CreateEmptyBuffer(
-      channel_layout, channels, kSampleRate, frames, start_time);
-  EXPECT_EQ(frames, buffer->frame_count());
-  EXPECT_EQ(start_time, buffer->timestamp());
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(10), buffer->duration());
-  EXPECT_FALSE(buffer->end_of_stream());
-
-  // Read all 100 frames from the buffer. All data should be 0.
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, frames);
-  buffer->ReadFrames(frames, 0, 0, bus.get());
-  VerifyBus(bus.get(), frames, 0, 0);
-}
-
-TEST(AudioBufferTest, Trim) {
-  const ChannelLayout channel_layout = CHANNEL_LAYOUT_4_0;
-  const int channels = ChannelLayoutToChannelCount(channel_layout);
-  const int frames = kSampleRate / 10;
-  const base::TimeDelta start_time;
-  const base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
-  scoped_refptr<AudioBuffer> buffer =
-      MakeAudioBuffer<float>(kSampleFormatPlanarF32, channel_layout, channels,
-                             kSampleRate, 0.0f, 1.0f, frames, start_time);
-  EXPECT_EQ(frames, buffer->frame_count());
-  EXPECT_EQ(start_time, buffer->timestamp());
-  EXPECT_EQ(duration, buffer->duration());
-
-  const int ten_ms_of_frames = kSampleRate / 100;
-  const base::TimeDelta ten_ms = base::TimeDelta::FromMilliseconds(10);
-
-  std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, frames);
-  buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get());
-  VerifyBus(bus.get(), buffer->frame_count(), 0.0f, 1.0f);
-
-  // Trim off 10ms of frames from the start.
-  buffer->TrimStart(ten_ms_of_frames);
-  EXPECT_EQ(start_time, buffer->timestamp());
-  EXPECT_EQ(frames - ten_ms_of_frames, buffer->frame_count());
-  EXPECT_EQ(duration - ten_ms, buffer->duration());
-  buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get());
-  VerifyBus(bus.get(), buffer->frame_count(), ten_ms_of_frames, 1.0f);
-
-  // Trim off 10ms of frames from the end.
-  buffer->TrimEnd(ten_ms_of_frames);
-  EXPECT_EQ(start_time, buffer->timestamp());
-  EXPECT_EQ(frames - 2 * ten_ms_of_frames, buffer->frame_count());
-  EXPECT_EQ(duration - 2 * ten_ms, buffer->duration());
-  buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get());
-  VerifyBus(bus.get(), buffer->frame_count(), ten_ms_of_frames, 1.0f);
-
-  // Trim off 40ms more from the start.
-  buffer->TrimStart(4 * ten_ms_of_frames);
-  EXPECT_EQ(start_time, buffer->timestamp());
-  EXPECT_EQ(frames - 6 * ten_ms_of_frames, buffer->frame_count());
-  EXPECT_EQ(duration - 6 * ten_ms, buffer->duration());
-  buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get());
-  VerifyBus(bus.get(), buffer->frame_count(), 5 * ten_ms_of_frames, 1.0f);
-
-  // Trim off the final 40ms from the end.
-  buffer->TrimEnd(4 * ten_ms_of_frames);
-  EXPECT_EQ(0, buffer->frame_count());
-  EXPECT_EQ(start_time, buffer->timestamp());
-  EXPECT_EQ(base::TimeDelta(), buffer->duration());
-}
-
-TEST(AudioBufferTest, TrimRangePlanar) {
-  TrimRangeTest(kSampleFormatPlanarF32);
-}
-
-TEST(AudioBufferTest, TrimRangeInterleaved) { TrimRangeTest(kSampleFormatF32); }
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_bus.cc b/src/cobalt/media/base/audio_bus.cc
deleted file mode 100644
index 65536ef..0000000
--- a/src/cobalt/media/base/audio_bus.cc
+++ /dev/null
@@ -1,336 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_bus.h"
-
-#include <algorithm>
-#include <limits>
-
-#include "base/logging.h"
-#include "base/numerics/safe_conversions.h"
-#include "cobalt/media/base/audio_parameters.h"
-#include "cobalt/media/base/audio_sample_types.h"
-#include "cobalt/media/base/limits.h"
-#include "cobalt/media/base/vector_math.h"
-#include "starboard/memory.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-static bool IsAligned(void* ptr) {
-  return (reinterpret_cast<uintptr_t>(ptr) &
-          (AudioBus::kChannelAlignment - 1)) == 0U;
-}
-
-// In order to guarantee that the memory block for each channel starts at an
-// aligned address when splitting a contiguous block of memory into one block
-// per channel, we may have to make these blocks larger than otherwise needed.
-// We do this by allocating space for potentially more frames than requested.
-// This method returns the required size for the contiguous memory block
-// in bytes and outputs the adjusted number of frames via |out_aligned_frames|.
-static int CalculateMemorySizeInternal(int channels, int frames,
-                                       int* out_aligned_frames) {
-  // Since our internal sample format is float, we can guarantee the alignment
-  // by making the number of frames an integer multiple of
-  // AudioBus::kChannelAlignment / sizeof(float).
-  int aligned_frames =
-      ((frames * sizeof(float) + AudioBus::kChannelAlignment - 1) &
-       ~(AudioBus::kChannelAlignment - 1)) /
-      sizeof(float);
-
-  if (out_aligned_frames) *out_aligned_frames = aligned_frames;
-
-  return sizeof(float) * channels * aligned_frames;
-}
-
-static void ValidateConfig(int channels, int frames) {
-  CHECK_GT(frames, 0);
-  CHECK_GT(channels, 0);
-  CHECK_LE(channels, static_cast<int>(limits::kMaxChannels));
-}
-
-void AudioBus::CheckOverflow(int start_frame, int frames, int total_frames) {
-  CHECK_GE(start_frame, 0);
-  CHECK_GE(frames, 0);
-  CHECK_GT(total_frames, 0);
-  int sum = start_frame + frames;
-  CHECK_LE(sum, total_frames);
-  CHECK_GE(sum, 0);
-}
-
-AudioBus::AudioBus(int channels, int frames)
-    : frames_(frames), can_set_channel_data_(false) {
-  ValidateConfig(channels, frames_);
-
-  int aligned_frames = 0;
-  int size = CalculateMemorySizeInternal(channels, frames, &aligned_frames);
-
-  data_.reset(static_cast<float*>(
-      base::AlignedAlloc(size, AudioBus::kChannelAlignment)));
-
-  BuildChannelData(channels, aligned_frames, data_.get());
-}
-
-AudioBus::AudioBus(int channels, int frames, float* data)
-    : frames_(frames), can_set_channel_data_(false) {
-  // Since |data| may have come from an external source, ensure it's valid.
-  CHECK(data);
-  ValidateConfig(channels, frames_);
-
-  int aligned_frames = 0;
-  CalculateMemorySizeInternal(channels, frames, &aligned_frames);
-
-  BuildChannelData(channels, aligned_frames, data);
-}
-
-AudioBus::AudioBus(int frames, const std::vector<float*>& channel_data)
-    : channel_data_(channel_data),
-      frames_(frames),
-      can_set_channel_data_(false) {
-  ValidateConfig(base::checked_cast<int>(channel_data_.size()), frames_);
-
-  // Sanity check wrapped vector for alignment and channel count.
-  for (size_t i = 0; i < channel_data_.size(); ++i)
-    DCHECK(IsAligned(channel_data_[i]));
-}
-
-AudioBus::AudioBus(int channels)
-    : channel_data_(channels), frames_(0), can_set_channel_data_(true) {
-  CHECK_GT(channels, 0);
-  for (size_t i = 0; i < channel_data_.size(); ++i) channel_data_[i] = NULL;
-}
-
-AudioBus::~AudioBus() {}
-
-std::unique_ptr<AudioBus> AudioBus::Create(int channels, int frames) {
-  return base::WrapUnique(new AudioBus(channels, frames));
-}
-
-std::unique_ptr<AudioBus> AudioBus::Create(const AudioParameters& params) {
-  return base::WrapUnique(
-      new AudioBus(params.channels(), params.frames_per_buffer()));
-}
-
-std::unique_ptr<AudioBus> AudioBus::CreateWrapper(int channels) {
-  return base::WrapUnique(new AudioBus(channels));
-}
-
-std::unique_ptr<AudioBus> AudioBus::WrapVector(
-    int frames, const std::vector<float*>& channel_data) {
-  return base::WrapUnique(new AudioBus(frames, channel_data));
-}
-
-std::unique_ptr<AudioBus> AudioBus::WrapMemory(int channels, int frames,
-                                               void* data) {
-  // |data| must be aligned by AudioBus::kChannelAlignment.
-  CHECK(IsAligned(data));
-  return base::WrapUnique(
-      new AudioBus(channels, frames, static_cast<float*>(data)));
-}
-
-std::unique_ptr<AudioBus> AudioBus::WrapMemory(const AudioParameters& params,
-                                               void* data) {
-  // |data| must be aligned by AudioBus::kChannelAlignment.
-  CHECK(IsAligned(data));
-  return base::WrapUnique(new AudioBus(params.channels(),
-                                       params.frames_per_buffer(),
-                                       static_cast<float*>(data)));
-}
-
-void AudioBus::SetChannelData(int channel, float* data) {
-  CHECK(can_set_channel_data_);
-  CHECK(data);
-  CHECK_GE(channel, 0);
-  CHECK_LT(static_cast<size_t>(channel), channel_data_.size());
-  DCHECK(IsAligned(data));
-  channel_data_[channel] = data;
-}
-
-void AudioBus::set_frames(int frames) {
-  CHECK(can_set_channel_data_);
-  ValidateConfig(static_cast<int>(channel_data_.size()), frames);
-  frames_ = frames;
-}
-
-void AudioBus::ZeroFramesPartial(int start_frame, int frames) {
-  CheckOverflow(start_frame, frames, frames_);
-
-  if (frames <= 0) return;
-
-  for (size_t i = 0; i < channel_data_.size(); ++i) {
-    SbMemorySet(channel_data_[i] + start_frame, 0,
-                frames * sizeof(*channel_data_[i]));
-  }
-}
-
-void AudioBus::ZeroFrames(int frames) { ZeroFramesPartial(0, frames); }
-
-void AudioBus::Zero() { ZeroFrames(frames_); }
-
-bool AudioBus::AreFramesZero() const {
-  for (size_t i = 0; i < channel_data_.size(); ++i) {
-    for (int j = 0; j < frames_; ++j) {
-      if (channel_data_[i][j]) return false;
-    }
-  }
-  return true;
-}
-
-int AudioBus::CalculateMemorySize(const AudioParameters& params) {
-  return CalculateMemorySizeInternal(params.channels(),
-                                     params.frames_per_buffer(), NULL);
-}
-
-int AudioBus::CalculateMemorySize(int channels, int frames) {
-  return CalculateMemorySizeInternal(channels, frames, NULL);
-}
-
-void AudioBus::BuildChannelData(int channels, int aligned_frames, float* data) {
-  DCHECK(IsAligned(data));
-  DCHECK_EQ(channel_data_.size(), 0U);
-  // Initialize |channel_data_| with pointers into |data|.
-  channel_data_.reserve(channels);
-  for (int i = 0; i < channels; ++i)
-    channel_data_.push_back(data + i * aligned_frames);
-}
-
-// Forwards to non-deprecated version.
-void AudioBus::FromInterleaved(const void* source, int frames,
-                               int bytes_per_sample) {
-  switch (bytes_per_sample) {
-    case 1:
-      FromInterleaved<UnsignedInt8SampleTypeTraits>(
-          reinterpret_cast<const uint8_t*>(source), frames);
-      break;
-    case 2:
-      FromInterleaved<SignedInt16SampleTypeTraits>(
-          reinterpret_cast<const int16_t*>(source), frames);
-      break;
-    case 4:
-      FromInterleaved<SignedInt32SampleTypeTraits>(
-          reinterpret_cast<const int32_t*>(source), frames);
-      break;
-    default:
-      NOTREACHED() << "Unsupported bytes per sample encountered: "
-                   << bytes_per_sample;
-      ZeroFrames(frames);
-  }
-}
-
-// Forwards to non-deprecated version.
-void AudioBus::FromInterleavedPartial(const void* source, int start_frame,
-                                      int frames, int bytes_per_sample) {
-  switch (bytes_per_sample) {
-    case 1:
-      FromInterleavedPartial<UnsignedInt8SampleTypeTraits>(
-          reinterpret_cast<const uint8_t*>(source), start_frame, frames);
-      break;
-    case 2:
-      FromInterleavedPartial<SignedInt16SampleTypeTraits>(
-          reinterpret_cast<const int16_t*>(source), start_frame, frames);
-      break;
-    case 4:
-      FromInterleavedPartial<SignedInt32SampleTypeTraits>(
-          reinterpret_cast<const int32_t*>(source), start_frame, frames);
-      break;
-    default:
-      NOTREACHED() << "Unsupported bytes per sample encountered: "
-                   << bytes_per_sample;
-      ZeroFramesPartial(start_frame, frames);
-  }
-}
-
-// Forwards to non-deprecated version.
-void AudioBus::ToInterleaved(int frames, int bytes_per_sample,
-                             void* dest) const {
-  switch (bytes_per_sample) {
-    case 1:
-      ToInterleaved<UnsignedInt8SampleTypeTraits>(
-          frames, reinterpret_cast<uint8_t*>(dest));
-      break;
-    case 2:
-      ToInterleaved<SignedInt16SampleTypeTraits>(
-          frames, reinterpret_cast<int16_t*>(dest));
-      break;
-    case 4:
-      ToInterleaved<SignedInt32SampleTypeTraits>(
-          frames, reinterpret_cast<int32_t*>(dest));
-      break;
-    default:
-      NOTREACHED() << "Unsupported bytes per sample encountered: "
-                   << bytes_per_sample;
-  }
-}
-
-// Forwards to non-deprecated version.
-void AudioBus::ToInterleavedPartial(int start_frame, int frames,
-                                    int bytes_per_sample, void* dest) const {
-  switch (bytes_per_sample) {
-    case 1:
-      ToInterleavedPartial<UnsignedInt8SampleTypeTraits>(
-          start_frame, frames, reinterpret_cast<uint8_t*>(dest));
-      break;
-    case 2:
-      ToInterleavedPartial<SignedInt16SampleTypeTraits>(
-          start_frame, frames, reinterpret_cast<int16_t*>(dest));
-      break;
-    case 4:
-      ToInterleavedPartial<SignedInt32SampleTypeTraits>(
-          start_frame, frames, reinterpret_cast<int32_t*>(dest));
-      break;
-    default:
-      NOTREACHED() << "Unsupported bytes per sample encountered: "
-                   << bytes_per_sample;
-  }
-}
-
-void AudioBus::CopyTo(AudioBus* dest) const {
-  CopyPartialFramesTo(0, frames(), 0, dest);
-}
-
-void AudioBus::CopyPartialFramesTo(int source_start_frame, int frame_count,
-                                   int dest_start_frame, AudioBus* dest) const {
-  CHECK_EQ(channels(), dest->channels());
-  CHECK_LE(source_start_frame + frame_count, frames());
-  CHECK_LE(dest_start_frame + frame_count, dest->frames());
-
-  // Since we don't know if the other AudioBus is wrapped or not (and we don't
-  // want to care), just copy using the public channel() accessors.
-  for (int i = 0; i < channels(); ++i) {
-    SbMemoryCopy(dest->channel(i) + dest_start_frame,
-                 channel(i) + source_start_frame,
-                 sizeof(*channel(i)) * frame_count);
-  }
-}
-
-void AudioBus::Scale(float volume) {
-  if (volume > 0 && volume != 1) {
-    for (int i = 0; i < channels(); ++i)
-      vector_math::FMUL(channel(i), volume, frames(), channel(i));
-  } else if (volume == 0) {
-    Zero();
-  }
-}
-
-void AudioBus::SwapChannels(int a, int b) {
-  DCHECK(a < channels() && a >= 0);
-  DCHECK(b < channels() && b >= 0);
-  DCHECK_NE(a, b);
-  std::swap(channel_data_[a], channel_data_[b]);
-}
-
-scoped_refptr<AudioBusRefCounted> AudioBusRefCounted::Create(int channels,
-                                                             int frames) {
-  return scoped_refptr<AudioBusRefCounted>(
-      new AudioBusRefCounted(channels, frames));
-}
-
-AudioBusRefCounted::AudioBusRefCounted(int channels, int frames)
-    : AudioBus(channels, frames) {}
-
-AudioBusRefCounted::~AudioBusRefCounted() {}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_bus.h b/src/cobalt/media/base/audio_bus.h
deleted file mode 100644
index 5870486..0000000
--- a/src/cobalt/media/base/audio_bus.h
+++ /dev/null
@@ -1,311 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_BUS_H_
-#define COBALT_MEDIA_BASE_AUDIO_BUS_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/aligned_memory.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "cobalt/media/base/media_export.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-class AudioParameters;
-
-// Represents a sequence of audio frames containing frames() audio samples for
-// each of channels() channels. The data is stored as a set of contiguous
-// float arrays with one array per channel. The memory for the arrays is either
-// allocated and owned by the AudioBus or it is provided to one of the factory
-// methods. AudioBus guarantees that it allocates memory such that float array
-// for each channel is aligned by AudioBus::kChannelAlignment bytes and it
-// requires the same for memory passed to its Wrap...() factory methods.
-// TODO(chfremer): There are currently no unit tests involving CreateWrapper and
-// SetChannelData, so we need to add them.
-class MEDIA_EXPORT AudioBus {
- public:
-  // Guaranteed alignment of each channel's data; use 16-byte alignment for easy
-  // SSE optimizations.
-  enum { kChannelAlignment = 16 };
-
-  // Creates a new AudioBus and allocates |channels| of length |frames|.  Uses
-  // channels() and frames_per_buffer() from AudioParameters if given.
-  static scoped_ptr<AudioBus> Create(int channels, int frames);
-  static scoped_ptr<AudioBus> Create(const AudioParameters& params);
-
-  // Creates a new AudioBus with the given number of channels, but zero length.
-  // Clients are expected to subsequently call SetChannelData() and set_frames()
-  // to wrap externally allocated memory.
-  static scoped_ptr<AudioBus> CreateWrapper(int channels);
-
-  // Creates a new AudioBus from an existing channel vector.  Does not transfer
-  // ownership of |channel_data| to AudioBus; i.e., |channel_data| must outlive
-  // the returned AudioBus.  Each channel must be aligned by kChannelAlignment.
-  static scoped_ptr<AudioBus> WrapVector(
-      int frames, const std::vector<float*>& channel_data);
-
-  // Creates a new AudioBus by wrapping an existing block of memory.  Block must
-  // be at least CalculateMemorySize() bytes in size.  |data| must outlive the
-  // returned AudioBus.  |data| must be aligned by kChannelAlignment.
-  static scoped_ptr<AudioBus> WrapMemory(int channels, int frames, void* data);
-  static scoped_ptr<AudioBus> WrapMemory(const AudioParameters& params,
-                                         void* data);
-
-  // Based on the given number of channels and frames, calculates the minimum
-  // required size in bytes of a contiguous block of memory to be passed to
-  // AudioBus for storage of the audio data.
-  // Uses channels() and frames_per_buffer() from AudioParameters if given.
-  static int CalculateMemorySize(int channels, int frames);
-  static int CalculateMemorySize(const AudioParameters& params);
-
-  // Methods that are expected to be called after AudioBus::CreateWrapper() in
-  // order to wrap externally allocated memory. Note: It is illegal to call
-  // these methods when using a factory method other than CreateWrapper().
-  void SetChannelData(int channel, float* data);
-  void set_frames(int frames);
-
-  // Overwrites the sample values stored in this AudioBus instance with values
-  // from a given interleaved |source_buffer| with expected layout
-  // [ch0, ch1, ..., chN, ch0, ch1, ...] and sample values in the format
-  // corresponding to the given SourceSampleTypeTraits.
-  // The sample values are converted to float values by means of the method
-  // convert_to_float32() provided by the SourceSampleTypeTraits. For a list of
-  // ready-to-use SampleTypeTraits, see file audio_sample_types.h.
-  // If |num_frames_to_write| is less than frames(), the remaining frames are
-  // zeroed out. If |num_frames_to_write| is more than frames(), this results in
-  // undefined behavior.
-  template <class SourceSampleTypeTraits>
-  void FromInterleaved(
-      const typename SourceSampleTypeTraits::ValueType* source_buffer,
-      int num_frames_to_write);
-
-  // DEPRECATED (https://crbug.com/580391)
-  // Please use the version templated with SourceSampleTypeTraits instead.
-  // TODO(chfremer): Remove (https://crbug.com/619623)
-  void FromInterleaved(const void* source, int frames, int bytes_per_sample);
-
-  // Similar to FromInterleaved...(), but overwrites the frames starting at a
-  // given offset |write_offset_in_frames| and does not zero out frames that are
-  // not overwritten.
-  template <class SourceSampleTypeTraits>
-  void FromInterleavedPartial(
-      const typename SourceSampleTypeTraits::ValueType* source_buffer,
-      int write_offset_in_frames, int num_frames_to_write);
-
-  // DEPRECATED (https://crbug.com/580391)
-  // Please use the version templated with SourceSampleTypeTraits instead.
-  // TODO(chfremer): Remove (https://crbug.com/619623)
-  void FromInterleavedPartial(const void* source, int start_frame, int frames,
-                              int bytes_per_sample);
-
-  // Reads the sample values stored in this AudioBus instance and places them
-  // into the given |dest_buffer| in interleaved format using the sample format
-  // specified by TargetSampleTypeTraits. For a list of ready-to-use
-  // SampleTypeTraits, see file audio_sample_types.h. If |num_frames_to_read| is
-  // larger than frames(), this results in undefined behavior.
-  template <class TargetSampleTypeTraits>
-  void ToInterleaved(
-      int num_frames_to_read,
-      typename TargetSampleTypeTraits::ValueType* dest_buffer) const;
-
-  // DEPRECATED (https://crbug.com/580391)
-  // Please use the version templated with TargetSampleTypeTraits instead.
-  // TODO(chfremer): Remove (https://crbug.com/619623)
-  void ToInterleaved(int frames, int bytes_per_sample, void* dest) const;
-
-  // Similar to ToInterleaved(), but reads the frames starting at a given
-  // offset |read_offset_in_frames|.
-  template <class TargetSampleTypeTraits>
-  void ToInterleavedPartial(
-      int read_offset_in_frames, int num_frames_to_read,
-      typename TargetSampleTypeTraits::ValueType* dest_buffer) const;
-
-  // DEPRECATED (https://crbug.com/580391)
-  // Please use the version templated with TargetSampleTypeTraits instead.
-  // TODO(chfremer): Remove (https://crbug.com/619623)
-  void ToInterleavedPartial(int start_frame, int frames, int bytes_per_sample,
-                            void* dest) const;
-
-  // Helper method for copying channel data from one AudioBus to another.  Both
-  // AudioBus object must have the same frames() and channels().
-  void CopyTo(AudioBus* dest) const;
-
-  // Helper method to copy frames from one AudioBus to another. Both AudioBus
-  // objects must have the same number of channels(). |source_start_frame| is
-  // the starting offset. |dest_start_frame| is the starting offset in |dest|.
-  // |frame_count| is the number of frames to copy.
-  void CopyPartialFramesTo(int source_start_frame, int frame_count,
-                           int dest_start_frame, AudioBus* dest) const;
-
-  // Returns a raw pointer to the requested channel.  Pointer is guaranteed to
-  // have a 16-byte alignment.  Warning: Do not rely on having sane (i.e. not
-  // inf, nan, or between [-1.0, 1.0]) values in the channel data.
-  float* channel(int channel) { return channel_data_[channel]; }
-  const float* channel(int channel) const { return channel_data_[channel]; }
-
-  // Returns the number of channels.
-  int channels() const { return static_cast<int>(channel_data_.size()); }
-  // Returns the number of frames.
-  int frames() const { return frames_; }
-
-  // Helper method for zeroing out all channels of audio data.
-  void Zero();
-  void ZeroFrames(int frames);
-  void ZeroFramesPartial(int start_frame, int frames);
-
-  // Checks if all frames are zero.
-  bool AreFramesZero() const;
-
-  // Scale internal channel values by |volume| >= 0.  If an invalid value
-  // is provided, no adjustment is done.
-  void Scale(float volume);
-
-  // Swaps channels identified by |a| and |b|.  The caller needs to make sure
-  // the channels are valid.
-  void SwapChannels(int a, int b);
-
-  virtual ~AudioBus();
-
- protected:
-  AudioBus(int channels, int frames);
-  AudioBus(int channels, int frames, float* data);
-  AudioBus(int frames, const std::vector<float*>& channel_data);
-  explicit AudioBus(int channels);
-
- private:
-  // Helper method for building |channel_data_| from a block of memory.  |data|
-  // must be at least CalculateMemorySize(...) bytes in size.
-  void BuildChannelData(int channels, int aligned_frame, float* data);
-
-  static void CheckOverflow(int start_frame, int frames, int total_frames);
-
-  template <class SourceSampleTypeTraits>
-  static void CopyConvertFromInterleavedSourceToAudioBus(
-      const typename SourceSampleTypeTraits::ValueType* source_buffer,
-      int write_offset_in_frames, int num_frames_to_write, AudioBus* dest);
-
-  template <class TargetSampleTypeTraits>
-  static void CopyConvertFromAudioBusToInterleavedTarget(
-      const AudioBus* source, int read_offset_in_frames, int num_frames_to_read,
-      typename TargetSampleTypeTraits::ValueType* dest_buffer);
-
-  // Contiguous block of channel memory.
-  scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> data_;
-
-  // One float pointer per channel pointing to a contiguous block of memory for
-  // that channel. If the memory is owned by this instance, this will
-  // point to the memory in |data_|. Otherwise, it may point to memory provided
-  // by the client.
-  std::vector<float*> channel_data_;
-  int frames_;
-
-  // Protect SetChannelData() and set_frames() for use by CreateWrapper().
-  bool can_set_channel_data_;
-
-  DISALLOW_COPY_AND_ASSIGN(AudioBus);
-};
-
-// Delegates to FromInterleavedPartial()
-template <class SourceSampleTypeTraits>
-void AudioBus::FromInterleaved(
-    const typename SourceSampleTypeTraits::ValueType* source_buffer,
-    int num_frames_to_write) {
-  FromInterleavedPartial<SourceSampleTypeTraits>(source_buffer, 0,
-                                                 num_frames_to_write);
-  // Zero any remaining frames.
-  ZeroFramesPartial(num_frames_to_write, frames_ - num_frames_to_write);
-}
-
-template <class SourceSampleTypeTraits>
-void AudioBus::FromInterleavedPartial(
-    const typename SourceSampleTypeTraits::ValueType* source_buffer,
-    int write_offset_in_frames, int num_frames_to_write) {
-  CheckOverflow(write_offset_in_frames, num_frames_to_write, frames_);
-  CopyConvertFromInterleavedSourceToAudioBus<SourceSampleTypeTraits>(
-      source_buffer, write_offset_in_frames, num_frames_to_write, this);
-}
-
-// Delegates to ToInterleavedPartial()
-template <class TargetSampleTypeTraits>
-void AudioBus::ToInterleaved(
-    int num_frames_to_read,
-    typename TargetSampleTypeTraits::ValueType* dest_buffer) const {
-  ToInterleavedPartial<TargetSampleTypeTraits>(0, num_frames_to_read,
-                                               dest_buffer);
-}
-
-template <class TargetSampleTypeTraits>
-void AudioBus::ToInterleavedPartial(
-    int read_offset_in_frames, int num_frames_to_read,
-    typename TargetSampleTypeTraits::ValueType* dest) const {
-  CheckOverflow(read_offset_in_frames, num_frames_to_read, frames_);
-  CopyConvertFromAudioBusToInterleavedTarget<TargetSampleTypeTraits>(
-      this, read_offset_in_frames, num_frames_to_read, dest);
-}
-
-// TODO(chfremer): Consider using vector instructions to speed this up,
-//                 https://crbug.com/619628
-template <class SourceSampleTypeTraits>
-void AudioBus::CopyConvertFromInterleavedSourceToAudioBus(
-    const typename SourceSampleTypeTraits::ValueType* source_buffer,
-    int write_offset_in_frames, int num_frames_to_write, AudioBus* dest) {
-  const int channels = dest->channels();
-  for (int ch = 0; ch < channels; ++ch) {
-    float* channel_data = dest->channel(ch);
-    for (int target_frame_index = write_offset_in_frames,
-             read_pos_in_source = ch;
-         target_frame_index < write_offset_in_frames + num_frames_to_write;
-         ++target_frame_index, read_pos_in_source += channels) {
-      auto source_value = source_buffer[read_pos_in_source];
-      channel_data[target_frame_index] =
-          SourceSampleTypeTraits::ToFloat(source_value);
-    }
-  }
-}
-
-// TODO(chfremer): Consider using vector instructions to speed this up,
-//                 https://crbug.com/619628
-template <class TargetSampleTypeTraits>
-void AudioBus::CopyConvertFromAudioBusToInterleavedTarget(
-    const AudioBus* source, int read_offset_in_frames, int num_frames_to_read,
-    typename TargetSampleTypeTraits::ValueType* dest_buffer) {
-  const int channels = source->channels();
-  for (int ch = 0; ch < channels; ++ch) {
-    const float* channel_data = source->channel(ch);
-    for (int source_frame_index = read_offset_in_frames, write_pos_in_dest = ch;
-         source_frame_index < read_offset_in_frames + num_frames_to_read;
-         ++source_frame_index, write_pos_in_dest += channels) {
-      float sourceSampleValue = channel_data[source_frame_index];
-      dest_buffer[write_pos_in_dest] =
-          TargetSampleTypeTraits::FromFloat(sourceSampleValue);
-    }
-  }
-}
-
-// RefCounted version of AudioBus. This is not meant for general use. Only use
-// this when your lifetime requirements make it impossible to use an
-// AudioBus scoped_ptr.
-class MEDIA_EXPORT AudioBusRefCounted
-    : public media::AudioBus,
-      public base::RefCountedThreadSafe<AudioBusRefCounted> {
- public:
-  static scoped_refptr<AudioBusRefCounted> Create(int channels, int frames);
-
- private:
-  friend class base::RefCountedThreadSafe<AudioBusRefCounted>;
-
-  AudioBusRefCounted(int channels, int frames);
-  ~AudioBusRefCounted() OVERRIDE;
-
-  DISALLOW_COPY_AND_ASSIGN(AudioBusRefCounted);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_BUS_H_
diff --git a/src/cobalt/media/base/audio_capturer_source.h b/src/cobalt/media/base/audio_capturer_source.h
deleted file mode 100644
index 9f7f3fa..0000000
--- a/src/cobalt/media/base/audio_capturer_source.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_CAPTURER_SOURCE_H_
-#define COBALT_MEDIA_BASE_AUDIO_CAPTURER_SOURCE_H_
-
-#include <string>
-#include <vector>
-
-#include "base/memory/ref_counted.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "cobalt/media/base/audio_parameters.h"
-#include "cobalt/media/base/media_export.h"
-
-namespace cobalt {
-namespace media {
-
-// AudioCapturerSource is an interface representing the source for
-// captured audio.  An implementation will periodically call Capture() on a
-// callback object.
-class AudioCapturerSource
-    : public base::RefCountedThreadSafe<media::AudioCapturerSource> {
- public:
-  class CaptureCallback {
-   public:
-    // Callback to deliver the captured data from the OS.
-    // TODO(chcunningham): Update delay argument to use frames instead of
-    // milliseconds to prevent loss of precision. See http://crbug.com/587291.
-    virtual void Capture(const AudioBus* audio_source,
-                         int audio_delay_milliseconds, double volume,
-                         bool key_pressed) = 0;
-
-    // Signals an error has occurred.
-    virtual void OnCaptureError(const std::string& message) = 0;
-
-   protected:
-    virtual ~CaptureCallback() {}
-  };
-
-  // Sets information about the audio stream format and the device
-  // to be used. It must be called before any of the other methods.
-  // The |session_id| is used by the browser to identify which input device to
-  // be used. For clients who do not care about device permission and device
-  // selection, pass |session_id| using
-  // AudioInputDeviceManager::kFakeOpenSessionId.
-  virtual void Initialize(const AudioParameters& params,
-                          CaptureCallback* callback, int session_id) = 0;
-
-  // Starts the audio recording.
-  virtual void Start() = 0;
-
-  // Stops the audio recording. This API is synchronous, and no more data
-  // callback will be passed to the client after it is being called.
-  virtual void Stop() = 0;
-
-  // Sets the capture volume, with range [0.0, 1.0] inclusive.
-  virtual void SetVolume(double volume) = 0;
-
-  // Enables or disables the WebRtc AGC control.
-  virtual void SetAutomaticGainControl(bool enable) = 0;
-
- protected:
-  friend class base::RefCountedThreadSafe<AudioCapturerSource>;
-  virtual ~AudioCapturerSource() {}
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_CAPTURER_SOURCE_H_
diff --git a/src/cobalt/media/base/audio_decoder.cc b/src/cobalt/media/base/audio_decoder.cc
deleted file mode 100644
index ea41120..0000000
--- a/src/cobalt/media/base/audio_decoder.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_decoder.h"
-
-#include "cobalt/media/base/audio_buffer.h"
-
-namespace cobalt {
-namespace media {
-
-AudioDecoder::AudioDecoder() {}
-
-AudioDecoder::~AudioDecoder() {}
-
-bool AudioDecoder::NeedsBitstreamConversion() const { return false; }
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_fifo.cc b/src/cobalt/media/base/audio_fifo.cc
deleted file mode 100644
index 87a3156..0000000
--- a/src/cobalt/media/base/audio_fifo.cc
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_fifo.h"
-
-#include "base/logging.h"
-#include "starboard/memory.h"
-
-namespace cobalt {
-namespace media {
-
-// Given current position in the FIFO, the maximum number of elements in the
-// FIFO and the size of the input; this method provides two output results:
-// |size| and |wrap_size|. These two results can then be utilized for memcopy
-// operations to and from the FIFO.
-// Under "normal" circumstances, |size| will be equal to |in_size| and
-// |wrap_size| will be zero. This case corresponding to the non-wrapping case
-// where we have not yet reached the "edge" of the FIFO. If |pos| + |in_size|
-// exceeds the total size of the FIFO, we must wrap around and start reusing
-// a part the allocated memory. The size of this part is given by |wrap_size|.
-static void GetSizes(int pos, int max_size, int in_size, int* size,
-                     int* wrap_size) {
-  if (pos + in_size > max_size) {
-    // Wrapping is required => derive size of each segment.
-    *size = max_size - pos;
-    *wrap_size = in_size - *size;
-  } else {
-    // Wrapping is not required.
-    *size = in_size;
-    *wrap_size = 0;
-  }
-}
-
-// Updates the read/write position with |step| modulo the maximum number of
-// elements in the FIFO to ensure that the position counters wraps around at
-// the endpoint.
-static int UpdatePos(int pos, int step, int max_size) {
-  return ((pos + step) % max_size);
-}
-
-AudioFifo::AudioFifo(int channels, int frames)
-    : audio_bus_(AudioBus::Create(channels, frames)),
-      max_frames_(frames),
-      frames_pushed_(0),
-      frames_consumed_(0),
-      read_pos_(0),
-      write_pos_(0) {}
-
-AudioFifo::~AudioFifo() {}
-
-int AudioFifo::frames() const {
-  int delta = frames_pushed_ - frames_consumed_;
-  return delta;
-}
-
-void AudioFifo::Push(const AudioBus* source) {
-  DCHECK(source);
-  DCHECK_EQ(source->channels(), audio_bus_->channels());
-
-  // Ensure that there is space for the new data in the FIFO.
-  const int source_size = source->frames();
-  CHECK_LE(source_size + frames(), max_frames_);
-
-  // Figure out if wrapping is needed and if so what segment sizes we need
-  // when adding the new audio bus content to the FIFO.
-  int append_size = 0;
-  int wrap_size = 0;
-  GetSizes(write_pos_, max_frames(), source_size, &append_size, &wrap_size);
-
-  // Copy all channels from the source to the FIFO. Wrap around if needed.
-  for (int ch = 0; ch < source->channels(); ++ch) {
-    float* dest = audio_bus_->channel(ch);
-    const float* src = source->channel(ch);
-
-    // Append part of (or the complete) source to the FIFO.
-    SbMemoryCopy(&dest[write_pos_], &src[0], append_size * sizeof(src[0]));
-    if (wrap_size > 0) {
-      // Wrapping is needed: copy remaining part from the source to the FIFO.
-      SbMemoryCopy(&dest[0], &src[append_size], wrap_size * sizeof(src[0]));
-    }
-  }
-
-  frames_pushed_ += source_size;
-  DCHECK_LE(frames(), max_frames());
-  write_pos_ = UpdatePos(write_pos_, source_size, max_frames());
-}
-
-void AudioFifo::Consume(AudioBus* destination, int start_frame,
-                        int frames_to_consume) {
-  DCHECK(destination);
-  DCHECK_EQ(destination->channels(), audio_bus_->channels());
-
-  // It is not possible to ask for more data than what is available in the FIFO.
-  CHECK_LE(frames_to_consume, frames());
-
-  // A copy from the FIFO to |destination| will only be performed if the
-  // allocated memory in |destination| is sufficient.
-  CHECK_LE(frames_to_consume + start_frame, destination->frames());
-
-  // Figure out if wrapping is needed and if so what segment sizes we need
-  // when removing audio bus content from the FIFO.
-  int consume_size = 0;
-  int wrap_size = 0;
-  GetSizes(read_pos_, max_frames(), frames_to_consume, &consume_size,
-           &wrap_size);
-
-  // For all channels, remove the requested amount of data from the FIFO
-  // and copy the content to the destination. Wrap around if needed.
-  for (int ch = 0; ch < destination->channels(); ++ch) {
-    float* dest = destination->channel(ch);
-    const float* src = audio_bus_->channel(ch);
-
-    // Copy a selected part of the FIFO to the destination.
-    SbMemoryCopy(&dest[start_frame], &src[read_pos_],
-                 consume_size * sizeof(src[0]));
-    if (wrap_size > 0) {
-      // Wrapping is needed: copy remaining part to the destination.
-      SbMemoryCopy(&dest[consume_size + start_frame], &src[0],
-                   wrap_size * sizeof(src[0]));
-    }
-  }
-
-  frames_consumed_ += frames_to_consume;
-  read_pos_ = UpdatePos(read_pos_, frames_to_consume, max_frames());
-}
-
-void AudioFifo::Clear() {
-  frames_pushed_ = 0;
-  frames_consumed_ = 0;
-  read_pos_ = 0;
-  write_pos_ = 0;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_fifo.h b/src/cobalt/media/base/audio_fifo.h
deleted file mode 100644
index 007aa14..0000000
--- a/src/cobalt/media/base/audio_fifo.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_FIFO_H_
-#define COBALT_MEDIA_BASE_AUDIO_FIFO_H_
-
-#include <memory>
-
-#include "base/basictypes.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "cobalt/media/base/media_export.h"
-
-namespace cobalt {
-namespace media {
-
-// First-in first-out container for AudioBus elements.
-// The maximum number of audio frames in the FIFO is set at construction and
-// can not be extended dynamically.  The allocated memory is utilized as a
-// ring buffer.
-// This class is thread-unsafe.
-class MEDIA_EXPORT AudioFifo {
- public:
-  // Creates a new AudioFifo and allocates |channels| of length |frames|.
-  AudioFifo(int channels, int frames);
-  virtual ~AudioFifo();
-
-  // Pushes all audio channel data from |source| to the FIFO.
-  // Push() will crash if the allocated space is insufficient.
-  void Push(const AudioBus* source);
-
-  // Consumes |frames_to_consume| audio frames from the FIFO and copies
-  // them to |destination| starting at position |start_frame|.
-  // Consume() will crash if the FIFO does not contain |frames_to_consume|
-  // frames or if there is insufficient space in |destination| to store the
-  // frames.
-  void Consume(AudioBus* destination, int start_frame, int frames_to_consume);
-
-  // Empties the FIFO without deallocating any memory.
-  void Clear();
-
-  // Number of actual audio frames in the FIFO.
-  int frames() const;
-
-  int max_frames() const { return max_frames_; }
-
- private:
-  // The actual FIFO is an audio bus implemented as a ring buffer.
-  std::unique_ptr<AudioBus> audio_bus_;
-
-  // Maximum number of elements the FIFO can contain.
-  // This value is set by |frames| in the constructor.
-  const int max_frames_;
-
-  // Number of actual elements in the FIFO.
-  int frames_pushed_;
-  int frames_consumed_;
-
-  // Current read position.
-  int read_pos_;
-
-  // Current write position.
-  int write_pos_;
-
-  DISALLOW_COPY_AND_ASSIGN(AudioFifo);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_FIFO_H_
diff --git a/src/cobalt/media/base/audio_hash.cc b/src/cobalt/media/base/audio_hash.cc
deleted file mode 100644
index f88da39..0000000
--- a/src/cobalt/media/base/audio_hash.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_hash.h"
-
-// MSVC++ requires this to be set before any other includes to get M_PI.
-#define _USE_MATH_DEFINES
-#include <cmath>
-#include <sstream>
-
-#include "base/basictypes.h"
-#include "base/stringprintf.h"
-#include "cobalt/media/base/audio_bus.h"
-
-namespace cobalt {
-namespace media {
-
-AudioHash::AudioHash() : audio_hash_(), sample_count_(0) {}
-
-AudioHash::~AudioHash() {}
-
-void AudioHash::Update(const AudioBus* audio_bus, int frames) {
-  // Use uint32_t to ensure overflow is a defined operation.
-  for (uint32_t ch = 0; ch < static_cast<uint32_t>(audio_bus->channels());
-       ++ch) {
-    const float* channel = audio_bus->channel(ch);
-    for (uint32_t i = 0; i < static_cast<uint32_t>(frames); ++i) {
-      const uint32_t kSampleIndex = sample_count_ + i;
-      const uint32_t kHashIndex =
-          (kSampleIndex * (ch + 1)) % arraysize(audio_hash_);
-
-      // Mix in a sine wave with the result so we ensure that sequences of empty
-      // buffers don't result in an empty hash.
-      if (ch == 0) {
-        audio_hash_[kHashIndex] +=
-            channel[i] + sin(2.0 * M_PI * M_PI * kSampleIndex);
-      } else {
-        audio_hash_[kHashIndex] += channel[i];
-      }
-    }
-  }
-
-  sample_count_ += static_cast<uint32_t>(frames);
-}
-
-std::string AudioHash::ToString() const {
-  std::string result;
-  for (size_t i = 0; i < arraysize(audio_hash_); ++i)
-    result += base::StringPrintf("%.2f,", audio_hash_[i]);
-  return result;
-}
-
-bool AudioHash::IsEquivalent(const std::string& other, double tolerance) const {
-  float other_hash;
-  char comma;
-
-  std::stringstream is(other);
-  for (size_t i = 0; i < arraysize(audio_hash_); ++i) {
-    is >> other_hash >> comma;
-    if (fabs(audio_hash_[i] - other_hash) > tolerance) return false;
-  }
-  return true;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_hash.h b/src/cobalt/media/base/audio_hash.h
deleted file mode 100644
index 66594b4..0000000
--- a/src/cobalt/media/base/audio_hash.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_HASH_H_
-#define COBALT_MEDIA_BASE_AUDIO_HASH_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/string_piece.h"
-#include "cobalt/media/base/media_export.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-class AudioBus;
-
-// Computes a running hash for a series of AudioBus objects.  The hash is the
-// sum of each sample bucketed based on the frame index, channel number, and
-// current hash count.  The hash was designed with two properties in mind:
-//
-//   1. Uniform error distribution across the input sample.
-//   2. Resilience to error below a certain threshold.
-//
-// The first is achieved by using a simple summing approach and moving position
-// weighting into the bucket choice.  The second is handled during conversion to
-// string by rounding out values to only two decimal places.
-//
-// Using only two decimal places allows for roughly -40 dBFS of error.  For
-// reference, SincResampler produces an RMS error of around -15 dBFS.  See
-// http://en.wikipedia.org/wiki/DBFS and http://crbug.com/168204 for more info.
-class MEDIA_EXPORT AudioHash {
- public:
-  AudioHash();
-  ~AudioHash();
-
-  // Update current hash with the contents of the provided AudioBus.
-  void Update(const AudioBus* audio_bus, int frames);
-
-  // Return a string representation of the current hash.
-  std::string ToString() const;
-
-  // Compare with another hash value given as string representation.
-  // Returns true if for every bucket the difference between this and
-  // other is less than tolerance.
-  bool IsEquivalent(const std::string& other, double tolerance) const;
-
- private:
-  // Storage for the audio hash.  The number of buckets controls the importance
-  // of position in the hash.  A higher number reduces the chance of false
-  // positives related to incorrect sample position.  Value chosen by dice roll.
-  float audio_hash_[6];
-
-  // The total number of samples processed per channel.  Uses a uint32_t instead
-  // of size_t so overflows on 64-bit and 32-bit machines are equivalent.
-  uint32_t sample_count_;
-
-  DISALLOW_COPY_AND_ASSIGN(AudioHash);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_HASH_H_
diff --git a/src/cobalt/media/base/audio_hash_unittest.cc b/src/cobalt/media/base/audio_hash_unittest.cc
deleted file mode 100644
index 4f1ebbc..0000000
--- a/src/cobalt/media/base/audio_hash_unittest.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <memory>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "cobalt/media/base/audio_hash.h"
-#include "cobalt/media/base/fake_audio_render_callback.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cobalt {
-namespace media {
-
-static const int kChannelCount = 2;
-static const int kFrameCount = 1024;
-
-class AudioHashTest : public testing::Test {
- public:
-  AudioHashTest()
-      : bus_one_(AudioBus::Create(kChannelCount, kFrameCount)),
-        bus_two_(AudioBus::Create(kChannelCount, kFrameCount)),
-        fake_callback_(0.01) {
-    // Fill each channel in each bus with unique data.
-    GenerateUniqueChannels(bus_one_.get());
-    GenerateUniqueChannels(bus_two_.get());
-  }
-
-  void GenerateUniqueChannels(AudioBus* audio_bus) {
-    // Use an AudioBus wrapper to avoid an extra memcpy when filling channels.
-    std::unique_ptr<AudioBus> wrapped_bus = AudioBus::CreateWrapper(1);
-    wrapped_bus->set_frames(audio_bus->frames());
-
-    // Since FakeAudioRenderCallback generates only a single channel of unique
-    // audio data, we need to fill each channel manually.
-    for (int ch = 0; ch < audio_bus->channels(); ++ch) {
-      wrapped_bus->SetChannelData(0, audio_bus->channel(ch));
-      fake_callback_.Render(wrapped_bus.get(), 0, 0);
-    }
-  }
-
-  ~AudioHashTest() override {}
-
- protected:
-  std::unique_ptr<AudioBus> bus_one_;
-  std::unique_ptr<AudioBus> bus_two_;
-  FakeAudioRenderCallback fake_callback_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AudioHashTest);
-};
-
-// Ensure the same data hashes the same.
-TEST_F(AudioHashTest, Equivalence) {
-  AudioHash hash_one;
-  hash_one.Update(bus_one_.get(), bus_one_->frames());
-
-  AudioHash hash_two;
-  hash_two.Update(bus_one_.get(), bus_one_->frames());
-
-  EXPECT_EQ(hash_one.ToString(), hash_two.ToString());
-}
-
-// Ensure sample order matters to the hash.
-TEST_F(AudioHashTest, SampleOrder) {
-  AudioHash original_hash;
-  original_hash.Update(bus_one_.get(), bus_one_->frames());
-
-  // Swap a sample in the bus.
-  std::swap(bus_one_->channel(0)[0], bus_one_->channel(0)[1]);
-
-  AudioHash swapped_hash;
-  swapped_hash.Update(bus_one_.get(), bus_one_->frames());
-
-  EXPECT_NE(original_hash.ToString(), swapped_hash.ToString());
-}
-
-// Ensure channel order matters to the hash.
-TEST_F(AudioHashTest, ChannelOrder) {
-  AudioHash original_hash;
-  original_hash.Update(bus_one_.get(), bus_one_->frames());
-
-  // Reverse channel order for the same sample data.
-  const int channels = bus_one_->channels();
-  std::unique_ptr<AudioBus> swapped_ch_bus = AudioBus::CreateWrapper(channels);
-  swapped_ch_bus->set_frames(bus_one_->frames());
-  for (int i = channels - 1; i >= 0; --i)
-    swapped_ch_bus->SetChannelData(channels - (i + 1), bus_one_->channel(i));
-
-  AudioHash swapped_hash;
-  swapped_hash.Update(swapped_ch_bus.get(), swapped_ch_bus->frames());
-
-  EXPECT_NE(original_hash.ToString(), swapped_hash.ToString());
-}
-
-// Ensure bus order matters to the hash.
-TEST_F(AudioHashTest, BusOrder) {
-  AudioHash original_hash;
-  original_hash.Update(bus_one_.get(), bus_one_->frames());
-  original_hash.Update(bus_two_.get(), bus_two_->frames());
-
-  AudioHash reordered_hash;
-  reordered_hash.Update(bus_two_.get(), bus_two_->frames());
-  reordered_hash.Update(bus_one_.get(), bus_one_->frames());
-
-  EXPECT_NE(original_hash.ToString(), reordered_hash.ToString());
-}
-
-// Ensure bus order matters to the hash even with empty buses.
-TEST_F(AudioHashTest, EmptyBusOrder) {
-  bus_one_->Zero();
-  bus_two_->Zero();
-
-  AudioHash one_bus_hash;
-  one_bus_hash.Update(bus_one_.get(), bus_one_->frames());
-
-  AudioHash two_bus_hash;
-  two_bus_hash.Update(bus_one_.get(), bus_one_->frames());
-  two_bus_hash.Update(bus_two_.get(), bus_two_->frames());
-
-  EXPECT_NE(one_bus_hash.ToString(), two_bus_hash.ToString());
-}
-
-// Where A = [0, n], ensure hash(A[0:n/2]), hash(A[n/2:n]) and hash(A) result
-// in the same value.
-TEST_F(AudioHashTest, HashIgnoresUpdateOrder) {
-  AudioHash full_hash;
-  full_hash.Update(bus_one_.get(), bus_one_->frames());
-
-  AudioHash half_hash;
-  half_hash.Update(bus_one_.get(), bus_one_->frames() / 2);
-
-  // Create a new bus representing the second half of |bus_one_|.
-  const int half_frames = bus_one_->frames() / 2;
-  const int channels = bus_one_->channels();
-  std::unique_ptr<AudioBus> half_bus = AudioBus::CreateWrapper(channels);
-  half_bus->set_frames(half_frames);
-  for (int i = 0; i < channels; ++i)
-    half_bus->SetChannelData(i, bus_one_->channel(i) + half_frames);
-
-  half_hash.Update(half_bus.get(), half_bus->frames());
-  EXPECT_EQ(full_hash.ToString(), half_hash.ToString());
-}
-
-// Ensure approximate hashes pass verification.
-TEST_F(AudioHashTest, VerifySimilarHash) {
-  AudioHash hash_one;
-  hash_one.Update(bus_one_.get(), bus_one_->frames());
-
-  // Twiddle the values inside the first bus.
-  float* channel = bus_one_->channel(0);
-  for (int i = 0; i < bus_one_->frames(); i += bus_one_->frames() / 64)
-    channel[i] += 0.0001f;
-
-  AudioHash hash_two;
-  hash_two.Update(bus_one_.get(), bus_one_->frames());
-
-  EXPECT_EQ(hash_one.ToString(), hash_two.ToString());
-
-  // Twiddle the values too much...
-  for (int i = 0; i < bus_one_->frames(); ++i) channel[i] += 0.0001f;
-
-  AudioHash hash_three;
-  hash_three.Update(bus_one_.get(), bus_one_->frames());
-  EXPECT_NE(hash_one.ToString(), hash_three.ToString());
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_latency.cc b/src/cobalt/media/base/audio_latency.cc
deleted file mode 100644
index 9379217..0000000
--- a/src/cobalt/media/base/audio_latency.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_latency.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-namespace {
-#if !defined(OS_WIN)
-// Taken from "Bit Twiddling Hacks"
-// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
-uint32_t RoundUpToPowerOfTwo(uint32_t v) {
-  v--;
-  v |= v >> 1;
-  v |= v >> 2;
-  v |= v >> 4;
-  v |= v >> 8;
-  v |= v >> 16;
-  v++;
-  return v;
-}
-#endif
-}  // namespace
-
-// static
-int AudioLatency::GetHighLatencyBufferSize(int sample_rate,
-                                           int preferred_buffer_size) {
-  // Empirically, we consider 20ms of samples to be high latency.
-  const double twenty_ms_size = 2.0 * sample_rate / 100;
-
-#if defined(OS_WIN)
-  preferred_buffer_size = std::max(preferred_buffer_size, 1);
-
-  // Windows doesn't use power of two buffer sizes, so we should always round up
-  // to the nearest multiple of the output buffer size.
-  const int high_latency_buffer_size =
-      std::ceil(twenty_ms_size / preferred_buffer_size) * preferred_buffer_size;
-#else
-  // On other platforms use the nearest higher power of two buffer size.  For a
-  // given sample rate, this works out to:
-  //
-  //     <= 3200   : 64
-  //     <= 6400   : 128
-  //     <= 12800  : 256
-  //     <= 25600  : 512
-  //     <= 51200  : 1024
-  //     <= 102400 : 2048
-  //     <= 204800 : 4096
-  //
-  // On Linux, the minimum hardware buffer size is 512, so the lower calculated
-  // values are unused.  OSX may have a value as low as 128.
-  const int high_latency_buffer_size = RoundUpToPowerOfTwo(twenty_ms_size);
-#endif  // defined(OS_WIN)
-
-#if defined(OS_CHROMEOS)
-  return high_latency_buffer_size;  // No preference.
-#else
-  return std::max(preferred_buffer_size, high_latency_buffer_size);
-#endif  // defined(OS_CHROMEOS)
-}
-
-// static
-int AudioLatency::GetRtcBufferSize(int sample_rate, int hardware_buffer_size) {
-  // Use native hardware buffer size as default. On Windows, we strive to open
-  // up using this native hardware buffer size to achieve best
-  // possible performance and to ensure that no FIFO is needed on the browser
-  // side to match the client request. That is why there is no #if case for
-  // Windows below.
-  int frames_per_buffer = hardware_buffer_size;
-
-  // No |hardware_buffer_size| is specified, fall back to 10 ms buffer size.
-  if (!frames_per_buffer) {
-    frames_per_buffer = sample_rate / 100;
-    DVLOG(1) << "Using 10 ms sink output buffer size: " << frames_per_buffer;
-    return frames_per_buffer;
-  }
-
-#if defined(OS_LINUX) || defined(OS_MACOSX)
-  // On Linux and MacOS, the low level IO implementations on the browser side
-  // supports all buffer size the clients want. We use the native peer
-  // connection buffer size (10ms) to achieve best possible performance.
-  frames_per_buffer = sample_rate / 100;
-#elif defined(OS_ANDROID)
-  // TODO(olka/henrika): This settings are very old, need to be revisited.
-  int frames_per_10ms = sample_rate / 100;
-  if (frames_per_buffer < 2 * frames_per_10ms) {
-    // Examples of low-latency frame sizes and the resulting |buffer_size|:
-    //  Nexus 7     : 240 audio frames => 2*480 = 960
-    //  Nexus 10    : 256              => 2*441 = 882
-    //  Galaxy Nexus: 144              => 2*441 = 882
-    frames_per_buffer = 2 * frames_per_10ms;
-    DVLOG(1) << "Low-latency output detected on Android";
-  }
-#endif
-
-  DVLOG(1) << "Using sink output buffer size: " << frames_per_buffer;
-  return frames_per_buffer;
-}
-
-// static
-int AudioLatency::GetInteractiveBufferSize(int hardware_buffer_size) {
-#if defined(OS_ANDROID)
-  // The optimum low-latency hardware buffer size is usually too small on
-  // Android for WebAudio to render without glitching. So, if it is small, use
-  // a larger size.
-  //
-  // Since WebAudio renders in 128-frame blocks, the small buffer sizes (144 for
-  // a Galaxy Nexus), cause significant processing jitter. Sometimes multiple
-  // blocks will processed, but other times will not be since the WebAudio can't
-  // satisfy the request. By using a larger render buffer size, we smooth out
-  // the jitter.
-  const int kSmallBufferSize = 1024;
-  const int kDefaultCallbackBufferSize = 2048;
-  if (hardware_buffer_size <= kSmallBufferSize)
-    return kDefaultCallbackBufferSize;
-#endif
-
-  return hardware_buffer_size;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_latency.h b/src/cobalt/media/base/audio_latency.h
deleted file mode 100644
index bc6681f..0000000
--- a/src/cobalt/media/base/audio_latency.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_LATENCY_H_
-#define COBALT_MEDIA_BASE_AUDIO_LATENCY_H_
-
-#include "cobalt/media/base/media_export.h"
-
-namespace cobalt {
-namespace media {
-
-class MEDIA_EXPORT AudioLatency {
- public:
-  // Categories of expected latencies for input/output audio. Do not change
-  // existing values, they are used for UMA histogram reporting.
-  enum LatencyType {
-    // Specific latency in milliseconds.
-    LATENCY_EXACT_MS = 0,
-    // Lowest possible latency which does not cause glitches.
-    LATENCY_INTERACTIVE = 1,
-    // Latency optimized for real time communication.
-    LATENCY_RTC = 2,
-    // Latency optimized for continuous playback and power saving.
-    LATENCY_PLAYBACK = 3,
-    // For validation only.
-    LATENCY_LAST = LATENCY_PLAYBACK,
-    LATENCY_COUNT = LATENCY_LAST + 1
-  };
-
-  // |preferred_buffer_size| should be set to 0 if a client has no preference.
-  static int GetHighLatencyBufferSize(int sample_rate,
-                                      int preferred_buffer_size);
-
-  // |hardware_buffer_size| should be set to 0 if unknown/invalid/not preferred.
-  static int GetRtcBufferSize(int sample_rate, int hardware_buffer_size);
-
-  static int GetInteractiveBufferSize(int hardware_buffer_size);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_LATENCY_H_
diff --git a/src/cobalt/media/base/audio_latency_unittest.cc b/src/cobalt/media/base/audio_latency_unittest.cc
deleted file mode 100644
index 542fba9..0000000
--- a/src/cobalt/media/base/audio_latency_unittest.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_latency.h"
-
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "starboard/types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cobalt {
-namespace media {
-
-// TODO(olka): extend unit tests, use real-world sample rates.
-
-TEST(AudioLatency, HighLatencyBufferSizes) {
-#if defined(OS_WIN)
-  for (int i = 6400; i <= 204800; i *= 2) {
-    EXPECT_EQ(2 * (i / 100),
-              AudioLatency::GetHighLatencyBufferSize(i, i / 100));
-  }
-#else
-  for (int i = 6400; i <= 204800; i *= 2)
-    EXPECT_EQ(2 * (i / 100), AudioLatency::GetHighLatencyBufferSize(i, 32));
-#endif  // defined(OS_WIN)
-}
-
-TEST(AudioLatency, InteractiveBufferSizes) {
-#if defined(OS_ANDROID)
-  int i = 6400;
-  for (; i <= 102400; i *= 2)
-    EXPECT_EQ(2048, AudioLatency::GetInteractiveBufferSize(i / 100));
-  for (; i <= 204800; i *= 2)
-    EXPECT_EQ(i / 100, AudioLatency::GetInteractiveBufferSize(i / 100));
-#else
-  for (int i = 6400; i <= 204800; i *= 2)
-    EXPECT_EQ(i / 100, AudioLatency::GetInteractiveBufferSize(i / 100));
-#endif  // defined(OS_ANDROID)
-}
-
-TEST(AudioLatency, RtcBufferSizes) {
-  for (int i = 6400; i < 204800; i *= 2) {
-    EXPECT_EQ(i / 100, AudioLatency::GetRtcBufferSize(i, 0));
-#if defined(OS_WIN)
-    EXPECT_EQ(500, AudioLatency::GetRtcBufferSize(i, 500));
-#elif defined(OS_ANDROID)
-    EXPECT_EQ(i / 50, AudioLatency::GetRtcBufferSize(i, i / 50 - 1));
-    EXPECT_EQ(i / 50 + 1, AudioLatency::GetRtcBufferSize(i, i / 50 + 1));
-#else
-    EXPECT_EQ(i / 100, AudioLatency::GetRtcBufferSize(i, 500));
-#endif  // defined(OS_WIN)
-  }
-}
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_point.cc b/src/cobalt/media/base/audio_point.cc
deleted file mode 100644
index 9d86f87..0000000
--- a/src/cobalt/media/base/audio_point.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_point.h"
-
-#include "base/logging.h"
-#include "base/string_number_conversions.h"
-#include "base/string_split.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-std::string PointsToString(const std::vector<Point>& points) {
-  std::string points_string;
-  if (!points.empty()) {
-    for (size_t i = 0; i < points.size() - 1; ++i) {
-      points_string.append(points[i].ToString());
-      points_string.append(", ");
-    }
-    points_string.append(points.back().ToString());
-  }
-  return points_string;
-}
-
-std::vector<Point> ParsePointsFromString(const std::string& points_string) {
-  std::vector<Point> points;
-  if (points_string.empty()) return points;
-
-  const auto& tokens =
-      base::SplitString(points_string, base::kWhitespaceASCII,
-                        base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-  if (tokens.size() < 3 || tokens.size() % 3 != 0) {
-    LOG(ERROR) << "Malformed points string: " << points_string;
-    return points;
-  }
-
-  std::vector<float> float_tokens;
-  float_tokens.reserve(tokens.size());
-  for (const auto& token : tokens) {
-    double float_token;
-    if (!base::StringToDouble(token, &float_token)) {
-      LOG(ERROR) << "Unable to convert token=" << token
-                 << " to double from points string: " << points_string;
-      return points;
-    }
-    float_tokens.push_back(float_token);
-  }
-
-  points.reserve(float_tokens.size() / 3);
-  for (size_t i = 0; i < float_tokens.size(); i += 3) {
-    points.push_back(
-        Point(float_tokens[i + 0], float_tokens[i + 1], float_tokens[i + 2]));
-  }
-
-  return points;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_point.h b/src/cobalt/media/base/audio_point.h
deleted file mode 100644
index 4f6f989..0000000
--- a/src/cobalt/media/base/audio_point.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_POINT_H_
-#define COBALT_MEDIA_BASE_AUDIO_POINT_H_
-
-#include <string>
-#include <vector>
-
-#include "cobalt/media/base/media_export.h"
-#include "ui/gfx/geometry/point3_f.h"
-
-namespace cobalt {
-namespace media {
-
-using Point = gfx::Point3F;
-
-// Returns a vector of points parsed from a whitespace-separated string
-// formatted as: "x1 y1 z1 ... zn yn zn" for n points.
-//
-// Returns an empty vector if |points_string| is empty or isn't parseable.
-MEDIA_EXPORT std::vector<Point> ParsePointsFromString(
-    const std::string& points_string);
-
-// Returns |points| as a human-readable string. (Not necessarily in the format
-// required by ParsePointsFromString).
-MEDIA_EXPORT std::string PointsToString(const std::vector<Point>& points);
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_POINT_H_
diff --git a/src/cobalt/media/base/audio_point_unittest.cc b/src/cobalt/media/base/audio_point_unittest.cc
deleted file mode 100644
index a9d82b3..0000000
--- a/src/cobalt/media/base/audio_point_unittest.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <cmath>
-
-#include "cobalt/media/base/audio_point.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cobalt {
-namespace media {
-namespace {
-
-TEST(PointTest, PointsToString) {
-  std::vector<Point> points(1, Point(1, 0, 0.01f));
-  points.push_back(Point(0, 2, 0.02f));
-  EXPECT_EQ("1.000000,0.000000,0.010000, 0.000000,2.000000,0.020000",
-            PointsToString(points));
-
-  EXPECT_EQ("", PointsToString(std::vector<Point>()));
-}
-
-TEST(PointTest, ParsePointString) {
-  const std::vector<Point> expected_empty;
-  EXPECT_EQ(expected_empty, ParsePointsFromString(""));
-  EXPECT_EQ(expected_empty, ParsePointsFromString("0 0 a"));
-  EXPECT_EQ(expected_empty, ParsePointsFromString("1 2"));
-  EXPECT_EQ(expected_empty, ParsePointsFromString("1 2 3 4"));
-
-  {
-    std::vector<Point> expected(1, Point(-0.02f, 0, 0));
-    expected.push_back(Point(0.02f, 0, 0));
-    EXPECT_EQ(expected, ParsePointsFromString("-0.02 0 0 0.02 0 0"));
-  }
-  {
-    std::vector<Point> expected(1, Point(1, 2, 3));
-    EXPECT_EQ(expected, ParsePointsFromString("1 2 3"));
-  }
-}
-
-}  // namespace
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_pull_fifo.cc b/src/cobalt/media/base/audio_pull_fifo.cc
deleted file mode 100644
index 758d94c..0000000
--- a/src/cobalt/media/base/audio_pull_fifo.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_pull_fifo.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "starboard/memory.h"
-
-namespace cobalt {
-namespace media {
-
-AudioPullFifo::AudioPullFifo(int channels, int frames, const ReadCB& read_cb)
-    : read_cb_(read_cb),
-      fifo_(AudioBus::Create(channels, frames)),
-      fifo_index_(frames) {}
-
-AudioPullFifo::~AudioPullFifo() {}
-
-void AudioPullFifo::Consume(AudioBus* destination, int frames_to_consume) {
-  DCHECK_LE(frames_to_consume, destination->frames());
-
-  int remaining_frames_to_provide = frames_to_consume;
-
-  // Try to fulfill the request using what's available in the FIFO.
-  int frames_read = ReadFromFifo(destination, remaining_frames_to_provide, 0);
-  int write_pos = frames_read;
-  remaining_frames_to_provide -= frames_read;
-
-  // Get the remaining audio frames from the producer using the callback.
-  while (remaining_frames_to_provide > 0) {
-    DCHECK_EQ(fifo_index_, fifo_->frames());
-    fifo_index_ = 0;
-
-    // Fill up the FIFO by acquiring audio data from the producer.
-    read_cb_.Run(write_pos, fifo_.get());
-
-    // Try to fulfill the request using what's available in the FIFO.
-    frames_read =
-        ReadFromFifo(destination, remaining_frames_to_provide, write_pos);
-    write_pos += frames_read;
-    remaining_frames_to_provide -= frames_read;
-  }
-}
-
-void AudioPullFifo::Clear() { fifo_index_ = fifo_->frames(); }
-
-int AudioPullFifo::SizeInFrames() const { return fifo_->frames(); }
-
-int AudioPullFifo::ReadFromFifo(AudioBus* destination, int frames_to_provide,
-                                int write_pos) {
-  int frames = std::min(frames_to_provide, fifo_->frames() - fifo_index_);
-  if (frames <= 0) return 0;
-
-  for (int ch = 0; ch < fifo_->channels(); ++ch) {
-    const float* src = fifo_->channel(ch) + fifo_index_;
-    float* dest = destination->channel(ch) + write_pos;
-    SbMemoryCopy(dest, src, frames * sizeof(*src));
-  }
-
-  fifo_index_ += frames;
-  return frames;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_pull_fifo.h b/src/cobalt/media/base/audio_pull_fifo.h
deleted file mode 100644
index 4c1271f..0000000
--- a/src/cobalt/media/base/audio_pull_fifo.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_PULL_FIFO_H_
-#define COBALT_MEDIA_BASE_AUDIO_PULL_FIFO_H_
-
-#include <memory>
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "cobalt/media/base/media_export.h"
-
-namespace cobalt {
-namespace media {
-class AudioBus;
-
-// A FIFO (First In First Out) buffer to handle mismatches in buffer sizes
-// between a producer and consumer. The consumer will pull data from this FIFO.
-// If data is already available in the FIFO, it is provided to the consumer.
-// If insufficient data is available to satisfy the request, the FIFO will ask
-// the producer for more data to fulfill a request.
-class MEDIA_EXPORT AudioPullFifo {
- public:
-  // Callback type for providing more data into the FIFO.  Expects AudioBus
-  // to be completely filled with data upon return; zero padded if not enough
-  // frames are available to satisfy the request.  |frame_delay| is the number
-  // of output frames already processed and can be used to estimate delay.
-  typedef base::Callback<void(int frame_delay, AudioBus* audio_bus)> ReadCB;
-
-  // Constructs an AudioPullFifo with the specified |read_cb|, which is used to
-  // read audio data to the FIFO if data is not already available. The internal
-  // FIFO can contain |channel| number of channels, where each channel is of
-  // length |frames| audio frames.
-  AudioPullFifo(int channels, int frames, const ReadCB& read_cb);
-  virtual ~AudioPullFifo();
-
-  // Consumes |frames_to_consume| audio frames from the FIFO and copies
-  // them to |destination|. If the FIFO does not have enough data, we ask
-  // the producer to give us more data to fulfill the request using the
-  // ReadCB implementation.
-  void Consume(AudioBus* destination, int frames_to_consume);
-
-  // Empties the FIFO without deallocating any memory.
-  void Clear();
-
-  // Returns the size of the fifo in number of frames.
-  int SizeInFrames() const;
-
- private:
-  // Attempt to fulfill the request using what is available in the FIFO.
-  // Append new data to the |destination| starting at |write_pos|.
-  int ReadFromFifo(AudioBus* destination, int frames_to_provide, int write_pos);
-
-  // Source of data to the FIFO.
-  const ReadCB read_cb_;
-
-  // Temporary audio bus to hold the data from the producer.
-  std::unique_ptr<AudioBus> fifo_;
-  int fifo_index_;
-
-  DISALLOW_COPY_AND_ASSIGN(AudioPullFifo);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_PULL_FIFO_H_
diff --git a/src/cobalt/media/base/audio_pull_fifo_unittest.cc b/src/cobalt/media/base/audio_pull_fifo_unittest.cc
deleted file mode 100644
index d2ded4c..0000000
--- a/src/cobalt/media/base/audio_pull_fifo_unittest.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <memory>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/stringprintf.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "cobalt/media/base/audio_pull_fifo.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cobalt {
-namespace media {
-
-// Block diagram of a possible real-world usage:
-//
-//       | Producer | ----> | AudioPullFifo | ----> | Consumer |
-//                    push                    pull
-//          2048      ---->       (2048)      ---->     ~512
-
-// Number of channels in each audio bus.
-static int kChannels = 2;
-
-// Max number of audio framed the FIFO can contain.
-static const int kMaxFramesInFifo = 2048;
-
-class AudioPullFifoTest : public testing::TestWithParam<int> {
- public:
-  AudioPullFifoTest()
-      : pull_fifo_(kChannels, kMaxFramesInFifo,
-                   base::Bind(&AudioPullFifoTest::ProvideInput,
-                              base::Unretained(this))),
-        audio_bus_(AudioBus::Create(kChannels, kMaxFramesInFifo)),
-        fill_value_(0),
-        last_frame_delay_(-1) {
-    EXPECT_EQ(kMaxFramesInFifo, pull_fifo_.SizeInFrames());
-  }
-  virtual ~AudioPullFifoTest() {}
-
-  void VerifyValue(const float data[], int size, float start_value) {
-    float value = start_value;
-    for (int i = 0; i < size; ++i) {
-      ASSERT_FLOAT_EQ(value++, data[i]) << "i=" << i;
-    }
-  }
-
-  // Consume data using different sizes, acquire audio frames from the FIFO
-  // and verify that the retrieved values matches the values written by the
-  // producer.
-  void ConsumeTest(int frames_to_consume) {
-    int start_value = 0;
-    SCOPED_TRACE(
-        base::StringPrintf("Checking frames_to_consume %d", frames_to_consume));
-    pull_fifo_.Consume(audio_bus_.get(), frames_to_consume);
-    for (int j = 0; j < kChannels; ++j) {
-      VerifyValue(audio_bus_->channel(j), frames_to_consume, start_value);
-    }
-    start_value += frames_to_consume;
-    EXPECT_LT(last_frame_delay_, audio_bus_->frames());
-  }
-
-  // AudioPullFifo::ReadCB implementation where we increase a value for each
-  // audio frame that we provide. Note that all channels are given the same
-  // value to simplify the verification.
-  virtual void ProvideInput(int frame_delay, AudioBus* audio_bus) {
-    ASSERT_GT(frame_delay, last_frame_delay_);
-    last_frame_delay_ = frame_delay;
-
-    EXPECT_EQ(audio_bus->channels(), audio_bus_->channels());
-    EXPECT_EQ(audio_bus->frames(), kMaxFramesInFifo);
-    for (int i = 0; i < audio_bus->frames(); ++i) {
-      for (int j = 0; j < audio_bus->channels(); ++j) {
-        // Store same value in all channels.
-        audio_bus->channel(j)[i] = fill_value_;
-      }
-      fill_value_++;
-    }
-  }
-
- protected:
-  AudioPullFifo pull_fifo_;
-  std::unique_ptr<AudioBus> audio_bus_;
-  int fill_value_;
-  int last_frame_delay_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AudioPullFifoTest);
-};
-
-TEST_P(AudioPullFifoTest, Consume) { ConsumeTest(GetParam()); }
-
-// Test common |frames_to_consume| values which will be used as input
-// parameter to AudioPullFifo::Consume() when the consumer asks for data.
-INSTANTIATE_TEST_CASE_P(AudioPullFifoTest, AudioPullFifoTest,
-                        testing::Values(544, 512, 512, 512, 512, 2048, 544, 441,
-                                        440, 433, 500));
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_push_fifo.cc b/src/cobalt/media/base/audio_push_fifo.cc
deleted file mode 100644
index 8bea7dfe..0000000
--- a/src/cobalt/media/base/audio_push_fifo.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_push_fifo.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-
-namespace cobalt {
-namespace media {
-
-AudioPushFifo::AudioPushFifo(const OutputCallback& callback)
-    : callback_(callback), frames_per_buffer_(0) {
-  DCHECK(!callback_.is_null());
-}
-
-AudioPushFifo::~AudioPushFifo() {}
-
-void AudioPushFifo::Reset(int frames_per_buffer) {
-  DCHECK_GT(frames_per_buffer, 0);
-
-  audio_queue_.reset();
-  queued_frames_ = 0;
-
-  frames_per_buffer_ = frames_per_buffer;
-}
-
-void AudioPushFifo::Push(const AudioBus& input_bus) {
-  DCHECK_GT(frames_per_buffer_, 0);
-
-  // Fast path: No buffering required.
-  if ((queued_frames_ == 0) && (input_bus.frames() == frames_per_buffer_)) {
-    callback_.Run(input_bus, 0);
-    return;
-  }
-
-  // Lazy-create the |audio_queue_| if needed.
-  if (!audio_queue_ || audio_queue_->channels() != input_bus.channels())
-    audio_queue_ = AudioBus::Create(input_bus.channels(), frames_per_buffer_);
-
-  // Start with a frame offset that refers to the position of the first sample
-  // in |audio_queue_| relative to the first sample in |input_bus|.
-  int frame_delay = -queued_frames_;
-
-  // Repeatedly fill up |audio_queue_| with more sample frames from |input_bus|
-  // and deliver batches until all sample frames in |input_bus| have been
-  // consumed.
-  int input_offset = 0;
-  do {
-    // Attempt to fill |audio_queue_| completely.
-    const int frames_to_enqueue =
-        std::min(static_cast<int>(input_bus.frames() - input_offset),
-                 frames_per_buffer_ - queued_frames_);
-    if (frames_to_enqueue > 0) {
-      DVLOG(2) << "Enqueuing " << frames_to_enqueue << " frames.";
-      input_bus.CopyPartialFramesTo(input_offset, frames_to_enqueue,
-                                    queued_frames_, audio_queue_.get());
-      queued_frames_ += frames_to_enqueue;
-      input_offset += frames_to_enqueue;
-    }
-
-    // If |audio_queue_| has been filled completely, deliver the re-buffered
-    // audio to the consumer.
-    if (queued_frames_ == frames_per_buffer_) {
-      DVLOG(2) << "Delivering another " << queued_frames_ << " frames.";
-      callback_.Run(*audio_queue_, frame_delay);
-      frame_delay += frames_per_buffer_;
-      queued_frames_ = 0;
-    } else {
-      // Not enough frames queued-up yet to deliver more frames.
-    }
-  } while (input_offset < input_bus.frames());
-}
-
-void AudioPushFifo::Flush() {
-  if (queued_frames_ == 0) return;
-
-  audio_queue_->ZeroFramesPartial(queued_frames_,
-                                  audio_queue_->frames() - queued_frames_);
-  callback_.Run(*audio_queue_, -queued_frames_);
-  queued_frames_ = 0;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_push_fifo.h b/src/cobalt/media/base/audio_push_fifo.h
deleted file mode 100644
index 846eff9..0000000
--- a/src/cobalt/media/base/audio_push_fifo.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_PUSH_FIFO_H_
-#define COBALT_MEDIA_BASE_AUDIO_PUSH_FIFO_H_
-
-#include <memory>
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "cobalt/media/base/media_export.h"
-
-namespace cobalt {
-namespace media {
-
-// Yet another FIFO for audio data that re-buffers audio to a desired buffer
-// size.  Unlike AudioFifo and AudioBlockFifo, this FIFO cannot overflow: The
-// client is required to provide a callback that is called synchronously during
-// a push whenever enough data becomes available.  This implementation
-// eliminates redundant memory copies when the input buffer size always matches
-// the desired buffer size.
-class MEDIA_EXPORT AudioPushFifo final {
- public:
-  // Called synchronously zero, one, or multiple times during a call to Push()
-  // to deliver re-buffered audio.  |frame_delay| refers to the position of the
-  // first frame in |output| relative to the first frame in the Push() call.  If
-  // negative, this indicates the output contains some data from a prior call to
-  // Push().  If zero or positive, the output contains data from the current
-  // call to Push().  Clients can use this to adjust timestamps.
-  using OutputCallback =
-      base::Callback<void(const AudioBus& output_bus, int frame_delay)>;
-
-  // Creates a new AudioPushFifo which delivers re-buffered audio by running
-  // |callback|.
-  explicit AudioPushFifo(const OutputCallback& callback);
-
-  ~AudioPushFifo();
-
-  // Returns the number of frames in each AudioBus delivered to the
-  // OutputCallback.
-  int frames_per_buffer() const { return frames_per_buffer_; }
-
-  // Must be called at least once before the first call to Push().  May be
-  // called later (e.g., to support an audio format change).
-  void Reset(int frames_per_buffer);
-
-  // Pushes all audio channel data from |input_bus| through the FIFO.  This will
-  // result in zero, one, or multiple synchronous calls to the OutputCallback
-  // provided in the constructor.  If the |input_bus| has a different number of
-  // channels than the prior Push() call, any currently-queued frames will be
-  // dropped.
-  void Push(const AudioBus& input_bus);
-
-  // Flushes any enqueued frames by invoking the OutputCallback with those
-  // frames plus padded zero samples.  If there are no frames currently
-  // enqueued, OutputCallback is not run.
-  void Flush();
-
- private:
-  const OutputCallback callback_;
-
-  int frames_per_buffer_;
-
-  // Queue of frames pending for delivery.
-  std::unique_ptr<AudioBus> audio_queue_;
-  int queued_frames_;
-
-  DISALLOW_COPY_AND_ASSIGN(AudioPushFifo);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_PUSH_FIFO_H_
diff --git a/src/cobalt/media/base/audio_push_fifo_unittest.cc b/src/cobalt/media/base/audio_push_fifo_unittest.cc
deleted file mode 100644
index 3c3ebf4..0000000
--- a/src/cobalt/media/base/audio_push_fifo_unittest.cc
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <limits>
-#include <memory>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "cobalt/media/base/audio_push_fifo.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cobalt {
-namespace media {
-
-namespace {
-
-class AudioPushFifoTest : public testing::TestWithParam<int> {
- public:
-  AudioPushFifoTest() {}
-  ~AudioPushFifoTest() override {}
-
-  int output_chunk_size() const { return GetParam(); }
-
-  void SetUp() final {
-    fifo_.reset(new AudioPushFifo(base::Bind(
-        &AudioPushFifoTest::ReceiveAndCheckNextChunk, base::Unretained(this))));
-    fifo_->Reset(output_chunk_size());
-    ASSERT_EQ(output_chunk_size(), fifo_->frames_per_buffer());
-  }
-
- protected:
-  struct OutputChunkResult {
-    int num_frames;
-    float first_sample_value;
-    float last_sample_value;
-    int frame_delay;
-  };
-
-  // Returns the number of output chunks that should have been emitted given the
-  // number of input frames pushed so far.
-  size_t GetExpectedOutputChunks(int frames_pushed) const {
-    return static_cast<size_t>(frames_pushed / output_chunk_size());
-  }
-
-  // Returns the number of Push() calls to make in order to get at least 3
-  // output chunks.
-  int GetNumPushTestIterations(int input_chunk_size) const {
-    return 3 * std::max(1, output_chunk_size() / input_chunk_size);
-  }
-
-  // Repeatedly pushes constant-sized batches of input samples and checks that
-  // the input data is re-chunked correctly.
-  void RunSimpleRechunkTest(int input_chunk_size) {
-    const int num_iterations = GetNumPushTestIterations(input_chunk_size);
-
-    int sample_value = 0;
-    const std::unique_ptr<AudioBus> audio_bus =
-        AudioBus::Create(1, input_chunk_size);
-
-    for (int i = 0; i < num_iterations; ++i) {
-      EXPECT_EQ(GetExpectedOutputChunks(i * input_chunk_size), results_.size());
-
-      // Fill audio data with predictable values.
-      for (int j = 0; j < audio_bus->frames(); ++j)
-        audio_bus->channel(0)[j] = static_cast<float>(sample_value++);
-
-      fifo_->Push(*audio_bus);
-      // Note: AudioPushFifo has just called ReceiveAndCheckNextChunk() zero or
-      // more times.
-    }
-    EXPECT_EQ(GetExpectedOutputChunks(num_iterations * input_chunk_size),
-              results_.size());
-
-    // Confirm first and last sample values that have been output are the
-    // expected ones.
-    ASSERT_FALSE(results_.empty());
-    EXPECT_EQ(0.0f, results_.front().first_sample_value);
-    const float last_value_in_last_chunk = static_cast<float>(
-        GetExpectedOutputChunks(num_iterations * input_chunk_size) *
-            output_chunk_size() -
-        1);
-    EXPECT_EQ(last_value_in_last_chunk, results_.back().last_sample_value);
-
-    // Confirm the expected frame delays for the first output chunk (or two).
-    if (input_chunk_size < output_chunk_size()) {
-      const int num_queued_before_first_output =
-          ((output_chunk_size() - 1) / input_chunk_size) * input_chunk_size;
-      EXPECT_EQ(-num_queued_before_first_output, results_.front().frame_delay);
-    } else if (input_chunk_size >= output_chunk_size()) {
-      EXPECT_EQ(0, results_[0].frame_delay);
-      if (input_chunk_size >= 2 * output_chunk_size()) {
-        EXPECT_EQ(output_chunk_size(), results_[1].frame_delay);
-      } else {
-        const int num_remaining_after_first_output =
-            input_chunk_size - output_chunk_size();
-        EXPECT_EQ(-num_remaining_after_first_output, results_[1].frame_delay);
-      }
-    }
-
-    const size_t num_results_before_flush = results_.size();
-    fifo_->Flush();
-    const size_t num_results_after_flush = results_.size();
-    if (num_results_after_flush > num_results_before_flush) {
-      EXPECT_NE(0, results_.back().frame_delay);
-      EXPECT_LT(-output_chunk_size(), results_.back().frame_delay);
-    }
-  }
-
-  // Returns a "random" integer in the range [begin,end).
-  int GetRandomInRange(int begin, int end) {
-    const int len = end - begin;
-    const int rand_offset = (len == 0) ? 0 : (NextRandomInt() % (end - begin));
-    return begin + rand_offset;
-  }
-
-  std::unique_ptr<AudioPushFifo> fifo_;
-  std::vector<OutputChunkResult> results_;
-
- private:
-  // Called by |fifo_| to deliver another chunk of audio.  Sanity checks
-  // the sample values are as expected, and without any dropped/duplicated, and
-  // adds a result to |results_|.
-  void ReceiveAndCheckNextChunk(const AudioBus& audio_bus, int frame_delay) {
-    OutputChunkResult result;
-    result.num_frames = audio_bus.frames();
-    result.first_sample_value = audio_bus.channel(0)[0];
-    result.last_sample_value = audio_bus.channel(0)[audio_bus.frames() - 1];
-    result.frame_delay = frame_delay;
-
-    // Check that each sample value is the previous sample value plus one.
-    for (int i = 1; i < audio_bus.frames(); ++i) {
-      const float expected_value = result.first_sample_value + i;
-      const float actual_value = audio_bus.channel(0)[i];
-      if (actual_value != expected_value) {
-        if (actual_value == 0.0f) {
-          // This chunk is probably being emitted by a Flush().  If that's true
-          // then the frame_delay will be negative and the rest of the
-          // |audio_bus| should be all zeroes.
-          ASSERT_GT(0, frame_delay);
-          for (int j = i + 1; j < audio_bus.frames(); ++j)
-            ASSERT_EQ(0.0f, audio_bus.channel(0)[j]);
-          break;
-        } else {
-          ASSERT_EQ(expected_value, actual_value) << "Sample at offset " << i
-                                                  << " is incorrect.";
-        }
-      }
-    }
-
-    results_.push_back(result);
-  }
-
-  // Note: Not using base::RandInt() because it is horribly slow on debug
-  // builds.  The following is a very simple, deterministic LCG:
-  int NextRandomInt() {
-    rand_seed_ = (1103515245 * rand_seed_ + 12345) % (1 << 31);
-    return static_cast<int>(rand_seed_);
-  }
-
-  uint32_t rand_seed_ = 0x7e110;
-
-  DISALLOW_COPY_AND_ASSIGN(AudioPushFifoTest);
-};
-
-// Tests an atypical edge case: Push()ing one frame at a time.
-TEST_P(AudioPushFifoTest, PushOneFrameAtATime) { RunSimpleRechunkTest(1); }
-
-// Tests that re-chunking the audio from common platform input chunk sizes
-// works.
-TEST_P(AudioPushFifoTest, Push128FramesAtATime) { RunSimpleRechunkTest(128); }
-TEST_P(AudioPushFifoTest, Push512FramesAtATime) { RunSimpleRechunkTest(512); }
-
-// Tests that re-chunking the audio from common "10 ms" input chunk sizes
-// works (44100 Hz * 10 ms = 441, and 48000 Hz * 10 ms = 480).
-TEST_P(AudioPushFifoTest, Push441FramesAtATime) { RunSimpleRechunkTest(441); }
-TEST_P(AudioPushFifoTest, Push480FramesAtATime) { RunSimpleRechunkTest(480); }
-
-// Tests that re-chunking when input audio is provided in varying chunk sizes
-// works.
-TEST_P(AudioPushFifoTest, PushArbitraryNumbersOfFramesAtATime) {
-  // The loop below will run until both: 1) kMinNumIterations loops have
-  // occurred; and 2) there are at least 3 entries in |results_|.
-  const int kMinNumIterations = 30;
-
-  int sample_value = 0;
-  int frames_pushed_so_far = 0;
-  for (int i = 0; i < kMinNumIterations || results_.size() < 3; ++i) {
-    EXPECT_EQ(GetExpectedOutputChunks(frames_pushed_so_far), results_.size());
-
-    // Create an AudioBus of a random length, populated with sample values.
-    const int input_chunk_size = GetRandomInRange(1, 1920);
-    const std::unique_ptr<AudioBus> audio_bus =
-        AudioBus::Create(1, input_chunk_size);
-    for (int j = 0; j < audio_bus->frames(); ++j)
-      audio_bus->channel(0)[j] = static_cast<float>(sample_value++);
-
-    fifo_->Push(*audio_bus);
-    // Note: AudioPushFifo has just called ReceiveAndCheckNextChunk() zero or
-    // more times.
-
-    frames_pushed_so_far += input_chunk_size;
-  }
-  EXPECT_EQ(GetExpectedOutputChunks(frames_pushed_so_far), results_.size());
-
-  ASSERT_FALSE(results_.empty());
-  EXPECT_EQ(0.0f, results_.front().first_sample_value);
-  const float last_value_in_last_chunk = static_cast<float>(
-      GetExpectedOutputChunks(frames_pushed_so_far) * output_chunk_size() - 1);
-  EXPECT_EQ(last_value_in_last_chunk, results_.back().last_sample_value);
-
-  const size_t num_results_before_flush = results_.size();
-  fifo_->Flush();
-  const size_t num_results_after_flush = results_.size();
-  if (num_results_after_flush > num_results_before_flush) {
-    EXPECT_NE(0, results_.back().frame_delay);
-    EXPECT_LT(-output_chunk_size(), results_.back().frame_delay);
-  }
-}
-
-INSTANTIATE_TEST_CASE_P(, AudioPushFifoTest,
-                        ::testing::Values(
-                            // 1 ms output chunks at common sample rates.
-                            16,  // 16000 Hz
-                            22,  // 22050 Hz
-                            44,  // 44100 Hz
-                            48,  // 48000 Hz
-
-                            // 10 ms output chunks at common sample rates.
-                            160,  // 16000 Hz
-                            220,  // 22050 Hz
-                            441,  // 44100 Hz
-                            480,  // 48000 Hz
-
-                            // 60 ms output chunks at common sample rates.
-                            960,   // 16000 Hz
-                            1323,  // 22050 Hz
-                            2646,  // 44100 Hz
-                            2880   // 48000 Hz
-                            ));
-
-}  // namespace
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_renderer.cc b/src/cobalt/media/base/audio_renderer.cc
deleted file mode 100644
index 1dae249..0000000
--- a/src/cobalt/media/base/audio_renderer.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_renderer.h"
-
-namespace cobalt {
-namespace media {
-
-AudioRenderer::AudioRenderer() {}
-AudioRenderer::~AudioRenderer() {}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_renderer.h b/src/cobalt/media/base/audio_renderer.h
deleted file mode 100644
index f6a9628..0000000
--- a/src/cobalt/media/base/audio_renderer.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_RENDERER_H_
-#define COBALT_MEDIA_BASE_AUDIO_RENDERER_H_
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/time.h"
-#include "cobalt/media/base/buffering_state.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/pipeline_status.h"
-
-namespace cobalt {
-namespace media {
-
-class CdmContext;
-class DemuxerStream;
-class RendererClient;
-class TimeSource;
-
-class MEDIA_EXPORT AudioRenderer {
- public:
-  AudioRenderer();
-
-  // Stop all operations and fire all pending callbacks.
-  virtual ~AudioRenderer();
-
-  // Initialize an AudioRenderer with |stream|, executing |init_cb| upon
-  // completion. If initialization fails, only |init_cb|
-  // (not RendererClient::OnError) will be called.
-  //
-  // |cdm_context| can be used to handle encrypted streams. May be null if the
-  // stream is not encrypted.
-  virtual void Initialize(DemuxerStream* stream, CdmContext* cdm_context,
-                          RendererClient* client,
-                          const PipelineStatusCB& init_cb) = 0;
-
-  // Returns the TimeSource associated with audio rendering.
-  virtual TimeSource* GetTimeSource() = 0;
-
-  // Discard any audio data, executing |callback| when completed.
-  //
-  // Clients should expect |buffering_state_cb| to be called with
-  // BUFFERING_HAVE_NOTHING while flushing is in progress.
-  virtual void Flush(const base::Closure& callback) = 0;
-
-  // Starts playback by reading from |stream| and decoding and rendering audio.
-  //
-  // Only valid to call after a successful Initialize() or Flush().
-  virtual void StartPlaying() = 0;
-
-  // Sets the output volume.
-  virtual void SetVolume(float volume) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AudioRenderer);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_RENDERER_H_
diff --git a/src/cobalt/media/base/audio_renderer_sink.h b/src/cobalt/media/base/audio_renderer_sink.h
deleted file mode 100644
index 2795952..0000000
--- a/src/cobalt/media/base/audio_renderer_sink.h
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_RENDERER_SINK_H_
-#define COBALT_MEDIA_BASE_AUDIO_RENDERER_SINK_H_
-
-#include <string>
-
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "cobalt/media/base/audio_parameters.h"
-#include "cobalt/media/base/output_device_info.h"
-#include "starboard/types.h"
-#include "url/origin.h"
-
-namespace cobalt {
-namespace media {
-
-// AudioRendererSink is an interface representing the end-point for
-// rendered audio.  An implementation is expected to
-// periodically call Render() on a callback object.
-
-class AudioRendererSink
-    : public base::RefCountedThreadSafe<media::AudioRendererSink> {
- public:
-  class RenderCallback {
-   public:
-    // Attempts to completely fill all channels of |dest|, returns actual
-    // number of frames filled. |frames_skipped| contains the number of frames
-    // the consumer has skipped, if any.
-    // TODO(jameswest): Change to use the same signature as
-    // AudioOutputStream::AudioSourceCallback::OnMoreData.
-    virtual int Render(AudioBus* dest, uint32_t frames_delayed,
-                       uint32_t frames_skipped) = 0;
-
-    // Signals an error has occurred.
-    virtual void OnRenderError() = 0;
-
-   protected:
-    virtual ~RenderCallback() {}
-  };
-
-  // Sets important information about the audio stream format.
-  // It must be called before any of the other methods.
-  virtual void Initialize(const AudioParameters& params,
-                          RenderCallback* callback) = 0;
-
-  // Starts audio playback.
-  virtual void Start() = 0;
-
-  // Stops audio playback and performs cleanup. It must be called before
-  // destruction.
-  virtual void Stop() = 0;
-
-  // Pauses playback.
-  virtual void Pause() = 0;
-
-  // Resumes playback after calling Pause().
-  virtual void Play() = 0;
-
-  // Sets the playback volume, with range [0.0, 1.0] inclusive.
-  // Returns |true| on success.
-  virtual bool SetVolume(double volume) = 0;
-
-  // Returns current output device information. If the information is not
-  // available yet, this method may block until it becomes available.
-  // If the sink is not associated with any output device, |device_status| of
-  // OutputDeviceInfo should be set to OUTPUT_DEVICE_STATUS_ERROR_INTERNAL.
-  // Must never be called on the IO thread.
-  virtual OutputDeviceInfo GetOutputDeviceInfo() = 0;
-
-  // If DCHECKs are enabled, this function returns true if called on rendering
-  // thread, otherwise false. With DCHECKs disabled, it returns true. Thus, it
-  // is intended to be used for DCHECKing.
-  virtual bool CurrentThreadIsRenderingThread() = 0;
-
- protected:
-  friend class base::RefCountedThreadSafe<AudioRendererSink>;
-  virtual ~AudioRendererSink() {}
-};
-
-// Same as AudioRendererSink except that Initialize() and Start() can be called
-// again after Stop().
-// TODO(sandersd): Fold back into AudioRendererSink once all subclasses support
-// this.
-
-class RestartableAudioRendererSink : public AudioRendererSink {
- protected:
-  ~RestartableAudioRendererSink() override {}
-};
-
-class SwitchableAudioRendererSink : public RestartableAudioRendererSink {
- public:
-  // Attempts to switch the audio output device associated with a sink.
-  // Once the attempt is finished, |callback| is invoked with the
-  // result of the operation passed as a parameter. The result is a value from
-  // the media::OutputDeviceStatus enum.
-  // There is no guarantee about the thread where |callback| will be invoked.
-  virtual void SwitchOutputDevice(const std::string& device_id,
-                                  const url::Origin& security_origin,
-                                  const OutputDeviceStatusCB& callback) = 0;
-
- protected:
-  ~SwitchableAudioRendererSink() override {}
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_RENDERER_SINK_H_
diff --git a/src/cobalt/media/base/audio_splicer.cc b/src/cobalt/media/base/audio_splicer.cc
deleted file mode 100644
index 9414daf..0000000
--- a/src/cobalt/media/base/audio_splicer.cc
+++ /dev/null
@@ -1,551 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_splicer.h"
-
-#include <algorithm>
-#include <cstdlib>
-#include <deque>
-#include <utility>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "cobalt/media/base/audio_buffer.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "cobalt/media/base/audio_decoder_config.h"
-#include "cobalt/media/base/audio_timestamp_helper.h"
-#include "cobalt/media/base/media_log.h"
-#include "cobalt/media/base/vector_math.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-namespace {
-
-enum {
-  // Minimum gap size needed before the splicer will take action to
-  // fill a gap. This avoids periodically inserting and then dropping samples
-  // when the buffer timestamps are slightly off because of timestamp rounding
-  // in the source content. Unit is frames.
-  kMinGapSize = 2,
-
-  // Limits the number of MEDIA_LOG() per sanitizer instance warning the user
-  // about splicer overlaps within |kMaxTimeDeltaInMilliseconds| or gaps larger
-  // than |kMinGapSize| and less than |kMaxTimeDeltaInMilliseconds|. These
-  // warnings may be frequent for some streams, and number of sanitizer
-  // instances may be high, so keep this limit low to help reduce log spam.
-  kMaxSanitizerWarningLogs = 5,
-};
-
-// AudioBuffer::TrimStart() is not as accurate as the timestamp helper, so
-// manually adjust the duration and timestamp after trimming.
-void AccurateTrimStart(int frames_to_trim,
-                       const scoped_refptr<AudioBuffer> buffer,
-                       const AudioTimestampHelper& timestamp_helper) {
-  buffer->TrimStart(frames_to_trim);
-  buffer->set_timestamp(timestamp_helper.GetTimestamp());
-}
-
-// Returns an AudioBus whose frame buffer is backed by the provided AudioBuffer.
-std::unique_ptr<AudioBus> CreateAudioBufferWrapper(
-    const scoped_refptr<AudioBuffer>& buffer) {
-  std::unique_ptr<AudioBus> wrapper =
-      AudioBus::CreateWrapper(buffer->channel_count());
-  wrapper->set_frames(buffer->frame_count());
-  for (int ch = 0; ch < buffer->channel_count(); ++ch) {
-    wrapper->SetChannelData(
-        ch, reinterpret_cast<float*>(buffer->channel_data()[ch]));
-  }
-  return wrapper;
-}
-
-}  // namespace
-
-class AudioStreamSanitizer {
- public:
-  AudioStreamSanitizer(int samples_per_second,
-                       const scoped_refptr<MediaLog>& media_log);
-  ~AudioStreamSanitizer();
-
-  // Resets the sanitizer state by clearing the output buffers queue, and
-  // resetting the timestamp helper.
-  void Reset();
-
-  // Similar to Reset(), but initializes the timestamp helper with the given
-  // parameters.
-  void ResetTimestampState(int64_t frame_count, base::TimeDelta base_timestamp);
-
-  // Adds a new buffer full of samples or end of stream buffer to the splicer.
-  // Returns true if the buffer was accepted. False is returned if an error
-  // occurred.
-  bool AddInput(const scoped_refptr<AudioBuffer>& input);
-
-  // Returns true if the sanitizer has a buffer to return.
-  bool HasNextBuffer() const;
-
-  // Removes the next buffer from the output buffer queue and returns it; should
-  // only be called if HasNextBuffer() returns true.
-  scoped_refptr<AudioBuffer> GetNextBuffer();
-
-  // Returns the total frame count of all buffers available for output.
-  int GetFrameCount() const;
-
-  const AudioTimestampHelper& timestamp_helper() {
-    return output_timestamp_helper_;
-  }
-
-  // Transfer all buffers into |output|.  Returns false if AddInput() on the
-  // |output| sanitizer fails for any buffer removed from |this|.
-  bool DrainInto(AudioStreamSanitizer* output);
-
- private:
-  void AddOutputBuffer(const scoped_refptr<AudioBuffer>& buffer);
-
-  AudioTimestampHelper output_timestamp_helper_;
-  bool received_end_of_stream_ = false;
-
-  typedef std::deque<scoped_refptr<AudioBuffer> > BufferQueue;
-  BufferQueue output_buffers_;
-
-  scoped_refptr<MediaLog> media_log_;
-
-  // To prevent log spam, counts the number of audio gap or overlaps warned in
-  // logs.
-  int num_warning_logs_ = 0;
-
-  DISALLOW_ASSIGN(AudioStreamSanitizer);
-};
-
-AudioStreamSanitizer::AudioStreamSanitizer(
-    int samples_per_second, const scoped_refptr<MediaLog>& media_log)
-    : output_timestamp_helper_(samples_per_second), media_log_(media_log) {}
-
-AudioStreamSanitizer::~AudioStreamSanitizer() {}
-
-void AudioStreamSanitizer::Reset() { ResetTimestampState(0, kNoTimestamp); }
-
-void AudioStreamSanitizer::ResetTimestampState(int64_t frame_count,
-                                               base::TimeDelta base_timestamp) {
-  output_buffers_.clear();
-  received_end_of_stream_ = false;
-  output_timestamp_helper_.SetBaseTimestamp(base_timestamp);
-  if (frame_count > 0) output_timestamp_helper_.AddFrames(frame_count);
-}
-
-bool AudioStreamSanitizer::AddInput(const scoped_refptr<AudioBuffer>& input) {
-  DCHECK(!received_end_of_stream_ || input->end_of_stream());
-
-  if (input->end_of_stream()) {
-    output_buffers_.push_back(input);
-    received_end_of_stream_ = true;
-    return true;
-  }
-
-  DCHECK(input->timestamp() != kNoTimestamp);
-  DCHECK(input->duration() > base::TimeDelta());
-  DCHECK_GT(input->frame_count(), 0);
-
-  if (output_timestamp_helper_.base_timestamp() == kNoTimestamp)
-    output_timestamp_helper_.SetBaseTimestamp(input->timestamp());
-
-  if (output_timestamp_helper_.base_timestamp() > input->timestamp()) {
-    MEDIA_LOG(ERROR, media_log_)
-        << "Audio splicing failed: unexpected timestamp sequence. base "
-           "timestamp="
-        << output_timestamp_helper_.base_timestamp().InMicroseconds()
-        << "us, input timestamp=" << input->timestamp().InMicroseconds()
-        << "us";
-    return false;
-  }
-
-  const base::TimeDelta timestamp = input->timestamp();
-  const base::TimeDelta expected_timestamp =
-      output_timestamp_helper_.GetTimestamp();
-  const base::TimeDelta delta = timestamp - expected_timestamp;
-
-  if (std::abs(delta.InMilliseconds()) >
-      AudioSplicer::kMaxTimeDeltaInMilliseconds) {
-    MEDIA_LOG(ERROR, media_log_)
-        << "Audio splicing failed: coded frame timestamp differs from "
-           "expected timestamp "
-        << expected_timestamp.InMicroseconds() << "us by "
-        << delta.InMicroseconds() << "us, more than threshold of +/-"
-        << AudioSplicer::kMaxTimeDeltaInMilliseconds
-        << "ms. Expected timestamp is based on decoded frames and frame rate.";
-    return false;
-  }
-
-  int frames_to_fill = 0;
-  if (!delta.is_zero())
-    frames_to_fill = output_timestamp_helper_.GetFramesToTarget(timestamp);
-
-  if (frames_to_fill == 0 || std::abs(frames_to_fill) < kMinGapSize) {
-    AddOutputBuffer(input);
-    return true;
-  }
-
-  if (frames_to_fill > 0) {
-    LIMITED_MEDIA_LOG(DEBUG, media_log_, num_warning_logs_,
-                      kMaxSanitizerWarningLogs)
-        << "Audio splicer inserting silence for small gap of "
-        << delta.InMicroseconds() << "us at time "
-        << expected_timestamp.InMicroseconds() << "us.";
-    DVLOG(1) << "Gap detected @ " << expected_timestamp.InMicroseconds()
-             << " us: " << delta.InMicroseconds() << " us";
-
-    // Create a buffer with enough silence samples to fill the gap and
-    // add it to the output buffer.
-    scoped_refptr<AudioBuffer> gap = AudioBuffer::CreateEmptyBuffer(
-        input->channel_layout(), input->channel_count(), input->sample_rate(),
-        frames_to_fill, expected_timestamp);
-    AddOutputBuffer(gap);
-
-    // Add the input buffer now that the gap has been filled.
-    AddOutputBuffer(input);
-    return true;
-  }
-
-  // Overlapping buffers marked as splice frames are handled by AudioSplicer,
-  // but decoder and demuxer quirks may sometimes produce overlapping samples
-  // which need to be sanitized.
-  //
-  // A crossfade can't be done here because only the current buffer is available
-  // at this point, not previous buffers.
-  LIMITED_MEDIA_LOG(DEBUG, media_log_, num_warning_logs_,
-                    kMaxSanitizerWarningLogs)
-      << "Audio splicer skipping frames for small overlap of "
-      << -delta.InMicroseconds() << "us at time "
-      << expected_timestamp.InMicroseconds() << "us.";
-  DVLOG(1) << "Overlap detected @ " << expected_timestamp.InMicroseconds()
-           << " us: " << -delta.InMicroseconds() << " us";
-
-  const int frames_to_skip = -frames_to_fill;
-  if (input->frame_count() <= frames_to_skip) {
-    DVLOG(1) << "Dropping whole buffer";
-    return true;
-  }
-
-  // Copy the trailing samples that do not overlap samples already output
-  // into a new buffer.  Add this new buffer to the output queue.
-  //
-  // TODO(acolwell): Implement a cross-fade here so the transition is less
-  // jarring.
-  AccurateTrimStart(frames_to_skip, input, output_timestamp_helper_);
-  AddOutputBuffer(input);
-  return true;
-}
-
-bool AudioStreamSanitizer::HasNextBuffer() const {
-  return !output_buffers_.empty();
-}
-
-scoped_refptr<AudioBuffer> AudioStreamSanitizer::GetNextBuffer() {
-  scoped_refptr<AudioBuffer> ret = output_buffers_.front();
-  output_buffers_.pop_front();
-  return ret;
-}
-
-void AudioStreamSanitizer::AddOutputBuffer(
-    const scoped_refptr<AudioBuffer>& buffer) {
-  output_timestamp_helper_.AddFrames(buffer->frame_count());
-  output_buffers_.push_back(buffer);
-}
-
-int AudioStreamSanitizer::GetFrameCount() const {
-  int frame_count = 0;
-  for (const auto& buffer : output_buffers_)
-    frame_count += buffer->frame_count();
-  return frame_count;
-}
-
-bool AudioStreamSanitizer::DrainInto(AudioStreamSanitizer* output) {
-  while (HasNextBuffer()) {
-    if (!output->AddInput(GetNextBuffer())) return false;
-  }
-  return true;
-}
-
-AudioSplicer::AudioSplicer(int samples_per_second,
-                           const scoped_refptr<MediaLog>& media_log)
-    : max_crossfade_duration_(
-          base::TimeDelta::FromMilliseconds(kCrossfadeDurationInMilliseconds)),
-      splice_timestamp_(kNoTimestamp),
-      max_splice_end_timestamp_(kNoTimestamp),
-      output_sanitizer_(
-          new AudioStreamSanitizer(samples_per_second, media_log)),
-      pre_splice_sanitizer_(
-          new AudioStreamSanitizer(samples_per_second, media_log)),
-      post_splice_sanitizer_(
-          new AudioStreamSanitizer(samples_per_second, media_log)),
-      have_all_pre_splice_buffers_(false) {}
-
-AudioSplicer::~AudioSplicer() {}
-
-void AudioSplicer::Reset() {
-  output_sanitizer_->Reset();
-  pre_splice_sanitizer_->Reset();
-  post_splice_sanitizer_->Reset();
-  have_all_pre_splice_buffers_ = false;
-  reset_splice_timestamps();
-}
-
-bool AudioSplicer::AddInput(const scoped_refptr<AudioBuffer>& input) {
-  // If we're not processing a splice, add the input to the output queue.
-  if (splice_timestamp_ == kNoTimestamp) {
-    DCHECK(!pre_splice_sanitizer_->HasNextBuffer());
-    DCHECK(!post_splice_sanitizer_->HasNextBuffer());
-    return output_sanitizer_->AddInput(input);
-  }
-
-  const AudioTimestampHelper& output_ts_helper =
-      output_sanitizer_->timestamp_helper();
-
-  if (!have_all_pre_splice_buffers_) {
-    DCHECK(!input->end_of_stream());
-
-    // If the provided buffer is entirely before the splice point it can also be
-    // added to the output queue.
-    if (input->timestamp() + input->duration() < splice_timestamp_) {
-      DCHECK(!pre_splice_sanitizer_->HasNextBuffer());
-      return output_sanitizer_->AddInput(input);
-    }
-
-    // If we've encountered the first pre splice buffer, reset the pre splice
-    // sanitizer based on |output_sanitizer_|.  This is done so that gaps and
-    // overlaps between buffers across the sanitizers are accounted for prior
-    // to calculating crossfade.
-    if (!pre_splice_sanitizer_->HasNextBuffer()) {
-      pre_splice_sanitizer_->ResetTimestampState(
-          output_ts_helper.frame_count(), output_ts_helper.base_timestamp());
-    }
-
-    return pre_splice_sanitizer_->AddInput(input);
-  }
-
-  // The first post splice buffer is expected to match |splice_timestamp_|.
-  if (!post_splice_sanitizer_->HasNextBuffer())
-    CHECK(splice_timestamp_ == input->timestamp());
-
-  // At this point we have all the fade out preroll buffers from the decoder.
-  // We now need to wait until we have enough data to perform the crossfade (or
-  // we receive an end of stream).
-  if (!post_splice_sanitizer_->AddInput(input)) return false;
-
-  // Ensure |output_sanitizer_| has a valid base timestamp so we can use it for
-  // timestamp calculations.
-  if (output_ts_helper.base_timestamp() == kNoTimestamp) {
-    output_sanitizer_->ResetTimestampState(
-        0, pre_splice_sanitizer_->timestamp_helper().base_timestamp());
-  }
-
-  // If a splice frame was incorrectly marked due to poor demuxed timestamps, we
-  // may not actually have a splice.  Here we check if any frames exist before
-  // the splice.  In this case, just transfer all data to the output sanitizer.
-  const int frames_before_splice =
-      output_ts_helper.base_timestamp() == kNoTimestamp
-          ? 0
-          : output_ts_helper.GetFramesToTarget(splice_timestamp_);
-  if (frames_before_splice < 0 ||
-      pre_splice_sanitizer_->GetFrameCount() <= frames_before_splice) {
-    CHECK(pre_splice_sanitizer_->DrainInto(output_sanitizer_.get()));
-
-    // If the file contains incorrectly muxed timestamps, there may be huge gaps
-    // between the demuxed and decoded timestamps.
-    if (!post_splice_sanitizer_->DrainInto(output_sanitizer_.get()))
-      return false;
-
-    reset_splice_timestamps();
-    return true;
-  }
-
-  // Wait until we have enough data to crossfade or end of stream.
-  if (!input->end_of_stream() &&
-      input->timestamp() + input->duration() < max_splice_end_timestamp_) {
-    return true;
-  }
-
-  scoped_refptr<AudioBuffer> crossfade_buffer;
-  std::unique_ptr<AudioBus> pre_splice =
-      ExtractCrossfadeFromPreSplice(&crossfade_buffer);
-
-  // Crossfade the pre splice and post splice sections and transfer all relevant
-  // buffers into |output_sanitizer_|.
-  CrossfadePostSplice(std::move(pre_splice), crossfade_buffer);
-
-  // Clear the splice timestamp so new splices can be accepted.
-  reset_splice_timestamps();
-  return true;
-}
-
-bool AudioSplicer::HasNextBuffer() const {
-  return output_sanitizer_->HasNextBuffer();
-}
-
-scoped_refptr<AudioBuffer> AudioSplicer::GetNextBuffer() {
-  return output_sanitizer_->GetNextBuffer();
-}
-
-void AudioSplicer::SetSpliceTimestamp(base::TimeDelta splice_timestamp) {
-  if (splice_timestamp == kNoTimestamp) {
-    DCHECK(splice_timestamp_ != kNoTimestamp);
-    DCHECK(!have_all_pre_splice_buffers_);
-    have_all_pre_splice_buffers_ = true;
-    return;
-  }
-
-  if (splice_timestamp_ == splice_timestamp) return;
-
-  // TODO(dalecurtis): We may need the concept of a future_splice_timestamp_ to
-  // handle cases where another splice comes in before we've received 5ms of
-  // data from the last one.  Leave this as a CHECK for now to figure out if
-  // this case is possible.
-  CHECK(splice_timestamp_ == kNoTimestamp);
-  splice_timestamp_ = splice_timestamp;
-  max_splice_end_timestamp_ = splice_timestamp_ + max_crossfade_duration_;
-  pre_splice_sanitizer_->Reset();
-  post_splice_sanitizer_->Reset();
-  have_all_pre_splice_buffers_ = false;
-}
-
-std::unique_ptr<AudioBus> AudioSplicer::ExtractCrossfadeFromPreSplice(
-    scoped_refptr<AudioBuffer>* crossfade_buffer) {
-  DCHECK(crossfade_buffer);
-  const AudioTimestampHelper& output_ts_helper =
-      output_sanitizer_->timestamp_helper();
-
-  int frames_before_splice =
-      output_ts_helper.GetFramesToTarget(splice_timestamp_);
-
-  // Determine crossfade frame count based on available frames in each splicer
-  // and capping to the maximum crossfade duration.
-  const int max_crossfade_frame_count =
-      output_ts_helper.GetFramesToTarget(max_splice_end_timestamp_) -
-      frames_before_splice;
-  const int frames_to_crossfade = std::min(
-      max_crossfade_frame_count,
-      std::min(pre_splice_sanitizer_->GetFrameCount() - frames_before_splice,
-               post_splice_sanitizer_->GetFrameCount()));
-  // There must always be frames to crossfade, otherwise the splice should not
-  // have been generated.
-  DCHECK_GT(frames_to_crossfade, 0);
-
-  int frames_read = 0;
-  std::unique_ptr<AudioBus> output_bus;
-  while (pre_splice_sanitizer_->HasNextBuffer() &&
-         frames_read < frames_to_crossfade) {
-    scoped_refptr<AudioBuffer> preroll = pre_splice_sanitizer_->GetNextBuffer();
-
-    // We don't know the channel count until we see the first buffer, so wait
-    // until the first buffer to allocate the output AudioBus.
-    if (!output_bus) {
-      output_bus =
-          AudioBus::Create(preroll->channel_count(), frames_to_crossfade);
-      // Allocate output buffer for crossfade.
-      *crossfade_buffer = AudioBuffer::CreateBuffer(
-          kSampleFormatPlanarF32, preroll->channel_layout(),
-          preroll->channel_count(), preroll->sample_rate(),
-          frames_to_crossfade);
-    }
-
-    // There may be enough of a gap introduced during decoding such that an
-    // entire buffer exists before the splice point.
-    if (frames_before_splice >= preroll->frame_count()) {
-      // Adjust the number of frames remaining before the splice.  NOTE: This is
-      // safe since |pre_splice_sanitizer_| is a continuation of the timeline in
-      // |output_sanitizer_|.  As such we're guaranteed there are no gaps or
-      // overlaps in the timeline between the two sanitizers.
-      frames_before_splice -= preroll->frame_count();
-      CHECK(output_sanitizer_->AddInput(preroll));
-      continue;
-    }
-
-    const int frames_to_read =
-        std::min(preroll->frame_count() - frames_before_splice,
-                 output_bus->frames() - frames_read);
-    preroll->ReadFrames(frames_to_read, frames_before_splice, frames_read,
-                        output_bus.get());
-    frames_read += frames_to_read;
-
-    // If only part of the buffer was consumed, trim it appropriately and stick
-    // it into the output queue.
-    if (frames_before_splice) {
-      preroll->TrimEnd(preroll->frame_count() - frames_before_splice);
-      CHECK(output_sanitizer_->AddInput(preroll));
-      frames_before_splice = 0;
-    }
-  }
-
-  // Ensure outputs were properly allocated.  The method should not have been
-  // called if there is not enough data to crossfade.
-  // TODO(dalecurtis): Convert to DCHECK() once http://crbug.com/356073 fixed.
-  CHECK(output_bus);
-  CHECK(crossfade_buffer->get());
-
-  // All necessary buffers have been processed, it's safe to reset.
-  pre_splice_sanitizer_->Reset();
-  DCHECK_EQ(output_bus->frames(), frames_read);
-  DCHECK_EQ(output_ts_helper.GetFramesToTarget(splice_timestamp_), 0);
-  return output_bus;
-}
-
-void AudioSplicer::CrossfadePostSplice(
-    std::unique_ptr<AudioBus> pre_splice_bus,
-    const scoped_refptr<AudioBuffer>& crossfade_buffer) {
-  // Use the calculated timestamp and duration to ensure there's no extra gaps
-  // or overlaps to process when adding the buffer to |output_sanitizer_|.
-  const AudioTimestampHelper& output_ts_helper =
-      output_sanitizer_->timestamp_helper();
-  crossfade_buffer->set_timestamp(output_ts_helper.GetTimestamp());
-
-  // AudioBuffer::ReadFrames() only allows output into an AudioBus, so wrap
-  // our AudioBuffer in one so we can avoid extra data copies.
-  std::unique_ptr<AudioBus> output_bus =
-      CreateAudioBufferWrapper(crossfade_buffer);
-
-  // Extract crossfade section from the |post_splice_sanitizer_|.
-  int frames_read = 0, frames_to_trim = 0;
-  scoped_refptr<AudioBuffer> remainder;
-  while (post_splice_sanitizer_->HasNextBuffer() &&
-         frames_read < output_bus->frames()) {
-    scoped_refptr<AudioBuffer> postroll =
-        post_splice_sanitizer_->GetNextBuffer();
-    const int frames_to_read =
-        std::min(postroll->frame_count(), output_bus->frames() - frames_read);
-    postroll->ReadFrames(frames_to_read, 0, frames_read, output_bus.get());
-    frames_read += frames_to_read;
-
-    // If only part of the buffer was consumed, save it for after we've added
-    // the crossfade buffer
-    if (frames_to_read < postroll->frame_count()) {
-      DCHECK(!remainder.get());
-      remainder.swap(postroll);
-      frames_to_trim = frames_to_read;
-    }
-  }
-
-  DCHECK_EQ(output_bus->frames(), frames_read);
-
-  // Crossfade the audio into |crossfade_buffer|.
-  for (int ch = 0; ch < output_bus->channels(); ++ch) {
-    vector_math::Crossfade(pre_splice_bus->channel(ch),
-                           pre_splice_bus->frames(), output_bus->channel(ch));
-  }
-
-  CHECK(output_sanitizer_->AddInput(crossfade_buffer));
-  DCHECK_EQ(crossfade_buffer->frame_count(), output_bus->frames());
-
-  if (remainder.get()) {
-    // Trim off consumed frames.
-    AccurateTrimStart(frames_to_trim, remainder, output_ts_helper);
-    CHECK(output_sanitizer_->AddInput(remainder));
-  }
-
-  // Transfer all remaining buffers out and reset once empty.
-  CHECK(post_splice_sanitizer_->DrainInto(output_sanitizer_.get()));
-  post_splice_sanitizer_->Reset();
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/audio_splicer.h b/src/cobalt/media/base/audio_splicer.h
deleted file mode 100644
index 550fa70..0000000
--- a/src/cobalt/media/base/audio_splicer.h
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_AUDIO_SPLICER_H_
-#define COBALT_MEDIA_BASE_AUDIO_SPLICER_H_
-
-#include <memory>
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-#include "base/time.h"
-#include "cobalt/media/base/audio_parameters.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/timestamp_constants.h"
-
-namespace cobalt {
-namespace media {
-
-class AudioBuffer;
-class AudioBus;
-class AudioStreamSanitizer;
-class MediaLog;
-
-// Helper class that handles filling gaps and resolving overlaps.
-class MEDIA_EXPORT AudioSplicer {
- public:
-  AudioSplicer(int samples_per_second,
-               const scoped_refptr<MediaLog>& media_log);
-  ~AudioSplicer();
-
-  enum {
-    // The number of ms to crossfade before trimming when buffers overlap.
-    kCrossfadeDurationInMilliseconds = 5,
-
-    // Largest gap or overlap allowed between buffers.  Anything larger than
-    // this will trigger an error.  This is an arbitrary value, but the initial
-    // selection of 50ms roughly represents the duration of 2 compressed AAC or
-    // MP3 frames.
-    kMaxTimeDeltaInMilliseconds = 50,
-  };
-
-  // Resets the splicer state by clearing the output buffers queue and resetting
-  // the timestamp helper.
-  void Reset();
-
-  // Adds a new buffer full of samples or end of stream buffer to the splicer.
-  // Returns true if the buffer was accepted.  False is returned if an error
-  // occurred.
-  bool AddInput(const scoped_refptr<AudioBuffer>& input);
-
-  // Returns true if the splicer has a buffer to return.
-  bool HasNextBuffer() const;
-
-  // Removes the next buffer from the output buffer queue and returns it; this
-  // should only be called if HasNextBuffer() returns true.
-  scoped_refptr<AudioBuffer> GetNextBuffer();
-
-  // Indicates an upcoming splice point.  All buffers overlapping or after the
-  // |splice_timestamp| will be considered as "before the splice."  Clients must
-  // then call SetSpliceTimestamp(kNoTimestamp) to signal that future buffers
-  // should be considered as "after the splice."
-  //
-  // Once |kCrossfadeDurationInMilliseconds| of buffers "after the splice" or
-  // end of stream has been received, the "after" buffers will be crossfaded
-  // with all "before" buffers which overlap them.  "before" buffers outside
-  // of the overlap range will be discarded.
-  void SetSpliceTimestamp(base::TimeDelta splice_timestamp);
-
- private:
-  friend class AudioSplicerTest;
-
-  // Extracts frames to be crossfaded from |pre_splice_sanitizer_|.  Transfers
-  // all frames before |splice_timestamp_| into |output_sanitizer_| and drops
-  // frames outside of the crossfade duration.
-  //
-  // The size of the returned AudioBus is the crossfade duration in frames.
-  // Crossfade duration is calculated based on the number of frames available
-  // after |splice_timestamp_| in each sanitizer and capped by
-  // |max_crossfade_duration_|.
-  //
-  // |pre_splice_sanitizer_| will be empty after this operation.
-  std::unique_ptr<AudioBus> ExtractCrossfadeFromPreSplice(
-      scoped_refptr<AudioBuffer>* crossfade_buffer);
-
-  // Crossfades |pre_splice_bus->frames()| frames from
-  // |post_splice_sanitizer_|
-  // with those from |pre_splice_bus|.  Adds the crossfaded buffer to
-  // |output_sanitizer_| along with all buffers in |post_splice_sanitizer_|.
-  //
-  // |post_splice_sanitizer_| will be empty after this operation.
-  void CrossfadePostSplice(std::unique_ptr<AudioBus> pre_splice_bus,
-                           const scoped_refptr<AudioBuffer>& crossfade_buffer);
-
-  // Reset the splice and splice end timestamps.
-  void reset_splice_timestamps() {
-    splice_timestamp_ = max_splice_end_timestamp_ = kNoTimestamp;
-  }
-
-  const base::TimeDelta max_crossfade_duration_;
-  base::TimeDelta splice_timestamp_;
-  base::TimeDelta max_splice_end_timestamp_;
-
-  // The various sanitizers for each stage of the crossfade process.  Buffers in
-  // |output_sanitizer_| are immediately available for consumption by external
-  // callers.
-  //
-  // Overlapped buffers go into the |pre_splice_sanitizer_| while overlapping
-  // buffers go into the |post_splice_sanitizer_|.  Once enough buffers for
-  // crossfading are received the pre and post sanitizers are drained into
-  // |output_sanitizer_| by the two ExtractCrossfadeFromXXX methods above.
-  //
-  // |pre_splice_sanitizer_| is not constructed until the first splice frame is
-  // encountered.  At which point it is constructed based on the timestamp state
-  // of |output_sanitizer_|.  It is destructed once the splice is finished.
-  std::unique_ptr<AudioStreamSanitizer> output_sanitizer_;
-  std::unique_ptr<AudioStreamSanitizer> pre_splice_sanitizer_;
-  std::unique_ptr<AudioStreamSanitizer> post_splice_sanitizer_;
-
-  // Whether all buffers which should go into |pre_splice_sanitizer_| have been
-  // received.  If true, buffers should now be put in |post_splice_sanitizer_|.
-  bool have_all_pre_splice_buffers_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(AudioSplicer);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_AUDIO_SPLICER_H_
diff --git a/src/cobalt/media/base/audio_splicer_unittest.cc b/src/cobalt/media/base/audio_splicer_unittest.cc
deleted file mode 100644
index 29220c6..0000000
--- a/src/cobalt/media/base/audio_splicer_unittest.cc
+++ /dev/null
@@ -1,743 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/audio_splicer.h"
-
-#include <memory>
-
-#include "base/basictypes.h"
-#include "cobalt/media/base/audio_buffer.h"
-#include "cobalt/media/base/audio_bus.h"
-#include "cobalt/media/base/audio_timestamp_helper.h"
-#include "cobalt/media/base/test_helpers.h"
-#include "cobalt/media/base/timestamp_constants.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cobalt {
-namespace media {
-
-// Do not change this format.  AddInput() and GetValue() only work with float.
-static const SampleFormat kSampleFormat = kSampleFormatF32;
-static_assert(kSampleFormat == kSampleFormatF32, "invalid splice format");
-
-static const int kChannels = 1;
-static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_MONO;
-static const int kDefaultSampleRate = 44100;
-static const int kDefaultBufferSize = 100;
-
-class AudioSplicerTest : public ::testing::Test {
- public:
-  AudioSplicerTest()
-      : splicer_(kDefaultSampleRate, new MediaLog()),
-        input_timestamp_helper_(kDefaultSampleRate) {
-    input_timestamp_helper_.SetBaseTimestamp(base::TimeDelta());
-  }
-
-  scoped_refptr<AudioBuffer> GetNextInputBuffer(float value) {
-    return GetNextInputBuffer(value, kDefaultBufferSize);
-  }
-
-  scoped_refptr<AudioBuffer> GetNextInputBuffer(float value, int frame_size) {
-    scoped_refptr<AudioBuffer> buffer = MakeAudioBuffer<float>(
-        kSampleFormat, kChannelLayout, kChannels, kDefaultSampleRate, value,
-        0.0f, frame_size, input_timestamp_helper_.GetTimestamp());
-    input_timestamp_helper_.AddFrames(frame_size);
-    return buffer;
-  }
-
-  float GetValue(const scoped_refptr<AudioBuffer>& buffer) {
-    return reinterpret_cast<const float*>(buffer->channel_data()[0])[0];
-  }
-
-  bool VerifyData(const scoped_refptr<AudioBuffer>& buffer, float value) {
-    int frames = buffer->frame_count();
-    std::unique_ptr<AudioBus> bus = AudioBus::Create(kChannels, frames);
-    buffer->ReadFrames(frames, 0, 0, bus.get());
-    for (int ch = 0; ch < buffer->channel_count(); ++ch) {
-      for (int i = 0; i < frames; ++i) {
-        if (bus->channel(ch)[i] != value) return false;
-      }
-    }
-    return true;
-  }
-
-  void VerifyNextBuffer(const scoped_refptr<AudioBuffer>& input) {
-    ASSERT_TRUE(splicer_.HasNextBuffer());
-    scoped_refptr<AudioBuffer> output = splicer_.GetNextBuffer();
-    EXPECT_EQ(input->timestamp(), output->timestamp());
-    EXPECT_EQ(input->duration(), output->duration());
-    EXPECT_EQ(input->frame_count(), output->frame_count());
-    EXPECT_TRUE(VerifyData(output, GetValue(input)));
-  }
-
-  void VerifyPreSpliceOutput(
-      const scoped_refptr<AudioBuffer>& overlapped_buffer,
-      const scoped_refptr<AudioBuffer>& overlapping_buffer,
-      int expected_pre_splice_size,
-      base::TimeDelta expected_pre_splice_duration) {
-    ASSERT_TRUE(splicer_.HasNextBuffer());
-    scoped_refptr<AudioBuffer> pre_splice_output = splicer_.GetNextBuffer();
-    EXPECT_EQ(overlapped_buffer->timestamp(), pre_splice_output->timestamp());
-    EXPECT_EQ(expected_pre_splice_size, pre_splice_output->frame_count());
-    EXPECT_EQ(expected_pre_splice_duration, pre_splice_output->duration());
-    EXPECT_TRUE(VerifyData(pre_splice_output, GetValue(overlapped_buffer)));
-  }
-
-  void VerifyCrossfadeOutput(
-      const scoped_refptr<AudioBuffer>& overlapped_buffer_1,
-      const scoped_refptr<AudioBuffer>& overlapped_buffer_2,
-      const scoped_refptr<AudioBuffer>& overlapping_buffer,
-      int second_overlap_index, int expected_crossfade_size,
-      base::TimeDelta expected_crossfade_duration) {
-    ASSERT_TRUE(splicer_.HasNextBuffer());
-
-    scoped_refptr<AudioBuffer> crossfade_output = splicer_.GetNextBuffer();
-    EXPECT_EQ(expected_crossfade_size, crossfade_output->frame_count());
-    EXPECT_EQ(expected_crossfade_duration, crossfade_output->duration());
-
-    // The splice timestamp may be adjusted by a microsecond.
-    EXPECT_NEAR(overlapping_buffer->timestamp().InMicroseconds(),
-                crossfade_output->timestamp().InMicroseconds(), 1);
-
-    // Verify the actual crossfade.
-    const int frames = crossfade_output->frame_count();
-    float overlapped_value = GetValue(overlapped_buffer_1);
-    const float overlapping_value = GetValue(overlapping_buffer);
-    std::unique_ptr<AudioBus> bus = AudioBus::Create(kChannels, frames);
-    crossfade_output->ReadFrames(frames, 0, 0, bus.get());
-    for (int ch = 0; ch < crossfade_output->channel_count(); ++ch) {
-      float cf_ratio = 0;
-      const float cf_increment = 1.0f / frames;
-      for (int i = 0; i < frames; ++i, cf_ratio += cf_increment) {
-        if (overlapped_buffer_2.get() && i >= second_overlap_index)
-          overlapped_value = GetValue(overlapped_buffer_2);
-        const float actual = bus->channel(ch)[i];
-        const float expected =
-            (1.0f - cf_ratio) * overlapped_value + cf_ratio * overlapping_value;
-        ASSERT_FLOAT_EQ(expected, actual) << "i=" << i;
-      }
-    }
-  }
-
-  bool AddInput(const scoped_refptr<AudioBuffer>& input) {
-    // Since the splicer doesn't make copies it's working directly on the input
-    // buffers.  We must make a copy before adding to ensure the original buffer
-    // is not modified in unexpected ways.
-    scoped_refptr<AudioBuffer> buffer_copy =
-        input->end_of_stream()
-            ? AudioBuffer::CreateEOSBuffer()
-            : AudioBuffer::CopyFrom(kSampleFormat, input->channel_layout(),
-                                    input->channel_count(),
-                                    input->sample_rate(), input->frame_count(),
-                                    &input->channel_data()[0],
-                                    input->timestamp());
-    return splicer_.AddInput(buffer_copy);
-  }
-
-  base::TimeDelta max_crossfade_duration() {
-    return splicer_.max_crossfade_duration_;
-  }
-
- protected:
-  AudioSplicer splicer_;
-  AudioTimestampHelper input_timestamp_helper_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AudioSplicerTest);
-};
-
-TEST_F(AudioSplicerTest, PassThru) {
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-
-  // Test single buffer pass-thru behavior.
-  scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
-  EXPECT_TRUE(AddInput(input_1));
-  VerifyNextBuffer(input_1);
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-
-  // Test that multiple buffers can be queued in the splicer.
-  scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
-  scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.3f);
-  EXPECT_TRUE(AddInput(input_2));
-  EXPECT_TRUE(AddInput(input_3));
-  VerifyNextBuffer(input_2);
-  VerifyNextBuffer(input_3);
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-}
-
-TEST_F(AudioSplicerTest, Reset) {
-  scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
-  EXPECT_TRUE(AddInput(input_1));
-  ASSERT_TRUE(splicer_.HasNextBuffer());
-
-  splicer_.Reset();
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-
-  // Add some bytes to the timestamp helper so that the
-  // next buffer starts many frames beyond the end of
-  // |input_1|. This is to make sure that Reset() actually
-  // clears its state and doesn't try to insert a gap.
-  input_timestamp_helper_.AddFrames(100);
-
-  // Verify that a new input buffer passes through as expected.
-  scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
-  EXPECT_TRUE(AddInput(input_2));
-  VerifyNextBuffer(input_2);
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-}
-
-TEST_F(AudioSplicerTest, EndOfStream) {
-  scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
-  scoped_refptr<AudioBuffer> input_2 = AudioBuffer::CreateEOSBuffer();
-  scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.2f);
-  EXPECT_TRUE(input_2->end_of_stream());
-
-  EXPECT_TRUE(AddInput(input_1));
-  EXPECT_TRUE(AddInput(input_2));
-
-  VerifyNextBuffer(input_1);
-
-  scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer();
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-  EXPECT_TRUE(output_2->end_of_stream());
-
-  // Verify that buffers can be added again after Reset().
-  splicer_.Reset();
-  EXPECT_TRUE(AddInput(input_3));
-  VerifyNextBuffer(input_3);
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-}
-
-// Test the gap insertion code.
-// +--------------+    +--------------+
-// |11111111111111|    |22222222222222|
-// +--------------+    +--------------+
-// Results in:
-// +--------------+----+--------------+
-// |11111111111111|0000|22222222222222|
-// +--------------+----+--------------+
-TEST_F(AudioSplicerTest, GapInsertion) {
-  scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
-
-  // Add bytes to the timestamp helper so that the next buffer
-  // will have a starting timestamp that indicates a gap is
-  // present.
-  const int kGapSize = 7;
-  input_timestamp_helper_.AddFrames(kGapSize);
-  scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
-
-  EXPECT_TRUE(AddInput(input_1));
-  EXPECT_TRUE(AddInput(input_2));
-
-  // Verify that the first input buffer passed through unmodified.
-  VerifyNextBuffer(input_1);
-
-  // Verify the contents of the gap buffer.
-  scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer();
-  base::TimeDelta gap_timestamp = input_1->timestamp() + input_1->duration();
-  base::TimeDelta gap_duration = input_2->timestamp() - gap_timestamp;
-  EXPECT_GT(gap_duration, base::TimeDelta());
-  EXPECT_EQ(gap_timestamp, output_2->timestamp());
-  EXPECT_NEAR(gap_duration.InMicroseconds(),
-              output_2->duration().InMicroseconds(), 1);
-  EXPECT_EQ(kGapSize, output_2->frame_count());
-  EXPECT_TRUE(VerifyData(output_2, 0.0f));
-
-  // Verify that the second input buffer passed through unmodified.
-  VerifyNextBuffer(input_2);
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-}
-
-// Test that an error is signalled when the gap between input buffers is
-// too large.
-TEST_F(AudioSplicerTest, GapTooLarge) {
-  scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
-
-  // Add a seconds worth of bytes so that an unacceptably large
-  // gap exists between |input_1| and |input_2|.
-  const int kGapSize = kDefaultSampleRate;
-  input_timestamp_helper_.AddFrames(kGapSize);
-  scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
-
-  EXPECT_TRUE(AddInput(input_1));
-  EXPECT_FALSE(AddInput(input_2));
-
-  VerifyNextBuffer(input_1);
-
-  // Verify that the second buffer is not available.
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-
-  // Reset the timestamp helper so it can generate a buffer that is
-  // right after |input_1|.
-  input_timestamp_helper_.SetBaseTimestamp(input_1->timestamp() +
-                                           input_1->duration());
-
-  // Verify that valid buffers are still accepted.
-  scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.3f);
-  EXPECT_TRUE(AddInput(input_3));
-  VerifyNextBuffer(input_3);
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-}
-
-// Verifies that an error is signalled if AddInput() is called
-// with a timestamp that is earlier than the first buffer added.
-TEST_F(AudioSplicerTest, BufferAddedBeforeBase) {
-  input_timestamp_helper_.SetBaseTimestamp(
-      base::TimeDelta::FromMicroseconds(10));
-  scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
-
-  // Reset the timestamp helper so the next buffer will have a timestamp earlier
-  // than |input_1|.
-  input_timestamp_helper_.SetBaseTimestamp(base::TimeDelta::FromSeconds(0));
-  scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.1f);
-
-  EXPECT_GT(input_1->timestamp(), input_2->timestamp());
-  EXPECT_TRUE(AddInput(input_1));
-  EXPECT_FALSE(AddInput(input_2));
-}
-
-// Test when one buffer partially overlaps another.
-// +--------------+
-// |11111111111111|
-// +--------------+
-//            +--------------+
-//            |22222222222222|
-//            +--------------+
-// Results in:
-// +--------------+----------+
-// |11111111111111|2222222222|
-// +--------------+----------+
-TEST_F(AudioSplicerTest, PartialOverlap) {
-  scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
-
-  // Reset timestamp helper so that the next buffer will have a
-  // timestamp that starts in the middle of |input_1|.
-  const int kOverlapSize = input_1->frame_count() / 4;
-  input_timestamp_helper_.SetBaseTimestamp(input_1->timestamp());
-  input_timestamp_helper_.AddFrames(input_1->frame_count() - kOverlapSize);
-
-  scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f);
-
-  EXPECT_TRUE(AddInput(input_1));
-  EXPECT_TRUE(AddInput(input_2));
-
-  // Verify that the first input buffer passed through unmodified.
-  VerifyNextBuffer(input_1);
-
-  ASSERT_TRUE(splicer_.HasNextBuffer());
-  scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer();
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-
-  // Verify that the second input buffer was truncated to only contain
-  // the samples that are after the end of |input_1|.
-  base::TimeDelta expected_timestamp =
-      input_1->timestamp() + input_1->duration();
-  base::TimeDelta expected_duration =
-      (input_2->timestamp() + input_2->duration()) - expected_timestamp;
-  EXPECT_EQ(expected_timestamp, output_2->timestamp());
-  EXPECT_EQ(expected_duration, output_2->duration());
-  EXPECT_TRUE(VerifyData(output_2, GetValue(input_2)));
-}
-
-// Test that an input buffer that is completely overlapped by a buffer
-// that was already added is dropped.
-// +--------------+
-// |11111111111111|
-// +--------------+
-//       +-----+
-//       |22222|
-//       +-----+
-//                +-------------+
-//                |3333333333333|
-//                +-------------+
-// Results in:
-// +--------------+-------------+
-// |11111111111111|3333333333333|
-// +--------------+-------------+
-TEST_F(AudioSplicerTest, DropBuffer) {
-  scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f);
-
-  // Reset timestamp helper so that the next buffer will have a
-  // timestamp that starts in the middle of |input_1|.
-  const int kOverlapOffset = input_1->frame_count() / 2;
-  const int kOverlapSize = input_1->frame_count() / 4;
-  input_timestamp_helper_.SetBaseTimestamp(input_1->timestamp());
-  input_timestamp_helper_.AddFrames(kOverlapOffset);
-
-  scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f, kOverlapSize);
-
-  // Reset the timestamp helper so the next buffer will be right after
-  // |input_1|.
-  input_timestamp_helper_.SetBaseTimestamp(input_1->timestamp());
-  input_timestamp_helper_.AddFrames(input_1->frame_count());
-  scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.3f);
-
-  EXPECT_TRUE(AddInput(input_1));
-  EXPECT_TRUE(AddInput(input_2));
-  EXPECT_TRUE(AddInput(input_3));
-
-  VerifyNextBuffer(input_1);
-  VerifyNextBuffer(input_3);
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-}
-
-// Test crossfade when one buffer partially overlaps another.
-// +--------------+
-// |11111111111111|
-// +--------------+
-//            +--------------+
-//            |22222222222222|
-//            +--------------+
-// Results in:
-// +----------+----+----------+
-// |1111111111|xxxx|2222222222|
-// +----------+----+----------+
-// Where "xxxx" represents the crossfaded portion of the signal.
-TEST_F(AudioSplicerTest, PartialOverlapCrossfade) {
-  const int kCrossfadeSize =
-      input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration());
-  const int kBufferSize = kCrossfadeSize * 2;
-
-  scoped_refptr<AudioBuffer> extra_pre_splice_buffer =
-      GetNextInputBuffer(0.2f, kBufferSize);
-  scoped_refptr<AudioBuffer> overlapped_buffer =
-      GetNextInputBuffer(1.0f, kBufferSize);
-
-  // Reset timestamp helper so that the next buffer will have a timestamp that
-  // starts in the middle of |overlapped_buffer|.
-  input_timestamp_helper_.SetBaseTimestamp(overlapped_buffer->timestamp());
-  input_timestamp_helper_.AddFrames(overlapped_buffer->frame_count() -
-                                    kCrossfadeSize);
-  splicer_.SetSpliceTimestamp(input_timestamp_helper_.GetTimestamp());
-  scoped_refptr<AudioBuffer> overlapping_buffer =
-      GetNextInputBuffer(0.0f, kBufferSize);
-
-  // |extra_pre_splice_buffer| is entirely before the splice and should be ready
-  // for output.
-  EXPECT_TRUE(AddInput(extra_pre_splice_buffer));
-  VerifyNextBuffer(extra_pre_splice_buffer);
-
-  // The splicer should be internally queuing input since |overlapped_buffer| is
-  // part of the splice.
-  EXPECT_TRUE(AddInput(overlapped_buffer));
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-
-  // |overlapping_buffer| completes the splice.
-  splicer_.SetSpliceTimestamp(kNoTimestamp);
-  EXPECT_TRUE(AddInput(overlapping_buffer));
-  ASSERT_TRUE(splicer_.HasNextBuffer());
-
-  // Add one more buffer to make sure it's passed through untouched.
-  scoped_refptr<AudioBuffer> extra_post_splice_buffer =
-      GetNextInputBuffer(0.5f, kBufferSize);
-  EXPECT_TRUE(AddInput(extra_post_splice_buffer));
-
-  VerifyPreSpliceOutput(overlapped_buffer, overlapping_buffer, 221,
-                        base::TimeDelta::FromMicroseconds(5011));
-
-  // Due to rounding the crossfade size may vary by up to a frame.
-  const int kExpectedCrossfadeSize = 220;
-  EXPECT_NEAR(kExpectedCrossfadeSize, kCrossfadeSize, 1);
-
-  VerifyCrossfadeOutput(overlapped_buffer, NULL, overlapping_buffer, 0,
-                        kExpectedCrossfadeSize,
-                        base::TimeDelta::FromMicroseconds(4988));
-
-  // Retrieve the remaining portion after crossfade.
-  ASSERT_TRUE(splicer_.HasNextBuffer());
-  scoped_refptr<AudioBuffer> post_splice_output = splicer_.GetNextBuffer();
-  EXPECT_EQ(base::TimeDelta::FromMicroseconds(20022),
-            post_splice_output->timestamp());
-  EXPECT_EQ(overlapping_buffer->frame_count() - kExpectedCrossfadeSize,
-            post_splice_output->frame_count());
-  EXPECT_EQ(base::TimeDelta::FromMicroseconds(5034),
-            post_splice_output->duration());
-
-  EXPECT_TRUE(VerifyData(post_splice_output, GetValue(overlapping_buffer)));
-
-  VerifyNextBuffer(extra_post_splice_buffer);
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-}
-
-// Test crossfade when one buffer partially overlaps another, but an end of
-// stream buffer is received before the crossfade duration is reached.
-// +--------------+
-// |11111111111111|
-// +--------------+
-//            +---------++---+
-//            |222222222||EOS|
-//            +---------++---+
-// Results in:
-// +----------+----+----++---+
-// |1111111111|xxxx|2222||EOS|
-// +----------+----+----++---+
-// Where "x" represents the crossfaded portion of the signal.
-TEST_F(AudioSplicerTest, PartialOverlapCrossfadeEndOfStream) {
-  const int kCrossfadeSize =
-      input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration());
-
-  scoped_refptr<AudioBuffer> overlapped_buffer =
-      GetNextInputBuffer(1.0f, kCrossfadeSize * 2);
-
-  // Reset timestamp helper so that the next buffer will have a timestamp that
-  // starts 3/4 of the way into |overlapped_buffer|.
-  input_timestamp_helper_.SetBaseTimestamp(overlapped_buffer->timestamp());
-  input_timestamp_helper_.AddFrames(3 * overlapped_buffer->frame_count() / 4);
-  splicer_.SetSpliceTimestamp(input_timestamp_helper_.GetTimestamp());
-  scoped_refptr<AudioBuffer> overlapping_buffer =
-      GetNextInputBuffer(0.0f, kCrossfadeSize / 3);
-
-  // The splicer should be internally queuing input since |overlapped_buffer| is
-  // part of the splice.
-  EXPECT_TRUE(AddInput(overlapped_buffer));
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-
-  // |overlapping_buffer| should not have enough data to complete the splice, so
-  // ensure output is not available.
-  splicer_.SetSpliceTimestamp(kNoTimestamp);
-  EXPECT_TRUE(AddInput(overlapping_buffer));
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-
-  // Now add an EOS buffer which should complete the splice.
-  EXPECT_TRUE(AddInput(AudioBuffer::CreateEOSBuffer()));
-
-  VerifyPreSpliceOutput(overlapped_buffer, overlapping_buffer, 331,
-                        base::TimeDelta::FromMicroseconds(7505));
-  VerifyCrossfadeOutput(overlapped_buffer, NULL, overlapping_buffer, 0,
-                        overlapping_buffer->frame_count(),
-                        overlapping_buffer->duration());
-
-  // Ensure the last buffer is an EOS buffer.
-  ASSERT_TRUE(splicer_.HasNextBuffer());
-  scoped_refptr<AudioBuffer> post_splice_output = splicer_.GetNextBuffer();
-  EXPECT_TRUE(post_splice_output->end_of_stream());
-
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-}
-
-// Test crossfade when one buffer partially overlaps another, but the amount of
-// overlapped data is less than the crossfade duration.
-// +------------+
-// |111111111111|
-// +------------+
-//            +--------------+
-//            |22222222222222|
-//            +--------------+
-// Results in:
-// +----------+-+------------+
-// |1111111111|x|222222222222|
-// +----------+-+------------+
-// Where "x" represents the crossfaded portion of the signal.
-TEST_F(AudioSplicerTest, PartialOverlapCrossfadeShortPreSplice) {
-  const int kCrossfadeSize =
-      input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration());
-
-  scoped_refptr<AudioBuffer> overlapped_buffer =
-      GetNextInputBuffer(1.0f, kCrossfadeSize / 2);
-
-  // Reset timestamp helper so that the next buffer will have a timestamp that
-  // starts in the middle of |overlapped_buffer|.
-  input_timestamp_helper_.SetBaseTimestamp(overlapped_buffer->timestamp());
-  input_timestamp_helper_.AddFrames(overlapped_buffer->frame_count() / 2);
-  splicer_.SetSpliceTimestamp(input_timestamp_helper_.GetTimestamp());
-  scoped_refptr<AudioBuffer> overlapping_buffer =
-      GetNextInputBuffer(0.0f, kCrossfadeSize * 2);
-
-  // The splicer should be internally queuing input since |overlapped_buffer| is
-  // part of the splice.
-  EXPECT_TRUE(AddInput(overlapped_buffer));
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-
-  // |overlapping_buffer| completes the splice.
-  splicer_.SetSpliceTimestamp(kNoTimestamp);
-  EXPECT_TRUE(AddInput(overlapping_buffer));
-
-  const int kExpectedPreSpliceSize = 55;
-  const base::TimeDelta kExpectedPreSpliceDuration =
-      base::TimeDelta::FromMicroseconds(1247);
-  VerifyPreSpliceOutput(overlapped_buffer, overlapping_buffer,
-                        kExpectedPreSpliceSize, kExpectedPreSpliceDuration);
-  VerifyCrossfadeOutput(overlapped_buffer, NULL, overlapping_buffer, 0,
-                        kExpectedPreSpliceSize, kExpectedPreSpliceDuration);
-
-  // Retrieve the remaining portion after crossfade.
-  ASSERT_TRUE(splicer_.HasNextBuffer());
-  scoped_refptr<AudioBuffer> post_splice_output = splicer_.GetNextBuffer();
-  EXPECT_EQ(overlapping_buffer->timestamp() + kExpectedPreSpliceDuration,
-            post_splice_output->timestamp());
-  EXPECT_EQ(overlapping_buffer->frame_count() - kExpectedPreSpliceSize,
-            post_splice_output->frame_count());
-  EXPECT_EQ(overlapping_buffer->duration() - kExpectedPreSpliceDuration,
-            post_splice_output->duration());
-
-  EXPECT_TRUE(VerifyData(post_splice_output, GetValue(overlapping_buffer)));
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-}
-
-// Test behavior when a splice frame is incorrectly marked and does not actually
-// overlap.
-// +----------+
-// |1111111111|
-// +----------+
-//            +--------------+
-//            |22222222222222|
-//            +--------------+
-// Results in:
-// +----------+--------------+
-// |1111111111|22222222222222|
-// +----------+--------------+
-TEST_F(AudioSplicerTest, IncorrectlyMarkedSplice) {
-  const int kBufferSize =
-      input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration()) * 2;
-
-  scoped_refptr<AudioBuffer> first_buffer =
-      GetNextInputBuffer(1.0f, kBufferSize);
-  // Fuzz the duration slightly so that the buffer overlaps the splice timestamp
-  // by a microsecond, which is not enough to crossfade.
-  const base::TimeDelta kSpliceTimestamp =
-      input_timestamp_helper_.GetTimestamp() -
-      base::TimeDelta::FromMicroseconds(1);
-  splicer_.SetSpliceTimestamp(kSpliceTimestamp);
-  scoped_refptr<AudioBuffer> second_buffer =
-      GetNextInputBuffer(0.0f, kBufferSize);
-  second_buffer->set_timestamp(kSpliceTimestamp);
-
-  // The splicer should be internally queuing input since |first_buffer| is part
-  // of the supposed splice.
-  EXPECT_TRUE(AddInput(first_buffer));
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-
-  // |second_buffer| should complete the supposed splice, so ensure output is
-  // now available.
-  splicer_.SetSpliceTimestamp(kNoTimestamp);
-  EXPECT_TRUE(AddInput(second_buffer));
-
-  VerifyNextBuffer(first_buffer);
-  VerifyNextBuffer(second_buffer);
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-}
-
-// Test behavior when a splice frame is incorrectly marked and there is a gap
-// between whats in the pre splice and post splice.
-// +--------+
-// |11111111|
-// +--------+
-//            +--------------+
-//            |22222222222222|
-//            +--------------+
-// Results in:
-// +--------+-+--------------+
-// |11111111|0|22222222222222|
-// +--------+-+--------------+
-TEST_F(AudioSplicerTest, IncorrectlyMarkedSpliceWithGap) {
-  const int kBufferSize =
-      input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration()) * 2;
-  const int kGapSize = 2;
-
-  scoped_refptr<AudioBuffer> first_buffer =
-      GetNextInputBuffer(1.0f, kBufferSize - kGapSize);
-  scoped_refptr<AudioBuffer> gap_buffer = GetNextInputBuffer(0.0f, kGapSize);
-  splicer_.SetSpliceTimestamp(input_timestamp_helper_.GetTimestamp());
-  scoped_refptr<AudioBuffer> second_buffer =
-      GetNextInputBuffer(0.0f, kBufferSize);
-
-  // The splicer should pass through the first buffer since it's not part of the
-  // splice.
-  EXPECT_TRUE(AddInput(first_buffer));
-  VerifyNextBuffer(first_buffer);
-
-  // Do not add |gap_buffer|.
-
-  // |second_buffer| will complete the supposed splice.
-  splicer_.SetSpliceTimestamp(kNoTimestamp);
-  EXPECT_TRUE(AddInput(second_buffer));
-
-  VerifyNextBuffer(gap_buffer);
-  VerifyNextBuffer(second_buffer);
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-}
-
-// Test behavior when a splice frame is incorrectly marked and there is a gap
-// between what's in the pre splice and post splice that is too large to recover
-// from.
-// +--------+
-// |11111111|
-// +--------+
-//                    +------+
-//                    |222222|
-//                    +------+
-// Results in an error and not a crash.
-TEST_F(AudioSplicerTest, IncorrectlyMarkedSpliceWithBadGap) {
-  const int kBufferSize =
-      input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration()) * 2;
-  const int kGapSize = kBufferSize +
-                       input_timestamp_helper_.GetFramesToTarget(
-                           base::TimeDelta::FromMilliseconds(
-                               AudioSplicer::kMaxTimeDeltaInMilliseconds + 1));
-
-  scoped_refptr<AudioBuffer> first_buffer =
-      GetNextInputBuffer(1.0f, kBufferSize);
-  scoped_refptr<AudioBuffer> gap_buffer = GetNextInputBuffer(0.0f, kGapSize);
-  splicer_.SetSpliceTimestamp(input_timestamp_helper_.GetTimestamp());
-  scoped_refptr<AudioBuffer> second_buffer =
-      GetNextInputBuffer(0.0f, kBufferSize);
-
-  // The splicer should pass through the first buffer since it's not part of the
-  // splice.
-  EXPECT_TRUE(AddInput(first_buffer));
-  VerifyNextBuffer(first_buffer);
-
-  // Do not add |gap_buffer|.
-
-  // |second_buffer| will complete the supposed splice.
-  splicer_.SetSpliceTimestamp(kNoTimestamp);
-  EXPECT_FALSE(AddInput(second_buffer));
-}
-
-// Ensure we don't crash when a splice frame is incorrectly marked such that the
-// splice timestamp has already passed when SetSpliceTimestamp() is called.
-// This can happen if the encoded timestamps are too far behind the decoded
-// timestamps.
-TEST_F(AudioSplicerTest, IncorrectlyMarkedPastSplice) {
-  const int kBufferSize = 200;
-
-  scoped_refptr<AudioBuffer> first_buffer =
-      GetNextInputBuffer(1.0f, kBufferSize);
-  EXPECT_TRUE(AddInput(first_buffer));
-  VerifyNextBuffer(first_buffer);
-
-  // Start the splice at a timestamp which has already occurred.
-  splicer_.SetSpliceTimestamp(base::TimeDelta());
-
-  scoped_refptr<AudioBuffer> second_buffer =
-      GetNextInputBuffer(0.5f, kBufferSize);
-  EXPECT_TRUE(AddInput(second_buffer));
-  EXPECT_FALSE(splicer_.HasNextBuffer());
-
-  // |third_buffer| will complete the supposed splice.  The buffer size is set
-  // such that unchecked the splicer would try to trim off a negative number of
-  // frames.
-  splicer_.SetSpliceTimestamp(kNoTimestamp);
-  scoped_refptr<AudioBuffer> third_buffer =
-      GetNextInputBuffer(0.0f, kBufferSize * 10);
-  third_buffer->set_timestamp(base::TimeDelta());
-  EXPECT_TRUE(AddInput(third_buffer));
-
-  // The second buffer should come through unmodified.
-  VerifyNextBuffer(second_buffer);
-
-  // The third buffer should be partially dropped since it overlaps the second.
-  ASSERT_TRUE(splicer_.HasNextBuffer());
-  const base::TimeDelta second_buffer_end_ts =
-      second_buffer->timestamp() + second_buffer->duration();
-  scoped_refptr<AudioBuffer> output = splicer_.GetNextBuffer();
-  EXPECT_EQ(second_buffer_end_ts, output->timestamp());
-  EXPECT_EQ(third_buffer->duration() -
-                (second_buffer_end_ts - third_buffer->timestamp()),
-            output->duration());
-  EXPECT_TRUE(VerifyData(output, GetValue(third_buffer)));
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/cdm_callback_promise.cc b/src/cobalt/media/base/cdm_callback_promise.cc
deleted file mode 100644
index 28dbbee..0000000
--- a/src/cobalt/media/base/cdm_callback_promise.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/cdm_callback_promise.h"
-
-#include "base/callback_helpers.h"
-#include "base/logging.h"
-
-namespace cobalt {
-namespace media {
-
-template <typename... T>
-CdmCallbackPromise<T...>::CdmCallbackPromise(
-    const base::Callback<void(const T&...)>& resolve_cb,
-    const PromiseRejectedCB& reject_cb)
-    : resolve_cb_(resolve_cb), reject_cb_(reject_cb) {
-  DCHECK(!resolve_cb_.is_null());
-  DCHECK(!reject_cb_.is_null());
-}
-
-template <typename... T>
-CdmCallbackPromise<T...>::~CdmCallbackPromise() {
-  if (IsPromiseSettled()) return;
-
-  DCHECK(!resolve_cb_.is_null() && !reject_cb_.is_null());
-  RejectPromiseOnDestruction();
-}
-
-template <typename... T>
-void CdmCallbackPromise<T...>::resolve(const T&... result) {
-  MarkPromiseSettled();
-  base::ResetAndReturn(&resolve_cb_).Run(result...);
-}
-
-template <typename... T>
-void CdmCallbackPromise<T...>::reject(MediaKeys::Exception exception_code,
-                                      uint32_t system_code,
-                                      const std::string& error_message) {
-  MarkPromiseSettled();
-  base::ResetAndReturn(&reject_cb_)
-      .Run(exception_code, system_code, error_message);
-}
-
-// Explicit template instantiation for the Promises needed.
-template class MEDIA_EXPORT CdmCallbackPromise<>;
-template class MEDIA_EXPORT CdmCallbackPromise<std::string>;
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/cdm_callback_promise.h b/src/cobalt/media/base/cdm_callback_promise.h
deleted file mode 100644
index a721f56..0000000
--- a/src/cobalt/media/base/cdm_callback_promise.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_CDM_CALLBACK_PROMISE_H_
-#define COBALT_MEDIA_BASE_CDM_CALLBACK_PROMISE_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "cobalt/media/base/cdm_promise.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/media_keys.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-typedef base::Callback<void(
-    MediaKeys::Exception exception_code, uint32_t system_code,
-    const std::string& error_message)> PromiseRejectedCB;
-
-template <typename... T>
-class MEDIA_EXPORT CdmCallbackPromise : public CdmPromiseTemplate<T...> {
- public:
-  CdmCallbackPromise(const base::Callback<void(const T&...)>& resolve_cb,
-                     const PromiseRejectedCB& reject_cb);
-  virtual ~CdmCallbackPromise();
-
-  // CdmPromiseTemplate<T> implementation.
-  virtual void resolve(const T&... result) OVERRIDE;
-  virtual void reject(MediaKeys::Exception exception_code, uint32_t system_code,
-                      const std::string& error_message) OVERRIDE;
-
- private:
-  using CdmPromiseTemplate<T...>::IsPromiseSettled;
-  using CdmPromiseTemplate<T...>::MarkPromiseSettled;
-  using CdmPromiseTemplate<T...>::RejectPromiseOnDestruction;
-
-  base::Callback<void(const T&...)> resolve_cb_;
-  PromiseRejectedCB reject_cb_;
-
-  DISALLOW_COPY_AND_ASSIGN(CdmCallbackPromise);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_CDM_CALLBACK_PROMISE_H_
diff --git a/src/cobalt/media/base/cdm_config.h b/src/cobalt/media/base/cdm_config.h
deleted file mode 100644
index f197fb8..0000000
--- a/src/cobalt/media/base/cdm_config.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_CDM_CONFIG_H_
-#define COBALT_MEDIA_BASE_CDM_CONFIG_H_
-
-namespace cobalt {
-namespace media {
-
-// The runtime configuration for new CDM instances as computed by
-// |requestMediaKeySystemAccess|. This is in some sense the Chromium-side
-// counterpart of Blink's WebMediaKeySystemConfiguration.
-struct CdmConfig {
-  // Allow access to a distinctive identifier.
-  bool allow_distinctive_identifier = false;
-
-  // Allow access to persistent state.
-  bool allow_persistent_state = false;
-
-  // Use hardware-secure codecs. This flag is only used on Android, it should
-  // always be false on other platforms.
-  bool use_hw_secure_codecs = false;
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_CDM_CONFIG_H_
diff --git a/src/cobalt/media/base/cdm_context.cc b/src/cobalt/media/base/cdm_context.cc
deleted file mode 100644
index d6af837..0000000
--- a/src/cobalt/media/base/cdm_context.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/cdm_context.h"
-
-namespace cobalt {
-namespace media {
-
-const int CdmContext::kInvalidCdmId = 0;
-
-CdmContext::CdmContext() {}
-
-CdmContext::~CdmContext() {}
-
-void IgnoreCdmAttached(bool /* success */) {}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/cdm_context.h b/src/cobalt/media/base/cdm_context.h
deleted file mode 100644
index 8a27b8a..0000000
--- a/src/cobalt/media/base/cdm_context.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_CDM_CONTEXT_H_
-#define COBALT_MEDIA_BASE_CDM_CONTEXT_H_
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "cobalt/media/base/media_export.h"
-
-namespace cobalt {
-namespace media {
-
-class Decryptor;
-
-// An interface representing the context that a media player needs from a
-// content decryption module (CDM) to decrypt (and decode) encrypted buffers.
-// This is used to pass the CDM to the media player (e.g. SetCdm()).
-class MEDIA_EXPORT CdmContext {
- public:
-  // Indicates an invalid CDM ID. See GetCdmId() for details.
-  static const int kInvalidCdmId;
-
-  virtual ~CdmContext();
-
-  // Gets the Decryptor object associated with the CDM. Returns NULL if the
-  // CDM does not support a Decryptor (i.e. platform-based CDMs where decryption
-  // occurs implicitly along with decoding). The returned object is only
-  // guaranteed to be valid during the CDM's lifetime.
-  virtual Decryptor* GetDecryptor() = 0;
-
-  // Returns an ID that can be used to find a remote CDM, in which case this CDM
-  // serves as a proxy to the remote one. Returns kInvalidCdmId when remote CDM
-  // is not supported (e.g. this CDM is a local CDM).
-  virtual int GetCdmId() const = 0;
-
- protected:
-  CdmContext();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CdmContext);
-};
-
-// Callback to notify that the CdmContext has been completely attached to
-// the media pipeline. Parameter indicates whether the operation succeeded.
-typedef base::Callback<void(bool)> CdmAttachedCB;
-
-// A dummy implementation of CdmAttachedCB.
-MEDIA_EXPORT void IgnoreCdmAttached(bool success);
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_CDM_CONTEXT_H_
diff --git a/src/cobalt/media/base/cdm_factory.cc b/src/cobalt/media/base/cdm_factory.cc
deleted file mode 100644
index b227ab0..0000000
--- a/src/cobalt/media/base/cdm_factory.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/cdm_factory.h"
-
-namespace cobalt {
-namespace media {
-
-CdmFactory::CdmFactory() {}
-
-CdmFactory::~CdmFactory() {}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/cdm_factory.h b/src/cobalt/media/base/cdm_factory.h
deleted file mode 100644
index 77925a4..0000000
--- a/src/cobalt/media/base/cdm_factory.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_CDM_FACTORY_H_
-#define COBALT_MEDIA_BASE_CDM_FACTORY_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/media_keys.h"
-
-class GURL;
-
-namespace cobalt {
-namespace media {
-
-// Callback used when CDM is created. |error_message| only used if
-// MediaKeys is null (i.e. CDM can't be created).
-using CdmCreatedCB = base::Callback<void(const scoped_refptr<MediaKeys>&,
-                                         const std::string& error_message)>;
-
-struct CdmConfig;
-
-class MEDIA_EXPORT CdmFactory {
- public:
-  CdmFactory();
-  virtual ~CdmFactory();
-
-  // Creates a CDM for |key_system| and returns it through |cdm_created_cb|
-  // asynchronously.
-  virtual void Create(
-      const std::string& key_system, const GURL& security_origin,
-      const CdmConfig& cdm_config, const SessionMessageCB& session_message_cb,
-      const SessionClosedCB& session_closed_cb,
-      const SessionKeysChangeCB& session_keys_change_cb,
-      const SessionExpirationUpdateCB& session_expiration_update_cb,
-      const CdmCreatedCB& cdm_created_cb) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CdmFactory);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_CDM_FACTORY_H_
diff --git a/src/cobalt/media/base/cdm_initialized_promise.cc b/src/cobalt/media/base/cdm_initialized_promise.cc
deleted file mode 100644
index bb1775f..0000000
--- a/src/cobalt/media/base/cdm_initialized_promise.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/cdm_initialized_promise.h"
-
-namespace cobalt {
-namespace media {
-
-CdmInitializedPromise::CdmInitializedPromise(
-    const CdmCreatedCB& cdm_created_cb, const scoped_refptr<MediaKeys>& cdm)
-    : cdm_created_cb_(cdm_created_cb), cdm_(cdm) {}
-
-CdmInitializedPromise::~CdmInitializedPromise() {}
-
-void CdmInitializedPromise::resolve() {
-  MarkPromiseSettled();
-  cdm_created_cb_.Run(cdm_, "");
-}
-
-void CdmInitializedPromise::reject(MediaKeys::Exception exception_code,
-                                   uint32_t system_code,
-                                   const std::string& error_message) {
-  MarkPromiseSettled();
-  cdm_created_cb_.Run(NULL, error_message);
-  // Usually after this |this| (and the |cdm_| within it) will be destroyed.
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/cdm_initialized_promise.h b/src/cobalt/media/base/cdm_initialized_promise.h
deleted file mode 100644
index 360c2f2..0000000
--- a/src/cobalt/media/base/cdm_initialized_promise.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_CDM_INITIALIZED_PROMISE_H_
-#define COBALT_MEDIA_BASE_CDM_INITIALIZED_PROMISE_H_
-
-#include <string>
-
-#include "base/memory/ref_counted.h"
-#include "cobalt/media/base/cdm_factory.h"
-#include "cobalt/media/base/cdm_promise.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/media_keys.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-// Promise to be resolved when the CDM is initialized. It owns the MediaKeys
-// object until the initialization completes, which it then passes to
-// |cdm_created_cb|.
-class MEDIA_EXPORT CdmInitializedPromise : public SimpleCdmPromise {
- public:
-  CdmInitializedPromise(const CdmCreatedCB& cdm_created_cb,
-                        const scoped_refptr<MediaKeys>& cdm);
-  ~CdmInitializedPromise() OVERRIDE;
-
-  // SimpleCdmPromise implementation.
-  void resolve() OVERRIDE;
-  void reject(MediaKeys::Exception exception_code, uint32_t system_code,
-              const std::string& error_message) OVERRIDE;
-
- private:
-  CdmCreatedCB cdm_created_cb_;
-
-  // Holds a ref-count of the CDM.
-  scoped_refptr<MediaKeys> cdm_;
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_CDM_INITIALIZED_PROMISE_H_
diff --git a/src/cobalt/media/base/cdm_key_information.cc b/src/cobalt/media/base/cdm_key_information.cc
deleted file mode 100644
index f4ecd5b..0000000
--- a/src/cobalt/media/base/cdm_key_information.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/stl_util.h"
-#include "cobalt/media/base/cdm_key_information.h"
-
-namespace cobalt {
-namespace media {
-
-CdmKeyInformation::CdmKeyInformation()
-    : status(INTERNAL_ERROR), system_code(0) {}
-
-CdmKeyInformation::CdmKeyInformation(const std::vector<uint8_t>& key_id,
-                                     KeyStatus status, uint32_t system_code)
-    : key_id(key_id), status(status), system_code(system_code) {}
-
-CdmKeyInformation::CdmKeyInformation(const std::string& key_id,
-                                     KeyStatus status, uint32_t system_code)
-    : CdmKeyInformation(reinterpret_cast<const uint8_t*>(key_id.data()),
-                        key_id.size(), status, system_code) {}
-
-CdmKeyInformation::CdmKeyInformation(const uint8_t* key_id_data,
-                                     size_t key_id_length, KeyStatus status,
-                                     uint32_t system_code)
-    : key_id(key_id_data, key_id_data + key_id_length),
-      status(status),
-      system_code(system_code) {}
-
-CdmKeyInformation::CdmKeyInformation(const CdmKeyInformation& other) = default;
-
-CdmKeyInformation::~CdmKeyInformation() {}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/cdm_key_information.h b/src/cobalt/media/base/cdm_key_information.h
deleted file mode 100644
index f150549..0000000
--- a/src/cobalt/media/base/cdm_key_information.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_CDM_KEY_INFORMATION_H_
-#define COBALT_MEDIA_BASE_CDM_KEY_INFORMATION_H_
-
-#include <string>
-#include <vector>
-
-#include "cobalt/media/base/media_export.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-struct MEDIA_EXPORT CdmKeyInformation {
-  enum KeyStatus {
-    USABLE = 0,
-    INTERNAL_ERROR = 1,
-    EXPIRED = 2,
-    OUTPUT_RESTRICTED = 3,
-    OUTPUT_DOWNSCALED = 4,
-    KEY_STATUS_PENDING = 5,
-    RELEASED = 6,
-    KEY_STATUS_MAX = RELEASED
-  };
-
-  // Default constructor needed for passing this type through IPC. Regular
-  // code should use one of the other constructors.
-  CdmKeyInformation();
-  CdmKeyInformation(const std::vector<uint8_t>& key_id, KeyStatus status,
-                    uint32_t system_code);
-  CdmKeyInformation(const std::string& key_id, KeyStatus status,
-                    uint32_t system_code);
-  CdmKeyInformation(const uint8_t* key_id_data, size_t key_id_length,
-                    KeyStatus status, uint32_t system_code);
-  CdmKeyInformation(const CdmKeyInformation& other);
-  ~CdmKeyInformation();
-
-  std::vector<uint8_t> key_id;
-  KeyStatus status;
-  uint32_t system_code;
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_CDM_KEY_INFORMATION_H_
diff --git a/src/cobalt/media/base/cdm_promise.cc b/src/cobalt/media/base/cdm_promise.cc
deleted file mode 100644
index 1048e63..0000000
--- a/src/cobalt/media/base/cdm_promise.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/cdm_promise.h"
-
-namespace cobalt {
-namespace media {
-
-CdmPromise::CdmPromise() {}
-
-CdmPromise::~CdmPromise() {}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/cdm_promise.h b/src/cobalt/media/base/cdm_promise.h
deleted file mode 100644
index 9ab3ff4..0000000
--- a/src/cobalt/media/base/cdm_promise.h
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_CDM_PROMISE_H_
-#define COBALT_MEDIA_BASE_CDM_PROMISE_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/media_keys.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-// Interface for promises being resolved/rejected in response to various
-// session actions. These may be called synchronously or asynchronously.
-// The promise must be resolved or rejected exactly once. It is expected that
-// the caller free the promise once it is resolved/rejected.
-
-// These classes are almost generic, except for the parameters to reject(). If
-// a generic class for promises is available, this could be changed to use the
-// generic class as long as the parameters to reject() can be set appropriately.
-
-// The base class only has a reject() method and GetResolveParameterType() that
-// indicates the type of CdmPromiseTemplate. CdmPromiseTemplate<T> adds the
-// resolve(T) method that is dependent on the type of promise. This base class
-// is specified so that the promises can be easily saved before passing across
-// the pepper interface.
-class MEDIA_EXPORT CdmPromise {
- public:
-  enum ResolveParameterType {
-    VOID_TYPE,
-    INT_TYPE,
-    STRING_TYPE,
-    KEY_IDS_VECTOR_TYPE
-  };
-
-  CdmPromise();
-  virtual ~CdmPromise();
-
-  // Used to indicate that the operation failed. |exception_code| must be
-  // specified. |system_code| is a Key System-specific value for the error
-  // that occurred, or 0 if there is no associated status code or such status
-  // codes are not supported by the Key System. |error_message| is optional.
-  virtual void reject(MediaKeys::Exception exception_code, uint32_t system_code,
-                      const std::string& error_message) = 0;
-
-  // Used to determine the template type of CdmPromiseTemplate<T> so that
-  // saved CdmPromise objects can be cast to the correct templated version.
-  virtual ResolveParameterType GetResolveParameterType() const = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CdmPromise);
-};
-
-// For some reason the Windows compiler is not happy with the implementation
-// of CdmPromiseTemplate being in the .cc file, so moving it here.
-template <typename... T>
-struct CdmPromiseTraits {};
-
-template <>
-struct CdmPromiseTraits<> {
-  static const CdmPromise::ResolveParameterType kType = CdmPromise::VOID_TYPE;
-};
-
-template <>
-struct CdmPromiseTraits<int> {
-  static const CdmPromise::ResolveParameterType kType = CdmPromise::INT_TYPE;
-};
-
-template <>
-struct CdmPromiseTraits<std::string> {
-  static const CdmPromise::ResolveParameterType kType = CdmPromise::STRING_TYPE;
-};
-
-// This class adds the resolve(T) method. This class is still an interface, and
-// is used as the type of promise that gets passed around.
-template <typename... T>
-class MEDIA_EXPORT CdmPromiseTemplate : public CdmPromise {
- public:
-  CdmPromiseTemplate() : is_settled_(false) {}
-
-  virtual ~CdmPromiseTemplate() { DCHECK(is_settled_); }
-
-  virtual void resolve(const T&... result) = 0;
-
-  // CdmPromise implementation.
-  virtual void reject(MediaKeys::Exception exception_code, uint32_t system_code,
-                      const std::string& error_message) = 0;
-
-  ResolveParameterType GetResolveParameterType() const override {
-    return CdmPromiseTraits<T...>::kType;
-  }
-
- protected:
-  bool IsPromiseSettled() const { return is_settled_; }
-
-  // All implementations must call this method in resolve() and reject() methods
-  // to indicate that the promise has been settled.
-  void MarkPromiseSettled() {
-    // Promise can only be settled once.
-    DCHECK(!is_settled_);
-    is_settled_ = true;
-  }
-
-  // Must be called by the concrete destructor if !IsPromiseSettled().
-  // Note: We can't call reject() in ~CdmPromise() because reject() is virtual.
-  void RejectPromiseOnDestruction() {
-    DCHECK(!is_settled_);
-    std::string message =
-        "Unfulfilled promise rejected automatically during destruction.";
-    DVLOG(1) << message;
-    reject(MediaKeys::INVALID_STATE_ERROR, 0, message);
-    DCHECK(is_settled_);
-  }
-
- private:
-  // Keep track of whether the promise has been resolved or rejected yet.
-  bool is_settled_;
-
-  DISALLOW_COPY_AND_ASSIGN(CdmPromiseTemplate);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_CDM_PROMISE_H_
diff --git a/src/cobalt/media/base/cdm_promise_adapter.cc b/src/cobalt/media/base/cdm_promise_adapter.cc
deleted file mode 100644
index 88db68e..0000000
--- a/src/cobalt/media/base/cdm_promise_adapter.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/cdm_promise_adapter.h"
-
-#include <utility>
-
-#include "cobalt/media/base/media_keys.h"
-
-namespace cobalt {
-namespace media {
-
-CdmPromiseAdapter::CdmPromiseAdapter() : next_promise_id_(1) {}
-
-CdmPromiseAdapter::~CdmPromiseAdapter() {
-  DCHECK(promises_.empty());
-  DCHECK(thread_checker_.CalledOnValidThread());
-  Clear();
-}
-
-uint32_t CdmPromiseAdapter::SavePromise(std::unique_ptr<CdmPromise> promise) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  uint32_t promise_id = next_promise_id_++;
-  promises_.add(promise_id, std::move(promise));
-  return promise_id;
-}
-
-template <typename... T>
-void CdmPromiseAdapter::ResolvePromise(uint32_t promise_id,
-                                       const T&... result) {
-  std::unique_ptr<CdmPromise> promise = TakePromise(promise_id);
-  if (!promise) {
-    NOTREACHED() << "Promise not found for " << promise_id;
-    return;
-  }
-
-  // Sanity check the type before we do static_cast.
-  CdmPromise::ResolveParameterType type = promise->GetResolveParameterType();
-  CdmPromise::ResolveParameterType expected = CdmPromiseTraits<T...>::kType;
-  if (type != expected) {
-    NOTREACHED() << "Promise type mismatch: " << type << " vs " << expected;
-    return;
-  }
-
-  static_cast<CdmPromiseTemplate<T...>*>(promise.get())->resolve(result...);
-}
-
-void CdmPromiseAdapter::RejectPromise(uint32_t promise_id,
-                                      MediaKeys::Exception exception_code,
-                                      uint32_t system_code,
-                                      const std::string& error_message) {
-  std::unique_ptr<CdmPromise> promise = TakePromise(promise_id);
-  if (!promise) {
-    NOTREACHED() << "No promise found for promise_id " << promise_id;
-    return;
-  }
-
-  promise->reject(exception_code, system_code, error_message);
-}
-
-void CdmPromiseAdapter::Clear() {
-  // Reject all outstanding promises.
-  DCHECK(thread_checker_.CalledOnValidThread());
-  for (auto& promise : promises_)
-    promise.second->reject(MediaKeys::UNKNOWN_ERROR, 0, "Operation aborted.");
-  promises_.clear();
-}
-
-std::unique_ptr<CdmPromise> CdmPromiseAdapter::TakePromise(
-    uint32_t promise_id) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  PromiseMap::iterator it = promises_.find(promise_id);
-  if (it == promises_.end()) return NULL;
-  return promises_.take_and_erase(it);
-}
-
-// Explicit instantiation of function templates.
-template MEDIA_EXPORT void CdmPromiseAdapter::ResolvePromise(uint32_t);
-template MEDIA_EXPORT void CdmPromiseAdapter::ResolvePromise(
-    uint32_t, const std::string&);
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/cdm_promise_adapter.h b/src/cobalt/media/base/cdm_promise_adapter.h
deleted file mode 100644
index a7247e2..0000000
--- a/src/cobalt/media/base/cdm_promise_adapter.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_CDM_PROMISE_ADAPTER_H_
-#define COBALT_MEDIA_BASE_CDM_PROMISE_ADAPTER_H_
-
-#include <memory>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/scoped_ptr_hash_map.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/media/base/cdm_promise.h"
-#include "cobalt/media/base/media_export.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-// Helps convert CdmPromises to an integer identifier and vice versa. The
-// integer identifier is needed where we cannot pass CdmPromises through, such
-// as PPAPI, IPC and JNI.
-class MEDIA_EXPORT CdmPromiseAdapter {
- public:
-  CdmPromiseAdapter();
-  ~CdmPromiseAdapter();
-
-  // Takes ownership of |promise| and returns an integer promise ID.
-  uint32_t SavePromise(std::unique_ptr<media::CdmPromise> promise);
-
-  // Takes the promise for |promise_id|, sanity checks its |type|, and resolves
-  // it with |result|.
-  template <typename... T>
-  void ResolvePromise(uint32_t promise_id, const T&... result);
-
-  // Takes the promise for |promise_id| and rejects it with |exception_code|,
-  // |system_code| and |error_message|.
-  void RejectPromise(uint32_t promise_id, MediaKeys::Exception exception_code,
-                     uint32_t system_code, const std::string& error_message);
-
-  // Rejects and clears all |promises_|.
-  void Clear();
-
- private:
-  // A map between promise IDs and CdmPromises. It owns the CdmPromises.
-  typedef base::ScopedPtrHashMap<uint32_t, std::unique_ptr<CdmPromise>>
-      PromiseMap;
-
-  // Finds, takes the ownership of and returns the promise for |promise_id|.
-  // Returns null if no promise can be found.
-  std::unique_ptr<CdmPromise> TakePromise(uint32_t promise_id);
-
-  uint32_t next_promise_id_;
-  PromiseMap promises_;
-
-  base::ThreadChecker thread_checker_;
-  DISALLOW_COPY_AND_ASSIGN(CdmPromiseAdapter);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_CDM_PROMISE_ADAPTER_H_
diff --git a/src/cobalt/media/base/channel_mixing_matrix.cc b/src/cobalt/media/base/channel_mixing_matrix.cc
deleted file mode 100644
index fb07184..0000000
--- a/src/cobalt/media/base/channel_mixing_matrix.cc
+++ /dev/null
@@ -1,301 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// MSVC++ requires this to be set before any other includes to get M_SQRT1_2.
-#define _USE_MATH_DEFINES
-
-#include "cobalt/media/base/channel_mixing_matrix.h"
-
-#include <algorithm>
-#include <cmath>
-
-#include "base/logging.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-// Default scale factor for mixing two channels together.  We use a different
-// value for stereo -> mono and mono -> stereo mixes.
-static const float kEqualPowerScale = static_cast<float>(M_SQRT1_2);
-
-static void ValidateLayout(ChannelLayout layout) {
-  CHECK_NE(layout, CHANNEL_LAYOUT_NONE);
-  CHECK_LE(layout, CHANNEL_LAYOUT_MAX);
-  CHECK_NE(layout, CHANNEL_LAYOUT_UNSUPPORTED);
-  CHECK_NE(layout, CHANNEL_LAYOUT_DISCRETE);
-  CHECK_NE(layout, CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC);
-
-  // Verify there's at least one channel.  Should always be true here by virtue
-  // of not being one of the invalid layouts, but lets double check to be sure.
-  int channel_count = ChannelLayoutToChannelCount(layout);
-  DCHECK_GT(channel_count, 0);
-
-  // If we have more than one channel, verify a symmetric layout for sanity.
-  // The unit test will verify all possible layouts, so this can be a DCHECK.
-  // Symmetry allows simplifying the matrix building code by allowing us to
-  // assume that if one channel of a pair exists, the other will too.
-  if (channel_count > 1) {
-    // Assert that LEFT exists if and only if RIGHT exists, and so on.
-    DCHECK_EQ(ChannelOrder(layout, LEFT) >= 0,
-              ChannelOrder(layout, RIGHT) >= 0);
-    DCHECK_EQ(ChannelOrder(layout, SIDE_LEFT) >= 0,
-              ChannelOrder(layout, SIDE_RIGHT) >= 0);
-    DCHECK_EQ(ChannelOrder(layout, BACK_LEFT) >= 0,
-              ChannelOrder(layout, BACK_RIGHT) >= 0);
-    DCHECK_EQ(ChannelOrder(layout, LEFT_OF_CENTER) >= 0,
-              ChannelOrder(layout, RIGHT_OF_CENTER) >= 0);
-  } else {
-    DCHECK_EQ(layout, CHANNEL_LAYOUT_MONO);
-  }
-}
-
-ChannelMixingMatrix::ChannelMixingMatrix(ChannelLayout input_layout,
-                                         int input_channels,
-                                         ChannelLayout output_layout,
-                                         int output_channels)
-    : input_layout_(input_layout),
-      input_channels_(input_channels),
-      output_layout_(output_layout),
-      output_channels_(output_channels) {
-  // Stereo down mix should never be the output layout.
-  CHECK_NE(output_layout, CHANNEL_LAYOUT_STEREO_DOWNMIX);
-
-  // Verify that the layouts are supported
-  if (input_layout != CHANNEL_LAYOUT_DISCRETE) ValidateLayout(input_layout);
-  if (output_layout != CHANNEL_LAYOUT_DISCRETE) ValidateLayout(output_layout);
-
-  // Special case for 5.0, 5.1 with back channels when upmixed to 7.0, 7.1,
-  // which should map the back LR to side LR.
-  if (input_layout_ == CHANNEL_LAYOUT_5_0_BACK &&
-      output_layout_ == CHANNEL_LAYOUT_7_0) {
-    input_layout_ = CHANNEL_LAYOUT_5_0;
-  } else if (input_layout_ == CHANNEL_LAYOUT_5_1_BACK &&
-             output_layout_ == CHANNEL_LAYOUT_7_1) {
-    input_layout_ = CHANNEL_LAYOUT_5_1;
-  }
-}
-
-ChannelMixingMatrix::~ChannelMixingMatrix() {}
-
-bool ChannelMixingMatrix::CreateTransformationMatrix(
-    std::vector<std::vector<float>>* matrix) {
-  matrix_ = matrix;
-
-  // Size out the initial matrix.
-  matrix_->reserve(output_channels_);
-  for (int output_ch = 0; output_ch < output_channels_; ++output_ch)
-    matrix_->push_back(std::vector<float>(input_channels_, 0));
-
-  // First check for discrete case.
-  if (input_layout_ == CHANNEL_LAYOUT_DISCRETE ||
-      output_layout_ == CHANNEL_LAYOUT_DISCRETE) {
-    // If the number of input channels is more than output channels, then
-    // copy as many as we can then drop the remaining input channels.
-    // If the number of input channels is less than output channels, then
-    // copy them all, then zero out the remaining output channels.
-    int passthrough_channels = std::min(input_channels_, output_channels_);
-    for (int i = 0; i < passthrough_channels; ++i) (*matrix_)[i][i] = 1;
-
-    return true;
-  }
-
-  // Route matching channels and figure out which ones aren't accounted for.
-  for (Channels ch = LEFT; ch < CHANNELS_MAX + 1;
-       ch = static_cast<Channels>(ch + 1)) {
-    int input_ch_index = ChannelOrder(input_layout_, ch);
-    if (input_ch_index < 0) continue;
-
-    int output_ch_index = ChannelOrder(output_layout_, ch);
-    if (output_ch_index < 0) {
-      unaccounted_inputs_.push_back(ch);
-      continue;
-    }
-
-    DCHECK_LT(static_cast<size_t>(output_ch_index), matrix_->size());
-    DCHECK_LT(static_cast<size_t>(input_ch_index),
-              (*matrix_)[output_ch_index].size());
-    (*matrix_)[output_ch_index][input_ch_index] = 1;
-  }
-
-  // If all input channels are accounted for, there's nothing left to do.
-  if (unaccounted_inputs_.empty()) {
-    // Since all output channels map directly to inputs we can optimize.
-    return true;
-  }
-
-  // Mix front LR into center.
-  if (IsUnaccounted(LEFT)) {
-    // When down mixing to mono from stereo, we need to be careful of full scale
-    // stereo mixes.  Scaling by 1 / sqrt(2) here will likely lead to clipping
-    // so we use 1 / 2 instead.
-    float scale =
-        (output_layout_ == CHANNEL_LAYOUT_MONO && input_channels_ == 2)
-            ? 0.5
-            : kEqualPowerScale;
-    Mix(LEFT, CENTER, scale);
-    Mix(RIGHT, CENTER, scale);
-  }
-
-  // Mix center into front LR.
-  if (IsUnaccounted(CENTER)) {
-    // When up mixing from mono, just do a copy to front LR.
-    float scale = (input_layout_ == CHANNEL_LAYOUT_MONO) ? 1 : kEqualPowerScale;
-    MixWithoutAccounting(CENTER, LEFT, scale);
-    Mix(CENTER, RIGHT, scale);
-  }
-
-  // Mix back LR into: side LR || back center || front LR || front center.
-  if (IsUnaccounted(BACK_LEFT)) {
-    if (HasOutputChannel(SIDE_LEFT)) {
-      // If the input has side LR, mix back LR into side LR, but instead if the
-      // input doesn't have side LR (but output does) copy back LR to side LR.
-      float scale = HasInputChannel(SIDE_LEFT) ? kEqualPowerScale : 1;
-      Mix(BACK_LEFT, SIDE_LEFT, scale);
-      Mix(BACK_RIGHT, SIDE_RIGHT, scale);
-    } else if (HasOutputChannel(BACK_CENTER)) {
-      // Mix back LR into back center.
-      Mix(BACK_LEFT, BACK_CENTER, kEqualPowerScale);
-      Mix(BACK_RIGHT, BACK_CENTER, kEqualPowerScale);
-    } else if (output_layout_ > CHANNEL_LAYOUT_MONO) {
-      // Mix back LR into front LR.
-      Mix(BACK_LEFT, LEFT, kEqualPowerScale);
-      Mix(BACK_RIGHT, RIGHT, kEqualPowerScale);
-    } else {
-      // Mix back LR into front center.
-      Mix(BACK_LEFT, CENTER, kEqualPowerScale);
-      Mix(BACK_RIGHT, CENTER, kEqualPowerScale);
-    }
-  }
-
-  // Mix side LR into: back LR || back center || front LR || front center.
-  if (IsUnaccounted(SIDE_LEFT)) {
-    if (HasOutputChannel(BACK_LEFT)) {
-      // If the input has back LR, mix side LR into back LR, but instead if the
-      // input doesn't have back LR (but output does) copy side LR to back LR.
-      float scale = HasInputChannel(BACK_LEFT) ? kEqualPowerScale : 1;
-      Mix(SIDE_LEFT, BACK_LEFT, scale);
-      Mix(SIDE_RIGHT, BACK_RIGHT, scale);
-    } else if (HasOutputChannel(BACK_CENTER)) {
-      // Mix side LR into back center.
-      Mix(SIDE_LEFT, BACK_CENTER, kEqualPowerScale);
-      Mix(SIDE_RIGHT, BACK_CENTER, kEqualPowerScale);
-    } else if (output_layout_ > CHANNEL_LAYOUT_MONO) {
-      // Mix side LR into front LR.
-      Mix(SIDE_LEFT, LEFT, kEqualPowerScale);
-      Mix(SIDE_RIGHT, RIGHT, kEqualPowerScale);
-    } else {
-      // Mix side LR into front center.
-      Mix(SIDE_LEFT, CENTER, kEqualPowerScale);
-      Mix(SIDE_RIGHT, CENTER, kEqualPowerScale);
-    }
-  }
-
-  // Mix back center into: back LR || side LR || front LR || front center.
-  if (IsUnaccounted(BACK_CENTER)) {
-    if (HasOutputChannel(BACK_LEFT)) {
-      // Mix back center into back LR.
-      MixWithoutAccounting(BACK_CENTER, BACK_LEFT, kEqualPowerScale);
-      Mix(BACK_CENTER, BACK_RIGHT, kEqualPowerScale);
-    } else if (HasOutputChannel(SIDE_LEFT)) {
-      // Mix back center into side LR.
-      MixWithoutAccounting(BACK_CENTER, SIDE_LEFT, kEqualPowerScale);
-      Mix(BACK_CENTER, SIDE_RIGHT, kEqualPowerScale);
-    } else if (output_layout_ > CHANNEL_LAYOUT_MONO) {
-      // Mix back center into front LR.
-      // TODO(dalecurtis): Not sure about these values?
-      MixWithoutAccounting(BACK_CENTER, LEFT, kEqualPowerScale);
-      Mix(BACK_CENTER, RIGHT, kEqualPowerScale);
-    } else {
-      // Mix back center into front center.
-      // TODO(dalecurtis): Not sure about these values?
-      Mix(BACK_CENTER, CENTER, kEqualPowerScale);
-    }
-  }
-
-  // Mix LR of center into: front LR || front center.
-  if (IsUnaccounted(LEFT_OF_CENTER)) {
-    if (HasOutputChannel(LEFT)) {
-      // Mix LR of center into front LR.
-      Mix(LEFT_OF_CENTER, LEFT, kEqualPowerScale);
-      Mix(RIGHT_OF_CENTER, RIGHT, kEqualPowerScale);
-    } else {
-      // Mix LR of center into front center.
-      Mix(LEFT_OF_CENTER, CENTER, kEqualPowerScale);
-      Mix(RIGHT_OF_CENTER, CENTER, kEqualPowerScale);
-    }
-  }
-
-  // Mix LFE into: front center || front LR.
-  if (IsUnaccounted(LFE)) {
-    if (!HasOutputChannel(CENTER)) {
-      // Mix LFE into front LR.
-      MixWithoutAccounting(LFE, LEFT, kEqualPowerScale);
-      Mix(LFE, RIGHT, kEqualPowerScale);
-    } else {
-      // Mix LFE into front center.
-      Mix(LFE, CENTER, kEqualPowerScale);
-    }
-  }
-
-  // All channels should now be accounted for.
-  DCHECK(unaccounted_inputs_.empty());
-
-  // See if the output |matrix_| is simply a remapping matrix.  If each input
-  // channel maps to a single output channel we can simply remap.  Doing this
-  // programmatically is less fragile than logic checks on channel mappings.
-  for (int output_ch = 0; output_ch < output_channels_; ++output_ch) {
-    int input_mappings = 0;
-    for (int input_ch = 0; input_ch < input_channels_; ++input_ch) {
-      // We can only remap if each row contains a single scale of 1.  I.e., each
-      // output channel is mapped from a single unscaled input channel.
-      if ((*matrix_)[output_ch][input_ch] != 1 || ++input_mappings > 1)
-        return false;
-    }
-  }
-
-  // If we've gotten here, |matrix_| is simply a remapping.
-  return true;
-}
-
-void ChannelMixingMatrix::AccountFor(Channels ch) {
-  unaccounted_inputs_.erase(
-      std::find(unaccounted_inputs_.begin(), unaccounted_inputs_.end(), ch));
-}
-
-bool ChannelMixingMatrix::IsUnaccounted(Channels ch) const {
-  return std::find(unaccounted_inputs_.begin(), unaccounted_inputs_.end(),
-                   ch) != unaccounted_inputs_.end();
-}
-
-bool ChannelMixingMatrix::HasInputChannel(Channels ch) const {
-  return ChannelOrder(input_layout_, ch) >= 0;
-}
-
-bool ChannelMixingMatrix::HasOutputChannel(Channels ch) const {
-  return ChannelOrder(output_layout_, ch) >= 0;
-}
-
-void ChannelMixingMatrix::Mix(Channels input_ch, Channels output_ch,
-                              float scale) {
-  MixWithoutAccounting(input_ch, output_ch, scale);
-  AccountFor(input_ch);
-}
-
-void ChannelMixingMatrix::MixWithoutAccounting(Channels input_ch,
-                                               Channels output_ch,
-                                               float scale) {
-  int input_ch_index = ChannelOrder(input_layout_, input_ch);
-  int output_ch_index = ChannelOrder(output_layout_, output_ch);
-
-  DCHECK(IsUnaccounted(input_ch));
-  DCHECK_GE(input_ch_index, 0);
-  DCHECK_GE(output_ch_index, 0);
-
-  DCHECK_EQ((*matrix_)[output_ch_index][input_ch_index], 0);
-  (*matrix_)[output_ch_index][input_ch_index] = scale;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/channel_mixing_matrix.h b/src/cobalt/media/base/channel_mixing_matrix.h
deleted file mode 100644
index 7286243..0000000
--- a/src/cobalt/media/base/channel_mixing_matrix.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_CHANNEL_MIXING_MATRIX_H_
-#define COBALT_MEDIA_BASE_CHANNEL_MIXING_MATRIX_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "cobalt/media/base/channel_layout.h"
-#include "cobalt/media/base/media_export.h"
-
-namespace cobalt {
-namespace media {
-
-class MEDIA_EXPORT ChannelMixingMatrix {
- public:
-  ChannelMixingMatrix(ChannelLayout input_layout, int input_channels,
-                      ChannelLayout output_layout, int output_channels);
-
-  ~ChannelMixingMatrix();
-
-  // Create the transformation matrix of input channels to output channels.
-  // Updates the empty matrix with the transformation, and returns true
-  // if the transformation is just a remapping of channels (no mixing).
-  bool CreateTransformationMatrix(std::vector<std::vector<float>>* matrix);
-
- private:
-  // Result transformation of input channels to output channels
-  std::vector<std::vector<float>>* matrix_;
-
-  // Input and output channel layout provided during construction.
-  ChannelLayout input_layout_;
-  int input_channels_;
-  ChannelLayout output_layout_;
-  int output_channels_;
-
-  // Helper variable for tracking which inputs are currently unaccounted,
-  // should be empty after construction completes.
-  std::vector<Channels> unaccounted_inputs_;
-
-  // Helper methods for managing unaccounted input channels.
-  void AccountFor(Channels ch);
-  bool IsUnaccounted(Channels ch) const;
-
-  // Helper methods for checking if |ch| exists in either |input_layout_| or
-  // |output_layout_| respectively.
-  bool HasInputChannel(Channels ch) const;
-  bool HasOutputChannel(Channels ch) const;
-
-  // Helper methods for updating |matrix_| with the proper value for
-  // mixing |input_ch| into |output_ch|.  MixWithoutAccounting() does not
-  // remove the channel from |unaccounted_inputs_|.
-  void Mix(Channels input_ch, Channels output_ch, float scale);
-  void MixWithoutAccounting(Channels input_ch, Channels output_ch, float scale);
-
-  DISALLOW_COPY_AND_ASSIGN(ChannelMixingMatrix);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_CHANNEL_MIXING_MATRIX_H_
diff --git a/src/cobalt/media/base/channel_mixing_matrix_unittest.cc b/src/cobalt/media/base/channel_mixing_matrix_unittest.cc
deleted file mode 100644
index 120319d..0000000
--- a/src/cobalt/media/base/channel_mixing_matrix_unittest.cc
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// MSVC++ requires this to be set before any other includes to get M_SQRT1_2.
-#define _USE_MATH_DEFINES
-
-#include "cobalt/media/base/channel_mixing_matrix.h"
-
-#include <cmath>
-
-#include "base/basictypes.h"
-#include "base/stringprintf.h"
-#include "starboard/types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cobalt {
-namespace media {
-
-// Test all possible layout conversions can be constructed and mixed.
-TEST(ChannelMixingMatrixTest, ConstructAllPossibleLayouts) {
-  for (ChannelLayout input_layout = CHANNEL_LAYOUT_MONO;
-       input_layout <= CHANNEL_LAYOUT_MAX;
-       input_layout = static_cast<ChannelLayout>(input_layout + 1)) {
-    for (ChannelLayout output_layout = CHANNEL_LAYOUT_MONO;
-         output_layout <= CHANNEL_LAYOUT_MAX;
-         output_layout = static_cast<ChannelLayout>(output_layout + 1)) {
-      // DISCRETE can't be tested here based on the current approach.
-      // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC is not mixable.
-      // Stereo down mix should never be the output layout.
-      if (input_layout == CHANNEL_LAYOUT_DISCRETE ||
-          input_layout == CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC ||
-          output_layout == CHANNEL_LAYOUT_DISCRETE ||
-          output_layout == CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC ||
-          output_layout == CHANNEL_LAYOUT_STEREO_DOWNMIX) {
-        continue;
-      }
-
-      SCOPED_TRACE(base::StringPrintf("Input Layout: %d, Output Layout: %d",
-                                      input_layout, output_layout));
-      ChannelMixingMatrix matrix_builder(
-          input_layout, ChannelLayoutToChannelCount(input_layout),
-          output_layout, ChannelLayoutToChannelCount(output_layout));
-      std::vector<std::vector<float>> matrix;
-      matrix_builder.CreateTransformationMatrix(&matrix);
-    }
-  }
-}
-
-// Verify channels are mixed and scaled correctly.
-TEST(ChannelMixingMatrixTest, StereoToMono) {
-  ChannelLayout input_layout = CHANNEL_LAYOUT_STEREO;
-  ChannelLayout output_layout = CHANNEL_LAYOUT_MONO;
-  ChannelMixingMatrix matrix_builder(
-      input_layout, ChannelLayoutToChannelCount(input_layout), output_layout,
-      ChannelLayoutToChannelCount(output_layout));
-  std::vector<std::vector<float>> matrix;
-  bool remapping = matrix_builder.CreateTransformationMatrix(&matrix);
-
-  //                      Input: stereo
-  //                      LEFT  RIGHT
-  // Output: mono CENTER  0.5   0.5
-  //
-  EXPECT_FALSE(remapping);
-  EXPECT_EQ(1u, matrix.size());
-  EXPECT_EQ(2u, matrix[0].size());
-  EXPECT_EQ(0.5f, matrix[0][0]);
-  EXPECT_EQ(0.5f, matrix[0][1]);
-}
-
-TEST(ChannelMixingMatrixTest, MonoToStereo) {
-  ChannelLayout input_layout = CHANNEL_LAYOUT_MONO;
-  ChannelLayout output_layout = CHANNEL_LAYOUT_STEREO;
-  ChannelMixingMatrix matrix_builder(
-      input_layout, ChannelLayoutToChannelCount(input_layout), output_layout,
-      ChannelLayoutToChannelCount(output_layout));
-  std::vector<std::vector<float>> matrix;
-  bool remapping = matrix_builder.CreateTransformationMatrix(&matrix);
-
-  //                       Input: mono
-  //                       CENTER
-  // Output: stereo LEFT   1
-  //                RIGHT  1
-  //
-  EXPECT_TRUE(remapping);
-  EXPECT_EQ(2u, matrix.size());
-  EXPECT_EQ(1u, matrix[0].size());
-  EXPECT_EQ(1.0f, matrix[0][0]);
-  EXPECT_EQ(1u, matrix[1].size());
-  EXPECT_EQ(1.0f, matrix[1][0]);
-}
-
-TEST(ChannelMixingMatrixTest, FiveOneToMono) {
-  ChannelLayout input_layout = CHANNEL_LAYOUT_5_1;
-  ChannelLayout output_layout = CHANNEL_LAYOUT_MONO;
-  ChannelMixingMatrix matrix_builder(
-      input_layout, ChannelLayoutToChannelCount(input_layout), output_layout,
-      ChannelLayoutToChannelCount(output_layout));
-  std::vector<std::vector<float>> matrix;
-  bool remapping = matrix_builder.CreateTransformationMatrix(&matrix);
-
-  // Note: 1/sqrt(2) is shown as 0.707.
-  //
-  //                      Input: 5.1
-  //                      LEFT   RIGHT  CENTER  LFE    SIDE_LEFT  SIDE_RIGHT
-  // Output: mono CENTER  0.707  0.707  1       0.707  0.707      0.707
-  //
-  EXPECT_FALSE(remapping);
-  EXPECT_EQ(1u, matrix.size());
-  EXPECT_EQ(6u, matrix[0].size());
-  EXPECT_FLOAT_EQ(static_cast<float>(M_SQRT1_2), matrix[0][0]);
-  EXPECT_FLOAT_EQ(static_cast<float>(M_SQRT1_2), matrix[0][1]);
-  // The center channel will be mixed at scale 1.
-  EXPECT_EQ(1.0f, matrix[0][2]);
-  EXPECT_FLOAT_EQ(static_cast<float>(M_SQRT1_2), matrix[0][3]);
-  EXPECT_FLOAT_EQ(static_cast<float>(M_SQRT1_2), matrix[0][4]);
-  EXPECT_FLOAT_EQ(static_cast<float>(M_SQRT1_2), matrix[0][5]);
-}
-
-TEST(ChannelMixingMatrixTest, DiscreteToDiscrete) {
-  const struct {
-    int input_channels;
-    int output_channels;
-  } test_case[] = {
-      {2, 2}, {2, 5}, {5, 2},
-  };
-
-  for (size_t n = 0; n < arraysize(test_case); n++) {
-    int input_channels = test_case[n].input_channels;
-    int output_channels = test_case[n].output_channels;
-    ChannelMixingMatrix matrix_builder(CHANNEL_LAYOUT_DISCRETE, input_channels,
-                                       CHANNEL_LAYOUT_DISCRETE,
-                                       output_channels);
-    std::vector<std::vector<float>> matrix;
-    bool remapping = matrix_builder.CreateTransformationMatrix(&matrix);
-    EXPECT_TRUE(remapping);
-    EXPECT_EQ(static_cast<size_t>(output_channels), matrix.size());
-    for (int i = 0; i < output_channels; i++) {
-      EXPECT_EQ(static_cast<size_t>(input_channels), matrix[i].size());
-      for (int j = 0; j < input_channels; j++) {
-        if (i == j) {
-          EXPECT_EQ(1.0f, matrix[i][j]);
-        } else {
-          EXPECT_EQ(0.0f, matrix[i][j]);
-        }
-      }
-    }
-  }
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/decode_status.cc b/src/cobalt/media/base/decode_status.cc
deleted file mode 100644
index 8acf646..0000000
--- a/src/cobalt/media/base/decode_status.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/decode_status.h"
-
-#include <ostream>
-
-namespace cobalt {
-namespace media {
-
-std::ostream& operator<<(std::ostream& os, const DecodeStatus& status) {
-  switch (status) {
-    case DecodeStatus::OK:
-      os << "DecodeStatus::OK";
-      break;
-    case DecodeStatus::ABORTED:
-      os << "DecodeStatus::ABORTED";
-      break;
-    case DecodeStatus::DECODE_ERROR:
-      os << "DecodeStatus::DECODE_ERROR";
-      break;
-  }
-  return os;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/decode_status.h b/src/cobalt/media/base/decode_status.h
deleted file mode 100644
index 7fb1338..0000000
--- a/src/cobalt/media/base/decode_status.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_DECODE_STATUS_H_
-#define COBALT_MEDIA_BASE_DECODE_STATUS_H_
-
-#include <iosfwd>
-
-#include "cobalt/media/base/media_export.h"
-
-namespace cobalt {
-namespace media {
-
-enum class DecodeStatus {
-  OK = 0,        // Everything went as planned.
-  ABORTED,       // Read aborted due to Reset() during pending read.
-  DECODE_ERROR,  // Decoder returned decode error. Note: Prefixed by DECODE_
-                 // since ERROR is a reserved name (special macro) on Windows.
-};
-
-// Helper function so that DecodeStatus can be printed easily.
-MEDIA_EXPORT std::ostream& operator<<(std::ostream& os,
-                                      const DecodeStatus& status);
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_DECODE_STATUS_H_
diff --git a/src/cobalt/media/base/decoder_factory.cc b/src/cobalt/media/base/decoder_factory.cc
deleted file mode 100644
index 71b0e38..0000000
--- a/src/cobalt/media/base/decoder_factory.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/decoder_factory.h"
-
-#include "base/single_thread_task_runner.h"
-
-namespace cobalt {
-namespace media {
-
-DecoderFactory::DecoderFactory() {}
-
-DecoderFactory::~DecoderFactory() {}
-
-void DecoderFactory::CreateAudioDecoders(
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    ScopedVector<AudioDecoder>* audio_decoders) {}
-
-void DecoderFactory::CreateVideoDecoders(
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    GpuVideoAcceleratorFactories* gpu_factories,
-    ScopedVector<VideoDecoder>* video_decoders) {}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/decoder_factory.h b/src/cobalt/media/base/decoder_factory.h
deleted file mode 100644
index 524005f..0000000
--- a/src/cobalt/media/base/decoder_factory.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_DECODER_FACTORY_H_
-#define COBALT_MEDIA_BASE_DECODER_FACTORY_H_
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_vector.h"
-#include "cobalt/media/base/media_export.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace cobalt {
-namespace media {
-
-class AudioDecoder;
-class GpuVideoAcceleratorFactories;
-class VideoDecoder;
-
-// A factory class for creating audio and video decoders.
-class MEDIA_EXPORT DecoderFactory {
- public:
-  DecoderFactory();
-  virtual ~DecoderFactory();
-
-  // Creates audio decoders and append them to the end of |audio_decoders|.
-  // Decoders are single-threaded, each decoder should run on |task_runner|.
-  virtual void CreateAudioDecoders(
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-      ScopedVector<AudioDecoder>* audio_decoders);
-
-  // Creates video decoders and append them to the end of |video_decoders|.
-  // Decoders are single-threaded, each decoder should run on |task_runner|.
-  virtual void CreateVideoDecoders(
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-      GpuVideoAcceleratorFactories* gpu_factories,
-      ScopedVector<VideoDecoder>* video_decoders);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(DecoderFactory);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_DECODER_FACTORY_H_
diff --git a/src/cobalt/media/base/eme_constants.h b/src/cobalt/media/base/eme_constants.h
index 556f707..8e3af74 100644
--- a/src/cobalt/media/base/eme_constants.h
+++ b/src/cobalt/media/base/eme_constants.h
@@ -15,9 +15,10 @@
 // http://w3c.github.io/encrypted-media/initdata-format-registry.html#registry
 enum EmeInitDataType {
   kEmeInitDataTypeUnknown,
-  kEmeInitDataTypeWebM,
   kEmeInitDataTypeCenc,
-  kEmeInitDataTypeKeyIds
+  kEmeInitDataTypeFairplay,
+  kEmeInitDataTypeKeyIds,
+  kEmeInitDataTypeWebM,
 };
 
 // Defines bitmask values that specify codecs used in Encrypted Media Extension
diff --git a/src/cobalt/media/base/fake_audio_render_callback.cc b/src/cobalt/media/base/fake_audio_render_callback.cc
deleted file mode 100644
index b3da077..0000000
--- a/src/cobalt/media/base/fake_audio_render_callback.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// MSVC++ requires this to be set before any other includes to get M_PI.
-#define _USE_MATH_DEFINES
-
-#include <cmath>
-
-#include "cobalt/media/base/fake_audio_render_callback.h"
-#include "starboard/memory.h"
-
-namespace cobalt {
-namespace media {
-
-FakeAudioRenderCallback::FakeAudioRenderCallback(double step)
-    : half_fill_(false),
-      step_(step),
-      last_frames_delayed_(-1),
-      last_channel_count_(-1),
-      volume_(1) {
-  reset();
-}
-
-FakeAudioRenderCallback::~FakeAudioRenderCallback() {}
-
-int FakeAudioRenderCallback::Render(AudioBus* audio_bus,
-                                    uint32_t frames_delayed,
-                                    uint32_t frames_skipped) {
-  return RenderInternal(audio_bus, frames_delayed, volume_);
-}
-
-double FakeAudioRenderCallback::ProvideInput(AudioBus* audio_bus,
-                                             uint32_t frames_delayed) {
-  // Volume should only be applied by the caller to ProvideInput, so don't bake
-  // it into the rendered audio.
-  RenderInternal(audio_bus, frames_delayed, 1.0);
-  return volume_;
-}
-
-int FakeAudioRenderCallback::RenderInternal(AudioBus* audio_bus,
-                                            uint32_t frames_delayed,
-                                            double volume) {
-  DCHECK_LE(frames_delayed, static_cast<uint32_t>(INT_MAX));
-  last_frames_delayed_ = static_cast<int>(frames_delayed);
-  last_channel_count_ = audio_bus->channels();
-
-  int number_of_frames = audio_bus->frames();
-  if (half_fill_) number_of_frames /= 2;
-
-  // Fill first channel with a sine wave.
-  for (int i = 0; i < number_of_frames; ++i)
-    audio_bus->channel(0)[i] = sin(2 * M_PI * (x_ + step_ * i)) * volume;
-  x_ += number_of_frames * step_;
-
-  // Copy first channel into the rest of the channels.
-  for (int i = 1; i < audio_bus->channels(); ++i) {
-    SbMemoryCopy(audio_bus->channel(i), audio_bus->channel(0),
-                 number_of_frames * sizeof(*audio_bus->channel(i)));
-  }
-
-  return number_of_frames;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/fake_audio_render_callback.h b/src/cobalt/media/base/fake_audio_render_callback.h
deleted file mode 100644
index 44ddb22..0000000
--- a/src/cobalt/media/base/fake_audio_render_callback.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_FAKE_AUDIO_RENDER_CALLBACK_H_
-#define COBALT_MEDIA_BASE_FAKE_AUDIO_RENDER_CALLBACK_H_
-
-#include "base/basictypes.h"
-#include "cobalt/media/base/audio_converter.h"
-#include "cobalt/media/base/audio_renderer_sink.h"
-#include "starboard/types.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace cobalt {
-namespace media {
-
-// Fake RenderCallback which will fill each request with a sine wave.  Sine
-// state is kept across callbacks.  State can be reset to default via reset().
-// Also provide an interface to AudioTransformInput.
-class FakeAudioRenderCallback : public AudioRendererSink::RenderCallback,
-                                public AudioConverter::InputCallback {
- public:
-  // The function used to fulfill Render() is f(x) = sin(2 * PI * x * |step|),
-  // where x = [|number_of_frames| * m, |number_of_frames| * (m + 1)] and m =
-  // the number of Render() calls fulfilled thus far.
-  explicit FakeAudioRenderCallback(double step);
-  ~FakeAudioRenderCallback() OVERRIDE;
-
-  // Renders a sine wave into the provided audio data buffer.  If |half_fill_|
-  // is set, will only fill half the buffer.
-  int Render(AudioBus* audio_bus, uint32_t frames_delayed,
-             uint32_t frames_skipped) OVERRIDE;
-  MOCK_METHOD0(OnRenderError, void());
-
-  // AudioTransform::ProvideAudioTransformInput implementation.
-  double ProvideInput(AudioBus* audio_bus, uint32_t frames_delayed) OVERRIDE;
-
-  // Toggles only filling half the requested amount during Render().
-  void set_half_fill(bool half_fill) { half_fill_ = half_fill; }
-
-  // Reset the sine state to initial value.
-  void reset() { x_ = 0; }
-
-  // Returns the last |frames_delayed| provided to Render() or -1 if
-  // no Render() call occurred.
-  int last_frames_delayed() const { return last_frames_delayed_; }
-
-  // Set volume information used by ProvideAudioTransformInput().
-  void set_volume(double volume) { volume_ = volume; }
-
-  int last_channel_count() const { return last_channel_count_; }
-
- private:
-  int RenderInternal(AudioBus* audio_bus, uint32_t frames_delayed,
-                     double volume);
-
-  bool half_fill_;
-  double x_;
-  double step_;
-  int last_frames_delayed_;
-  int last_channel_count_;
-  double volume_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeAudioRenderCallback);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_FAKE_AUDIO_RENDER_CALLBACK_H_
diff --git a/src/cobalt/media/base/fake_audio_renderer_sink.cc b/src/cobalt/media/base/fake_audio_renderer_sink.cc
deleted file mode 100644
index 27aea01..0000000
--- a/src/cobalt/media/base/fake_audio_renderer_sink.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/fake_audio_renderer_sink.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-
-namespace cobalt {
-namespace media {
-
-FakeAudioRendererSink::FakeAudioRendererSink()
-    : FakeAudioRendererSink(
-          AudioParameters(AudioParameters::AUDIO_FAKE, CHANNEL_LAYOUT_STEREO,
-                          AudioParameters::kTelephoneSampleRate, 16, 1)) {}
-
-FakeAudioRendererSink::FakeAudioRendererSink(
-    const AudioParameters& hardware_params)
-    : state_(kUninitialized),
-      callback_(NULL),
-      output_device_info_(std::string(), OUTPUT_DEVICE_STATUS_OK,
-                          hardware_params) {}
-
-FakeAudioRendererSink::~FakeAudioRendererSink() { DCHECK(!callback_); }
-
-void FakeAudioRendererSink::Initialize(const AudioParameters& params,
-                                       RenderCallback* callback) {
-  DCHECK_EQ(state_, kUninitialized);
-  DCHECK(!callback_);
-  DCHECK(callback);
-
-  callback_ = callback;
-  ChangeState(kInitialized);
-}
-
-void FakeAudioRendererSink::Start() {
-  DCHECK_EQ(state_, kInitialized);
-  ChangeState(kStarted);
-}
-
-void FakeAudioRendererSink::Stop() {
-  callback_ = NULL;
-  ChangeState(kStopped);
-}
-
-void FakeAudioRendererSink::Pause() {
-  DCHECK(state_ == kStarted || state_ == kPlaying) << "state_ " << state_;
-  ChangeState(kPaused);
-}
-
-void FakeAudioRendererSink::Play() {
-  DCHECK(state_ == kStarted || state_ == kPaused) << "state_ " << state_;
-  DCHECK_EQ(state_, kPaused);
-  ChangeState(kPlaying);
-}
-
-bool FakeAudioRendererSink::SetVolume(double volume) { return true; }
-
-OutputDeviceInfo FakeAudioRendererSink::GetOutputDeviceInfo() {
-  return output_device_info_;
-}
-
-bool FakeAudioRendererSink::CurrentThreadIsRenderingThread() {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-bool FakeAudioRendererSink::Render(AudioBus* dest, uint32_t frames_delayed,
-                                   int* frames_written) {
-  if (state_ != kPlaying) return false;
-
-  *frames_written = callback_->Render(dest, frames_delayed, 0);
-  return true;
-}
-
-void FakeAudioRendererSink::OnRenderError() {
-  DCHECK_NE(state_, kUninitialized);
-  DCHECK_NE(state_, kStopped);
-
-  callback_->OnRenderError();
-}
-
-void FakeAudioRendererSink::ChangeState(State new_state) {
-  static const char* kStateNames[] = {"kUninitialized", "kInitialized",
-                                      "kStarted",       "kPaused",
-                                      "kPlaying",       "kStopped"};
-
-  DVLOG(1) << __FUNCTION__ << " : " << kStateNames[state_] << " -> "
-           << kStateNames[new_state];
-  state_ = new_state;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/fake_audio_renderer_sink.h b/src/cobalt/media/base/fake_audio_renderer_sink.h
deleted file mode 100644
index c55f3a6..0000000
--- a/src/cobalt/media/base/fake_audio_renderer_sink.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_FAKE_AUDIO_RENDERER_SINK_H_
-#define COBALT_MEDIA_BASE_FAKE_AUDIO_RENDERER_SINK_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "cobalt/media/base/audio_parameters.h"
-#include "cobalt/media/base/audio_renderer_sink.h"
-#include "cobalt/media/base/output_device_info.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-class FakeAudioRendererSink : public AudioRendererSink {
- public:
-  enum State {
-    kUninitialized,
-    kInitialized,
-    kStarted,
-    kPaused,
-    kPlaying,
-    kStopped
-  };
-
-  FakeAudioRendererSink();
-
-  explicit FakeAudioRendererSink(const AudioParameters& hardware_params);
-
-  void Initialize(const AudioParameters& params,
-                  RenderCallback* callback) OVERRIDE;
-  void Start() OVERRIDE;
-  void Stop() OVERRIDE;
-  void Pause() OVERRIDE;
-  void Play() OVERRIDE;
-  bool SetVolume(double volume) OVERRIDE;
-  OutputDeviceInfo GetOutputDeviceInfo() OVERRIDE;
-  bool CurrentThreadIsRenderingThread() OVERRIDE;
-
-  // Attempts to call Render() on the callback provided to
-  // Initialize() with |dest| and |frames_delayed|.
-  // Returns true and sets |frames_written| to the return value of the
-  // Render() call.
-  // Returns false if this object is in a state where calling Render()
-  // should not occur. (i.e., in the kPaused or kStopped state.) The
-  // value of |frames_written| is undefined if false is returned.
-  bool Render(AudioBus* dest, uint32_t frames_delayed, int* frames_written);
-  void OnRenderError();
-
-  State state() const { return state_; }
-
- protected:
-  ~FakeAudioRendererSink() OVERRIDE;
-
- private:
-  void ChangeState(State new_state);
-
-  State state_;
-  RenderCallback* callback_;
-  OutputDeviceInfo output_device_info_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeAudioRendererSink);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_FAKE_AUDIO_RENDERER_SINK_H_
diff --git a/src/cobalt/media/base/fake_media_resources.cc b/src/cobalt/media/base/fake_media_resources.cc
deleted file mode 100644
index 55d7ed8..0000000
--- a/src/cobalt/media/base/fake_media_resources.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/fake_media_resources.h"
-
-#include "base/utf_string_conversions.h"
-#include "cobalt/media/base/media_resources.h"
-
-namespace cobalt {
-namespace media {
-
-base::string16 FakeLocalizedStringProvider(MessageId message_id) {
-  if (message_id == DEFAULT_AUDIO_DEVICE_NAME)
-    return base::ASCIIToUTF16("Default");
-
-  return base::ASCIIToUTF16("FakeString");
-}
-
-void SetUpFakeMediaResources() {
-  SetLocalizedStringProvider(FakeLocalizedStringProvider);
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/fake_media_resources.h b/src/cobalt/media/base/fake_media_resources.h
deleted file mode 100644
index 4683995..0000000
--- a/src/cobalt/media/base/fake_media_resources.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_FAKE_MEDIA_RESOURCES_H_
-#define COBALT_MEDIA_BASE_FAKE_MEDIA_RESOURCES_H_
-
-namespace cobalt {
-namespace media {
-
-// Call if tests require non-empty resource strings.
-void SetUpFakeMediaResources();
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_FAKE_MEDIA_RESOURCES_H_
diff --git a/src/cobalt/media/base/fake_text_track_stream.cc b/src/cobalt/media/base/fake_text_track_stream.cc
deleted file mode 100644
index c9c7af1..0000000
--- a/src/cobalt/media/base/fake_text_track_stream.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/fake_text_track_stream.h"
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "cobalt/media/base/decoder_buffer.h"
-#include "cobalt/media/filters/webvtt_util.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-FakeTextTrackStream::FakeTextTrackStream()
-    : task_runner_(base::ThreadTaskRunnerHandle::Get()), stopping_(false) {}
-
-FakeTextTrackStream::~FakeTextTrackStream() { DCHECK(read_cb_.is_null()); }
-
-void FakeTextTrackStream::Read(const ReadCB& read_cb) {
-  DCHECK(!read_cb.is_null());
-  DCHECK(read_cb_.is_null());
-  OnRead();
-  read_cb_ = read_cb;
-
-  if (stopping_) {
-    task_runner_->PostTask(FROM_HERE,
-                           base::Bind(&FakeTextTrackStream::AbortPendingRead,
-                                      base::Unretained(this)));
-  }
-}
-
-DemuxerStream::Type FakeTextTrackStream::type() const {
-  return DemuxerStream::TEXT;
-}
-
-bool FakeTextTrackStream::SupportsConfigChanges() { return false; }
-
-VideoRotation FakeTextTrackStream::video_rotation() { return VIDEO_ROTATION_0; }
-
-bool FakeTextTrackStream::enabled() const { return true; }
-
-void FakeTextTrackStream::set_enabled(bool enabled, base::TimeDelta timestamp) {
-  NOTIMPLEMENTED();
-}
-
-void FakeTextTrackStream::SetStreamStatusChangeCB(
-    const StreamStatusChangeCB& cb) {
-  NOTIMPLEMENTED();
-}
-
-void FakeTextTrackStream::SatisfyPendingRead(const base::TimeDelta& start,
-                                             const base::TimeDelta& duration,
-                                             const std::string& id,
-                                             const std::string& content,
-                                             const std::string& settings) {
-  DCHECK(!read_cb_.is_null());
-
-  const uint8_t* const data_buf =
-      reinterpret_cast<const uint8_t*>(content.data());
-  const int data_len = static_cast<int>(content.size());
-
-  std::vector<uint8_t> side_data;
-  MakeSideData(id.begin(), id.end(), settings.begin(), settings.end(),
-               &side_data);
-
-  const uint8_t* const sd_buf = &side_data[0];
-  const int sd_len = static_cast<int>(side_data.size());
-
-  scoped_refptr<DecoderBuffer> buffer;
-  buffer = DecoderBuffer::CopyFrom(data_buf, data_len, sd_buf, sd_len);
-
-  buffer->set_timestamp(start);
-  buffer->set_duration(duration);
-
-  // Assume all fake text buffers are keyframes.
-  buffer->set_is_key_frame(true);
-
-  base::ResetAndReturn(&read_cb_).Run(kOk, buffer);
-}
-
-void FakeTextTrackStream::AbortPendingRead() {
-  DCHECK(!read_cb_.is_null());
-  base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
-}
-
-void FakeTextTrackStream::SendEosNotification() {
-  DCHECK(!read_cb_.is_null());
-  base::ResetAndReturn(&read_cb_).Run(kOk, DecoderBuffer::CreateEOSBuffer());
-}
-
-void FakeTextTrackStream::Stop() {
-  stopping_ = true;
-  if (!read_cb_.is_null()) AbortPendingRead();
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/fake_text_track_stream.h b/src/cobalt/media/base/fake_text_track_stream.h
deleted file mode 100644
index f6249ff..0000000
--- a/src/cobalt/media/base/fake_text_track_stream.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_FAKE_TEXT_TRACK_STREAM_H_
-#define COBALT_MEDIA_BASE_FAKE_TEXT_TRACK_STREAM_H_
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/message_loop.h"
-#include "cobalt/media/base/audio_decoder_config.h"
-#include "cobalt/media/base/demuxer_stream.h"
-#include "cobalt/media/base/video_decoder_config.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace cobalt {
-namespace media {
-
-// Fake implementation of the DemuxerStream.  These are the stream objects
-// we pass to the text renderer object when streams are added and removed.
-class FakeTextTrackStream : public DemuxerStream {
- public:
-  FakeTextTrackStream();
-  ~FakeTextTrackStream() OVERRIDE;
-
-  // DemuxerStream implementation.
-  void Read(const ReadCB&) OVERRIDE;
-  MOCK_METHOD0(audio_decoder_config, AudioDecoderConfig());
-  MOCK_METHOD0(video_decoder_config, VideoDecoderConfig());
-  Type type() const OVERRIDE;
-  MOCK_METHOD0(EnableBitstreamConverter, void());
-  bool SupportsConfigChanges() OVERRIDE;
-  VideoRotation video_rotation() OVERRIDE;
-  bool enabled() const OVERRIDE;
-  void set_enabled(bool enabled, base::TimeDelta timestamp) OVERRIDE;
-  void SetStreamStatusChangeCB(const StreamStatusChangeCB& cb) OVERRIDE;
-
-  void SatisfyPendingRead(const base::TimeDelta& start,
-                          const base::TimeDelta& duration,
-                          const std::string& id, const std::string& content,
-                          const std::string& settings);
-  void AbortPendingRead();
-  void SendEosNotification();
-
-  void Stop();
-
-  MOCK_METHOD0(OnRead, void());
-
- private:
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-  ReadCB read_cb_;
-  bool stopping_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeTextTrackStream);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_FAKE_TEXT_TRACK_STREAM_H_
diff --git a/src/cobalt/media/base/loopback_audio_converter.cc b/src/cobalt/media/base/loopback_audio_converter.cc
deleted file mode 100644
index f223da5..0000000
--- a/src/cobalt/media/base/loopback_audio_converter.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/loopback_audio_converter.h"
-
-namespace cobalt {
-namespace media {
-
-LoopbackAudioConverter::LoopbackAudioConverter(
-    const AudioParameters& input_params, const AudioParameters& output_params,
-    bool disable_fifo)
-    : audio_converter_(input_params, output_params, disable_fifo) {}
-
-LoopbackAudioConverter::~LoopbackAudioConverter() {}
-
-double LoopbackAudioConverter::ProvideInput(AudioBus* audio_bus,
-                                            uint32_t frames_delayed) {
-  audio_converter_.ConvertWithDelay(frames_delayed, audio_bus);
-  return 1.0;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/loopback_audio_converter.h b/src/cobalt/media/base/loopback_audio_converter.h
deleted file mode 100644
index c5fe75b..0000000
--- a/src/cobalt/media/base/loopback_audio_converter.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_LOOPBACK_AUDIO_CONVERTER_H_
-#define COBALT_MEDIA_BASE_LOOPBACK_AUDIO_CONVERTER_H_
-
-#include "base/basictypes.h"
-#include "cobalt/media/base/audio_converter.h"
-
-namespace cobalt {
-namespace media {
-
-// LoopbackAudioConverter works similar to AudioConverter and converts input
-// streams to different audio parameters. Then, the LoopbackAudioConverter can
-// be used as an input to another AudioConverter. This allows us to
-// use converted audio from AudioOutputStreams as input to an AudioConverter.
-// For example, this allows converting multiple streams into a common format and
-// using the converted audio as input to another AudioConverter (i.e. a mixer).
-class LoopbackAudioConverter : public AudioConverter::InputCallback {
- public:
-  LoopbackAudioConverter(const AudioParameters& input_params,
-                         const AudioParameters& output_params,
-                         bool disable_fifo);
-
-  ~LoopbackAudioConverter() OVERRIDE;
-
-  void AddInput(AudioConverter::InputCallback* input) {
-    audio_converter_.AddInput(input);
-  }
-
-  void RemoveInput(AudioConverter::InputCallback* input) {
-    audio_converter_.RemoveInput(input);
-  }
-
-  bool empty() { return audio_converter_.empty(); }
-
- private:
-  double ProvideInput(AudioBus* audio_bus, uint32_t frames_delayed) OVERRIDE;
-
-  AudioConverter audio_converter_;
-
-  DISALLOW_COPY_AND_ASSIGN(LoopbackAudioConverter);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_LOOPBACK_AUDIO_CONVERTER_H_
diff --git a/src/cobalt/media/base/media_switches.cc b/src/cobalt/media/base/media_switches.cc
deleted file mode 100644
index 42c2d73..0000000
--- a/src/cobalt/media/base/media_switches.cc
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "build/build_config.h"
-#include "cobalt/media/base/media_switches.h"
-
-namespace switches {
-
-// Allow users to specify a custom buffer size for debugging purpose.
-const char kAudioBufferSize[] = "audio-buffer-size";
-
-// Set number of threads to use for video decoding.
-const char kVideoThreads[] = "video-threads";
-
-// Suspend media pipeline on background tabs.
-const char kEnableMediaSuspend[] = "enable-media-suspend";
-const char kDisableMediaSuspend[] = "disable-media-suspend";
-
-// Force to report VP9 as an unsupported MIME type.
-const char kReportVp9AsAnUnsupportedMimeType[] =
-    "report-vp9-as-an-unsupported-mime-type";
-
-#if defined(OS_ANDROID)
-// Use WebMediaPlayerAndroid instead of WebMediaPlayerImpl. This is a temporary
-// switch for holding back the new unified media pipeline.
-const char kDisableUnifiedMediaPipeline[] = "disable-unified-media-pipeline";
-#endif
-
-#if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_SOLARIS)
-// The Alsa device to use when opening an audio input stream.
-const char kAlsaInputDevice[] = "alsa-input-device";
-// The Alsa device to use when opening an audio stream.
-const char kAlsaOutputDevice[] = "alsa-output-device";
-#endif
-
-// Use GpuMemoryBuffers for Video Capture when this is an option for the device.
-// Experimental, see http://crbug.com/503835 and http://crbug.com/440843.
-const char kUseGpuMemoryBuffersForCapture[] =
-    "use-gpu-memory-buffers-for-capture";
-
-#if defined(OS_WIN)
-// Use exclusive mode audio streaming for Windows Vista and higher.
-// Leads to lower latencies for audio streams which uses the
-// AudioParameters::AUDIO_PCM_LOW_LATENCY audio path.
-// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd370844.aspx
-// for details.
-const char kEnableExclusiveAudio[] = "enable-exclusive-audio";
-
-// Force the use of MediaFoundation for video capture. This is only supported in
-// Windows 7 and above. Used, like |kForceDirectShowVideoCapture|, to
-// troubleshoot problems in Windows platforms.
-const char kForceMediaFoundationVideoCapture[] = "force-mediafoundation";
-
-// Use Windows WaveOut/In audio API even if Core Audio is supported.
-const char kForceWaveAudio[] = "force-wave-audio";
-
-// Instead of always using the hardware channel layout, check if a driver
-// supports the source channel layout.  Avoids outputting empty channels and
-// permits drivers to enable stereo to multichannel expansion.  Kept behind a
-// flag since some drivers lie about supported layouts and hang when used.  See
-// http://crbug.com/259165 for more details.
-const char kTrySupportedChannelLayouts[] = "try-supported-channel-layouts";
-
-// Number of buffers to use for WaveOut.
-const char kWaveOutBuffers[] = "waveout-buffers";
-#endif
-
-#if defined(USE_CRAS)
-// Use CRAS, the ChromeOS audio server.
-const char kUseCras[] = "use-cras";
-#endif
-
-#if !defined(OS_ANDROID)
-// Use a media session for each tabs in a way that two tabs can't play on top of
-// each other. This is different from the Media Session API as it is enabling a
-// default behaviour for the browser.
-const char kEnableDefaultMediaSession[] = "enable-default-media-session";
-#endif
-
-// Use fake device for Media Stream to replace actual camera and microphone.
-const char kUseFakeDeviceForMediaStream[] = "use-fake-device-for-media-stream";
-
-// Use an .y4m file to play as the webcam. See the comments in
-// media/capture/video/file_video_capture_device.h for more details.
-const char kUseFileForFakeVideoCapture[] = "use-file-for-fake-video-capture";
-
-// Play a .wav file as the microphone. Note that for WebRTC calls we'll treat
-// the bits as if they came from the microphone, which means you should disable
-// audio processing (lest your audio file will play back distorted). The input
-// file is converted to suit Chrome's audio buses if necessary, so most sane
-// .wav files should work. You can pass either <path> to play the file looping
-// or <path>%noloop to stop after playing the file to completion.
-const char kUseFileForFakeAudioCapture[] = "use-file-for-fake-audio-capture";
-
-// Enables support for inband text tracks in media content.
-const char kEnableInbandTextTracks[] = "enable-inband-text-tracks";
-
-// When running tests on a system without the required hardware or libraries,
-// this flag will cause the tests to fail. Otherwise, they silently succeed.
-const char kRequireAudioHardwareForTesting[] =
-    "require-audio-hardware-for-testing";
-
-// Allows clients to override the threshold for when the media renderer will
-// declare the underflow state for the video stream when audio is present.
-// TODO(dalecurtis): Remove once experiments for http://crbug.com/470940 finish.
-const char kVideoUnderflowThresholdMs[] = "video-underflow-threshold-ms";
-
-// Disables the new rendering algorithm for webrtc, which is designed to improve
-// the rendering smoothness.
-const char kDisableRTCSmoothnessAlgorithm[] =
-    "disable-rtc-smoothness-algorithm";
-
-// Enables demuxing of vp9 in mp4. Note that this flag will not have any effect
-// if MP4 demuxing is not enabled in the build.
-const char kEnableVp9InMp4[] = "enable-vp9-in-mp4";
-
-// Force media player using SurfaceView instead of SurfaceTexture on Android.
-const char kForceVideoOverlays[] = "force-video-overlays";
-
-// Allows explicitly specifying MSE audio/video buffer sizes.
-// Default values are 150M for video and 12M for audio.
-const char kMSEAudioBufferSizeLimit[] = "mse-audio-buffer-size-limit";
-const char kMSEVideoBufferSizeLimit[] = "mse-video-buffer-size-limit";
-
-}  // namespace switches
-
-namespace cobalt {
-namespace media {
-
-#if defined(OS_WIN)
-// Enables H264 HW encode acceleration using Media Foundation for Windows.
-const base::Feature kMediaFoundationH264Encoding{
-    "MediaFoundationH264Encoding", base::FEATURE_DISABLED_BY_DEFAULT};
-#endif  // defined(OS_WIN)
-
-#if defined(ENABLE_PLUGINS)
-// Let flash join and be controlled by media session, only valid when
-// |kEnableDefaultMediaSession| is on.
-const base::Feature kFlashJoinsMediaSession{"FlashJoinsMediaSession",
-                                            base::FEATURE_DISABLED_BY_DEFAULT};
-#endif  // defined(ENABLE_PLUGINS)
-
-// Use new audio rendering mixer.
-const base::Feature kNewAudioRenderingMixingStrategy{
-    "NewAudioRenderingMixingStrategy", base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Only used for disabling overlay fullscreen (aka SurfaceView) in Clank.
-const base::Feature kOverlayFullscreenVideo{"overlay-fullscreen-video",
-                                            base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Let videos be resumed via remote controls (for example, the notification)
-// when in background.
-const base::Feature kResumeBackgroundVideo {
-  "resume-background-video",
-#if defined(OS_ANDROID)
-      base::FEATURE_ENABLED_BY_DEFAULT
-#else
-      base::FEATURE_DISABLED_BY_DEFAULT
-#endif
-};
-
-// Use shared block-based buffering for media.
-const base::Feature kUseNewMediaCache{"use-new-media-cache",
-                                      base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Correct video colors based on output display?
-const base::Feature kVideoColorManagement{"video-color-management",
-                                          base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Enables support for External Clear Key (ECK) key system for testing on
-// supported platforms. On platforms that do not support ECK, this feature has
-// no effect.
-const base::Feature kExternalClearKeyForTesting{
-    "external-clear-key-for-testing", base::FEATURE_DISABLED_BY_DEFAULT};
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/media_switches.h b/src/cobalt/media/base/media_switches.h
deleted file mode 100644
index 4ca9e7b..0000000
--- a/src/cobalt/media/base/media_switches.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Defines all the "media" command-line switches.
-
-#ifndef COBALT_MEDIA_BASE_MEDIA_SWITCHES_H_
-#define COBALT_MEDIA_BASE_MEDIA_SWITCHES_H_
-
-#include "base/feature_list.h"
-#include "build/build_config.h"
-#include "cobalt/media/base/media_export.h"
-
-namespace switches {
-
-MEDIA_EXPORT extern const char kAudioBufferSize[];
-
-MEDIA_EXPORT extern const char kVideoThreads[];
-
-MEDIA_EXPORT extern const char kEnableMediaSuspend[];
-MEDIA_EXPORT extern const char kDisableMediaSuspend[];
-
-MEDIA_EXPORT extern const char kReportVp9AsAnUnsupportedMimeType[];
-
-#if defined(OS_ANDROID)
-MEDIA_EXPORT extern const char kDisableUnifiedMediaPipeline[];
-#endif
-
-#if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_SOLARIS)
-MEDIA_EXPORT extern const char kAlsaInputDevice[];
-MEDIA_EXPORT extern const char kAlsaOutputDevice[];
-#endif
-
-MEDIA_EXPORT extern const char kUseGpuMemoryBuffersForCapture[];
-
-#if defined(OS_WIN)
-MEDIA_EXPORT extern const char kEnableExclusiveAudio[];
-MEDIA_EXPORT extern const char kForceMediaFoundationVideoCapture[];
-MEDIA_EXPORT extern const char kForceWaveAudio[];
-MEDIA_EXPORT extern const char kTrySupportedChannelLayouts[];
-MEDIA_EXPORT extern const char kWaveOutBuffers[];
-#endif
-
-#if defined(USE_CRAS)
-MEDIA_EXPORT extern const char kUseCras[];
-#endif
-
-#if !defined(OS_ANDROID)
-MEDIA_EXPORT extern const char kEnableDefaultMediaSession[];
-#endif
-
-MEDIA_EXPORT extern const char kUseFakeDeviceForMediaStream[];
-MEDIA_EXPORT extern const char kUseFileForFakeVideoCapture[];
-MEDIA_EXPORT extern const char kUseFileForFakeAudioCapture[];
-
-MEDIA_EXPORT extern const char kEnableInbandTextTracks[];
-
-MEDIA_EXPORT extern const char kRequireAudioHardwareForTesting[];
-
-MEDIA_EXPORT extern const char kVideoUnderflowThresholdMs[];
-
-MEDIA_EXPORT extern const char kDisableRTCSmoothnessAlgorithm[];
-
-MEDIA_EXPORT extern const char kEnableVp9InMp4[];
-
-MEDIA_EXPORT extern const char kForceVideoOverlays[];
-
-MEDIA_EXPORT extern const char kMSEAudioBufferSizeLimit[];
-MEDIA_EXPORT extern const char kMSEVideoBufferSizeLimit[];
-
-}  // namespace switches
-
-namespace cobalt {
-namespace media {
-
-// All features in alphabetical order. The features should be documented
-// alongside the definition of their values in the .cc file.
-
-#if defined(OS_WIN)
-MEDIA_EXPORT extern const base::Feature kMediaFoundationH264Encoding;
-#endif  // defined(OS_WIN)
-
-#if defined(ENABLE_PLUGINS)
-MEDIA_EXPORT extern const base::Feature kFlashJoinsMediaSession;
-#endif  // defined(ENABLE_PLUGINS)
-
-MEDIA_EXPORT extern const base::Feature kNewAudioRenderingMixingStrategy;
-MEDIA_EXPORT extern const base::Feature kOverlayFullscreenVideo;
-MEDIA_EXPORT extern const base::Feature kResumeBackgroundVideo;
-MEDIA_EXPORT extern const base::Feature kUseNewMediaCache;
-MEDIA_EXPORT extern const base::Feature kVideoColorManagement;
-MEDIA_EXPORT extern const base::Feature kExternalClearKeyForTesting;
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_MEDIA_SWITCHES_H_
diff --git a/src/cobalt/media/base/mock_audio_renderer_sink.cc b/src/cobalt/media/base/mock_audio_renderer_sink.cc
deleted file mode 100644
index bc25049..0000000
--- a/src/cobalt/media/base/mock_audio_renderer_sink.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/mock_audio_renderer_sink.h"
-
-namespace cobalt {
-namespace media {
-MockAudioRendererSink::MockAudioRendererSink()
-    : MockAudioRendererSink(OUTPUT_DEVICE_STATUS_OK) {}
-
-MockAudioRendererSink::MockAudioRendererSink(OutputDeviceStatus device_status)
-    : MockAudioRendererSink(std::string(), device_status) {}
-
-MockAudioRendererSink::MockAudioRendererSink(const std::string& device_id,
-                                             OutputDeviceStatus device_status)
-    : MockAudioRendererSink(
-          device_id, device_status,
-          AudioParameters(AudioParameters::AUDIO_FAKE, CHANNEL_LAYOUT_STEREO,
-                          AudioParameters::kTelephoneSampleRate, 16, 1)) {}
-
-MockAudioRendererSink::MockAudioRendererSink(
-    const std::string& device_id, OutputDeviceStatus device_status,
-    const AudioParameters& device_output_params)
-    : output_device_info_(device_id, device_status, device_output_params) {}
-
-MockAudioRendererSink::~MockAudioRendererSink() {}
-
-void MockAudioRendererSink::SwitchOutputDevice(
-    const std::string& device_id, const url::Origin& security_origin,
-    const OutputDeviceStatusCB& callback) {
-  // NB: output device won't be changed, since it's not required by any tests
-  // now.
-  callback.Run(output_device_info_.device_status());
-}
-
-void MockAudioRendererSink::Initialize(const AudioParameters& params,
-                                       RenderCallback* renderer) {
-  callback_ = renderer;
-}
-
-OutputDeviceInfo MockAudioRendererSink::GetOutputDeviceInfo() {
-  return output_device_info_;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/mock_audio_renderer_sink.h b/src/cobalt/media/base/mock_audio_renderer_sink.h
deleted file mode 100644
index e590482..0000000
--- a/src/cobalt/media/base/mock_audio_renderer_sink.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_MOCK_AUDIO_RENDERER_SINK_H_
-#define COBALT_MEDIA_BASE_MOCK_AUDIO_RENDERER_SINK_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "cobalt/media/base/audio_parameters.h"
-#include "cobalt/media/base/audio_renderer_sink.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace cobalt {
-namespace media {
-
-class MockAudioRendererSink : public SwitchableAudioRendererSink {
- public:
-  MockAudioRendererSink();
-  explicit MockAudioRendererSink(OutputDeviceStatus device_status);
-  MockAudioRendererSink(const std::string& device_id,
-                        OutputDeviceStatus device_status);
-  MockAudioRendererSink(const std::string& device_id,
-                        OutputDeviceStatus device_status,
-                        const AudioParameters& device_output_params);
-
-  MOCK_METHOD0(Start, void());
-  MOCK_METHOD0(Stop, void());
-  MOCK_METHOD0(Pause, void());
-  MOCK_METHOD0(Play, void());
-  MOCK_METHOD1(SetVolume, bool(double volume));
-  MOCK_METHOD0(CurrentThreadIsRenderingThread, bool());
-
-  OutputDeviceInfo GetOutputDeviceInfo();
-
-  void SwitchOutputDevice(const std::string& device_id,
-                          const url::Origin& security_origin,
-                          const OutputDeviceStatusCB& callback) OVERRIDE;
-  void Initialize(const AudioParameters& params,
-                  RenderCallback* renderer) OVERRIDE;
-  AudioRendererSink::RenderCallback* callback() { return callback_; }
-
- protected:
-  ~MockAudioRendererSink() OVERRIDE;
-
- private:
-  RenderCallback* callback_;
-  OutputDeviceInfo output_device_info_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockAudioRendererSink);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_MOCK_AUDIO_RENDERER_SINK_H_
diff --git a/src/cobalt/media/base/output_device_info.cc b/src/cobalt/media/base/output_device_info.cc
deleted file mode 100644
index 96a586a..0000000
--- a/src/cobalt/media/base/output_device_info.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/output_device_info.h"
-
-namespace cobalt {
-namespace media {
-
-// Output device information returned by GetOutputDeviceInfo() methods of
-// various interfaces.
-OutputDeviceInfo::OutputDeviceInfo()
-    : OutputDeviceInfo(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL) {}
-
-OutputDeviceInfo::OutputDeviceInfo(OutputDeviceStatus device_status)
-    : OutputDeviceInfo(std::string(), device_status,
-                       AudioParameters::UnavailableDeviceParams()) {}
-
-OutputDeviceInfo::OutputDeviceInfo(const std::string& device_id,
-                                   OutputDeviceStatus device_status,
-                                   const AudioParameters& output_params)
-    : device_id_(device_id),
-      device_status_(device_status),
-      output_params_(output_params) {}
-
-OutputDeviceInfo::OutputDeviceInfo(const OutputDeviceInfo&) = default;
-
-OutputDeviceInfo& OutputDeviceInfo::operator=(const OutputDeviceInfo&) =
-    default;
-
-OutputDeviceInfo::~OutputDeviceInfo() {}
-
-std::string OutputDeviceInfo::AsHumanReadableString() const {
-  std::ostringstream s;
-  s << "device_id: " << device_id() << " device_status: " << device_status()
-    << " output_params: [ " << output_params().AsHumanReadableString() << " ]";
-  return s.str();
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/output_device_info.h b/src/cobalt/media/base/output_device_info.h
deleted file mode 100644
index 920e66e..0000000
--- a/src/cobalt/media/base/output_device_info.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_OUTPUT_DEVICE_INFO_H_
-#define COBALT_MEDIA_BASE_OUTPUT_DEVICE_INFO_H_
-
-#include <string>
-
-#include "base/callback.h"
-#include "cobalt/media/base/audio_parameters.h"
-#include "cobalt/media/base/media_export.h"
-
-namespace cobalt {
-namespace media {
-
-// Result of an audio output device switch operation
-enum OutputDeviceStatus {
-  OUTPUT_DEVICE_STATUS_OK = 0,
-  OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
-  OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
-  OUTPUT_DEVICE_STATUS_ERROR_TIMED_OUT,
-  OUTPUT_DEVICE_STATUS_ERROR_INTERNAL,
-  OUTPUT_DEVICE_STATUS_LAST = OUTPUT_DEVICE_STATUS_ERROR_INTERNAL,
-};
-
-using OutputDeviceStatusCB = base::Callback<void(OutputDeviceStatus)>;
-
-// Output device information returned by
-// AudioRendererSink::GetOutputDeviceInfo()
-class MEDIA_EXPORT OutputDeviceInfo {
- public:
-  // Use this constructor to initialize with "no info available" values.
-  OutputDeviceInfo();
-
-  // Use this constructor to indicate a specific error status of the device.
-  explicit OutputDeviceInfo(OutputDeviceStatus device_status);
-
-  OutputDeviceInfo(const std::string& device_id,
-                   OutputDeviceStatus device_status,
-                   const AudioParameters& output_params);
-
-  OutputDeviceInfo(const OutputDeviceInfo& other);
-
-  OutputDeviceInfo& operator=(const OutputDeviceInfo&);
-
-  ~OutputDeviceInfo();
-
-  // Returns the device ID.
-  const std::string& device_id() const { return device_id_; }
-
-  // Returns the status of output device.
-  OutputDeviceStatus device_status() const { return device_status_; }
-
-  // Returns the device's audio output parameters.
-  // The return value is undefined if the device status (as returned by
-  // device_status()) is different from OUTPUT_DEVICE_STATUS_OK.
-  const AudioParameters& output_params() const { return output_params_; }
-
-  // Returns a human-readable string describing |*this|.  For debugging & test
-  // output only.
-  std::string AsHumanReadableString() const;
-
- private:
-  std::string device_id_;
-  OutputDeviceStatus device_status_;
-  AudioParameters output_params_;
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_OUTPUT_DEVICE_INFO_H_
diff --git a/src/cobalt/media/base/pipeline.h b/src/cobalt/media/base/pipeline.h
index fafb88f..7fde2b8 100644
--- a/src/cobalt/media/base/pipeline.h
+++ b/src/cobalt/media/base/pipeline.h
@@ -15,6 +15,7 @@
 #ifndef COBALT_MEDIA_BASE_PIPELINE_H_
 #define COBALT_MEDIA_BASE_PIPELINE_H_
 
+#include <string>
 #include <vector>
 
 #include "base/callback.h"
@@ -83,6 +84,10 @@
   };
 
   typedef base::Callback<void(BufferingState)> BufferingStateCB;
+#if SB_HAS(PLAYER_WITH_URL)
+  typedef base::Callback<void(EmeInitDataType, const std::vector<uint8_t>&)>
+      OnEncryptedMediaInitDataEncounteredCB;
+#endif  // SB_HAS(PLAYER_WITH_URL)
 
   static scoped_refptr<Pipeline> Create(
       PipelineWindow window,
@@ -118,6 +123,11 @@
 #if COBALT_MEDIA_ENABLE_VIDEO_DUMPER
                      const SetEMEInitDataReadyCB& set_eme_init_data_ready_cb,
 #endif  // COBALT_MEDIA_ENABLE_VIDEO_DUMPER
+#if SB_HAS(PLAYER_WITH_URL)
+                     const OnEncryptedMediaInitDataEncounteredCB&
+                         encrypted_media_init_data_encountered_cb,
+                     const std::string& source_url,
+#endif  // SB_HAS(PLAYER_WITH_URL)
                      const PipelineStatusCB& ended_cb,
                      const PipelineStatusCB& error_cb,
                      const PipelineStatusCB& seek_cb,
diff --git a/src/cobalt/media/base/pipeline_impl.cc b/src/cobalt/media/base/pipeline_impl.cc
deleted file mode 100644
index 5741762..0000000
--- a/src/cobalt/media/base/pipeline_impl.cc
+++ /dev/null
@@ -1,1249 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/pipeline_impl.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/callback_helpers.h"
-#include "base/command_line.h"
-#include "base/location.h"
-#include "base/metrics/histogram.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "cobalt/media/base/bind_to_current_loop.h"
-#include "cobalt/media/base/demuxer.h"
-#include "cobalt/media/base/media_log.h"
-#include "cobalt/media/base/media_switches.h"
-#include "cobalt/media/base/renderer.h"
-#include "cobalt/media/base/renderer_client.h"
-#include "cobalt/media/base/serial_runner.h"
-#include "cobalt/media/base/text_renderer.h"
-#include "cobalt/media/base/text_track_config.h"
-#include "cobalt/media/base/timestamp_constants.h"
-#include "cobalt/media/base/video_decoder_config.h"
-
-static const double kDefaultPlaybackRate = 0.0;
-static const float kDefaultVolume = 1.0f;
-
-namespace cobalt {
-namespace media {
-
-class PipelineImpl::RendererWrapper : public DemuxerHost,
-                                      public RendererClient {
- public:
-  RendererWrapper(scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
-                  scoped_refptr<MediaLog> media_log);
-  ~RendererWrapper() final;
-
-  void Start(Demuxer* demuxer, std::unique_ptr<Renderer> renderer,
-             std::unique_ptr<TextRenderer> text_renderer,
-             base::WeakPtr<PipelineImpl> weak_pipeline);
-  void Stop(const base::Closure& stop_cb);
-  void Seek(base::TimeDelta time);
-  void Suspend();
-  void Resume(std::unique_ptr<Renderer> renderer, base::TimeDelta time);
-  void SetPlaybackRate(double playback_rate);
-  void SetVolume(float volume);
-  base::TimeDelta GetMediaTime() const;
-  Ranges<base::TimeDelta> GetBufferedTimeRanges() const;
-  bool DidLoadingProgress();
-  PipelineStatistics GetStatistics() const;
-  void SetCdm(CdmContext* cdm_context, const CdmAttachedCB& cdm_attached_cb);
-
-  // |enabledTrackIds| contains track ids of enabled audio tracks.
-  void OnEnabledAudioTracksChanged(
-      const std::vector<MediaTrack::Id>& enabledTrackIds);
-
-  // |trackId| either empty, which means no video track is selected, or contain
-  // one element - the selected video track id.
-  void OnSelectedVideoTrackChanged(
-      const std::vector<MediaTrack::Id>& selectedTrackId);
-
- private:
-  // Contains state shared between main and media thread.
-  // Main thread can only read. Media thread can both - read and write.
-  // So it is not necessary to lock when reading from the media thread.
-  // This struct should only contain state that is not immediately needed by
-  // PipelineClient and can be cached on the media thread until queried.
-  // Alternatively we could cache it on the main thread by posting the
-  // notification to the main thread. But some of the state change notifications
-  // (OnStatisticsUpdate and OnBufferedTimeRangesChanged) arrive much more
-  // frequently than needed. Posting all those notifications to the main thread
-  // causes performance issues: crbug.com/619975.
-  struct SharedState {
-    // TODO(scherkus): Enforce that Renderer is only called on a single thread,
-    // even for accessing media time http://crbug.com/370634
-    std::unique_ptr<Renderer> renderer;
-
-    // True when OnBufferedTimeRangesChanged() has been called more recently
-    // than DidLoadingProgress().
-    bool did_loading_progress = false;
-
-    // Amount of available buffered data as reported by Demuxer.
-    Ranges<base::TimeDelta> buffered_time_ranges;
-
-    // Accumulated statistics reported by the renderer.
-    PipelineStatistics statistics;
-
-    // The media timestamp to return while the pipeline is suspended.
-    // Otherwise set to kNoTimestamp.
-    base::TimeDelta suspend_timestamp = kNoTimestamp;
-  };
-
-  // DemuxerHost implementaion.
-  void OnBufferedTimeRangesChanged(const Ranges<base::TimeDelta>& ranges) final;
-  void SetDuration(base::TimeDelta duration) final;
-  void OnDemuxerError(PipelineStatus error) final;
-  void AddTextStream(DemuxerStream* text_stream,
-                     const TextTrackConfig& config) final;
-  void RemoveTextStream(DemuxerStream* text_stream) final;
-
-  // RendererClient implementation.
-  void OnError(PipelineStatus error) final;
-  void OnEnded() final;
-  void OnStatisticsUpdate(const PipelineStatistics& stats) final;
-  void OnBufferingStateChange(BufferingState state) final;
-  void OnWaitingForDecryptionKey() final;
-  void OnVideoNaturalSizeChange(const gfx::Size& size) final;
-  void OnVideoOpacityChange(bool opaque) final;
-  void OnDurationChange(base::TimeDelta duration) final;
-
-  // TextRenderer tasks and notifications.
-  void OnTextRendererEnded();
-  void AddTextStreamTask(DemuxerStream* text_stream,
-                         const TextTrackConfig& config);
-  void RemoveTextStreamTask(DemuxerStream* text_stream);
-
-  // Common handlers for notifications from renderers and demuxer.
-  void OnPipelineError(PipelineStatus error);
-  void OnCdmAttached(const CdmAttachedCB& cdm_attached_cb,
-                     CdmContext* cdm_context, bool success);
-  void CheckPlaybackEnded();
-
-  // State transition tasks.
-  void SetState(State next_state);
-  void CompleteSeek(base::TimeDelta seek_time, PipelineStatus status);
-  void CompleteSuspend(PipelineStatus status);
-  void InitializeDemuxer(const PipelineStatusCB& done_cb);
-  void InitializeRenderer(const PipelineStatusCB& done_cb);
-  void DestroyRenderer();
-  void ReportMetadata();
-
-  const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
-  const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
-  const scoped_refptr<MediaLog> media_log_;
-
-  base::WeakPtr<PipelineImpl> weak_pipeline_;
-  Demuxer* demuxer_;
-  std::unique_ptr<TextRenderer> text_renderer_;
-  double playback_rate_;
-  float volume_;
-  CdmContext* cdm_context_;
-
-  // Lock used to serialize |shared_state_|.
-  mutable base::Lock shared_state_lock_;
-
-  // State shared between main and media thread.
-  SharedState shared_state_;
-
-  // Current state of the pipeline.
-  State state_;
-
-  // Status of the pipeline.  Initialized to PIPELINE_OK which indicates that
-  // the pipeline is operating correctly. Any other value indicates that the
-  // pipeline is stopped or is stopping.  Clients can call the Stop() method to
-  // reset the pipeline state, and restore this to PIPELINE_OK.
-  PipelineStatus status_;
-
-  // Whether we've received the audio/video/text ended events.
-  bool renderer_ended_;
-  bool text_renderer_ended_;
-
-  // Series of tasks to Start(), Seek(), and Resume().
-  std::unique_ptr<SerialRunner> pending_callbacks_;
-
-  base::WeakPtr<RendererWrapper> weak_this_;
-  base::WeakPtrFactory<RendererWrapper> weak_factory_;
-  DISALLOW_COPY_AND_ASSIGN(RendererWrapper);
-};
-
-PipelineImpl::RendererWrapper::RendererWrapper(
-    scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
-    scoped_refptr<MediaLog> media_log)
-    : media_task_runner_(std::move(media_task_runner)),
-      main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      media_log_(std::move(media_log)),
-      demuxer_(NULL),
-      playback_rate_(kDefaultPlaybackRate),
-      volume_(kDefaultVolume),
-      cdm_context_(NULL),
-      state_(kCreated),
-      status_(PIPELINE_OK),
-      renderer_ended_(false),
-      text_renderer_ended_(false),
-      weak_factory_(this) {
-  weak_this_ = weak_factory_.GetWeakPtr();
-  media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated));
-}
-
-PipelineImpl::RendererWrapper::~RendererWrapper() {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-  DCHECK(state_ == kCreated || state_ == kStopped);
-}
-
-// Note that the usage of base::Unretained() with the renderers is considered
-// safe as they are owned by |pending_callbacks_| and share the same lifetime.
-//
-// That being said, deleting the renderers while keeping |pending_callbacks_|
-// running on the media thread would result in crashes.
-
-void PipelineImpl::RendererWrapper::Start(
-    Demuxer* demuxer, std::unique_ptr<Renderer> renderer,
-    std::unique_ptr<TextRenderer> text_renderer,
-    base::WeakPtr<PipelineImpl> weak_pipeline) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-  DCHECK_EQ(kCreated, state_) << "Received start in unexpected state: "
-                              << state_;
-
-  SetState(kStarting);
-
-  DCHECK(!demuxer_);
-  DCHECK(!shared_state_.renderer);
-  DCHECK(!text_renderer_);
-  DCHECK(!renderer_ended_);
-  DCHECK(!text_renderer_ended_);
-  DCHECK(!weak_pipeline_);
-  demuxer_ = demuxer;
-  {
-    base::AutoLock auto_lock(shared_state_lock_);
-    shared_state_.renderer = std::move(renderer);
-  }
-  text_renderer_ = std::move(text_renderer);
-  if (text_renderer_) {
-    text_renderer_->Initialize(
-        base::Bind(&RendererWrapper::OnTextRendererEnded, weak_this_));
-  }
-  weak_pipeline_ = weak_pipeline;
-
-  // Queue asynchronous actions required to start.
-  DCHECK(!pending_callbacks_);
-  SerialRunner::Queue fns;
-
-  // Initialize demuxer.
-  fns.Push(base::Bind(&RendererWrapper::InitializeDemuxer, weak_this_));
-
-  // Once the demuxer is initialized successfully, media metadata must be
-  // available - report the metadata to client.
-  fns.Push(base::Bind(&RendererWrapper::ReportMetadata, weak_this_));
-
-  // Initialize renderer.
-  fns.Push(base::Bind(&RendererWrapper::InitializeRenderer, weak_this_));
-
-  // Run tasks.
-  pending_callbacks_ =
-      SerialRunner::Run(fns, base::Bind(&RendererWrapper::CompleteSeek,
-                                        weak_this_, base::TimeDelta()));
-}
-
-void PipelineImpl::RendererWrapper::Stop(const base::Closure& stop_cb) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-  DCHECK(state_ != kStopping && state_ != kStopped);
-
-  SetState(kStopping);
-
-  if (shared_state_.statistics.video_frames_decoded > 0) {
-    UMA_HISTOGRAM_COUNTS("Media.DroppedFrameCount",
-                         shared_state_.statistics.video_frames_dropped);
-  }
-
-  // If we stop during starting/seeking/suspending/resuming we don't want to
-  // leave outstanding callbacks around. The callbacks also do not get run if
-  // the pipeline is stopped before it had a chance to complete outstanding
-  // tasks.
-  pending_callbacks_.reset();
-
-  DestroyRenderer();
-  text_renderer_.reset();
-
-  if (demuxer_) {
-    demuxer_->Stop();
-    demuxer_ = NULL;
-  }
-
-  SetState(kStopped);
-
-  // Post the stop callback to enqueue it after the tasks that may have been
-  // posted by Demuxer and Renderer during stopping. Note that in theory the
-  // tasks posted by Demuxer/Renderer may post even more tasks that will get
-  // enqueued after |stop_cb|. This may be problematic because Demuxer may
-  // get destroyed as soon as |stop_cb| is run. In practice this is not a
-  // problem, but ideally Demuxer should be destroyed on the media thread.
-  media_task_runner_->PostTask(FROM_HERE, stop_cb);
-}
-
-void PipelineImpl::RendererWrapper::Seek(base::TimeDelta time) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  // Suppress seeking if we're not fully started.
-  if (state_ != kPlaying) {
-    DCHECK(state_ == kStopping || state_ == kStopped)
-        << "Receive seek in unexpected state: " << state_;
-    OnPipelineError(PIPELINE_ERROR_INVALID_STATE);
-    return;
-  }
-
-  base::TimeDelta seek_timestamp = std::max(time, demuxer_->GetStartTime());
-
-  SetState(kSeeking);
-  renderer_ended_ = false;
-  text_renderer_ended_ = false;
-
-  // Queue asynchronous actions required to start.
-  DCHECK(!pending_callbacks_);
-  SerialRunner::Queue bound_fns;
-
-  // Abort any reads the renderer may be blocked on.
-  demuxer_->AbortPendingReads();
-
-  // Pause.
-  if (text_renderer_) {
-    bound_fns.Push(base::Bind(&TextRenderer::Pause,
-                              base::Unretained(text_renderer_.get())));
-  }
-
-  // Flush.
-  DCHECK(shared_state_.renderer);
-  bound_fns.Push(base::Bind(&Renderer::Flush,
-                            base::Unretained(shared_state_.renderer.get())));
-
-  if (text_renderer_) {
-    bound_fns.Push(base::Bind(&TextRenderer::Flush,
-                              base::Unretained(text_renderer_.get())));
-  }
-
-  // Seek demuxer.
-  bound_fns.Push(
-      base::Bind(&Demuxer::Seek, base::Unretained(demuxer_), seek_timestamp));
-
-  // Run tasks.
-  pending_callbacks_ = SerialRunner::Run(
-      bound_fns,
-      base::Bind(&RendererWrapper::CompleteSeek, weak_this_, seek_timestamp));
-}
-
-void PipelineImpl::RendererWrapper::Suspend() {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  // Suppress suspending if we're not playing.
-  if (state_ != kPlaying) {
-    DCHECK(state_ == kStopping || state_ == kStopped)
-        << "Receive suspend in unexpected state: " << state_;
-    OnPipelineError(PIPELINE_ERROR_INVALID_STATE);
-    return;
-  }
-  DCHECK(shared_state_.renderer);
-  DCHECK(!pending_callbacks_.get());
-
-  SetState(kSuspending);
-
-  // Freeze playback and record the media time before destroying the renderer.
-  shared_state_.renderer->SetPlaybackRate(0.0);
-  {
-    base::AutoLock auto_lock(shared_state_lock_);
-    shared_state_.suspend_timestamp = shared_state_.renderer->GetMediaTime();
-    DCHECK(shared_state_.suspend_timestamp != kNoTimestamp);
-  }
-
-  // Queue the asynchronous actions required to stop playback.
-  SerialRunner::Queue fns;
-
-  if (text_renderer_) {
-    fns.Push(base::Bind(&TextRenderer::Pause,
-                        base::Unretained(text_renderer_.get())));
-  }
-
-  // No need to flush the renderer since it's going to be destroyed.
-  pending_callbacks_ = SerialRunner::Run(
-      fns, base::Bind(&RendererWrapper::CompleteSuspend, weak_this_));
-}
-
-void PipelineImpl::RendererWrapper::Resume(std::unique_ptr<Renderer> renderer,
-                                           base::TimeDelta timestamp) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  // Suppress resuming if we're not suspended.
-  if (state_ != kSuspended) {
-    DCHECK(state_ == kStopping || state_ == kStopped)
-        << "Receive resume in unexpected state: " << state_;
-    OnPipelineError(PIPELINE_ERROR_INVALID_STATE);
-    return;
-  }
-  DCHECK(!shared_state_.renderer);
-  DCHECK(!pending_callbacks_.get());
-
-  SetState(kResuming);
-
-  {
-    base::AutoLock auto_lock(shared_state_lock_);
-    shared_state_.renderer = std::move(renderer);
-  }
-
-  renderer_ended_ = false;
-  text_renderer_ended_ = false;
-  base::TimeDelta start_timestamp =
-      std::max(timestamp, demuxer_->GetStartTime());
-
-  // Queue the asynchronous actions required to start playback.
-  SerialRunner::Queue fns;
-
-  fns.Push(
-      base::Bind(&Demuxer::Seek, base::Unretained(demuxer_), start_timestamp));
-
-  fns.Push(base::Bind(&RendererWrapper::InitializeRenderer, weak_this_));
-
-  pending_callbacks_ = SerialRunner::Run(
-      fns,
-      base::Bind(&RendererWrapper::CompleteSeek, weak_this_, start_timestamp));
-}
-
-void PipelineImpl::RendererWrapper::SetPlaybackRate(double playback_rate) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  playback_rate_ = playback_rate;
-  if (state_ == kPlaying)
-    shared_state_.renderer->SetPlaybackRate(playback_rate_);
-}
-
-void PipelineImpl::RendererWrapper::SetVolume(float volume) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  volume_ = volume;
-  if (state_ == kPlaying) shared_state_.renderer->SetVolume(volume_);
-}
-
-base::TimeDelta PipelineImpl::RendererWrapper::GetMediaTime() const {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-
-  base::AutoLock auto_lock(shared_state_lock_);
-  if (shared_state_.suspend_timestamp != kNoTimestamp)
-    return shared_state_.suspend_timestamp;
-  return shared_state_.renderer ? shared_state_.renderer->GetMediaTime()
-                                : base::TimeDelta();
-}
-
-Ranges<base::TimeDelta> PipelineImpl::RendererWrapper::GetBufferedTimeRanges()
-    const {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-
-  base::AutoLock auto_lock(shared_state_lock_);
-  return shared_state_.buffered_time_ranges;
-}
-
-bool PipelineImpl::RendererWrapper::DidLoadingProgress() {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-
-  base::AutoLock auto_lock(shared_state_lock_);
-  bool did_progress = shared_state_.did_loading_progress;
-  shared_state_.did_loading_progress = false;
-  return did_progress;
-}
-
-PipelineStatistics PipelineImpl::RendererWrapper::GetStatistics() const {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-
-  base::AutoLock auto_lock(shared_state_lock_);
-  return shared_state_.statistics;
-}
-
-void PipelineImpl::RendererWrapper::SetCdm(
-    CdmContext* cdm_context, const CdmAttachedCB& cdm_attached_cb) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  if (!shared_state_.renderer) {
-    cdm_context_ = cdm_context;
-    cdm_attached_cb.Run(true);
-    return;
-  }
-
-  shared_state_.renderer->SetCdm(
-      cdm_context, base::Bind(&RendererWrapper::OnCdmAttached, weak_this_,
-                              cdm_attached_cb, cdm_context));
-}
-
-void PipelineImpl::RendererWrapper::OnBufferedTimeRangesChanged(
-    const Ranges<base::TimeDelta>& ranges) {
-  // TODO(alokp): Add thread DCHECK after ensuring that all Demuxer
-  // implementations call DemuxerHost on the media thread.
-  base::AutoLock auto_lock(shared_state_lock_);
-  shared_state_.did_loading_progress = true;
-  shared_state_.buffered_time_ranges = ranges;
-}
-
-void PipelineImpl::RendererWrapper::SetDuration(base::TimeDelta duration) {
-  // TODO(alokp): Add thread DCHECK after ensuring that all Demuxer
-  // implementations call DemuxerHost on the media thread.
-  media_log_->AddEvent(media_log_->CreateTimeEvent(MediaLogEvent::DURATION_SET,
-                                                   "duration", duration));
-  UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration);
-
-  main_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&PipelineImpl::OnDurationChange, weak_pipeline_, duration));
-}
-
-void PipelineImpl::RendererWrapper::OnDemuxerError(PipelineStatus error) {
-  // TODO(alokp): Add thread DCHECK after ensuring that all Demuxer
-  // implementations call DemuxerHost on the media thread.
-  media_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&RendererWrapper::OnPipelineError, weak_this_, error));
-}
-
-void PipelineImpl::RendererWrapper::AddTextStream(
-    DemuxerStream* text_stream, const TextTrackConfig& config) {
-  // TODO(alokp): Add thread DCHECK after ensuring that all Demuxer
-  // implementations call DemuxerHost on the media thread.
-  media_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&RendererWrapper::AddTextStreamTask, weak_this_,
-                            text_stream, config));
-}
-
-void PipelineImpl::RendererWrapper::RemoveTextStream(
-    DemuxerStream* text_stream) {
-  // TODO(alokp): Add thread DCHECK after ensuring that all Demuxer
-  // implementations call DemuxerHost on the media thread.
-  media_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&RendererWrapper::RemoveTextStreamTask, weak_this_,
-                            text_stream));
-}
-
-void PipelineImpl::RendererWrapper::OnError(PipelineStatus error) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  media_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&RendererWrapper::OnPipelineError, weak_this_, error));
-}
-
-void PipelineImpl::RendererWrapper::OnEnded() {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-  media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED));
-
-  if (state_ != kPlaying) return;
-
-  DCHECK(!renderer_ended_);
-  renderer_ended_ = true;
-  CheckPlaybackEnded();
-}
-
-void PipelineImpl::OnEnabledAudioTracksChanged(
-    const std::vector<MediaTrack::Id>& enabledTrackIds) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  media_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&RendererWrapper::OnEnabledAudioTracksChanged,
-                 base::Unretained(renderer_wrapper_.get()), enabledTrackIds));
-}
-
-void PipelineImpl::OnSelectedVideoTrackChanged(
-    const std::vector<MediaTrack::Id>& selectedTrackId) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  media_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&RendererWrapper::OnSelectedVideoTrackChanged,
-                 base::Unretained(renderer_wrapper_.get()), selectedTrackId));
-}
-
-void PipelineImpl::RendererWrapper::OnEnabledAudioTracksChanged(
-    const std::vector<MediaTrack::Id>& enabledTrackIds) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  // Track status notifications might be delivered asynchronously. If we receive
-  // a notification when pipeline is stopped/shut down, it's safe to ignore it.
-  if (state_ == kStopping || state_ == kStopped) {
-    return;
-  }
-
-  DCHECK(demuxer_);
-  DCHECK(shared_state_.renderer || (state_ != kPlaying));
-
-  base::TimeDelta currTime = (state_ == kPlaying)
-                                 ? shared_state_.renderer->GetMediaTime()
-                                 : demuxer_->GetStartTime();
-  demuxer_->OnEnabledAudioTracksChanged(enabledTrackIds, currTime);
-}
-
-void PipelineImpl::RendererWrapper::OnSelectedVideoTrackChanged(
-    const std::vector<MediaTrack::Id>& selectedTrackId) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  // Track status notifications might be delivered asynchronously. If we receive
-  // a notification when pipeline is stopped/shut down, it's safe to ignore it.
-  if (state_ == kStopping || state_ == kStopped) {
-    return;
-  }
-
-  DCHECK(demuxer_);
-  DCHECK(shared_state_.renderer || (state_ != kPlaying));
-
-  base::TimeDelta currTime = (state_ == kPlaying)
-                                 ? shared_state_.renderer->GetMediaTime()
-                                 : demuxer_->GetStartTime();
-  demuxer_->OnSelectedVideoTrackChanged(selectedTrackId, currTime);
-}
-
-void PipelineImpl::RendererWrapper::OnStatisticsUpdate(
-    const PipelineStatistics& stats) {
-  DVLOG(3) << __func__;
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  base::AutoLock auto_lock(shared_state_lock_);
-  shared_state_.statistics.audio_bytes_decoded += stats.audio_bytes_decoded;
-  shared_state_.statistics.video_bytes_decoded += stats.video_bytes_decoded;
-  shared_state_.statistics.video_frames_decoded += stats.video_frames_decoded;
-  shared_state_.statistics.video_frames_dropped += stats.video_frames_dropped;
-  shared_state_.statistics.audio_memory_usage += stats.audio_memory_usage;
-  shared_state_.statistics.video_memory_usage += stats.video_memory_usage;
-}
-
-void PipelineImpl::RendererWrapper::OnBufferingStateChange(
-    BufferingState state) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-  DVLOG(2) << __func__ << "(" << state << ") ";
-
-  main_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&PipelineImpl::OnBufferingStateChange, weak_pipeline_, state));
-}
-
-void PipelineImpl::RendererWrapper::OnWaitingForDecryptionKey() {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  main_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&PipelineImpl::OnWaitingForDecryptionKey, weak_pipeline_));
-}
-
-void PipelineImpl::RendererWrapper::OnVideoNaturalSizeChange(
-    const gfx::Size& size) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  main_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&PipelineImpl::OnVideoNaturalSizeChange,
-                            weak_pipeline_, size));
-}
-
-void PipelineImpl::RendererWrapper::OnVideoOpacityChange(bool opaque) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  main_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&PipelineImpl::OnVideoOpacityChange, weak_pipeline_, opaque));
-}
-
-void PipelineImpl::RendererWrapper::OnDurationChange(base::TimeDelta duration) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-  SetDuration(duration);
-}
-
-void PipelineImpl::RendererWrapper::OnTextRendererEnded() {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-  media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::TEXT_ENDED));
-
-  if (state_ != kPlaying) return;
-
-  DCHECK(!text_renderer_ended_);
-  text_renderer_ended_ = true;
-  CheckPlaybackEnded();
-}
-
-void PipelineImpl::RendererWrapper::AddTextStreamTask(
-    DemuxerStream* text_stream, const TextTrackConfig& config) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  // TODO(matthewjheaney): fix up text_ended_ when text stream
-  // is added (http://crbug.com/321446).
-  if (text_renderer_) text_renderer_->AddTextStream(text_stream, config);
-}
-
-void PipelineImpl::RendererWrapper::RemoveTextStreamTask(
-    DemuxerStream* text_stream) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  if (text_renderer_) text_renderer_->RemoveTextStream(text_stream);
-}
-
-void PipelineImpl::RendererWrapper::OnPipelineError(PipelineStatus error) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-  DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!";
-
-  // Preserve existing abnormal status.
-  if (status_ != PIPELINE_OK) return;
-
-  // Don't report pipeline error events to the media log here. The embedder
-  // will log this when Client::OnError is called. If the pipeline is already
-  // stopped or stopping we also don't want to log any event. In case we are
-  // suspending or suspended, the error may be recoverable, so don't propagate
-  // it now, instead let the subsequent seek during resume propagate it if
-  // it's unrecoverable.
-  if (state_ == kStopping || state_ == kStopped || state_ == kSuspending ||
-      state_ == kSuspended) {
-    return;
-  }
-
-  status_ = error;
-  main_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&PipelineImpl::OnError, weak_pipeline_, error));
-}
-
-void PipelineImpl::RendererWrapper::OnCdmAttached(
-    const CdmAttachedCB& cdm_attached_cb, CdmContext* cdm_context,
-    bool success) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  if (success) cdm_context_ = cdm_context;
-  cdm_attached_cb.Run(success);
-}
-
-void PipelineImpl::RendererWrapper::CheckPlaybackEnded() {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  if (shared_state_.renderer && !renderer_ended_) return;
-
-  if (text_renderer_ && text_renderer_->HasTracks() && !text_renderer_ended_)
-    return;
-
-  DCHECK_EQ(status_, PIPELINE_OK);
-  main_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&PipelineImpl::OnEnded, weak_pipeline_));
-}
-
-void PipelineImpl::RendererWrapper::SetState(State next_state) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-  DVLOG(1) << PipelineImpl::GetStateString(state_) << " -> "
-           << PipelineImpl::GetStateString(next_state);
-
-  state_ = next_state;
-  media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state));
-}
-
-void PipelineImpl::RendererWrapper::CompleteSeek(base::TimeDelta seek_time,
-                                                 PipelineStatus status) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-  DCHECK(state_ == kStarting || state_ == kSeeking || state_ == kResuming);
-
-  if (state_ == kStarting) {
-    UMA_HISTOGRAM_ENUMERATION("Media.PipelineStatus.Start", status,
-                              PIPELINE_STATUS_MAX + 1);
-  }
-
-  DCHECK(pending_callbacks_);
-  pending_callbacks_.reset();
-
-  if (status != PIPELINE_OK) {
-    OnPipelineError(status);
-    return;
-  }
-
-  shared_state_.renderer->StartPlayingFrom(
-      std::max(seek_time, demuxer_->GetStartTime()));
-  {
-    base::AutoLock auto_lock(shared_state_lock_);
-    shared_state_.suspend_timestamp = kNoTimestamp;
-  }
-
-  if (text_renderer_) text_renderer_->StartPlaying();
-
-  shared_state_.renderer->SetPlaybackRate(playback_rate_);
-  shared_state_.renderer->SetVolume(volume_);
-
-  SetState(kPlaying);
-  main_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&PipelineImpl::OnSeekDone, weak_pipeline_));
-}
-
-void PipelineImpl::RendererWrapper::CompleteSuspend(PipelineStatus status) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-  DCHECK_EQ(kSuspending, state_);
-
-  DCHECK(pending_callbacks_);
-  pending_callbacks_.reset();
-
-  // In case we are suspending or suspended, the error may be recoverable,
-  // so don't propagate it now, instead let the subsequent seek during resume
-  // propagate it if it's unrecoverable.
-  LOG_IF(WARNING, status != PIPELINE_OK)
-      << "Encountered pipeline error while suspending: " << status;
-
-  DestroyRenderer();
-  {
-    base::AutoLock auto_lock(shared_state_lock_);
-    shared_state_.statistics.audio_memory_usage = 0;
-    shared_state_.statistics.video_memory_usage = 0;
-  }
-
-  // Abort any reads the renderer may have kicked off.
-  demuxer_->AbortPendingReads();
-
-  SetState(kSuspended);
-  main_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&PipelineImpl::OnSuspendDone, weak_pipeline_));
-}
-
-void PipelineImpl::RendererWrapper::InitializeDemuxer(
-    const PipelineStatusCB& done_cb) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  demuxer_->Initialize(this, done_cb, !!text_renderer_);
-}
-
-void PipelineImpl::RendererWrapper::InitializeRenderer(
-    const PipelineStatusCB& done_cb) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  if (!demuxer_->GetStream(DemuxerStream::AUDIO) &&
-      !demuxer_->GetStream(DemuxerStream::VIDEO)) {
-    done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER);
-    return;
-  }
-
-  if (cdm_context_)
-    shared_state_.renderer->SetCdm(cdm_context_,
-                                   base::Bind(&IgnoreCdmAttached));
-
-  shared_state_.renderer->Initialize(demuxer_, this, done_cb);
-}
-
-void PipelineImpl::RendererWrapper::DestroyRenderer() {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  // Destroy the renderer outside the lock scope to avoid holding the lock
-  // while renderer is being destroyed (in case Renderer destructor is costly).
-  std::unique_ptr<Renderer> renderer;
-  {
-    base::AutoLock auto_lock(shared_state_lock_);
-    renderer.swap(shared_state_.renderer);
-  }
-}
-
-void PipelineImpl::RendererWrapper::ReportMetadata() {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
-
-  PipelineMetadata metadata;
-  metadata.timeline_offset = demuxer_->GetTimelineOffset();
-  DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
-  if (stream) {
-    metadata.has_video = true;
-    metadata.natural_size = stream->video_decoder_config().natural_size();
-    metadata.video_rotation = stream->video_rotation();
-  }
-  if (demuxer_->GetStream(DemuxerStream::AUDIO)) {
-    metadata.has_audio = true;
-  }
-
-  main_task_runner_->PostTask(FROM_HERE, base::Bind(&PipelineImpl::OnMetadata,
-                                                    weak_pipeline_, metadata));
-}
-
-PipelineImpl::PipelineImpl(
-    const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
-    MediaLog* media_log)
-    : media_task_runner_(media_task_runner),
-      media_log_(media_log),
-      client_(NULL),
-      playback_rate_(kDefaultPlaybackRate),
-      volume_(kDefaultVolume),
-      weak_factory_(this) {
-  DVLOG(2) << __func__;
-  renderer_wrapper_.reset(new RendererWrapper(media_task_runner_, media_log_));
-}
-
-PipelineImpl::~PipelineImpl() {
-  DVLOG(2) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(!client_) << "Stop() must complete before destroying object";
-  DCHECK(seek_cb_.is_null());
-  DCHECK(suspend_cb_.is_null());
-  DCHECK(!weak_factory_.HasWeakPtrs());
-
-  // RendererWrapper is deleted on the media thread.
-  media_task_runner_->DeleteSoon(FROM_HERE, renderer_wrapper_.release());
-}
-
-void PipelineImpl::Start(Demuxer* demuxer, std::unique_ptr<Renderer> renderer,
-                         Client* client, const PipelineStatusCB& seek_cb) {
-  DVLOG(2) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(demuxer);
-  DCHECK(renderer);
-  DCHECK(client);
-  DCHECK(!seek_cb.is_null());
-
-  DCHECK(!client_);
-  DCHECK(seek_cb_.is_null());
-  client_ = client;
-  seek_cb_ = seek_cb;
-  last_media_time_ = base::TimeDelta();
-
-  std::unique_ptr<TextRenderer> text_renderer;
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableInbandTextTracks)) {
-    text_renderer.reset(new TextRenderer(
-        media_task_runner_,
-        BindToCurrentLoop(base::Bind(&PipelineImpl::OnAddTextTrack,
-                                     weak_factory_.GetWeakPtr()))));
-  }
-
-  media_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&RendererWrapper::Start,
-                 base::Unretained(renderer_wrapper_.get()), demuxer,
-                 base::Passed(&renderer), base::Passed(&text_renderer),
-                 weak_factory_.GetWeakPtr()));
-}
-
-void PipelineImpl::Stop() {
-  DVLOG(2) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  if (!IsRunning()) {
-    DVLOG(2) << "Media pipeline isn't running. Ignoring Stop()";
-    return;
-  }
-
-  if (media_task_runner_->BelongsToCurrentThread()) {
-    // This path is executed by unittests that share media and main threads.
-    base::Closure stop_cb = base::Bind(&base::DoNothing);
-    media_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&RendererWrapper::Stop,
-                   base::Unretained(renderer_wrapper_.get()), stop_cb));
-  } else {
-    // This path is executed by production code where the two task runners -
-    // main and media - live on different threads.
-    //
-    // TODO(alokp): We should not have to wait for the RendererWrapper::Stop.
-    // RendererWrapper holds a raw reference to Demuxer, which in turn holds a
-    // raw reference to DataSource. Both Demuxer and DataSource need to live
-    // until RendererWrapper is stopped. If RendererWrapper owned Demuxer and
-    // Demuxer owned DataSource, we could simply let RendererWrapper get lazily
-    // destroyed on the media thread.
-    base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::AUTOMATIC,
-                               base::WaitableEvent::InitialState::NOT_SIGNALED);
-    base::Closure stop_cb =
-        base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter));
-    // If posting the task fails or the posted task fails to run,
-    // we will wait here forever. So add a CHECK to make sure we do not run
-    // into those situations.
-    CHECK(media_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&RendererWrapper::Stop,
-                   base::Unretained(renderer_wrapper_.get()), stop_cb)));
-    waiter.Wait();
-  }
-
-  // Once the pipeline is stopped, nothing is reported back to the client.
-  // Reset all callbacks and client handle.
-  seek_cb_.Reset();
-  suspend_cb_.Reset();
-  client_ = NULL;
-
-  // Invalidate self weak pointers effectively canceling all pending
-  // notifications in the message queue.
-  weak_factory_.InvalidateWeakPtrs();
-}
-
-void PipelineImpl::Seek(base::TimeDelta time, const PipelineStatusCB& seek_cb) {
-  DVLOG(2) << __func__ << " to " << time.InMicroseconds();
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(!seek_cb.is_null());
-
-  if (!IsRunning()) {
-    DLOG(ERROR) << "Media pipeline isn't running. Ignoring Seek().";
-    return;
-  }
-
-  DCHECK(seek_cb_.is_null());
-  seek_cb_ = seek_cb;
-  last_media_time_ = base::TimeDelta();
-  media_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&RendererWrapper::Seek,
-                            base::Unretained(renderer_wrapper_.get()), time));
-}
-
-void PipelineImpl::Suspend(const PipelineStatusCB& suspend_cb) {
-  DVLOG(2) << __func__;
-  DCHECK(!suspend_cb.is_null());
-
-  DCHECK(IsRunning());
-  DCHECK(suspend_cb_.is_null());
-  suspend_cb_ = suspend_cb;
-
-  media_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&RendererWrapper::Suspend,
-                            base::Unretained(renderer_wrapper_.get())));
-}
-
-void PipelineImpl::Resume(std::unique_ptr<Renderer> renderer,
-                          base::TimeDelta time,
-                          const PipelineStatusCB& seek_cb) {
-  DVLOG(2) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(renderer);
-  DCHECK(!seek_cb.is_null());
-
-  DCHECK(IsRunning());
-  DCHECK(seek_cb_.is_null());
-  seek_cb_ = seek_cb;
-  last_media_time_ = base::TimeDelta();
-
-  media_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&RendererWrapper::Resume,
-                            base::Unretained(renderer_wrapper_.get()),
-                            base::Passed(&renderer), time));
-}
-
-bool PipelineImpl::IsRunning() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return !!client_;
-}
-
-double PipelineImpl::GetPlaybackRate() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return playback_rate_;
-}
-
-void PipelineImpl::SetPlaybackRate(double playback_rate) {
-  DVLOG(2) << __func__ << "(" << playback_rate << ")";
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  if (playback_rate < 0.0) return;
-
-  playback_rate_ = playback_rate;
-  media_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&RendererWrapper::SetPlaybackRate,
-                 base::Unretained(renderer_wrapper_.get()), playback_rate_));
-}
-
-float PipelineImpl::GetVolume() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return volume_;
-}
-
-void PipelineImpl::SetVolume(float volume) {
-  DVLOG(2) << __func__ << "(" << volume << ")";
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  if (volume < 0.0f || volume > 1.0f) return;
-
-  volume_ = volume;
-  media_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&RendererWrapper::SetVolume,
-                 base::Unretained(renderer_wrapper_.get()), volume_));
-}
-
-base::TimeDelta PipelineImpl::GetMediaTime() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  base::TimeDelta media_time = renderer_wrapper_->GetMediaTime();
-
-  // Clamp current media time to the last reported value, this prevents higher
-  // level clients from seeing time go backwards based on inaccurate or spurious
-  // delay values reported to the AudioClock.
-  //
-  // It is expected that such events are transient and will be recovered as
-  // rendering continues over time.
-  if (media_time < last_media_time_) {
-    DVLOG(2) << __func__ << ": actual=" << media_time
-             << " clamped=" << last_media_time_;
-    return last_media_time_;
-  }
-
-  DVLOG(3) << __FUNCTION__ << ": " << media_time.InMilliseconds() << " ms";
-  last_media_time_ = media_time;
-  return last_media_time_;
-}
-
-Ranges<base::TimeDelta> PipelineImpl::GetBufferedTimeRanges() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return renderer_wrapper_->GetBufferedTimeRanges();
-}
-
-base::TimeDelta PipelineImpl::GetMediaDuration() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return duration_;
-}
-
-bool PipelineImpl::DidLoadingProgress() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return renderer_wrapper_->DidLoadingProgress();
-}
-
-PipelineStatistics PipelineImpl::GetStatistics() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return renderer_wrapper_->GetStatistics();
-}
-
-void PipelineImpl::SetCdm(CdmContext* cdm_context,
-                          const CdmAttachedCB& cdm_attached_cb) {
-  DVLOG(2) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(cdm_context);
-  DCHECK(!cdm_attached_cb.is_null());
-
-  media_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&RendererWrapper::SetCdm,
-                 base::Unretained(renderer_wrapper_.get()), cdm_context,
-                 media::BindToCurrentLoop(cdm_attached_cb)));
-}
-
-#define RETURN_STRING(state) \
-  case state:                \
-    return #state;
-
-// static
-const char* PipelineImpl::GetStateString(State state) {
-  switch (state) {
-    RETURN_STRING(kCreated);
-    RETURN_STRING(kStarting);
-    RETURN_STRING(kSeeking);
-    RETURN_STRING(kPlaying);
-    RETURN_STRING(kStopping);
-    RETURN_STRING(kStopped);
-    RETURN_STRING(kSuspending);
-    RETURN_STRING(kSuspended);
-    RETURN_STRING(kResuming);
-  }
-  NOTREACHED();
-  return "INVALID";
-}
-
-#undef RETURN_STRING
-
-void PipelineImpl::OnError(PipelineStatus error) {
-  DVLOG(2) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!";
-  DCHECK(IsRunning());
-
-  // If the error happens during starting/seeking/suspending/resuming,
-  // report the error via the completion callback for those tasks.
-  // Else report error via the client interface.
-  if (!seek_cb_.is_null()) {
-    base::ResetAndReturn(&seek_cb_).Run(error);
-  } else if (!suspend_cb_.is_null()) {
-    base::ResetAndReturn(&suspend_cb_).Run(error);
-  } else {
-    DCHECK(client_);
-    client_->OnError(error);
-  }
-
-  // Any kind of error stops the pipeline.
-  Stop();
-}
-
-void PipelineImpl::OnEnded() {
-  DVLOG(2) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(IsRunning());
-
-  DCHECK(client_);
-  client_->OnEnded();
-}
-
-void PipelineImpl::OnMetadata(PipelineMetadata metadata) {
-  DVLOG(2) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(IsRunning());
-
-  DCHECK(client_);
-  client_->OnMetadata(metadata);
-}
-
-void PipelineImpl::OnBufferingStateChange(BufferingState state) {
-  DVLOG(2) << __func__ << "(" << state << ")";
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(IsRunning());
-
-  DCHECK(client_);
-  client_->OnBufferingStateChange(state);
-}
-
-void PipelineImpl::OnDurationChange(base::TimeDelta duration) {
-  DVLOG(2) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(IsRunning());
-
-  duration_ = duration;
-
-  DCHECK(client_);
-  client_->OnDurationChange();
-}
-
-void PipelineImpl::OnAddTextTrack(const TextTrackConfig& config,
-                                  const AddTextTrackDoneCB& done_cb) {
-  DVLOG(2) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(IsRunning());
-
-  DCHECK(client_);
-  client_->OnAddTextTrack(config, done_cb);
-}
-
-void PipelineImpl::OnWaitingForDecryptionKey() {
-  DVLOG(2) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(IsRunning());
-
-  DCHECK(client_);
-  client_->OnWaitingForDecryptionKey();
-}
-
-void PipelineImpl::OnVideoNaturalSizeChange(const gfx::Size& size) {
-  DVLOG(2) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(IsRunning());
-
-  DCHECK(client_);
-  client_->OnVideoNaturalSizeChange(size);
-}
-
-void PipelineImpl::OnVideoOpacityChange(bool opaque) {
-  DVLOG(2) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(IsRunning());
-
-  DCHECK(client_);
-  client_->OnVideoOpacityChange(opaque);
-}
-
-void PipelineImpl::OnSeekDone() {
-  DVLOG(3) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(IsRunning());
-
-  DCHECK(!seek_cb_.is_null());
-  base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
-}
-
-void PipelineImpl::OnSuspendDone() {
-  DVLOG(3) << __func__;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(IsRunning());
-
-  DCHECK(!suspend_cb_.is_null());
-  base::ResetAndReturn(&suspend_cb_).Run(PIPELINE_OK);
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/pipeline_impl.h b/src/cobalt/media/base/pipeline_impl.h
deleted file mode 100644
index cad17f3..0000000
--- a/src/cobalt/media/base/pipeline_impl.h
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_PIPELINE_IMPL_H_
-#define COBALT_MEDIA_BASE_PIPELINE_IMPL_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/pipeline.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace cobalt {
-namespace media {
-
-class MediaLog;
-class TextRenderer;
-
-// Pipeline runs the media pipeline.  Filters are created and called on the
-// task runner injected into this object. Pipeline works like a state
-// machine to perform asynchronous initialization, pausing, seeking and playing.
-//
-// Here's a state diagram that describes the lifetime of this object.
-//
-//   [ *Created ]                       [ Any State ]
-//         | Start()                         | Stop() / SetError()
-//         V                                 V
-//   [ Starting ]                       [ Stopping ]
-//         |                                 |
-//         V                                 V
-//   [ Playing ] <---------.            [ Stopped ]
-//     |     | Seek()      |
-//     |     V             |
-//     |   [ Seeking ] ----'
-//     |                   ^
-//     | Suspend()         |
-//     V                   |
-//   [ Suspending ]        |
-//     |                   |
-//     V                   |
-//   [ Suspended ]         |
-//     | Resume()          |
-//     V                   |
-//   [ Resuming ] ---------'
-//
-// Initialization is a series of state transitions from "Created" through each
-// filter initialization state.  When all filter initialization states have
-// completed, we simulate a Seek() to the beginning of the media to give filters
-// a chance to preroll. From then on the normal Seek() transitions are carried
-// out and we start playing the media.
-//
-// If any error ever happens, this object will transition to the "Error" state
-// from any state. If Stop() is ever called, this object will transition to
-// "Stopped" state.
-//
-// TODO(sandersd): It should be possible to pass through Suspended when going
-// from InitDemuxer to InitRenderer, thereby eliminating the Resuming state.
-// Some annoying differences between the two paths need to be removed first.
-class MEDIA_EXPORT PipelineImpl : public Pipeline {
- public:
-  // Constructs a media pipeline that will execute media tasks on
-  // |media_task_runner|.
-  PipelineImpl(
-      const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
-      MediaLog* media_log);
-  ~PipelineImpl() OVERRIDE;
-
-  // Pipeline implementation.
-  void Start(Demuxer* demuxer, scoped_ptr<Renderer> renderer, Client* client,
-             const PipelineStatusCB& seek_cb) OVERRIDE;
-  void Stop() OVERRIDE;
-  void Seek(base::TimeDelta time, const PipelineStatusCB& seek_cb) OVERRIDE;
-  void Suspend(const PipelineStatusCB& suspend_cb) OVERRIDE;
-  void Resume(scoped_ptr<Renderer> renderer, base::TimeDelta time,
-              const PipelineStatusCB& seek_cb) OVERRIDE;
-  bool IsRunning() const OVERRIDE;
-  double GetPlaybackRate() const OVERRIDE;
-  void SetPlaybackRate(double playback_rate) OVERRIDE;
-  float GetVolume() const OVERRIDE;
-  void SetVolume(float volume) OVERRIDE;
-  base::TimeDelta GetMediaTime() const OVERRIDE;
-  Ranges<base::TimeDelta> GetBufferedTimeRanges() const OVERRIDE;
-  base::TimeDelta GetMediaDuration() const OVERRIDE;
-  bool DidLoadingProgress() OVERRIDE;
-  PipelineStatistics GetStatistics() const OVERRIDE;
-  void SetCdm(CdmContext* cdm_context,
-              const CdmAttachedCB& cdm_attached_cb) OVERRIDE;
-
-  // |enabledTrackIds| contains track ids of enabled audio tracks.
-  void OnEnabledAudioTracksChanged(
-      const std::vector<MediaTrack::Id>& enabledTrackIds) OVERRIDE;
-
-  // |trackId| either empty, which means no video track is selected, or contain
-  // one element - the selected video track id.
-  void OnSelectedVideoTrackChanged(
-      const std::vector<MediaTrack::Id>& selectedTrackId) OVERRIDE;
-
- private:
-  friend class MediaLog;
-  class RendererWrapper;
-
-  // Pipeline states, as described above.
-  // TODO(alokp): Move this to RendererWrapper after removing the references
-  // from MediaLog.
-  enum State {
-    kCreated,
-    kStarting,
-    kSeeking,
-    kPlaying,
-    kStopping,
-    kStopped,
-    kSuspending,
-    kSuspended,
-    kResuming,
-  };
-  static const char* GetStateString(State state);
-
-  // Notifications from RendererWrapper.
-  void OnError(PipelineStatus error);
-  void OnEnded();
-  void OnMetadata(PipelineMetadata metadata);
-  void OnBufferingStateChange(BufferingState state);
-  void OnDurationChange(base::TimeDelta duration);
-  void OnAddTextTrack(const TextTrackConfig& config,
-                      const AddTextTrackDoneCB& done_cb);
-  void OnWaitingForDecryptionKey();
-  void OnVideoNaturalSizeChange(const gfx::Size& size);
-  void OnVideoOpacityChange(bool opaque);
-
-  // Task completion callbacks from RendererWrapper.
-  void OnSeekDone();
-  void OnSuspendDone();
-
-  // Parameters passed in the constructor.
-  const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
-  const scoped_refptr<MediaLog> media_log_;
-
-  // Pipeline client. Valid only while the pipeline is running.
-  Client* client_;
-
-  // RendererWrapper instance that runs on the media thread.
-  scoped_ptr<RendererWrapper> renderer_wrapper_;
-
-  // Temporary callback used for Start(), Seek(), and Resume().
-  PipelineStatusCB seek_cb_;
-
-  // Temporary callback used for Suspend().
-  PipelineStatusCB suspend_cb_;
-
-  // Current playback rate (>= 0.0). This value is set immediately via
-  // SetPlaybackRate() and a task is dispatched on the task runner to notify
-  // the filters.
-  double playback_rate_;
-
-  // Current volume level (from 0.0f to 1.0f). This value is set immediately
-  // via SetVolume() and a task is dispatched on the task runner to notify the
-  // filters.
-  float volume_;
-
-  // Current duration as reported by Demuxer.
-  base::TimeDelta duration_;
-
-  // Set by GetMediaTime(), used to prevent the current media time value as
-  // reported to JavaScript from going backwards in time.
-  mutable base::TimeDelta last_media_time_;
-
-  base::ThreadChecker thread_checker_;
-  base::WeakPtrFactory<PipelineImpl> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(PipelineImpl);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_PIPELINE_IMPL_H_
diff --git a/src/cobalt/media/base/pipeline_impl_unittest.cc b/src/cobalt/media/base/pipeline_impl_unittest.cc
deleted file mode 100644
index 9815839..0000000
--- a/src/cobalt/media/base/pipeline_impl_unittest.cc
+++ /dev/null
@@ -1,1095 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/pipeline_impl.h"
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/clock.h"
-#include "base/location.h"
-#include "base/message_loop.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "base/threading/simple_thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "cobalt/media/base/fake_text_track_stream.h"
-#include "cobalt/media/base/gmock_callback_support.h"
-#include "cobalt/media/base/media_log.h"
-#include "cobalt/media/base/mock_filters.h"
-#include "cobalt/media/base/test_helpers.h"
-#include "cobalt/media/base/text_renderer.h"
-#include "cobalt/media/base/text_track_config.h"
-#include "cobalt/media/base/time_delta_interpolator.h"
-#include "starboard/types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/size.h"
-
-using ::testing::_;
-using ::testing::AnyNumber;
-using ::testing::DeleteArg;
-using ::testing::DoAll;
-// TODO(scherkus): Remove InSequence after refactoring Pipeline.
-using ::testing::InSequence;
-using ::testing::Invoke;
-using ::testing::InvokeWithoutArgs;
-using ::testing::Mock;
-using ::testing::NotNull;
-using ::testing::Return;
-using ::testing::SaveArg;
-using ::testing::StrictMock;
-using ::testing::WithArg;
-
-namespace cobalt {
-namespace media {
-
-ACTION_P(SetDemuxerProperties, duration) { arg0->SetDuration(duration); }
-
-ACTION_P(Stop, pipeline) { pipeline->Stop(); }
-
-ACTION_P2(SetError, renderer_client, status) {
-  (*renderer_client)->OnError(status);
-}
-
-ACTION_P2(SetBufferingState, renderer_client, buffering_state) {
-  (*renderer_client)->OnBufferingStateChange(buffering_state);
-}
-
-ACTION_TEMPLATE(PostCallback, HAS_1_TEMPLATE_PARAMS(int, k),
-                AND_1_VALUE_PARAMS(p0)) {
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(::std::tr1::get<k>(args), p0));
-}
-
-// TODO(scherkus): even though some filters are initialized on separate
-// threads these test aren't flaky... why?  It's because filters' Initialize()
-// is executed on |message_loop_| and the mock filters instantly call
-// InitializationComplete(), which keeps the pipeline humming along.  If
-// either filters don't call InitializationComplete() immediately or filter
-// initialization is moved to a separate thread this test will become flaky.
-class PipelineImplTest : public ::testing::Test {
- public:
-  // Used for setting expectations on pipeline callbacks.  Using a StrictMock
-  // also lets us test for missing callbacks.
-  class CallbackHelper : public MockPipelineClient {
-   public:
-    CallbackHelper() {}
-    virtual ~CallbackHelper() {}
-
-    MOCK_METHOD1(OnStart, void(PipelineStatus));
-    MOCK_METHOD1(OnSeek, void(PipelineStatus));
-    MOCK_METHOD1(OnSuspend, void(PipelineStatus));
-    MOCK_METHOD1(OnResume, void(PipelineStatus));
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
-  };
-
-  PipelineImplTest()
-      : pipeline_(
-            new PipelineImpl(message_loop_.task_runner(), new MediaLog())),
-        demuxer_(new StrictMock<MockDemuxer>()),
-        demuxer_host_(NULL),
-        scoped_renderer_(new StrictMock<MockRenderer>()),
-        renderer_(scoped_renderer_.get()),
-        renderer_client_(NULL) {
-    // SetDemuxerExpectations() adds overriding expectations for expected
-    // non-NULL streams.
-    DemuxerStream* null_pointer = NULL;
-    EXPECT_CALL(*demuxer_, GetStream(_)).WillRepeatedly(Return(null_pointer));
-
-    EXPECT_CALL(*demuxer_, GetTimelineOffset())
-        .WillRepeatedly(Return(base::Time()));
-
-    EXPECT_CALL(*renderer_, GetMediaTime())
-        .WillRepeatedly(Return(base::TimeDelta()));
-
-    EXPECT_CALL(*demuxer_, GetStartTime()).WillRepeatedly(Return(start_time_));
-  }
-
-  virtual ~PipelineImplTest() {
-    if (pipeline_->IsRunning()) {
-      ExpectDemuxerStop();
-
-      // The mock demuxer doesn't stop the fake text track stream,
-      // so just stop it manually.
-      if (text_stream_) text_stream_->Stop();
-
-      pipeline_->Stop();
-    }
-
-    pipeline_.reset();
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void OnDemuxerError() { demuxer_host_->OnDemuxerError(PIPELINE_ERROR_ABORT); }
-
- protected:
-  // Sets up expectations to allow the demuxer to initialize.
-  typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
-  void SetDemuxerExpectations(MockDemuxerStreamVector* streams,
-                              const base::TimeDelta& duration) {
-    EXPECT_CALL(callbacks_, OnDurationChange());
-    EXPECT_CALL(*demuxer_, Initialize(_, _, _))
-        .WillOnce(DoAll(SaveArg<0>(&demuxer_host_),
-                        SetDemuxerProperties(duration),
-                        PostCallback<1>(PIPELINE_OK)));
-
-    // Configure the demuxer to return the streams.
-    for (size_t i = 0; i < streams->size(); ++i) {
-      DemuxerStream* stream = (*streams)[i];
-      EXPECT_CALL(*demuxer_, GetStream(stream->type()))
-          .WillRepeatedly(Return(stream));
-    }
-  }
-
-  void SetDemuxerExpectations(MockDemuxerStreamVector* streams) {
-    // Initialize with a default non-zero duration.
-    SetDemuxerExpectations(streams, base::TimeDelta::FromSeconds(10));
-  }
-
-  std::unique_ptr<StrictMock<MockDemuxerStream>> CreateStream(
-      DemuxerStream::Type type) {
-    std::unique_ptr<StrictMock<MockDemuxerStream>> stream(
-        new StrictMock<MockDemuxerStream>(type));
-    return stream;
-  }
-
-  // Sets up expectations to allow the video renderer to initialize.
-  void SetRendererExpectations() {
-    EXPECT_CALL(*renderer_, Initialize(_, _, _))
-        .WillOnce(
-            DoAll(SaveArg<1>(&renderer_client_), PostCallback<2>(PIPELINE_OK)));
-    EXPECT_CALL(*renderer_, HasAudio()).WillRepeatedly(Return(audio_stream()));
-    EXPECT_CALL(*renderer_, HasVideo()).WillRepeatedly(Return(video_stream()));
-  }
-
-  void AddTextStream() {
-    EXPECT_CALL(callbacks_, OnAddTextTrack(_, _))
-        .WillOnce(Invoke(this, &PipelineImplTest::DoOnAddTextTrack));
-    demuxer_host_->AddTextStream(text_stream(),
-                                 TextTrackConfig(kTextSubtitles, "", "", ""));
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void StartPipeline() {
-    EXPECT_CALL(callbacks_, OnWaitingForDecryptionKey()).Times(0);
-    pipeline_->Start(
-        demuxer_.get(), std::move(scoped_renderer_), &callbacks_,
-        base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)));
-  }
-
-  // Sets up expectations on the callback and initializes the pipeline. Called
-  // after tests have set expectations any filters they wish to use.
-  void StartPipelineAndExpect(PipelineStatus start_status) {
-    EXPECT_CALL(callbacks_, OnStart(start_status));
-
-    if (start_status == PIPELINE_OK) {
-      EXPECT_CALL(callbacks_, OnMetadata(_)).WillOnce(SaveArg<0>(&metadata_));
-      EXPECT_CALL(*renderer_, SetPlaybackRate(0.0));
-      EXPECT_CALL(*renderer_, SetVolume(1.0f));
-      EXPECT_CALL(*renderer_, StartPlayingFrom(start_time_))
-          .WillOnce(
-              SetBufferingState(&renderer_client_, BUFFERING_HAVE_ENOUGH));
-      EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
-    }
-
-    StartPipeline();
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void CreateAudioStream() {
-    audio_stream_ = CreateStream(DemuxerStream::AUDIO);
-  }
-
-  void CreateVideoStream() {
-    video_stream_ = CreateStream(DemuxerStream::VIDEO);
-    video_stream_->set_video_decoder_config(video_decoder_config_);
-  }
-
-  void CreateTextStream() {
-    std::unique_ptr<FakeTextTrackStream> text_stream(new FakeTextTrackStream());
-    EXPECT_CALL(*text_stream, OnRead()).Times(AnyNumber());
-    text_stream_ = std::move(text_stream);
-  }
-
-  MockDemuxerStream* audio_stream() { return audio_stream_.get(); }
-
-  MockDemuxerStream* video_stream() { return video_stream_.get(); }
-
-  FakeTextTrackStream* text_stream() { return text_stream_.get(); }
-
-  void ExpectSeek(const base::TimeDelta& seek_time, bool underflowed) {
-    EXPECT_CALL(*demuxer_, AbortPendingReads());
-    EXPECT_CALL(*demuxer_, Seek(seek_time, _))
-        .WillOnce(RunCallback<1>(PIPELINE_OK));
-
-    EXPECT_CALL(*renderer_, Flush(_))
-        .WillOnce(
-            DoAll(SetBufferingState(&renderer_client_, BUFFERING_HAVE_NOTHING),
-                  RunClosure<0>()));
-    EXPECT_CALL(*renderer_, SetPlaybackRate(_));
-    EXPECT_CALL(*renderer_, SetVolume(_));
-    EXPECT_CALL(*renderer_, StartPlayingFrom(seek_time))
-        .WillOnce(SetBufferingState(&renderer_client_, BUFFERING_HAVE_ENOUGH));
-    EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
-
-    // We expect a successful seek callback followed by a buffering update.
-    EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
-    EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
-  }
-
-  void DoSeek(const base::TimeDelta& seek_time) {
-    pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
-                                          base::Unretained(&callbacks_)));
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void ExpectSuspend() {
-    EXPECT_CALL(*demuxer_, AbortPendingReads());
-    EXPECT_CALL(*renderer_, SetPlaybackRate(0));
-    EXPECT_CALL(callbacks_, OnSuspend(PIPELINE_OK));
-  }
-
-  void DoSuspend() {
-    pipeline_->Suspend(
-        base::Bind(&CallbackHelper::OnSuspend, base::Unretained(&callbacks_)));
-    base::RunLoop().RunUntilIdle();
-
-    // |renderer_| has been deleted, replace it.
-    scoped_renderer_.reset(new StrictMock<MockRenderer>()),
-        renderer_ = scoped_renderer_.get();
-  }
-
-  void ExpectResume(const base::TimeDelta& seek_time) {
-    SetRendererExpectations();
-    EXPECT_CALL(*demuxer_, Seek(seek_time, _))
-        .WillOnce(RunCallback<1>(PIPELINE_OK));
-    EXPECT_CALL(*renderer_, SetPlaybackRate(_));
-    EXPECT_CALL(*renderer_, SetVolume(_));
-    EXPECT_CALL(*renderer_, StartPlayingFrom(seek_time))
-        .WillOnce(SetBufferingState(&renderer_client_, BUFFERING_HAVE_ENOUGH));
-    EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
-    EXPECT_CALL(callbacks_, OnResume(PIPELINE_OK));
-  }
-
-  void DoResume(const base::TimeDelta& seek_time) {
-    pipeline_->Resume(
-        std::move(scoped_renderer_), seek_time,
-        base::Bind(&CallbackHelper::OnResume, base::Unretained(&callbacks_)));
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void ExpectDemuxerStop() {
-    if (demuxer_) EXPECT_CALL(*demuxer_, Stop());
-  }
-
-  void DoOnAddTextTrack(const TextTrackConfig& config,
-                        const AddTextTrackDoneCB& done_cb) {
-    std::unique_ptr<TextTrack> text_track(new MockTextTrack);
-    done_cb.Run(std::move(text_track));
-  }
-
-  void RunBufferedTimeRangesTest(const base::TimeDelta duration) {
-    EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
-    EXPECT_FALSE(pipeline_->DidLoadingProgress());
-
-    Ranges<base::TimeDelta> ranges;
-    ranges.Add(base::TimeDelta(), duration);
-    demuxer_host_->OnBufferedTimeRangesChanged(ranges);
-    base::RunLoop().RunUntilIdle();
-
-    EXPECT_TRUE(pipeline_->DidLoadingProgress());
-    EXPECT_FALSE(pipeline_->DidLoadingProgress());
-    EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
-    EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
-    EXPECT_EQ(duration, pipeline_->GetBufferedTimeRanges().end(0));
-  }
-
-  // Fixture members.
-  StrictMock<CallbackHelper> callbacks_;
-  base::SimpleTestTickClock test_tick_clock_;
-  base::MessageLoop message_loop_;
-  std::unique_ptr<PipelineImpl> pipeline_;
-
-  std::unique_ptr<StrictMock<MockDemuxer>> demuxer_;
-  DemuxerHost* demuxer_host_;
-  std::unique_ptr<StrictMock<MockRenderer>> scoped_renderer_;
-  StrictMock<MockRenderer>* renderer_;
-  StrictMock<CallbackHelper> text_renderer_callbacks_;
-  TextRenderer* text_renderer_;
-  std::unique_ptr<StrictMock<MockDemuxerStream>> audio_stream_;
-  std::unique_ptr<StrictMock<MockDemuxerStream>> video_stream_;
-  std::unique_ptr<FakeTextTrackStream> text_stream_;
-  RendererClient* renderer_client_;
-  VideoDecoderConfig video_decoder_config_;
-  PipelineMetadata metadata_;
-  base::TimeDelta start_time_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PipelineImplTest);
-};
-
-// Test that playback controls methods no-op when the pipeline hasn't been
-// started.
-TEST_F(PipelineImplTest, NotStarted) {
-  const base::TimeDelta kZero;
-
-  EXPECT_FALSE(pipeline_->IsRunning());
-
-  // Setting should still work.
-  EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
-  pipeline_->SetPlaybackRate(-1.0);
-  EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
-  pipeline_->SetPlaybackRate(1.0);
-  EXPECT_EQ(1.0f, pipeline_->GetPlaybackRate());
-
-  // Setting should still work.
-  EXPECT_EQ(1.0f, pipeline_->GetVolume());
-  pipeline_->SetVolume(-1.0f);
-  EXPECT_EQ(1.0f, pipeline_->GetVolume());
-  pipeline_->SetVolume(0.0f);
-  EXPECT_EQ(0.0f, pipeline_->GetVolume());
-
-  EXPECT_TRUE(kZero == pipeline_->GetMediaTime());
-  EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
-  EXPECT_TRUE(kZero == pipeline_->GetMediaDuration());
-}
-
-TEST_F(PipelineImplTest, NeverInitializes) {
-  // Don't execute the callback passed into Initialize().
-  EXPECT_CALL(*demuxer_, Initialize(_, _, _));
-
-  // This test hangs during initialization by never calling
-  // InitializationComplete().  StrictMock<> will ensure that the callback is
-  // never executed.
-  StartPipeline();
-  base::RunLoop().RunUntilIdle();
-
-  // Because our callback will get executed when the test tears down, we'll
-  // verify that nothing has been called, then set our expectation for the call
-  // made during tear down.
-  Mock::VerifyAndClear(&callbacks_);
-}
-
-TEST_F(PipelineImplTest, StopWithoutStart) {
-  pipeline_->Stop();
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(PipelineImplTest, StartThenStopImmediately) {
-  EXPECT_CALL(*demuxer_, Initialize(_, _, _))
-      .WillOnce(PostCallback<1>(PIPELINE_OK));
-  EXPECT_CALL(*demuxer_, Stop());
-  EXPECT_CALL(callbacks_, OnMetadata(_));
-
-  EXPECT_CALL(callbacks_, OnStart(_));
-  StartPipeline();
-  base::RunLoop().RunUntilIdle();
-
-  pipeline_->Stop();
-}
-
-TEST_F(PipelineImplTest, DemuxerErrorDuringStop) {
-  CreateAudioStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(audio_stream());
-
-  SetDemuxerExpectations(&streams);
-  SetRendererExpectations();
-
-  StartPipelineAndExpect(PIPELINE_OK);
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_CALL(*demuxer_, Stop())
-      .WillOnce(InvokeWithoutArgs(this, &PipelineImplTest::OnDemuxerError));
-  pipeline_->Stop();
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(PipelineImplTest, NoStreams) {
-  EXPECT_CALL(*demuxer_, Initialize(_, _, _))
-      .WillOnce(PostCallback<1>(PIPELINE_OK));
-  EXPECT_CALL(*demuxer_, Stop());
-  EXPECT_CALL(callbacks_, OnMetadata(_));
-
-  StartPipelineAndExpect(PIPELINE_ERROR_COULD_NOT_RENDER);
-}
-
-TEST_F(PipelineImplTest, AudioStream) {
-  CreateAudioStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(audio_stream());
-
-  SetDemuxerExpectations(&streams);
-  SetRendererExpectations();
-
-  StartPipelineAndExpect(PIPELINE_OK);
-  EXPECT_TRUE(metadata_.has_audio);
-  EXPECT_FALSE(metadata_.has_video);
-}
-
-TEST_F(PipelineImplTest, VideoStream) {
-  CreateVideoStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(video_stream());
-
-  SetDemuxerExpectations(&streams);
-  SetRendererExpectations();
-
-  StartPipelineAndExpect(PIPELINE_OK);
-  EXPECT_FALSE(metadata_.has_audio);
-  EXPECT_TRUE(metadata_.has_video);
-}
-
-TEST_F(PipelineImplTest, AudioVideoStream) {
-  CreateAudioStream();
-  CreateVideoStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(audio_stream());
-  streams.push_back(video_stream());
-
-  SetDemuxerExpectations(&streams);
-  SetRendererExpectations();
-
-  StartPipelineAndExpect(PIPELINE_OK);
-  EXPECT_TRUE(metadata_.has_audio);
-  EXPECT_TRUE(metadata_.has_video);
-}
-
-TEST_F(PipelineImplTest, VideoTextStream) {
-  CreateVideoStream();
-  CreateTextStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(video_stream());
-
-  SetDemuxerExpectations(&streams);
-  SetRendererExpectations();
-
-  StartPipelineAndExpect(PIPELINE_OK);
-  EXPECT_FALSE(metadata_.has_audio);
-  EXPECT_TRUE(metadata_.has_video);
-
-  AddTextStream();
-}
-
-TEST_F(PipelineImplTest, VideoAudioTextStream) {
-  CreateVideoStream();
-  CreateAudioStream();
-  CreateTextStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(video_stream());
-  streams.push_back(audio_stream());
-
-  SetDemuxerExpectations(&streams);
-  SetRendererExpectations();
-
-  StartPipelineAndExpect(PIPELINE_OK);
-  EXPECT_TRUE(metadata_.has_audio);
-  EXPECT_TRUE(metadata_.has_video);
-
-  AddTextStream();
-}
-
-TEST_F(PipelineImplTest, Seek) {
-  CreateAudioStream();
-  CreateVideoStream();
-  CreateTextStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(audio_stream());
-  streams.push_back(video_stream());
-
-  SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
-  SetRendererExpectations();
-
-  // Initialize then seek!
-  StartPipelineAndExpect(PIPELINE_OK);
-
-  // Every filter should receive a call to Seek().
-  base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
-  ExpectSeek(expected, false);
-  DoSeek(expected);
-}
-
-TEST_F(PipelineImplTest, SeekAfterError) {
-  CreateAudioStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(audio_stream());
-
-  SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
-  SetRendererExpectations();
-
-  // Initialize then seek!
-  StartPipelineAndExpect(PIPELINE_OK);
-
-  EXPECT_CALL(*demuxer_, Stop());
-  EXPECT_CALL(callbacks_, OnError(_));
-  OnDemuxerError();
-  base::RunLoop().RunUntilIdle();
-
-  pipeline_->Seek(
-      base::TimeDelta::FromMilliseconds(100),
-      base::Bind(&CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(PipelineImplTest, SuspendResume) {
-  CreateAudioStream();
-  CreateVideoStream();
-  CreateTextStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(audio_stream());
-  streams.push_back(video_stream());
-
-  SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
-  SetRendererExpectations();
-
-  StartPipelineAndExpect(PIPELINE_OK);
-
-  // Inject some fake memory usage to verify its cleared after suspend.
-  PipelineStatistics stats;
-  stats.audio_memory_usage = 12345;
-  stats.video_memory_usage = 67890;
-  renderer_client_->OnStatisticsUpdate(stats);
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(stats.audio_memory_usage,
-            pipeline_->GetStatistics().audio_memory_usage);
-  EXPECT_EQ(stats.video_memory_usage,
-            pipeline_->GetStatistics().video_memory_usage);
-
-  ExpectSuspend();
-  DoSuspend();
-
-  EXPECT_EQ(0, pipeline_->GetStatistics().audio_memory_usage);
-  EXPECT_EQ(0, pipeline_->GetStatistics().video_memory_usage);
-
-  base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
-  ExpectResume(expected);
-  DoResume(expected);
-}
-
-TEST_F(PipelineImplTest, SetVolume) {
-  CreateAudioStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(audio_stream());
-
-  SetDemuxerExpectations(&streams);
-  SetRendererExpectations();
-
-  // The audio renderer should receive a call to SetVolume().
-  float expected = 0.5f;
-  EXPECT_CALL(*renderer_, SetVolume(expected));
-
-  // Initialize then set volume!
-  StartPipelineAndExpect(PIPELINE_OK);
-  pipeline_->SetVolume(expected);
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(PipelineImplTest, Properties) {
-  CreateVideoStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(video_stream());
-
-  const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
-  SetDemuxerExpectations(&streams, kDuration);
-  SetRendererExpectations();
-
-  StartPipelineAndExpect(PIPELINE_OK);
-  EXPECT_EQ(kDuration.ToInternalValue(),
-            pipeline_->GetMediaDuration().ToInternalValue());
-  EXPECT_FALSE(pipeline_->DidLoadingProgress());
-}
-
-TEST_F(PipelineImplTest, GetBufferedTimeRanges) {
-  CreateVideoStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(video_stream());
-
-  const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
-  SetDemuxerExpectations(&streams, kDuration);
-  SetRendererExpectations();
-
-  StartPipelineAndExpect(PIPELINE_OK);
-  RunBufferedTimeRangesTest(kDuration / 8);
-
-  base::TimeDelta kSeekTime = kDuration / 2;
-  ExpectSeek(kSeekTime, false);
-  DoSeek(kSeekTime);
-
-  EXPECT_FALSE(pipeline_->DidLoadingProgress());
-}
-
-TEST_F(PipelineImplTest, BufferedTimeRangesCanChangeAfterStop) {
-  EXPECT_CALL(*demuxer_, Initialize(_, _, _))
-      .WillOnce(
-          DoAll(SaveArg<0>(&demuxer_host_), PostCallback<1>(PIPELINE_OK)));
-  EXPECT_CALL(*demuxer_, Stop());
-  EXPECT_CALL(callbacks_, OnMetadata(_));
-  EXPECT_CALL(callbacks_, OnStart(_));
-  StartPipeline();
-  base::RunLoop().RunUntilIdle();
-
-  pipeline_->Stop();
-  RunBufferedTimeRangesTest(base::TimeDelta::FromSeconds(5));
-}
-
-TEST_F(PipelineImplTest, EndedCallback) {
-  CreateAudioStream();
-  CreateVideoStream();
-  CreateTextStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(audio_stream());
-  streams.push_back(video_stream());
-
-  SetDemuxerExpectations(&streams);
-  SetRendererExpectations();
-  StartPipelineAndExpect(PIPELINE_OK);
-
-  AddTextStream();
-
-  // The ended callback shouldn't run until all renderers have ended.
-  renderer_client_->OnEnded();
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_CALL(callbacks_, OnEnded());
-  text_stream()->SendEosNotification();
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(PipelineImplTest, ErrorDuringSeek) {
-  CreateAudioStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(audio_stream());
-
-  SetDemuxerExpectations(&streams);
-  SetRendererExpectations();
-  StartPipelineAndExpect(PIPELINE_OK);
-
-  double playback_rate = 1.0;
-  EXPECT_CALL(*renderer_, SetPlaybackRate(playback_rate));
-  pipeline_->SetPlaybackRate(playback_rate);
-  base::RunLoop().RunUntilIdle();
-
-  base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
-
-  EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
-  EXPECT_CALL(*renderer_, Flush(_))
-      .WillOnce(
-          DoAll(SetBufferingState(&renderer_client_, BUFFERING_HAVE_NOTHING),
-                RunClosure<0>()));
-
-  EXPECT_CALL(*demuxer_, AbortPendingReads());
-  EXPECT_CALL(*demuxer_, Seek(seek_time, _))
-      .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
-  EXPECT_CALL(*demuxer_, Stop());
-
-  pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
-                                        base::Unretained(&callbacks_)));
-  EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
-  base::RunLoop().RunUntilIdle();
-}
-
-// Invoked function OnError. This asserts that the pipeline does not enqueue
-// non-teardown related tasks while tearing down.
-static void TestNoCallsAfterError(PipelineImpl* pipeline,
-                                  base::MessageLoop* message_loop,
-                                  PipelineStatus /* status */) {
-  CHECK(pipeline);
-  CHECK(message_loop);
-
-  // When we get to this stage, the message loop should be empty.
-  EXPECT_TRUE(message_loop->IsIdleForTesting());
-
-  // Make calls on pipeline after error has occurred.
-  pipeline->SetPlaybackRate(0.5);
-  pipeline->SetVolume(0.5f);
-
-  // No additional tasks should be queued as a result of these calls.
-  EXPECT_TRUE(message_loop->IsIdleForTesting());
-}
-
-TEST_F(PipelineImplTest, NoMessageDuringTearDownFromError) {
-  CreateAudioStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(audio_stream());
-
-  SetDemuxerExpectations(&streams);
-  SetRendererExpectations();
-  StartPipelineAndExpect(PIPELINE_OK);
-
-  // Trigger additional requests on the pipeline during tear down from error.
-  base::Callback<void(PipelineStatus)> cb =
-      base::Bind(&TestNoCallsAfterError, pipeline_.get(), &message_loop_);
-  ON_CALL(callbacks_, OnError(_))
-      .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run));
-
-  base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
-
-  // Seek() isn't called as the demuxer errors out first.
-  EXPECT_CALL(*renderer_, Flush(_))
-      .WillOnce(
-          DoAll(SetBufferingState(&renderer_client_, BUFFERING_HAVE_NOTHING),
-                RunClosure<0>()));
-  EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
-
-  EXPECT_CALL(*demuxer_, AbortPendingReads());
-  EXPECT_CALL(*demuxer_, Seek(seek_time, _))
-      .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
-  EXPECT_CALL(*demuxer_, Stop());
-
-  pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
-                                        base::Unretained(&callbacks_)));
-  EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(PipelineImplTest, DestroyAfterStop) {
-  CreateAudioStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(audio_stream());
-  SetDemuxerExpectations(&streams);
-  SetRendererExpectations();
-  StartPipelineAndExpect(PIPELINE_OK);
-
-  ExpectDemuxerStop();
-  pipeline_->Stop();
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(PipelineImplTest, Underflow) {
-  CreateAudioStream();
-  CreateVideoStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(audio_stream());
-  streams.push_back(video_stream());
-
-  SetDemuxerExpectations(&streams);
-  SetRendererExpectations();
-  StartPipelineAndExpect(PIPELINE_OK);
-
-  // Simulate underflow.
-  EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
-  renderer_client_->OnBufferingStateChange(BUFFERING_HAVE_NOTHING);
-  base::RunLoop().RunUntilIdle();
-
-  // Seek while underflowed.
-  base::TimeDelta expected = base::TimeDelta::FromSeconds(5);
-  ExpectSeek(expected, true);
-  DoSeek(expected);
-}
-
-TEST_F(PipelineImplTest, PositiveStartTime) {
-  start_time_ = base::TimeDelta::FromSeconds(1);
-  EXPECT_CALL(*demuxer_, GetStartTime()).WillRepeatedly(Return(start_time_));
-  CreateAudioStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(audio_stream());
-  SetDemuxerExpectations(&streams);
-  SetRendererExpectations();
-  StartPipelineAndExpect(PIPELINE_OK);
-  ExpectDemuxerStop();
-  pipeline_->Stop();
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(PipelineImplTest, GetMediaTime) {
-  CreateAudioStream();
-  MockDemuxerStreamVector streams;
-  streams.push_back(audio_stream());
-  SetDemuxerExpectations(&streams);
-  SetRendererExpectations();
-  StartPipelineAndExpect(PIPELINE_OK);
-
-  // Pipeline should report the same media time returned by the renderer.
-  base::TimeDelta kMediaTime = base::TimeDelta::FromSeconds(2);
-  EXPECT_CALL(*renderer_, GetMediaTime()).WillRepeatedly(Return(kMediaTime));
-  EXPECT_EQ(kMediaTime, pipeline_->GetMediaTime());
-
-  // Media time should not go backwards even if the renderer returns an
-  // errorneous value. PipelineImpl should clamp it to last reported value.
-  EXPECT_CALL(*renderer_, GetMediaTime())
-      .WillRepeatedly(Return(base::TimeDelta::FromSeconds(1)));
-  EXPECT_EQ(kMediaTime, pipeline_->GetMediaTime());
-}
-
-class PipelineTeardownTest : public PipelineImplTest {
- public:
-  enum TeardownState {
-    kInitDemuxer,
-    kInitRenderer,
-    kFlushing,
-    kSeeking,
-    kPlaying,
-    kSuspending,
-    kSuspended,
-    kResuming,
-  };
-
-  enum StopOrError {
-    kStop,
-    kError,
-    kErrorAndStop,
-  };
-
-  PipelineTeardownTest() {}
-  ~PipelineTeardownTest() override {}
-
-  void RunTest(TeardownState state, StopOrError stop_or_error) {
-    switch (state) {
-      case kInitDemuxer:
-      case kInitRenderer:
-        DoInitialize(state, stop_or_error);
-        break;
-
-      case kFlushing:
-      case kSeeking:
-        DoInitialize(state, stop_or_error);
-        DoSeek(state, stop_or_error);
-        break;
-
-      case kPlaying:
-        DoInitialize(state, stop_or_error);
-        DoStopOrError(stop_or_error, true);
-        break;
-
-      case kSuspending:
-      case kSuspended:
-      case kResuming:
-        DoInitialize(state, stop_or_error);
-        DoSuspend(state, stop_or_error);
-        break;
-    }
-  }
-
- private:
-  // TODO(scherkus): We do radically different things whether teardown is
-  // invoked via stop vs error. The teardown path should be the same,
-  // see http://crbug.com/110228
-  void DoInitialize(TeardownState state, StopOrError stop_or_error) {
-    SetInitializeExpectations(state, stop_or_error);
-    StartPipeline();
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void SetInitializeExpectations(TeardownState state,
-                                 StopOrError stop_or_error) {
-    if (state == kInitDemuxer) {
-      if (stop_or_error == kStop) {
-        EXPECT_CALL(*demuxer_, Initialize(_, _, _))
-            .WillOnce(
-                DoAll(Stop(pipeline_.get()), PostCallback<1>(PIPELINE_OK)));
-        // Note: OnStart callback is not called after pipeline is stopped.
-      } else {
-        EXPECT_CALL(*demuxer_, Initialize(_, _, _))
-            .WillOnce(PostCallback<1>(DEMUXER_ERROR_COULD_NOT_OPEN));
-        EXPECT_CALL(callbacks_, OnStart(DEMUXER_ERROR_COULD_NOT_OPEN));
-      }
-
-      EXPECT_CALL(*demuxer_, Stop());
-      return;
-    }
-
-    CreateAudioStream();
-    CreateVideoStream();
-    MockDemuxerStreamVector streams;
-    streams.push_back(audio_stream());
-    streams.push_back(video_stream());
-    SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
-
-    EXPECT_CALL(*renderer_, HasAudio()).WillRepeatedly(Return(true));
-    EXPECT_CALL(*renderer_, HasVideo()).WillRepeatedly(Return(true));
-
-    if (state == kInitRenderer) {
-      if (stop_or_error == kStop) {
-        EXPECT_CALL(*renderer_, Initialize(_, _, _))
-            .WillOnce(
-                DoAll(Stop(pipeline_.get()), PostCallback<2>(PIPELINE_OK)));
-        // Note: OnStart is not callback after pipeline is stopped.
-      } else {
-        EXPECT_CALL(*renderer_, Initialize(_, _, _))
-            .WillOnce(PostCallback<2>(PIPELINE_ERROR_INITIALIZATION_FAILED));
-        EXPECT_CALL(callbacks_, OnStart(PIPELINE_ERROR_INITIALIZATION_FAILED));
-      }
-
-      EXPECT_CALL(callbacks_, OnMetadata(_));
-      EXPECT_CALL(*demuxer_, Stop());
-      return;
-    }
-
-    EXPECT_CALL(*renderer_, Initialize(_, _, _))
-        .WillOnce(
-            DoAll(SaveArg<1>(&renderer_client_), PostCallback<2>(PIPELINE_OK)));
-
-    // If we get here it's a successful initialization.
-    EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK));
-    EXPECT_CALL(callbacks_, OnMetadata(_));
-
-    EXPECT_CALL(*renderer_, SetPlaybackRate(0.0));
-    EXPECT_CALL(*renderer_, SetVolume(1.0f));
-    EXPECT_CALL(*renderer_, StartPlayingFrom(base::TimeDelta()))
-        .WillOnce(SetBufferingState(&renderer_client_, BUFFERING_HAVE_ENOUGH));
-    EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
-  }
-
-  void DoSeek(TeardownState state, StopOrError stop_or_error) {
-    SetSeekExpectations(state, stop_or_error);
-
-    EXPECT_CALL(*demuxer_, AbortPendingReads());
-    EXPECT_CALL(*demuxer_, Stop());
-
-    pipeline_->Seek(
-        base::TimeDelta::FromSeconds(10),
-        base::Bind(&CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void SetSeekExpectations(TeardownState state, StopOrError stop_or_error) {
-    if (state == kFlushing) {
-      if (stop_or_error == kStop) {
-        EXPECT_CALL(*renderer_, Flush(_))
-            .WillOnce(DoAll(
-                SetBufferingState(&renderer_client_, BUFFERING_HAVE_NOTHING),
-                Stop(pipeline_.get()), RunClosure<0>()));
-        // Note: OnBufferingStateChange or OnSeek callbacks are not called
-        // after pipeline is stopped.
-      } else {
-        EXPECT_CALL(*renderer_, Flush(_))
-            .WillOnce(DoAll(
-                SetBufferingState(&renderer_client_, BUFFERING_HAVE_NOTHING),
-                SetError(&renderer_client_, PIPELINE_ERROR_READ),
-                RunClosure<0>()));
-        EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
-        EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
-      }
-      return;
-    }
-
-    EXPECT_CALL(*renderer_, Flush(_))
-        .WillOnce(
-            DoAll(SetBufferingState(&renderer_client_, BUFFERING_HAVE_NOTHING),
-                  RunClosure<0>()));
-    EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
-
-    if (state == kSeeking) {
-      if (stop_or_error == kStop) {
-        EXPECT_CALL(*demuxer_, Seek(_, _))
-            .WillOnce(
-                DoAll(Stop(pipeline_.get()), RunCallback<1>(PIPELINE_OK)));
-        // Note: OnSeek callback is not called after pipeline is stopped.
-      } else {
-        EXPECT_CALL(*demuxer_, Seek(_, _))
-            .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
-        EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
-      }
-      return;
-    }
-
-    NOTREACHED() << "State not supported: " << state;
-  }
-
-  void DoSuspend(TeardownState state, StopOrError stop_or_error) {
-    SetSuspendExpectations(state, stop_or_error);
-
-    if (state == kResuming) {
-      EXPECT_CALL(*demuxer_, Stop());
-    }
-
-    PipelineImplTest::DoSuspend();
-
-    if (state == kResuming) {
-      PipelineImplTest::DoResume(base::TimeDelta());
-      return;
-    }
-
-    // kSuspended, kSuspending never throw errors, since Resume() is always able
-    // to restore the pipeline to a pristine state.
-    DoStopOrError(stop_or_error, false);
-  }
-
-  void SetSuspendExpectations(TeardownState state, StopOrError stop_or_error) {
-    EXPECT_CALL(*renderer_, SetPlaybackRate(0));
-    EXPECT_CALL(*demuxer_, AbortPendingReads());
-    EXPECT_CALL(callbacks_, OnSuspend(PIPELINE_OK));
-    if (state == kResuming) {
-      if (stop_or_error == kStop) {
-        EXPECT_CALL(*demuxer_, Seek(_, _))
-            .WillOnce(
-                DoAll(Stop(pipeline_.get()), RunCallback<1>(PIPELINE_OK)));
-        // Note: OnResume callback is not called after pipeline is stopped.
-      } else {
-        EXPECT_CALL(*demuxer_, Seek(_, _))
-            .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
-        EXPECT_CALL(callbacks_, OnResume(PIPELINE_ERROR_READ));
-      }
-    } else if (state != kSuspended && state != kSuspending) {
-      NOTREACHED() << "State not supported: " << state;
-    }
-  }
-
-  void DoStopOrError(StopOrError stop_or_error, bool expect_errors) {
-    switch (stop_or_error) {
-      case kStop:
-        EXPECT_CALL(*demuxer_, Stop());
-        pipeline_->Stop();
-        break;
-
-      case kError:
-        if (expect_errors) {
-          EXPECT_CALL(*demuxer_, Stop());
-          EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
-        }
-        renderer_client_->OnError(PIPELINE_ERROR_READ);
-        break;
-
-      case kErrorAndStop:
-        EXPECT_CALL(*demuxer_, Stop());
-        if (expect_errors)
-          EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
-        renderer_client_->OnError(PIPELINE_ERROR_READ);
-        base::RunLoop().RunUntilIdle();
-        pipeline_->Stop();
-        break;
-    }
-
-    base::RunLoop().RunUntilIdle();
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest);
-};
-
-#define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state)   \
-  TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
-    RunTest(k##state, k##stop_or_error);                  \
-  }
-
-INSTANTIATE_TEARDOWN_TEST(Stop, InitDemuxer);
-INSTANTIATE_TEARDOWN_TEST(Stop, InitRenderer);
-INSTANTIATE_TEARDOWN_TEST(Stop, Flushing);
-INSTANTIATE_TEARDOWN_TEST(Stop, Seeking);
-INSTANTIATE_TEARDOWN_TEST(Stop, Playing);
-INSTANTIATE_TEARDOWN_TEST(Stop, Suspending);
-INSTANTIATE_TEARDOWN_TEST(Stop, Suspended);
-INSTANTIATE_TEARDOWN_TEST(Stop, Resuming);
-
-INSTANTIATE_TEARDOWN_TEST(Error, InitDemuxer);
-INSTANTIATE_TEARDOWN_TEST(Error, InitRenderer);
-INSTANTIATE_TEARDOWN_TEST(Error, Flushing);
-INSTANTIATE_TEARDOWN_TEST(Error, Seeking);
-INSTANTIATE_TEARDOWN_TEST(Error, Playing);
-INSTANTIATE_TEARDOWN_TEST(Error, Suspending);
-INSTANTIATE_TEARDOWN_TEST(Error, Suspended);
-INSTANTIATE_TEARDOWN_TEST(Error, Resuming);
-
-INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Playing);
-INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Suspended);
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/player_tracker.cc b/src/cobalt/media/base/player_tracker.cc
deleted file mode 100644
index 7f274c1..0000000
--- a/src/cobalt/media/base/player_tracker.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/player_tracker.h"
-
-namespace cobalt {
-namespace media {
-
-PlayerTracker::PlayerTracker() {}
-
-PlayerTracker::~PlayerTracker() {}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/player_tracker.h b/src/cobalt/media/base/player_tracker.h
deleted file mode 100644
index dcedbc1..0000000
--- a/src/cobalt/media/base/player_tracker.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_PLAYER_TRACKER_H_
-#define COBALT_MEDIA_BASE_PLAYER_TRACKER_H_
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "cobalt/media/base/media_export.h"
-
-namespace cobalt {
-namespace media {
-
-// An interface for players to register to be notified when a new decryption key
-// becomes available or when the CDM is unset.
-class MEDIA_EXPORT PlayerTracker {
- public:
-  virtual ~PlayerTracker();
-
-  // Registers player callbacks with the CDM.
-  // - |new_key_cb| is fired when a new decryption key becomes available.
-  // - |cdm_unset_cb| is fired when the CDM is detached from the player. The
-  //   player should stop using the CDM and release any ref-count to the CDM.
-  // Returns a registration ID which can be used to unregister a player.
-  virtual int RegisterPlayer(const base::Closure& new_key_cb,
-                             const base::Closure& cdm_unset_cb) = 0;
-
-  // Unregisters a previously registered player. This should be called when
-  // the CDM is detached from the player (e.g. setMediaKeys(0)), or when the
-  // player is destroyed.
-  virtual void UnregisterPlayer(int registration_id) = 0;
-
- protected:
-  PlayerTracker();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PlayerTracker);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_PLAYER_TRACKER_H_
diff --git a/src/cobalt/media/base/renderer_factory.cc b/src/cobalt/media/base/renderer_factory.cc
deleted file mode 100644
index d3e7e19..0000000
--- a/src/cobalt/media/base/renderer_factory.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/renderer_factory.h"
-
-namespace cobalt {
-namespace media {
-
-RendererFactory::RendererFactory() {}
-
-RendererFactory::~RendererFactory() {}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/renderer_factory.h b/src/cobalt/media/base/renderer_factory.h
deleted file mode 100644
index 1211f4a..0000000
--- a/src/cobalt/media/base/renderer_factory.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_RENDERER_FACTORY_H_
-#define COBALT_MEDIA_BASE_RENDERER_FACTORY_H_
-
-#include <memory>
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/renderer.h"
-#include "cobalt/media/base/surface_manager.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-class TaskRunner;
-}
-
-namespace cobalt {
-namespace media {
-
-class AudioRendererSink;
-class VideoRendererSink;
-
-// A factory class for creating media::Renderer to be used by media pipeline.
-class MEDIA_EXPORT RendererFactory {
- public:
-  RendererFactory();
-  virtual ~RendererFactory();
-
-  // Creates and returns a Renderer. All methods of the created Renderer except
-  // for GetMediaTime() will be called on the |media_task_runner|.
-  // GetMediaTime() could be called on any thread.
-  // The created Renderer can use |audio_renderer_sink| to render audio and
-  // |video_renderer_sink| to render video.
-  virtual std::unique_ptr<Renderer> CreateRenderer(
-      const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
-      const scoped_refptr<base::TaskRunner>& worker_task_runner,
-      AudioRendererSink* audio_renderer_sink,
-      VideoRendererSink* video_renderer_sink,
-      const RequestSurfaceCB& request_surface_cb) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(RendererFactory);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_RENDERER_FACTORY_H_
diff --git a/src/cobalt/media/base/sbplayer_pipeline.cc b/src/cobalt/media/base/sbplayer_pipeline.cc
index 4844a7d..0cae47c 100644
--- a/src/cobalt/media/base/sbplayer_pipeline.cc
+++ b/src/cobalt/media/base/sbplayer_pipeline.cc
@@ -52,6 +52,7 @@
 
 namespace {
 
+static const int kRetryDelayAtSuspendInMilliseconds = 100;
 const char kVideoDumpFileName[] = "video_content.dmp";
 
 // Used to post parameters to SbPlayerPipeline::StartTask() as the number of
@@ -65,6 +66,9 @@
   Pipeline::BufferingStateCB buffering_state_cb;
   base::Closure duration_change_cb;
   base::Closure output_mode_change_cb;
+#if SB_HAS(PLAYER_WITH_URL)
+  std::string source_url;
+#endif  // SB_HAS(PLAYER_WITH_URL)
 };
 
 // SbPlayerPipeline is a PipelineBase implementation that uses the SbPlayer
@@ -86,6 +90,11 @@
 #if COBALT_MEDIA_ENABLE_VIDEO_DUMPER
              const SetEMEInitDataReadyCB& set_eme_init_data_ready_cb,
 #endif  // COBALT_MEDIA_ENABLE_VIDEO_DUMPER
+#if SB_HAS(PLAYER_WITH_URL)
+             const OnEncryptedMediaInitDataEncounteredCB&
+                 on_encrypted_media_init_data_encountered_cb,
+             const std::string& source_url,
+#endif  // SB_HAS(PLAYER_WITH_URL)
              const PipelineStatusCB& ended_cb, const PipelineStatusCB& error_cb,
              const PipelineStatusCB& seek_cb,
              const BufferingStateCB& buffering_state_cb,
@@ -127,16 +136,23 @@
                      const TextTrackConfig& config) OVERRIDE;
   void RemoveTextStream(DemuxerStream* text_stream) OVERRIDE;
 
+#if SB_HAS(PLAYER_WITH_URL)
+  void CreatePlayerWithUrl(const std::string& source_url);
+  void SetDrmSystem(SbDrmSystem drm_system);
+#else   // SB_HAS(PLAYER_WITH_URL)
   void CreatePlayer(SbDrmSystem drm_system);
+#endif  // SB_HAS(PLAYER_WITH_URL)
   void OnDemuxerInitialized(PipelineStatus status);
   void OnDemuxerSeeked(PipelineStatus status);
   void OnDemuxerStopped();
+
+#if !SB_HAS(PLAYER_WITH_URL)
   void OnDemuxerStreamRead(DemuxerStream::Type type,
                            DemuxerStream::Status status,
                            const scoped_refptr<DecoderBuffer>& buffer);
-
   // StarboardPlayer::Host implementation.
   void OnNeedData(DemuxerStream::Type type) OVERRIDE;
+#endif  // !SB_HAS(PLAYER_WITH_URL)
   void OnPlayerStatus(SbPlayerState state) OVERRIDE;
 
   void UpdateDecoderConfig(DemuxerStream* stream);
@@ -206,6 +222,10 @@
   base::Closure duration_change_cb_;
   base::Closure output_mode_change_cb_;
   base::optional<bool> decode_to_texture_output_mode_;
+#if SB_HAS(PLAYER_WITH_URL)
+  StarboardPlayer::OnEncryptedMediaInitDataEncounteredCB
+      on_encrypted_media_init_data_encountered_cb_;
+#endif  //  SB_HAS(PLAYER_WITH_URL)
 
   // Demuxer reference used for setting the preload value.
   Demuxer* demuxer_;
@@ -278,25 +298,59 @@
   waitable_event.Wait();
 }
 
+#if SB_HAS(PLAYER_WITH_URL)
+void OnEncryptedMediaInitDataEncountered(
+    const Pipeline::OnEncryptedMediaInitDataEncounteredCB&
+        on_encrypted_media_init_data_encountered,
+    const char* init_data_type, const unsigned char* init_data,
+    unsigned int init_data_length) {
+  media::EmeInitDataType init_data_type_enum;
+  if (!SbStringCompareAll(init_data_type, "cenc")) {
+    init_data_type_enum = media::kEmeInitDataTypeCenc;
+  } else if (!SbStringCompareAll(init_data_type, "fairplay")) {
+    init_data_type_enum = media::kEmeInitDataTypeFairplay;
+  } else if (!SbStringCompareAll(init_data_type, "keyids")) {
+    init_data_type_enum = media::kEmeInitDataTypeKeyIds;
+  } else if (!SbStringCompareAll(init_data_type, "webm")) {
+    init_data_type_enum = media::kEmeInitDataTypeWebM;
+  } else {
+    LOG(WARNING) << "Unknown EME initialization data type.";
+    return;
+  }
+  std::vector<uint8_t> init_data_vec(init_data, init_data + init_data_length);
+  DCHECK(!on_encrypted_media_init_data_encountered.is_null());
+  on_encrypted_media_init_data_encountered.Run(init_data_type_enum,
+                                               init_data_vec);
+}
+#endif  // SB_HAS(PLAYER_WITH_URL)
+
 void SbPlayerPipeline::Start(
     Demuxer* demuxer, const SetDrmSystemReadyCB& set_drm_system_ready_cb,
 #if COBALT_MEDIA_ENABLE_VIDEO_DUMPER
     const SetEMEInitDataReadyCB& set_eme_init_data_ready_cb,
 #endif  // COBALT_MEDIA_ENABLE_VIDEO_DUMPER
+#if SB_HAS(PLAYER_WITH_URL)
+    const OnEncryptedMediaInitDataEncounteredCB&
+        on_encrypted_media_init_data_encountered_cb,
+    const std::string& source_url,
+#endif  // SB_HAS(PLAYER_WITH_URL)
     const PipelineStatusCB& ended_cb, const PipelineStatusCB& error_cb,
     const PipelineStatusCB& seek_cb, const BufferingStateCB& buffering_state_cb,
     const base::Closure& duration_change_cb,
     const base::Closure& output_mode_change_cb) {
   TRACE_EVENT0("cobalt::media", "SbPlayerPipeline::Start");
 
-  DCHECK(demuxer);
   DCHECK(!ended_cb.is_null());
   DCHECK(!error_cb.is_null());
   DCHECK(!seek_cb.is_null());
   DCHECK(!buffering_state_cb.is_null());
   DCHECK(!duration_change_cb.is_null());
   DCHECK(!output_mode_change_cb.is_null());
-
+#if SB_HAS(PLAYER_WITH_URL)
+  DCHECK(!on_encrypted_media_init_data_encountered_cb.is_null());
+#else   // SB_HAS(PLAYER_WITH_URL)
+  DCHECK(demuxer);
+#endif  // SB_HAS(PLAYER_WITH_URL)
   StartTaskParameters parameters;
   parameters.demuxer = demuxer;
   parameters.set_drm_system_ready_cb = set_drm_system_ready_cb;
@@ -306,6 +360,16 @@
   parameters.buffering_state_cb = buffering_state_cb;
   parameters.duration_change_cb = duration_change_cb;
   parameters.output_mode_change_cb = output_mode_change_cb;
+#if SB_HAS(PLAYER_WITH_URL)
+  parameters.source_url = source_url;
+  on_encrypted_media_init_data_encountered_cb_ =
+      base::Bind(&OnEncryptedMediaInitDataEncountered,
+                 on_encrypted_media_init_data_encountered_cb);
+  set_drm_system_ready_cb_ = parameters.set_drm_system_ready_cb;
+  DCHECK(!set_drm_system_ready_cb_.is_null());
+  set_drm_system_ready_cb_.Run(
+      base::Bind(&SbPlayerPipeline::SetDrmSystem, this));
+#endif  // SB_HAS(PLAYER_WITH_URL)
 
 #if COBALT_MEDIA_ENABLE_VIDEO_DUMPER
   set_eme_init_data_ready_cb.Run(base::Bind(
@@ -382,8 +446,13 @@
     seek_cb_ = seek_cb;
     seek_time_ = time;
   }
+#if SB_HAS(PLAYER_WITH_URL)
+  player_->Seek(seek_time_);
+#else  //  SB_HAS(PLAYER_WITH_URL)
   demuxer_->Seek(time, BindToCurrentLoop(base::Bind(
                            &SbPlayerPipeline::OnDemuxerSeeked, this)));
+
+#endif  // SB_HAS(PLAYER_WITH_URL)
 }
 
 bool SbPlayerPipeline::HasAudio() const {
@@ -527,11 +596,15 @@
   duration_change_cb_ = parameters.duration_change_cb;
   output_mode_change_cb_ = parameters.output_mode_change_cb;
 
+#if SB_HAS(PLAYER_WITH_URL)
+  CreatePlayerWithUrl(parameters.source_url);
+#else   // SB_HAS(PLAYER_WITH_URL)
   const bool kEnableTextTracks = false;
   demuxer_->Initialize(this,
                        BindToCurrentLoop(base::Bind(
                            &SbPlayerPipeline::OnDemuxerInitialized, this)),
                        kEnableTextTracks);
+#endif  // SB_HAS(PLAYER_WITH_URL)
 }
 
 void SbPlayerPipeline::SetVolumeTask(float volume) {
@@ -593,6 +666,75 @@
   NOTREACHED();
 }
 
+#if SB_HAS(PLAYER_WITH_URL)
+void SbPlayerPipeline::CreatePlayerWithUrl(const std::string& source_url) {
+  TRACE_EVENT0("cobalt::media", "SbPlayerPipeline::CreatePlayerWithUrl");
+  DCHECK(message_loop_->BelongsToCurrentThread());
+
+  if (stopped_) {
+    return;
+  }
+
+  if (suspended_) {
+    message_loop_->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&SbPlayerPipeline::CreatePlayerWithUrl, this, source_url),
+        TimeDelta::FromMilliseconds(kRetryDelayAtSuspendInMilliseconds));
+    return;
+  }
+
+  // TODO:  Check |suspended_| here as the pipeline can be suspended before the
+  // player is created.  In this case we should delay creating the player as the
+  // creation of player may fail.
+
+  {
+    base::AutoLock auto_lock(lock_);
+    DLOG(INFO) << "StarboardPlayer created with url: " << source_url;
+    player_.reset(new StarboardPlayer(
+        message_loop_, source_url, window_, this, set_bounds_helper_.get(),
+        *decode_to_texture_output_mode_,
+        on_encrypted_media_init_data_encountered_cb_));
+    SetPlaybackRateTask(playback_rate_);
+    SetVolumeTask(volume_);
+  }
+
+  if (player_->IsValid()) {
+    base::Closure output_mode_change_cb;
+    {
+      base::AutoLock auto_lock(lock_);
+      DCHECK(!output_mode_change_cb_.is_null());
+      output_mode_change_cb = base::ResetAndReturn(&output_mode_change_cb_);
+    }
+    output_mode_change_cb.Run();
+    return;
+  }
+
+  player_.reset();
+
+  PipelineStatusCB seek_cb;
+  {
+    base::AutoLock auto_lock(lock_);
+    DCHECK(!seek_cb_.is_null());
+    seek_cb = base::ResetAndReturn(&seek_cb_);
+  }
+  seek_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
+}
+
+void SbPlayerPipeline::SetDrmSystem(SbDrmSystem drm_system) {
+  TRACE_EVENT0("cobalt::media", "SbPlayerPipeline::SetDrmSystem");
+
+  base::AutoLock auto_lock(lock_);
+  if (!player_) {
+    DLOG(INFO)
+        << "Player not set before calling SbPlayerPipeline::SetDrmSystem";
+    return;
+  }
+
+  if (player_->IsValid()) {
+    player_->SetDrmSystem(drm_system);
+  }
+}
+#else  // SB_HAS(PLAYER_WITH_URL)
 void SbPlayerPipeline::CreatePlayer(SbDrmSystem drm_system) {
   TRACE_EVENT0("cobalt::media", "SbPlayerPipeline::CreatePlayer");
 
@@ -600,10 +742,15 @@
   DCHECK(audio_stream_);
   DCHECK(video_stream_);
 
+  if (stopped_) {
+    return;
+  }
+
   if (suspended_) {
-    message_loop_->PostTask(
+    message_loop_->PostDelayedTask(
         FROM_HERE,
-        base::Bind(&SbPlayerPipeline::CreatePlayer, this, drm_system));
+        base::Bind(&SbPlayerPipeline::CreatePlayer, this, drm_system),
+        TimeDelta::FromMilliseconds(kRetryDelayAtSuspendInMilliseconds));
     return;
   }
 
@@ -653,7 +800,12 @@
   seek_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
 }
 
+#endif  // SB_HAS(PLAYER_WITH_URL)
+
 void SbPlayerPipeline::OnDemuxerInitialized(PipelineStatus status) {
+#if SB_HAS(PLAYER_WITH_URL)
+// Does not apply.
+#else
   TRACE_EVENT0("cobalt::media", "SbPlayerPipeline::OnDemuxerInitialized");
 
   DCHECK(message_loop_->BelongsToCurrentThread());
@@ -668,9 +820,10 @@
   }
 
   if (suspended_) {
-    message_loop_->PostTask(
+    message_loop_->PostDelayedTask(
         FROM_HERE,
-        base::Bind(&SbPlayerPipeline::OnDemuxerInitialized, this, status));
+        base::Bind(&SbPlayerPipeline::OnDemuxerInitialized, this, status),
+        TimeDelta::FromMilliseconds(kRetryDelayAtSuspendInMilliseconds));
     return;
   }
 
@@ -700,6 +853,7 @@
   }
 
   CreatePlayer(kSbDrmSystemInvalid);
+#endif  // SB_HAS(PLAYER_WITH_URL)
 }
 
 void SbPlayerPipeline::OnDemuxerSeeked(PipelineStatus status) {
@@ -722,6 +876,8 @@
   base::ResetAndReturn(&stop_cb_).Run();
 }
 
+#if !SB_HAS(PLAYER_WITH_URL)
+
 void SbPlayerPipeline::OnDemuxerStreamRead(
     DemuxerStream::Type type, DemuxerStream::Status status,
     const scoped_refptr<DecoderBuffer>& buffer) {
@@ -806,6 +962,8 @@
   stream->Read(base::Bind(&SbPlayerPipeline::OnDemuxerStreamRead, this, type));
 }
 
+#endif  // !SB_HAS(PLAYER_WITH_URL)
+
 void SbPlayerPipeline::OnPlayerStatus(SbPlayerState state) {
   DCHECK(message_loop_->BelongsToCurrentThread());
 
@@ -820,6 +978,10 @@
     case kSbPlayerStatePrerolling:
       break;
     case kSbPlayerStatePresenting:
+#if SB_HAS(PLAYER_WITH_URL)
+      duration_ = player_->GetDuration();
+      buffering_state_cb_.Run(kHaveMetadata);
+#endif  // SB_HAS(PLAYER_WITH_URL)
       buffering_state_cb_.Run(kPrerollCompleted);
       if (!seek_cb_.is_null()) {
         PipelineStatusCB seek_cb;
diff --git a/src/cobalt/media/base/serial_runner.cc b/src/cobalt/media/base/serial_runner.cc
deleted file mode 100644
index 733a86a..0000000
--- a/src/cobalt/media/base/serial_runner.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/serial_runner.h"
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-
-namespace cobalt {
-namespace media {
-
-// Converts a Closure into a bound function accepting a PipelineStatusCB.
-static void RunClosure(const base::Closure& closure,
-                       const PipelineStatusCB& status_cb) {
-  closure.Run();
-  status_cb.Run(PIPELINE_OK);
-}
-
-// Converts a bound function accepting a Closure into a bound function
-// accepting a PipelineStatusCB. Since closures have no way of reporting a
-// status |status_cb| is executed with PIPELINE_OK.
-static void RunBoundClosure(const SerialRunner::BoundClosure& bound_closure,
-                            const PipelineStatusCB& status_cb) {
-  bound_closure.Run(base::Bind(status_cb, PIPELINE_OK));
-}
-
-// Runs |status_cb| with |last_status| on |task_runner|.
-static void RunOnTaskRunner(
-    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
-    const PipelineStatusCB& status_cb, PipelineStatus last_status) {
-  // Force post to permit cancellation of a series in the scenario where all
-  // bound functions run on the same thread.
-  task_runner->PostTask(FROM_HERE, base::Bind(status_cb, last_status));
-}
-
-SerialRunner::Queue::Queue() {}
-SerialRunner::Queue::Queue(const Queue& other) = default;
-SerialRunner::Queue::~Queue() {}
-
-void SerialRunner::Queue::Push(const base::Closure& closure) {
-  bound_fns_.push(base::Bind(&RunClosure, closure));
-}
-
-void SerialRunner::Queue::Push(const BoundClosure& bound_closure) {
-  bound_fns_.push(base::Bind(&RunBoundClosure, bound_closure));
-}
-
-void SerialRunner::Queue::Push(const BoundPipelineStatusCB& bound_status_cb) {
-  bound_fns_.push(bound_status_cb);
-}
-
-SerialRunner::BoundPipelineStatusCB SerialRunner::Queue::Pop() {
-  BoundPipelineStatusCB bound_fn = bound_fns_.front();
-  bound_fns_.pop();
-  return bound_fn;
-}
-
-bool SerialRunner::Queue::empty() { return bound_fns_.empty(); }
-
-SerialRunner::SerialRunner(const Queue& bound_fns,
-                           const PipelineStatusCB& done_cb)
-    : task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      bound_fns_(bound_fns),
-      done_cb_(done_cb),
-      weak_factory_(this) {
-  // Respect both cancellation and calling stack guarantees for |done_cb|
-  // when empty.
-  if (bound_fns_.empty()) {
-    task_runner_->PostTask(FROM_HERE,
-                           base::Bind(&SerialRunner::RunNextInSeries,
-                                      weak_factory_.GetWeakPtr(), PIPELINE_OK));
-    return;
-  }
-
-  RunNextInSeries(PIPELINE_OK);
-}
-
-SerialRunner::~SerialRunner() {}
-
-std::unique_ptr<SerialRunner> SerialRunner::Run(
-    const Queue& bound_fns, const PipelineStatusCB& done_cb) {
-  std::unique_ptr<SerialRunner> callback_series(
-      new SerialRunner(bound_fns, done_cb));
-  return callback_series;
-}
-
-void SerialRunner::RunNextInSeries(PipelineStatus last_status) {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  DCHECK(!done_cb_.is_null());
-
-  if (bound_fns_.empty() || last_status != PIPELINE_OK) {
-    base::ResetAndReturn(&done_cb_).Run(last_status);
-    return;
-  }
-
-  BoundPipelineStatusCB bound_fn = bound_fns_.Pop();
-  bound_fn.Run(base::Bind(
-      &RunOnTaskRunner, task_runner_,
-      base::Bind(&SerialRunner::RunNextInSeries, weak_factory_.GetWeakPtr())));
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/serial_runner.h b/src/cobalt/media/base/serial_runner.h
deleted file mode 100644
index 11d8f63..0000000
--- a/src/cobalt/media/base/serial_runner.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_SERIAL_RUNNER_H_
-#define COBALT_MEDIA_BASE_SERIAL_RUNNER_H_
-
-#include <memory>
-#include <queue>
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/pipeline_status.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace cobalt {
-namespace media {
-
-// Runs a series of bound functions accepting Closures or PipelineStatusCB.
-// SerialRunner doesn't use regular Closure/PipelineStatusCBs as it late binds
-// the completion callback as the series progresses.
-class MEDIA_EXPORT SerialRunner {
- public:
-  typedef base::Callback<void(const base::Closure&)> BoundClosure;
-  typedef base::Callback<void(const PipelineStatusCB&)> BoundPipelineStatusCB;
-
-  // Serial queue of bound functions to run.
-  class MEDIA_EXPORT Queue {
-   public:
-    Queue();
-    Queue(const Queue& other);
-    ~Queue();
-
-    void Push(const base::Closure& closure);
-    void Push(const BoundClosure& bound_fn);
-    void Push(const BoundPipelineStatusCB& bound_fn);
-
-   private:
-    friend class SerialRunner;
-
-    BoundPipelineStatusCB Pop();
-    bool empty();
-
-    std::queue<BoundPipelineStatusCB> bound_fns_;
-  };
-
-  // Executes the bound functions in series, executing |done_cb| when finished.
-  //
-  // All bound functions are executed on the thread that Run() is called on,
-  // including |done_cb|.
-  //
-  // To eliminate an unnecessary posted task, the first function is executed
-  // immediately on the caller's stack. It is *strongly advised* to ensure
-  // the calling code does no more work after the call to Run().
-  //
-  // In all cases, |done_cb| is guaranteed to execute on a separate calling
-  // stack.
-  //
-  // Deleting the object will prevent execution of any unstarted bound
-  // functions, including |done_cb|.
-  static std::unique_ptr<SerialRunner> Run(const Queue& bound_fns,
-                                           const PipelineStatusCB& done_cb);
-
- private:
-  friend std::default_delete<SerialRunner>;
-
-  SerialRunner(const Queue& bound_fns, const PipelineStatusCB& done_cb);
-  ~SerialRunner();
-
-  void RunNextInSeries(PipelineStatus last_status);
-
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-  Queue bound_fns_;
-  PipelineStatusCB done_cb_;
-
-  // NOTE: Weak pointers must be invalidated before all other member variables.
-  base::WeakPtrFactory<SerialRunner> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(SerialRunner);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_SERIAL_RUNNER_H_
diff --git a/src/cobalt/media/base/serial_runner_unittest.cc b/src/cobalt/media/base/serial_runner_unittest.cc
deleted file mode 100644
index 5bd5a01..0000000
--- a/src/cobalt/media/base/serial_runner_unittest.cc
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <memory>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/debug/stack_trace.h"
-#include "base/message_loop.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "cobalt/media/base/pipeline_status.h"
-#include "cobalt/media/base/serial_runner.h"
-#include "starboard/types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cobalt {
-namespace media {
-
-class SerialRunnerTest : public ::testing::Test {
- public:
-  SerialRunnerTest()
-      : inside_start_(false), done_called_(false), done_status_(PIPELINE_OK) {}
-  ~SerialRunnerTest() override {}
-
-  void RunSerialRunner() {
-    message_loop_.task_runner()->PostTask(
-        FROM_HERE, base::Bind(&SerialRunnerTest::StartRunnerInternal,
-                              base::Unretained(this), bound_fns_));
-    base::RunLoop().RunUntilIdle();
-  }
-
-  // Pushes a bound function to the queue that will run its callback with
-  // |status|. called(i) returns whether the i'th bound function pushed to the
-  // queue was called while running the SerialRunner.
-  void PushBoundFunction(PipelineStatus status) {
-    bound_fns_.Push(base::Bind(&SerialRunnerTest::RunBoundFunction,
-                               base::Unretained(this), status, called_.size()));
-    called_.push_back(false);
-  }
-
-  void PushBoundClosure() {
-    bound_fns_.Push(base::Bind(&SerialRunnerTest::RunBoundClosure,
-                               base::Unretained(this), called_.size()));
-    called_.push_back(false);
-  }
-
-  void PushClosure() {
-    bound_fns_.Push(base::Bind(&SerialRunnerTest::RunClosure,
-                               base::Unretained(this), called_.size()));
-    called_.push_back(false);
-  }
-
-  // Push a bound function to the queue that will delete the SerialRunner,
-  // which should cancel all remaining queued work.
-  void PushCancellation() {
-    bound_fns_.Push(base::Bind(&SerialRunnerTest::CancelSerialRunner,
-                               base::Unretained(this)));
-  }
-
-  // Queries final status of pushed functions and done callback. Valid only
-  // after calling RunSerialRunner().
-  bool called(size_t index) { return called_[index]; }
-  bool done_called() { return done_called_; }
-  PipelineStatus done_status() { return done_status_; }
-
- private:
-  void RunBoundFunction(PipelineStatus status, size_t index,
-                        const PipelineStatusCB& status_cb) {
-    EXPECT_EQ(index == 0u, inside_start_)
-        << "First bound function should run on same stack as "
-        << "SerialRunner::Run() while all others should not\n"
-        << base::debug::StackTrace().ToString();
-
-    called_[index] = true;
-    status_cb.Run(status);
-  }
-
-  void RunBoundClosure(size_t index, const base::Closure& done_cb) {
-    EXPECT_EQ(index == 0u, inside_start_)
-        << "First bound function should run on same stack as "
-        << "SerialRunner::Run() while all others should not\n"
-        << base::debug::StackTrace().ToString();
-
-    called_[index] = true;
-    done_cb.Run();
-  }
-
-  void RunClosure(size_t index) {
-    EXPECT_EQ(index == 0u, inside_start_)
-        << "First bound function should run on same stack as "
-        << "SerialRunner::Run() while all others should not\n"
-        << base::debug::StackTrace().ToString();
-
-    called_[index] = true;
-  }
-
-  void StartRunnerInternal(const SerialRunner::Queue& bound_fns) {
-    inside_start_ = true;
-    runner_ = SerialRunner::Run(
-        bound_fns_,
-        base::Bind(&SerialRunnerTest::DoneCallback, base::Unretained(this)));
-    inside_start_ = false;
-  }
-
-  void DoneCallback(PipelineStatus status) {
-    EXPECT_FALSE(inside_start_)
-        << "Done callback should not run on same stack as SerialRunner::Run()\n"
-        << base::debug::StackTrace().ToString();
-
-    done_called_ = true;
-    done_status_ = status;
-    message_loop_.QuitWhenIdle();
-  }
-
-  void CancelSerialRunner(const PipelineStatusCB& status_cb) {
-    // Tasks run by |runner_| shouldn't reset it, hence we post a task to do so.
-    message_loop_.task_runner()->PostTask(
-        FROM_HERE, base::Bind(&SerialRunnerTest::ResetSerialRunner,
-                              base::Unretained(this)));
-    status_cb.Run(PIPELINE_OK);
-  }
-
-  void ResetSerialRunner() { runner_.reset(); }
-
-  base::MessageLoop message_loop_;
-  SerialRunner::Queue bound_fns_;
-  std::unique_ptr<SerialRunner> runner_;
-
-  // Used to enforce calling stack guarantees of the API.
-  bool inside_start_;
-
-  // Tracks whether the i'th bound function was called.
-  std::vector<bool> called_;
-
-  // Tracks whether the final done callback was called + resulting status.
-  bool done_called_;
-  PipelineStatus done_status_;
-
-  DISALLOW_COPY_AND_ASSIGN(SerialRunnerTest);
-};
-
-TEST_F(SerialRunnerTest, Empty) {
-  RunSerialRunner();
-
-  EXPECT_TRUE(done_called());
-  EXPECT_EQ(PIPELINE_OK, done_status());
-}
-
-TEST_F(SerialRunnerTest, Single) {
-  PushBoundFunction(PIPELINE_OK);
-  RunSerialRunner();
-
-  EXPECT_TRUE(called(0));
-  EXPECT_TRUE(done_called());
-  EXPECT_EQ(PIPELINE_OK, done_status());
-}
-
-TEST_F(SerialRunnerTest, Single_Error) {
-  PushBoundFunction(PIPELINE_ERROR_ABORT);
-  RunSerialRunner();
-
-  EXPECT_TRUE(called(0));
-  EXPECT_TRUE(done_called());
-  EXPECT_EQ(PIPELINE_ERROR_ABORT, done_status());
-}
-
-TEST_F(SerialRunnerTest, Single_Cancel) {
-  PushBoundFunction(PIPELINE_OK);
-  PushCancellation();
-  RunSerialRunner();
-
-  EXPECT_TRUE(called(0));
-  EXPECT_FALSE(done_called());
-}
-
-TEST_F(SerialRunnerTest, Multiple) {
-  PushBoundFunction(PIPELINE_OK);
-  PushBoundFunction(PIPELINE_OK);
-  RunSerialRunner();
-
-  EXPECT_TRUE(called(0));
-  EXPECT_TRUE(called(1));
-  EXPECT_TRUE(done_called());
-  EXPECT_EQ(PIPELINE_OK, done_status());
-}
-
-TEST_F(SerialRunnerTest, Multiple_Error) {
-  PushBoundFunction(PIPELINE_ERROR_ABORT);
-  PushBoundFunction(PIPELINE_OK);
-  RunSerialRunner();
-
-  EXPECT_TRUE(called(0));
-  EXPECT_FALSE(called(1));  // A bad status cancels remaining work.
-  EXPECT_TRUE(done_called());
-  EXPECT_EQ(PIPELINE_ERROR_ABORT, done_status());
-}
-
-TEST_F(SerialRunnerTest, Multiple_Cancel) {
-  PushBoundFunction(PIPELINE_OK);
-  PushCancellation();
-  PushBoundFunction(PIPELINE_OK);
-  RunSerialRunner();
-
-  EXPECT_TRUE(called(0));
-  EXPECT_FALSE(called(1));
-  EXPECT_FALSE(done_called());
-}
-
-TEST_F(SerialRunnerTest, BoundClosure) {
-  PushBoundClosure();
-  RunSerialRunner();
-
-  EXPECT_TRUE(called(0));
-  EXPECT_TRUE(done_called());
-  EXPECT_EQ(PIPELINE_OK, done_status());
-}
-
-TEST_F(SerialRunnerTest, Closure) {
-  PushClosure();
-  RunSerialRunner();
-
-  EXPECT_TRUE(called(0));
-  EXPECT_TRUE(done_called());
-  EXPECT_EQ(PIPELINE_OK, done_status());
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/starboard_player.cc b/src/cobalt/media/base/starboard_player.cc
index 4582565..920d564 100644
--- a/src/cobalt/media/base/starboard_player.cc
+++ b/src/cobalt/media/base/starboard_player.cc
@@ -14,6 +14,9 @@
 
 #include "cobalt/media/base/starboard_player.h"
 
+#include <string>
+#include <vector>
+
 #include "base/bind.h"
 #include "base/compiler_specific.h"
 #include "base/debug/trace_event.h"
@@ -67,6 +70,44 @@
   player_ = NULL;
 }
 
+#if SB_HAS(PLAYER_WITH_URL)
+StarboardPlayer::StarboardPlayer(
+    const scoped_refptr<base::MessageLoopProxy>& message_loop,
+    const std::string& url, SbWindow window, Host* host,
+    SbPlayerSetBoundsHelper* set_bounds_helper, bool prefer_decode_to_texture,
+    const OnEncryptedMediaInitDataEncounteredCB&
+        on_encrypted_media_init_data_encountered_cb)
+    : url_(url),
+      message_loop_(message_loop),
+      callback_helper_(
+          new CallbackHelper(ALLOW_THIS_IN_INITIALIZER_LIST(this))),
+      window_(window),
+      drm_system_(kSbDrmSystemInvalid),
+      host_(host),
+      set_bounds_helper_(set_bounds_helper),
+      frame_width_(1),
+      frame_height_(1),
+      ticket_(SB_PLAYER_INITIAL_TICKET),
+      volume_(1.0),
+      playback_rate_(0.0),
+      seek_pending_(false),
+      state_(kPlaying),
+      on_encrypted_media_init_data_encountered_cb_(
+          on_encrypted_media_init_data_encountered_cb) {
+  DCHECK(host_);
+  DCHECK(set_bounds_helper_);
+
+  output_mode_ = ComputeSbPlayerOutputModeWithUrl(prefer_decode_to_texture);
+
+  CreatePlayerWithUrl(url_);
+
+  message_loop->PostTask(
+      FROM_HERE,
+      base::Bind(&StarboardPlayer::CallbackHelper::ClearDecoderBufferCache,
+                 callback_helper_));
+}
+#else
+
 StarboardPlayer::StarboardPlayer(
     const scoped_refptr<base::MessageLoopProxy>& message_loop,
     const AudioDecoderConfig& audio_config,
@@ -105,6 +146,7 @@
       base::Bind(&StarboardPlayer::CallbackHelper::ClearDecoderBufferCache,
                  callback_helper_));
 }
+#endif  // SB_HAS(PLAYER_WITH_URL)
 
 StarboardPlayer::~StarboardPlayer() {
   DCHECK(message_loop_->BelongsToCurrentThread());
@@ -130,6 +172,8 @@
   frame_height_ = frame_height;
 }
 
+#if !SB_HAS(PLAYER_WITH_URL)
+
 void StarboardPlayer::WriteBuffer(DemuxerStream::Type type,
                                   const scoped_refptr<DecoderBuffer>& buffer) {
   DCHECK(message_loop_->BelongsToCurrentThread());
@@ -144,7 +188,6 @@
   }
 
   if (state_ == kSuspended) {
-    DCHECK(!SbPlayerIsValid(player_));
     return;
   }
 
@@ -197,9 +240,10 @@
                       drm_info.subsample_count > 0 ? &drm_info : NULL);
 }
 
+#endif  // !SB_HAS(PLAYER_WITH_URL)
+
 void StarboardPlayer::SetBounds(int z_index, const gfx::Rect& rect) {
   if (state_ == kSuspended) {
-    DCHECK(!SbPlayerIsValid(player_));
     pending_set_bounds_z_index_ = z_index;
     pending_set_bounds_rect_ = rect;
     return;
@@ -216,7 +260,6 @@
   seek_pending_ = true;
 
   if (state_ == kSuspended) {
-    DCHECK(!SbPlayerIsValid(player_));
     return;
   }
 
@@ -230,7 +273,6 @@
   decoder_buffer_cache_.ClearAll();
 
   if (state_ == kSuspended) {
-    DCHECK(!SbPlayerIsValid(player_));
     preroll_timestamp_ = time;
     return;
   }
@@ -255,7 +297,6 @@
   volume_ = volume;
 
   if (state_ == kSuspended) {
-    DCHECK(!SbPlayerIsValid(player_));
     return;
   }
 
@@ -269,7 +310,6 @@
   playback_rate_ = playback_rate;
 
   if (state_ == kSuspended) {
-    DCHECK(!SbPlayerIsValid(player_));
     return;
   }
 
@@ -287,8 +327,6 @@
 
   base::AutoLock auto_lock(lock_);
   if (state_ == kSuspended) {
-    DCHECK(!SbPlayerIsValid(player_));
-
     if (video_frames_decoded) {
       *video_frames_decoded = cached_video_frames_decoded_;
     }
@@ -316,12 +354,31 @@
   }
 }
 
+#if SB_HAS(PLAYER_WITH_URL)
+base::TimeDelta StarboardPlayer::GetDuration() {
+  base::AutoLock auto_lock(lock_);
+  if (state_ == kSuspended) {
+    return base::TimeDelta();
+  }
+
+  DCHECK(SbPlayerIsValid(player_));
+
+  SbPlayerInfo info;
+  SbPlayerGetInfo(player_, &info);
+  DCHECK_NE(info.duration_pts, SB_PLAYER_NO_DURATION);
+  return SbMediaTimeToTimeDelta(info.duration_pts);
+}
+
+void StarboardPlayer::SetDrmSystem(SbDrmSystem drm_system) {
+  SbPlayerSetDrmSystem(player_, drm_system);
+}
+#endif  // SB_HAS(PLAYER_WITH_URL)
+
 void StarboardPlayer::Suspend() {
   DCHECK(message_loop_->BelongsToCurrentThread());
 
   // Check if the player is already suspended.
   if (state_ == kSuspended) {
-    DCHECK(!SbPlayerIsValid(player_));
     return;
   }
 
@@ -354,11 +411,13 @@
     return;
   }
 
-  DCHECK(!SbPlayerIsValid(player_));
-
   decoder_buffer_cache_.StartResuming();
 
+#if SB_HAS(PLAYER_WITH_URL)
+  CreatePlayerWithUrl(url_);
+#else   // SB_HAS(PLAYER_WITH_URL)
   CreatePlayer();
+#endif  // SB_HAS(PLAYER_WITH_URL)
 
   base::AutoLock auto_lock(lock_);
   state_ = kResuming;
@@ -379,8 +438,56 @@
   NOTREACHED();
   return ShellVideoFrameProvider::kOutputModeInvalid;
 }
+
 }  // namespace
 
+#if SB_HAS(PLAYER_WITH_URL)
+
+// static
+void StarboardPlayer::EncryptedMediaInitDataEncounteredCB(
+    SbPlayer player, void* context, const char* init_data_type,
+    const unsigned char* init_data, unsigned int init_data_length) {
+  StarboardPlayer* helper = static_cast<StarboardPlayer*>(context);
+  DCHECK(!helper->on_encrypted_media_init_data_encountered_cb_.is_null());
+  helper->on_encrypted_media_init_data_encountered_cb_.Run(
+      init_data_type, init_data, init_data_length);
+}
+
+void StarboardPlayer::CreatePlayerWithUrl(const std::string& url) {
+  TRACE_EVENT0("cobalt::media", "StarboardPlayer::CreatePlayerWithUrl");
+  DCHECK(message_loop_->BelongsToCurrentThread());
+
+  DCHECK(!on_encrypted_media_init_data_encountered_cb_.is_null());
+  DLOG(INFO) << "SbPlayerCreateWithUrl passed url " << url;
+  player_ = SbPlayerCreateWithUrl(
+      url.c_str(), window_, SB_PLAYER_NO_DURATION,
+      &StarboardPlayer::PlayerStatusCB,
+      &StarboardPlayer::EncryptedMediaInitDataEncounteredCB, this);
+  DCHECK(SbPlayerIsValid(player_));
+
+  if (output_mode_ == kSbPlayerOutputModeDecodeToTexture) {
+    // If the player is setup to decode to texture, then provide Cobalt with
+    // a method of querying that texture.
+    ShellMediaPlatform::Instance()
+        ->GetVideoFrameProvider()
+        ->SetGetCurrentSbDecodeTargetFunction(
+            base::Bind(&StarboardPlayer::GetCurrentSbDecodeTarget,
+                       base::Unretained(this)));
+  }
+  ShellMediaPlatform::Instance()->GetVideoFrameProvider()->SetOutputMode(
+      ToVideoFrameProviderOutputMode(output_mode_));
+
+  set_bounds_helper_->SetPlayer(this);
+
+  if (pending_set_bounds_z_index_ && pending_set_bounds_rect_) {
+    SetBounds(*pending_set_bounds_z_index_, *pending_set_bounds_rect_);
+    pending_set_bounds_z_index_ = base::nullopt_t();
+    pending_set_bounds_rect_ = base::nullopt_t();
+  }
+}
+
+#else
+
 void StarboardPlayer::CreatePlayer() {
   TRACE_EVENT0("cobalt::media", "StarboardPlayer::CreatePlayer");
   DCHECK(message_loop_->BelongsToCurrentThread());
@@ -425,6 +532,8 @@
   }
 }
 
+#endif  // SB_HAS(PLAYER_WITH_URL)
+
 SbDecodeTarget StarboardPlayer::GetCurrentSbDecodeTarget() {
   return SbPlayerGetCurrentFrame(player_);
 }
@@ -452,6 +561,9 @@
 
 void StarboardPlayer::OnDecoderStatus(SbPlayer player, SbMediaType type,
                                       SbPlayerDecoderState state, int ticket) {
+// TODO: Remove decoder status related function on a broader scope when
+//       PLAYER_WITH_URL is defined.
+#if !SB_HAS(PLAYER_WITH_URL)
   DCHECK(message_loop_->BelongsToCurrentThread());
 
   if (player_ != player || ticket != ticket_) {
@@ -484,6 +596,7 @@
   }
 
   host_->OnNeedData(SbMediaTypeToDemuxerStreamType(type));
+#endif  // !SB_HAS(PLAYER_WITH_URL)
 }
 
 void StarboardPlayer::OnPlayerStatus(SbPlayer player, SbPlayerState state,
@@ -558,6 +671,35 @@
                  helper->callback_helper_, sample_buffer));
 }
 
+#if SB_HAS(PLAYER_WITH_URL)
+// static
+SbPlayerOutputMode StarboardPlayer::ComputeSbPlayerOutputModeWithUrl(
+    bool prefer_decode_to_texture) {
+  // Try to choose the output mode according to the passed in value of
+  // |prefer_decode_to_texture|.  If the preferred output mode is unavailable
+  // though, fallback to an output mode that is available.
+  SbPlayerOutputMode output_mode = kSbPlayerOutputModeInvalid;
+  if (SbPlayerOutputModeSupportedWithUrl(kSbPlayerOutputModePunchOut)) {
+    output_mode = kSbPlayerOutputModePunchOut;
+  }
+  if ((prefer_decode_to_texture || output_mode == kSbPlayerOutputModeInvalid) &&
+      SbPlayerOutputModeSupportedWithUrl(kSbPlayerOutputModeDecodeToTexture)) {
+    output_mode = kSbPlayerOutputModeDecodeToTexture;
+  }
+  CHECK_NE(kSbPlayerOutputModeInvalid, output_mode);
+
+#if defined(COBALT_ENABLE_LIB)
+  // When Cobalt is used as a library, it doesn't control the
+  // screen and so punch-out cannot be assumed.  You will need
+  // to implement decode-to-texture support if you wish to use
+  // Cobalt as a library and play videos with it.
+  CHECK_EQ(kSbPlayerOutputModeDecodeToTexture, output_mode)
+#endif  // defined(COBALT_ENABLE_LIB)
+
+  return output_mode;
+}
+#else
+
 // static
 SbPlayerOutputMode StarboardPlayer::ComputeSbPlayerOutputMode(
     SbMediaVideoCodec codec, SbDrmSystem drm_system,
@@ -587,6 +729,6 @@
 
   return output_mode;
 }
-
+#endif  // SB_HAS(PLAYER_WITH_URL)
 }  // namespace media
 }  // namespace cobalt
diff --git a/src/cobalt/media/base/starboard_player.h b/src/cobalt/media/base/starboard_player.h
index ed318e0..b68dd6a 100644
--- a/src/cobalt/media/base/starboard_player.h
+++ b/src/cobalt/media/base/starboard_player.h
@@ -16,6 +16,7 @@
 #define COBALT_MEDIA_BASE_STARBOARD_PLAYER_H_
 
 #include <map>
+#include <string>
 #include <utility>
 
 #include "base/memory/ref_counted.h"
@@ -39,27 +40,43 @@
  public:
   class Host {
    public:
+#if !SB_HAS(PLAYER_WITH_URL)
     virtual void OnNeedData(DemuxerStream::Type type) = 0;
+#endif  // !SB_HAS(PLAYER_WITH_URL)
     virtual void OnPlayerStatus(SbPlayerState state) = 0;
 
    protected:
     ~Host() {}
   };
 
+#if SB_HAS(PLAYER_WITH_URL)
+  typedef base::Callback<void(const char*, const unsigned char*, unsigned)>
+      OnEncryptedMediaInitDataEncounteredCB;
+
+  StarboardPlayer(const scoped_refptr<base::MessageLoopProxy>& message_loop,
+                  const std::string& url, SbWindow window, Host* host,
+                  SbPlayerSetBoundsHelper* set_bounds_helper,
+                  bool prefer_decode_to_texture,
+                  const OnEncryptedMediaInitDataEncounteredCB&
+                      encrypted_media_init_data_encountered_cb);
+#else   // SB_HAS(PLAYER_WITH_URL)
   StarboardPlayer(const scoped_refptr<base::MessageLoopProxy>& message_loop,
                   const AudioDecoderConfig& audio_config,
                   const VideoDecoderConfig& video_config, SbWindow window,
                   SbDrmSystem drm_system, Host* host,
                   SbPlayerSetBoundsHelper* set_bounds_helper,
                   bool prefer_decode_to_texture);
+#endif  // SB_HAS(PLAYER_WITH_URL)
   ~StarboardPlayer();
 
   bool IsValid() const { return SbPlayerIsValid(player_); }
 
   void UpdateVideoResolution(int frame_width, int frame_height);
 
+#if !SB_HAS(PLAYER_WITH_URL)
   void WriteBuffer(DemuxerStream::Type type,
                    const scoped_refptr<DecoderBuffer>& buffer);
+#endif  // !SB_HAS(PLAYER_WITH_URL)
   void SetBounds(int z_index, const gfx::Rect& rect);
 
   void PrepareForSeek();
@@ -70,6 +87,11 @@
   void GetInfo(uint32* video_frames_decoded, uint32* video_frames_dropped,
                base::TimeDelta* media_time);
 
+#if SB_HAS(PLAYER_WITH_URL)
+  base::TimeDelta GetDuration();
+  void SetDrmSystem(SbDrmSystem drm_system);
+#endif  // SB_HAS(PLAYER_WITH_URL)
+
   void Suspend();
   void Resume();
 
@@ -110,7 +132,15 @@
   typedef std::map<const void*, std::pair<scoped_refptr<DecoderBuffer>, int> >
       DecodingBuffers;
 
+#if SB_HAS(PLAYER_WITH_URL)
+  OnEncryptedMediaInitDataEncounteredCB
+      on_encrypted_media_init_data_encountered_cb_;
+
+  void CreatePlayerWithUrl(const std::string& url);
+#else   // SB_HAS(PLAYER_WITH_URL)
   void CreatePlayer();
+#endif  // SB_HAS(PLAYER_WITH_URL)
+
   void ClearDecoderBufferCache();
 
   void OnDecoderStatus(SbPlayer player, SbMediaType type,
@@ -125,13 +155,23 @@
   static void DeallocateSampleCB(SbPlayer player, void* context,
                                  const void* sample_buffer);
 
+#if SB_HAS(PLAYER_WITH_URL)
+  // Returns the output mode that should be used for the URL player.
+  static SbPlayerOutputMode ComputeSbPlayerOutputModeWithUrl(
+      bool prefer_decode_to_texture);
+
+  static void EncryptedMediaInitDataEncounteredCB(
+      SbPlayer player, void* context, const char* init_data_type,
+      const unsigned char* init_data, unsigned int init_data_length);
+#else   // SB_HAS(PLAYER_WITH_URL)
   // Returns the output mode that should be used for a video with the given
   // specifications.
   static SbPlayerOutputMode ComputeSbPlayerOutputMode(
       SbMediaVideoCodec codec, SbDrmSystem drm_system,
       bool prefer_decode_to_texture);
-
+#endif  // SB_HAS(PLAYER_WITH_URL)
   // The following variables are initialized in the ctor and never changed.
+  std::string url_;
   const scoped_refptr<base::MessageLoopProxy> message_loop_;
   scoped_refptr<CallbackHelper> callback_helper_;
   AudioDecoderConfig audio_config_;
diff --git a/src/cobalt/media/base/user_input_monitor.cc b/src/cobalt/media/base/user_input_monitor.cc
deleted file mode 100644
index aab1594..0000000
--- a/src/cobalt/media/base/user_input_monitor.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/user_input_monitor.h"
-
-#include "base/logging.h"
-
-namespace cobalt {
-namespace media {
-
-#ifdef DISABLE_USER_INPUT_MONITOR
-std::unique_ptr<UserInputMonitor> UserInputMonitor::Create(
-    const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
-    const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) {
-  return NULL;
-}
-#endif  // DISABLE_USER_INPUT_MONITOR
-
-UserInputMonitor::UserInputMonitor()
-    : key_press_counter_references_(0),
-      mouse_listeners_count_(0),
-      mouse_listeners_(new MouseListenerList()) {}
-
-UserInputMonitor::~UserInputMonitor() {
-  DCHECK_EQ(0u, key_press_counter_references_);
-  mouse_listeners_->AssertEmpty();
-}
-
-void UserInputMonitor::AddMouseListener(MouseEventListener* listener) {
-  mouse_listeners_->AddObserver(listener);
-  {
-    base::AutoLock auto_lock(lock_);
-    mouse_listeners_count_++;
-    if (mouse_listeners_count_ == 1) {
-      StartMouseMonitoring();
-      DVLOG(2) << "Started mouse monitoring.";
-    }
-  }
-}
-
-void UserInputMonitor::RemoveMouseListener(MouseEventListener* listener) {
-  mouse_listeners_->RemoveObserver(listener);
-  {
-    base::AutoLock auto_lock(lock_);
-    DCHECK_NE(mouse_listeners_count_, 0u);
-    mouse_listeners_count_--;
-    if (mouse_listeners_count_ == 0) {
-      StopMouseMonitoring();
-      DVLOG(2) << "Stopped mouse monitoring.";
-    }
-  }
-}
-
-void UserInputMonitor::EnableKeyPressMonitoring() {
-  base::AutoLock auto_lock(lock_);
-  ++key_press_counter_references_;
-  if (key_press_counter_references_ == 1) {
-    StartKeyboardMonitoring();
-    DVLOG(2) << "Started keyboard monitoring.";
-  }
-}
-
-void UserInputMonitor::DisableKeyPressMonitoring() {
-  base::AutoLock auto_lock(lock_);
-  DCHECK_NE(key_press_counter_references_, 0u);
-  --key_press_counter_references_;
-  if (key_press_counter_references_ == 0) {
-    StopKeyboardMonitoring();
-    DVLOG(2) << "Stopped keyboard monitoring.";
-  }
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/user_input_monitor.h b/src/cobalt/media/base/user_input_monitor.h
deleted file mode 100644
index caf7819..0000000
--- a/src/cobalt/media/base/user_input_monitor.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_USER_INPUT_MONITOR_H_
-#define COBALT_MEDIA_BASE_USER_INPUT_MONITOR_H_
-
-#include <memory>
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-#include "base/observer_list_threadsafe.h"
-#include "base/synchronization/lock.h"
-#include "cobalt/media/base/media_export.h"
-#include "starboard/types.h"
-
-struct SkIPoint;
-
-namespace base {
-class SingleThreadTaskRunner;
-}  // namespace base
-
-namespace cobalt {
-namespace media {
-
-// Monitors and notifies about mouse movements and keyboard events.
-// Thread safe. The listeners are called on the thread where the listeners are
-// added.
-class MEDIA_EXPORT UserInputMonitor {
- public:
-  // The interface to receive mouse movement events.
-  class MEDIA_EXPORT MouseEventListener {
-   public:
-    // |position| is the new mouse position.
-    virtual void OnMouseMoved(const SkIPoint& position) = 0;
-
-   protected:
-    virtual ~MouseEventListener() {}
-  };
-  typedef base::ObserverListThreadSafe<UserInputMonitor::MouseEventListener>
-      MouseListenerList;
-
-  UserInputMonitor();
-  virtual ~UserInputMonitor();
-
-  // Creates a platform-specific instance of UserInputMonitor.
-  // |io_task_runner| is the task runner for an IO thread.
-  // |ui_task_runner| is the task runner for a UI thread.
-  static std::unique_ptr<UserInputMonitor> Create(
-      const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
-      const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner);
-
-  // The same |listener| should only be added once.
-  // The clients should make sure to call Remove*Listener before |listener| is
-  // destroyed.
-  void AddMouseListener(MouseEventListener* listener);
-  void RemoveMouseListener(MouseEventListener* listener);
-
-  // A caller must call EnableKeyPressMonitoring and
-  // DisableKeyPressMonitoring in pair.
-  void EnableKeyPressMonitoring();
-  void DisableKeyPressMonitoring();
-
-  // Returns the number of keypresses. The starting point from when it is
-  // counted is not guaranteed, but consistent within the pair of calls of
-  // EnableKeyPressMonitoring and DisableKeyPressMonitoring. So a caller can
-  // use the difference between the values returned at two times to get the
-  // number of keypresses happened within that time period, but should not make
-  // any assumption on the initial value.
-  virtual size_t GetKeyPressCount() const = 0;
-
- protected:
-  scoped_refptr<MouseListenerList> mouse_listeners() {
-    return mouse_listeners_;
-  }
-
- private:
-  virtual void StartKeyboardMonitoring() = 0;
-  virtual void StopKeyboardMonitoring() = 0;
-  virtual void StartMouseMonitoring() = 0;
-  virtual void StopMouseMonitoring() = 0;
-
-  base::Lock lock_;
-  size_t key_press_counter_references_;
-  size_t mouse_listeners_count_;
-  scoped_refptr<MouseListenerList> mouse_listeners_;
-
-  DISALLOW_COPY_AND_ASSIGN(UserInputMonitor);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_USER_INPUT_MONITOR_H_
diff --git a/src/cobalt/media/base/video_capture_types.cc b/src/cobalt/media/base/video_capture_types.cc
deleted file mode 100644
index 8f00415..0000000
--- a/src/cobalt/media/base/video_capture_types.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/video_capture_types.h"
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/stringprintf.h"
-#include "cobalt/media/base/limits.h"
-#include "cobalt/media/base/video_frame.h"
-
-namespace cobalt {
-namespace media {
-
-// This list is ordered by precedence of use.
-static VideoPixelFormat const kSupportedCapturePixelFormats[] = {
-    PIXEL_FORMAT_I420,  PIXEL_FORMAT_YV12,  PIXEL_FORMAT_NV12,
-    PIXEL_FORMAT_NV21,  PIXEL_FORMAT_UYVY,  PIXEL_FORMAT_YUY2,
-    PIXEL_FORMAT_RGB24, PIXEL_FORMAT_RGB32, PIXEL_FORMAT_ARGB,
-    PIXEL_FORMAT_MJPEG,
-};
-
-VideoCaptureFormat::VideoCaptureFormat()
-    : frame_rate(0.0f),
-      pixel_format(PIXEL_FORMAT_UNKNOWN),
-      pixel_storage(PIXEL_STORAGE_CPU) {}
-
-VideoCaptureFormat::VideoCaptureFormat(const gfx::Size& frame_size,
-                                       float frame_rate,
-                                       VideoPixelFormat pixel_format)
-    : frame_size(frame_size),
-      frame_rate(frame_rate),
-      pixel_format(pixel_format),
-      pixel_storage(PIXEL_STORAGE_CPU) {}
-
-VideoCaptureFormat::VideoCaptureFormat(const gfx::Size& frame_size,
-                                       float frame_rate,
-                                       VideoPixelFormat pixel_format,
-                                       VideoPixelStorage pixel_storage)
-    : frame_size(frame_size),
-      frame_rate(frame_rate),
-      pixel_format(pixel_format),
-      pixel_storage(pixel_storage) {}
-
-bool VideoCaptureFormat::IsValid() const {
-  return (frame_size.width() < media::limits::kMaxDimension) &&
-         (frame_size.height() < media::limits::kMaxDimension) &&
-         (frame_size.GetArea() >= 0) &&
-         (frame_size.GetArea() < media::limits::kMaxCanvas) &&
-         (frame_rate >= 0.0f) &&
-         (frame_rate < media::limits::kMaxFramesPerSecond) &&
-         (pixel_format >= PIXEL_FORMAT_UNKNOWN &&
-          pixel_format <= PIXEL_FORMAT_MAX) &&
-         (pixel_storage == PIXEL_STORAGE_CPU ||
-          pixel_storage == PIXEL_STORAGE_GPUMEMORYBUFFER);
-}
-
-size_t VideoCaptureFormat::ImageAllocationSize() const {
-  return VideoFrame::AllocationSize(pixel_format, frame_size);
-}
-
-// static
-std::string VideoCaptureFormat::ToString(const VideoCaptureFormat& format) {
-  // Beware: This string is parsed by manager.js:parseVideoCaptureFormat_,
-  // take care when changing the formatting.
-  return base::StringPrintf(
-      "(%s)@%.3ffps, pixel format: %s, storage: %s",
-      format.frame_size.ToString().c_str(), format.frame_rate,
-      VideoPixelFormatToString(format.pixel_format).c_str(),
-      PixelStorageToString(format.pixel_storage).c_str());
-}
-
-// static
-std::string VideoCaptureFormat::PixelStorageToString(
-    VideoPixelStorage storage) {
-  switch (storage) {
-    case PIXEL_STORAGE_CPU:
-      return "CPU";
-    case PIXEL_STORAGE_GPUMEMORYBUFFER:
-      return "GPUMEMORYBUFFER";
-  }
-  NOTREACHED() << "Invalid VideoPixelStorage provided: "
-               << static_cast<int>(storage);
-  return std::string();
-}
-
-// static
-bool VideoCaptureFormat::ComparePixelFormatPreference(
-    const VideoPixelFormat& lhs, const VideoPixelFormat& rhs) {
-  auto* format_lhs = std::find(
-      kSupportedCapturePixelFormats,
-      kSupportedCapturePixelFormats + arraysize(kSupportedCapturePixelFormats),
-      lhs);
-  auto* format_rhs = std::find(
-      kSupportedCapturePixelFormats,
-      kSupportedCapturePixelFormats + arraysize(kSupportedCapturePixelFormats),
-      rhs);
-  return format_lhs < format_rhs;
-}
-
-VideoCaptureParams::VideoCaptureParams()
-    : resolution_change_policy(RESOLUTION_POLICY_FIXED_RESOLUTION),
-      power_line_frequency(PowerLineFrequency::FREQUENCY_DEFAULT) {}
-
-bool VideoCaptureParams::IsValid() const {
-  return requested_format.IsValid() &&
-         resolution_change_policy >= RESOLUTION_POLICY_FIXED_RESOLUTION &&
-         resolution_change_policy <= RESOLUTION_POLICY_LAST &&
-         power_line_frequency >= PowerLineFrequency::FREQUENCY_DEFAULT &&
-         power_line_frequency <= PowerLineFrequency::FREQUENCY_MAX;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/video_capture_types.h b/src/cobalt/media/base/video_capture_types.h
deleted file mode 100644
index 0be06a4..0000000
--- a/src/cobalt/media/base/video_capture_types.h
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_VIDEO_CAPTURE_TYPES_H_
-#define COBALT_MEDIA_BASE_VIDEO_CAPTURE_TYPES_H_
-
-#include <string>
-#include <vector>
-
-#include "build/build_config.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/video_types.h"
-#include "starboard/types.h"
-#include "ui/gfx/size.h"
-
-namespace cobalt {
-namespace media {
-
-// TODO(wjia): this type should be defined in a common place and
-// shared with device manager.
-typedef int VideoCaptureSessionId;
-
-// Storage type for the pixels. In principle, all combinations of Storage and
-// Format are possible, though some are very typical, such as texture + ARGB,
-// and others are only available if the platform allows it e.g. GpuMemoryBuffer.
-// TODO(mcasas): http://crbug.com/504160 Consider making this an enum class.
-enum VideoPixelStorage {
-  PIXEL_STORAGE_CPU,
-  PIXEL_STORAGE_GPUMEMORYBUFFER,
-  PIXEL_STORAGE_MAX = PIXEL_STORAGE_GPUMEMORYBUFFER,
-};
-
-// Policies for capture devices that have source content that varies in size.
-// It is up to the implementation how the captured content will be transformed
-// (e.g., scaling and/or letterboxing) in order to produce video frames that
-// strictly adheree to one of these policies.
-enum ResolutionChangePolicy {
-  // Capture device outputs a fixed resolution all the time. The resolution of
-  // the first frame is the resolution for all frames.
-  RESOLUTION_POLICY_FIXED_RESOLUTION,
-
-  // Capture device is allowed to output frames of varying resolutions. The
-  // width and height will not exceed the maximum dimensions specified. The
-  // aspect ratio of the frames will match the aspect ratio of the maximum
-  // dimensions as closely as possible.
-  RESOLUTION_POLICY_FIXED_ASPECT_RATIO,
-
-  // Capture device is allowed to output frames of varying resolutions not
-  // exceeding the maximum dimensions specified.
-  RESOLUTION_POLICY_ANY_WITHIN_LIMIT,
-
-  // Must always be equal to largest entry in the enum.
-  RESOLUTION_POLICY_LAST = RESOLUTION_POLICY_ANY_WITHIN_LIMIT,
-};
-
-// Potential values of the googPowerLineFrequency optional constraint passed to
-// getUserMedia. Note that the numeric values are currently significant, and are
-// used to map enum values to corresponding frequency values.
-// TODO(ajose): http://crbug.com/525167 Consider making this a class.
-enum class PowerLineFrequency {
-  FREQUENCY_DEFAULT = 0,
-  FREQUENCY_50HZ = 50,
-  FREQUENCY_60HZ = 60,
-  FREQUENCY_MAX = FREQUENCY_60HZ
-};
-
-// Assert that the int:frequency mapping is correct.
-static_assert(static_cast<int>(PowerLineFrequency::FREQUENCY_DEFAULT) == 0,
-              "static_cast<int>(FREQUENCY_DEFAULT) must equal 0.");
-static_assert(static_cast<int>(PowerLineFrequency::FREQUENCY_50HZ) == 50,
-              "static_cast<int>(FREQUENCY_DEFAULT) must equal 50.");
-static_assert(static_cast<int>(PowerLineFrequency::FREQUENCY_60HZ) == 60,
-              "static_cast<int>(FREQUENCY_DEFAULT) must equal 60.");
-
-// Some drivers use rational time per frame instead of float frame rate, this
-// constant k is used to convert between both: A fps -> [k/k*A] seconds/frame.
-const int kFrameRatePrecision = 10000;
-
-// Video capture format specification.
-// This class is used by the video capture device to specify the format of every
-// frame captured and returned to a client. It is also used to specify a
-// supported capture format by a device.
-struct MEDIA_EXPORT VideoCaptureFormat {
-  VideoCaptureFormat();
-  VideoCaptureFormat(const gfx::Size& frame_size, float frame_rate,
-                     VideoPixelFormat pixel_format);
-  VideoCaptureFormat(const gfx::Size& frame_size, float frame_rate,
-                     VideoPixelFormat pixel_format,
-                     VideoPixelStorage pixel_storage);
-
-  static std::string ToString(const VideoCaptureFormat& format);
-  static std::string PixelStorageToString(VideoPixelStorage storage);
-
-  // Compares the priority of the pixel formats. Returns true if |lhs| is the
-  // preferred pixel format in comparison with |rhs|. Returns false otherwise.
-  static bool ComparePixelFormatPreference(const VideoPixelFormat& lhs,
-                                           const VideoPixelFormat& rhs);
-
-  // Returns the required buffer size to hold an image of a given
-  // VideoCaptureFormat with no padding and tightly packed.
-  size_t ImageAllocationSize() const;
-
-  // Checks that all values are in the expected range. All limits are specified
-  // in media::Limits.
-  bool IsValid() const;
-
-  bool operator==(const VideoCaptureFormat& other) const {
-    return frame_size == other.frame_size && frame_rate == other.frame_rate &&
-           pixel_format == other.pixel_format;
-  }
-
-  gfx::Size frame_size;
-  float frame_rate;
-  VideoPixelFormat pixel_format;
-  VideoPixelStorage pixel_storage;
-};
-
-typedef std::vector<VideoCaptureFormat> VideoCaptureFormats;
-
-// Parameters for starting video capture.
-// This class is used by the client of a video capture device to specify the
-// format of frames in which the client would like to have captured frames
-// returned.
-struct MEDIA_EXPORT VideoCaptureParams {
-  VideoCaptureParams();
-
-  // Returns true if requested_format.IsValid() and all other values are within
-  // their expected ranges.
-  bool IsValid() const;
-
-  bool operator==(const VideoCaptureParams& other) const {
-    return requested_format == other.requested_format &&
-           resolution_change_policy == other.resolution_change_policy &&
-           power_line_frequency == other.power_line_frequency;
-  }
-
-  // Requests a resolution and format at which the capture will occur.
-  VideoCaptureFormat requested_format;
-
-  // Policy for resolution change.
-  ResolutionChangePolicy resolution_change_policy;
-
-  // User-specified power line frequency.
-  PowerLineFrequency power_line_frequency;
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_VIDEO_CAPTURE_TYPES_H_
diff --git a/src/cobalt/media/base/video_capturer_source.cc b/src/cobalt/media/base/video_capturer_source.cc
deleted file mode 100644
index cbaa4f3..0000000
--- a/src/cobalt/media/base/video_capturer_source.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/video_capturer_source.h"
-
-namespace cobalt {
-namespace media {
-
-// TODO(mcasas): VideoCapturerSource is implemented in other .dll(s) (e.g.
-// content) in Windows component build. The current compiler fails to generate
-// object files for this destructor if it's defined in the header file and that
-// breaks linking. Consider removing this file when the compiler+linker is able
-// to generate symbols across linking units.
-VideoCapturerSource::~VideoCapturerSource() {}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/video_capturer_source.h b/src/cobalt/media/base/video_capturer_source.h
deleted file mode 100644
index d1048a5..0000000
--- a/src/cobalt/media/base/video_capturer_source.h
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_VIDEO_CAPTURER_SOURCE_H_
-#define COBALT_MEDIA_BASE_VIDEO_CAPTURER_SOURCE_H_
-
-#include <string>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "base/time.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/video_capture_types.h"
-
-namespace cobalt {
-namespace media {
-
-class VideoFrame;
-
-// VideoCapturerSource is an interface representing the source for captured
-// video.  An implementation will periodically call the frame callback with new
-// video frames.
-class MEDIA_EXPORT VideoCapturerSource {
- public:
-  virtual ~VideoCapturerSource();
-
-  // This callback is used to deliver video frames.
-  //
-  // |estimated_capture_time| - The capture time of the delivered video
-  // frame. This field represents the local time at which either: 1) the frame
-  // was generated, if it was done so locally; or 2) the targeted play-out time
-  // of the frame, if it was generated from a remote source. Either way, an
-  // implementation should not present the frame before this point-in-time. This
-  // value is NOT a high-resolution timestamp, and so it should not be used as a
-  // presentation time; but, instead, it should be used for buffering playback
-  // and for A/V synchronization purposes. NOTE: It is possible for this value
-  // to be null if the current implementation lacks this timing information.
-  //
-  // |video_frame->timestamp()| gives the presentation timestamp of the video
-  // frame relative to the first frame generated by the corresponding source.
-  // Because a source can start generating frames before a subscriber is added,
-  // the first video frame delivered may not have timestamp equal to 0.
-  using VideoCaptureDeliverFrameCB =
-      base::Callback<void(const scoped_refptr<media::VideoFrame>& video_frame,
-                          base::TimeTicks estimated_capture_time)>;
-
-  using VideoCaptureDeviceFormatsCB =
-      base::Callback<void(const media::VideoCaptureFormats&)>;
-
-  using RunningCallback = base::Callback<void(bool)>;
-
-  // Collects the formats that can currently be used.
-  // |max_requested_height|, |max_requested_width|, and
-  // |max_requested_frame_rate| is used by Tab and Screen capture to decide what
-  // resolution/framerate to generate. |callback| is triggered when the formats
-  // have been collected.
-  virtual void GetCurrentSupportedFormats(
-      int max_requested_width, int max_requested_height,
-      double max_requested_frame_rate,
-      const VideoCaptureDeviceFormatsCB& callback) = 0;
-
-  // Starts capturing frames using the capture |params|. |new_frame_callback| is
-  // triggered when a new video frame is available.
-  // If capturing is started successfully then |running_callback| will be
-  // called with a parameter of true. Note that some implementations may
-  // simply reject StartCapture (by calling running_callback with a false
-  // argument) if called with the wrong task runner.
-  // If capturing fails to start or stopped due to an external event then
-  // |running_callback| will be called with a parameter of false.
-  // |running_callback| will always be called on the same thread as the
-  // StartCapture.
-  virtual void StartCapture(
-      const media::VideoCaptureParams& params,
-      const VideoCaptureDeliverFrameCB& new_frame_callback,
-      const RunningCallback& running_callback) = 0;
-
-  // Asks source to send a refresh frame. In cases where source does not provide
-  // a continuous rate of new frames (e.g. canvas capture, screen capture where
-  // the screen's content has not changed in a while), consumers may request a
-  // "refresh frame" to be delivered. For instance, this would be needed when
-  // a new sink is added to a MediaStreamTrack.
-  //
-  // The default implementation is a no-op and implementations are not required
-  // to honor this request. If they decide to and capturing is started
-  // successfully, then |new_frame_callback| should be called with a frame.
-  //
-  // Note: This should only be called after StartCapture() and before
-  // StopCapture(). Otherwise, its behavior is undefined.
-  virtual void RequestRefreshFrame() {}
-
-  // Optionally suspends frame delivery. The source may or may not honor this
-  // request. Thus, the caller cannot assume frame delivery will actually
-  // stop. Even if frame delivery is suspended, this might not take effect
-  // immediately.
-  //
-  // The purpose of this is to allow minimizing resource usage while
-  // there are no frame consumers present.
-  //
-  // Note: This should only be called after StartCapture() and before
-  // StopCapture(). Otherwise, its behavior is undefined.
-  virtual void MaybeSuspend() {}
-
-  // Resumes frame delivery, if it was suspended. If frame delivery was not
-  // suspended, this is a no-op, and frame delivery will continue.
-  //
-  // Note: This should only be called after StartCapture() and before
-  // StopCapture(). Otherwise, its behavior is undefined.
-  virtual void Resume() {}
-
-  // Stops capturing frames and clears all callbacks including the
-  // SupportedFormatsCallback callback. Note that queued frame callbacks
-  // may still occur after this call, so the caller must take care to
-  // use refcounted or weak references in |new_frame_callback|.
-  virtual void StopCapture() = 0;
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_VIDEO_CAPTURER_SOURCE_H_
diff --git a/src/cobalt/media/base/video_frame_pool.cc b/src/cobalt/media/base/video_frame_pool.cc
deleted file mode 100644
index 977523e..0000000
--- a/src/cobalt/media/base/video_frame_pool.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/video_frame_pool.h"
-
-#include <list>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-
-namespace cobalt {
-namespace media {
-
-class VideoFramePool::PoolImpl
-    : public base::RefCountedThreadSafe<VideoFramePool::PoolImpl> {
- public:
-  PoolImpl();
-
-  // See VideoFramePool::CreateFrame() for usage.
-  scoped_refptr<VideoFrame> CreateFrame(VideoPixelFormat format,
-                                        const gfx::Size& coded_size,
-                                        const gfx::Rect& visible_rect,
-                                        const gfx::Size& natural_size,
-                                        base::TimeDelta timestamp);
-
-  // Shuts down the frame pool and releases all frames in |frames_|.
-  // Once this is called frames will no longer be inserted back into
-  // |frames_|.
-  void Shutdown();
-
-  size_t GetPoolSizeForTesting() const { return frames_.size(); }
-
- private:
-  friend class base::RefCountedThreadSafe<VideoFramePool::PoolImpl>;
-  ~PoolImpl();
-
-  // Called when the frame wrapper gets destroyed.
-  // |frame| is the actual frame that was wrapped and is placed
-  // in |frames_| by this function so it can be reused.
-  void FrameReleased(const scoped_refptr<VideoFrame>& frame);
-
-  base::Lock lock_;
-  bool is_shutdown_;
-  std::list<scoped_refptr<VideoFrame> > frames_;
-
-  DISALLOW_COPY_AND_ASSIGN(PoolImpl);
-};
-
-VideoFramePool::PoolImpl::PoolImpl() : is_shutdown_(false) {}
-
-VideoFramePool::PoolImpl::~PoolImpl() { DCHECK(is_shutdown_); }
-
-scoped_refptr<VideoFrame> VideoFramePool::PoolImpl::CreateFrame(
-    VideoPixelFormat format, const gfx::Size& coded_size,
-    const gfx::Rect& visible_rect, const gfx::Size& natural_size,
-    base::TimeDelta timestamp) {
-  base::AutoLock auto_lock(lock_);
-  DCHECK(!is_shutdown_);
-
-  scoped_refptr<VideoFrame> frame;
-  while (!frame.get() && !frames_.empty()) {
-    scoped_refptr<VideoFrame> pool_frame = frames_.front();
-    frames_.pop_front();
-
-    if (pool_frame->format() == format &&
-        pool_frame->coded_size() == coded_size &&
-        pool_frame->visible_rect() == visible_rect &&
-        pool_frame->natural_size() == natural_size) {
-      frame = pool_frame;
-      frame->set_timestamp(timestamp);
-      frame->metadata()->Clear();
-      break;
-    }
-  }
-
-  if (!frame.get()) {
-    frame = VideoFrame::CreateZeroInitializedFrame(
-        format, coded_size, visible_rect, natural_size, timestamp);
-    // This can happen if the arguments are not valid.
-    if (!frame) {
-      LOG(ERROR) << "Failed to create a video frame";
-      return NULL;
-    }
-  }
-
-  scoped_refptr<VideoFrame> wrapped_frame = VideoFrame::WrapVideoFrame(
-      frame, frame->format(), frame->visible_rect(), frame->natural_size());
-  wrapped_frame->AddDestructionObserver(
-      base::Bind(&VideoFramePool::PoolImpl::FrameReleased, this, frame));
-  return wrapped_frame;
-}
-
-void VideoFramePool::PoolImpl::Shutdown() {
-  base::AutoLock auto_lock(lock_);
-  is_shutdown_ = true;
-  frames_.clear();
-}
-
-void VideoFramePool::PoolImpl::FrameReleased(
-    const scoped_refptr<VideoFrame>& frame) {
-  base::AutoLock auto_lock(lock_);
-  if (is_shutdown_) return;
-
-  frames_.push_back(frame);
-}
-
-VideoFramePool::VideoFramePool() : pool_(new PoolImpl()) {}
-
-VideoFramePool::~VideoFramePool() { pool_->Shutdown(); }
-
-scoped_refptr<VideoFrame> VideoFramePool::CreateFrame(
-    VideoPixelFormat format, const gfx::Size& coded_size,
-    const gfx::Rect& visible_rect, const gfx::Size& natural_size,
-    base::TimeDelta timestamp) {
-  return pool_->CreateFrame(format, coded_size, visible_rect, natural_size,
-                            timestamp);
-}
-
-size_t VideoFramePool::GetPoolSizeForTesting() const {
-  return pool_->GetPoolSizeForTesting();
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/video_frame_pool.h b/src/cobalt/media/base/video_frame_pool.h
deleted file mode 100644
index 3ad816a..0000000
--- a/src/cobalt/media/base/video_frame_pool.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_VIDEO_FRAME_POOL_H_
-#define COBALT_MEDIA_BASE_VIDEO_FRAME_POOL_H_
-
-#include "base/basictypes.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/video_frame.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace media {
-
-// Simple VideoFrame pool used to avoid unnecessarily allocating and destroying
-// VideoFrame objects. The pool manages the memory for the VideoFrame
-// returned by CreateFrame(). When one of these VideoFrames is destroyed,
-// the memory is returned to the pool for use by a subsequent CreateFrame()
-// call. The memory in the pool is retained for the life of the
-// VideoFramePool object. If the parameters passed to CreateFrame() change
-// during the life of this object, then the memory used by frames with the old
-// parameter values will be purged from the pool.
-class MEDIA_EXPORT VideoFramePool {
- public:
-  VideoFramePool();
-  ~VideoFramePool();
-
-  // Returns a frame from the pool that matches the specified
-  // parameters or creates a new frame if no suitable frame exists in
-  // the pool. The pool is drained if no matching frame is found.
-  // The buffer for the new frame will be zero initialized.  Reused frames will
-  // not be zero initialized.
-  scoped_refptr<VideoFrame> CreateFrame(VideoPixelFormat format,
-                                        const gfx::Size& coded_size,
-                                        const gfx::Rect& visible_rect,
-                                        const gfx::Size& natural_size,
-                                        base::TimeDelta timestamp);
-
- protected:
-  friend class VideoFramePoolTest;
-
-  // Returns the number of frames in the pool for testing purposes.
-  size_t GetPoolSizeForTesting() const;
-
- private:
-  class PoolImpl;
-  scoped_refptr<PoolImpl> pool_;
-
-  DISALLOW_COPY_AND_ASSIGN(VideoFramePool);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_VIDEO_FRAME_POOL_H_
diff --git a/src/cobalt/media/base/video_frame_pool_unittest.cc b/src/cobalt/media/base/video_frame_pool_unittest.cc
deleted file mode 100644
index 602b601..0000000
--- a/src/cobalt/media/base/video_frame_pool_unittest.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <memory>
-
-#include "cobalt/media/base/video_frame_pool.h"
-#include "starboard/memory.h"
-#include "starboard/types.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace cobalt {
-namespace media {
-
-class VideoFramePoolTest : public ::testing::Test {
- public:
-  VideoFramePoolTest() : pool_(new VideoFramePool()) {}
-
-  scoped_refptr<VideoFrame> CreateFrame(VideoPixelFormat format,
-                                        int timestamp_ms) {
-    gfx::Size coded_size(320, 240);
-    gfx::Rect visible_rect(coded_size);
-    gfx::Size natural_size(coded_size);
-
-    scoped_refptr<VideoFrame> frame =
-        pool_->CreateFrame(format, coded_size, visible_rect, natural_size,
-                           base::TimeDelta::FromMilliseconds(timestamp_ms));
-    EXPECT_EQ(format, frame->format());
-    EXPECT_EQ(base::TimeDelta::FromMilliseconds(timestamp_ms),
-              frame->timestamp());
-    EXPECT_EQ(coded_size, frame->coded_size());
-    EXPECT_EQ(visible_rect, frame->visible_rect());
-    EXPECT_EQ(natural_size, frame->natural_size());
-
-    return frame;
-  }
-
-  void CheckPoolSize(size_t size) const {
-    EXPECT_EQ(size, pool_->GetPoolSizeForTesting());
-  }
-
- protected:
-  std::unique_ptr<VideoFramePool> pool_;
-};
-
-TEST_F(VideoFramePoolTest, FrameInitializedAndZeroed) {
-  scoped_refptr<VideoFrame> frame = CreateFrame(PIXEL_FORMAT_YV12, 10);
-
-  // Verify that frame is initialized with zeros.
-  for (size_t i = 0; i < VideoFrame::NumPlanes(frame->format()); ++i)
-    EXPECT_EQ(0, frame->data(i)[0]);
-}
-
-TEST_F(VideoFramePoolTest, SimpleFrameReuse) {
-  scoped_refptr<VideoFrame> frame = CreateFrame(PIXEL_FORMAT_YV12, 10);
-  const uint8_t* old_y_data = frame->data(VideoFrame::kYPlane);
-
-  // Clear frame reference to return the frame to the pool.
-  frame = NULL;
-
-  // Verify that the next frame from the pool uses the same memory.
-  scoped_refptr<VideoFrame> new_frame = CreateFrame(PIXEL_FORMAT_YV12, 20);
-  EXPECT_EQ(old_y_data, new_frame->data(VideoFrame::kYPlane));
-}
-
-TEST_F(VideoFramePoolTest, SimpleFormatChange) {
-  scoped_refptr<VideoFrame> frame_a = CreateFrame(PIXEL_FORMAT_YV12, 10);
-  scoped_refptr<VideoFrame> frame_b = CreateFrame(PIXEL_FORMAT_YV12, 10);
-
-  // Clear frame references to return the frames to the pool.
-  frame_a = NULL;
-  frame_b = NULL;
-
-  // Verify that both frames are in the pool.
-  CheckPoolSize(2u);
-
-  // Verify that requesting a frame with a different format causes the pool
-  // to get drained.
-  scoped_refptr<VideoFrame> new_frame = CreateFrame(PIXEL_FORMAT_YV12A, 10);
-  CheckPoolSize(0u);
-}
-
-TEST_F(VideoFramePoolTest, FrameValidAfterPoolDestruction) {
-  scoped_refptr<VideoFrame> frame = CreateFrame(PIXEL_FORMAT_YV12, 10);
-
-  // Destroy the pool.
-  pool_.reset();
-
-  // Write to the Y plane. The memory tools should detect a
-  // use-after-free if the storage was actually removed by pool destruction.
-  SbMemorySet(
-      frame->data(VideoFrame::kYPlane), 0xff,
-      frame->rows(VideoFrame::kYPlane) * frame->stride(VideoFrame::kYPlane));
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/video_renderer.cc b/src/cobalt/media/base/video_renderer.cc
deleted file mode 100644
index b1ee475..0000000
--- a/src/cobalt/media/base/video_renderer.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/video_renderer.h"
-
-namespace cobalt {
-namespace media {
-
-VideoRenderer::VideoRenderer() {}
-VideoRenderer::~VideoRenderer() {}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/base/video_renderer.h b/src/cobalt/media/base/video_renderer.h
deleted file mode 100644
index a8c8a2c..0000000
--- a/src/cobalt/media/base/video_renderer.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_VIDEO_RENDERER_H_
-#define COBALT_MEDIA_BASE_VIDEO_RENDERER_H_
-
-#include "base/basictypes.h"
-#include "base/callback_forward.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/pipeline_status.h"
-#include "cobalt/media/base/time_source.h"
-
-namespace cobalt {
-namespace media {
-
-class CdmContext;
-class DemuxerStream;
-class RendererClient;
-
-class MEDIA_EXPORT VideoRenderer {
- public:
-  VideoRenderer();
-
-  // Stops all operations and fires all pending callbacks.
-  virtual ~VideoRenderer();
-
-  // Initializes a VideoRenderer with |stream|, executing |init_cb| upon
-  // completion. If initialization fails, only |init_cb|
-  // (not RendererClient::OnError) will be called.
-  //
-  // |cdm_context| can be used to handle encrypted streams. May be null if the
-  // stream is not encrypted.
-  //
-  // |wall_clock_time_cb| is used to convert media timestamps into wallclock
-  // timestamps.
-  virtual void Initialize(DemuxerStream* stream, CdmContext* cdm_context,
-                          RendererClient* client,
-                          const TimeSource::WallClockTimeCB& wall_clock_time_cb,
-                          const PipelineStatusCB& init_cb) = 0;
-
-  // Discards any video data and stops reading from |stream|, executing
-  // |callback| when completed.
-  //
-  // Clients should expect |buffering_state_cb| to be called with
-  // BUFFERING_HAVE_NOTHING while flushing is in progress.
-  virtual void Flush(const base::Closure& callback) = 0;
-
-  // Starts playback at |timestamp| by reading from |stream| and decoding and
-  // rendering video.
-  //
-  // Only valid to call after a successful Initialize() or Flush().
-  virtual void StartPlayingFrom(base::TimeDelta timestamp) = 0;
-
-  // Called when time starts or stops moving. Time progresses when a base time
-  // has been set and the playback rate is > 0. If either condition changes,
-  // time stops progressing.
-  virtual void OnTimeProgressing() = 0;
-  virtual void OnTimeStopped() = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(VideoRenderer);
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_VIDEO_RENDERER_H_
diff --git a/src/cobalt/media/base/video_renderer_sink.h b/src/cobalt/media/base/video_renderer_sink.h
deleted file mode 100644
index f81d575..0000000
--- a/src/cobalt/media/base/video_renderer_sink.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COBALT_MEDIA_BASE_VIDEO_RENDERER_SINK_H_
-#define COBALT_MEDIA_BASE_VIDEO_RENDERER_SINK_H_
-
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/time.h"
-#include "cobalt/media/base/media_export.h"
-#include "cobalt/media/base/video_frame.h"
-
-namespace cobalt {
-namespace media {
-
-// VideoRendererSink is an interface representing the end-point for rendered
-// video frames.  An implementation is expected to periodically call Render() on
-// a callback object.
-class MEDIA_EXPORT VideoRendererSink {
- public:
-  class RenderCallback {
-   public:
-    // Returns a VideoFrame for rendering which should be displayed within the
-    // presentation interval [|deadline_min|, |deadline_max|].  Returns NULL if
-    // no frame or no new frame (since the last Render() call) is available for
-    // rendering within the requested interval.  Intervals are expected to be
-    // regular, contiguous, and monotonically increasing.  Irregular intervals
-    // may affect the rendering decisions made by the underlying callback.
-    //
-    // If |background_rendering| is true, the VideoRenderSink is pumping
-    // callbacks at a lower frequency than normal and the results of the
-    // Render() call may not be used.
-    virtual scoped_refptr<VideoFrame> Render(base::TimeTicks deadline_min,
-                                             base::TimeTicks deadline_max,
-                                             bool background_rendering) = 0;
-
-    // Called by the sink when a VideoFrame previously returned via Render() was
-    // not actually rendered.  Must be called before the next Render() call.
-    virtual void OnFrameDropped() = 0;
-
-    virtual ~RenderCallback() {}
-  };
-
-  // Starts video rendering.  See RenderCallback for more details.  Must be
-  // called to receive Render() callbacks.  Callbacks may start immediately, so
-  // |callback| must be ready to receive callbacks before calling Start().
-  virtual void Start(RenderCallback* callback) = 0;
-
-  // Stops video rendering, waits for any outstanding calls to the |callback|
-  // given to Start() to complete before returning.  No new calls to |callback|
-  // will be issued after this method returns.  May be used as a means of power
-  // conservation by the sink implementation, so clients should call this
-  // liberally if no new frames are expected.
-  virtual void Stop() = 0;
-
-  // Instead of using a callback driven rendering path, allow clients to paint a
-  // single frame as they see fit without regard for the compositor; this is
-  // useful for painting poster images or hole frames without having to issue a
-  // Start() -> Render() -> Stop(). Clients are free to mix usage of Render()
-  // based painting and PaintSingleFrame().
-  virtual void PaintSingleFrame(const scoped_refptr<VideoFrame>& frame,
-                                bool repaint_duplicate_frame = false) = 0;
-
-  virtual ~VideoRendererSink() {}
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_BASE_VIDEO_RENDERER_SINK_H_
diff --git a/src/cobalt/media/base/video_types.cc b/src/cobalt/media/base/video_types.cc
deleted file mode 100644
index 7e53cf8..0000000
--- a/src/cobalt/media/base/video_types.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cobalt/media/base/video_types.h"
-
-#include "base/logging.h"
-
-namespace cobalt {
-namespace media {
-
-std::string VideoPixelFormatToString(VideoPixelFormat format) {
-  switch (format) {
-    case PIXEL_FORMAT_UNKNOWN:
-      return "PIXEL_FORMAT_UNKNOWN";
-    case PIXEL_FORMAT_I420:
-      return "PIXEL_FORMAT_I420";
-    case PIXEL_FORMAT_YV12:
-      return "PIXEL_FORMAT_YV12";
-    case PIXEL_FORMAT_YV16:
-      return "PIXEL_FORMAT_YV16";
-    case PIXEL_FORMAT_YV12A:
-      return "PIXEL_FORMAT_YV12A";
-    case PIXEL_FORMAT_YV24:
-      return "PIXEL_FORMAT_YV24";
-    case PIXEL_FORMAT_NV12:
-      return "PIXEL_FORMAT_NV12";
-    case PIXEL_FORMAT_NV21:
-      return "PIXEL_FORMAT_NV21";
-    case PIXEL_FORMAT_UYVY:
-      return "PIXEL_FORMAT_UYVY";
-    case PIXEL_FORMAT_YUY2:
-      return "PIXEL_FORMAT_YUY2";
-    case PIXEL_FORMAT_ARGB:
-      return "PIXEL_FORMAT_ARGB";
-    case PIXEL_FORMAT_XRGB:
-      return "PIXEL_FORMAT_XRGB";
-    case PIXEL_FORMAT_RGB24:
-      return "PIXEL_FORMAT_RGB24";
-    case PIXEL_FORMAT_RGB32:
-      return "PIXEL_FORMAT_RGB32";
-    case PIXEL_FORMAT_MJPEG:
-      return "PIXEL_FORMAT_MJPEG";
-    case PIXEL_FORMAT_MT21:
-      return "PIXEL_FORMAT_MT21";
-    case PIXEL_FORMAT_YUV420P9:
-      return "PIXEL_FORMAT_YUV420P9";
-    case PIXEL_FORMAT_YUV420P10:
-      return "PIXEL_FORMAT_YUV420P10";
-    case PIXEL_FORMAT_YUV422P9:
-      return "PIXEL_FORMAT_YUV422P9";
-    case PIXEL_FORMAT_YUV422P10:
-      return "PIXEL_FORMAT_YUV422P10";
-    case PIXEL_FORMAT_YUV444P9:
-      return "PIXEL_FORMAT_YUV444P9";
-    case PIXEL_FORMAT_YUV444P10:
-      return "PIXEL_FORMAT_YUV444P10";
-    case PIXEL_FORMAT_YUV420P12:
-      return "PIXEL_FORMAT_YUV420P12";
-    case PIXEL_FORMAT_YUV422P12:
-      return "PIXEL_FORMAT_YUV422P12";
-    case PIXEL_FORMAT_YUV444P12:
-      return "PIXEL_FORMAT_YUV444P12";
-    case PIXEL_FORMAT_Y8:
-      return "PIXEL_FORMAT_Y8";
-    case PIXEL_FORMAT_Y16:
-      return "PIXEL_FORMAT_Y16";
-  }
-  NOTREACHED() << "Invalid VideoPixelFormat provided: " << format;
-  return "";
-}
-
-bool IsYuvPlanar(VideoPixelFormat format) {
-  switch (format) {
-    case PIXEL_FORMAT_YV12:
-    case PIXEL_FORMAT_I420:
-    case PIXEL_FORMAT_YV16:
-    case PIXEL_FORMAT_YV12A:
-    case PIXEL_FORMAT_YV24:
-    case PIXEL_FORMAT_NV12:
-    case PIXEL_FORMAT_NV21:
-    case PIXEL_FORMAT_MT21:
-    case PIXEL_FORMAT_YUV420P9:
-    case PIXEL_FORMAT_YUV420P10:
-    case PIXEL_FORMAT_YUV422P9:
-    case PIXEL_FORMAT_YUV422P10:
-    case PIXEL_FORMAT_YUV444P9:
-    case PIXEL_FORMAT_YUV444P10:
-    case PIXEL_FORMAT_YUV420P12:
-    case PIXEL_FORMAT_YUV422P12:
-    case PIXEL_FORMAT_YUV444P12:
-      return true;
-
-    case PIXEL_FORMAT_UNKNOWN:
-    case PIXEL_FORMAT_UYVY:
-    case PIXEL_FORMAT_YUY2:
-    case PIXEL_FORMAT_ARGB:
-    case PIXEL_FORMAT_XRGB:
-    case PIXEL_FORMAT_RGB24:
-    case PIXEL_FORMAT_RGB32:
-    case PIXEL_FORMAT_MJPEG:
-    case PIXEL_FORMAT_Y8:
-    case PIXEL_FORMAT_Y16:
-      return false;
-  }
-  return false;
-}
-
-bool IsOpaque(VideoPixelFormat format) {
-  switch (format) {
-    case PIXEL_FORMAT_UNKNOWN:
-    case PIXEL_FORMAT_I420:
-    case PIXEL_FORMAT_YV12:
-    case PIXEL_FORMAT_YV16:
-    case PIXEL_FORMAT_YV24:
-    case PIXEL_FORMAT_NV12:
-    case PIXEL_FORMAT_NV21:
-    case PIXEL_FORMAT_UYVY:
-    case PIXEL_FORMAT_YUY2:
-    case PIXEL_FORMAT_XRGB:
-    case PIXEL_FORMAT_RGB24:
-    case PIXEL_FORMAT_MJPEG:
-    case PIXEL_FORMAT_MT21:
-    case PIXEL_FORMAT_YUV420P9:
-    case PIXEL_FORMAT_YUV420P10:
-    case PIXEL_FORMAT_YUV422P9:
-    case PIXEL_FORMAT_YUV422P10:
-    case PIXEL_FORMAT_YUV444P9:
-    case PIXEL_FORMAT_YUV444P10:
-    case PIXEL_FORMAT_YUV420P12:
-    case PIXEL_FORMAT_YUV422P12:
-    case PIXEL_FORMAT_YUV444P12:
-    case PIXEL_FORMAT_Y8:
-    case PIXEL_FORMAT_Y16:
-      return true;
-    case PIXEL_FORMAT_YV12A:
-    case PIXEL_FORMAT_ARGB:
-    case PIXEL_FORMAT_RGB32:
-      break;
-  }
-  return false;
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/can_play_type_handler.h b/src/cobalt/media/can_play_type_handler.h
index fe081a6..eddad62 100644
--- a/src/cobalt/media/can_play_type_handler.h
+++ b/src/cobalt/media/can_play_type_handler.h
@@ -22,12 +22,12 @@
 
 class CanPlayTypeHandler {
  public:
+  virtual ~CanPlayTypeHandler() {}
   virtual std::string CanPlayType(const std::string& mime_type,
                                   const std::string& key_system) = 0;
 
  protected:
   CanPlayTypeHandler() {}
-  ~CanPlayTypeHandler() {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(CanPlayTypeHandler);
diff --git a/src/cobalt/media/media.gyp b/src/cobalt/media/media.gyp
index 30a6943..24ceb59 100644
--- a/src/cobalt/media/media.gyp
+++ b/src/cobalt/media/media.gyp
@@ -27,8 +27,6 @@
         'media_module.cc',
         'media_module.h',
         'media_module_<(sb_media_platform).cc',
-        'media_module_stub.cc',
-        'media_module_stub.h',
         'shell_media_platform_<(sb_media_platform).cc',
         'shell_media_platform_<(sb_media_platform).h',
         'shell_video_data_allocator_common.cc',
diff --git a/src/cobalt/media/media2.gyp b/src/cobalt/media/media2.gyp
index 3530256..255ad17 100644
--- a/src/cobalt/media/media2.gyp
+++ b/src/cobalt/media/media2.gyp
@@ -29,8 +29,6 @@
         'fetcher_buffered_data_source.h',
         'media_module.cc',
         'media_module.h',
-        'media_module_stub.cc',
-        'media_module_stub.h',
         'media_module_starboard.cc',
 
         'base/audio_codecs.cc',
diff --git a/src/cobalt/media/media_module.h b/src/cobalt/media/media_module.h
index 7d21976..9391c89 100644
--- a/src/cobalt/media/media_module.h
+++ b/src/cobalt/media/media_module.h
@@ -52,8 +52,7 @@
 #endif  // !defined(COBALT_MEDIA_SOURCE_2016)
 
 // TODO: Collapse MediaModule into ShellMediaPlatform.
-class MediaModule : public CanPlayTypeHandler,
-                    public WebMediaPlayerFactory,
+class MediaModule : public WebMediaPlayerFactory,
                     public WebMediaPlayerDelegate {
  public:
   struct Options {
@@ -75,6 +74,9 @@
   static math::Size CalculateOutputResolution(
       system_window::SystemWindow* system_window,
       const base::optional<math::Size>& output_resolution_override);
+  // MediaModule implementation should implement this function to allow creation
+  // of CanPlayTypeHandler.
+  static scoped_ptr<CanPlayTypeHandler> CreateCanPlayTypeHandler();
 
   virtual ~MediaModule() {}
 
diff --git a/src/cobalt/media/media_module_starboard.cc b/src/cobalt/media/media_module_starboard.cc
index 558bdfb..6642d2f 100644
--- a/src/cobalt/media/media_module_starboard.cc
+++ b/src/cobalt/media/media_module_starboard.cc
@@ -44,15 +44,8 @@
 typedef ::media::ShellMediaPlatformStarboard ShellMediaPlatformStarboard;
 #endif  // !defined(COBALT_MEDIA_SOURCE_2016)
 
-class MediaModuleStarboard : public MediaModule {
+class CanPlayTypeHandlerStarboard : public CanPlayTypeHandler {
  public:
-  MediaModuleStarboard(system_window::SystemWindow* system_window,
-                       render_tree::ResourceProvider* resource_provider,
-                       const Options& options)
-      : options_(options),
-        system_window_(system_window),
-        media_platform_(resource_provider) {}
-
   std::string CanPlayType(const std::string& mime_type,
                           const std::string& key_system) OVERRIDE {
     SbMediaSupportType type =
@@ -68,6 +61,17 @@
     NOTREACHED();
     return "";
   }
+};
+
+class MediaModuleStarboard : public MediaModule {
+ public:
+  MediaModuleStarboard(system_window::SystemWindow* system_window,
+                       render_tree::ResourceProvider* resource_provider,
+                       const Options& options)
+      : options_(options),
+        system_window_(system_window),
+        media_platform_(resource_provider) {}
+
   scoped_ptr<WebMediaPlayer> CreateWebMediaPlayer(
       WebMediaPlayerClient* client) OVERRIDE {
     TRACK_MEMORY_SCOPE("Media");
@@ -124,5 +128,9 @@
       new MediaModuleStarboard(system_window, resource_provider, options));
 }
 
+scoped_ptr<CanPlayTypeHandler> MediaModule::CreateCanPlayTypeHandler() {
+  return make_scoped_ptr<CanPlayTypeHandler>(new CanPlayTypeHandlerStarboard);
+}
+
 }  // namespace media
 }  // namespace cobalt
diff --git a/src/cobalt/media/media_module_stub.cc b/src/cobalt/media/media_module_stub.cc
deleted file mode 100644
index ba8fd9f..0000000
--- a/src/cobalt/media/media_module_stub.cc
+++ /dev/null
@@ -1,127 +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 "cobalt/media/media_module_stub.h"
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "nb/memory_scope.h"
-
-namespace cobalt {
-namespace media {
-
-#if !defined(COBALT_MEDIA_SOURCE_2016)
-typedef ::media::BufferedDataSource BufferedDataSource;
-typedef ::media::WebMediaPlayer WebMediaPlayer;
-typedef ::media::WebMediaPlayerClient WebMediaPlayerClient;
-using ::media::Ranges;
-#endif  // !defined(COBALT_MEDIA_SOURCE_2016)
-
-namespace {
-
-class DummyWebMediaPlayer : public WebMediaPlayer {
- private:
-  void LoadMediaSource() OVERRIDE {}
-  void LoadProgressive(const GURL& url,
-                       scoped_ptr<BufferedDataSource> data_source,
-                       WebMediaPlayer::CORSMode cors_mode) OVERRIDE {
-    UNREFERENCED_PARAMETER(url);
-    UNREFERENCED_PARAMETER(data_source);
-    UNREFERENCED_PARAMETER(cors_mode);
-  }
-  void CancelLoad() OVERRIDE {}
-
-  // Playback controls.
-  void Play() OVERRIDE {}
-  void Pause() OVERRIDE {}
-  bool SupportsFullscreen() const OVERRIDE { return false; }
-  bool SupportsSave() const OVERRIDE { return false; }
-  void Seek(float seconds) OVERRIDE { UNREFERENCED_PARAMETER(seconds); }
-  void SetEndTime(float seconds) OVERRIDE { UNREFERENCED_PARAMETER(seconds); }
-  void SetRate(float rate) OVERRIDE { UNREFERENCED_PARAMETER(rate); }
-  void SetVolume(float volume) OVERRIDE { UNREFERENCED_PARAMETER(volume); }
-  void SetVisible(bool visible) OVERRIDE { UNREFERENCED_PARAMETER(visible); }
-  const Ranges<base::TimeDelta>& GetBufferedTimeRanges() OVERRIDE {
-    return buffer_;
-  }
-  float GetMaxTimeSeekable() const OVERRIDE { return 0.f; }
-
-  // Suspend/Resume
-  void Suspend() OVERRIDE {}
-  void Resume() OVERRIDE {}
-
-  // True if the loaded media has a playable video/audio track.
-  bool HasVideo() const OVERRIDE { return false; }
-  bool HasAudio() const OVERRIDE { return false; }
-
-  // Dimension of the video.
-  gfx::Size GetNaturalSize() const OVERRIDE { return gfx::Size(); }
-
-  // Getters of playback state.
-  bool IsPaused() const OVERRIDE { return false; }
-  bool IsSeeking() const OVERRIDE { return false; }
-  float GetDuration() const OVERRIDE { return 0.f; }
-  float GetCurrentTime() const OVERRIDE { return 0.f; }
-
-  // Get rate of loading the resource.
-  int GetDataRate() const OVERRIDE { return 1; }
-
-  // Internal states of loading and network.
-  NetworkState GetNetworkState() const OVERRIDE { return kNetworkStateEmpty; }
-  ReadyState GetReadyState() const OVERRIDE { return kReadyStateHaveNothing; }
-
-  bool DidLoadingProgress() const OVERRIDE { return false; }
-#if !defined(COBALT_MEDIA_SOURCE_2016)
-  unsigned long long GetTotalBytes() const OVERRIDE { return 0; }
-#endif  // !defined(COBALT_MEDIA_SOURCE_2016)
-
-  bool HasSingleSecurityOrigin() const OVERRIDE { return false; }
-  bool DidPassCORSAccessCheck() const OVERRIDE { return false; }
-
-  float MediaTimeForTimeValue(float time_value) const OVERRIDE {
-    UNREFERENCED_PARAMETER(time_value);
-    return 0.f;
-  }
-
-  unsigned GetDecodedFrameCount() const OVERRIDE { return 0; }
-  unsigned GetDroppedFrameCount() const OVERRIDE { return 0; }
-  unsigned GetAudioDecodedByteCount() const OVERRIDE { return 0; }
-  unsigned GetVideoDecodedByteCount() const OVERRIDE { return 0; }
-
-#if defined(COBALT_MEDIA_SOURCE_2016)
-  void SetDrmSystem(DrmSystem* drm_system) OVERRIDE {}
-#endif  // defined(COBALT_MEDIA_SOURCE_2016)
-
-  Ranges<base::TimeDelta> buffer_;
-};
-
-}  // namespace
-
-std::string MediaModuleStub::CanPlayType(const std::string& mime_type,
-                                         const std::string& key_system) {
-  UNREFERENCED_PARAMETER(mime_type);
-  UNREFERENCED_PARAMETER(key_system);
-  return "";  // Cannot play.
-}
-
-scoped_ptr<WebMediaPlayer> MediaModuleStub::CreateWebMediaPlayer(
-    WebMediaPlayerClient* client) {
-  UNREFERENCED_PARAMETER(client);
-  TRACK_MEMORY_SCOPE("Media");
-  return make_scoped_ptr<WebMediaPlayer>(new DummyWebMediaPlayer);
-}
-
-}  // namespace media
-}  // namespace cobalt
diff --git a/src/cobalt/media/media_module_stub.h b/src/cobalt/media/media_module_stub.h
deleted file mode 100644
index d5d3d4e..0000000
--- a/src/cobalt/media/media_module_stub.h
+++ /dev/null
@@ -1,42 +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.
-
-#ifndef COBALT_MEDIA_MEDIA_MODULE_STUB_H_
-#define COBALT_MEDIA_MEDIA_MODULE_STUB_H_
-
-#include <string>
-
-#include "cobalt/media/media_module.h"
-
-namespace cobalt {
-namespace media {
-
-#if !defined(COBALT_MEDIA_SOURCE_2016)
-typedef ::media::WebMediaPlayerClient WebMediaPlayerClient;
-#endif  // !defined(WebMediaPlayerDelegate)
-
-class MediaModuleStub : public MediaModule {
- public:
-  MediaModuleStub() {}
-
-  std::string CanPlayType(const std::string& mime_type,
-                          const std::string& key_system) OVERRIDE;
-  scoped_ptr<WebMediaPlayer> CreateWebMediaPlayer(
-      WebMediaPlayerClient* client) OVERRIDE;
-};
-
-}  // namespace media
-}  // namespace cobalt
-
-#endif  // COBALT_MEDIA_MEDIA_MODULE_STUB_H_
diff --git a/src/cobalt/media/player/web_media_player.h b/src/cobalt/media/player/web_media_player.h
index b3b5cb6..613efe7 100644
--- a/src/cobalt/media/player/web_media_player.h
+++ b/src/cobalt/media/player/web_media_player.h
@@ -83,10 +83,15 @@
 
   virtual ~WebMediaPlayer() {}
 
+#if SB_HAS(PLAYER_WITH_URL)
+  virtual void LoadUrl(const GURL& url) = 0;
+#else   // SB_HAS(PLAYER_WITH_URL)
   virtual void LoadMediaSource() = 0;
   virtual void LoadProgressive(const GURL& url,
                                scoped_ptr<BufferedDataSource> data_source,
                                CORSMode cors_mode) = 0;
+#endif  // SB_HAS(PLAYER_WITH_URL)
+
   virtual void CancelLoad() = 0;
 
   // Playback controls.
@@ -194,7 +199,7 @@
  public:
   virtual void NetworkStateChanged() = 0;
   virtual void ReadyStateChanged() = 0;
-  virtual void TimeChanged() = 0;
+  virtual void TimeChanged(bool eos_played) = 0;
   virtual void DurationChanged() = 0;
   virtual void OutputModeChanged() = 0;
   virtual void PlaybackStateChanged() = 0;
diff --git a/src/cobalt/media/player/web_media_player_impl.cc b/src/cobalt/media/player/web_media_player_impl.cc
index bd0d14b..884212f 100644
--- a/src/cobalt/media/player/web_media_player_impl.cc
+++ b/src/cobalt/media/player/web_media_player_impl.cc
@@ -209,11 +209,36 @@
 
 }  // anonymous namespace
 
+#if SB_HAS(PLAYER_WITH_URL)
+
+void WebMediaPlayerImpl::LoadUrl(const GURL& url) {
+  TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::LoadUrl");
+  DCHECK_EQ(main_loop_, MessageLoop::current());
+
+  UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(url), kMaxURLScheme);
+  DLOG(INFO) << "Start URL playback";
+
+  // Handle any volume changes that occured before load().
+  SetVolume(GetClient()->Volume());
+
+  // TODO: Set networkState to WebMediaPlayer::kNetworkStateIdle on stop.
+  SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
+  SetReadyState(WebMediaPlayer::kReadyStateHaveNothing);
+  media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));
+
+  is_local_source_ = !url.SchemeIs("http") && !url.SchemeIs("https");
+
+  StartPipeline(url);
+}
+
+#else  // SB_HAS(PLAYER_WITH_URL)
+
 void WebMediaPlayerImpl::LoadMediaSource() {
   TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::LoadMediaSource");
-
   DCHECK_EQ(main_loop_, MessageLoop::current());
 
+  DLOG(INFO) << "Start MEDIASOURCE playback";
+
   // Handle any volume changes that occured before load().
   SetVolume(GetClient()->Volume());
 
@@ -237,10 +262,10 @@
     const GURL& url, scoped_ptr<BufferedDataSource> data_source,
     CORSMode cors_mode) {
   TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::LoadProgressive");
-
   DCHECK_EQ(main_loop_, MessageLoop::current());
 
   UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(url), kMaxURLScheme);
+  DLOG(INFO) << "Start PROGRESSIVE playback";
 
   // Handle any volume changes that occured before load().
   SetVolume(GetClient()->Volume());
@@ -263,6 +288,8 @@
   StartPipeline(progressive_demuxer_.get());
 }
 
+#endif  // SB_HAS(PLAYER_WITH_URL)
+
 void WebMediaPlayerImpl::CancelLoad() {
   DCHECK_EQ(main_loop_, MessageLoop::current());
 }
@@ -590,7 +617,8 @@
   // Update our paused time.
   if (state_.paused) state_.paused_time = pipeline_->GetMediaTime();
 
-  GetClient()->TimeChanged();
+  const bool eos_played = false;
+  GetClient()->TimeChanged(eos_played);
 }
 
 void WebMediaPlayerImpl::OnPipelineEnded(PipelineStatus status) {
@@ -599,7 +627,9 @@
     OnPipelineError(status);
     return;
   }
-  GetClient()->TimeChanged();
+
+  const bool eos_played = true;
+  GetClient()->TimeChanged(eos_played);
 }
 
 void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
@@ -691,6 +721,28 @@
                                      "is_downloading_data", is_downloading));
 }
 
+#if SB_HAS(PLAYER_WITH_URL)
+void WebMediaPlayerImpl::StartPipeline(const GURL& url) {
+  TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::StartPipeline");
+
+  state_.starting = true;
+
+  pipeline_->SetDecodeToTextureOutputMode(client_->PreferDecodeToTexture());
+  pipeline_->Start(
+      NULL, BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::SetDrmSystemReadyCB),
+#if COBALT_MEDIA_ENABLE_VIDEO_DUMPER
+      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::SetEMEInitDataReadyCB),
+#endif  // COBALT_MEDIA_ENABLE_VIDEO_DUMPER
+      BIND_TO_RENDER_LOOP(
+          &WebMediaPlayerImpl::OnEncryptedMediaInitDataEncountered),
+      url.spec(), BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
+      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
+      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek),
+      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingState),
+      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
+      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOutputModeChanged));
+}
+#else  // SB_HAS(PLAYER_WITH_URL)
 void WebMediaPlayerImpl::StartPipeline(Demuxer* demuxer) {
   TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::StartPipeline");
 
@@ -702,6 +754,7 @@
 #if COBALT_MEDIA_ENABLE_VIDEO_DUMPER
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::SetEMEInitDataReadyCB),
 #endif  // COBALT_MEDIA_ENABLE_VIDEO_DUMPER
+      // SB_HAS(PLAYER_WITH_URL)
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek),
@@ -709,6 +762,7 @@
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOutputModeChanged));
 }
+#endif  // SB_HAS(PLAYER_WITH_URL)
 
 void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
   DCHECK_EQ(main_loop_, MessageLoop::current());
diff --git a/src/cobalt/media/player/web_media_player_impl.h b/src/cobalt/media/player/web_media_player_impl.h
index c3804ac..5df1690 100644
--- a/src/cobalt/media/player/web_media_player_impl.h
+++ b/src/cobalt/media/player/web_media_player_impl.h
@@ -113,10 +113,14 @@
       const scoped_refptr<MediaLog>& media_log);
   ~WebMediaPlayerImpl() OVERRIDE;
 
+#if SB_HAS(PLAYER_WITH_URL)
+  void LoadUrl(const GURL& url) OVERRIDE;
+#else   // SB_HAS(PLAYER_WITH_URL)
   void LoadMediaSource() OVERRIDE;
   void LoadProgressive(const GURL& url,
                        scoped_ptr<BufferedDataSource> data_source,
                        CORSMode cors_mode) OVERRIDE;
+#endif  // SB_HAS(PLAYER_WITH_URL)
   void CancelLoad() OVERRIDE;
 
   // Playback controls.
@@ -200,7 +204,11 @@
   void OnDownloadingStatusChanged(bool is_downloading);
 
   // Finishes starting the pipeline due to a call to load().
+#if SB_HAS(PLAYER_WITH_URL)
+  void StartPipeline(const GURL& url);
+#else   // SB_HAS(PLAYER_WITH_URL)
   void StartPipeline(Demuxer* demuxer);
+#endif  // SB_HAS(PLAYER_WITH_URL)
 
   // Helpers that set the network/ready state and notifies the client if
   // they've changed.
@@ -214,6 +222,9 @@
                                    bool* is_seeking) const;
   void OnEncryptedMediaInitDataEncountered(
       EmeInitDataType init_data_type, const std::vector<uint8_t>& init_data);
+  void OnEncryptedMediaInitDataEncounteredWrapper(
+      const char* init_data_type, const unsigned char* init_data,
+      unsigned int init_data_length);
 
   // Getter method to |client_|.
   WebMediaPlayerClient* GetClient();
diff --git a/src/cobalt/media/sandbox/web_media_player_helper.cc b/src/cobalt/media/sandbox/web_media_player_helper.cc
index 58618a2..6b98c90 100644
--- a/src/cobalt/media/sandbox/web_media_player_helper.cc
+++ b/src/cobalt/media/sandbox/web_media_player_helper.cc
@@ -35,7 +35,7 @@
   // WebMediaPlayerClient methods
   void NetworkStateChanged() OVERRIDE {}
   void ReadyStateChanged() OVERRIDE {}
-  void TimeChanged() OVERRIDE {}
+  void TimeChanged(bool) OVERRIDE {}
   void DurationChanged() OVERRIDE {}
   void OutputModeChanged() OVERRIDE {}
   void PlaybackStateChanged() OVERRIDE {}
@@ -48,9 +48,8 @@
 #endif  // defined(COBALT_MEDIA_SOURCE_2016)
   std::string SourceURL() const OVERRIDE { return ""; }
 #if defined(COBALT_MEDIA_SOURCE_2016)
-  void EncryptedMediaInitDataEncountered(EmeInitDataType init_data_type,
-                                         const unsigned char* init_data,
-                                         unsigned init_data_length) OVERRIDE {}
+  void EncryptedMediaInitDataEncountered(EmeInitDataType, const unsigned char*,
+                                         unsigned) OVERRIDE {}
 #endif  // defined(COBALT_MEDIA_SOURCE_2016)
 };
 
@@ -58,7 +57,11 @@
     : client_(new WebMediaPlayerClientStub),
       player_(media_module->CreateWebMediaPlayer(client_)) {
   player_->SetRate(1.0);
+// TODO: Investigate a better way to exclude this when SB_HAS(PLAYER_WITH_URL)
+//       is enabled.
+#if !SB_HAS(PLAYER_WITH_URL)
   player_->LoadMediaSource();
+#endif  // !SB_HAS(PLAYER_WITH_URL)
   player_->Play();
 }
 
@@ -71,8 +74,12 @@
   scoped_ptr<BufferedDataSource> data_source(new FetcherBufferedDataSource(
       base::MessageLoopProxy::current(), video_url, csp::SecurityCallback(),
       fetcher_factory->network_module()));
+// TODO: Investigate a better way to exclude this when SB_HAS(PLAYER_WITH_URL)
+//       is enabled.
+#if !SB_HAS(PLAYER_WITH_URL)
   player_->LoadProgressive(video_url, data_source.Pass(),
                            WebMediaPlayer::kCORSModeUnspecified);
+#endif  // !SB_HAS(PLAYER_WITH_URL)
   player_->Play();
 }
 
diff --git a/src/cobalt/media/sandbox/web_media_player_sandbox.cc b/src/cobalt/media/sandbox/web_media_player_sandbox.cc
index 8b634c1..99f5d9e 100644
--- a/src/cobalt/media/sandbox/web_media_player_sandbox.cc
+++ b/src/cobalt/media/sandbox/web_media_player_sandbox.cc
@@ -74,7 +74,7 @@
 
   void PopBack() {
     if (!buffs_.empty()) {
-      delete buffs_.back();
+      delete[] buffs_.back();
       buffs_.pop_back();
     }
   }
diff --git a/src/cobalt/network/starboard/user_agent_string_factory_starboard.cc b/src/cobalt/network/starboard/user_agent_string_factory_starboard.cc
index 3487dd7..b021729 100644
--- a/src/cobalt/network/starboard/user_agent_string_factory_starboard.cc
+++ b/src/cobalt/network/starboard/user_agent_string_factory_starboard.cc
@@ -27,7 +27,8 @@
 
 #if SB_API_VERSION == SB_EXPERIMENTAL_API_VERSION
 const char kStarboardStabilitySuffix[] = "-Experimental";
-#elif SB_API_VERSION >= SB_RELEASE_CANDIDATE_API_VERSION && \
+#elif defined(SB_RELEASE_CANDIDATE_API_VERSION) && \
+    SB_API_VERSION >= SB_RELEASE_CANDIDATE_API_VERSION && \
     SB_API_VERSION < SB_EXPERIMENTAL_API_VERSION
 const char kStarboardStabilitySuffix[] = "-ReleaseCandidate";
 #else
diff --git a/src/cobalt/renderer/backend/egl/graphics_context.cc b/src/cobalt/renderer/backend/egl/graphics_context.cc
index e29c3f4..c5e6a4c 100644
--- a/src/cobalt/renderer/backend/egl/graphics_context.cc
+++ b/src/cobalt/renderer/backend/egl/graphics_context.cc
@@ -235,32 +235,48 @@
   EGL_CALL(eglDestroyContext(display_, context_));
 }
 
+void GraphicsContextEGL::SafeEglMakeCurrent(RenderTargetEGL* surface) {
+  EGLSurface egl_surface = surface->GetSurface();
+
+  // This should only be used with egl surfaces (not framebuffer objects).
+  DCHECK_NE(egl_surface, EGL_NO_SURFACE);
+  DCHECK_EQ(surface->GetPlatformHandle(), 0);
+
+  if (surface->is_surface_bad()) {
+    // A surface may become invalid in the middle of shutdown processing. If
+    // this is a known bad surface, then bind the null surface just as if this
+    // is the first time it is found to be bad.
+    egl_surface = null_surface_->GetSurface();
+    EGL_CALL(eglMakeCurrent(display_, egl_surface, egl_surface, context_));
+    return;
+  }
+
+  eglMakeCurrent(display_, egl_surface, egl_surface, context_);
+  EGLint make_current_error = eglGetError();
+  if (make_current_error != EGL_SUCCESS) {
+    LOG(ERROR) << "eglMakeCurrent ERROR: " << make_current_error;
+    if (make_current_error == EGL_BAD_ALLOC ||
+        make_current_error == EGL_BAD_NATIVE_WINDOW) {
+      LOG(ERROR) << "eglMakeCurrent raised either EGL_BAD_ALLOC or "
+                    "EGL_BAD_NATIVE_WINDOW, continuing with null surface "
+                    "under the assumption that our window surface has become "
+                    "invalid due to a suspend or shutdown being triggered.";
+      surface->set_surface_bad();
+      egl_surface = null_surface_->GetSurface();
+      EGL_CALL(eglMakeCurrent(display_, egl_surface, egl_surface, context_));
+    } else {
+      NOTREACHED() << "Unexpected error when calling eglMakeCurrent().";
+    }
+  }
+}
+
 void GraphicsContextEGL::MakeCurrentWithSurface(RenderTargetEGL* surface) {
   DCHECK_NE(EGL_NO_SURFACE, surface) <<
       "Use ReleaseCurrentContext().";
 
   EGLSurface egl_surface = surface->GetSurface();
   if (egl_surface != EGL_NO_SURFACE) {
-    // This render target is not a frame buffer object. It has an EGLSurface
-    // that can be bound using eglMakeCurrent.
-    DCHECK_EQ(surface->GetPlatformHandle(), 0);
-
-    eglMakeCurrent(display_, egl_surface, egl_surface, context_);
-    EGLint make_current_error = eglGetError();
-    if (make_current_error != EGL_SUCCESS) {
-      LOG(ERROR) << "eglMakeCurrent ERROR: " << make_current_error;
-      if (make_current_error == EGL_BAD_ALLOC ||
-          make_current_error == EGL_BAD_NATIVE_WINDOW) {
-        LOG(ERROR) << "eglMakeCurrent raised either EGL_BAD_ALLOC or "
-                      "EGL_BAD_NATIVE_WINDOW, continuing with null surface "
-                      "under the assumption that our window surface has become "
-                      "invalid due to a suspend or shutdown being triggered.";
-        egl_surface = null_surface_->GetSurface();
-        EGL_CALL(eglMakeCurrent(display_, egl_surface, egl_surface, context_));
-      } else {
-        NOTREACHED() << "Unexpected error when calling eglMakeCurrent().";
-      }
-    }
+    SafeEglMakeCurrent(surface);
 
     // Minimize calls to glBindFramebuffer. Normally, nothing keeps their
     // framebuffer object bound, so 0 is normally bound at this point --
@@ -295,13 +311,13 @@
 
 void GraphicsContextEGL::ResetCurrentSurface() {
   if (is_current_ && current_surface_) {
-    EGLSurface egl_surface = current_surface_->GetSurface();
-    if (egl_surface == EGL_NO_SURFACE) {
-      DCHECK_NE(current_surface_->GetPlatformHandle(), 0);
-      egl_surface = null_surface_->GetSurface();
+    if (current_surface_->GetSurface() == EGL_NO_SURFACE) {
+      EGLSurface egl_surface = null_surface_->GetSurface();
+      EGL_CALL(eglMakeCurrent(display_, egl_surface, egl_surface, context_));
+    } else {
+      SafeEglMakeCurrent(current_surface_);
     }
 
-    EGL_CALL(eglMakeCurrent(display_, egl_surface, egl_surface, context_));
     GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER,
         current_surface_->GetPlatformHandle()));
   }
@@ -485,6 +501,10 @@
 
 void GraphicsContextEGL::SwapBuffers(RenderTargetEGL* surface) {
   TRACE_EVENT0("cobalt::renderer", "GraphicsContextEGL::SwapBuffers()");
+  if (surface->is_surface_bad()) {
+    // The surface may become invalid during shutdown.
+    return;
+  }
 
   // SwapBuffers should have no effect for offscreen render targets. The
   // current implementation of eglSwapBuffers() does nothing for PBuffers,
diff --git a/src/cobalt/renderer/backend/egl/graphics_context.h b/src/cobalt/renderer/backend/egl/graphics_context.h
index ef6d668..1e8cf51 100644
--- a/src/cobalt/renderer/backend/egl/graphics_context.h
+++ b/src/cobalt/renderer/backend/egl/graphics_context.h
@@ -120,6 +120,10 @@
   bool IsCurrent() const { return is_current_; }
 
  private:
+  // Make the given surface the current surface. Do error detection in case
+  // the surface has become invalid (which can happen during shutdown).
+  void SafeEglMakeCurrent(RenderTargetEGL* surface);
+
   // Performs a test to determine if the pixel data returned by glReadPixels
   // needs to be vertically flipped or not.  This test is expensive, so it
   // caches the results the first time it is computed and simply returns the
diff --git a/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc b/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc
index 0812b2e..0435764 100644
--- a/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc
+++ b/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc
@@ -489,7 +489,7 @@
       } break;
       case Image::YUV_2PLANE_BT709: {
         std::vector<TextureInfo> texture_infos;
-#if SB_API_VERSION >= SB_DECODE_TARGET_PLANE_FORMAT_VERSION
+#if SB_API_VERSION >= 7
         switch (image.textures[0].texture->GetFormat()) {
           case GL_ALPHA:
             texture_infos.push_back(TextureInfo("y", "a"));
@@ -514,10 +514,10 @@
           default:
             NOTREACHED();
         }
-#else  // SB_API_VERSION >= SB_DECODE_TARGET_PLANE_FORMAT_VERSION
+#else  // SB_API_VERSION >= 7
         texture_infos.push_back(TextureInfo("y", "a"));
         texture_infos.push_back(TextureInfo("uv", "ba"));
-#endif  // SB_API_VERSION >= SB_DECODE_TARGET_PLANE_FORMAT_VERSION
+#endif  // SB_API_VERSION >= 7
         result = MakeBlitProgram(
             color_matrix, texture_infos,
             CreateFragmentShader(texture_target, texture_infos));
diff --git a/src/cobalt/renderer/rasterizer/lib/exported/video.h b/src/cobalt/renderer/rasterizer/lib/exported/video.h
index 9f06902..eba728a 100644
--- a/src/cobalt/renderer/rasterizer/lib/exported/video.h
+++ b/src/cobalt/renderer/rasterizer/lib/exported/video.h
@@ -23,7 +23,7 @@
 #endif
 
 // Functions to be called to set callbacks to receive updates to video rendering
-// parameters. By default, this callbacks are not set and warnings will be
+// parameters. By default, these callbacks are not set and warnings will be
 // when an unhandled parameter change happens. To unset them again, any of these
 // setter functions can be called with a null callback function pointer.
 
@@ -33,13 +33,24 @@
   kCbLibVideoProjectionTypeMesh = 2,
 } CbLibVideoProjectionType;
 
-// If projection_type is Rectangular or Mesh, this signals the start of off-
-// screen video playback. If it is None, this signals the end of playback.
-typedef void (*CbLibVideoUpdateProjectionTypeCallback)(
-    void* context, CbLibVideoProjectionType projection_type);
+typedef enum {
+  kCbLibVideoStereoModeMono = 0,
+  kCbLibVideoStereoModeStereoLeftRight = 1,
+  kCbLibVideoStereoModeStereoTopBottom = 2,
+  kCbLibVideoStereoModeStereoLeftRightUnadjustedCoordinates = 3,
+} CbLibVideoStereoMode;
 
-SB_EXPORT_PLATFORM void CbLibVideoSetOnUpdateProjectionType(
-    void* context, CbLibVideoUpdateProjectionTypeCallback callback);
+// If projection_type is Rectangular or Mesh, this signals the start of off-
+// screen video playback and also sets the stereo_mode of the video texture.
+// If it is None, this signals the end of playback and stereo_mode can be
+// ignored.
+typedef void (*CbLibVideoUpdateProjectionTypeAndStereoModeCallback)(
+    void* context, CbLibVideoProjectionType projection_type,
+    CbLibVideoStereoMode stereo_mode);
+
+SB_EXPORT_PLATFORM void CbLibVideoSetOnUpdateProjectionTypeAndStereoMode(
+    void* context,
+    CbLibVideoUpdateProjectionTypeAndStereoModeCallback callback);
 
 typedef enum {
   kCbLibVideoMeshDrawModeTriangles = 0,
@@ -65,27 +76,19 @@
 SB_EXPORT_PLATFORM void CbLibVideoSetOnUpdateMeshes(
     void* context, CbLibVideoUpdateMeshesCallback callback);
 
-typedef enum {
-  kCbLibVideoStereoModeMono = 0,
-  kCbLibVideoStereoModeStereoLeftRight = 1,
-  kCbLibVideoStereoModeStereoTopBottom = 2,
-  kCbLibVideoStereoModeStereoLeftRightUnadjustedCoordinates = 3,
-} CbLibVideoStereoMode;
-
-// Called when the layout of the different stereo views changes on the video
-// texture.
-typedef void (*CbLibVideoUpdateStereoModeCallback)(
-    void* context, CbLibVideoStereoMode stereo_mode);
-
-SB_EXPORT_PLATFORM void CbLibVideoSetOnUpdateStereoMode(
-    void* context, CbLibVideoUpdateStereoModeCallback callback);
-
 // Called to set the RGB video texture ID.
 typedef void (*CbLibVideoUpdateRgbTextureIdCallback)(void* context, int id);
 
 SB_EXPORT_PLATFORM void CbLibVideoSetOnUpdateRgbTextureId(
     void* context, CbLibVideoUpdateRgbTextureIdCallback callback);
 
+// Called to set aspect ratio of the video (width over height).
+typedef void (*CbLibVideoUpdateAspectRatioCallback)(void* context,
+                                                    float aspect_ratio);
+
+SB_EXPORT_PLATFORM void CbLibVideoSetOnUpdateAspectRatio(
+    void* context, CbLibVideoUpdateAspectRatioCallback callback);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/src/cobalt/renderer/rasterizer/lib/external_rasterizer.cc b/src/cobalt/renderer/rasterizer/lib/external_rasterizer.cc
index 4838ed8..84f02fd 100644
--- a/src/cobalt/renderer/rasterizer/lib/external_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/lib/external_rasterizer.cc
@@ -106,10 +106,10 @@
                      kWarningMessageDidNotSet##instance_name>;
 
 INSTANCE_CALLBACK_UPDATE(UpdateMeshes, CbLibVideoSetOnUpdateMeshes);
-INSTANCE_CALLBACK_UPDATE(UpdateStereoMode, CbLibVideoSetOnUpdateStereoMode);
 INSTANCE_CALLBACK_UPDATE(UpdateRgbTextureId, CbLibVideoSetOnUpdateRgbTextureId);
-INSTANCE_CALLBACK_UPDATE(UpdateProjectionType,
-                         CbLibVideoSetOnUpdateProjectionType);
+INSTANCE_CALLBACK_UPDATE(UpdateProjectionTypeAndStereoMode,
+                         CbLibVideoSetOnUpdateProjectionTypeAndStereoMode);
+INSTANCE_CALLBACK_UPDATE(UpdateAspectRatio, CbLibVideoSetOnUpdateAspectRatio);
 INSTANCE_CALLBACK_UPDATE(GraphicsContextCreated,
                          CbLibGraphicsSetContextCreatedCallback);
 INSTANCE_CALLBACK_UPDATE(BeginRenderFrame,
@@ -119,11 +119,12 @@
 #undef INSTANCE_CALLBACK_UPDATE
 
 UpdateMeshes::LazyCallback g_update_meshes_callback = LAZY_INSTANCE_INITIALIZER;
-UpdateStereoMode::LazyCallback g_update_stereo_mode_callback =
-    LAZY_INSTANCE_INITIALIZER;
 UpdateRgbTextureId::LazyCallback g_update_rgb_texture_id_callback =
     LAZY_INSTANCE_INITIALIZER;
-UpdateProjectionType::LazyCallback g_update_projection_type_callback =
+UpdateProjectionTypeAndStereoMode::LazyCallback
+    g_update_projection_type_and_stereo_mode_callback =
+        LAZY_INSTANCE_INITIALIZER;
+UpdateAspectRatio::LazyCallback g_update_aspect_ratio_callback =
     LAZY_INSTANCE_INITIALIZER;
 GraphicsContextCreated::LazyCallback g_graphics_context_created_callback =
     LAZY_INSTANCE_INITIALIZER;
@@ -200,7 +201,6 @@
   // host directly.
   scoped_refptr<backend::RenderTarget> video_offscreen_render_target_;
   scoped_ptr<backend::TextureEGL> video_texture_;
-
   CbLibVideoProjectionType video_projection_type_;
   scoped_refptr<skia::HardwareMesh> left_eye_video_mesh_;
   scoped_refptr<skia::HardwareMesh> right_eye_video_mesh_;
@@ -210,6 +210,8 @@
   // of the buffer for the main RenderTarget should aim to be within some small
   // delta of this whenever a new RenderTree is rendered.
   cobalt::math::Size target_main_render_target_size_;
+  int video_width_;
+  int video_height_;
 };
 
 ExternalRasterizer::Impl::Impl(backend::GraphicsContext* graphics_context,
@@ -229,6 +231,8 @@
       video_projection_type_(kCbLibVideoProjectionTypeNone),
       video_stereo_mode_(render_tree::StereoMode::kMono),
       video_texture_rgb_(0),
+      video_width_(-1),
+      video_height_(-1),
       target_main_render_target_size_(1, 1) {
   CHECK(!g_external_rasterizer_impl);
   g_external_rasterizer_impl = this;
@@ -286,25 +290,34 @@
       new_projection_type = kCbLibVideoProjectionTypeMesh;
     }
 
-    if (video_projection_type_ != new_projection_type) {
+    if (video_projection_type_ != new_projection_type ||
+        filter->stereo_mode() != video_stereo_mode_) {
+      // Note the above condition will always be true when playback has not
+      // started.
       video_projection_type_ = new_projection_type;
-      g_update_projection_type_callback.Get().Run(video_projection_type_);
+      video_stereo_mode_ = filter->stereo_mode();
+      g_update_projection_type_and_stereo_mode_callback.Get().Run(
+          video_projection_type_,
+          static_cast<CbLibVideoStereoMode>(video_stereo_mode_));
     }
 
-    if (filter->stereo_mode() != video_stereo_mode_) {
-      video_stereo_mode_ = filter->stereo_mode();
-      g_update_stereo_mode_callback.Get().Run(
-          static_cast<CbLibVideoStereoMode>(video_stereo_mode_));
+    const scoped_refptr<render_tree::Node>& video_render_tree =
+        map_to_mesh_search.found_node->data().source;
+    math::SizeF resolutionf = video_render_tree->GetBounds().size();
+    int width = static_cast<int>(resolutionf.width());
+    int height = static_cast<int>(resolutionf.height());
+
+    if (video_width_ != width || video_height_ != height) {
+      g_update_aspect_ratio_callback.Get().Run(
+          width > 0 && height > 0 ?  // Avoid division by zero.
+              resolutionf.width() / resolutionf.height()
+                                  : 0.0f);
+      video_width_ = width;
+      video_height_ = height;
     }
 
     if (video_projection_type_ == kCbLibVideoProjectionTypeMesh) {
       // Use resolution to lookup custom mesh map.
-      const scoped_refptr<render_tree::Node>& video_render_tree =
-          map_to_mesh_search.found_node->data().source;
-      math::SizeF resolutionf = video_render_tree->GetBounds().size();
-      int width = static_cast<int>(resolutionf.width());
-      int height = static_cast<int>(resolutionf.height());
-
       math::Size resolution(width, height);
       scoped_refptr<skia::HardwareMesh> left_eye_video_mesh(
           base::polymorphic_downcast<skia::HardwareMesh*>(
@@ -346,7 +359,9 @@
   } else {
     if (video_projection_type_ != kCbLibVideoProjectionTypeNone) {
       video_projection_type_ = kCbLibVideoProjectionTypeNone;
-      g_update_projection_type_callback.Get().Run(video_projection_type_);
+      g_update_projection_type_and_stereo_mode_callback.Get().Run(
+          video_projection_type_, kCbLibVideoStereoModeMono);
+      video_width_ = video_height_ = -1;
     }
   }
 
@@ -526,13 +541,6 @@
                : base::Bind(&UpdateMeshes::DefaultImplementation);
 }
 
-void CbLibVideoSetOnUpdateStereoMode(
-    void* context, CbLibVideoUpdateStereoModeCallback callback) {
-  g_update_stereo_mode_callback.Get() =
-      callback ? base::Bind(callback, context)
-               : base::Bind(&UpdateStereoMode::DefaultImplementation);
-}
-
 void CbLibVideoSetOnUpdateRgbTextureId(
     void* context, CbLibVideoUpdateRgbTextureIdCallback callback) {
   g_update_rgb_texture_id_callback.Get() =
@@ -540,11 +548,20 @@
                : base::Bind(&UpdateRgbTextureId::DefaultImplementation);
 }
 
-void CbLibVideoSetOnUpdateProjectionType(
-    void* context, CbLibVideoUpdateProjectionTypeCallback callback) {
-  g_update_projection_type_callback.Get() =
+void CbLibVideoSetOnUpdateProjectionTypeAndStereoMode(
+    void* context,
+    CbLibVideoUpdateProjectionTypeAndStereoModeCallback callback) {
+  g_update_projection_type_and_stereo_mode_callback.Get() =
       callback ? base::Bind(callback, context)
-               : base::Bind(&UpdateProjectionType::DefaultImplementation);
+               : base::Bind(
+                     &UpdateProjectionTypeAndStereoMode::DefaultImplementation);
+}
+
+void CbLibVideoSetOnUpdateAspectRatio(
+    void* context, CbLibVideoUpdateAspectRatioCallback callback) {
+  g_update_aspect_ratio_callback.Get() =
+      callback ? base::Bind(callback, context)
+               : base::Bind(&UpdateAspectRatio::DefaultImplementation);
 }
 
 void CbLibGraphicsSetContextCreatedCallback(
diff --git a/src/cobalt/renderer/rasterizer/pixel_test.cc b/src/cobalt/renderer/rasterizer/pixel_test.cc
index d9a85e7..d96d361 100644
--- a/src/cobalt/renderer/rasterizer/pixel_test.cc
+++ b/src/cobalt/renderer/rasterizer/pixel_test.cc
@@ -568,6 +568,161 @@
   TestTree(new CompositionNode(builder.Pass()));
 }
 
+TEST_F(PixelTest, EmptyRectWithRoundedCornersAnd4DifferentEdgeColorsBorder) {
+  // Create a test render tree for a border with rounded corners and 4 different
+  // edge colors.
+  BorderSide border_left(25, render_tree::kBorderStyleSolid,
+                         ColorRGBA(0.0, 0.0, 1.0, 1));
+  BorderSide border_right(25, render_tree::kBorderStyleSolid,
+                          ColorRGBA(0.0, 1.0, 1.0, 0.5));
+  BorderSide border_top(25, render_tree::kBorderStyleSolid,
+                        ColorRGBA(1.0, 1.0, 1.0, 1));
+  BorderSide border_bottom(25, render_tree::kBorderStyleSolid,
+                           ColorRGBA(0.0, 1.0, 0.0, 0.8f));
+  scoped_ptr<Border> border(
+      new Border(border_left, border_right, border_top, border_bottom));
+
+  math::RectF rect(200, 100);
+
+  RoundedCorner rounded_corner(100, 100);
+  scoped_ptr<RoundedCorners> rounded_corners(
+      new RoundedCorners(rounded_corner));
+  *rounded_corners = rounded_corners->Normalize(rect);
+
+  TestTree(new RectNode(rect, border.Pass(), rounded_corners.Pass()));
+}
+
+TEST_F(PixelTest, EmptyRectWith4DifferentRoundedCornersAndEdgeColorsBorder) {
+  // Create a test render tree for a border with 4 different rounded corners and
+  // edge colors.
+  BorderSide border_left(25, render_tree::kBorderStyleSolid,
+                         ColorRGBA(0.0, 0.0, 1.0, 1));
+  BorderSide border_right(25, render_tree::kBorderStyleSolid,
+                          ColorRGBA(0.0, 1.0, 1.0, 0.5));
+  BorderSide border_top(25, render_tree::kBorderStyleSolid,
+                        ColorRGBA(1.0, 1.0, 1.0, 1));
+  BorderSide border_bottom(25, render_tree::kBorderStyleSolid,
+                           ColorRGBA(0.0, 1.0, 0.0, 0.8f));
+  scoped_ptr<Border> border(
+      new Border(border_left, border_right, border_top, border_bottom));
+
+  math::RectF rect(200, 100);
+
+  RoundedCorner top_left(30, 30);
+  RoundedCorner top_right(10, 10);
+  RoundedCorner bottom_right(50, 50);
+  RoundedCorner bottom_left(40, 40);
+  scoped_ptr<RoundedCorners> rounded_corners(
+      new RoundedCorners(top_left, top_right, bottom_right, bottom_left));
+  *rounded_corners = rounded_corners->Normalize(rect);
+
+  TestTree(new RectNode(rect, border.Pass(), rounded_corners.Pass()));
+}
+
+TEST_F(PixelTest, EmptyRectWithRoundedCornersAnd4DifferentEdgeWidthsBorder) {
+  // Create a test render tree for a border with rounded corners and 4 different
+  // edge widths.
+  BorderSide border_left(25, render_tree::kBorderStyleSolid,
+                         ColorRGBA(0.0, 1.0, 0.0, 0.8f));
+  BorderSide border_right(30, render_tree::kBorderStyleSolid,
+                          ColorRGBA(0.0, 1.0, 0.0, 0.8f));
+  BorderSide border_top(40, render_tree::kBorderStyleSolid,
+                        ColorRGBA(0.0, 1.0, 0.0, 0.8f));
+  BorderSide border_bottom(10, render_tree::kBorderStyleSolid,
+                           ColorRGBA(0.0, 1.0, 0.0, 0.8f));
+  scoped_ptr<Border> border(
+      new Border(border_left, border_right, border_top, border_bottom));
+
+  math::RectF rect(200, 100);
+
+  RoundedCorner rounded_corner(100, 100);
+  scoped_ptr<RoundedCorners> rounded_corners(
+      new RoundedCorners(rounded_corner));
+  *rounded_corners = rounded_corners->Normalize(rect);
+
+  TestTree(new RectNode(rect, border.Pass(), rounded_corners.Pass()));
+}
+
+TEST_F(PixelTest, EmptyRectWith4DifferentRoundedCornersAndEdgeWidthsBorder) {
+  // Create a test render tree for a border with 4 different rounded corners and
+  // edge widths.
+  BorderSide border_left(25, render_tree::kBorderStyleSolid,
+                         ColorRGBA(0.0, 1.0, 0.0, 0.8f));
+  BorderSide border_right(30, render_tree::kBorderStyleSolid,
+                          ColorRGBA(0.0, 1.0, 0.0, 0.8f));
+  BorderSide border_top(40, render_tree::kBorderStyleSolid,
+                        ColorRGBA(0.0, 1.0, 0.0, 0.8f));
+  BorderSide border_bottom(10, render_tree::kBorderStyleSolid,
+                           ColorRGBA(0.0, 1.0, 0.0, 0.8f));
+  scoped_ptr<Border> border(
+      new Border(border_left, border_right, border_top, border_bottom));
+
+  math::RectF rect(200, 100);
+
+  RoundedCorner top_left(50, 50);
+  RoundedCorner top_right(10, 10);
+  RoundedCorner bottom_right(60, 60);
+  RoundedCorner bottom_left(40, 40);
+  scoped_ptr<RoundedCorners> rounded_corners(
+      new RoundedCorners(top_left, top_right, bottom_right, bottom_left));
+  *rounded_corners = rounded_corners->Normalize(rect);
+
+  TestTree(new RectNode(rect, border.Pass(), rounded_corners.Pass()));
+}
+
+TEST_F(PixelTest,
+       EmptyRectWithRoundedCornersAnd4DifferentEdgeColorsAndEdgeWidthsBorder) {
+  // Create a test render tree for a border with rounded corners and 4 different
+  // edge colors and edge widths.
+  BorderSide border_left(25, render_tree::kBorderStyleSolid,
+                         ColorRGBA(0.0, 0.0, 1.0, 1));
+  BorderSide border_right(30, render_tree::kBorderStyleSolid,
+                          ColorRGBA(0.0, 1.0, 1.0, 0.5));
+  BorderSide border_top(40, render_tree::kBorderStyleSolid,
+                        ColorRGBA(1.0, 1.0, 1.0, 1));
+  BorderSide border_bottom(10, render_tree::kBorderStyleSolid,
+                           ColorRGBA(0.0, 1.0, 0.0, 0.8f));
+  scoped_ptr<Border> border(
+      new Border(border_left, border_right, border_top, border_bottom));
+
+  math::RectF rect(200, 100);
+
+  RoundedCorner rounded_corner(100, 100);
+  scoped_ptr<RoundedCorners> rounded_corners(
+      new RoundedCorners(rounded_corner));
+  *rounded_corners = rounded_corners->Normalize(rect);
+
+  TestTree(new RectNode(rect, border.Pass(), rounded_corners.Pass()));
+}
+
+TEST_F(PixelTest,
+       EmptyRectWith4DifferentRoundedCornersAndEdgeColorsAndEdgeWidthsBorder) {
+  // Create a test render tree for a border with 4 different rounded corners,
+  // edge colors and edge widths.
+  BorderSide border_left(25, render_tree::kBorderStyleSolid,
+                         ColorRGBA(0.0, 0.0, 1.0, 1));
+  BorderSide border_right(30, render_tree::kBorderStyleSolid,
+                          ColorRGBA(0.0, 1.0, 1.0, 0.5));
+  BorderSide border_top(40, render_tree::kBorderStyleSolid,
+                        ColorRGBA(1.0, 1.0, 1.0, 1));
+  BorderSide border_bottom(10, render_tree::kBorderStyleSolid,
+                           ColorRGBA(0.0, 1.0, 0.0, 0.8f));
+  scoped_ptr<Border> border(
+      new Border(border_left, border_right, border_top, border_bottom));
+
+  math::RectF rect(200, 100);
+
+  RoundedCorner top_left(60, 60);
+  RoundedCorner top_right(10, 10);
+  RoundedCorner bottom_right(50, 50);
+  RoundedCorner bottom_left(40, 40);
+  scoped_ptr<RoundedCorners> rounded_corners(
+      new RoundedCorners(top_left, top_right, bottom_right, bottom_left));
+  *rounded_corners = rounded_corners->Normalize(rect);
+
+  TestTree(new RectNode(rect, border.Pass(), rounded_corners.Pass()));
+}
+
 TEST_F(PixelTest, SingleRGBAImageLargerThanRenderTarget) {
   // Tests that rasterizing images that are larger than the render target
   // work as expected (e.g. they are cropped).
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
index e7e9075..6581495 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
@@ -182,9 +182,9 @@
     } break;
     case kSbDecodeTargetFormat2PlaneYUVNV12: {
       DCHECK_LT(plane, 2);
-#if SB_API_VERSION >= SB_DECODE_TARGET_PLANE_FORMAT_VERSION
+#if SB_API_VERSION >= 7
       // If this DCHECK fires, please set gl_texture_format, introduced
-      // in Starboard SB_DECODE_TARGET_PLANE_FORMAT_VERSION.
+      // in Starboard 7.
       //
       // You probably want to set it to GL_ALPHA on plane 0 (luma) and
       // GL_LUMINANCE_ALPHA on plane 1 (chroma), which was the default before.
@@ -206,7 +206,7 @@
           CHECK(false);
           return 0;
       }
-#else  // SB_API_VERSION >= SB_DECODE_TARGET_PLANE_FORMAT_VERSION
+#else  // SB_API_VERSION >= 7
       switch (plane) {
         case 0:
           return GL_ALPHA;
@@ -216,7 +216,7 @@
           NOTREACHED();
           return GL_RGBA;
       }
-#endif  // SB_API_VERSION >= SB_DECODE_TARGET_PLANE_FORMAT_VERSION
+#endif  // SB_API_VERSION >= 7
     } break;
     case kSbDecodeTargetFormat3PlaneYUVI420: {
       DCHECK_LT(plane, 3);
diff --git a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
index 918a60e..42e722f 100644
--- a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
@@ -1156,11 +1156,10 @@
     const render_tree::RoundedCorners& rounded_corners,
     const math::RectF& content_rect,
     const render_tree::RoundedCorners& inner_rounded_corners,
-    const render_tree::Border& border) {
+    const render_tree::ColorRGBA& color) {
   SkPaint paint;
   paint.setAntiAlias(true);
 
-  const render_tree::ColorRGBA& color = border.top.color;
   float alpha = color.a();
   alpha *= draw_state->opacity;
   paint.setARGB(alpha * 255, color.r() * 255, color.g() * 255, color.b() * 255);
@@ -1175,6 +1174,205 @@
       RoundedRectToSkia(content_rect, inner_rounded_corners), paint);
 }
 
+namespace {
+bool IsCircle(const math::SizeF& size,
+              const render_tree::RoundedCorners& rounded_corners) {
+  if (size.width() != size.height()) {
+    return false;
+  }
+
+  float radius = size.width() * 0.5f;
+  // Corners cannot be "more round" than a circle, so we check using >= rather
+  // than == here.
+  return rounded_corners.AllCornersGE(
+      render_tree::RoundedCorner(radius, radius));
+}
+
+bool AllBorderSidesShareSameProperties(const render_tree::Border& border) {
+  return (border.top == border.left && border.top == border.right &&
+          border.top == border.bottom);
+}
+
+base::optional<SkPoint> CalculateIntersectionPoint(const SkPoint& a,
+                                                   const SkPoint& b,
+                                                   const SkPoint& c,
+                                                   const SkPoint& d) {
+  // Given 2 lines, each represented by 2 points (points a and b lie on line 1
+  // and points c and d lie on line 2), calculates the intersection point of
+  // these 2 lines if they intersect.
+  const float ab_width = b.x() - a.x();
+  const float ab_height = b.y() - a.y();
+  const float cd_width = d.x() - c.x();
+  const float cd_height = d.y() - c.y();
+  base::optional<SkPoint> intersection;
+
+  const float determinant = (ab_width * cd_height) - (ab_height * cd_width);
+  if (determinant) {
+    const float param =
+        ((c.x() - a.x()) * cd_height - (c.y() - a.y()) * cd_width) /
+        determinant;
+    intersection =
+        SkPoint({a.x() + param * ab_width, a.y() + param * ab_height});
+  }
+
+  return intersection;
+}
+}  // namespace
+
+void SetUpDrawStateClipPath(RenderTreeNodeVisitorDrawState* draw_state,
+                            const SkPoint* points) {
+  draw_state->render_target->restore();
+  draw_state->render_target->save();
+
+  SkPath path;
+  path.addPoly(points, 4, true);
+
+  draw_state->render_target->clipPath(path, SkRegion::kIntersect_Op, true);
+}
+
+void DrawSolidRoundedRectBorderByEdge(
+    RenderTreeNodeVisitorDrawState* draw_state, const math::RectF& rect,
+    const render_tree::RoundedCorners& rounded_corners,
+    const math::RectF& content_rect,
+    const render_tree::RoundedCorners& inner_rounded_corners,
+    const render_tree::Border& border) {
+  // Render each border edge seperately using SkCanvas::clipPath() to clip out
+  // each edge's region from the overall RRect.
+  // Divide the area into 4 trapezoids, each represented by 4 points that
+  // encompass the clipped out region for a border edge (including the rounded
+  // corners). Draw within each clipped out region seperately.
+  //       A ___________ B
+  //        |\_________/|
+  //        ||E       F||
+  //        ||         ||
+  //        ||G_______H||
+  //        |/_________\|
+  //       C             D
+  // NOTE: As described in
+  // https://www.w3.org/TR/css3-background/#corner-transitions, the spec does
+  // not give an exact function for calculating the center of color/style
+  // transitions between adjoining borders, so the following math resembles
+  // Chrome: https://cs.chromium.org/BoxBorderPainter::ClipBorderSidePolygon.
+  // The center of a transition (represented by points E, F, G and H above) is
+  // calculated by finding the intersection point of 2 lines:
+  // 1) The line consisting of the outer point (ex: point A, B, C or D) and this
+  // outer point adjusted by the corresponding edge's border width (inner
+  // point).
+  // 2) The line consisting of the inner point adjusted by the corresponding
+  // edge's border radius in the x-direction and the inner point adjusted by the
+  // corresponding edge's border radius in the y-direction.
+  // If no intersection point exists, the transition center is just the inner
+  // point.
+
+  base::optional<SkPoint> intersection;
+  // Top Left
+  const SkPoint top_left_outer = {rect.x(), rect.y()};
+  SkPoint top_left_inner = {rect.x() + border.left.width,
+                            rect.y() + border.top.width};
+
+  if (!inner_rounded_corners.top_left.IsSquare()) {
+    intersection = CalculateIntersectionPoint(
+        top_left_outer, top_left_inner,
+        SkPoint({top_left_inner.x() + inner_rounded_corners.top_left.horizontal,
+                 top_left_inner.y()}),
+        SkPoint(
+            {top_left_inner.x(),
+             top_left_inner.y() + inner_rounded_corners.top_left.vertical}));
+    if (intersection) {
+      top_left_inner = SkPoint({intersection->x(), intersection->y()});
+    }
+  }
+
+  // Top Right
+  const SkPoint top_right_outer = {rect.right(), rect.y()};
+  SkPoint top_right_inner = {rect.right() - border.right.width,
+                             rect.y() + border.top.width};
+
+  if (!inner_rounded_corners.top_right.IsSquare()) {
+    intersection = CalculateIntersectionPoint(
+        top_right_outer, top_right_inner,
+        SkPoint(
+            {top_right_inner.x() - inner_rounded_corners.top_right.horizontal,
+             top_right_inner.y()}),
+        SkPoint(
+            {top_right_inner.x(),
+             top_right_inner.y() + inner_rounded_corners.top_right.vertical}));
+    if (intersection) {
+      top_right_inner = SkPoint({intersection->x(), intersection->y()});
+    }
+  }
+
+  // Bottom Left
+  const SkPoint bottom_left_outer = {rect.x(), rect.bottom()};
+  SkPoint bottom_left_inner = {rect.x() + border.left.width,
+                               rect.bottom() - border.bottom.width};
+
+  if (!inner_rounded_corners.bottom_left.IsSquare()) {
+    intersection = CalculateIntersectionPoint(
+        bottom_left_outer, bottom_left_inner,
+        SkPoint({bottom_left_inner.x() +
+                     inner_rounded_corners.bottom_left.horizontal,
+                 bottom_left_inner.y()}),
+        SkPoint({bottom_left_inner.x(),
+                 bottom_left_inner.y() -
+                     inner_rounded_corners.bottom_left.vertical}));
+    if (intersection) {
+      bottom_left_inner = SkPoint({intersection->x(), intersection->y()});
+    }
+  }
+
+  // Bottom Right
+  const SkPoint bottom_right_outer = {rect.right(), rect.bottom()};
+  SkPoint bottom_right_inner = {rect.right() - border.right.width,
+                                rect.bottom() - border.bottom.width};
+
+  if (!inner_rounded_corners.bottom_right.IsSquare()) {
+    intersection = CalculateIntersectionPoint(
+        bottom_right_outer, bottom_right_inner,
+        SkPoint({bottom_right_inner.x() -
+                     inner_rounded_corners.bottom_right.horizontal,
+                 bottom_right_inner.y()}),
+        SkPoint({bottom_right_inner.x(),
+                 bottom_right_inner.y() -
+                     inner_rounded_corners.bottom_right.vertical}));
+    if (intersection) {
+      bottom_right_inner = SkPoint({intersection->x(), intersection->y()});
+    }
+  }
+
+  // Top
+  SkPoint top_points[4] = {top_left_outer, top_left_inner,     // A, E
+                           top_right_inner, top_right_outer};  // F, B
+  SetUpDrawStateClipPath(draw_state, top_points);
+  DrawSolidRoundedRectBorderToRenderTarget(draw_state, rect, rounded_corners,
+                                           content_rect, inner_rounded_corners,
+                                           border.top.color);
+
+  // Left
+  SkPoint left_points[4] = {top_left_outer, bottom_left_outer,   // A, C
+                            bottom_left_inner, top_left_inner};  // G, E
+  SetUpDrawStateClipPath(draw_state, left_points);
+  DrawSolidRoundedRectBorderToRenderTarget(draw_state, rect, rounded_corners,
+                                           content_rect, inner_rounded_corners,
+                                           border.left.color);
+
+  // Bottom
+  SkPoint bottom_points[4] = {bottom_left_inner, bottom_left_outer,     // G, C
+                              bottom_right_outer, bottom_right_inner};  // D, H
+  SetUpDrawStateClipPath(draw_state, bottom_points);
+  DrawSolidRoundedRectBorderToRenderTarget(draw_state, rect, rounded_corners,
+                                           content_rect, inner_rounded_corners,
+                                           border.bottom.color);
+
+  // Right
+  SkPoint right_points[4] = {top_right_inner, bottom_right_inner,   // F, H
+                             bottom_right_outer, top_right_outer};  // D, B
+  SetUpDrawStateClipPath(draw_state, right_points);
+  DrawSolidRoundedRectBorderToRenderTarget(draw_state, rect, rounded_corners,
+                                           content_rect, inner_rounded_corners,
+                                           border.right.color);
+}
+
 void DrawSolidRoundedRectBorderSoftware(
     RenderTreeNodeVisitorDrawState* draw_state, const math::RectF& rect,
     const render_tree::RoundedCorners& rounded_corners,
@@ -1196,9 +1394,18 @@
   RenderTreeNodeVisitorDrawState sub_draw_state(*draw_state);
   sub_draw_state.render_target = &canvas;
 
-  DrawSolidRoundedRectBorderToRenderTarget(&sub_draw_state, canvas_rect,
-                                           rounded_corners, canvas_content_rect,
-                                           inner_rounded_corners, border);
+  if (AllBorderSidesShareSameProperties(border)) {
+    // If all 4 edges share the same border properties, render the whole RRect
+    // at once.
+    DrawSolidRoundedRectBorderToRenderTarget(
+        &sub_draw_state, canvas_rect, rounded_corners, canvas_content_rect,
+        inner_rounded_corners, border.top.color);
+  } else {
+    DrawSolidRoundedRectBorderByEdge(&sub_draw_state, canvas_rect,
+                                     rounded_corners, canvas_content_rect,
+                                     inner_rounded_corners, border);
+  }
+
   canvas.flush();
 
   SkPaint render_target_paint;
@@ -1207,56 +1414,26 @@
                                         &render_target_paint);
 }
 
-namespace {
-bool IsCircle(const math::SizeF& size,
-              const render_tree::RoundedCorners& rounded_corners) {
-  if (size.width() != size.height()) {
-    return false;
-  }
-
-  float radius = size.width() * 0.5f;
-  // Corners cannot be "more round" than a circle, so we check using >= rather
-  // than == here.
-  return rounded_corners.AllCornersGE(
-      render_tree::RoundedCorner(radius, radius));
-}
-
-bool ValidateSolidBorderProperties(const render_tree::Border& border) {
-  if ((border.top == border.left) &&
-      (border.top == border.right) &&
-      (border.top == border.bottom) &&
-      (border.top.style == render_tree::kBorderStyleSolid)) {
-    return true;
-  } else {
-    DLOG(ERROR) << "Border sides have different properties: " << border;
-    return false;
-  }
-}
-
-}  // namespace
-
 void DrawSolidRoundedRectBorder(
     RenderTreeNodeVisitorDrawState* draw_state, const math::RectF& rect,
     const render_tree::RoundedCorners& rounded_corners,
     const math::RectF& content_rect,
     const render_tree::RoundedCorners& inner_rounded_corners,
     const render_tree::Border& border) {
-  // We only support rendering of rounded corner borders if each side has
-  // the same properties.
-  DCHECK(ValidateSolidBorderProperties(border));
-
-  if (IsCircle(rect.size(), rounded_corners)) {
-    // We are able to render circular borders using hardware, so introduce
-    // a special case for them.
-    DrawSolidRoundedRectBorderToRenderTarget(draw_state, rect, rounded_corners,
-                                             content_rect,
-                                             inner_rounded_corners, border);
+  if (IsCircle(rect.size(), rounded_corners) &&
+      AllBorderSidesShareSameProperties(border)) {
+    // We are able to render circular borders, whose edges have the same
+    // properties, using hardware, so introduce a special case for them.
+    DrawSolidRoundedRectBorderToRenderTarget(
+        draw_state, rect, rounded_corners, content_rect, inner_rounded_corners,
+        border.top.color);
   } else {
     // For now we fallback to software for drawing most rounded corner borders,
     // with some situations specified above being special cased. The reason we
     // do this is to limit then number of shaders that need to be implemented.
-    NOTIMPLEMENTED() << "Warning: Software rasterizing a solid rectangle "
-                        "border.";
+    NOTIMPLEMENTED() << "Warning: Software rasterizing either a solid "
+                        "rectangle, oval or circle border with different "
+                        "properties.";
     DrawSolidRoundedRectBorderSoftware(draw_state, rect, rounded_corners,
                                        content_rect, inner_rounded_corners,
                                        border);
diff --git a/src/cobalt/renderer/rasterizer/testdata/EmptyRectWith4DifferentRoundedCornersAndEdgeColorsAndEdgeWidthsBorder-expected.png b/src/cobalt/renderer/rasterizer/testdata/EmptyRectWith4DifferentRoundedCornersAndEdgeColorsAndEdgeWidthsBorder-expected.png
new file mode 100644
index 0000000..aadf0b8
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/EmptyRectWith4DifferentRoundedCornersAndEdgeColorsAndEdgeWidthsBorder-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/EmptyRectWith4DifferentRoundedCornersAndEdgeColorsBorder-expected.png b/src/cobalt/renderer/rasterizer/testdata/EmptyRectWith4DifferentRoundedCornersAndEdgeColorsBorder-expected.png
new file mode 100644
index 0000000..9cdbe4e
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/EmptyRectWith4DifferentRoundedCornersAndEdgeColorsBorder-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/EmptyRectWith4DifferentRoundedCornersAndEdgeWidthsBorder-expected.png b/src/cobalt/renderer/rasterizer/testdata/EmptyRectWith4DifferentRoundedCornersAndEdgeWidthsBorder-expected.png
new file mode 100644
index 0000000..b62c4f3
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/EmptyRectWith4DifferentRoundedCornersAndEdgeWidthsBorder-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/EmptyRectWithRoundedCornersAnd4DifferentEdgeColorsAndEdgeWidthsBorder-expected.png b/src/cobalt/renderer/rasterizer/testdata/EmptyRectWithRoundedCornersAnd4DifferentEdgeColorsAndEdgeWidthsBorder-expected.png
new file mode 100644
index 0000000..b97b7e3
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/EmptyRectWithRoundedCornersAnd4DifferentEdgeColorsAndEdgeWidthsBorder-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/EmptyRectWithRoundedCornersAnd4DifferentEdgeColorsBorder-expected.png b/src/cobalt/renderer/rasterizer/testdata/EmptyRectWithRoundedCornersAnd4DifferentEdgeColorsBorder-expected.png
new file mode 100644
index 0000000..ca41662
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/EmptyRectWithRoundedCornersAnd4DifferentEdgeColorsBorder-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/EmptyRectWithRoundedCornersAnd4DifferentEdgeWidthsBorder-expected.png b/src/cobalt/renderer/rasterizer/testdata/EmptyRectWithRoundedCornersAnd4DifferentEdgeWidthsBorder-expected.png
new file mode 100644
index 0000000..c591a83
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/EmptyRectWithRoundedCornersAnd4DifferentEdgeWidthsBorder-expected.png
Binary files differ
diff --git a/src/cobalt/script/execution_state.cc b/src/cobalt/script/execution_state.cc
index 3f09116..4d14f0a 100644
--- a/src/cobalt/script/execution_state.cc
+++ b/src/cobalt/script/execution_state.cc
@@ -34,7 +34,8 @@
 };
 
 std::string ExecutionStateImpl::GetStackTrace() const {
-  return StackTraceToString(global_environment_->GetStackTrace());
+  return StackTraceToString(
+      global_environment_->GetStackTrace(0 /*max_frames*/));
 }
 
 }  // namespace
diff --git a/src/cobalt/script/fake_global_environment.h b/src/cobalt/script/fake_global_environment.h
index 68349e7..470a7e4 100644
--- a/src/cobalt/script/fake_global_environment.h
+++ b/src/cobalt/script/fake_global_environment.h
@@ -27,15 +27,15 @@
  public:
   void CreateGlobalObject() OVERRIDE {}
   bool EvaluateScript(const scoped_refptr<SourceCode>& /*script_utf8*/,
-                      std::string* /*out_result*/,
-                      bool /*mute_script_erros_report*/) OVERRIDE {
+                      bool /*mute_errors*/,
+                      std::string* /*out_result*/) OVERRIDE {
     return false;
   }
   bool EvaluateScript(
       const scoped_refptr<SourceCode>& /*script_utf8*/,
-      const scoped_refptr<Wrappable>& /*owning_object*/,
-      base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle,
-      bool /*mute_errors*/) OVERRIDE {
+      const scoped_refptr<Wrappable>& /*owning_object*/, bool /*mute_errors*/,
+      base::optional<OpaqueHandleHolder::Reference>* /*out_opaque_handle*/)
+      OVERRIDE {
     return false;
   }
   // False positive lint error.
diff --git a/src/cobalt/script/fake_script_runner.h b/src/cobalt/script/fake_script_runner.h
index cb304ed..cc4a1cb 100644
--- a/src/cobalt/script/fake_script_runner.h
+++ b/src/cobalt/script/fake_script_runner.h
@@ -29,8 +29,7 @@
   FakeScriptRunner() : fake_global_environment_(new FakeGlobalEnvironment()) {}
   std::string Execute(const std::string& /*script_utf8*/,
                       const base::SourceLocation& /*script_location*/,
-                      bool* out_succeeded,
-                      bool /*mute_script_erros_report*/) OVERRIDE {
+                      bool /*mute_errors*/, bool* out_succeeded) OVERRIDE {
     if (out_succeeded) {
       *out_succeeded = true;
     }
diff --git a/src/cobalt/script/global_environment.h b/src/cobalt/script/global_environment.h
index daf1e38..ba6fbeb 100644
--- a/src/cobalt/script/global_environment.h
+++ b/src/cobalt/script/global_environment.h
@@ -58,8 +58,8 @@
   // If out_result is non-NULL, it will be set to hold the result of the script
   // evaluation if the script succeeds, or an exception message if it fails.
   virtual bool EvaluateScript(const scoped_refptr<SourceCode>& script_utf8,
-                              std::string* out_result_utf8,
-                              bool mute_errors) = 0;
+                              bool mute_errors,
+                              std::string* out_result_utf8) = 0;
 
   // Evaluate the JavaScript source code. Returns true on success,
   // false if there is an exception.
@@ -67,14 +67,13 @@
   // of the script that is owned by |owner|.
   virtual bool EvaluateScript(
       const scoped_refptr<SourceCode>& script_utf8,
-      const scoped_refptr<Wrappable>& owning_object,
-      base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle,
-      bool mute_errors) = 0;
+      const scoped_refptr<Wrappable>& owning_object, bool mute_errors,
+      base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle) = 0;
 
   // Returns the stack trace as a vector of individual frames.
   // Set |max_frames| to 0 to retrieve all available frames. Otherwise
   // return at most |max_frames|.
-  virtual std::vector<StackFrame> GetStackTrace(int max_frames = 0) = 0;
+  virtual std::vector<StackFrame> GetStackTrace(int max_frames) = 0;
 
   // Prevent this wrappable's associated JS wrapper object from being garbage
   // collected. AllowGarbageCollection must be called some time afterwards or
diff --git a/src/cobalt/script/javascript_engine.h b/src/cobalt/script/javascript_engine.h
index c8e4f72..e9388fa 100644
--- a/src/cobalt/script/javascript_engine.h
+++ b/src/cobalt/script/javascript_engine.h
@@ -11,6 +11,7 @@
 // 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_SCRIPT_JAVASCRIPT_ENGINE_H_
 #define COBALT_SCRIPT_JAVASCRIPT_ENGINE_H_
 
@@ -31,7 +32,7 @@
   struct Options {
     Options() : disable_jit(false), gc_threshold_bytes(1024*1024) {}
 
-    // Default false. When set to true then the javascript engine should
+    // Default false. When set to true then the JavaScript engine should
     // disable the just-in-time compiler.
     bool disable_jit;
 
@@ -51,8 +52,8 @@
       const Options& options = Options());
 
   // Updates the memory usage and returns the total memory that is reserved
-  // across all of the engines. This includes the part that is actually occupied
-  // by JS objects, and the part that is not yet.
+  // across all of the engines. This includes the part that is actually
+  // occupied by JavaScript objects, and the part that is not yet.
   // This function is defined per-implementation.
   static size_t UpdateMemoryStatsAndReturnReserved();
 
@@ -62,11 +63,11 @@
   // Kick off the engine's garbage collection synchronously.
   virtual void CollectGarbage() = 0;
 
-  // Indicate to the JS heap that extra bytes have been allocated by some
-  // Javascript object. This may mean collection needs to happen sooner.
+  // Indicate to the JavaScript heap that extra bytes have been allocated by
+  // some Javascript object. This may mean collection needs to happen sooner.
   virtual void ReportExtraMemoryCost(size_t bytes) = 0;
 
-  // Installs an ErrorHandler for listening to javascript errors.
+  // Installs an ErrorHandler for listening to JavaScript errors.
   // Returns true if the error handler could be installed. False otherwise.
   virtual bool RegisterErrorHandler(ErrorHandler handler) = 0;
 
diff --git a/src/cobalt/script/mozjs-45/callback_function_conversion.h b/src/cobalt/script/mozjs-45/callback_function_conversion.h
index 5087404..2f56bb5 100644
--- a/src/cobalt/script/mozjs-45/callback_function_conversion.h
+++ b/src/cobalt/script/mozjs-45/callback_function_conversion.h
@@ -81,8 +81,7 @@
 
   MozjsGlobalEnvironment* global_environment =
       static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context));
-  *out_callback_function = MozjsCallbackHolderClass(
-      object, context, global_environment->wrapper_factory());
+  *out_callback_function = MozjsCallbackHolderClass(context, object);
 }
 
 }  // namespace mozjs
diff --git a/src/cobalt/script/mozjs-45/conversion_helpers.cc b/src/cobalt/script/mozjs-45/conversion_helpers.cc
index 1870b1a..46a7b25 100644
--- a/src/cobalt/script/mozjs-45/conversion_helpers.cc
+++ b/src/cobalt/script/mozjs-45/conversion_helpers.cc
@@ -104,8 +104,7 @@
   DCHECK(js_object);
   MozjsGlobalEnvironment* global_environment =
       static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context));
-  *out_holder = MozjsObjectHandleHolder(js_object, context,
-                                        global_environment->wrapper_factory());
+  *out_holder = MozjsObjectHandleHolder(context, js_object);
 }
 
 // ValueHandle -> JSValue
@@ -133,8 +132,7 @@
       << "Unexpected conversion flags found.";
   MozjsGlobalEnvironment* global_environment =
       static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context));
-  *out_holder = MozjsValueHandleHolder(value, context,
-                                       global_environment->wrapper_factory());
+  *out_holder = MozjsValueHandleHolder(context, value);
 }
 
 }  // namespace mozjs
diff --git a/src/cobalt/script/mozjs-45/conversion_helpers.h b/src/cobalt/script/mozjs-45/conversion_helpers.h
index c23b660..e7a0065 100644
--- a/src/cobalt/script/mozjs-45/conversion_helpers.h
+++ b/src/cobalt/script/mozjs-45/conversion_helpers.h
@@ -17,11 +17,13 @@
 
 #include <limits>
 #include <string>
+#include <vector>
 
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/optional.h"
 #include "base/stringprintf.h"
+#include "cobalt/base/compiler.h"
 #include "cobalt/base/enable_if.h"
 #include "cobalt/base/token.h"
 #include "cobalt/script/mozjs-45/mozjs_callback_interface_holder.h"
@@ -99,6 +101,17 @@
                  int conversion_flags, ExceptionState* exception_state,
                  std::string* out_string);
 
+// std::vector<uint8_t> -> JSValue
+// Note that this conversion is specifically for the Web IDL type ByteString.
+// Ideally, conversion requests would be explicit in what type they wanted to
+// convert to, however it is currently solely based on input type.
+inline void ToJSValue(JSContext* context, const std::vector<uint8_t>& in_data,
+                      JS::MutableHandleValue out_value) {
+  JSString* js_string = JS_NewStringCopyN(
+      context, reinterpret_cast<const char*>(in_data.data()), in_data.size());
+  out_value.setString(js_string);
+}
+
 // base::Token -> JSValue
 inline void ToJSValue(JSContext* context, const base::Token& token,
                       JS::MutableHandleValue out_value) {
@@ -121,7 +134,9 @@
   DCHECK_EQ(conversion_flags, kNoConversionFlags)
       << "No conversion flags supported.";
   DCHECK(out_boolean);
-  // ToBoolean implements the ECMAScript ToBoolean operation.
+  // |JS::ToBoolean| implements the ECMAScript ToBoolean operation.
+  // Note that |JS::ToBoolean| will handle the case in which |value| is of
+  // type Symbol without throwing.
   *out_boolean = JS::ToBoolean(value);
 }
 
@@ -197,6 +212,12 @@
   TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(out_number);
 
+  if (UNLIKELY(value.isSymbol())) {
+    exception_state->SetSimpleException(
+        kTypeError, "Cannot convert a Symbol value to a number");
+    return;
+  }
+
   int32_t out;
   // Convert a JavaScript value to an integer type as specified by the
   // ECMAScript standard.
@@ -226,6 +247,13 @@
                                  (sizeof(T) > 4),
                              T>::type* = NULL) {
   TRACK_MEMORY_SCOPE("Javascript");
+
+  if (UNLIKELY(value.isSymbol())) {
+    exception_state->SetSimpleException(
+        kTypeError, "Cannot convert a Symbol value to a number");
+    return;
+  }
+
   double to_number;
   JS::ToNumber(context, value, &to_number);
 
@@ -294,6 +322,12 @@
   TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(out_number);
 
+  if (UNLIKELY(value.isSymbol())) {
+    exception_state->SetSimpleException(
+        kTypeError, "Cannot convert a Symbol value to a number");
+    return;
+  }
+
   uint32_t out;
   // Convert a JavaScript value to an integer type as specified by the
   // ECMAScript standard.
@@ -327,6 +361,12 @@
   TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(out_number);
 
+  if (UNLIKELY(value.isSymbol())) {
+    exception_state->SetSimpleException(
+        kTypeError, "Cannot convert a Symbol value to a number");
+    return;
+  }
+
   uint64_t out;
   // This produces and IDL unsigned long long.
   // TODO: Consider only creating |value_to_convert| if the conversion flag is
@@ -382,6 +422,13 @@
   DCHECK_EQ(conversion_flags & ~kConversionFlagsNumeric, 0)
       << "Unexpected conversion flags found.";
   DCHECK(out_number);
+
+  if (UNLIKELY(value.isSymbol())) {
+    exception_state->SetSimpleException(
+        kTypeError, "Cannot convert a Symbol value to a number");
+    return;
+  }
+
   double double_value;
   if (!JS::ToNumber(context, value, &double_value)) {
     exception_state->SetSimpleException(kNotNumberType);
@@ -602,8 +649,8 @@
 
   JS::RootedObject implementing_object(context, &value.toObject());
   DCHECK(implementing_object);
-  *out_callback_interface = MozjsCallbackInterfaceHolder<T>(
-      implementing_object, context, global_environment->wrapper_factory());
+  *out_callback_interface =
+      MozjsCallbackInterfaceHolder<T>(context, implementing_object);
 }
 
 template <typename T>
diff --git a/src/cobalt/script/mozjs-45/mozjs_callback_interface_holder.h b/src/cobalt/script/mozjs-45/mozjs_callback_interface_holder.h
index c14ced1..998c2b2 100644
--- a/src/cobalt/script/mozjs-45/mozjs_callback_interface_holder.h
+++ b/src/cobalt/script/mozjs-45/mozjs_callback_interface_holder.h
@@ -30,12 +30,10 @@
  public:
   typedef MozjsUserObjectHolder<MozjsCallbackInterface> BaseClass;
   MozjsCallbackInterfaceHolder() {}
-  MozjsCallbackInterfaceHolder(JS::HandleObject object, JSContext* context,
-                               WrapperFactory* wrapper_factory)
-      : BaseClass(object, context, wrapper_factory) {}
-  MozjsCallbackInterfaceHolder(JS::HandleValue value, JSContext* context,
-                               WrapperFactory* wrapper_factory)
-      : BaseClass(value, context, wrapper_factory) {}
+  MozjsCallbackInterfaceHolder(JSContext* context, JS::HandleObject object)
+      : BaseClass(context, object) {}
+  MozjsCallbackInterfaceHolder(JSContext* context, JS::HandleValue value)
+      : BaseClass(context, value) {}
 };
 
 template <typename CallbackInterface>
diff --git a/src/cobalt/script/mozjs-45/mozjs_global_environment.cc b/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
index bf451ff..8d03389 100644
--- a/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
+++ b/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
@@ -188,8 +188,8 @@
 }
 
 bool MozjsGlobalEnvironment::EvaluateScript(
-    const scoped_refptr<SourceCode>& source_code, std::string* out_result_utf8,
-    bool mute_errors) {
+    const scoped_refptr<SourceCode>& source_code, bool mute_errors,
+    std::string* out_result_utf8) {
   TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(thread_checker_.CalledOnValidThread());
 
@@ -202,7 +202,7 @@
   last_error_message_ = &error_message;
 
   bool success =
-      EvaluateScriptInternal(source_code, &result_value, mute_errors);
+      EvaluateScriptInternal(source_code, mute_errors, &result_value);
   if (out_result_utf8) {
     if (success) {
       MozjsExceptionState exception_state(context_);
@@ -220,9 +220,8 @@
 
 bool MozjsGlobalEnvironment::EvaluateScript(
     const scoped_refptr<SourceCode>& source_code,
-    const scoped_refptr<Wrappable>& owning_object,
-    base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle,
-    bool mute_errors) {
+    const scoped_refptr<Wrappable>& owning_object, bool mute_errors,
+    base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle) {
   TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(thread_checker_.CalledOnValidThread());
   JSAutoRequest auto_request(context_);
@@ -230,20 +229,19 @@
   JS::AutoSaveExceptionState auto_save_exception_state(context_);
   JS::RootedValue result_value(context_);
   bool success =
-      EvaluateScriptInternal(source_code, &result_value, mute_errors);
+      EvaluateScriptInternal(source_code, mute_errors, &result_value);
   if (success && out_opaque_handle) {
     JS::RootedObject js_object(context_);
     JS_ValueToObject(context_, result_value, &js_object);
-    MozjsObjectHandleHolder mozjs_object_holder(js_object, context_,
-                                                wrapper_factory());
+    MozjsObjectHandleHolder mozjs_object_holder(context_, js_object);
     out_opaque_handle->emplace(owning_object.get(), mozjs_object_holder);
   }
   return success;
 }
 
 bool MozjsGlobalEnvironment::EvaluateScriptInternal(
-    const scoped_refptr<SourceCode>& source_code,
-    JS::MutableHandleValue out_result, bool mute_errors) {
+    const scoped_refptr<SourceCode>& source_code, bool mute_errors,
+    JS::MutableHandleValue out_result) {
   TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(global_object_proxy_);
@@ -268,8 +266,8 @@
   }
 
   JS::CompileOptions options(context_);
-  options.setFileAndLine(location.file_path.c_str(), location.line_number);
-  options.setMutedErrors(mute_errors);
+  options.setFileAndLine(location.file_path.c_str(), location.line_number)
+      .setMutedErrors(mute_errors);
   bool success =
       JS::Evaluate(context_, options, inflated_buffer, length, out_result);
   if (!success && context_->isExceptionPending()) {
@@ -287,7 +285,7 @@
   scoped_refptr<SourceCode> source_code =
       new MozjsSourceCode(source, base::SourceLocation(filename, 1, 1));
   std::string result;
-  bool success = EvaluateScript(source_code, &result, false /*mute_errors*/);
+  bool success = EvaluateScript(source_code, false /*mute_errors*/, &result);
   if (!success) {
     DLOG(FATAL) << result;
   }
@@ -497,8 +495,7 @@
   // corresponding object, then the null value must be used instead.
   //   https://www.w3.org/TR/html5/webappapis.html#runtime-script-errors
   if (exception.isObject()) {
-    error_report.error.reset(
-        new MozjsValueHandleHolder(exception, context_, wrapper_factory()));
+    error_report.error.reset(new MozjsValueHandleHolder(context_, exception));
   }
   error_report.is_muted = report->isMuted;
 
diff --git a/src/cobalt/script/mozjs-45/mozjs_global_environment.h b/src/cobalt/script/mozjs-45/mozjs_global_environment.h
index 5a11a63..643d0ec 100644
--- a/src/cobalt/script/mozjs-45/mozjs_global_environment.h
+++ b/src/cobalt/script/mozjs-45/mozjs_global_environment.h
@@ -50,14 +50,14 @@
 
   void CreateGlobalObject() OVERRIDE;
 
-  bool EvaluateScript(const scoped_refptr<SourceCode>& script,
-                      std::string* out_result_utf8, bool mute_errors) OVERRIDE;
+  bool EvaluateScript(const scoped_refptr<SourceCode>& script, bool mute_errors,
+                      std::string* out_result_utf8) OVERRIDE;
 
-  bool EvaluateScript(
-      const scoped_refptr<SourceCode>& script_utf8,
-      const scoped_refptr<Wrappable>& owning_object,
-      base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle,
-      bool mute_errors) OVERRIDE;
+  bool EvaluateScript(const scoped_refptr<SourceCode>& script_utf8,
+                      const scoped_refptr<Wrappable>& owning_object,
+                      bool mute_errors,
+                      base::optional<OpaqueHandleHolder::Reference>*
+                          out_opaque_handle) OVERRIDE;
 
   std::vector<StackFrame> GetStackTrace(int max_frames = 0) OVERRIDE;
 
@@ -144,8 +144,8 @@
 
  private:
   bool EvaluateScriptInternal(const scoped_refptr<SourceCode>& source_code,
-                              JS::MutableHandleValue out_result,
-                              bool mute_errors);
+                              bool mute_errors,
+                              JS::MutableHandleValue out_result);
 
   void EvaluateEmbeddedScript(const unsigned char* data, size_t size,
                               const char* filename);
diff --git a/src/cobalt/script/mozjs-45/mozjs_script_value_factory.h b/src/cobalt/script/mozjs-45/mozjs_script_value_factory.h
index c2612cf..4f7d02e 100644
--- a/src/cobalt/script/mozjs-45/mozjs_script_value_factory.h
+++ b/src/cobalt/script/mozjs-45/mozjs_script_value_factory.h
@@ -45,8 +45,8 @@
     JS::RootedObject promise_wrapper(
         context, PromiseWrapper::Create(context, global_object));
     DCHECK(promise_wrapper);
-    scoped_ptr<ScriptPromiseType> promise(new MozjsPromiseHolderType(
-        promise_wrapper, context, global_environment_->wrapper_factory()));
+    scoped_ptr<ScriptPromiseType> promise(
+        new MozjsPromiseHolderType(context, promise_wrapper));
     return promise.Pass();
   }
 
diff --git a/src/cobalt/script/mozjs-45/mozjs_user_object_holder.h b/src/cobalt/script/mozjs-45/mozjs_user_object_holder.h
index 5f6cd95..f1fe6c4 100644
--- a/src/cobalt/script/mozjs-45/mozjs_user_object_holder.h
+++ b/src/cobalt/script/mozjs-45/mozjs_user_object_holder.h
@@ -23,9 +23,8 @@
 #include "cobalt/script/mozjs-45/wrapper_factory.h"
 #include "cobalt/script/mozjs-45/wrapper_private.h"
 #include "cobalt/script/script_value.h"
-#include "third_party/mozjs-45/js/src/jsapi.h"
-
 #include "nb/memory_scope.h"
+#include "third_party/mozjs-45/js/src/jsapi.h"
 
 namespace cobalt {
 namespace script {
@@ -45,21 +44,16 @@
 
   MozjsUserObjectHolder()
       : context_(NULL),
-        wrapper_factory_(NULL),
         prevent_garbage_collection_count_(0) {}
 
-  MozjsUserObjectHolder(JS::HandleObject object, JSContext* context,
-                        WrapperFactory* wrapper_factory)
-      : handle_(MozjsUserObjectType(context, object)),
-        context_(context),
-        wrapper_factory_(wrapper_factory),
+  MozjsUserObjectHolder(JSContext* context, JS::HandleObject object)
+      : context_(context),
+        handle_(MozjsUserObjectType(context, object)),
         prevent_garbage_collection_count_(0) {}
 
-  MozjsUserObjectHolder(JS::HandleValue value, JSContext* context,
-                        WrapperFactory* wrapper_factory)
-      : handle_(MozjsUserObjectType(context, value)),
-        context_(context),
-        wrapper_factory_(wrapper_factory),
+  MozjsUserObjectHolder(JSContext* context, JS::HandleValue value)
+      : context_(context),
+        handle_(MozjsUserObjectType(context, value)),
         prevent_garbage_collection_count_(0) {}
 
   ~MozjsUserObjectHolder() {
@@ -121,7 +115,7 @@
     JSAutoRequest auto_request(context_);
     JS::RootedValue rooted_value(context_, js_value());
     return make_scoped_ptr<BaseClass>(
-        new MozjsUserObjectHolder(rooted_value, context_, wrapper_factory_));
+        new MozjsUserObjectHolder(context_, rooted_value));
   }
 
   bool EqualTo(const BaseClass& other) const OVERRIDE {
@@ -157,7 +151,6 @@
 
   JSContext* context_;
   base::optional<MozjsUserObjectType> handle_;
-  WrapperFactory* wrapper_factory_;
   int prevent_garbage_collection_count_;
   base::optional<JS::Value> persistent_root_;
 };
diff --git a/src/cobalt/script/script_runner.cc b/src/cobalt/script/script_runner.cc
index 1da3b56..0c372ac 100644
--- a/src/cobalt/script/script_runner.cc
+++ b/src/cobalt/script/script_runner.cc
@@ -70,7 +70,7 @@
 
   std::string Execute(const std::string& script_utf8,
                       const base::SourceLocation& script_location,
-                      bool* out_succeeded, bool mute_errors) OVERRIDE;
+                      bool mute_errors, bool* out_succeeded) OVERRIDE;
   GlobalEnvironment* GetGlobalEnvironment() const OVERRIDE {
     return global_environment_;
   }
@@ -81,7 +81,7 @@
 
 std::string ScriptRunnerImpl::Execute(
     const std::string& script_utf8, const base::SourceLocation& script_location,
-    bool* out_succeeded, bool mute_errors) {
+    bool mute_errors, bool* out_succeeded) {
   scoped_refptr<SourceCode> source_code =
       SourceCode::CreateSourceCode(script_utf8, script_location);
   if (out_succeeded) {
@@ -92,7 +92,7 @@
     return "";
   }
   std::string result;
-  if (!global_environment_->EvaluateScript(source_code, &result, mute_errors)) {
+  if (!global_environment_->EvaluateScript(source_code, mute_errors, &result)) {
     DLOG(WARNING) << "Failed to execute JavaScript: " << result;
 #if defined(HANDLE_CORE_DUMP)
     script_runner_log.Get().IncrementFailCount();
diff --git a/src/cobalt/script/script_runner.h b/src/cobalt/script/script_runner.h
index 5f399d4..fb2eb27 100644
--- a/src/cobalt/script/script_runner.h
+++ b/src/cobalt/script/script_runner.h
@@ -36,7 +36,7 @@
   //   script executed without errors.
   virtual std::string Execute(const std::string& script_utf8,
                               const base::SourceLocation& script_location,
-                              bool* out_succeeded, bool mute_errors) = 0;
+                              bool mute_errors, bool* out_succeeded) = 0;
   virtual GlobalEnvironment* GetGlobalEnvironment() const { return NULL; }
   virtual ~ScriptRunner() {}
 };
diff --git a/src/cobalt/script/standalone_javascript_runner.cc b/src/cobalt/script/standalone_javascript_runner.cc
index aca3084..9c80eee 100644
--- a/src/cobalt/script/standalone_javascript_runner.cc
+++ b/src/cobalt/script/standalone_javascript_runner.cc
@@ -69,8 +69,8 @@
 
   // Execute the script and get the results of execution.
   std::string result;
-  bool success = global_environment_->EvaluateScript(source, &result,
-                                                     false /*mute_errors*/);
+  bool success = global_environment_->EvaluateScript(
+      source, false /*mute_errors*/, &result);
   // Echo the results to stdout.
   if (!success) {
     std::cout << "Exception: ";
diff --git a/src/cobalt/script/v8c/v8c.cc b/src/cobalt/script/v8c/v8c.cc
index 993cc58..8ef4f6f 100644
--- a/src/cobalt/script/v8c/v8c.cc
+++ b/src/cobalt/script/v8c/v8c.cc
@@ -95,7 +95,8 @@
 
         // Execute the script and get the results of execution.
         std::string result;
-        bool success = global_environment->EvaluateScript(source, &result);
+        bool success = global_environment->EvaluateScript(
+            source, false /*mute_errors*/, &result);
         // Echo the results to stdout.
         if (!success) {
           std::cout << "Exception: ";
diff --git a/src/cobalt/script/v8c/v8c_global_environment.cc b/src/cobalt/script/v8c/v8c_global_environment.cc
index a4d1c6f..a3c08bc 100644
--- a/src/cobalt/script/v8c/v8c_global_environment.cc
+++ b/src/cobalt/script/v8c/v8c_global_environment.cc
@@ -55,7 +55,7 @@
 }
 
 bool V8cGlobalEnvironment::EvaluateScript(
-    const scoped_refptr<SourceCode>& source_code,
+    const scoped_refptr<SourceCode>& source_code, bool mute_errors,
     std::string* out_result_utf8) {
   TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(thread_checker_.CalledOnValidThread());
@@ -65,22 +65,31 @@
   v8::Local<v8::Context> context = context_.Get(isolate_);
   v8::Context::Scope scope(context);
 
-  v8::TryCatch try_catch(isolate_);
-  // TODO: Also pass in a |v8::ScriptOrigin|.
   V8cSourceCode* v8c_source_code =
       base::polymorphic_downcast<V8cSourceCode*>(source_code.get());
+  const base::SourceLocation& source_location = v8c_source_code->location();
+
+  v8::TryCatch try_catch(isolate_);
+  v8::ScriptOrigin script_origin(
+      v8::String::NewFromUtf8(isolate_, source_location.file_path.c_str(),
+                              v8::NewStringType::kNormal)
+          .ToLocalChecked(),
+      v8::Integer::New(isolate_, source_location.line_number),
+      v8::Integer::New(isolate_, source_location.column_number),
+      v8::Boolean::New(isolate_, !mute_errors));
   v8::Local<v8::String> source =
       v8::String::NewFromUtf8(isolate_, v8c_source_code->source_utf8().c_str(),
                               v8::NewStringType::kNormal)
           .ToLocalChecked();
 
-  auto maybe_script = v8::Script::Compile(context, source);
+  v8::MaybeLocal<v8::Script> maybe_script =
+      v8::Script::Compile(context, source);
   v8::Local<v8::Script> script;
   if (!maybe_script.ToLocal(&script)) {
     return false;
   }
 
-  auto maybe_result = script->Run(context);
+  v8::MaybeLocal<v8::Value> maybe_result = script->Run(context);
   v8::Local<v8::Value> result;
   if (!maybe_result.ToLocal(&result)) {
     return false;
@@ -95,7 +104,7 @@
 
 bool V8cGlobalEnvironment::EvaluateScript(
     const scoped_refptr<SourceCode>& source_code,
-    const scoped_refptr<Wrappable>& owning_object,
+    const scoped_refptr<Wrappable>& owning_object, bool mute_errors,
     base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle) {
   TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/src/cobalt/script/v8c/v8c_global_environment.h b/src/cobalt/script/v8c/v8c_global_environment.h
index d60637f..224cc4d 100644
--- a/src/cobalt/script/v8c/v8c_global_environment.h
+++ b/src/cobalt/script/v8c/v8c_global_environment.h
@@ -46,11 +46,12 @@
 
   void CreateGlobalObject() override;
 
-  bool EvaluateScript(const scoped_refptr<SourceCode>& script,
+  bool EvaluateScript(const scoped_refptr<SourceCode>& script, bool mute_errors,
                       std::string* out_result_utf8) override;
 
   bool EvaluateScript(const scoped_refptr<SourceCode>& script_utf8,
                       const scoped_refptr<Wrappable>& owning_object,
+                      bool mute_errors,
                       base::optional<OpaqueHandleHolder::Reference>*
                           out_opaque_handle) override;
 
diff --git a/src/cobalt/site/docs/blog/index.md b/src/cobalt/site/docs/blog/index.md
new file mode 100644
index 0000000..7a9b5c2
--- /dev/null
+++ b/src/cobalt/site/docs/blog/index.md
@@ -0,0 +1,42 @@
+---
+layout: postlist
+title: Posts
+bodyclass: postslist
+tocDepth: h2
+tocHeader: Blog posts
+---
+
+{% for post in site.posts %}
+
+  {% if site.blog.posts_before_list and forloop.index > site.blog.posts_before_list %}
+
+{% if forloop.index0 == site.blog.posts_before_list %}
+## {{ site.blog.previous_post_text }}
+{% endif %}
+
+* [{{ post.title }}]({{ post.url | prepend: site.baseurl }}), {{ post.date | date_to_string }}
+
+  {% elsif site.excerpt_separator %}
+
+<p style="font-size: 0.8em; margin: 0;"><b>{{ post.date | date_to_string }}{% if post.attribution %}, {{ post.attribution }}{% endif %}</b></p>
+
+## {{ post.title }} <span>({{ post.date | date: "%b.&nbsp;%d&nbsp;%Y" }})</span>
+
+<p>{{ post.excerpt | remove: '<p>' | remove: '</p>' }} <a href="{{ post.url | prepend: site.baseurl }}">[read more]</a></p>
+
+{% unless forloop.last %}<hr>{% endunless %}
+
+  {% else %}
+
+## {{ post.title }} <span>({{ post.date | date: "%b.&nbsp;%d&nbsp;%Y" }})</span>
+
+<div class="postdate">
+Posted on {{ post.date | date: "%A, %B %d %Y" }} (<a href="{{ post.url }}">permanent link</a>)
+</div>
+{{ post.content }}
+
+{% unless forloop.last %}<hr>{% endunless %}
+
+  {% endif  %}
+
+{% endfor %}
diff --git a/src/cobalt/site/docs/contributors/index.md b/src/cobalt/site/docs/contributors/index.md
new file mode 100644
index 0000000..ea93cc6
--- /dev/null
+++ b/src/cobalt/site/docs/contributors/index.md
@@ -0,0 +1,64 @@
+---
+layout: doc
+title: "Contributing to Cobalt"
+---
+
+We'd love to hear about how you would like to contribute to Cobalt!
+Please read through this document first to understand the process and
+to make sure you know what to expect.
+
+## Before You Contribute
+
+### As an Individual
+
+Before Cobalt can use your code, as an unaffiliated individual, you must sign
+the [Google Individual Contributor License
+Agreement](https://cla.developers.google.com/about/google-individual) (CLA).
+You can complete that process online.
+
+### As a Company
+
+If you represent a company that wishes to have one or more employees contribute
+to Cobalt on behalf of your company, you need to agree to the
+[Software Grant and Corporate Contributor License Agreement](
+https://cla.developers.google.com/about/google-corporate).
+
+### What is a CLA?
+
+The Contributor License Agreement is necessary mainly because you own the
+copyright to your changes, even after your contribution becomes part of our
+codebase, so we need your permission to use and distribute your code. We also
+need to be sure of various other things — for instance that you‘ll tell us if
+you know that your code infringes on other people’s patents.
+
+You don‘t have to sign the CLA until after you’ve submitted your code for
+review and a member has approved it, but you must do it before we can put
+your code into our codebase. Before you start working on a larger
+contribution, get in touch with us to discuss your idea so that we can help
+out and possibly guide you. Early coordination makes it much easier to avoid
+frustration later on.
+
+### Code Reviews
+
+All submissions, including submissions by project members, require review. We
+currently use [Gerrit Code Review](https://www.gerritcodereview.com/) for this
+purpose. Currently, team-member submissions are reviewed privately, and
+external submissions go through public reviews.
+
+## Submission Process
+
+The following steps explain the submission process:
+
+*  Ensure you or your company have signed the appropriate CLA as discussed
+   in the [Before You Contribute](#before-you-contribute) section above.
+*  Rebase your changes down into a single git commit.
+*  Run `git cl upload` to upload the review to
+   [Cobalt's Gerrit instance](https://cobalt-review.googlesource.com/).
+*  Someone from the maintainers team reviews the code, adding comments on
+   any things that need to change before the code can be submitted.
+*  If you need to make changes, make them locally, test them, then
+   `git commit --amend` to add them to the **existing** commit. Then return
+   to step 2.
+*  If you do not need to make any more changes, a maintainer integrates the
+   change into our private repository, and it is pushed out to the public
+   repository after some time.
diff --git a/src/cobalt/site/docs/development/reference/supported-features.md b/src/cobalt/site/docs/development/reference/supported-features.md
new file mode 100644
index 0000000..087a1ae
--- /dev/null
+++ b/src/cobalt/site/docs/development/reference/supported-features.md
@@ -0,0 +1,168 @@
+---
+layout: doc
+title: "Cobalt Support Quick Reference"
+---
+
+## HTML elements
+
+*   `<body>`
+*   `<br>`
+*   `<div>`
+*   `<head>`
+*   `<html>`
+*   `<link>` (with `type="text/css"`)
+*   `<meta>`
+*   `<script>`
+*   `<span>`
+*   `<style>`
+*   `<video>`
+
+## CSS properties
+
+*   [animation](
+    https://www.w3.org/TR/css3-animations/#animation-shorthand-property)
+*   [background](https://www.w3.org/TR/css3-background/#the-background),
+    [background-color](
+    https://www.w3.org/TR/css3-background/#the-background-color),
+    [background-image](
+    https://www.w3.org/TR/css3-background/#the-background-image)
+*   [border](https://www.w3.org/TR/css3-background/#the-border-shorthands),
+    [border-top](
+    https://www.w3.org/TR/css3-background/#the-border-shorthands),
+    [border-bottom](
+    https://www.w3.org/TR/css3-background/#the-border-shorthands),
+    [border-left](
+    https://www.w3.org/TR/css3-background/#the-border-shorthands),
+    [border-right](
+    https://www.w3.org/TR/css3-background/#the-border-shorthands)
+*   [border-radius](https://www.w3.org/TR/css3-background/#the-border-radius)
+*   [border-style](https://www.w3.org/TR/css3-background/#the-border-style)
+*   [border-width](https://www.w3.org/TR/css3-background/#the-border-width)
+*   [box-shadow](https://www.w3.org/TR/css3-background/#the-box-shadow)
+*   [color](https://www.w3.org/TR/css3-color/#foreground)
+*   [content](https://www.w3.org/TR/CSS21/generate.html#content)
+*   [display](https://www.w3.org/TR/CSS21/visuren.html#propdef-display)
+*   [font](https://www.w3.org/TR/css-fonts-3/#font-prop)
+*   [@font-face](https://www.w3.org/TR/css-fonts-3/#font-face-rule)
+*   [font-family](https://www.w3.org/TR/css-fonts-3/#propdef-font-family)
+*   [font-size](https://www.w3.org/TR/css-fonts-3/#font-size-prop)
+*   [font-style](https://www.w3.org/TR/css-fonts-3/#font-style-prop)
+*   [font-weight](https://www.w3.org/TR/css-fonts-3/#font-weight-prop)
+*   [line-height](https://www.w3.org/TR/CSS2/visudet.html#propdef-line-height)
+*   [margin](https://www.w3.org/TR/CSS21/box.html#margin-properties),
+    [margin-top](https://www.w3.org/TR/CSS21/box.html#margin-properties),
+    [margin-bottom](https://www.w3.org/TR/CSS21/box.html#margin-properties),
+    [margin-left](https://www.w3.org/TR/CSS21/box.html#margin-properties),
+    [margin-right](https://www.w3.org/TR/CSS21/box.html#margin-properties)
+*   [max-height](https://www.w3.org/TR/CSS2/visudet.html#min-max-heights),
+    [max-width](https://www.w3.org/TR/CSS2/visudet.html#min-max-widths)
+*   [@media](https://www.w3.org/TR/css3-mediaqueries/)
+*   [opacity](https://www.w3.org/TR/css3-color/#transparency)
+*   [overflow](https://www.w3.org/TR/CSS2/visufx.html#overflow)
+*   [padding](https://www.w3.org/TR/CSS21/box.html#padding-properties),
+    [padding-top](https://www.w3.org/TR/CSS21/box.html#padding-properties),
+    [padding-bottom](https://www.w3.org/TR/CSS21/box.html#padding-properties),
+    [padding-left](https://www.w3.org/TR/CSS21/box.html#padding-properties),
+    [padding-right](https://www.w3.org/TR/CSS21/box.html#padding-properties)
+*   [position](https://www.w3.org/TR/CSS21/visuren.html#propdef-position)
+*   [top](https://www.w3.org/TR/CSS21/visuren.html#position-props),
+    [bottom](https://www.w3.org/TR/CSS21/visuren.html#position-props),
+    [left](https://www.w3.org/TR/CSS21/visuren.html#position-props),
+    [right](https://www.w3.org/TR/CSS21/visuren.html#position-props)
+*   [transform](https://www.w3.org/TR/css-transforms-1/#transform-property)
+*   [transform-origin](
+    https://www.w3.org/TR/css-transforms-1/#propdef-transform-origin)
+*   [transition](
+    https://www.w3.org/TR/css3-transitions/#transition-shorthand-property)
+*   [transition-delay](
+    https://www.w3.org/TR/css3-transitions/#transition-delay-property)
+*   [transition-duration](
+    https://www.w3.org/TR/css3-transitions/#transition-duration-property)
+*   [transition-property](
+    https://www.w3.org/TR/css3-transitions/#transition-property-property)
+*   [transition-timing-function](
+    https://www.w3.org/TR/css3-transitions/#transition-timing-function-property)
+*   [text-align](https://www.w3.org/TR/css-text-3/#text-align)
+*   [text-indent](https://www.w3.org/TR/css-text-3/#text-indent-property)
+*   [text-overflow](https://www.w3.org/TR/css3-ui/#propdef-text-overflow)
+*   [text-shadow](https://www.w3.org/TR/css-text-decor-3/#text-shadow-property)
+*   [text-transform](https://www.w3.org/TR/css-text-3/#text-transform-property)
+*   [vertical-align](
+    https://www.w3.org/TR/CSS2/visudet.html#propdef-vertical-align)
+    (supported values: `top`, `bottom`, `middle`, `baseline`)
+*   [visibility](https://www.w3.org/TR/CSS21/visufx.html#visibility)
+*   [white-space](https://www.w3.org/TR/css-text-3/#white-space-property)
+*   [z-index](https://www.w3.org/TR/CSS21/visuren.html#propdef-z-index)
+
+## CSS selectors
+
+*   Simple selectors:
+    ['*'](https://www.w3.org/TR/selectors4/#universal-selector),
+    [type](https://www.w3.org/TR/selectors4/#type-selectors),
+    [.class](https://www.w3.org/TR/selectors4/#class-html),
+    [#id](https://www.w3.org/TR/selectors4/#id-selectors),
+    [:empty](https://www.w3.org/TR/selectors4/#empty-pseudo),
+    [:focus](https://www.w3.org/TR/selectors4/#focus-pseudo),
+    [:not()](https://www.w3.org/TR/selectors4/#negation-pseudo)
+*   Pseudo elements:
+    [:before](https://www.w3.org/TR/selectors4/#pseudo-element),
+    [:after](https://www.w3.org/TR/selectors4/#pseudo-element),
+*   Combinators:
+    [' '](https://www.w3.org/TR/selectors4/#descendant-combinators),
+    ['>'](https://www.w3.org/TR/selectors4/#child-combinators),
+    ['+'](https://www.w3.org/TR/selectors4/#adjacent-sibling-combinators),
+    ['~'](https://www.w3.org/TR/selectors4/#general-sibling-combinators)
+*   [Grouping with ','](https://www.w3.org/TR/selectors4/#grouping)
+
+## JavaScript Web APIs
+
+*   [`Crypto.getRandomValues`](
+    https://www.w3.org/TR/WebCryptoAPI/#crypto-interface)
+*   [CSSOM](
+    http://www.w3.org/TR/cssom/) (partial)
+*   [CSSOM View](https://www.w3.org/TR/cssom-view-1/)
+    (no scrolling, moving, resizing)
+*   `Console.log`
+*   [DOM4](http://www.w3.org/TR/dom/) (partial)
+*   [EncryptedMedia Extensions v0.1b](
+    https://dvcs.w3.org/hg/html-media/raw-file/eme-v0.1b/encrypted-media/encrypted-media.html) (unprefixed)
+*   `Image` (for preloading and caching only)
+*   [Media Source Extensions, Editor's Draft 09 August 2012](
+    https://rawgit.com/w3c/media-source/6747ed7a3206f646963d760100b0f37e2fc7e47e/media-source.html)
+*   [Typed Arrays](
+    https://www.khronos.org/registry/typedarray/specs/latest/) (partial)
+*   [URL](https://url.spec.whatwg.org/#api) (partial)
+*   [Web Audio API](https://www.w3.org/TR/webaudio/) (partial)
+*   [Web Storage API](https://www.w3.org/TR/webstorage/)
+*   [XMLHttpRequest Level 1](http://www.w3.org/TR/XMLHttpRequest/)
+
+## Protocols
+
+*   https:
+*   h5vcc: (for embedded resources)
+*   [Content Security Policy Level 2](https://www.w3.org/TR/CSP2/)
+    in HTTP headers is _required_, and report-only is disabled.
+
+## Media formats
+
+### Containers
+
+*   FLV
+*   MKV (for WebM)
+*   MP4/FMP4
+*   WAV
+
+### Encodings (depending on platform support)
+
+*   AAC
+*   AVC (H.264) at 1080p/60fps ([Level
+    4.2](https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC#Levels))
+*   VP8/Vorbis
+*   VP9/Opus
+*   16-bit stereo PCM audio (for sound effects)
+
+### Images
+
+*   JPEG
+*   PNG
+*   WebP (non-animated)
diff --git a/src/cobalt/site/docs/development/setup-linux.md b/src/cobalt/site/docs/development/setup-linux.md
new file mode 100644
index 0000000..0a73913
--- /dev/null
+++ b/src/cobalt/site/docs/development/setup-linux.md
@@ -0,0 +1,173 @@
+---
+layout: doc
+title: "Set up your environment - Linux"
+---
+
+These instructions explain how Linux users set up their Cobalt development
+environment, fetch a copy of the Cobalt code repository, and build a Cobalt
+binary. Note that the binary has a graphical client and must be run locally
+on the machine that you are using to view the client. For example, you cannot
+SSH into another machine and run the binary on that machine.
+
+1.  Choose where you want to put the `depot_tools` directory, which is used
+    by the Cobalt code. An easy option is to put them in `~/depot_tools`.
+    Clone the tools by running the following command:
+
+    ```
+    $ cd ~/
+    $ git clone https://cobalt.googlesource.com/depot_tools
+    ```
+
+1.  Add your `depot_tools` directory to the end of your `PATH` variable.
+    We recommend adding something like this to your `.bashrc` or `.profile`
+    file:
+
+    ```
+    $ PATH=${PATH}:/path/to/depot_tools
+    ```
+
+1.  Run the following command to install packages needed to build and run
+    Cobalt on Linux:
+
+    ```
+    $ sudo apt-get install build-essential coreutils git gperf \
+           libasound2-dev libavformat-dev libavresample-dev \
+           libdirectfb-dev libdirectfb-extra libpulse-dev \
+           libgl1-mesa-dev libgles2-mesa-dev libx11-dev \
+           libxcomposite-dev libxcomposite1 libxrender-dev libxrender1 \
+           libxpm-dev m4 ruby tar xserver-xephyr xz-utils yasm
+    ```
+
+1.  Install the latest version of the standard C++ header files (`libstdc++`).
+    For example:
+
+    ```
+    sudo apt-get install libstdc++-4.8-dev
+    ```
+
+1.  Install `bison-2.7`. Note that this series of commands uninstalls any
+    version of `bison` that you already have installed to ensure that the
+    desired version is installed.
+
+    ```
+    $ sudo apt-get remove bison
+    $ cd /tmp
+    $ wget http://ftp.gnu.org/gnu/bison/bison-2.7.1.tar.gz
+    $ tar zxf bison-2.7.1.tar.gz
+    $ cd bison-2.7.1
+    $ sh configure && make && sudo make install
+    $ which bison
+    /usr/local/bin/bison
+    $ bison --version
+    bison (GNU Bison) 2.7.12-4996
+    ```
+
+1.  Clone the Cobalt code repository. The following `git` command creates a
+    `cobalt` directory that contains the repository:
+
+    ```
+    $ git clone https://cobalt.googlesource.com/cobalt
+    ```
+
+1.  Modify your path to include the version of Clang that is downloaded
+    in the next step of the instructions. The next step will return an
+    error if this version of Clang is not in your path before it runs.
+
+    ```
+    $PATH="/path/to/cobalt/src/third_party/llvm-build/Release+Asserts/bin:${PATH}"
+    ```
+
+1.  Build the code by navigating to the `src` directory in your new
+    `cobalt` directory and running the following command. You must
+    specify a platform when running this command. On goobuntu, the
+    canonical platform is `linux-x64x11`.
+
+    You can also use the `-C` command-line flag to specify a `build_type`.
+    Valid build types are `debug`, `devel`, `qa`, and `gold`. If you
+    specify a build type, the command finishes sooner. Otherwise, all types
+    are built.
+
+    ```
+    $ cobalt/build/gyp_cobalt [-C <build_type>] <platform>
+    ```
+
+    <aside class="note"><b>Important:</b> You need to rerun gyp_cobalt every
+    time a change is made to a `.gyp` file.</aside>
+
+1.  Compile the code from the `src/` directory:
+
+    ```
+    $ ninja -C out/<platform>_<build_type> <target_name>
+    ```
+
+    The previous command contains three variables:
+
+    1.  `<platform>` is the [platform
+        configuration](/starboard/porting.html#1-enumerate-and-name-your-platform-configurations)
+        that identifies the platform. As described in the Starboard porting
+        guide, it contains a `family name` (like `linux`) and a
+        `binary variant` (like `x64x11`), separated by a hyphen.
+    1.  `<build_type>` is the build you are compiling. Possible values are
+        `debug`, `devel`, `qa`, and `gold`. These values are also described in
+        the Starboard porting guide under the [required file modifications](
+        /starboard/porting.html#4-make-required-file-modifications) for the
+        `gyp_configuration.gypi` file.
+    1.  `<target_name>` is the name assigned to the compiled code and it is
+        used to run the code compiled in this step. The most common names are
+        `cobalt`, `nplb`, and `all`:
+        *   `cobalt` builds the Cobalt app.
+        *   `nplb` builds Starboard's platform verification test suite to
+            ensure that your platform's code passes all tests for running
+            Cobalt.
+        *   `all` builds all targets.
+
+    For example:
+
+    ```
+    ninja -C out/linux-x64x11_debug cobalt
+    ```
+
+    This command compiles the Cobalt `debug` configuration for the
+    `linux-x64x11` platform and creates a target named `cobalt` that
+    you can then use to run the compiled code.
+
+1.  Run the compiled code to launch the Cobalt client:
+
+    ```
+    # Note that 'cobalt' was the <target_name> from the previous step.
+    $ out/linux-x64x11_debug/cobalt [--url=<url>]
+    ```
+
+    The flags in the following table are frequently used, and the full set
+    of flags that this command supports are in <code><a
+    href="https://cobalt.googlesource.com/cobalt/+/master/src/cobalt/browser/switches.cc">cobalt/browser/switches.cc</a></code>.
+
+    <table class="details responsive">
+      <tr>
+        <th colspan="2">Flags</th>
+      </tr>
+      <tr>
+        <td><code>allow_http</code></td>
+        <td>Indicates that you want to use `http` instead of `https`.</td>
+      </tr>
+      <tr>
+        <td><code>ignore_certificate_errors</code></td>
+        <td>Indicates that you want to connect to an <code>https</code> host
+            that doesn't have a certificate that can be validated by our set
+            of root CAs.</td>
+      </tr>
+      <tr>
+        <td><code>url</code></td>
+        <td>Defines the startup URL that Cobalt will use. If no value is set,
+            then Cobalt uses a default URL. This option lets you point at a
+            different app than the YouTube app.</td>
+      </tr>
+    </table>
+
+<!--
+<aside class="note">
+<b>Note:</b> If you plan to upload reviews to the Cobalt repository, you
+also need to <a href="/development/setup-gitcookies.html">follow these
+instructions</a> to set up a <code>.gitcookies</code> file.
+</aside>
+-->
diff --git a/src/cobalt/site/docs/development/setup-raspi.md b/src/cobalt/site/docs/development/setup-raspi.md
new file mode 100644
index 0000000..5e5a352
--- /dev/null
+++ b/src/cobalt/site/docs/development/setup-raspi.md
@@ -0,0 +1,104 @@
+---
+layout: doc
+title: "Set up your environment - Raspberry Pi"
+---
+
+These instructions explain how to set up Cobalt for your workstation and your
+Raspberry Pi device.
+
+## Set up your device
+
+<aside class="note">
+<b>Note:</b> Raspberry Pi <em>cannot</em> have MesaGL installed and will return
+an error, like `DRI2 not supported` or `DRI2 failed to authenticate` if MesaGL
+is installed.
+</aside>
+
+The following commands update the package configuration on your Raspberry Pi
+so that Cobalt can run properly:
+
+```
+$ apt-get remove -y --purge --auto-remove libgl1-mesa-dev \
+          libegl1-mesa-dev libgles2-mesa libgles2-mesa-dev
+$ apt-get install -y libpulse-dev libasound2-dev libavformat-dev \
+          libavresample-dev
+```
+
+## Set up your workstation
+
+The following steps install the cross-compiling toolchain on your workstation.
+The toolchain runs on an x86 workstation and compiles binaries for your ARM
+Raspberry Pi.
+
+1.  Choose a location for the installed toolchain &ndash; e.g. `raspi-tools`
+    &ndash; and set `$RASPI_HOME` to that location.
+
+1.  Add `$RASPI_HOME` to your `.bashrc` (or equivalent).
+
+1.  Create the directory for the installed toolchain and go to it:
+
+    ```
+    mkdir -p $RASPI_HOME
+    cd $RASPI_HOME
+    ```
+
+1.  Clone the GitHub repository for Raspberry Pi tools:
+
+    ```
+    git clone git://github.com/raspberrypi/tools.git
+    ```
+
+1.  Sync your sysroot by completing the following steps:
+
+    1.  Boot up your RasPi, and set `$RASPI_ADDR` to the device's IP address.
+    1.  Run `mkdir -p $RASPI_HOME/sysroot`
+    1.  Run:
+
+        ``` 
+        rsync -avzh --safe-links \
+              --delete-after pi@$RASPI_ADDR:/{opt,lib,usr}
+              --exclude="lib/firmware" --exclude="lib/modules" \
+              --include="usr/lib" --include="usr/include" \
+              --include="usr/local/include" --include="usr/local/lib" \
+              --exclude="usr/*" --include="opt/vc" --exclude="opt/*" \
+              $RASPI_HOME/sysroot
+        password: raspberry
+        ```
+
+## Build, install, and run Cobalt for Raspberry Pi
+
+1.  Run the following commands to build Cobalt:
+
+    ```
+    $ gyp_cobalt raspi-1
+    $ ninja -C out/raspi-1_debug cobalt
+    ```
+
+1.  Run the following command to install your Cobalt binary (and content)
+    on the device:
+
+    ```
+    rsync -avzh --exclude="obj*" \
+          $COBALT_SRC/out/raspi-1_debug pi@$RASPI_ADDR:~/
+    ```
+
+    The `rsyncs` get somewhat faster after the first time, as `rsync` is good at
+    doing the minimum necessary effort.
+
+1.  Even if you have a keyboard hooked up to the RasPi, you should SSH
+    into the device to run Cobalt. Using SSH will make it easy for you
+    to quit or restart Cobalt.
+
+    ```
+    ssh pi@$RASPI_ADDR
+    cd raspi-1_debug
+    ./cobalt
+    ```
+
+    With this approach, you can just hit `[CTRL-C]` to close Cobalt. If you
+    were to run it from the console, you would have no way to quit without
+    SSHing into the device and killing the Cobalt process by its PID.
+
+    Note that you can also exit YouTube on Cobalt by hitting the `[Esc]` key
+    enough times to bring up the "Do you want to quit YouTube?" dialog and
+    selecting "yes".
diff --git a/src/cobalt/site/docs/index.md b/src/cobalt/site/docs/index.md
new file mode 100644
index 0000000..6a981fc
--- /dev/null
+++ b/src/cobalt/site/docs/index.md
@@ -0,0 +1,18 @@
+---
+layout: home
+---
+
+<div class="row">
+  <div class="col-md-4">
+    <h2><i class="material-icons">sd_card</i>&nbsp;Efficient</h2>
+    <p class="desc">Cobalt's small binary is optimized for memory, reducing the likelihood of out-of-memory crashes.</p>
+  </div>
+  <div class="col-md-4">
+    <h2><i class="material-icons">security</i>&nbsp;Secure</h2>
+    <p class="desc">Cobalt ensures strong security by requiring use of HTTPS and CSP.</p>
+  </div>
+  <div class="col-md-4">
+    <h2><i class="material-icons">devices_other</i>&nbsp;Cross-platform</h2>
+    <p class="desc">Cobalt's targeted, streamlined porting process supports a wide range of platforms and device types.</p>
+  </div>
+</div>
diff --git a/src/cobalt/site/docs/overview.md b/src/cobalt/site/docs/overview.md
new file mode 100644
index 0000000..db3f038
--- /dev/null
+++ b/src/cobalt/site/docs/overview.md
@@ -0,0 +1,88 @@
+---
+layout: doc
+title: "Getting started"
+---
+
+Cobalt is a lightweight HTML5/CSS/JS application container that is designed
+to provide a rich application development environment with minimal resource
+consumption (deployment size, RAM, CPU, GPU). At the same time, Cobalt enables
+a rich, low-latency user experience across a wide variety of platforms and
+devices.
+
+#### Target audiences
+
+Cobalt's documentation is written with two audiences in mind:
+
+*   **Porters** enable Cobalt to work on other platforms by using Starboard,
+    Cobalt's porting layer and OS abstraction, to implement the
+    platform-specific functionality that Cobalt uses. Each Starboard module
+    (memory, socket, thread, etc.) defines functions that must be implemented
+    for the porter's platform.
+
+*   **Developers** want to build applications in familiar environments with
+    advanced debugging tools without having to worry about compatibility with
+    a highly fragmented set of browsers. At the same time, they want to have
+    full control over their codebase so that they can ship features for
+    constrained platforms, like TVs, on time and without technical risk.
+
+## Benefits of Cobalt
+
+Cobalt significantly reduces the cost of supporting a browser on non-standard
+and resource-constrained platforms. In addition, since Cobalt operates at a
+consolidated, versioned platform abstraction layer, its porting effort is
+man-weeks, and subsequent rebases are near-free.
+
+These are some other benefits that Cobalt provides:
+
+*   **More platforms**
+
+    *   Cobalt does not require platforms to support JIT compilation and can
+        run on platforms that disallow execution of dynamically generated code.
+    *   Cobalt is a single-process application and does not rely on the ability
+        to spawn multiple processes.
+    *   Cobalt precompiles a set of shaders that are sufficient to express all
+        graphical effects, thereby accommodating platforms that cannot compile
+        shaders at runtime.
+    *   Cobalt requires a compliant C++03 compiler, allowing it to reach
+        platforms with legacy toolchains.
+
+*   **Small footprint**
+    *   Cobalt is optimized for memory. Its surface cache never exceeds a
+        predefined budget, and it never creates duplicate layers, reducing
+        the likelihood of out-of-memory crashes.
+    *   Cobalt's small binary is designed to take up as little space as
+        possible. By supporting a subset of HTML5/CSS/JS, Cobalt's reduced
+        package size even allows bundling of CJK fonts on low-end devices.
+
+*   **Reduced input latency**
+
+    *   Cobalt produces consistent 60FPS animations by only supporting
+        animation of properties that don't affect layout, like `transform`,
+        and always running animations on a separate thread.
+    *   Cobalt is optimized to run on single-core CPUs, resulting in better
+        input latency since the renderer and resource loader do not compete
+        with layout operations.
+    *   On platforms that support GLES2, Cobalt avoids CPU painting by
+        performing almost all rendering operations on the GPU.
+
+## Getting started
+
+### Porters
+
+Porters should begin with the [porting guide](/cobalt/starboard/porting.html),
+which explains how to use Starboard, Cobalt's porting layer, to customize the
+platform-specific functionality that Cobalt uses. There are several reference
+documents to help porters customize configuration files and to implement
+module-specific functionality. The [Testing with
+NPLB](/cobalt/starboard/testing.html) document provides an overview of
+Starboard's compliance test suite.
+
+### Developers
+
+Developers can follow the setup instructions for
+[Linux](/cobalt/development/setup-linux.html) or
+[RasPi](/cobalt/development/setup-raspi.html) to set up their Cobalt development
+environment, fetch a copy of the Cobalt code repository, and build a Cobalt
+binary. The [Cobalt support](/cobalt/development/reference/supported-features.html)
+guide lists the HTML elements, CSS properties, CSS selectors, and JavaScript Web
+APIs that developers can use in their Cobalt applications.
diff --git a/src/cobalt/site/docs/reference/starboard/configuration-public.md b/src/cobalt/site/docs/reference/starboard/configuration-public.md
new file mode 100644
index 0000000..1665986
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/configuration-public.md
@@ -0,0 +1,192 @@
+---
+layout: doc
+title: "Starboard Configuration Reference Guide"
+---
+
+## Architecture Configuration
+
+| Properties |
+| :--- |
+| **`SB_IS_BIG_ENDIAN`**<br><br>Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be automatically set based on this.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_IS_ARCH_ARM`**<br><br>Whether the current platform is an ARM architecture.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_IS_ARCH_MIPS`**<br><br>Whether the current platform is a MIPS architecture.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_IS_ARCH_PPC`**<br><br>Whether the current platform is a PPC architecture.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_IS_ARCH_X86`**<br><br>Whether the current platform is an x86 architecture.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_IS_32_BIT`**<br><br>Assume a 64-bit architecture.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_IS_64_BIT`**<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_32_BIT_POINTERS`**<br><br>Whether the current platform's pointers are 32-bit. Whether the current platform's longs are 32-bit.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_32_BIT_LONG`**<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_32_BIT_POINTERS`**<br><br>The default value in the Stub implementation is `0` |
+| **`SB_HAS_32_BIT_LONG`**<br><br>The default value in the Stub implementation is `0` |
+| **`SB_HAS_64_BIT_POINTERS`**<br><br>Whether the current platform's pointers are 64-bit. Whether the current platform's longs are 64-bit.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_64_BIT_LONG`**<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_64_BIT_POINTERS`**<br><br>The default value in the Stub implementation is `0` |
+| **`SB_HAS_64_BIT_LONG`**<br><br>The default value in the Stub implementation is `0` |
+| **`SB_HAS_MANY_CORES`**<br><br> Whether the current platform is expected to have many cores (> 6), or a wildly varying number of cores.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_1_CORE`**<br><br>Whether the current platform is expected to have exactly 1 core.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_HAS_2_CORES`**<br><br>Whether the current platform is expected to have exactly 2 cores.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_HAS_4_CORES`**<br><br>Whether the current platform is expected to have exactly 4 cores.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_HAS_6_CORES`**<br><br>Whether the current platform is expected to have exactly 6 cores.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_HAS_THREAD_PRIORITY_SUPPORT`**<br><br>Whether the current platform supports thread priorities.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_HAS_CROSS_CORE_SCHEDULER`**<br><br>Whether the current platform's thread scheduler will automatically balance threads between cores, as opposed to systems where threads will only ever run on the specifically pinned core.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_QUIRK_DOES_NOT_STACK_ALIGN_OVER_16_BYTES`**<br><br>Some platforms will not align variables on the stack with an alignment greater than 16 bytes. Platforms where this is the case should define the following quirk.<br><br>By default, this property is undefined. |
+| **`SB_HAS_QUIRK_THREAD_AFFINITY_UNSUPPORTED`**<br><br>Some platforms do not have thread affinity support. Platforms where this is the case should define the following quirk.<br><br>By default, this property is undefined. |
+
+
+## Compiler Configuration
+
+| Properties |
+| :--- |
+| **`SB_C_FORCE_INLINE`**<br><br>The platform's annotation for forcing a C function to be inlined.<br><br>The default value in the Stub implementation is <br>`__inline__ __attribute__((always_inline))` |
+| **`SB_C_INLINE`**<br><br>The platform's annotation for marking a C function as suggested to be inlined.<br><br>The default value in the Stub implementation is `inline` |
+| **`SB_C_NOINLINE`**<br><br>The platform's annotation for marking a C function as forcibly not inlined.<br><br>The default value in the Stub implementation is `__attribute__((noinline))` |
+| **`SB_EXPORT_PLATFORM`**<br><br>The platform's annotation for marking a symbol as exported outside of the current shared library.<br><br>The default value in the Stub implementation is <br>`__attribute__((visibility("default")))` |
+| **`SB_IMPORT_PLATFORM`**<br><br>The platform's annotation for marking a symbol as imported from outside of the current linking unit. |
+| **`SB_HAS_QUIRK_COMPILER_SAYS_GNUC_BUT_ISNT`**<br><br>On some platforms the &#95;&#95;GNUC&#95;&#95; is defined even though parts of the functionality are missing. Setting this to non-zero allows disabling missing functionality encountered.<br><br>By default, this property is undefined. |
+| **`SB_HAS_QUIRK_HASFEATURE_NOT_DEFINED_BUT_IT_IS`**<br><br>On some compilers, the frontend has a quirk such that #ifdef cannot correctly detect &#95;&#95;has_feature is defined, and an example error you get is:<br><br>By default, this property is undefined. |
+
+
+## Decoder-only Params
+
+| Properties |
+| :--- |
+| **`SB_MEDIA_BUFFER_ALIGNMENT`**<br><br>Specifies how media buffers must be aligned on this platform as some decoders may have special requirement on the alignment of buffers being decoded.<br><br>The default value in the Stub implementation is `128U` |
+| **`SB_MEDIA_VIDEO_FRAME_ALIGNMENT`**<br><br>Specifies how video frame buffers must be aligned on this platform.<br><br>The default value in the Stub implementation is `256U` |
+| **`SB_MEDIA_MAXIMUM_VIDEO_PREROLL_FRAMES`**<br><br>The encoded video frames are compressed in different ways, so their decoding time can vary a lot.  Occasionally a single frame can take longer time to decode than the average time per frame.  The player has to cache some frames to account for such inconsistency.  The number of frames being cached are controlled by SB_MEDIA_MAXIMUM_VIDEO_PREROLL_FRAMES and SB_MEDIA_MAXIMUM_VIDEO_FRAMES.  Specify the number of video frames to be cached before the playback starts. Note that setting this value too large may increase the playback start delay.<br><br>The default value in the Stub implementation is `4` |
+| **`SB_MEDIA_MAXIMUM_VIDEO_FRAMES`**<br><br>Specify the number of video frames to be cached during playback.  A large value leads to more stable fps but also causes the app to use more memory.<br><br>The default value in the Stub implementation is `12` |
+
+
+## Extensions Configuration
+
+| Properties |
+| :--- |
+| **`SB_HAS_LONG_LONG_HASH`**<br><br>GCC/Clang doesn't define a long long hash function, except for Android and Game consoles.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_HAS_STRING_HASH`**<br><br>GCC/Clang doesn't define a string hash function, except for Game Consoles.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_HAS_HASH_USING`**<br><br>Desktop Linux needs a using statement for the hash functions.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_HAS_HASH_VALUE`**<br><br>Set this to 1 if hash functions for custom types can be defined as a hash_value() function. Otherwise, they need to be placed inside a partially-specified hash struct template with an operator().<br><br>The default value in the Stub implementation is `0` |
+| **`SB_HAS_HASH_WARNING`**<br><br>Set this to 1 if use of hash_map or hash_set causes a deprecation warning (which then breaks the build).<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HASH_MAP_INCLUDE`**<br><br>The location to include hash_map on this platform.<br><br>The default value in the Stub implementation is `<ext/hash_map>` |
+| **`SB_HASH_NAMESPACE`**<br><br>C++'s hash_map and hash_set are often found in different namespaces depending on the compiler.<br><br>The default value in the Stub implementation is `__gnu_cxx` |
+| **`SB_HASH_SET_INCLUDE`**<br><br>The location to include hash_set on this platform.<br><br>The default value in the Stub implementation is `<ext/hash_set>` |
+| **`SB_VA_COPY(dest, source)`**<br><br>Define this to how this platform copies varargs blocks.<br><br>The default value in the Stub implementation is `va_copy(dest, source)` |
+
+
+## Filesystem Configuration
+
+| Properties |
+| :--- |
+| **`SB_FILE_MAX_NAME`**<br><br>The current platform's maximum length of the name of a single directory entry, not including the absolute path.<br><br>The default value in the Stub implementation is `64` |
+| **`SB_FILE_MAX_PATH`**<br><br>The current platform's maximum length of an absolute path.<br><br>The default value in the Stub implementation is `4096` |
+| **`SB_FILE_MAX_OPEN`**<br><br>The current platform's maximum number of files that can be opened at the same time by one process.<br><br>The default value in the Stub implementation is `64` |
+| **`SB_FILE_SEP_CHAR`**<br><br>The current platform's file path component separator character. This is the character that appears after a directory in a file path. For example, the absolute canonical path of the file "/path/to/a/file.txt" uses '/' as a path component separator character.<br><br>The default value in the Stub implementation is `'/'` |
+| **`SB_FILE_ALT_SEP_CHAR`**<br><br>The current platform's alternate file path component separator character. This is like SB_FILE_SEP_CHAR, except if your platform supports an alternate character, then you can place that here. For example, on windows machines, the primary separator character is probably '\', but the alternate is '/'.<br><br>The default value in the Stub implementation is `'/'` |
+| **`SB_PATH_SEP_CHAR`**<br><br>The current platform's search path component separator character. When specifying an ordered list of absolute paths of directories to search for a given reason, this is the character that appears between entries. For example, the search path of "/etc/search/first:/etc/search/second" uses ':' as a search path component separator character.<br><br>The default value in the Stub implementation is `':'` |
+| **`SB_FILE_SEP_STRING`**<br><br>The string form of SB_FILE_SEP_CHAR.<br><br>The default value in the Stub implementation is `"/"` |
+| **`SB_FILE_ALT_SEP_STRING`**<br><br>The string form of SB_FILE_ALT_SEP_CHAR.<br><br>The default value in the Stub implementation is `"/"` |
+| **`SB_PATH_SEP_STRING`**<br><br>The string form of SB_PATH_SEP_CHAR.<br><br>The default value in the Stub implementation is `":"` |
+| **`SB_HAS_QUIRK_FILESYSTEM_COARSE_ACCESS_TIME`**<br><br>On some platforms the file system stores access times at a coarser granularity than other times. When this quirk is defined, we assume the access time is of 1 day precision.<br><br>By default, this property is undefined. |
+
+
+## Graphics Configuration
+
+| Properties |
+| :--- |
+| **`SB_HAS_BLITTER`**<br><br>Specifies whether this platform supports a performant accelerated blitter API. The basic requirement is a scaled, clipped, alpha-blended blit.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_PREFERRED_RGBA_BYTE_ORDER`**<br><br>Specifies the preferred byte order of color channels in a pixel. Refer to starboard/configuration.h for the possible values. EGL/GLES platforms should generally prefer a byte order of RGBA, regardless of endianness.<br><br>The default value in the Stub implementation is <br>`SB_PREFERRED_RGBA_BYTE_ORDER_RGBA` |
+| **`SB_HAS_BILINEAR_FILTERING_SUPPORT`**<br><br>Indicates whether or not the given platform supports bilinear filtering. This can be checked to enable/disable renderer tests that verify that this is working properly.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_NV12_TEXTURE_SUPPORT`**<br><br>Indicates whether or not the given platform supports rendering of NV12 textures. These textures typically originate from video decoders.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER`**<br><br>Whether the current platform should frequently flip its display buffer.  If this is not required (i.e. SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER is set to 0), then optimizations are enabled so the display buffer is not flipped if the scene hasn't changed.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_HAS_VIRTUAL_REALITY`**<br><br>The default value in the Stub implementation is `1` |
+
+
+## Media Configuration
+
+| Properties |
+| :--- |
+| **`SB_HAS_PLAYER`**<br><br>Specifies whether this platform has support for a possibly-decrypting elementary stream player for at least H.264/AAC (and AES-128-CTR, if decrypting). A player is responsible for ingesting an audio and video elementary stream, optionally-encrypted, and ultimately producing synchronized audio/video. If a player is defined, it must choose one of the supported composition methods below.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_QUIRK_SEEK_TO_KEYFRAME`**<br><br>After a seek is triggerred, the default behavior is to append video frames from the last key frame before the seek time and append audio frames from the seek time because usually all audio frames are key frames.  On platforms that cannot decode video frames without displaying them, this will cause the video being played without audio for several seconds after seeking.  When the following macro is defined, the app will append audio frames start from the timestamp that is before the timestamp of the video key frame being appended.<br><br>By default, this property is undefined. |
+| **`SB_HAS_QUIRK_NO_FFS`**<br><br>dlmalloc will use the ffs intrinsic if available.  Platforms on which this is not available should define the following quirk.<br><br>By default, this property is undefined. |
+| **`SB_MEDIA_MAX_AUDIO_BITRATE_IN_BITS_PER_SECOND`**<br><br>The maximum audio bitrate the platform can decode.  The following value equals to 5M bytes per seconds which is more than enough for compressed audio.<br><br>The default value in the Stub implementation is `(40 * 1024 * 1024)` |
+| **`SB_MEDIA_MAX_VIDEO_BITRATE_IN_BITS_PER_SECOND`**<br><br>The maximum video bitrate the platform can decode.  The following value equals to 25M bytes per seconds which is more than enough for compressed video.<br><br>The default value in the Stub implementation is `(200 * 1024 * 1024)` |
+| **`SB_HAS_MEDIA_WEBM_VP9_SUPPORT`**<br><br>Specifies whether this platform has webm/vp9 support.  This should be set to non-zero on platforms with webm/vp9 support.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_MEDIA_THREAD_STACK_SIZE`**<br><br>Specifies the stack size for threads created inside media stack.  Set to 0 to use the default thread stack size.  Set to non-zero to explicitly set the stack size for media stack threads.<br><br>The default value in the Stub implementation is `0U` |
+
+
+## Memory Configuration
+
+| Properties |
+| :--- |
+| **`SB_MEMORY_PAGE_SIZE`**<br><br>The memory page size, which controls the size of chunks on memory that allocators deal with, and the alignment of those chunks. This doesn't have to be the hardware-defined physical page size, but it should be a multiple of it.<br><br>The default value in the Stub implementation is `4096` |
+| **`SB_HAS_MMAP`**<br><br>Whether this platform has and should use an MMAP function to map physical memory to the virtual address space.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_CAN_MAP_EXECUTABLE_MEMORY`**<br><br>Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is required for platforms that want to JIT.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_VIRTUAL_REGIONS`**<br><br>Whether this platform has and should use an growable heap (e.g. with sbrk()) to map physical memory to the virtual address space.<br><br>The default value in the Stub implementation is `0` |
+| **`SB_NETWORK_IO_BUFFER_ALIGNMENT`**<br><br>Specifies the alignment for IO Buffers, in bytes. Some low-level network APIs may require buffers to have a specific alignment, and this is the place to specify that.<br><br>The default value in the Stub implementation is `16` |
+| **`SB_MALLOC_ALIGNMENT`**<br><br>Determines the alignment that allocations should have on this platform.<br><br>The default value in the Stub implementation is `((size_t)16U)` |
+| **`SB_DEFAULT_MMAP_THRESHOLD`**<br><br>Determines the threshhold of allocation size that should be done with mmap (if available), rather than allocated within the core heap.<br><br>The default value in the Stub implementation is `((size_t)(256 * 1024U))` |
+| **`SB_MEMORY_LOG_PATH`**<br><br>Defines the path where memory debugging logs should be written to.<br><br>The default value in the Stub implementation is `"/tmp/starboard"` |
+
+
+## Network Configuration
+
+| Properties |
+| :--- |
+| **`SB_HAS_IPV6`**<br><br>Specifies whether this platform supports IPV6.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_PIPE`**<br><br>Specifies whether this platform supports pipe.<br><br>The default value in the Stub implementation is `1` |
+
+
+## System Header Configuration
+
+ Any system headers listed here that are not provided by the platform will be emulated in starboard/types.h.
+
+| Properties |
+| :--- |
+| **`SB_HAS_STDARG_H`**<br><br> Whether the current platform provides the standard header stdarg.h.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_STDBOOL_H`**<br><br>Whether the current platform provides the standard header stdbool.h.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_STDDEF_H`**<br><br>Whether the current platform provides the standard header stddef.h.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_STDINT_H`**<br><br>Whether the current platform provides the standard header stdint.h.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_INTTYPES_H`**<br><br>Whether the current platform provides the standard header inttypes.h.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_WCHAR_H`**<br><br>Whether the current platform provides the standard header wchar.h.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_LIMITS_H`**<br><br>Whether the current platform provides the standard header limits.h.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_FLOAT_H`**<br><br>Whether the current platform provides the standard header float.h.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_SSIZE_T`**<br><br>Whether the current platform provides ssize_t.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_MICROPHONE`**<br><br>Whether the current platform has microphone supported.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_SPEECH_RECOGNIZER`**<br><br>Whether the current platform has speech recognizer.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_SPEECH_SYNTHESIS`**<br><br>Whether the current platform has speech synthesis.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_IS_WCHAR_T_UTF32`**<br><br>Type detection for wchar_t.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_IS_WCHAR_T_UTF16`**<br><br>The default value in the Stub implementation is `1` |
+| **`SB_IS_WCHAR_T_UNSIGNED`**<br><br>Chrome only defines these two if ARMEL or MIPSEL are defined. Chrome has an exclusion for iOS here, we should too when we support iOS.<br><br>The default value in the Stub implementation is `1` |
+| **`SB_IS_WCHAR_T_SIGNED`**<br><br>The default value in the Stub implementation is `1` |
+| **`SB_HAS_QUIRK_MEMSET_IN_SYSTEM_HEADERS`**<br><br>Some platforms have memset predefined in system headers. Platforms where this is the case should define the following quirk.<br><br>By default, this property is undefined. |
+| **`SB_HAS_QUIRK_SOCKET_BSD_HEADERS`**<br><br>This quirk is used to switch the headers included in starboard/shared/linux/socket_get_interface_address.cc for darwin system headers. It may be removed at some point in favor of a different solution.<br><br>By default, this property is undefined. |
+
+
+## Thread Configuration
+
+| Properties |
+| :--- |
+| **`SB_MAX_THREADS`**<br><br>Defines the maximum number of simultaneous threads for this platform. Some platforms require sharing thread handles with other kinds of system handles, like mutexes, so we want to keep this managable.<br><br>The default value in the Stub implementation is `90` |
+| **`SB_MAX_THREAD_LOCAL_KEYS`**<br><br>The maximum number of thread local storage keys supported by this platform.<br><br>The default value in the Stub implementation is `512` |
+| **`SB_MAX_THREAD_NAME_LENGTH`**<br><br>The maximum length of the name for a thread, including the NULL-terminator.<br><br>The default value in the Stub implementation is `16;` |
+
+
+## Timing API
+
+| Properties |
+| :--- |
+| **`SB_HAS_TIME_THREAD_NOW`**<br><br>Whether this platform has an API to retrieve how long the current thread has spent in the executing state.<br><br>The default value in the Stub implementation is `1` |
+
+
+## Tuneable Parameters
+
+| Properties |
+| :--- |
+| **`SB_NETWORK_RECEIVE_BUFFER_SIZE`**<br><br>Specifies the network receive buffer size in bytes, set via SbSocketSetReceiveBufferSize().  Setting this to 0 indicates that SbSocketSetReceiveBufferSize() should not be called. Use this for OSs (such as Linux) where receive buffer auto-tuning is better.  On some platforms, this may affect max TCP window size which may dramatically affect throughput in the presence of latency.  If your platform does not have a good TCP auto-tuning mechanism, a setting of (128 * 1024) here is recommended.<br><br>The default value in the Stub implementation is `(0)` |
+
+
+## User Configuration
+
+| Properties |
+| :--- |
+| **`SB_USER_MAX_SIGNED_IN`**<br><br>The maximum number of users that can be signed in at the same time.<br><br>The default value in the Stub implementation is `1` |
+
+
diff --git a/src/cobalt/site/docs/reference/starboard/gyp-configuration.md b/src/cobalt/site/docs/reference/starboard/gyp-configuration.md
new file mode 100644
index 0000000..529fd31
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/gyp-configuration.md
@@ -0,0 +1,91 @@
+---
+layout: doc
+title: "Starboard: gyp_configuration Reference Guide"
+---
+
+| Variables |
+| :--- |
+| **`abort_on_allocation_failure`**<br><br> Halt execution on failure to allocate memory.<br><br>The default value is `1`. |
+| **`cobalt`**<br><br> Whether Cobalt is being built.<br><br>The default value is `1`. |
+| **`cobalt_config`**<br><br> Contains the current build configuration.<br><br>The default value is `'gold'`. |
+| **`cobalt_egl_swap_interval`**<br><br> Cobalt will call eglSwapInterval() and specify this value before calling eglSwapBuffers() each frame.<br><br>The default value is `1`. |
+| **`cobalt_enable_jit`**<br><br> Disable JIT and run in interpreter-only mode by default. It can be set to 1 to run in JIT mode.  For SpiderMonkey in particular, we have found that disabling JIT often results in faster JavaScript execution and lower memory usage. Setting this to 1 on a platform or engine for which there is no JIT implementation is a no-op. Setting this to 0 on an engine for which there is a JIT implementation is a platform configuration error.<br><br>The default value is `0`. |
+| **`cobalt_enable_lib`**<br><br> Enables embedding Cobalt as a shared library within another app. This requires a 'lib' starboard implementation for the corresponding platform.<br><br>The default value is `'<(sb_enable_lib)'`. |
+| **`cobalt_encrypted_media_extension_enable_key_statuses_update`**<br><br> 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.<br><br>The default value is `1`. |
+| **`cobalt_fastbuild`**<br><br> Contains the current build configuration.<br><br>The default value is `0`. |
+| **`cobalt_font_package`**<br><br> Contains the current font package selection.  This can be used to trade font quality, coverage, and latency for different font package sizes. The font package can be one of the following options:<ul><li><code>expanded</code> - The largest package. It includes everything in the 'standard' package, along with 'bold' weight CJK. It is recommended that 'local_font_cache_size_in_bytes' be increased to 24MB when using this package to account for the extra memory required by bold CJK. This package is ~48.7MB.<li><code>standard</code> - The default package. It includes all sans-serif, serif, and FCC fonts, non-CJK fallback fonts in both 'normal' and 'bold' weights, and 'normal' weight CJK ('bold' weight CJK is synthesized from it). This package is ~29.4MB.<li><code>limited_with_jp</code> - A significantly smaller package than 'standard'. This package removes all but 'normal' and 'bold' weighted sans-serif and serif, removes the FCC fonts (which must be provided by the system or downloaded from the web), removes the 'bold' weighted non-CJK fallback fonts (the 'normal' weight is still included and is used to synthesize bold), and replaces standard CJK with low quality CJK. However, higher quality Japanese is still included. Because low quality CJK cannot synthesize bold, bold glyphs are unavailable in Chinese and Korean. This package is ~10.9MB.<li><code>limited</code> - A smaller package than 'limited_with_jp'. The two packages are identical with the exception that 'limited' does not include the higher quality Japanese font; instead it relies on low quality CJK for all CJK characters. Because low quality CJK cannot synthesize bold, bold glyphs are unavailable in Chinese, Japanese, and Korean. This package is ~7.7MB.<li><code>minimal</code> - The smallest possible font package. It only includes Roboto's Basic Latin characters. Everything else must be provided by the system or downloaded from the web. This package is ~16.4KB.</li></ul> NOTE: When bold is needed, but unavailable, it is typically synthesized, resulting in lower quality glyphs than those generated directly from a bold font. However, this does not occur with low quality CJK, which is not high enough quality to synthesize. Its glyphs always have a 'normal' weight.<br><br>The default value is `'standard'`. |
+| **`cobalt_font_package_override_fallback_emoji`**<br><br> Font package overrides can be used to modify the files included within the selected package. The following values are available: -1 -- The package value for the specified category is not overridden. 0 -- The package value is overridden and no fonts for the specified category are included. 1 -- The package value is overridden and fonts from the specified category with a weight of 'normal' and a style of 'normal' are included. 2 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or bold' and a style of 'normal' are included. 3 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or 'bold' and a style of either 'normal' or 'italic' are included. 4 -- The package value is overridden and all available fonts from the specified category are included. This may include additional weights beyond 'normal' and 'bold'. See content/fonts/README.md for details on the specific values used by each of the packages use for the various font categories.<br><br>The default value is `-1`. |
+| **`cobalt_font_package_override_fallback_lang_cjk`**<br><br> Font package overrides can be used to modify the files included within the selected package. The following values are available: -1 -- The package value for the specified category is not overridden. 0 -- The package value is overridden and no fonts for the specified category are included. 1 -- The package value is overridden and fonts from the specified category with a weight of 'normal' and a style of 'normal' are included. 2 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or bold' and a style of 'normal' are included. 3 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or 'bold' and a style of either 'normal' or 'italic' are included. 4 -- The package value is overridden and all available fonts from the specified category are included. This may include additional weights beyond 'normal' and 'bold'. See content/fonts/README.md for details on the specific values used by each of the packages use for the various font categories.<br><br>The default value is `-1`. |
+| **`cobalt_font_package_override_fallback_lang_cjk_low_quality`**<br><br> Font package overrides can be used to modify the files included within the selected package. The following values are available: -1 -- The package value for the specified category is not overridden. 0 -- The package value is overridden and no fonts for the specified category are included. 1 -- The package value is overridden and fonts from the specified category with a weight of 'normal' and a style of 'normal' are included. 2 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or bold' and a style of 'normal' are included. 3 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or 'bold' and a style of either 'normal' or 'italic' are included. 4 -- The package value is overridden and all available fonts from the specified category are included. This may include additional weights beyond 'normal' and 'bold'. See content/fonts/README.md for details on the specific values used by each of the packages use for the various font categories.<br><br>The default value is `-1`. |
+| **`cobalt_font_package_override_fallback_lang_jp`**<br><br> Font package overrides can be used to modify the files included within the selected package. The following values are available: -1 -- The package value for the specified category is not overridden. 0 -- The package value is overridden and no fonts for the specified category are included. 1 -- The package value is overridden and fonts from the specified category with a weight of 'normal' and a style of 'normal' are included. 2 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or bold' and a style of 'normal' are included. 3 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or 'bold' and a style of either 'normal' or 'italic' are included. 4 -- The package value is overridden and all available fonts from the specified category are included. This may include additional weights beyond 'normal' and 'bold'. See content/fonts/README.md for details on the specific values used by each of the packages use for the various font categories.<br><br>The default value is `-1`. |
+| **`cobalt_font_package_override_fallback_lang_non_cjk`**<br><br> Font package overrides can be used to modify the files included within the selected package. The following values are available: -1 -- The package value for the specified category is not overridden. 0 -- The package value is overridden and no fonts for the specified category are included. 1 -- The package value is overridden and fonts from the specified category with a weight of 'normal' and a style of 'normal' are included. 2 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or bold' and a style of 'normal' are included. 3 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or 'bold' and a style of either 'normal' or 'italic' are included. 4 -- The package value is overridden and all available fonts from the specified category are included. This may include additional weights beyond 'normal' and 'bold'. See content/fonts/README.md for details on the specific values used by each of the packages use for the various font categories.<br><br>The default value is `-1`. |
+| **`cobalt_font_package_override_fallback_symbols`**<br><br> Font package overrides can be used to modify the files included within the selected package. The following values are available: -1 -- The package value for the specified category is not overridden. 0 -- The package value is overridden and no fonts for the specified category are included. 1 -- The package value is overridden and fonts from the specified category with a weight of 'normal' and a style of 'normal' are included. 2 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or bold' and a style of 'normal' are included. 3 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or 'bold' and a style of either 'normal' or 'italic' are included. 4 -- The package value is overridden and all available fonts from the specified category are included. This may include additional weights beyond 'normal' and 'bold'. See content/fonts/README.md for details on the specific values used by each of the packages use for the various font categories.<br><br>The default value is `-1`. |
+| **`cobalt_font_package_override_named_fcc_fonts`**<br><br> Font package overrides can be used to modify the files included within the selected package. The following values are available: -1 -- The package value for the specified category is not overridden. 0 -- The package value is overridden and no fonts for the specified category are included. 1 -- The package value is overridden and fonts from the specified category with a weight of 'normal' and a style of 'normal' are included. 2 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or bold' and a style of 'normal' are included. 3 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or 'bold' and a style of either 'normal' or 'italic' are included. 4 -- The package value is overridden and all available fonts from the specified category are included. This may include additional weights beyond 'normal' and 'bold'. See content/fonts/README.md for details on the specific values used by each of the packages use for the various font categories.<br><br>The default value is `-1`. |
+| **`cobalt_font_package_override_named_sans_serif`**<br><br> Font package overrides can be used to modify the files included within the selected package. The following values are available: -1 -- The package value for the specified category is not overridden. 0 -- The package value is overridden and no fonts for the specified category are included. 1 -- The package value is overridden and fonts from the specified category with a weight of 'normal' and a style of 'normal' are included. 2 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or bold' and a style of 'normal' are included. 3 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or 'bold' and a style of either 'normal' or 'italic' are included. 4 -- The package value is overridden and all available fonts from the specified category are included. This may include additional weights beyond 'normal' and 'bold'. See content/fonts/README.md for details on the specific values used by each of the packages use for the various font categories.<br><br>The default value is `-1`. |
+| **`cobalt_font_package_override_named_serif`**<br><br> Font package overrides can be used to modify the files included within the selected package. The following values are available: -1 -- The package value for the specified category is not overridden. 0 -- The package value is overridden and no fonts for the specified category are included. 1 -- The package value is overridden and fonts from the specified category with a weight of 'normal' and a style of 'normal' are included. 2 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or bold' and a style of 'normal' are included. 3 -- The package value is overridden and fonts from the specified category with a weight of either 'normal' or 'bold' and a style of either 'normal' or 'italic' are included. 4 -- The package value is overridden and all available fonts from the specified category are included. This may include additional weights beyond 'normal' and 'bold'. See content/fonts/README.md for details on the specific values used by each of the packages use for the various font categories.<br><br>The default value is `-1`. |
+| **`cobalt_gc_zeal`**<br><br> Can be set to enable zealous garbage collection, if |javascript_engine| supports it.  Zealous garbage collection will cause garbage collection to occur much more frequently than normal, for the purpose of finding or reproducing bugs.<br><br>The default value is `0`. |
+| **`cobalt_media_buffer_alignment`**<br><br> The media buffer will be allocated using the following alignment.  Set this to a larger value may increase the memory consumption of media buffers.<br><br>The default value is `0`. |
+| **`cobalt_media_buffer_allocation_unit`**<br><br> When the media stack needs more memory to store media buffers, it will allocate extra memory in units of |cobalt_media_buffer_allocation_unit|. This can be set to 0, in which case the media stack will allocate extra memory on demand.  When |cobalt_media_buffer_initial_capacity| and this value are both set to 0, the media stack will allocate individual buffers directly using SbMemory functions.<br><br>The default value is `1 * 1024 * 1024`. |
+| **`cobalt_media_buffer_initial_capacity`**<br><br> The amount of memory that will be used to store media buffers allocated during system startup.  To allocate a large chunk at startup helps with reducing fragmentation and can avoid failures to allocate incrementally. This can be set to 0.<br><br>The default value is `21 * 1024 * 1024`. |
+| **`cobalt_media_buffer_non_video_budget`**<br><br> Specifies the maximum amount of memory used by audio or text buffers of media source before triggering a garbage collection.  A large value will cause more memory being used by audio buffers but will also make JavaScript app less likely to re-download audio data.  Note that the JavaScript app may experience significant difficulty if this value is too low.<br><br>The default value is `5 * 1024 * 1024`. |
+| **`cobalt_media_buffer_padding`**<br><br> Extra bytes allocated at the end of a media buffer to ensure that the buffer can be use optimally by specific instructions like SIMD.  Set to 0 to remove any padding.<br><br>The default value is `0`. |
+| **`cobalt_media_buffer_pool_allocate_on_demand`**<br><br> When either |cobalt_media_buffer_initial_capacity| or |cobalt_media_buffer_allocation_unit| isn't zero, media buffers will be allocated using a memory pool.  Set the following variable to 1 to allocate the media buffer pool memory on demand and return all memory to the system when there is no media buffer allocated.  Setting the following value to 0 results in that Cobalt will allocate |cobalt_media_buffer_initial_capacity| bytes for media buffer on startup and will not release any media buffer memory back to the system even if there is no media buffers allocated.<br><br>The default value is `1`. |
+| **`cobalt_media_buffer_progressive_budget`**<br><br> The memory used when playing mp4 videos that is not in DASH format.  The resolution of such videos shouldn't go beyond 1080p.  Its value should be less than the sum of 'cobalt_media_buffer_non_video_budget' and 'cobalt_media_buffer_video_budget_1080p' but not less than 8 MB.<br><br>The default value is `12 * 1024 * 1024`. |
+| **`cobalt_media_buffer_storage_type`**<br><br> This can be set to "memory" or "file".  When it is set to "memory", the media buffers will be stored in main memory allocated by SbMemory functions.  When it is set to "file", the media buffers will be stored in a temporary file in the system cache folder acquired by calling SbSystemGetPath() with "kSbSystemPathCacheDirectory".  Note that when its value is "file" the media stack will still allocate memory to cache the the buffers in use.<br><br>The default value is `'memory'`. |
+| **`cobalt_media_buffer_video_budget_1080p`**<br><br> Specifies the maximum amount of memory used by video buffers of media source before triggering a garbage collection when the video resolution is lower than 1080p (1920x1080).  A large value will cause more memory being used by video buffers but will also make JavaScript app less likely to re-download video data.  Note that the JavaScript app may experience significant difficulty if this value is too low.<br><br>The default value is `16 * 1024 * 1024`. |
+| **`cobalt_media_buffer_video_budget_4k`**<br><br> Specifies the maximum amount of memory used by video buffers of media source before triggering a garbage collection when the video resolution is lower than 4k (3840x2160).  A large value will cause more memory being used by video buffers but will also make JavaScript app less likely to re-download video data.  Note that the JavaScript app may experience significant difficulty if this value is too low.<br><br>The default value is `60 * 1024 * 1024`. |
+| **`cobalt_media_source_2016`**<br><br> Use media source extension implementation that is conformed to the Candidate Recommandation of July 5th 2016.<br><br>The default value is `1`. |
+| **`cobalt_minimum_frame_time_in_milliseconds`**<br><br> Allow throttling of the frame rate. This is expressed in terms of milliseconds and can be a floating point number. Keep in mind that swapping frames may take some additional processing time, so it may be better to specify a lower delay. For example, '33' instead of '33.33' for 30 Hz refresh.<br><br>The default value is `'16.4'`. |
+| **`cobalt_platform_dependencies`**<br><br> List of platform-specific targets that get compiled into cobalt.<br><br>The default value is `[]`. |
+| **`cobalt_user_on_exit_strategy`**<br><br> This variable defines what Cobalt's preferred strategy should be for handling internally triggered application exit requests (e.g. the user chooses to back out of the application).<ul><li><code>stop</code> - The application should call SbSystemRequestStop() on exit, resulting in a complete shutdown of the application.<li><code>suspend</code> - The application should call SbSystemRequestSuspend() on exit, resulting in the application being "minimized".<li><code>noexit</code> - The application should never allow the user to trigger an exit, this will be managed by the system.<br><br>The default value is `'stop'`. |
+| **`cobalt_version`**<br><br> Build version number.<br><br>The default value is `0`. |
+| **`cobalt_webapi_extension_generated_header_idl_files`**<br><br>The default value is `[]`. |
+| **`cobalt_webapi_extension_source_idl_files`**<br><br>The default value is `[]`. |
+| **`compiler_flags_<config>`**<br><br>The following configurations are supported: <ul><li><code>[default]</code></li><li><code>c_debug</code></li><li><code>c_devel</code></li><li><code>c_gold</code></li><li><code>c_host</code></li><li><code>c_qa</code></li><li><code>cc_debug</code></li><li><code>cc_devel</code></li><li><code>cc_gold</code></li><li><code>cc_host</code></li><li><code>cc_qa</code></li><li><code>debug</code></li><li><code>devel</code></li><li><code>gold</code></li><li><code>host</code></li><li><code>qa</ul> |
+| **`custom_media_session_client`**<br><br> Set to 1 to enable a custom MediaSessionClient.<br><br>The default value is `0`. |
+| **`default_javascript_engine`**<br><br> The only currently-supported Javascript engine is 'mozjs-45'.<br><br>The default value is `'mozjs-45'`. |
+| **`default_renderer_options_dependency`**<br><br> Override this value to adjust the default rasterizer setting for your platform.<br><br>The default value is `'<(DEPTH)/cobalt/renderer/default_options_starboard.gyp:default_options'`. |
+| **`enable_account_manager`**<br><br> Set to 1 to enable H5vccAccountManager.<br><br>The default value is `0`. |
+| **`enable_crash_log`**<br><br> Set to 1 to enable H5vccCrashLog.<br><br>The default value is `0`. |
+| **`enable_map_to_mesh`**<br><br> Enable support for the map to mesh filter, which is primarily used to implement spherical video playback.<br><br>The default value is `0`. |
+| **`enable_spdy`**<br><br> Set to 1 to compile with SPDY support.<br><br>The default value is `0`. |
+| **`enable_sso`**<br><br> Set to 1 to enable H5vccSSO (Single Sign On).<br><br>The default value is `0`. |
+| **`enable_xhr_header_filtering`**<br><br> Set to 1 to enable filtering of HTTP headers before sending.<br><br>The default value is `0`. |
+| **`fallback_splash_screen_url`**<br><br> The URL of default build time splash screen - see cobalt/doc/splash_screen.md for information about this.<br><br>The default value is `'none'`. |
+| **`final_executable_type`**<br><br> The variables allow changing the target type on platforms where the native code may require an additional packaging step (ex. Android).<br><br>The default value is `'executable'`. |
+| **`gl_type`**<br><br> The source of EGL and GLES headers and libraries. Valid values (case and everything sensitive!):<ul><li><code>none</code> - No EGL + GLES implementation is available on this platform.<li><code>system_gles3</code> - Use the system implementation of EGL + GLES3. The headers and libraries must be on the system include and link paths.<li><code>system_gles2</code> - Use the system implementation of EGL + GLES2. The headers and libraries must be on the system include and link paths.<li><code>glimp</code> - Cobalt's own EGL + GLES2 implementation. This requires a valid Glimp implementation for the platform.<li><code>angle</code> - A DirectX-to-OpenGL adaptation layer. This requires a valid ANGLE implementation for the platform.</li></ul> Choosing an unsupported value will result in a GYP error: "cobalt/renderer/egl_and_gles/egl_and_gles_<gl_type>.gyp not found"<br><br>The default value is `'system_gles2'`. |
+| **`gtest_target_type`**<br><br> The variables allow changing the target type on platforms where the native code may require an additional packaging step (ex. Android).<br><br>The default value is `'executable'`. |
+| **`host_os`**<br><br> Contains the name of the hosting OS. The value is defined by gyp_cobalt.<br><br>The default value is `'win'`. |
+| **`image_cache_capacity_multiplier_when_playing_video`**<br><br> Modifying this value to be non-1.0f will result in the image cache capacity being cleared and then temporarily reduced for the duration that a video is playing.  This can be useful for some platforms if they are particularly constrained for (GPU) memory during video playback.  When playing a video, the image cache is reduced to: image_cache_size_in_bytes * image_cache_capacity_multiplier_when_playing_video.<br><br>The default value is `'1.0f'`. |
+| **`image_cache_size_in_bytes`**<br><br> Determines the capacity of the image cache, which manages image surfaces downloaded from a web page.  While it depends on the platform, often (and ideally) these images are cached within GPU memory. Set to -1 to automatically calculate the value at runtime, based on features like windows dimensions and the value of SbSystemGetTotalGPUMemory().<br><br>The default value is `-1`. |
+| **`in_app_dial`**<br><br> Set to 1 to build with DIAL support.<br><br>The default value is `0`. |
+| **`javascript_engine`**<br><br> The only currently-supported Javascript engine is 'mozjs-45'.<br><br>The default value is `'<(default_javascript_engine)'`. |
+| **`linker_flags_<config>`**<br><br>The following configurations are supported: <ul><li><code>[default]</code></li><li><code>debug</code></li><li><code>devel</code></li><li><code>gold</code></li><li><code>host</code></li><li><code>qa</ul> |
+| **`local_font_cache_size_in_bytes`**<br><br> Determines the capacity of the local font cache, which manages all fonts loaded from local files. Newly encountered sections of font files are lazily loaded into the cache, enabling subsequent requests to the same file sections to be handled via direct memory access. Once the limit is reached, further requests are handled via file stream. Setting the value to 0 disables memory caching and causes all font file accesses to be done using file streams.<br><br>The default value is `16 * 1024 * 1024`. |
+| **`max_cobalt_cpu_usage`**<br><br> Max Cobalt CPU usage specifies that the cobalt program should keep it's size below the specified size. A value of -1 causes this value to be assumed from the starboard API function: SbSystemGetTotalCPUMemory().<br><br>The default value is `-1`. |
+| **`max_cobalt_gpu_usage`**<br><br> Max Cobalt GPU usage specifies that the cobalt program should keep it's size below the specified size. A value of -1 causes this value to be assumed from the starboard API function: SbSystemGetTotalGPUMemory().<br><br>The default value is `-1`. |
+| **`mesh_cache_size_in_bytes`**<br><br> Determines the capacity of the mesh cache. Each mesh is held compressed in main memory, to be inflated into a GPU buffer when needed for projection. When set to 'auto', will be adjusted according to whether the enable_map_to_mesh is true or not.  If enable_map_to_mesh is false, then the mesh cache size will be set to 0.<br><br>The default value is `'auto'`. |
+| **`mozjs_garbage_collection_threshold_in_bytes`**<br><br> Determines the size of garbage collection threshold. After this many bytes have been allocated, the SpiderMonkey garbage collector will run. Lowering this has been found to reduce performance and decrease JavaScript memory usage. For example, we have measured on at least one platform that performance becomes 7% worse on average in certain cases when adjusting this number from 8MB to 1MB.<br><br>The default value is `8 * 1024 * 1024`. |
+| **`offscreen_target_cache_size_in_bytes`**<br><br> Determines the amount of GPU memory the offscreen target atlases will use. This is specific to the direct-GLES rasterizer and serves a similar purpose as the surface_cache_size_in_bytes, but caches any render tree nodes which require skia for rendering. Two atlases will be allocated from this memory or multiple atlases of the frame size if the limit allows. It is recommended that enough memory be reserved for two RGBA atlases about a quarter of the frame size.<br><br>The default value is `-1`. |
+| **`platform_libraries`**<br><br>The default value is `[]`. |
+| **`rasterizer_type`**<br><br> Defines what kind of rasterizer will be used.  This can be adjusted to force a stub graphics implementation or software graphics implementation. It can be one of the following options:<ul><li><code>direct-gles</code> - Uses a light wrapper over OpenGL ES to handle most draw elements. This will fall back to the skia hardware rasterizer for some render tree node types, but is generally faster on the CPU and GPU. This can handle 360 rendering.<li><code>hardware</code> - As much hardware acceleration of graphics commands as possible. This uses skia to wrap OpenGL ES commands. Required for 360 rendering.<li><code>software</code> - Perform most rasterization using the CPU and only interact with the GPU to send the final image to the output window.<li><code>stub</code> - Stub graphics rasterization.  A rasterizer object will still be available and valid, but it will do nothing.<br><br>The default value is `'direct-gles'`. |
+| **`reduce_cpu_memory_by`**<br><br> When specified this value will reduce the cpu memory consumption by the specified amount. -1 disables the value. When this value is specified then max_cobalt_cpu_usage will not be used in memory_constrainer, but will still be used for triggering a warning if the engine consumes more memory than this value specifies.<br><br>The default value is `-1`. |
+| **`reduce_gpu_memory_by`**<br><br> When specified this value will reduce the gpu memory consumption by the specified amount. -1 disables the value. When this value is specified then max_cobalt_gpu_usage will not be used in memory_constrainer, but will still be used for triggering a warning if the engine consumes more memory than this value specifies.<br><br>The default value is `-1`. |
+| **`remote_font_cache_size_in_bytes`**<br><br> Determines the capacity of the remote font cache, which manages all fonts downloaded from a web page.<br><br>The default value is `4 * 1024 * 1024`. |
+| **`render_dirty_region_only`**<br><br> If set to 1, will enable support for rendering only the regions of the display that are modified due to animations, instead of re-rendering the entire scene each frame.  This feature can reduce startup time where usually there is a small loading spinner animating on the screen.  On GLES renderers, Cobalt will attempt to implement this support by using eglSurfaceAttrib(..., EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED), otherwise the dirty region will be silently disabled.  On Blitter API platforms, if this is enabled, we explicitly create an extra offscreen full-size intermediate surface to render into.  Note that some GLES driver implementations may internally allocate an extra full screen surface to support this feature, and many have been noticed to not properly support this functionality (but they report that they do), and for these reasons this value is defaulted to 0.<br><br>The default value is `0`. |
+| **`sb_enable_lib`**<br><br> Enables embedding Cobalt as a shared library within another app. This requires a 'lib' starboard implementation for the corresponding platform.<br><br>The default value is `'<(sb_enable_lib)'`. |
+| **`sb_libevent_method`**<br><br> The event polling mechanism available on this platform to support libevent. Platforms may redefine to 'poll' if necessary. Other mechanisms, e.g. devpoll, kqueue, select, are not yet supported.<br><br>The default value is `'epoll'`. |
+| **`sb_media_platform`**<br><br> Used by cobalt/media/media.gyp to pick a proper media platform.<br><br>The default value is `'starboard'`. |
+| **`sb_pedantic_warnings`**<br><br> Enabling this variable enables pedantic levels of warnings for the current toolchain.<br><br>The default value is `0`. |
+| **`sb_static_contents_output_base_dir`**<br><br> Directory path to static contents.<br><br>The default value is `'<(PRODUCT_DIR)/content'`. |
+| **`sb_static_contents_output_data_dir`**<br><br> Directory path to static contents' data.<br><br>The default value is `'<(PRODUCT_DIR)/content/data'`. |
+| **`sb_target_platform`**<br><br> The target platform id as a string, like 'ps3', 'ps4', etc..<br><br>The default value is `''`. |
+| **`scratch_surface_cache_size_in_bytes`**<br><br> 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 Skia rasterizer.<br><br>The default value is `0`. |
+| **`skia_cache_size_in_bytes`**<br><br> Determines the capacity of the skia cache.  The Skia cache is maintained within Skia and is used to cache the results of complicated effects such as shadows, so that Skia draw calls that are used repeatedly across frames can be cached into surfaces.  This setting is only relevant when using the hardware-accelerated Skia rasterizer (e.g. as opposed to the Blitter API).<br><br>The default value is `4 * 1024 * 1024`. |
+| **`skia_glyph_atlas_height`**<br><br> Determines the size in pixels of the glyph atlas where rendered glyphs are cached. The resulting memory usage is 2 bytes of GPU memory per pixel. When a value is used that is too small, thrashing may occur that will result in visible stutter. Such thrashing is more likely to occur when CJK language glyphs are rendered and when the size of the glyphs in pixels is larger, such as for higher resolution displays. The negative default values indicates to the engine that these settings should be automatically set.<br><br>The default value is `'-1'`. |
+| **`skia_glyph_atlas_width`**<br><br> Determines the size in pixels of the glyph atlas where rendered glyphs are cached. The resulting memory usage is 2 bytes of GPU memory per pixel. When a value is used that is too small, thrashing may occur that will result in visible stutter. Such thrashing is more likely to occur when CJK language glyphs are rendered and when the size of the glyphs in pixels is larger, such as for higher resolution displays. The negative default values indicates to the engine that these settings should be automatically set.<br><br>The default value is `'-1'`. |
+| **`software_surface_cache_size_in_bytes`**<br><br> Only relevant if you are using the Blitter API. Determines the capacity of the software surface cache, which is used to cache all surfaces that are rendered via a software rasterizer to avoid re-rendering them.<br><br>The default value is `8 * 1024 * 1024`. |
+| **`starboard_path`**<br><br> The relative path from src/ to the directory containing the starboard_platform.gyp file.  It is currently set to 'starboard/<(target_arch)' to make semi-starboard platforms work. moved to starboard.<br><br>The default value is `'starboard/<(target_arch)'`. |
+| **`surface_cache_size_in_bytes`**<br><br> Determines the capacity of the surface cache.  The surface cache tracks which render tree nodes are being re-used across frames and stores the nodes that are most CPU-expensive to render into surfaces.<br><br>The default value is `0`. |
+| **`target_os`**<br><br> The operating system of the target, separate from the target_arch. In many cases, an 'unknown' value is fine, but, if set to 'linux', then we can assume some things, and it'll save us some configuration time.<br><br>The default value is `'unknown'`. |
+| **`tizen_os`**<br><br> Temporary indicator for Tizen - should eventually move to feature defines.<br><br>The default value is `0`. |
diff --git a/src/cobalt/site/docs/reference/starboard/modules/accessibility.md b/src/cobalt/site/docs/reference/starboard/modules/accessibility.md
new file mode 100644
index 0000000..b5f6734
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/accessibility.md
@@ -0,0 +1,151 @@
+---
+layout: doc
+title: "Starboard Module Reference: accessibility.h"
+---
+
+Provides access to the system options and settings related to accessibility.
+
+## Structs
+
+### SbAccessibilityDisplaySettings
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>bool</code><br>        <code>has_high_contrast_text_setting</code></td>    <td>Whether this platform has a system setting for high contrast text or not.</td>  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>is_high_contrast_text_enabled</code></td>    <td>Whether the high contrast text setting is enabled or not.</td>  </tr>
+</table>
+
+### SbAccessibilityTextToSpeechSettings
+
+A group of settings related to text-to-speech functionality, for platforms
+that expose system settings for text-to-speech.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>bool</code><br>        <code>has_text_to_speech_setting</code></td>    <td>Whether this platform has a system setting for text-to-speech or not.</td>  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>is_text_to_speech_enabled</code></td>    <td>Whether the text-to-speech setting is enabled or not. This setting is only
+valid if <code>has_text_to_speech_setting</code> is set to true.</td>  </tr>
+</table>
+
+## Functions
+
+### SbAccessibilityGetDisplaySettings
+
+**Description**
+
+Get the platform settings related to high contrast text.
+This function returns false if `out_settings` is NULL or if it is
+not zero-initialized.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbAccessibilityGetDisplaySettings-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbAccessibilityGetDisplaySettings-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbAccessibilityGetDisplaySettings-declaration">
+<pre>
+SB_EXPORT bool SbAccessibilityGetDisplaySettings(
+    SbAccessibilityDisplaySettings* out_settings);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbAccessibilityGetDisplaySettings-stub">
+
+```
+#include "starboard/accessibility.h"
+
+#include "starboard/memory.h"
+
+bool SbAccessibilityGetDisplaySettings(
+    SbAccessibilityDisplaySettings* out_setting) {
+  if (!out_setting ||
+      !SbMemoryIsZero(out_setting,
+                      sizeof(SbAccessibilityDisplaySettings))) {
+    return false;
+  }
+  out_setting->has_high_contrast_text_setting = false;
+  return true;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbAccessibilityDisplaySettings*</code><br>        <code>out_settings</code></td>
+    <td>A pointer to a zero-initialized
+SbAccessibilityDisplaySettings* struct.</td>
+  </tr>
+</table>
+
+### SbAccessibilityGetTextToSpeechSettings
+
+**Description**
+
+Get the platform settings related to the text-to-speech accessibility
+feature. This function returns false if `out_settings` is NULL or if it is
+not zero-initialized.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbAccessibilityGetTextToSpeechSettings-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbAccessibilityGetTextToSpeechSettings-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbAccessibilityGetTextToSpeechSettings-declaration">
+<pre>
+SB_EXPORT bool SbAccessibilityGetTextToSpeechSettings(
+    SbAccessibilityTextToSpeechSettings* out_settings);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbAccessibilityGetTextToSpeechSettings-stub">
+
+```
+#include "starboard/accessibility.h"
+
+#include "starboard/memory.h"
+
+bool SbAccessibilityGetTextToSpeechSettings(
+    SbAccessibilityTextToSpeechSettings* out_setting) {
+  if (!out_setting ||
+      !SbMemoryIsZero(out_setting,
+                      sizeof(SbAccessibilityTextToSpeechSettings))) {
+    return false;
+  }
+  out_setting->has_text_to_speech_setting = false;
+  return true;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbAccessibilityTextToSpeechSettings*</code><br>        <code>out_settings</code></td>
+    <td>A pointer to a zero-initialized
+SbAccessibilityTextToSpeechSettings struct.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/atomic.md b/src/cobalt/site/docs/reference/starboard/modules/atomic.md
new file mode 100644
index 0000000..9b100e2
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/atomic.md
@@ -0,0 +1,761 @@
+---
+layout: doc
+title: "Starboard Module Reference: atomic.h"
+---
+
+Defines a set of atomic integer operations that can be used as lightweight
+synchronization or as building blocks for heavier synchronization primitives.
+Their use is very subtle and requires detailed understanding of the behavior
+of supported architectures, so their direct use is not recommended except
+when rigorously deemed absolutely necessary for performance reasons.
+
+## Functions
+
+### SbAtomicAcquire_CompareAndSwap
+
+**Declaration**
+
+```
+static SbAtomic32 SbAtomicAcquire_CompareAndSwap(volatile SbAtomic32* ptr,
+                                                 SbAtomic32 old_value,
+                                                 SbAtomic32 new_value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic32*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic32</code><br>
+        <code>old_value</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic32</code><br>
+        <code>new_value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicAcquire_CompareAndSwap64
+
+**Declaration**
+
+```
+static SbAtomic64 SbAtomicAcquire_CompareAndSwap64(volatile SbAtomic64* ptr,
+                                                   SbAtomic64 old_value,
+                                                   SbAtomic64 new_value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic64*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic64</code><br>
+        <code>old_value</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic64</code><br>
+        <code>new_value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicAcquire_Load
+
+**Declaration**
+
+```
+static SbAtomic32 SbAtomicAcquire_Load(volatile const SbAtomic32* ptr);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile const SbAtomic32*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicAcquire_Load64
+
+**Declaration**
+
+```
+static SbAtomic64 SbAtomicAcquire_Load64(volatile const SbAtomic64* ptr);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile const SbAtomic64*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicAcquire_Store
+
+**Declaration**
+
+```
+static void SbAtomicAcquire_Store(volatile SbAtomic32* ptr, SbAtomic32 value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic32*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic32</code><br>
+        <code>value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicAcquire_Store64
+
+**Declaration**
+
+```
+static void SbAtomicAcquire_Store64(volatile SbAtomic64* ptr, SbAtomic64 value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic64*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic64</code><br>
+        <code>value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicBarrier_Increment
+
+**Declaration**
+
+```
+static SbAtomic32 SbAtomicBarrier_Increment(volatile SbAtomic32* ptr,
+                                            SbAtomic32 increment);
+// These following lower-level operations are typically useful only to people
+// implementing higher-level synchronization operations like spinlocks, mutexes,
+// and condition-variables.  They combine CompareAndSwap(), a load, or a store
+// with appropriate memory-ordering instructions.  "Acquire" operations ensure
+// that no later memory access can be reordered ahead of the operation.
+// "Release" operations ensure that no previous memory access can be reordered
+// after the operation.  "Barrier" operations have both "Acquire" and "Release"
+// semantics.  A SbAtomicMemoryBarrier() has "Barrier" semantics, but does no
+// memory access.
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic32*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic32</code><br>
+        <code>increment</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicBarrier_Increment64
+
+**Declaration**
+
+```
+static SbAtomic64 SbAtomicBarrier_Increment64(volatile SbAtomic64* ptr,
+                                              SbAtomic64 increment);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic64*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic64</code><br>
+        <code>increment</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicMemoryBarrier
+
+**Declaration**
+
+```
+static void SbAtomicMemoryBarrier();
+```
+
+### SbAtomicNoBarrier_CompareAndSwap
+
+**Description**
+
+Atomically execute:
+result = *ptr;
+if (*ptr == old_value)
+*ptr = new_value;
+return result;<br>
+I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
+Always return the old value of "*ptr"<br>
+This routine implies no memory barriers.
+
+**Declaration**
+
+```
+static SbAtomic32 SbAtomicNoBarrier_CompareAndSwap(volatile SbAtomic32* ptr,
+                                                   SbAtomic32 old_value,
+                                                   SbAtomic32 new_value);
+// Atomically store new_value into *ptr, returning the previous value held in
+// *ptr.  This routine implies no memory barriers.
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic32*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic32</code><br>
+        <code>old_value</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic32</code><br>
+        <code>new_value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicNoBarrier_CompareAndSwap64
+
+**Declaration**
+
+```
+static SbAtomic64 SbAtomicNoBarrier_CompareAndSwap64(volatile SbAtomic64* ptr,
+                                                     SbAtomic64 old_value,
+                                                     SbAtomic64 new_value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic64*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic64</code><br>
+        <code>old_value</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic64</code><br>
+        <code>new_value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicNoBarrier_Exchange
+
+**Declaration**
+
+```
+static SbAtomic32 SbAtomicNoBarrier_Exchange(volatile SbAtomic32* ptr,
+                                             SbAtomic32 new_value);
+// Atomically increment *ptr by "increment".  Returns the new value of
+// *ptr with the increment applied.  This routine implies no memory barriers.
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic32*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic32</code><br>
+        <code>new_value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicNoBarrier_Exchange64
+
+**Declaration**
+
+```
+static SbAtomic64 SbAtomicNoBarrier_Exchange64(volatile SbAtomic64* ptr,
+                                               SbAtomic64 new_value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic64*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic64</code><br>
+        <code>new_value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicNoBarrier_Increment
+
+**Declaration**
+
+```
+static SbAtomic32 SbAtomicNoBarrier_Increment(volatile SbAtomic32* ptr,
+                                              SbAtomic32 increment);
+// Same as SbAtomicNoBarrier_Increment, but with a memory barrier.
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic32*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic32</code><br>
+        <code>increment</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicNoBarrier_Increment64
+
+**Declaration**
+
+```
+static SbAtomic64 SbAtomicNoBarrier_Increment64(volatile SbAtomic64* ptr,
+                                                SbAtomic64 increment);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic64*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic64</code><br>
+        <code>increment</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicNoBarrier_Load
+
+**Declaration**
+
+```
+static SbAtomic32 SbAtomicNoBarrier_Load(volatile const SbAtomic32* ptr);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile const SbAtomic32*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicNoBarrier_Load64
+
+**Declaration**
+
+```
+static SbAtomic64 SbAtomicNoBarrier_Load64(volatile const SbAtomic64* ptr);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile const SbAtomic64*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicNoBarrier_Store
+
+**Declaration**
+
+```
+static void SbAtomicNoBarrier_Store(volatile SbAtomic32* ptr, SbAtomic32 value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic32*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic32</code><br>
+        <code>value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicNoBarrier_Store64
+
+**Declaration**
+
+```
+static void SbAtomicNoBarrier_Store64(volatile SbAtomic64* ptr,
+                                      SbAtomic64 value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic64*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic64</code><br>
+        <code>value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicPtr
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE SbAtomicPtr
+SbAtomicRelease_LoadPtr(volatile const SbAtomicPtr* ptr) {
+#if SB_HAS(64_BIT_POINTERS)
+  return SbAtomicRelease_Load64(ptr);
+#else
+  return SbAtomicRelease_Load(ptr);
+#endif
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbAtomicRelease_LoadPtr(volatile const SbAtomicPtr*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicRelease_CompareAndSwap
+
+**Declaration**
+
+```
+static SbAtomic32 SbAtomicRelease_CompareAndSwap(volatile SbAtomic32* ptr,
+                                                 SbAtomic32 old_value,
+                                                 SbAtomic32 new_value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic32*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic32</code><br>
+        <code>old_value</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic32</code><br>
+        <code>new_value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicRelease_CompareAndSwap64
+
+**Declaration**
+
+```
+static SbAtomic64 SbAtomicRelease_CompareAndSwap64(volatile SbAtomic64* ptr,
+                                                   SbAtomic64 old_value,
+                                                   SbAtomic64 new_value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic64*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic64</code><br>
+        <code>old_value</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic64</code><br>
+        <code>new_value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicRelease_Load
+
+**Declaration**
+
+```
+static SbAtomic32 SbAtomicRelease_Load(volatile const SbAtomic32* ptr);
+// 64-bit atomic operations (only available on 64-bit processors).
+#if SB_HAS(64_BIT_ATOMICS)
+typedef int64_t SbAtomic64;
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile const SbAtomic32*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicRelease_Load64
+
+**Declaration**
+
+```
+static SbAtomic64 SbAtomicRelease_Load64(volatile const SbAtomic64* ptr);
+#endif  // SB_HAS(64_BIT_ATOMICS)
+// Pointer-sized atomic operations. Forwards to either 32-bit or 64-bit
+// functions as appropriate.
+#if SB_HAS(64_BIT_POINTERS)
+typedef SbAtomic64 SbAtomicPtr;
+#else
+typedef SbAtomic32 SbAtomicPtr;
+#endif
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile const SbAtomic64*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicRelease_Store
+
+**Declaration**
+
+```
+static void SbAtomicRelease_Store(volatile SbAtomic32* ptr, SbAtomic32 value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic32*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic32</code><br>
+        <code>value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAtomicRelease_Store64
+
+**Declaration**
+
+```
+static void SbAtomicRelease_Store64(volatile SbAtomic64* ptr, SbAtomic64 value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>volatile SbAtomic64*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomic64</code><br>
+        <code>value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### void
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE void
+SbAtomicRelease_StorePtr(volatile SbAtomicPtr* ptr, SbAtomicPtr value) {
+#if SB_HAS(64_BIT_POINTERS)
+  SbAtomicRelease_Store64(ptr, value);
+#else
+  SbAtomicRelease_Store(ptr, value);
+#endif
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbAtomicRelease_StorePtr(volatile SbAtomicPtr*</code><br>
+        <code>ptr</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbAtomicPtr</code><br>
+        <code>value</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/audio_sink.md b/src/cobalt/site/docs/reference/starboard/modules/audio_sink.md
new file mode 100644
index 0000000..2a64654
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/audio_sink.md
@@ -0,0 +1,405 @@
+---
+layout: doc
+title: "Starboard Module Reference: audio_sink.h"
+---
+
+Provides an interface to output raw audio data.
+
+## Structs
+
+### SbAudioSink
+
+An opaque handle to an implementation-private structure representing an
+audio sink.
+
+## Functions
+
+### SbAudioSinkCreate
+
+**Description**
+
+Creates an audio sink for the specified `channels` and
+`sampling_frequency_hz`, acquires all resources needed to operate the
+audio sink, and returns an opaque handle to the audio sink.<br>
+If the particular platform doesn't support the requested audio sink, the
+function returns kSbAudioSinkInvalid without calling any of the callbacks.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbAudioSinkCreate-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbAudioSinkCreate-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbAudioSinkCreate-declaration">
+<pre>
+SB_EXPORT SbAudioSink
+SbAudioSinkCreate(int channels,
+                  int sampling_frequency_hz,
+                  SbMediaAudioSampleType audio_sample_type,
+                  SbMediaAudioFrameStorageType audio_frame_storage_type,
+                  SbAudioSinkFrameBuffers frame_buffers,
+                  int frames_per_channel,
+                  SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
+                  SbAudioSinkConsumeFramesFunc consume_frames_func,
+                  void* context);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbAudioSinkCreate-stub">
+
+```
+#include "starboard/audio_sink.h"
+
+struct SbAudioSinkPrivate {};
+
+namespace {
+struct SbAudioSinkPrivate g_singleton_stub;
+}
+
+SbAudioSink SbAudioSinkCreate(
+    int channels,
+    int sampling_frequency_hz,
+    SbMediaAudioSampleType audio_sample_type,
+    SbMediaAudioFrameStorageType audio_frame_storage_type,
+    SbAudioSinkFrameBuffers frame_buffers,
+    int frames_per_channel,
+    SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
+    SbAudioSinkConsumeFramesFunc consume_frames_func,
+    void* context) {
+  return &g_singleton_stub;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>channels</code></td>
+    <td>The number of audio channels, such as left and right channels
+in stereo audio.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>sampling_frequency_hz</code></td>
+    <td>The sample frequency of the audio data being
+streamed. For example, 22,000 Hz means 22,000 sample elements represents
+one second of audio data.</td>
+  </tr>
+  <tr>
+    <td><code>SbMediaAudioSampleType</code><br>        <code>audio_sample_type</code></td>
+    <td>The type of each sample of the audio data --
+<code>int16</code>, <code>float32</code>, etc.</td>
+  </tr>
+  <tr>
+    <td><code>SbMediaAudioFrameStorageType</code><br>        <code>audio_frame_storage_type</code></td>
+    <td>Indicates whether frames are interleaved or
+planar.</td>
+  </tr>
+  <tr>
+    <td><code>SbAudioSinkFrameBuffers</code><br>        <code>frame_buffers</code></td>
+    <td>An array of pointers to sample data.
+<ul><li>If the sink is operating in interleaved mode, the array contains only
+one element, which is an array containing (<code>frames_per_channel</code> *
+<code>channels</code>) samples.
+</li><li>If the sink is operating in planar mode, the number of elements in the
+array is the same as <code>channels</code>, and each element is an array of
+<code>frames_per_channel</code> samples. The caller has to ensure that
+<code>frame_buffers</code> is valid until <code><a href="#sbaudiosinkdestroy">SbAudioSinkDestroy</a></code> is called.</li></ul></td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>frames_per_channel</code></td>
+    <td>The size of the frame buffers, in units of the
+number of samples per channel. The frame, in this case, represents a
+group of samples at the same media time, one for each channel.</td>
+  </tr>
+  <tr>
+    <td><code>SbAudioSinkUpdateSourceStatusFunc</code><br>        <code>update_source_status_func</code></td>
+    <td>The audio sink calls this function on an
+internal thread to query the status of the source. The value cannot be NULL.  A function that the audio sink starts to call
+immediately after <code>SbAudioSinkCreate</code> is called, even before it returns.
+The caller has to ensure that the callback functions above return
+meaningful values in this case.</td>
+  </tr>
+  <tr>
+    <td><code>SbAudioSinkConsumeFramesFunc</code><br>        <code>consume_frames_func</code></td>
+    <td>The audio sink calls this function on an internal
+thread to report consumed frames. The value cannot be NULL.</td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>        <code>context</code></td>
+    <td>A value that is passed back to all callbacks and is generally
+used to point at a class or struct that contains state associated with the
+audio sink.</td>
+  </tr>
+</table>
+
+### SbAudioSinkDestroy
+
+**Description**
+
+Destroys `audio_sink`, freeing all associated resources. Before
+returning, the function waits until all callbacks that are in progress
+have finished. After the function returns, no further calls are made
+callbacks passed into <code><a href="#sbaudiosinkcreate">SbAudioSinkCreate</a></code>. In addition, you can not pass
+`audio_sink` to any other SbAudioSink functions after <code>SbAudioSinkDestroy</code>
+has been called on it.<br>
+This function can be called on any thread. However, it cannot be called
+within any of the callbacks passed into <code><a href="#sbaudiosinkcreate">SbAudioSinkCreate</a></code>.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbAudioSinkDestroy-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbAudioSinkDestroy-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbAudioSinkDestroy-declaration">
+<pre>
+SB_EXPORT void SbAudioSinkDestroy(SbAudioSink audio_sink);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbAudioSinkDestroy-stub">
+
+```
+#include "starboard/audio_sink.h"
+
+void SbAudioSinkDestroy(SbAudioSink /*audio_sink*/) {}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbAudioSink</code><br>        <code>audio_sink</code></td>
+    <td>The audio sink to destroy.</td>
+  </tr>
+</table>
+
+### SbAudioSinkGetMaxChannels
+
+**Description**
+
+Returns the maximum number of channels supported on the platform. For
+example, the number would be `2` if the platform only supports stereo.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbAudioSinkGetMaxChannels-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbAudioSinkGetMaxChannels-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbAudioSinkGetMaxChannels-declaration">
+<pre>
+SB_EXPORT int SbAudioSinkGetMaxChannels();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbAudioSinkGetMaxChannels-stub">
+
+```
+#include "starboard/audio_sink.h"
+
+int SbAudioSinkGetMaxChannels() {
+  return 2;
+}
+```
+
+  </div>
+</div>
+
+### SbAudioSinkGetNearestSupportedSampleFrequency
+
+**Description**
+
+Returns the supported sample rate closest to `sampling_frequency_hz`.
+On platforms that don't support all sample rates, it is the caller's
+responsibility to resample the audio frames into the supported sample rate
+returned by this function.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbAudioSinkGetNearestSupportedSampleFrequency-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbAudioSinkGetNearestSupportedSampleFrequency-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbAudioSinkGetNearestSupportedSampleFrequency-declaration">
+<pre>
+SB_EXPORT int SbAudioSinkGetNearestSupportedSampleFrequency(
+    int sampling_frequency_hz);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbAudioSinkGetNearestSupportedSampleFrequency-stub">
+
+```
+#include "starboard/audio_sink.h"
+
+int SbAudioSinkGetNearestSupportedSampleFrequency(
+    int sampling_frequency_hz) {
+  return sampling_frequency_hz;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>sampling_frequency_hz</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAudioSinkIsAudioFrameStorageTypeSupported
+
+**Description**
+
+Indicates whether `audio_frame_storage_type` is supported on this
+platform.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbAudioSinkIsAudioFrameStorageTypeSupported-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbAudioSinkIsAudioFrameStorageTypeSupported-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbAudioSinkIsAudioFrameStorageTypeSupported-declaration">
+<pre>
+SB_EXPORT bool SbAudioSinkIsAudioFrameStorageTypeSupported(
+    SbMediaAudioFrameStorageType audio_frame_storage_type);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbAudioSinkIsAudioFrameStorageTypeSupported-stub">
+
+```
+#include "starboard/audio_sink.h"
+
+bool SbAudioSinkIsAudioFrameStorageTypeSupported(
+    SbMediaAudioFrameStorageType audio_frame_storage_type) {
+  return true;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMediaAudioFrameStorageType</code><br>
+        <code>audio_frame_storage_type</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAudioSinkIsAudioSampleTypeSupported
+
+**Description**
+
+Indicates whether `audio_sample_type` is supported on this platform.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbAudioSinkIsAudioSampleTypeSupported-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbAudioSinkIsAudioSampleTypeSupported-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbAudioSinkIsAudioSampleTypeSupported-declaration">
+<pre>
+SB_EXPORT bool SbAudioSinkIsAudioSampleTypeSupported(
+    SbMediaAudioSampleType audio_sample_type);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbAudioSinkIsAudioSampleTypeSupported-stub">
+
+```
+#include "starboard/audio_sink.h"
+
+bool SbAudioSinkIsAudioSampleTypeSupported(
+    SbMediaAudioSampleType audio_sample_type) {
+  return true;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMediaAudioSampleType</code><br>
+        <code>audio_sample_type</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbAudioSinkIsValid
+
+**Description**
+
+Indicates whether the given audio sink handle is valid.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbAudioSinkIsValid-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbAudioSinkIsValid-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbAudioSinkIsValid-declaration">
+<pre>
+SB_EXPORT bool SbAudioSinkIsValid(SbAudioSink audio_sink);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbAudioSinkIsValid-stub">
+
+```
+#include "starboard/audio_sink.h"
+
+bool SbAudioSinkIsValid(SbAudioSink /*audio_sink*/) {
+  return true;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbAudioSink</code><br>        <code>audio_sink</code></td>
+    <td>The audio sink handle to check.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/blitter.md b/src/cobalt/site/docs/reference/starboard/modules/blitter.md
new file mode 100644
index 0000000..0dfb391
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/blitter.md
@@ -0,0 +1,1715 @@
+---
+layout: doc
+title: "Starboard Module Reference: blitter.h"
+---
+
+The Blitter API provides support for issuing simple blit-style draw
+commands to either an offscreen surface or to a Starboard SbWindow object.
+Blitter is jargon that means "BLock Transfer," which might be abbreviated
+as BLT and, hence, the word "blit."<br>
+This API is designed to allow implementations make use of GPU hardware
+acceleration, if it is available.  Draw commands exist for solid-color
+rectangles and rasterization/blitting of rectangular images onto
+rectangular target patches.<br>
+#### Threading Concerns
+
+
+Note that in general the Blitter API is not thread safe, except for all
+SbBlitterDevice-related functions.  All functions that are not required to
+internally ensure any thread safety guarantees are prefaced with a comment
+indicating that they are not thread safe.
+Functions which claim to not be thread safe can still be used from multiple
+threads, but manual synchronization must be performed in order to ensure
+their parameters are not referenced at the same time on another thread by
+another function.
+Examples:
+<ul><li>Multiple threads should not issue commands to the same SbBlitterContext
+object unless they are manually synchronized.
+</li><li>Multiple threads should not issue draw calls to the same render target,
+even if the draw calls are made within separate contexts.  In this case,
+be sure to manually synchronize through the use of syncrhonization
+primitives and use of the SbBlitterFlushContext() command.
+</li><li>Multiple threads can operate on the swap chain, but they must perform
+manual synchronization.</li></ul>
+
+## Enums
+
+### SbBlitterPixelDataFormat
+
+Defines the set of pixel formats that can be used with the Blitter API
+SbBlitterPixelData objects.  Note that not all of these formats are
+guaranteed to be supported by a particular device, so before using these
+formats in pixel data creation commands, it should be checked that they are
+supported first (e.g. via SbBlitterIsPixelFormatSupportedByPixelData()).
+SbBlitterPixelDataFormat specifies specific orderings of the color channels,
+and when doing so, byte-order is used, e.g. "RGBA" implies that a value for
+red is stored in the byte with the lowest memory address.  All pixel values
+are assumed to be in premultiplied alpha format.
+
+**Values**
+
+*   `kSbBlitterPixelDataFormatARGB8` - 32-bit pixels with 8-bits per channel, the alpha component in the bytewith the lowest address and blue in the byte with the highest address.
+*   `kSbBlitterPixelDataFormatBGRA8` - 32-bit pixels with 8-bits per channel, the blue component in the bytewith the lowest address and alpha in the byte with the highest address.
+*   `kSbBlitterPixelDataFormatRGBA8` - 32-bit pixels with 8-bits per channel, the red component in the bytewith the lowest address and alpha in the byte with the highest address.
+*   `kSbBlitterPixelDataFormatA8` - 8-bit pixels that contain only a single alpha channel.  When rendered,surfaces in this format will have (R, G, B) values of (255, 255, 255).
+*   `kSbBlitterNumPixelDataFormats` - Constant that indicates how many unique pixel formats Starboard supports.
+*   `kSbBlitterInvalidPixelDataFormat`
+
+### SbBlitterSurfaceFormat
+
+Enumeration that describes the color format of surfaces.  Note that
+SbBlitterSurfaceFormat does not differentiate between permutations of the
+color channel ordering (e.g. RGBA vs ARGB) since client code will never be
+able to access surface pixels directly.  This is the main difference between
+SbBlitterPixelDataFormat, which does explicitly dictate an ordering.
+
+**Values**
+
+*   `kSbBlitterSurfaceFormatRGBA8` - 32-bit RGBA color, with 8 bits per channel.
+*   `kSbBlitterSurfaceFormatA8` - 8-bit alpha-only color.
+*   `kSbBlitterNumSurfaceFormats` - Constant that indicates how many unique surface formats Starboard supports.
+*   `kSbBlitterInvalidSurfaceFormat`
+
+## Structs
+
+### SbBlitterContextPrivate
+
+SbBlitterContext objects represent a stateful communications channel with
+a device.  All state changes and draw calls are made through a specific
+SbBlitterContext object.  Every draw call made on a SbBlitterContext is
+submitted to the device with the SbBlitterContext's current state applied
+to it.<br>
+Draw calls may be submitted to the device as they are made on the
+SbBlitterContext. However, they are not guaranteed to be submitted until
+the SbBlitterContext object is flushed. That is, until you call
+SbBlitterFlushContext, you are not guaranteed that any API calls you have
+made have been received or acted on by the graphics device.
+
+### SbBlitterDevicePrivate
+
+A SbBlitterDevice object represents a process' connection to a blitter
+device, such as a GPU.  It is through this device that all subsequent Blitter
+API functionality can be accessed.
+
+### SbBlitterPixelDataPrivate
+
+A SbBlitterPixelData object represents a buffer of pixels stored in
+CPU-accessible memory.  In order to upload pixel data from the CPU to the
+GPU, clients should first create a SbBlitterPixelData object, fill in
+the pixel data, and then re-submit the filled in SbBlitterPixelData
+object to the Blitter API in order to obtain a SbBlitterSurface object that
+can be referenced by draw calls.
+
+### SbBlitterRect
+
+Defines a rectangle via a point (x, y) and a size, (width, height).
+This structure is used as a parameter type in various blit calls.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>x</code></td>    <td></td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>y</code></td>    <td></td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>width</code></td>    <td></td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>height</code></td>    <td></td>  </tr>
+</table>
+
+### SbBlitterRenderTargetPrivate
+
+A SbBlitterRenderTarget may be obtained from either a SbBlitterSwapChain
+if it represents a primary display output, or through a SbBlitterSurface
+if it represents an offscreen rendering target.  A SbBlitterRenderTarget
+must be specified within a SbBlitterContext before making a draw call.
+
+### SbBlitterSurfaceInfo
+
+SbBlitterSurfaceInfo collects information about surfaces that can be queried
+from them at any time.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>width</code></td>    <td></td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>height</code></td>    <td></td>  </tr>
+  <tr>
+    <td><code>SbBlitterSurfaceFormat</code><br>        <code>format</code></td>    <td></td>  </tr>
+</table>
+
+### SbBlitterSurfacePrivate
+
+A SbBlitterSurface object represents a device-side surface of pixel data that
+can be used as either the source or the target of device draw calls.
+Note that depending on how the surface is created, it may not be able to
+offer the ability to obtain a SbBlitterRenderTarget. SbBlitterSurface objects
+may be populated by data either by the CPU via SbBlitterPixelData objects, or
+via the device by using this SbBlitterSurface's SbBlitterRenderTarget object
+as the target of draw calls.
+
+### SbBlitterSwapChainPrivate
+
+A SbBlitterSwapChain represents the (potentially back buffered) output
+display device.  A SbBlitterRenderTarget can be retrieved from a
+SbBlitterSwapChain, providing a target for draw commands.  The
+SbBlitterSwapChain object also exposes the ability to flip back buffers.
+
+## Functions
+
+### SbBlitterAFromColor
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE uint8_t SbBlitterAFromColor(SbBlitterColor color) {
+  return (color & 0x000000FF) >> 0;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterColor</code><br>
+        <code>color</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterBFromColor
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE uint8_t SbBlitterBFromColor(SbBlitterColor color) {
+  return (color & 0x0000FF00) >> 8;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterColor</code><br>
+        <code>color</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterBlitRectToRect
+
+**Description**
+
+Issues a draw call on `context` that blits the area of `source_surface`
+specified by `src_rect` to `context`'s current render target at `dst_rect`.
+The source rectangle must lie within the dimensions of `source_surface`.
+Note that the `source_surface`'s alpha is modulated by `opacity` before
+being drawn. For `opacity`, a value of 0 implies complete invisibility,
+and a value of 255 implies complete opacity.<br>
+This function is not thread-safe.<br>
+The return value indicates whether the draw call succeeded.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterBlitRectToRect(SbBlitterContext context,
+                                       SbBlitterSurface source_surface,
+                                       SbBlitterRect src_rect,
+                                       SbBlitterRect dst_rect);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterContext</code><br>        <code>context</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>SbBlitterSurface</code><br>        <code>source_surface</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>SbBlitterRect</code><br>        <code>src_rect</code></td>
+    <td>The area to be block transferred (blitted).</td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterRect</code><br>        <code>dst_rect</code></td>
+    <td> </td>  </tr>
+</table>
+
+### SbBlitterBlitRectToRectTiled
+
+**Description**
+
+This function functions identically to <code><a href="#sbblitterblitrecttorect">SbBlitterBlitRectToRect()</a></code>, except
+it permits values of `src_rect` outside the dimensions of `source_surface`.
+In those regions, the pixel data from `source_surface` will be wrapped.
+Negative values for `src_rect.x` and `src_rect.y` are allowed.<br>
+The output is all stretched to fit inside of `dst_rect`.<br>
+This function is not thread-safe.<br>
+The return value indicates whether the draw call succeeded.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterBlitRectToRectTiled(SbBlitterContext context,
+                                            SbBlitterSurface source_surface,
+                                            SbBlitterRect src_rect,
+                                            SbBlitterRect dst_rect);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterContext</code><br>
+        <code>context</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterSurface</code><br>
+        <code>source_surface</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterRect</code><br>
+        <code>src_rect</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterRect</code><br>
+        <code>dst_rect</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterBlitRectsToRects
+
+**Description**
+
+This function achieves the same effect as calling <code><a href="#sbblitterblitrecttorect">SbBlitterBlitRectToRect()</a></code>
+`num_rects` times with each of the `num_rects` values of `src_rects` and
+`dst_rects`. This function allows for greater efficiency than looped calls
+to <code><a href="#sbblitterblitrecttorect">SbBlitterBlitRectToRect()</a></code>.<br>
+This function is not thread-safe.<br>
+The return value indicates whether the draw call succeeded.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterBlitRectsToRects(SbBlitterContext context,
+                                         SbBlitterSurface source_surface,
+                                         const SbBlitterRect* src_rects,
+                                         const SbBlitterRect* dst_rects,
+                                         int num_rects);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterContext</code><br>
+        <code>context</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterSurface</code><br>
+        <code>source_surface</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>const SbBlitterRect*</code><br>
+        <code>src_rects</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>const SbBlitterRect*</code><br>
+        <code>dst_rects</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>num_rects</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterBytesPerPixelForFormat
+
+**Description**
+
+A convenience function to return the number of bytes per pixel for a given
+pixel format.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE int SbBlitterBytesPerPixelForFormat(
+    SbBlitterPixelDataFormat format) {
+  switch (format) {
+    case kSbBlitterPixelDataFormatARGB8:
+      return 4;
+    case kSbBlitterPixelDataFormatBGRA8:
+      return 4;
+    case kSbBlitterPixelDataFormatRGBA8:
+      return 4;
+    case kSbBlitterPixelDataFormatA8:
+      return 1;
+    default:
+      return 0;
+  }
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterPixelDataFormat</code><br>
+        <code>format</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterColorFromRGBA
+
+**Description**
+
+A convenience function to create a SbBlitterColor object from separate
+8-bit RGBA components.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE SbBlitterColor SbBlitterColorFromRGBA(uint8_t r,
+                                                               uint8_t g,
+                                                               uint8_t b,
+                                                               uint8_t a) {
+  return (r << 24) | (g << 16) | (b << 8) | a;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>uint8_t</code><br>
+        <code>r</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>uint8_t</code><br>
+        <code>g</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>uint8_t</code><br>
+        <code>b</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>uint8_t</code><br>
+        <code>a</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterCreateContext
+
+**Description**
+
+Creates an SbBlitterContext object on `device`. The returned context can be
+used to set up draw state and issue draw calls.<br>
+Note that there is a limit on the number of contexts that can exist
+simultaneously, which can be queried by calling <code><a href="#sbblittergetmaxcontexts">SbBlitterGetMaxContexts()</a></code>.
+(The limit is often `1`.)<br>
+SbBlitterContext objects keep track of draw state between a series of draw
+calls. Please refer to the SbBlitterContext() definition for more
+information about contexts.<br>
+This function is thread-safe.<br>
+This function returns kSbBlitterInvalidContext upon failure. Note that the
+function fails if it has already been used to create the maximum number
+of contexts.
+
+**Declaration**
+
+```
+SB_EXPORT SbBlitterContext SbBlitterCreateContext(SbBlitterDevice device);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterDevice</code><br>        <code>device</code></td>
+    <td>The SbBlitterDevice for which the SbBlitterContext object is
+created.</td>
+  </tr>
+</table>
+
+### SbBlitterCreateDefaultDevice
+
+**Description**
+
+Creates and returns an SbBlitterDevice based on the Blitter API
+implementation's decision of which device should be the default. The
+returned SbBlitterDevice represents a connection to a device (like a GPU).<br>
+On many platforms there is always one single obvious choice for a device
+to use, and that is the one that this function will return. For example,
+if this is called on a platform that has a single GPU, this call should
+return an object that represents that GPU. On a platform that has no GPU,
+an object representing a software CPU implementation may be returned.<br>
+Only one default device can exist within a process at a time.
+This function is thread-safe.
+Returns kSbBlitterInvalidDevice on failure.
+
+**Declaration**
+
+```
+SB_EXPORT SbBlitterDevice SbBlitterCreateDefaultDevice();
+```
+
+### SbBlitterCreatePixelData
+
+**Description**
+
+Allocates an SbBlitterPixelData object through `device` with `width`,
+`height` and `pixel_format`. `pixel_format` must be supported by `device`
+(see <code><a href="#sbblitterispixelformatsupportedbypixeldata">SbBlitterIsPixelFormatSupportedByPixelData()</a></code>). This function is
+thread-safe.<br>
+Calling this function results in the allocation of CPU-accessible
+(though perhaps blitter-device-resident) memory to store pixel data
+of the requested size/format. An SbBlitterPixelData object should
+eventually be passed either into a call to
+SbBlitterCreateSurfaceFromPixelData() or into a call to
+SbBlitterDestroyPixelData().<br>
+Returns kSbBlitterInvalidPixelData upon failure.
+
+**Declaration**
+
+```
+SB_EXPORT SbBlitterPixelData
+SbBlitterCreatePixelData(SbBlitterDevice device,
+                         int width,
+                         int height,
+                         SbBlitterPixelDataFormat pixel_format);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterDevice</code><br>
+        <code>device</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>width</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>height</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterPixelDataFormat</code><br>
+        <code>pixel_format</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterCreateRenderTargetSurface
+
+**Description**
+
+Creates a new surface with undefined pixel data on `device` with the
+specified `width`, `height` and `surface_format`. One can set the pixel data
+on the resulting surface by getting its associated SbBlitterRenderTarget
+object and then calling <code><a href="#sbblittergetrendertargetfromsurface">SbBlitterGetRenderTargetFromSurface()</a></code>.<br>
+This function is thread-safe.<br>
+Returns kSbBlitterInvalidSurface upon failure.
+
+**Declaration**
+
+```
+SB_EXPORT SbBlitterSurface
+SbBlitterCreateRenderTargetSurface(SbBlitterDevice device,
+                                   int width,
+                                   int height,
+                                   SbBlitterSurfaceFormat surface_format);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterDevice</code><br>
+        <code>device</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>width</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>height</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterSurfaceFormat</code><br>
+        <code>surface_format</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterCreateSurfaceFromPixelData
+
+**Description**
+
+Creates an SbBlitterSurface object on `device`. Note that `device` must
+match the device that was used to create the SbBlitterPixelData object
+provided via the `pixel_data` parameter.<br>
+This function also destroys the input `pixel_data` object. As a result,
+`pixel_data` should not be accessed again after a call to this function.<br>
+The returned object cannot be used as a render target (e.g. calling
+SbBlitterGetRenderTargetFromSurface() on it will return
+SbBlitterInvalidRenderTarget).<br>
+This function is thread-safe with respect to `device`, but `pixel_data`
+should not be modified on another thread while this function is called.<br>
+Returns kSbBlitterInvalidSurface in the event of an error.
+
+**Declaration**
+
+```
+SB_EXPORT SbBlitterSurface
+SbBlitterCreateSurfaceFromPixelData(SbBlitterDevice device,
+                                    SbBlitterPixelData pixel_data);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterDevice</code><br>
+        <code>device</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterPixelData</code><br>
+        <code>pixel_data</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterCreateSwapChainFromWindow
+
+**Description**
+
+Creates and returns an SbBlitterSwapChain that can then be used to send
+graphics to the display. This function links `device` to `window`'s output,
+and drawing to the returned swap chain will result in `device` being used
+to render to `window`.<br>
+This function must be called from the thread that called SbWindowCreate()
+to create `window`.<br>
+Returns kSbBlitterInvalidSwapChain on failure.
+
+**Declaration**
+
+```
+SB_EXPORT SbBlitterSwapChain
+SbBlitterCreateSwapChainFromWindow(SbBlitterDevice device, SbWindow window);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterDevice</code><br>
+        <code>device</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbWindow</code><br>
+        <code>window</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterDestroyContext
+
+**Description**
+
+Destroys the specified `context`, freeing all its resources. This function
+is not thread-safe.<br>
+The return value indicates whether the destruction succeeded.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterDestroyContext(SbBlitterContext context);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterContext</code><br>        <code>context</code></td>
+    <td>The object to be destroyed.</td>
+  </tr>
+</table>
+
+### SbBlitterDestroyDevice
+
+**Description**
+
+Destroys `device`, cleaning up all resources associated with it.
+This function is thread-safe, but it should not be called if `device` is
+still being accessed elsewhere.<br>
+The return value indicates whether the destruction succeeded.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterDestroyDevice(SbBlitterDevice device);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterDevice</code><br>        <code>device</code></td>
+    <td>The SbBlitterDevice object to be destroyed.</td>
+  </tr>
+</table>
+
+### SbBlitterDestroyPixelData
+
+**Description**
+
+Destroys `pixel_data`. Note that this function does not need to be called
+and should not be called if <code><a href="#sbblittercreatesurfacefrompixeldata">SbBlitterCreateSurfaceFromPixelData()</a></code> has been
+called on `pixel_data` before. This function is thread-safe.<br>
+The return value indicates whether the destruction succeeded.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterDestroyPixelData(SbBlitterPixelData pixel_data);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterPixelData</code><br>        <code>pixel_data</code></td>
+    <td>The object to be destroyed.</td>
+  </tr>
+</table>
+
+### SbBlitterDestroySurface
+
+**Description**
+
+Destroys the `surface` object, cleaning up all resources associated with it.
+This function is not thread safe.<br>
+The return value indicates whether the destruction succeeded.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterDestroySurface(SbBlitterSurface surface);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterSurface</code><br>        <code>surface</code></td>
+    <td>The object to be destroyed.</td>
+  </tr>
+</table>
+
+### SbBlitterDestroySwapChain
+
+**Description**
+
+Destroys `swap_chain`, cleaning up all resources associated with it.
+This function is not thread-safe and must be called on the same thread
+that called <code><a href="#sbblittercreateswapchainfromwindow">SbBlitterCreateSwapChainFromWindow()</a></code>.<br>
+The return value indicates whether the destruction succeeded.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterDestroySwapChain(SbBlitterSwapChain swap_chain);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterSwapChain</code><br>        <code>swap_chain</code></td>
+    <td>The SbBlitterSwapChain to be destroyed.</td>
+  </tr>
+</table>
+
+### SbBlitterDownloadSurfacePixels
+
+**Description**
+
+Downloads `surface` pixel data into CPU memory pointed to by
+`out_pixel_data`, formatted according to the requested `pixel_format` and
+the requested `pitch_in_bytes`. Before calling this function, you can call
+SbBlitterIsPixelFormatSupportedByDownloadSurfacePixels() to confirm that
+`pixel_format` is, in fact, valid for `surface`.<br>
+When this function is called, it first waits for all previously flushed
+graphics commands to be executed by the device before downloading the data.
+Since this function waits for the pipeline to empty, it should be used
+sparingly, such as within in debug or test environments.<br>
+The return value indicates whether the pixel data was downloaded
+successfully.<br>
+The returned alpha format is premultiplied.<br>
+This function is not thread-safe.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterDownloadSurfacePixels(
+    SbBlitterSurface surface,
+    SbBlitterPixelDataFormat pixel_format,
+    int pitch_in_bytes,
+    void* out_pixel_data);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterSurface</code><br>        <code>surface</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>SbBlitterPixelDataFormat</code><br>        <code>pixel_format</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>pitch_in_bytes</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>void*</code><br>        <code>out_pixel_data</code></td>
+    <td>A pointer to a region of memory with a size of
+surface_height * <code>pitch_in_bytes</code> bytes.</td>
+  </tr>
+</table>
+
+### SbBlitterFillRect
+
+**Description**
+
+Issues a draw call on `context` that fills the specified rectangle `rect`.
+The rectangle's color is determined by the last call to <code><a href="#sbblittersetcolor">SbBlitterSetColor()</a></code>.<br>
+This function is not thread-safe.<br>
+The return value indicates whether the draw call succeeded.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterFillRect(SbBlitterContext context, SbBlitterRect rect);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterContext</code><br>        <code>context</code></td>
+    <td>The context on which the draw call will operate.</td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterRect</code><br>        <code>rect</code></td>
+    <td>The rectangle to be filled.</td>
+  </tr>
+</table>
+
+### SbBlitterFlipSwapChain
+
+**Description**
+
+Flips the `swap_chain` by making the buffer previously accessible to
+draw commands via <code><a href="#sbblittergetrendertargetfromswapchain">SbBlitterGetRenderTargetFromSwapChain()</a></code> visible on the
+display, while another buffer in an initially undefined state is set up
+as the new draw command target. Note that you do not need to call
+SbBlitterGetRenderTargetFromSwapChain() again after flipping, the swap
+chain's render target always refers to its current back buffer.<br>
+This function stalls the calling thread until the next vertical refresh.
+In addition, to ensure consistency with the Starboard Player API when
+rendering punch-out video, calls to SbPlayerSetBounds() do not take effect
+until this method is called.<br>
+The return value indicates whether the flip succeeded.<br>
+This function is not thread-safe.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterFlipSwapChain(SbBlitterSwapChain swap_chain);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterSwapChain</code><br>        <code>swap_chain</code></td>
+    <td>The SbBlitterSwapChain to be flipped.</td>
+  </tr>
+</table>
+
+### SbBlitterFlushContext
+
+**Description**
+
+Flushes all draw calls previously issued to `context`. Calling this function
+guarantees that the device processes all draw calls issued to this point on
+this `context` before processing any subsequent draw calls on any context.<br>
+Before calling <code><a href="#sbblitterflipswapchain">SbBlitterFlipSwapChain()</a></code>, it is often prudent to call this
+function to ensure that all draw calls are submitted before the flip occurs.<br>
+This function is not thread-safe.<br>
+The return value indicates whether the flush succeeded.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterFlushContext(SbBlitterContext context);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterContext</code><br>        <code>context</code></td>
+    <td>The context for which draw calls are being flushed.</td>
+  </tr>
+</table>
+
+### SbBlitterGFromColor
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE uint8_t SbBlitterGFromColor(SbBlitterColor color) {
+  return (color & 0x00FF0000) >> 16;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterColor</code><br>
+        <code>color</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterGetMaxContexts
+
+**Description**
+
+Returns the maximum number of contexts that `device` can support in
+parallel. Note that devices often support only a single context.<br>
+This function is thread-safe.<br>
+This function returns `-1` upon failure.
+
+**Declaration**
+
+```
+SB_EXPORT int SbBlitterGetMaxContexts(SbBlitterDevice device);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterDevice</code><br>        <code>device</code></td>
+    <td>The SbBlitterDevice for which the maximum number of contexts is
+returned.</td>
+  </tr>
+</table>
+
+### SbBlitterGetPixelDataPitchInBytes
+
+**Description**
+
+Retrieves the pitch (in bytes) for `pixel_data`. This indicates the number of
+bytes per row of pixel data in the image. This function is not thread-safe.<br>
+Returns `-1` in the event of an error.
+
+**Declaration**
+
+```
+SB_EXPORT int SbBlitterGetPixelDataPitchInBytes(SbBlitterPixelData pixel_data);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterPixelData</code><br>        <code>pixel_data</code></td>
+    <td>The object for which you are retrieving the pitch.</td>
+  </tr>
+</table>
+
+### SbBlitterGetPixelDataPointer
+
+**Description**
+
+Retrieves a CPU-accessible pointer to the pixel data represented by
+`pixel_data`. This pixel data can be modified by the CPU to initialize it
+on the CPU before calling <code><a href="#sbblittercreatesurfacefrompixeldata">SbBlitterCreateSurfaceFromPixelData()</a></code>.<br>
+Note that the pointer returned here is valid as long as `pixel_data` is
+valid, which means it is valid until either
+SbBlitterCreateSurfaceFromPixelData() or <code><a href="#sbblitterdestroypixeldata">SbBlitterDestroyPixelData()</a></code> is
+called.<br>
+This function is not thread-safe.<br>
+Returns `NULL` in the event of an error.
+
+**Declaration**
+
+```
+SB_EXPORT void* SbBlitterGetPixelDataPointer(SbBlitterPixelData pixel_data);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterPixelData</code><br>
+        <code>pixel_data</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterGetRenderTargetFromSurface
+
+**Description**
+
+Returns the SbBlitterRenderTarget object owned by `surface`.  The returned
+object can be used as a target for draw calls.<br>
+This function returns kSbBlitterInvalidRenderTarget if `surface` is not
+able to provide a render target or on any other error.<br>
+This function is not thread-safe.
+
+**Declaration**
+
+```
+SB_EXPORT SbBlitterRenderTarget
+SbBlitterGetRenderTargetFromSurface(SbBlitterSurface surface);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterSurface</code><br>
+        <code>surface</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterGetRenderTargetFromSwapChain
+
+**Description**
+
+Returns the `SbBlitterRenderTarget` object that is owned by `swap_chain`.
+The returned object can be used to provide a target to blitter draw calls
+that draw directly to the display buffer. This function is not thread-safe.<br>
+Returns kSbBlitterInvalidRenderTarget on failure.
+
+**Declaration**
+
+```
+SB_EXPORT SbBlitterRenderTarget
+SbBlitterGetRenderTargetFromSwapChain(SbBlitterSwapChain swap_chain);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterSwapChain</code><br>        <code>swap_chain</code></td>
+    <td>The SbBlitterSwapChain for which the target object is being
+retrieved.</td>
+  </tr>
+</table>
+
+### SbBlitterGetSurfaceInfo
+
+**Description**
+
+Retrieves an SbBlitterSurfaceInfo structure, which describes immutable
+parameters of the `surface`, such as its width, height and pixel format.
+The results are set on the output parameter `surface_info`, which cannot
+be NULL.<br>
+The return value indicates whether the information was retrieved
+successfully.<br>
+This function is not thread-safe.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterGetSurfaceInfo(SbBlitterSurface surface,
+                                       SbBlitterSurfaceInfo* surface_info);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterSurface</code><br>
+        <code>surface</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterSurfaceInfo*</code><br>
+        <code>surface_info</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterIsContextValid
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE bool SbBlitterIsContextValid(
+    SbBlitterContext context) {
+  return context != kSbBlitterInvalidContext;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterContext</code><br>
+        <code>context</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterIsDeviceValid
+
+**Description**
+
+Helper functions to check whether or not a blitter object is invalid.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE bool SbBlitterIsDeviceValid(SbBlitterDevice device) {
+  return device != kSbBlitterInvalidDevice;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterDevice</code><br>
+        <code>device</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterIsPixelDataValid
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE bool SbBlitterIsPixelDataValid(
+    SbBlitterPixelData pixel_data) {
+  return pixel_data != kSbBlitterInvalidPixelData;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterPixelData</code><br>
+        <code>pixel_data</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterIsPixelFormatSupportedByDownloadSurfacePixels
+
+**Description**
+
+Indicates whether the combination of parameter values is valid for calls
+to <code><a href="#sbblitterdownloadsurfacepixels">SbBlitterDownloadSurfacePixels()</a></code>.<br>
+This function is not thread-safe.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterIsPixelFormatSupportedByDownloadSurfacePixels(
+    SbBlitterSurface surface,
+    SbBlitterPixelDataFormat pixel_format);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterSurface</code><br>        <code>surface</code></td>
+    <td>The surface being checked.</td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterPixelDataFormat</code><br>        <code>pixel_format</code></td>
+    <td>The pixel format that would be used on the surface.</td>
+  </tr>
+</table>
+
+### SbBlitterIsPixelFormatSupportedByPixelData
+
+**Description**
+
+Indicates whether `device` supports calls to <code><a href="#sbblittercreatepixeldata">SbBlitterCreatePixelData</a></code>
+with the specified `pixel_format`. This function is thread-safe.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterIsPixelFormatSupportedByPixelData(
+    SbBlitterDevice device,
+    SbBlitterPixelDataFormat pixel_format);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterDevice</code><br>        <code>device</code></td>
+    <td>The device for which compatibility is being checked.</td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterPixelDataFormat</code><br>        <code>pixel_format</code></td>
+    <td>The SbBlitterPixelDataFormat for which compatibility is
+being checked.</td>
+  </tr>
+</table>
+
+### SbBlitterIsRenderTargetValid
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE bool SbBlitterIsRenderTargetValid(
+    SbBlitterRenderTarget render_target) {
+  return render_target != kSbBlitterInvalidRenderTarget;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterRenderTarget</code><br>
+        <code>render_target</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterIsSurfaceFormatSupportedByRenderTargetSurface
+
+**Description**
+
+Indicates whether the `device` supports calls to
+SbBlitterCreateRenderTargetSurface() with `surface_format`.<br>
+This function is thread-safe.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterIsSurfaceFormatSupportedByRenderTargetSurface(
+    SbBlitterDevice device,
+    SbBlitterSurfaceFormat surface_format);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterDevice</code><br>        <code>device</code></td>
+    <td>The device being checked for compatibility.</td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterSurfaceFormat</code><br>        <code>surface_format</code></td>
+    <td>The surface format being checked for compatibility.</td>
+  </tr>
+</table>
+
+### SbBlitterIsSurfaceValid
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE bool SbBlitterIsSurfaceValid(
+    SbBlitterSurface surface) {
+  return surface != kSbBlitterInvalidSurface;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterSurface</code><br>
+        <code>surface</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterIsSwapChainValid
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE bool SbBlitterIsSwapChainValid(
+    SbBlitterSwapChain swap_chain) {
+  return swap_chain != kSbBlitterInvalidSwapChain;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterSwapChain</code><br>
+        <code>swap_chain</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterMakeRect
+
+**Description**
+
+Convenience function to setup a rectangle with the specified parameters.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE SbBlitterRect SbBlitterMakeRect(int x,
+                                                         int y,
+                                                         int width,
+                                                         int height) {
+  SbBlitterRect rect;
+  rect.x = x;
+  rect.y = y;
+  rect.width = width;
+  rect.height = height;
+  return rect;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>x</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>y</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>width</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>height</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterRFromColor
+
+**Description**
+
+The following helper functions can be used to extract specific color
+components from a SbBlitterColor object.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE uint8_t SbBlitterRFromColor(SbBlitterColor color) {
+  return (color & 0xFF000000) >> 24;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterColor</code><br>
+        <code>color</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterSetBlending
+
+**Description**
+
+Sets the blending state for the specified `context`. By default, blending
+is disabled on a SbBlitterContext.<br>
+This function is not thread-safe.<br>
+The return value indicates whether the blending state was set successfully.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterSetBlending(SbBlitterContext context, bool blending);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterContext</code><br>        <code>context</code></td>
+    <td>The context for which the blending state is being set.</td>
+  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>blending</code></td>
+    <td>The blending state for the <code>context</code>.
+If <code>blending</code> is <code>true</code>, the source alpha of subsequent draw calls
+is used to blend with the destination color. In particular,
+(<code>Fc = Sc * Sa + Dc * (1 - Sa)</code>), where:
+<ul><li><code>Fc</code> is the final color.
+</li><li><code>Sc</code> is the source color.
+</li><li><code>Sa</code> is the source alpha.
+</li><li><code>Dc</code> is the destination color.
+If <code>blending</code> is <code>false</code>, the source color and source alpha overwrite
+the destination color and alpha.</td>
+  </tr>
+</table>
+
+### SbBlitterSetColor
+
+**Description**
+
+Sets the context's current color.  The current color's default value is
+`SbBlitterColorFromRGBA(255, 255, 255 255)`.<br>
+The current color affects the fill rectangle's color in calls to
+SbBlitterFillRect(). If <code><a href="#sbblittersetmodulateblitswithcolor">SbBlitterSetModulateBlitsWithColor()</a></code> has been called
+to enable blit color modulation, the source blit surface pixel color is also
+modulated by the color before being output.<br>
+This function is not thread-safe.<br>
+The return value indicates whether the color was set successfully.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterSetColor(SbBlitterContext context,
+                                 SbBlitterColor color);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterContext</code><br>        <code>context</code></td>
+    <td>The context for which the color is being set.</td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterColor</code><br>        <code>color</code></td>
+    <td>The context's new color, specified in unpremultiplied alpha format.</td>
+  </tr>
+</table>
+
+### SbBlitterSetModulateBlitsWithColor
+
+**Description**
+
+Sets whether or not blit calls should have their source pixels modulated by
+the current color, which is set using <code><a href="#sbblittersetcolor">SbBlitterSetColor()</a></code>, before being
+output. This function can apply opacity to blit calls, color alpha-only
+surfaces, and apply other effects.<br>
+This function is not thread-safe.<br>
+The return value indicates whether the state was set successfully.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterSetModulateBlitsWithColor(
+    SbBlitterContext context,
+    bool modulate_blits_with_color);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterContext</code><br>        <code>context</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>modulate_blits_with_color</code></td>
+    <td>Indicates whether to modulate source pixels
+in blit calls.</td>
+  </tr>
+</table>
+
+### SbBlitterSetRenderTarget
+
+**Description**
+
+Sets up `render_target` as the render target that all subsequent draw calls
+made on `context` will use.<br>
+This function is not thread-safe.<br>
+The return value indicates whether the render target was set successfully.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterSetRenderTarget(SbBlitterContext context,
+                                        SbBlitterRenderTarget render_target);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterContext</code><br>        <code>context</code></td>
+    <td>The object for which the render target is being set.</td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterRenderTarget</code><br>        <code>render_target</code></td>
+    <td>The target that the <code>context</code> should use for draw calls.</td>
+  </tr>
+</table>
+
+### SbBlitterSetScissor
+
+**Description**
+
+Sets the scissor rectangle, which dictates a visibility area that affects
+all draw calls. Only pixels within the scissor rectangle are rendered, and
+all drawing outside of that area is clipped.<br>
+When <code><a href="#sbblittersetrendertarget">SbBlitterSetRenderTarget()</a></code> is called, that function automatically sets
+the scissor rectangle to the size of the specified render target. If a
+scissor rectangle is specified outside of the extents of the current render
+target bounds, it will be intersected with the render target bounds.<br>
+This function is not thread-safe.<br>
+Returns whether the scissor was successfully set. It returns an error if
+it is called before a render target has been specified for the context.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbBlitterSetScissor(SbBlitterContext context,
+                                   SbBlitterRect rect);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterContext</code><br>
+        <code>context</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbBlitterRect</code><br>
+        <code>rect</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbBlitterSurfaceFormat
+
+**Description**
+
+This function maps SbBlitterPixelDataFormat values to their corresponding
+SbBlitterSurfaceFormat value.  Note that many SbBlitterPixelDataFormats
+correspond to the same <code>SbBlitterSurfaceFormat</code>, so this function is not
+invertible.  When creating a SbBlitterSurface object from a
+SbBlitterPixelData object, the SbBlitterSurface's format will be computed
+from the SbBlitterPixelData object by using this function.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE SbBlitterSurfaceFormat
+SbBlitterPixelDataFormatToSurfaceFormat(SbBlitterPixelDataFormat pixel_format) {
+  switch (pixel_format) {
+    case kSbBlitterPixelDataFormatARGB8:
+      return kSbBlitterSurfaceFormatRGBA8;
+    case kSbBlitterPixelDataFormatBGRA8:
+      return kSbBlitterSurfaceFormatRGBA8;
+    case kSbBlitterPixelDataFormatRGBA8:
+      return kSbBlitterSurfaceFormatRGBA8;
+    case kSbBlitterPixelDataFormatA8:
+      return kSbBlitterSurfaceFormatA8;
+    default:
+      return kSbBlitterInvalidSurfaceFormat;
+  }
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbBlitterPixelDataFormatToSurfaceFormat(SbBlitterPixelDataFormat</code><br>
+        <code>pixel_format</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/byte_swap.md b/src/cobalt/site/docs/reference/starboard/modules/byte_swap.md
new file mode 100644
index 0000000..a85b79e
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/byte_swap.md
@@ -0,0 +1,196 @@
+---
+layout: doc
+title: "Starboard Module Reference: byte_swap.h"
+---
+
+Specifies functions for swapping byte order. These functions are used to
+deal with endianness when performing I/O.
+
+## Macros
+
+<div id="macro-documentation-section">
+
+<h3 id="sb_host_to_net_s16" class="small-h3">SB_HOST_TO_NET_S16</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_host_to_net_s32" class="small-h3">SB_HOST_TO_NET_S32</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_host_to_net_s64" class="small-h3">SB_HOST_TO_NET_S64</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_host_to_net_u16" class="small-h3">SB_HOST_TO_NET_U16</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_host_to_net_u32" class="small-h3">SB_HOST_TO_NET_U32</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_host_to_net_u64" class="small-h3">SB_HOST_TO_NET_U64</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_net_to_host_s16" class="small-h3">SB_NET_TO_HOST_S16</h3>
+
+<h3 id="sb_net_to_host_s32" class="small-h3">SB_NET_TO_HOST_S32</h3>
+
+<h3 id="sb_net_to_host_s64" class="small-h3">SB_NET_TO_HOST_S64</h3>
+
+<h3 id="sb_net_to_host_u16" class="small-h3">SB_NET_TO_HOST_U16</h3>
+
+<h3 id="sb_net_to_host_u32" class="small-h3">SB_NET_TO_HOST_U32</h3>
+
+<h3 id="sb_net_to_host_u64" class="small-h3">SB_NET_TO_HOST_U64</h3>
+
+</div>
+
+## Functions
+
+### SbByteSwapS16
+
+**Description**
+
+Unconditionally swaps the byte order in signed 16-bit `value`.
+
+**Declaration**
+
+```
+SB_EXPORT int16_t SbByteSwapS16(int16_t value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int16_t</code><br>        <code>value</code></td>
+    <td>The value for which the byte order will be swapped.</td>
+  </tr>
+</table>
+
+### SbByteSwapS32
+
+**Description**
+
+Unconditionally swaps the byte order in signed 32-bit `value`.
+
+**Declaration**
+
+```
+SB_EXPORT int32_t SbByteSwapS32(int32_t value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int32_t</code><br>        <code>value</code></td>
+    <td>The value for which the byte order will be swapped.</td>
+  </tr>
+</table>
+
+### SbByteSwapS64
+
+**Description**
+
+Unconditionally swaps the byte order in signed 64-bit `value`.
+
+**Declaration**
+
+```
+SB_EXPORT int64_t SbByteSwapS64(int64_t value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int64_t</code><br>        <code>value</code></td>
+    <td>The value for which the byte order will be swapped.</td>
+  </tr>
+</table>
+
+### SbByteSwapU16
+
+**Description**
+
+Unconditionally swaps the byte order in unsigned 16-bit `value`.
+
+**Declaration**
+
+```
+SB_EXPORT uint16_t SbByteSwapU16(uint16_t value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>uint16_t</code><br>        <code>value</code></td>
+    <td>The value for which the byte order will be swapped.</td>
+  </tr>
+</table>
+
+### SbByteSwapU32
+
+**Description**
+
+Unconditionally swaps the byte order in unsigned 32-bit `value`.
+
+**Declaration**
+
+```
+SB_EXPORT uint32_t SbByteSwapU32(uint32_t value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>uint32_t</code><br>        <code>value</code></td>
+    <td>The value for which the byte order will be swapped.</td>
+  </tr>
+</table>
+
+### SbByteSwapU64
+
+**Description**
+
+Unconditionally swaps the byte order in unsigned 64-bit `value`.
+
+**Declaration**
+
+```
+SB_EXPORT uint64_t SbByteSwapU64(uint64_t value);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>uint64_t</code><br>        <code>value</code></td>
+    <td>The value for which the byte order will be swapped.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/character.md b/src/cobalt/site/docs/reference/starboard/modules/character.md
new file mode 100644
index 0000000..ac32c01
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/character.md
@@ -0,0 +1,321 @@
+---
+layout: doc
+title: "Starboard Module Reference: character.h"
+---
+
+Provides functions for interacting with characters.
+
+## Functions
+
+### SbCharacterIsAlphanumeric
+
+**Description**
+
+Indicates whether the given 8-bit character `c` (as an int) is alphanumeric
+in the current locale.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbCharacterIsAlphanumeric-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbCharacterIsAlphanumeric-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbCharacterIsAlphanumeric-declaration">
+<pre>
+SB_EXPORT bool SbCharacterIsAlphanumeric(int c);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbCharacterIsAlphanumeric-stub">
+
+```
+#include "starboard/character.h"
+
+bool SbCharacterIsAlphanumeric(int /*c*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>c</code></td>
+    <td>The character to be evaluated.</td>
+  </tr>
+</table>
+
+### SbCharacterIsDigit
+
+**Description**
+
+Indicates whether the given 8-bit character `c` (as an int) is a
+decimal digit in the current locale.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbCharacterIsDigit-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbCharacterIsDigit-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbCharacterIsDigit-declaration">
+<pre>
+SB_EXPORT bool SbCharacterIsDigit(int c);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbCharacterIsDigit-stub">
+
+```
+#include "starboard/character.h"
+
+bool SbCharacterIsDigit(int /*c*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>c</code></td>
+    <td>The character to be evaluated.</td>
+  </tr>
+</table>
+
+### SbCharacterIsHexDigit
+
+**Description**
+
+Indicates whether the given 8-bit character `c` (as an int) is a hexadecimal
+in the current locale.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbCharacterIsHexDigit-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbCharacterIsHexDigit-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbCharacterIsHexDigit-declaration">
+<pre>
+SB_EXPORT bool SbCharacterIsHexDigit(int c);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbCharacterIsHexDigit-stub">
+
+```
+#include "starboard/character.h"
+
+bool SbCharacterIsHexDigit(int /*c*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>c</code></td>
+    <td>The character to be evaluated.</td>
+  </tr>
+</table>
+
+### SbCharacterIsSpace
+
+**Description**
+
+Indicates whether the given 8-bit character `c` (as an int) is a space in
+the current locale.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbCharacterIsSpace-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbCharacterIsSpace-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbCharacterIsSpace-declaration">
+<pre>
+SB_EXPORT bool SbCharacterIsSpace(int c);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbCharacterIsSpace-stub">
+
+```
+#include "starboard/character.h"
+
+bool SbCharacterIsSpace(int /*c*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>c</code></td>
+    <td>The character to be evaluated.</td>
+  </tr>
+</table>
+
+### SbCharacterIsUpper
+
+**Description**
+
+Indicates whether the given 8-bit character `c` (as an int) is uppercase
+in the current locale.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbCharacterIsUpper-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbCharacterIsUpper-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbCharacterIsUpper-declaration">
+<pre>
+SB_EXPORT bool SbCharacterIsUpper(int c);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbCharacterIsUpper-stub">
+
+```
+#include "starboard/character.h"
+
+bool SbCharacterIsUpper(int /*c*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>c</code></td>
+    <td>The character to be evaluated.</td>
+  </tr>
+</table>
+
+### SbCharacterToLower
+
+**Description**
+
+Converts the given 8-bit character (as an int) to lowercase in the current
+locale and returns an 8-bit character. If there is no lowercase version of
+the character, or the character is already lowercase, the function just
+returns the character as-is.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbCharacterToLower-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbCharacterToLower-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbCharacterToLower-declaration">
+<pre>
+SB_EXPORT int SbCharacterToLower(int c);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbCharacterToLower-stub">
+
+```
+#include "starboard/character.h"
+
+int SbCharacterToLower(int c) {
+  return c;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>c</code></td>
+    <td>The character to be converted.</td>
+  </tr>
+</table>
+
+### SbCharacterToUpper
+
+**Description**
+
+Converts the given 8-bit character (as an int) to uppercase in the current
+locale and returns an 8-bit character. If there is no uppercase version of
+the character, or the character is already uppercase, the function just
+returns the character as-is.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbCharacterToUpper-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbCharacterToUpper-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbCharacterToUpper-declaration">
+<pre>
+SB_EXPORT int SbCharacterToUpper(int c);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbCharacterToUpper-stub">
+
+```
+#include "starboard/character.h"
+
+int SbCharacterToUpper(int c) {
+  return c;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>c</code></td>
+    <td>The character to be converted.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/condition_variable.md b/src/cobalt/site/docs/reference/starboard/modules/condition_variable.md
new file mode 100644
index 0000000..5556d60
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/condition_variable.md
@@ -0,0 +1,352 @@
+---
+layout: doc
+title: "Starboard Module Reference: condition_variable.h"
+---
+
+Defines an interface for condition variables.
+
+## Enums
+
+### SbConditionVariableResult
+
+Enumeration of possible results from waiting on a condvar.
+
+**Values**
+
+*   `kSbConditionVariableSignaled` - The wait completed because the condition variable was signaled.
+*   `kSbConditionVariableTimedOut` - The wait completed because it timed out, and was not signaled.
+*   `kSbConditionVariableFailed` - The wait failed, either because a parameter wasn't valid, or the conditionvariable has already been destroyed, or something similar.
+
+## Functions
+
+### SbConditionVariableBroadcast
+
+**Description**
+
+Broadcasts to all current waiters of `condition` to stop waiting. This
+function wakes all of the threads waiting on `condition` while
+SbConditionVariableSignal wakes a single thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbConditionVariableBroadcast-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbConditionVariableBroadcast-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbConditionVariableBroadcast-declaration">
+<pre>
+SB_EXPORT bool SbConditionVariableBroadcast(SbConditionVariable* condition);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbConditionVariableBroadcast-stub">
+
+```
+#include "starboard/condition_variable.h"
+
+bool SbConditionVariableBroadcast(SbConditionVariable* /*condition*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbConditionVariable*</code><br>        <code>condition</code></td>
+    <td>The condition that should no longer be waited for.</td>
+  </tr>
+</table>
+
+### SbConditionVariableCreate
+
+**Description**
+
+Creates a new condition variable to work with `opt_mutex`, which may be null,
+placing the newly created condition variable in `out_condition`.<br>
+The return value indicates whether the condition variable could be created.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbConditionVariableCreate-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbConditionVariableCreate-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbConditionVariableCreate-declaration">
+<pre>
+SB_EXPORT bool SbConditionVariableCreate(SbConditionVariable* out_condition,
+                                         SbMutex* opt_mutex);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbConditionVariableCreate-stub">
+
+```
+#include "starboard/condition_variable.h"
+
+bool SbConditionVariableCreate(SbConditionVariable* /*out_condition*/,
+                               SbMutex* /*opt_mutex*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbConditionVariable*</code><br>
+        <code>out_condition</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbMutex*</code><br>
+        <code>opt_mutex</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbConditionVariableDestroy
+
+**Description**
+
+Destroys the specified SbConditionVariable. The return value indicates
+whether the destruction was successful. The behavior is undefined if other
+threads are currently waiting on this condition variable.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbConditionVariableDestroy-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbConditionVariableDestroy-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbConditionVariableDestroy-declaration">
+<pre>
+SB_EXPORT bool SbConditionVariableDestroy(SbConditionVariable* condition);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbConditionVariableDestroy-stub">
+
+```
+#include "starboard/condition_variable.h"
+
+bool SbConditionVariableDestroy(SbConditionVariable* /*condition*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbConditionVariable*</code><br>        <code>condition</code></td>
+    <td>The SbConditionVariable to be destroyed. This invalidates the
+condition variable.</td>
+  </tr>
+</table>
+
+### SbConditionVariableIsSignaled
+
+**Description**
+
+Returns whether the given result is a success.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbConditionVariableIsSignaled(
+    SbConditionVariableResult result) {
+  return result == kSbConditionVariableSignaled;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbConditionVariableResult</code><br>
+        <code>result</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbConditionVariableSignal
+
+**Description**
+
+Signals the next waiter of `condition` to stop waiting. This function wakes
+a single thread waiting on `condition` while <code><a href="#sbconditionvariablebroadcast">SbConditionVariableBroadcast</a></code>
+wakes all threads waiting on it.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbConditionVariableSignal-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbConditionVariableSignal-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbConditionVariableSignal-declaration">
+<pre>
+SB_EXPORT bool SbConditionVariableSignal(SbConditionVariable* condition);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbConditionVariableSignal-stub">
+
+```
+#include "starboard/condition_variable.h"
+
+bool SbConditionVariableSignal(SbConditionVariable* /*condition*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbConditionVariable*</code><br>        <code>condition</code></td>
+    <td>The condition that the waiter should stop waiting for.</td>
+  </tr>
+</table>
+
+### SbConditionVariableWait
+
+**Description**
+
+Waits for `condition`, releasing the held lock `mutex`, blocking
+indefinitely, and returning the result. Behavior is undefined if `mutex` is
+not held.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbConditionVariableWait-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbConditionVariableWait-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbConditionVariableWait-declaration">
+<pre>
+SB_EXPORT SbConditionVariableResult
+SbConditionVariableWait(SbConditionVariable* condition, SbMutex* mutex);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbConditionVariableWait-stub">
+
+```
+#include "starboard/condition_variable.h"
+
+SbConditionVariableResult SbConditionVariableWait(
+    SbConditionVariable* /*condition*/,
+    SbMutex* /*mutex*/) {
+  return kSbConditionVariableFailed;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbConditionVariable*</code><br>
+        <code>condition</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbMutex*</code><br>
+        <code>mutex</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbConditionVariableWaitTimed
+
+**Description**
+
+Waits for `condition`, releasing the held lock `mutex`, blocking up to
+`timeout_duration`, and returning the acquisition result. Behavior is
+undefined if `mutex` is not held.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbConditionVariableWaitTimed-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbConditionVariableWaitTimed-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbConditionVariableWaitTimed-declaration">
+<pre>
+SB_EXPORT SbConditionVariableResult
+SbConditionVariableWaitTimed(SbConditionVariable* condition,
+                             SbMutex* mutex,
+                             SbTime timeout_duration);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbConditionVariableWaitTimed-stub">
+
+```
+#include "starboard/condition_variable.h"
+
+SbConditionVariableResult SbConditionVariableWaitTimed(
+    SbConditionVariable* /*condition*/,
+    SbMutex* /*mutex*/,
+    SbTime /*timeout*/) {
+  return kSbConditionVariableFailed;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbConditionVariable*</code><br>        <code>condition</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>SbMutex*</code><br>        <code>mutex</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>SbTime</code><br>        <code>timeout_duration</code></td>
+    <td>The maximum amount of time that function should wait
+for <code>condition</code>. If the <code>timeout_duration</code> value is less than or equal to
+zero, the function returns as quickly as possible with a
+kSbConditionVariableTimedOut result.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/configuration.md b/src/cobalt/site/docs/reference/starboard/modules/configuration.md
new file mode 100644
index 0000000..32576c8
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/configuration.md
@@ -0,0 +1,259 @@
+---
+layout: doc
+title: "Starboard Module Reference: configuration.h"
+---
+
+Provides a description of the current platform in lurid detail so that
+common code never needs to actually know what the current operating system
+and architecture are.<br>
+It is both very pragmatic and canonical in that if any application code
+finds itself needing to make a platform decision, it should always define
+a Starboard Configuration feature instead. This implies the continued
+existence of very narrowly-defined configuration features, but it retains
+porting control in Starboard.
+
+## Macros
+
+<div id="macro-documentation-section">
+
+<h3 id="sb_alignas" class="small-h3">SB_ALIGNAS</h3>
+
+Specifies the alignment for a class, struct, union, enum, class/struct field,
+or stack variable.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_alignof" class="small-h3">SB_ALIGNOF</h3>
+
+Returns the alignment reqiured for any instance of the type indicated by
+`type`.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_array_size" class="small-h3">SB_ARRAY_SIZE</h3>
+
+A constant expression that evaluates to the size_t size of a statically-sized
+array.
+
+<h3 id="sb_array_size_int" class="small-h3">SB_ARRAY_SIZE_INT</h3>
+
+A constant expression that evaluates to the int size of a statically-sized
+array.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_can" class="small-h3">SB_CAN</h3>
+
+Determines a compile-time capability of the system.
+
+<h3 id="sb_can_media_use_starboard_pipeline" class="small-h3">SB_CAN_MEDIA_USE_STARBOARD_PIPELINE</h3>
+
+Specifies whether the starboard media pipeline components (SbPlayerPipeline
+and StarboardDecryptor) are used.  Set to 0 means they are not used.
+
+<h3 id="sb_compile_assert" class="small-h3">SB_COMPILE_ASSERT</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_deprecated" class="small-h3">SB_DEPRECATED</h3>
+
+SB_DEPRECATED(int Foo(int bar));
+Annotates the function as deprecated, which will trigger a compiler
+warning when referenced.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_deprecated_external" class="small-h3">SB_DEPRECATED_EXTERNAL</h3>
+
+SB_DEPRECATED_EXTERNAL(...) annotates the function as deprecated for
+external clients, but not deprecated for starboard.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_disallow_copy_and_assign" class="small-h3">SB_DISALLOW_COPY_AND_ASSIGN</h3>
+
+A macro to disallow the copy constructor and operator= functions
+This should be used in the private: declarations for a class
+
+<h3 id="sb_experimental_api_version" class="small-h3">SB_EXPERIMENTAL_API_VERSION</h3>
+
+The API version that is currently open for changes, and therefore is not
+stable or frozen. Production-oriented ports should avoid declaring that they
+implement the experimental Starboard API version.
+
+<h3 id="sb_false" class="small-h3">SB_FALSE</h3>
+
+<h3 id="sb_function" class="small-h3">SB_FUNCTION</h3>
+
+Whether we use __PRETTY_FUNCTION__ or __FUNCTION__ for logging.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_has" class="small-h3">SB_HAS</h3>
+
+Determines at compile-time whether this platform has a standard feature or
+header available.
+
+<h3 id="sb_has_64_bit_atomics" class="small-h3">SB_HAS_64_BIT_ATOMICS</h3>
+
+Whether the current platform has 64-bit atomic operations.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_has_gles2" class="small-h3">SB_HAS_GLES2</h3>
+
+Specifies whether this platform has a performant OpenGL ES 2 implementation,
+which allows client applications to use GL rendering paths.  Derived from
+the gyp variable 'gl_type' which indicates what kind of GL implementation
+is available.
+
+<h3 id="sb_has_graphics" class="small-h3">SB_HAS_GRAPHICS</h3>
+
+Specifies whether this platform has any kind of supported graphics system.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_has_quirk" class="small-h3">SB_HAS_QUIRK</h3>
+
+Determines at compile-time whether this platform has a quirk.
+
+<h3 id="sb_int64_c" class="small-h3">SB_INT64_C</h3>
+
+Declare numeric literals of signed 64-bit type.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_is" class="small-h3">SB_IS</h3>
+
+Determines at compile-time an inherent aspect of this platform.
+
+<h3 id="sb_is_compiler_gcc" class="small-h3">SB_IS_COMPILER_GCC</h3>
+
+<h3 id="sb_is_compiler_msvc" class="small-h3">SB_IS_COMPILER_MSVC</h3>
+
+<h3 id="sb_is_little_endian" class="small-h3">SB_IS_LITTLE_ENDIAN</h3>
+
+Whether the current platform is little endian.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_likely" class="small-h3">SB_LIKELY</h3>
+
+Macro for hinting that an expression is likely to be true.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_maximum_api_version" class="small-h3">SB_MAXIMUM_API_VERSION</h3>
+
+The maximum API version allowed by this version of the Starboard headers,
+inclusive.
+
+<h3 id="sb_minimum_api_version" class="small-h3">SB_MINIMUM_API_VERSION</h3>
+
+The minimum API version allowed by this version of the Starboard headers,
+inclusive.
+
+<h3 id="sb_my_experimental_feature_version" class="small-h3">SB_MY_EXPERIMENTAL_FEATURE_VERSION</h3>
+
+EXAMPLE:
+// Introduce new experimental feature.
+//   Add a function, `SbMyNewFeature()` to `starboard/feature.h` which
+//   exposes functionality for my new feature.
+
+<h3 id="sb_noreturn" class="small-h3">SB_NORETURN</h3>
+
+Macro to annotate a function as noreturn, which signals to the compiler
+that the function cannot return.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_override" class="small-h3">SB_OVERRIDE</h3>
+
+Declares a function as overriding a virtual function on compilers that
+support it.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_player_with_url_api_version" class="small-h3">SB_PLAYER_WITH_URL_API_VERSION</h3>
+
+<h3 id="sb_preferred_rgba_byte_order_argb" class="small-h3">SB_PREFERRED_RGBA_BYTE_ORDER_ARGB</h3>
+
+An enumeration of values for the SB_PREFERRED_RGBA_BYTE_ORDER configuration
+variable.  Setting this up properly means avoiding slow color swizzles when
+passing pixel data from one library to another.  Note that these definitions
+are in byte-order and so are endianness-independent.
+
+<h3 id="sb_preferred_rgba_byte_order_bgra" class="small-h3">SB_PREFERRED_RGBA_BYTE_ORDER_BGRA</h3>
+
+An enumeration of values for the SB_PREFERRED_RGBA_BYTE_ORDER configuration
+variable.  Setting this up properly means avoiding slow color swizzles when
+passing pixel data from one library to another.  Note that these definitions
+are in byte-order and so are endianness-independent.
+
+<h3 id="sb_preferred_rgba_byte_order_rgba" class="small-h3">SB_PREFERRED_RGBA_BYTE_ORDER_RGBA</h3>
+
+An enumeration of values for the SB_PREFERRED_RGBA_BYTE_ORDER configuration
+variable.  Setting this up properly means avoiding slow color swizzles when
+passing pixel data from one library to another.  Note that these definitions
+are in byte-order and so are endianness-independent.
+
+<h3 id="sb_printf_format" class="small-h3">SB_PRINTF_FORMAT</h3>
+
+Tells the compiler a function is using a printf-style format string.
+`format_param` is the one-based index of the format string parameter;
+`dots_param` is the one-based index of the "..." parameter.
+For v*printf functions (which take a va_list), pass 0 for dots_param.
+(This is undocumented but matches what the system C headers do.)
+(Partially taken from base/compiler_specific.h)
+
+<h3 id="sb_release_candidate_api_version" class="small-h3">SB_RELEASE_CANDIDATE_API_VERSION</h3>
+
+The next API version to be frozen, but is still subject to emergency
+changes. It is reasonable to base a port on the Release Candidate API
+version, but be aware that small incompatible changes may still be made to
+it.
+The following will be uncommented when an API version is a release candidate.
+
+<h3 id="sb_restrict" class="small-h3">SB_RESTRICT</h3>
+
+Makes a pointer-typed parameter restricted so that the compiler can make
+certain optimizations because it knows the pointers are unique.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_stringify" class="small-h3">SB_STRINGIFY</h3>
+
+Standard CPP trick to stringify an evaluated macro definition.
+
+<h3 id="sb_stringify2" class="small-h3">SB_STRINGIFY2</h3>
+
+Standard CPP trick to stringify an evaluated macro definition.
+
+<h3 id="sb_true" class="small-h3">SB_TRUE</h3>
+
+<h3 id="sb_uint64_c" class="small-h3">SB_UINT64_C</h3>
+
+Declare numeric literals of unsigned 64-bit type.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_unlikely" class="small-h3">SB_UNLIKELY</h3>
+
+Macro for hinting that an expression is likely to be false.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_unreferenced_parameter" class="small-h3">SB_UNREFERENCED_PARAMETER</h3>
+
+Trivially references a parameter that is otherwise unreferenced, preventing a
+compiler warning on some platforms.
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_warn_unused_result" class="small-h3">SB_WARN_UNUSED_RESULT</h3>
+
+Causes the annotated (at the end) function to generate a warning if the
+result is not accessed.
+
+</div>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/cryptography.md b/src/cobalt/site/docs/reference/starboard/modules/cryptography.md
new file mode 100644
index 0000000..e4577d4
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/cryptography.md
@@ -0,0 +1,525 @@
+---
+layout: doc
+title: "Starboard Module Reference: cryptography.h"
+---
+
+Hardware-accelerated cryptography. Platforms should **only** implement this
+when there are **hardware-accelerated** cryptography facilities. Applications
+must fall back to platform-independent CPU-based algorithms if the cipher
+algorithm isn't supported in hardware.<br>
+# Tips for Porters<br>
+You should implement cipher algorithms in this descending order of priority
+to maximize usage for SSL.<br>
+<ol><li>GCM - The preferred block cipher mode for OpenSSL, mainly due to speed.
+</li><li>CTR - This can be used internally with GCM, as long as the CTR
+implementation only uses the last 4 bytes of the IV for the
+counter. (i.e. 96-bit IV, 32-bit counter)
+</li><li>ECB - This can be used (with a null IV) with any of the other cipher
+block modes to accelerate the core AES algorithm if none of the
+streaming modes can be accelerated.
+</li><li>CBC - GCM is always preferred if the server and client both support
+it. If not, they will generally negotiate down to AES-CBC. If this
+happens, and CBC is supported by SbCryptography, then it will be
+accelerated appropriately. But, most servers should support GCM,
+so it is not likely to come up much, which is why it is the lowest
+priority.</li></ol>
+Further reading on block cipher modes:
+https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
+https://crbug.com/442572
+https://crypto.stackexchange.com/questions/10775/practical-disadvantages-of-gcm-mode-encryption
+
+## Enums
+
+### SbCryptographyBlockCipherMode
+
+The method of chaining encrypted blocks in a sequence.
+https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
+
+**Values**
+
+*   `kSbCryptographyBlockCipherModeCbc` - Cipher Block Chaining mode.
+*   `kSbCryptographyBlockCipherModeCfb` - Cipher Feedback mode.
+*   `kSbCryptographyBlockCipherModeCtr` - Counter mode: A nonce is combined with an increasing counter.
+*   `kSbCryptographyBlockCipherModeEcb` - Electronic Code Book mode: No chaining.
+*   `kSbCryptographyBlockCipherModeOfb` - Output Feedback mode.
+*   `kSbCryptographyBlockCipherModeGcm` - Galois/Counter Mode.
+
+### SbCryptographyDirection
+
+The direction of a cryptographic transformation.
+
+**Values**
+
+*   `kSbCryptographyDirectionEncode` - Cryptographic transformations that encode/encrypt data into atarget format.
+*   `kSbCryptographyDirectionDecode` - Cryptographic transformations that decode/decrypt data intoits original form.
+
+## Functions
+
+### SbCryptographyCreateTransformer
+
+**Description**
+
+Creates an <code><a href="#sbcryptographytransform">SbCryptographyTransform</a></code>er with the given initialization
+data. It can then be used to transform a series of data blocks.
+Returns kSbCryptographyInvalidTransformer if the algorithm isn't
+supported, or if the parameters are not compatible with the
+algorithm.<br>
+An <code><a href="#sbcryptographytransform">SbCryptographyTransform</a></code>er contains all state to start decrypting
+a sequence of cipher blocks according to the cipher block mode. It
+is not thread-safe, but implementations must allow different
+SbCryptographyTransformer instances to operate on different threads.<br>
+All parameters must not be assumed to live longer than the call to
+this function. They must be copied by the implementation to be
+retained.<br>
+This function determines success mainly based on whether the combination of
+`algorithm`, `direction`, `block_size_bits`, and `mode` is supported and
+whether all the sizes passed in are sufficient for the selected
+parameters. In particular, this function cannot verify that the key and IV
+used were correct for the ciphertext, were it to be used in the decode
+direction. The caller must make that verification.<br>
+For example, to decrypt AES-128-CTR:
+SbCryptographyCreateTransformer(kSbCryptographyAlgorithmAes, 128,
+kSbCryptographyDirectionDecode,
+kSbCryptographyBlockCipherModeCtr,
+...);
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbCryptographyCreateTransformer-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbCryptographyCreateTransformer-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbCryptographyCreateTransformer-declaration">
+<pre>
+SB_EXPORT SbCryptographyTransformer
+SbCryptographyCreateTransformer(const char* algorithm,
+                                int block_size_bits,
+                                SbCryptographyDirection direction,
+                                SbCryptographyBlockCipherMode mode,
+                                const void* initialization_vector,
+                                int initialization_vector_size,
+                                const void* key,
+                                int key_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbCryptographyCreateTransformer-stub">
+
+```
+#include "starboard/configuration.h"
+#include "starboard/cryptography.h"
+
+SbCryptographyTransformer SbCryptographyCreateTransformer(
+    const char* algorithm,
+    int block_size_bits,
+    SbCryptographyDirection direction,
+    SbCryptographyBlockCipherMode mode,
+    const void* initialization_vector,
+    int initialization_vector_size,
+    const void* key,
+    int key_size) {
+  SB_UNREFERENCED_PARAMETER(algorithm);
+  SB_UNREFERENCED_PARAMETER(block_size_bits);
+  SB_UNREFERENCED_PARAMETER(direction);
+  SB_UNREFERENCED_PARAMETER(mode);
+  SB_UNREFERENCED_PARAMETER(initialization_vector);
+  SB_UNREFERENCED_PARAMETER(initialization_vector_size);
+  SB_UNREFERENCED_PARAMETER(key);
+  SB_UNREFERENCED_PARAMETER(key_size);
+  return kSbCryptographyInvalidTransformer;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>algorithm</code></td>
+    <td>A string that represents the cipher algorithm.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>block_size_bits</code></td>
+    <td>The block size variant of the algorithm to use, in bits.</td>
+  </tr>
+  <tr>
+    <td><code>SbCryptographyDirection</code><br>        <code>direction</code></td>
+    <td>The direction in which to transform the data.</td>
+  </tr>
+  <tr>
+    <td><code>SbCryptographyBlockCipherMode</code><br>        <code>mode</code></td>
+    <td>The block cipher mode to use.</td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>initialization_vector</code></td>
+    <td>The Initialization Vector (IV) to use. May be NULL
+for block cipher modes that don't use it, or don't set it at init time.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>initialization_vector_size</code></td>
+    <td>The size, in bytes, of the IV.</td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>key</code></td>
+    <td>The key to use for this transformation.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>key_size</code></td>
+    <td>The size, in bytes, of the key.</td>
+  </tr>
+</table>
+
+### SbCryptographyDestroyTransformer
+
+**Description**
+
+Destroys the given `transformer` instance.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbCryptographyDestroyTransformer-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbCryptographyDestroyTransformer-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbCryptographyDestroyTransformer-declaration">
+<pre>
+SB_EXPORT void SbCryptographyDestroyTransformer(
+    SbCryptographyTransformer transformer);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbCryptographyDestroyTransformer-stub">
+
+```
+#include "starboard/configuration.h"
+#include "starboard/cryptography.h"
+
+void SbCryptographyDestroyTransformer(SbCryptographyTransformer transformer) {
+  SB_UNREFERENCED_PARAMETER(transformer);
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbCryptographyTransformer</code><br>
+        <code>transformer</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbCryptographyGetTag
+
+**Description**
+
+Calculates the authenticator tag for a transformer and places up to
+`out_tag_size` bytes of it in `out_tag`. Returns whether it was able to get
+the tag, which mainly has to do with whether it is compatible with the
+current block cipher mode.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbCryptographyGetTag-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbCryptographyGetTag-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbCryptographyGetTag-declaration">
+<pre>
+SB_EXPORT bool SbCryptographyGetTag(
+    SbCryptographyTransformer transformer,
+    void* out_tag,
+    int out_tag_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbCryptographyGetTag-stub">
+
+```
+#include "starboard/configuration.h"
+#include "starboard/cryptography.h"
+
+bool SbCryptographyGetTag(
+    SbCryptographyTransformer transformer,
+    void* out_tag,
+    int out_tag_size) {
+  SB_UNREFERENCED_PARAMETER(transformer);
+  SB_UNREFERENCED_PARAMETER(out_tag);
+  SB_UNREFERENCED_PARAMETER(out_tag_size);
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbCryptographyTransformer</code><br>
+        <code>transformer</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>
+        <code>out_tag</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>out_tag_size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbCryptographyIsTransformerValid
+
+**Description**
+
+Returns whether the given transformer handle is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbCryptographyIsTransformerValid(
+    SbCryptographyTransformer transformer) {
+  return transformer != kSbCryptographyInvalidTransformer;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbCryptographyTransformer</code><br>
+        <code>transformer</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbCryptographySetAuthenticatedData
+
+**Description**
+
+Sets additional authenticated data (AAD) for a transformer, for chaining
+modes that support it (GCM). Returns whether the data was successfully
+set. This can fail if the chaining mode doesn't support AAD, if the
+parameters are invalid, or if the internal state is invalid for setting AAD.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbCryptographySetAuthenticatedData-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbCryptographySetAuthenticatedData-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbCryptographySetAuthenticatedData-declaration">
+<pre>
+SB_EXPORT bool SbCryptographySetAuthenticatedData(
+    SbCryptographyTransformer transformer,
+    const void* data,
+    int data_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbCryptographySetAuthenticatedData-stub">
+
+```
+#include "starboard/configuration.h"
+#include "starboard/cryptography.h"
+
+bool SbCryptographySetAuthenticatedData(
+    SbCryptographyTransformer transformer,
+    const void* data,
+    int data_size) {
+  SB_UNREFERENCED_PARAMETER(transformer);
+  SB_UNREFERENCED_PARAMETER(data);
+  SB_UNREFERENCED_PARAMETER(data_size);
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbCryptographyTransformer</code><br>
+        <code>transformer</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>
+        <code>data</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>data_size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbCryptographySetInitializationVector
+
+**Description**
+
+Sets the initialization vector (IV) for a transformer, replacing the
+internally-set IV. The block cipher mode algorithm will update the IV
+appropriately after every block, so this is not necessary unless the stream
+is discontiguous in some way. This happens with AES-GCM in TLS.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbCryptographySetInitializationVector-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbCryptographySetInitializationVector-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbCryptographySetInitializationVector-declaration">
+<pre>
+SB_EXPORT void SbCryptographySetInitializationVector(
+    SbCryptographyTransformer transformer,
+    const void* initialization_vector,
+    int initialization_vector_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbCryptographySetInitializationVector-stub">
+
+```
+#include "starboard/configuration.h"
+#include "starboard/cryptography.h"
+
+void SbCryptographySetInitializationVector(
+    SbCryptographyTransformer transformer,
+    const void* initialization_vector,
+    int initialization_vector_size) {
+  SB_UNREFERENCED_PARAMETER(transformer);
+  SB_UNREFERENCED_PARAMETER(initialization_vector);
+  SB_UNREFERENCED_PARAMETER(initialization_vector_size);
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbCryptographyTransformer</code><br>
+        <code>transformer</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>
+        <code>initialization_vector</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>initialization_vector_size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbCryptographyTransform
+
+**Description**
+
+Transforms one or more `block_size_bits`-sized blocks of `in_data`, with the
+given `transformer`, placing the result in `out_data`. Returns the number of
+bytes that were written to `out_data`, unless there was an error, in which
+case it will return a negative number.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbCryptographyTransform-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbCryptographyTransform-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbCryptographyTransform-declaration">
+<pre>
+SB_EXPORT int SbCryptographyTransform(
+    SbCryptographyTransformer transformer,
+    const void* in_data,
+    int in_data_size,
+    void* out_data);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbCryptographyTransform-stub">
+
+```
+#include "starboard/configuration.h"
+#include "starboard/cryptography.h"
+
+int SbCryptographyTransform(SbCryptographyTransformer transformer,
+                            const void* in_data,
+                            int in_data_size,
+                            void* out_data) {
+  SB_UNREFERENCED_PARAMETER(transformer);
+  SB_UNREFERENCED_PARAMETER(in_data);
+  SB_UNREFERENCED_PARAMETER(in_data_size);
+  SB_UNREFERENCED_PARAMETER(out_data);
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbCryptographyTransformer</code><br>        <code>transformer</code></td>
+    <td>A transformer initialized with an algorithm, IV, cipherkey,
+and so on.</td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>in_data</code></td>
+    <td>The data to be transformed.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>in_data_size</code></td>
+    <td>The size of the data to be transformed, in bytes. Must be a
+multiple of the transformer's <code>block-size_bits</code>, or an error will be
+returned.</td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>        <code>out_data</code></td>
+    <td>A buffer where the transformed data should be placed. Must have
+at least capacity for <code>in_data_size</code> bytes. May point to the same memory as
+<code>in_data</code>.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/decode_target.md b/src/cobalt/site/docs/reference/starboard/modules/decode_target.md
new file mode 100644
index 0000000..65cb112
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/decode_target.md
@@ -0,0 +1,524 @@
+---
+layout: doc
+title: "Starboard Module Reference: decode_target.h"
+---
+
+A target for decoding image and video data into. This corresponds roughly to
+an EGLImage, but that extension may not be fully supported on all GL
+platforms. SbDecodeTarget supports multi-plane targets. The SbBlitter API is
+supported as well, and this is able to more-or-less unify the two.<br>
+An SbDecodeTarget can be passed into any function which decodes video or
+image data. This allows the application to allocate fast graphics memory, and
+have decoding done directly into this memory, avoiding unnecessary memory
+copies, and also avoiding pushing data between CPU and GPU memory
+unnecessarily.<br>
+#### SbDecodeTargetFormat
+
+
+SbDecodeTargets support several different formats that can be used to decode
+into and render from. Some formats may be easier to decode into, and others
+may be easier to render. Some may take less memory. Each decoder needs to
+support the SbDecodeTargetFormat passed into it, or the decode will produce
+an error. Each decoder provides a way to check if a given
+SbDecodeTargetFormat is supported by that decoder.<br>
+#### SbDecodeTargetGraphicsContextProvider
+
+
+Some components may need to acquire SbDecodeTargets compatible with a certain
+rendering context, which may need to be created on a particular thread. The
+SbDecodeTargetGraphicsContextProvider are passed in to the Starboard
+implementation from the application and provide information about the
+rendering context that will be used to render the SbDecodeTarget objects.
+For GLES renderers, it also provides functionality to enable the Starboard
+implementation to run arbitrary code on the application's renderer thread
+with the renderer's EGLContext held current.  This may be useful if your
+SbDecodeTarget creation code needs to execute GLES commands like, for
+example, glGenTextures().<br>
+The primary usage is likely to be the the SbPlayer implementation on some
+platforms.<br>
+#### SbDecodeTarget Example
+
+
+Let's say that we are an application and we would like to use the interface
+defined in starboard/image.h to decode an imaginary "image/foo" image type.<br>
+First, the application should enumerate which SbDecodeTargetFormats are
+supported by that decoder.<br>
+SbDecodeTargetFormat kPreferredFormats[] = {
+kSbDecodeTargetFormat3PlaneYUVI420,
+kSbDecodeTargetFormat1PlaneRGBA,
+kSbDecodeTargetFormat1PlaneBGRA,
+};<br>
+SbDecodeTargetFormat format = kSbDecodeTargetFormatInvalid;
+for (int i = 0; i < SB_ARRAY_SIZE_INT(kPreferredFormats); ++i) {
+if (SbImageIsDecodeSupported("image/foo", kPreferredFormats[i])) {
+format = kPreferredFormats[i];
+break;
+}
+}<br>
+Now that the application has a format, it can create a decode target that it
+will use to decode the .foo file into. Let's assume format is
+kSbDecodeTargetFormat1PlaneRGBA, that we are on an EGL/GLES2 platform.
+Also, we won't do any error checking, to keep things even simpler.<br>
+SbDecodeTarget target = SbImageDecode(
+context_provider, encoded_foo_data, encoded_foo_data_size,
+"image/foo", format);<br>
+// If the decode works, you can get the texture out and render it.
+SbDecodeTargetInfo info;
+SbMemorySet(&info, 0, sizeof(info));
+SbDecodeTargetGetInfo(target, &info);
+GLuint texture =
+info.planes[kSbDecodeTargetPlaneRGBA].texture;
+
+## Enums
+
+### SbDecodeTargetFormat
+
+The list of all possible decoder target formats. An SbDecodeTarget consists
+of one or more planes of data, each plane corresponding with a surface. For
+some formats, different planes will be different sizes for the same
+dimensions.<br>
+NOTE: For enumeration entries with an alpha component, the alpha will always
+be premultiplied unless otherwise explicitly specified.
+
+**Values**
+
+*   `kSbDecodeTargetFormat1PlaneRGBA` - A decoder target format consisting of a single RGBA plane, in that channelorder.
+*   `kSbDecodeTargetFormat1PlaneBGRA` - A decoder target format consisting of a single BGRA plane, in that channelorder.
+*   `kSbDecodeTargetFormat2PlaneYUVNV12` - A decoder target format consisting of Y and interleaved UV planes, in thatplane and channel order.
+*   `kSbDecodeTargetFormat3PlaneYUVI420` - A decoder target format consisting of Y, U, and V planes, in that order.
+*   `kSbDecodeTargetFormat1PlaneUYVY` - A decoder target format consisting of a single plane with pixels layed outin the format UYVY.  Since there are two Y values per sample, but only oneU value and only one V value, horizontally the Y resolution is twice thesize of both the U and V resolutions.  Vertically, they Y, U and V allhave the same resolution.  This is a YUV 422 format.  When using thisformat with GL platforms, it is expected that the underlying texture willbe set to the GL_RGBA format, and the width of the texture will be equal tothe number of UYVY tuples per row (e.g. the u/v width resolution).Content region left/right should be specified in u/v width resolution.
+*   `kSbDecodeTargetFormatInvalid` - An invalid decode target format.
+
+### SbDecodeTargetPlane
+
+All the planes supported by SbDecodeTarget.
+
+**Values**
+
+*   `kSbDecodeTargetPlaneRGBA` - The RGBA plane for the RGBA format.
+*   `kSbDecodeTargetPlaneBGRA` - The BGRA plane for the BGRA format.
+*   `kSbDecodeTargetPlaneY` - The Y plane for multi-plane YUV formats.
+*   `kSbDecodeTargetPlaneUV` - The UV plane for 2-plane YUV formats.
+*   `kSbDecodeTargetPlaneU` - The U plane for 3-plane YUV formats.
+*   `kSbDecodeTargetPlaneV` - The V plane for 3-plane YUV formats.
+
+## Structs
+
+### SbDecodeTargetGraphicsContextProvider
+
+In general, the SbDecodeTargetGraphicsContextProvider structure provides
+information about the graphics context that will be used to render
+SbDecodeTargets.  Some Starboard implementations may need to have references
+to some graphics objects when creating/destroying resources used by
+SbDecodeTarget.  References to SbDecodeTargetGraphicsContextProvider objects
+should be provided to all Starboard functions that might create
+SbDecodeTargets (e.g. SbImageDecode()).
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>SbBlitterDevice</code><br>        <code>device</code></td>    <td>The SbBlitterDevice object that will be used to render any produced
+SbDecodeTargets.</td>  </tr>
+  <tr>
+    <td><code>SbDecodeTargetGlesContextRunner</code><br>        <code>gles_context_runner</code></td>    <td>The <code>gles_context_runner</code> function pointer is passed in from the
+application into the Starboard implementation, and can be invoked by the
+Starboard implementation to allow running arbitrary code on the renderer's
+thread with the EGLContext above held current.</td>  </tr>
+  <tr>
+    <td><code>char</code><br>        <code>dummy</code></td>    <td>Context data that is to be passed in to <code>gles_context_runner</code> when it is
+invoked.
+Some compilers complain about empty structures, this is to appease them.</td>  </tr>
+</table>
+
+### SbDecodeTargetInfo
+
+Contains all information about a decode target, including all of its planes.
+This can be queried via calls to SbDecodeTargetGetInfo().
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>SbDecodeTargetFormat</code><br>        <code>format</code></td>    <td>The decode target format, which would dictate how many planes can be
+expected in <code>planes</code>.</td>  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>is_opaque</code></td>    <td>Specifies whether the decode target is opaque.  The underlying
+source of this value is expected to be properly maintained by the Starboard
+implementation.  So, for example, if an opaque only image type were decoded
+into an SbDecodeTarget, then the implementation would configure things in
+such a way that this value is set to true.  By opaque, it is meant
+that all alpha values are guaranteed to be 255, if the decode target is of
+a format that has alpha values.  If the decode target is of a format that
+does not have alpha values, then this value should be set to true.
+Applications may rely on this value in order to implement certain
+optimizations such as occlusion culling.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>width</code></td>    <td>The width of the image represented by this decode target.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>height</code></td>    <td>The height of the image represented by this decode target.</td>  </tr>
+  <tr>
+    <td><code>SbDecodeTargetInfoPlane</code><br>        <code>planes[3]</code></td>    <td>The image planes (e.g. kSbDecodeTargetPlaneRGBA, or {kSbDecodeTargetPlaneY,
+kSbDecodeTargetPlaneU, kSbDecodeTargetPlaneV} associated with this
+decode target.</td>  </tr>
+</table>
+
+### SbDecodeTargetInfoContentRegion
+
+Defines a rectangular content region within a SbDecodeTargetInfoPlane
+structure.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>left</code></td>    <td></td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>top</code></td>    <td></td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>right</code></td>    <td></td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>bottom</code></td>    <td></td>  </tr>
+</table>
+
+### SbDecodeTargetInfoPlane
+
+Defines an image plane within a SbDecodeTargetInfo object.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>SbBlitterSurface</code><br>        <code>surface</code></td>    <td>A handle to the Blitter surface that can be used for rendering.</td>  </tr>
+  <tr>
+    <td><code>uint32_t</code><br>        <code>texture</code></td>    <td>A handle to the GL texture that can be used for rendering.</td>  </tr>
+  <tr>
+    <td><code>uint32_t</code><br>        <code>gl_texture_target</code></td>    <td>The GL texture target that should be used in calls to glBindTexture.
+Typically this would be GL_TEXTURE_2D, but some platforms may require
+that it be set to something else like GL_TEXTURE_EXTERNAL_OES.</td>  </tr>
+  <tr>
+    <td><code>uint32_t</code><br>        <code>gl_texture_format</code></td>    <td>For kSbDecodeTargetFormat2PlaneYUVNV12 planes: the format of the
+texture. Usually, for the luma plane, this is either GL_ALPHA or
+GL_RED_EXT. For the chroma plane, this is usually GL_LUMINANCE_ALPHA
+or GL_RG_EXT.
+Ignored for other plane types.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>width</code></td>    <td>The width of the texture/surface for this particular plane.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>height</code></td>    <td>The height of the texture/surface for this particular plane.</td>  </tr>
+  <tr>
+    <td><code>SbDecodeTargetInfoContentRegion</code><br>        <code>content_region</code></td>    <td>The following properties specify a rectangle indicating a region within
+the texture/surface that contains valid image data.  The top-left corner
+is (0, 0) and increases to the right and to the bottom.  The units
+specified by these parameters are number of pixels.  The range for
+left/right is [0, width], and for top/bottom it is [0, height].</td>  </tr>
+</table>
+
+### SbDecodeTargetPrivate
+
+Private structure representing a target for image data decoding.
+
+## Functions
+
+### PrivateDecodeTargetReleaser
+
+**Description**
+
+This function is just an implementation detail of
+SbDecodeTargetReleaseInGlesContext() and should not be called directly.
+
+**Declaration**
+
+```
+static SB_C_INLINE void PrivateDecodeTargetReleaser(void* context) {
+  SbDecodeTarget decode_target = (SbDecodeTarget)context;
+  SbDecodeTargetRelease(decode_target);
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>
+        <code>context</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbDecodeTargetGetInfo
+
+**Description**
+
+Writes all information about `decode_target` into `out_info`.  Returns false
+if the provided `out_info` structure is not zero initialized.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDecodeTargetGetInfo-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDecodeTargetGetInfo-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDecodeTargetGetInfo-declaration">
+<pre>
+SB_EXPORT bool SbDecodeTargetGetInfo(SbDecodeTarget decode_target,
+                                     SbDecodeTargetInfo* out_info);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDecodeTargetGetInfo-stub">
+
+```
+#include "starboard/decode_target.h"
+
+bool SbDecodeTargetGetInfo(SbDecodeTarget /*decode_target*/,
+                           SbDecodeTargetInfo* /*out_info*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDecodeTarget</code><br>
+        <code>decode_target</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbDecodeTargetInfo*</code><br>
+        <code>out_info</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbDecodeTargetIsFormatValid
+
+**Description**
+
+Returns whether a given format is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbDecodeTargetIsFormatValid(
+    SbDecodeTargetFormat format) {
+  return format != kSbDecodeTargetFormatInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDecodeTargetFormat</code><br>
+        <code>format</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbDecodeTargetIsValid
+
+**Description**
+
+Returns whether the given file handle is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbDecodeTargetIsValid(SbDecodeTarget handle) {
+  return handle != kSbDecodeTargetInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDecodeTarget</code><br>
+        <code>handle</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbDecodeTargetNumberOfPlanesForFormat
+
+**Declaration**
+
+```
+static SB_C_INLINE int SbDecodeTargetNumberOfPlanesForFormat(
+    SbDecodeTargetFormat format) {
+  switch (format) {
+    case kSbDecodeTargetFormat1PlaneRGBA:
+    case kSbDecodeTargetFormat1PlaneUYVY:
+      return 1;
+    case kSbDecodeTargetFormat1PlaneBGRA:
+      return 1;
+    case kSbDecodeTargetFormat2PlaneYUVNV12:
+      return 2;
+    case kSbDecodeTargetFormat3PlaneYUVI420:
+      return 3;
+    default:
+      SB_NOTREACHED();
+      return 0;
+  }
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDecodeTargetFormat</code><br>
+        <code>format</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbDecodeTargetRelease
+
+**Description**
+
+Returns ownership of `decode_target` to the Starboard implementation.
+This function will likely result in the destruction of the SbDecodeTarget and
+all its associated surfaces, though in some cases, platforms may simply
+adjust a reference count.  In the case where SB_HAS(GLES2), this function
+must be called on a thread with the context
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDecodeTargetRelease-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDecodeTargetRelease-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDecodeTargetRelease-declaration">
+<pre>
+SB_EXPORT void SbDecodeTargetRelease(SbDecodeTarget decode_target);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDecodeTargetRelease-stub">
+
+```
+#include "starboard/decode_target.h"
+
+void SbDecodeTargetRelease(SbDecodeTarget /*decode_target*/) {}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDecodeTarget</code><br>
+        <code>decode_target</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbDecodeTargetReleaseInGlesContext
+
+**Description**
+
+Helper function that is possibly useful to Starboard implementations that
+will release a decode target on the thread with the GLES context current.
+
+**Declaration**
+
+```
+static SB_C_INLINE void SbDecodeTargetReleaseInGlesContext(
+    SbDecodeTargetGraphicsContextProvider* provider,
+    SbDecodeTarget decode_target) {
+  SbDecodeTargetRunInGlesContext(provider, &PrivateDecodeTargetReleaser,
+                                 (void*)decode_target);
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDecodeTargetGraphicsContextProvider*</code><br>
+        <code>provider</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbDecodeTarget</code><br>
+        <code>decode_target</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbDecodeTargetRunInGlesContext
+
+**Description**
+
+Inline convenience function to run an arbitrary
+SbDecodeTargetGlesContextRunnerTarget function through a
+SbDecodeTargetGraphicsContextProvider.  This is intended to be called by
+Starboard implementations, if it is necessary.
+
+**Declaration**
+
+```
+static SB_C_INLINE void SbDecodeTargetRunInGlesContext(
+    SbDecodeTargetGraphicsContextProvider* provider,
+    SbDecodeTargetGlesContextRunnerTarget target,
+    void* target_context) {
+  provider->gles_context_runner(provider, target, target_context);
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDecodeTargetGraphicsContextProvider*</code><br>
+        <code>provider</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbDecodeTargetGlesContextRunnerTarget</code><br>
+        <code>target</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>
+        <code>target_context</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/directory.md b/src/cobalt/site/docs/reference/starboard/modules/directory.md
new file mode 100644
index 0000000..5115880
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/directory.md
@@ -0,0 +1,288 @@
+---
+layout: doc
+title: "Starboard Module Reference: directory.h"
+---
+
+Provides directory listing functions.
+
+## Structs
+
+### SbDirectoryEntry
+
+Represents a directory entry.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>char</code><br>        <code>name[SB_FILE_MAX_NAME]</code></td>    <td>The name of this directory entry.</td>  </tr>
+</table>
+
+### SbDirectory
+
+A handle to an open directory stream.
+
+## Functions
+
+### SbDirectoryCanOpen
+
+**Description**
+
+Indicates whether <code><a href="#sbdirectoryopen">SbDirectoryOpen</a></code> is allowed for the given `path`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDirectoryCanOpen-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDirectoryCanOpen-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDirectoryCanOpen-declaration">
+<pre>
+SB_EXPORT bool SbDirectoryCanOpen(const char* path);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDirectoryCanOpen-stub">
+
+```
+#include "starboard/directory.h"
+
+bool SbDirectoryCanOpen(const char* /*path*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>path</code></td>
+    <td>The path to be checked.</td>
+  </tr>
+</table>
+
+### SbDirectoryClose
+
+**Description**
+
+Closes an open directory stream handle. The return value indicates whether
+the directory was closed successfully.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDirectoryClose-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDirectoryClose-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDirectoryClose-declaration">
+<pre>
+SB_EXPORT bool SbDirectoryClose(SbDirectory directory);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDirectoryClose-stub">
+
+```
+#include "starboard/directory.h"
+
+bool SbDirectoryClose(SbDirectory /*directory*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDirectory</code><br>        <code>directory</code></td>
+    <td>The directory stream handle to close.</td>
+  </tr>
+</table>
+
+### SbDirectoryCreate
+
+**Description**
+
+Creates the directory `path`, assuming the parent directory already exists.
+This function returns `true` if the directory now exists (even if it existed
+before) and returns `false` if the directory does not exist.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDirectoryCreate-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDirectoryCreate-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDirectoryCreate-declaration">
+<pre>
+SB_EXPORT bool SbDirectoryCreate(const char* path);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDirectoryCreate-stub">
+
+```
+#include "starboard/directory.h"
+
+bool SbDirectoryCreate(const char* /*path*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>path</code></td>
+    <td>The path to be created.</td>
+  </tr>
+</table>
+
+### SbDirectoryGetNext
+
+**Description**
+
+Populates `out_entry` with the next entry in the specified directory stream,
+and moves the stream forward by one entry.<br>
+This function returns `true` if there was a next directory, and `false`
+at the end of the directory stream.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDirectoryGetNext-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDirectoryGetNext-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDirectoryGetNext-declaration">
+<pre>
+SB_EXPORT bool SbDirectoryGetNext(SbDirectory directory,
+                                  SbDirectoryEntry* out_entry);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDirectoryGetNext-stub">
+
+```
+#include "starboard/directory.h"
+
+bool SbDirectoryGetNext(SbDirectory /*directory*/,
+                        SbDirectoryEntry* /*out_entry*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDirectory</code><br>        <code>directory</code></td>
+    <td>The directory stream from which to retrieve the next directory.</td>
+  </tr>
+  <tr>
+    <td><code>SbDirectoryEntry*</code><br>        <code>out_entry</code></td>
+    <td>The variable to be populated with the next directory entry.</td>
+  </tr>
+</table>
+
+### SbDirectoryIsValid
+
+**Description**
+
+Returns whether the given directory stream handle is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbDirectoryIsValid(SbDirectory directory) {
+  return directory != kSbDirectoryInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDirectory</code><br>
+        <code>directory</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbDirectoryOpen
+
+**Description**
+
+Opens the given existing directory for listing. This function returns
+kSbDirectoryInvalidHandle if it is not successful.<br>
+If `out_error` is provided by the caller, it will be set to the appropriate
+SbFileError code on failure.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDirectoryOpen-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDirectoryOpen-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDirectoryOpen-declaration">
+<pre>
+SB_EXPORT SbDirectory SbDirectoryOpen(const char* path, SbFileError* out_error);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDirectoryOpen-stub">
+
+```
+#include "starboard/directory.h"
+
+SbDirectory SbDirectoryOpen(const char* /*path*/, SbFileError* /*out_error*/) {
+  return kSbDirectoryInvalid;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>path</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>SbFileError*</code><br>        <code>out_error</code></td>
+    <td>An output parameter that, in case of an error, is set to the
+reason that the directory could not be opened.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/double.md b/src/cobalt/site/docs/reference/starboard/modules/double.md
new file mode 100644
index 0000000..87398aa
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/double.md
@@ -0,0 +1,231 @@
+---
+layout: doc
+title: "Starboard Module Reference: double.h"
+---
+
+Provides double-precision floating point helper functions.
+
+## Functions
+
+### SbDoubleAbsolute
+
+**Description**
+
+Returns the absolute value of the given double-precision floating-point
+number `d`, preserving `NaN` and infinity.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDoubleAbsolute-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDoubleAbsolute-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDoubleAbsolute-declaration">
+<pre>
+SB_EXPORT double SbDoubleAbsolute(const double d);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDoubleAbsolute-stub">
+
+```
+#include "starboard/double.h"
+
+double SbDoubleAbsolute(double /*d*/) {
+  return 0.0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const double</code><br>        <code>d</code></td>
+    <td>The number to be adjusted.</td>
+  </tr>
+</table>
+
+### SbDoubleExponent
+
+**Description**
+
+Returns `base` taken to the power of `exponent`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDoubleExponent-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDoubleExponent-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDoubleExponent-declaration">
+<pre>
+SB_EXPORT double SbDoubleExponent(const double base, const double exponent);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDoubleExponent-stub">
+
+```
+#include "starboard/double.h"
+
+double SbDoubleExponent(const double /*base*/, const double /*exponent*/) {
+  return 0.0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const double</code><br>        <code>base</code></td>
+    <td>The number to be adjusted.</td>
+  </tr>
+  <tr>
+    <td><code>const double</code><br>        <code>exponent</code></td>
+    <td>The power to which the <code>base</code> number should be raised.</td>
+  </tr>
+</table>
+
+### SbDoubleFloor
+
+**Description**
+
+Floors double-precision floating-point number `d` to the nearest integer.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDoubleFloor-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDoubleFloor-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDoubleFloor-declaration">
+<pre>
+SB_EXPORT double SbDoubleFloor(const double d);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDoubleFloor-stub">
+
+```
+#include "starboard/double.h"
+
+double SbDoubleFloor(double /*d*/) {
+  return 0.0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const double</code><br>        <code>d</code></td>
+    <td>The number to be floored.</td>
+  </tr>
+</table>
+
+### SbDoubleIsFinite
+
+**Description**
+
+Determines whether double-precision floating-point number `d` represents a
+finite number.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDoubleIsFinite-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDoubleIsFinite-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDoubleIsFinite-declaration">
+<pre>
+SB_EXPORT bool SbDoubleIsFinite(const double d);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDoubleIsFinite-stub">
+
+```
+#include "starboard/double.h"
+
+bool SbDoubleIsFinite(const double /*d*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const double</code><br>        <code>d</code></td>
+    <td>The number to be evaluated.</td>
+  </tr>
+</table>
+
+### SbDoubleIsNan
+
+**Description**
+
+Determines whether double-precision floating-point number `d` represents
+"Not a Number."
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDoubleIsNan-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDoubleIsNan-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDoubleIsNan-declaration">
+<pre>
+SB_EXPORT bool SbDoubleIsNan(const double d);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDoubleIsNan-stub">
+
+```
+#include "starboard/double.h"
+
+bool SbDoubleIsNan(const double /*d*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const double</code><br>        <code>d</code></td>
+    <td>The number to be evaluated.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/drm.md b/src/cobalt/site/docs/reference/starboard/modules/drm.md
new file mode 100644
index 0000000..df6c5a0
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/drm.md
@@ -0,0 +1,626 @@
+---
+layout: doc
+title: "Starboard Module Reference: drm.h"
+---
+
+Provides definitions that allow for DRM support, which are common
+between Player and Decoder interfaces.
+
+## Enums
+
+### SbDrmKeyStatus
+
+Status of a particular media key.
+https://w3c.github.io/encrypted-media/#idl-def-MediaKeyStatus
+
+**Values**
+
+*   `kSbDrmKeyStatusUsable`
+*   `kSbDrmKeyStatusExpired`
+*   `kSbDrmKeyStatusReleased`
+*   `kSbDrmKeyStatusRestricted`
+*   `kSbDrmKeyStatusDownscaled`
+*   `kSbDrmKeyStatusPending`
+*   `kSbDrmKeyStatusError`
+
+## Structs
+
+### SbDrmKeyId
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>uint8_t</code><br>        <code>identifier[16]</code></td>    <td>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.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>identifier_size</code></td>    <td></td>  </tr>
+</table>
+
+### SbDrmSampleInfo
+
+All the optional information needed per sample for encrypted samples.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>uint8_t</code><br>        <code>initialization_vector[16]</code></td>    <td>The Initialization Vector needed to decrypt this sample.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>initialization_vector_size</code></td>    <td></td>  </tr>
+  <tr>
+    <td><code>uint8_t</code><br>        <code>identifier[16]</code></td>    <td>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.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>identifier_size</code></td>    <td></td>  </tr>
+  <tr>
+    <td><code>int32_t</code><br>        <code>subsample_count</code></td>    <td>The number of subsamples in this sample, must be at least 1.</td>  </tr>
+  <tr>
+    <td><code>const</code><br>        <code>SbDrmSubSampleMapping* subsample_mapping</code></td>    <td>The clear/encrypted mapping of each subsample in this sample. This must be
+an array of <code>subsample_count</code> mappings.</td>  </tr>
+</table>
+
+### SbDrmSubSampleMapping
+
+A mapping of clear and encrypted bytes for a single subsample. All
+subsamples within a sample must be encrypted with the same encryption
+parameters. The clear bytes always appear first in the sample.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>int32_t</code><br>        <code>clear_byte_count</code></td>    <td>How many bytes of the corresponding subsample are not encrypted</td>  </tr>
+  <tr>
+    <td><code>int32_t</code><br>        <code>encrypted_byte_count</code></td>    <td>How many bytes of the corresponding subsample are encrypted.</td>  </tr>
+</table>
+
+### SbDrmSystem
+
+A handle to a DRM system which can be used with either an SbDecoder or a
+SbPlayer.
+
+## Functions
+
+### SbDrmCloseSession
+
+**Description**
+
+Clear any internal states/resources related to the specified `session_id`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDrmCloseSession-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDrmCloseSession-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDrmCloseSession-declaration">
+<pre>
+SB_EXPORT void SbDrmCloseSession(SbDrmSystem drm_system,
+                                 const void* session_id,
+                                 int session_id_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDrmCloseSession-stub">
+
+```
+#include "starboard/drm.h"
+
+void SbDrmCloseSession(SbDrmSystem drm_system,
+                       const void* session_id,
+                       int session_id_size) {
+  SB_UNREFERENCED_PARAMETER(drm_system);
+  SB_UNREFERENCED_PARAMETER(session_id);
+  SB_UNREFERENCED_PARAMETER(session_id_size);
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDrmSystem</code><br>
+        <code>drm_system</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>
+        <code>session_id</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>session_id_size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbDrmCreateSystem
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDrmCreateSystem-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDrmCreateSystem-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDrmCreateSystem-declaration">
+<pre>
+SB_EXPORT SbDrmSystem
+SbDrmCreateSystem(const char* key_system,
+                  void* context,
+                  SbDrmSessionUpdateRequestFunc update_request_callback,
+                  SbDrmSessionUpdatedFunc session_updated_callback);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDrmCreateSystem-stub">
+
+```
+#include "starboard/drm.h"
+
+#if SB_API_VERSION >= 6
+
+SbDrmSystem SbDrmCreateSystem(
+    const char* key_system,
+    void* context,
+    SbDrmSessionUpdateRequestFunc update_request_callback,
+    SbDrmSessionUpdatedFunc session_updated_callback,
+    SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback) {
+  SB_UNREFERENCED_PARAMETER(context);
+  SB_UNREFERENCED_PARAMETER(key_system);
+  SB_UNREFERENCED_PARAMETER(update_request_callback);
+  SB_UNREFERENCED_PARAMETER(session_updated_callback);
+  SB_UNREFERENCED_PARAMETER(key_statuses_changed_callback);
+  return kSbDrmSystemInvalid;
+}
+
+#else  // SB_API_VERSION >= 6
+
+SbDrmSystem SbDrmCreateSystem(
+    const char* key_system,
+    void* context,
+    SbDrmSessionUpdateRequestFunc update_request_callback,
+    SbDrmSessionUpdatedFunc session_updated_callback) {
+  SB_UNREFERENCED_PARAMETER(context);
+  SB_UNREFERENCED_PARAMETER(key_system);
+  SB_UNREFERENCED_PARAMETER(update_request_callback);
+  SB_UNREFERENCED_PARAMETER(session_updated_callback);
+  return kSbDrmSystemInvalid;
+}
+
+#endif  // SB_API_VERSION >= 6
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>
+        <code>key_system</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>
+        <code>context</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbDrmSessionUpdateRequestFunc</code><br>
+        <code>update_request_callback</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbDrmSessionUpdatedFunc</code><br>
+        <code>session_updated_callback</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbDrmDestroySystem
+
+**Description**
+
+Destroys `drm_system`, which implicitly removes all keys installed in it and
+invalidates all outstanding session update requests. A DRM system cannot be
+destroyed unless any associated SbPlayer or SbDecoder has first been
+destroyed.<br>
+All callbacks are guaranteed to be finished when this function returns.
+As a result, if this function is called from a callback that is passed
+to <code><a href="#sbdrmcreatesystem">SbDrmCreateSystem()</a></code>, a deadlock will occur.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDrmDestroySystem-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDrmDestroySystem-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDrmDestroySystem-declaration">
+<pre>
+SB_EXPORT void SbDrmDestroySystem(SbDrmSystem drm_system);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDrmDestroySystem-stub">
+
+```
+#include "starboard/drm.h"
+
+void SbDrmDestroySystem(SbDrmSystem drm_system) {
+  SB_UNREFERENCED_PARAMETER(drm_system);
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDrmSystem</code><br>        <code>drm_system</code></td>
+    <td>The DRM system to be destroyed.</td>
+  </tr>
+</table>
+
+### SbDrmGenerateSessionUpdateRequest
+
+**Description**
+
+Asynchronously generates a session update request payload for
+`initialization_data`, of `initialization_data_size`, in case sensitive
+`type`, extracted from the media stream, in `drm_system`'s key system.<br>
+This function calls `drm_system`'s `update_request_callback` function,
+which is defined when the DRM system is created by <code><a href="#sbdrmcreatesystem">SbDrmCreateSystem</a></code>. When
+calling that function, this function either sends `context` (also from
+`SbDrmCreateSystem`) and a populated request, or it sends NULL `session_id`
+if an error occurred.<br>
+`drm_system`'s `context` may be used to route callbacks back to an object
+instance.<br>
+Callbacks may be called either from the current thread before this function
+returns or from another thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDrmGenerateSessionUpdateRequest-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDrmGenerateSessionUpdateRequest-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDrmGenerateSessionUpdateRequest-declaration">
+<pre>
+SB_EXPORT void SbDrmGenerateSessionUpdateRequest(
+    SbDrmSystem drm_system,
+    int ticket,
+    const char* type,
+    const void* initialization_data,
+    int initialization_data_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDrmGenerateSessionUpdateRequest-stub">
+
+```
+#include "starboard/drm.h"
+
+void SbDrmGenerateSessionUpdateRequest(SbDrmSystem /*drm_system*/,
+                                       int /*ticket*/,
+                                       const char* /*type*/,
+                                       const void* /*initialization_data*/,
+                                       int /*initialization_data_size*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDrmSystem</code><br>        <code>drm_system</code></td>
+    <td>The DRM system that defines the key system used for the
+session update request payload as well as the callback function that is
+called as a result of the function being called.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>ticket</code></td>
+    <td>The opaque ID that allows to distinguish callbacks from multiple
+concurrent calls to <code>SbDrmGenerateSessionUpdateRequest()</code>, which will be passed
+to <code>update_request_callback</code> as-is. It is the responsibility of the caller to
+establish ticket uniqueness, issuing multiple request with the same ticket
+may result in undefined behavior. The value <code>kSbDrmTicketInvalid</code> must not be
+used.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>type</code></td>
+    <td>The case-sensitive type of the session update request payload.</td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>initialization_data</code></td>
+    <td>The data for which the session update request payload
+is created.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>initialization_data_size</code></td>
+    <td>The size of the session update request payload.</td>
+  </tr>
+</table>
+
+### SbDrmGetKeyCount
+
+**Description**
+
+Returns the number of keys installed in `drm_system`.
+
+**Declaration**
+
+```
+SB_EXPORT int SbDrmGetKeyCount(SbDrmSystem drm_system);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDrmSystem</code><br>        <code>drm_system</code></td>
+    <td>The system for which the number of installed keys is retrieved.</td>
+  </tr>
+</table>
+
+### SbDrmGetKeyStatus
+
+**Description**
+
+Gets `out_key`, `out_key_size`, and `out_status` for the key with `index`
+in `drm_system`. Returns whether a key is installed at `index`.
+If not, the output parameters, which all must not be NULL, will not be
+modified.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbDrmGetKeyStatus(SbDrmSystem drm_system,
+                                 const void* session_id,
+                                 int session_id_size,
+                                 int index,
+                                 void** out_key,
+                                 int* out_key_size,
+                                 SbDrmKeyStatus* out_status);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDrmSystem</code><br>
+        <code>drm_system</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>
+        <code>session_id</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>session_id_size</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>index</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>void**</code><br>
+        <code>out_key</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int*</code><br>
+        <code>out_key_size</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbDrmKeyStatus*</code><br>
+        <code>out_status</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbDrmRemoveAllKeys
+
+**Description**
+
+Removes all installed keys for `drm_system`. Any outstanding session update
+requests are also invalidated.
+
+**Declaration**
+
+```
+SB_EXPORT void SbDrmRemoveAllKeys(SbDrmSystem drm_system);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDrmSystem</code><br>        <code>drm_system</code></td>
+    <td>The DRM system for which keys should be removed.</td>
+  </tr>
+</table>
+
+### SbDrmSystemIsValid
+
+**Description**
+
+Indicates whether `drm_system` is a valid SbDrmSystem.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE bool SbDrmSystemIsValid(SbDrmSystem drm) {
+  return drm != kSbDrmSystemInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDrmSystem</code><br>
+        <code>drm</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbDrmTicketIsValid
+
+**Description**
+
+Indicates whether `ticket` is a valid ticket.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE bool SbDrmTicketIsValid(int ticket) {
+  return ticket != kSbDrmTicketInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>ticket</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbDrmUpdateSession
+
+**Description**
+
+Update session with `key`, in `drm_system`'s key system, from the license
+server response. Calls `session_updated_callback` with `context` and whether
+the update succeeded. `context` may be used to route callbacks back to
+an object instance.<br>
+`ticket` is the opaque ID that allows to distinguish callbacks from
+multiple concurrent calls to <code>SbDrmUpdateSession()</code>, which will be passed
+to `session_updated_callback` as-is. It is the responsibility of the caller
+to establish ticket uniqueness, issuing multiple calls with the same ticket
+may result in undefined behavior.<br>
+Once the session is successfully updated, an SbPlayer or SbDecoder associated
+with that DRM key system will be able to decrypt encrypted samples.<br>
+`drm_system`'s `session_updated_callback` may called either from the
+current thread before this function returns or from another thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbDrmUpdateSession-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbDrmUpdateSession-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbDrmUpdateSession-declaration">
+<pre>
+SB_EXPORT void SbDrmUpdateSession(SbDrmSystem drm_system,
+                                  int ticket,
+                                  const void* key,
+                                  int key_size,
+                                  const void* session_id,
+                                  int session_id_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbDrmUpdateSession-stub">
+
+```
+#include "starboard/drm.h"
+
+void SbDrmUpdateSession(SbDrmSystem /*drm_system*/,
+                        int /*ticket*/,
+                        const void* /*key*/,
+                        int /*key_size*/,
+                        const void* /*session_id*/,
+                        int /*session_id_size*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDrmSystem</code><br>
+        <code>drm_system</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>ticket</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>
+        <code>key</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>key_size</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>
+        <code>session_id</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>session_id_size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/event.md b/src/cobalt/site/docs/reference/starboard/modules/event.md
new file mode 100644
index 0000000..84a7737
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/event.md
@@ -0,0 +1,248 @@
+---
+layout: doc
+title: "Starboard Module Reference: event.h"
+---
+
+Defines the event system that wraps the Starboard main loop and entry point.<br>
+## The Starboard Application life cycle
+
+
+<pre>     ---------- *
+    |           |
+    |        Preload
+    |           |
+    |           V
+  Start   [ PRELOADING ] ------------
+    |           |                    |
+    |         Start                  |
+    |           |                    |
+    |           V                    |
+     ----> [ STARTED ] <----         |
+                |           |        |
+              Pause       Unpause    |
+                |           |     Suspend
+                V           |        |
+     -----> [ PAUSED ] -----         |
+    |           |                    |
+ Resume      Suspend                 |
+    |           |                    |
+    |           V                    |
+     ---- [ SUSPENDED ] <------------
+                |
+               Stop
+                |
+                V
+           [ STOPPED ]</pre><br>
+The first event that a Starboard application receives is either |Start|
+(kSbEventTypeStart) or |Preload| (kSbEventTypePreload). |Start| puts the
+application in the |STARTED| state, whereas |Preload| puts the application in
+the |PRELOADING| state.<br>
+|PRELOADING| can only happen as the first application state. In this state,
+the application should start and run as normal, but will not receive any
+input, and should not try to initialize graphics resources (via GL or
+SbBlitter). In |PRELOADING|, the application can receive |Start| or |Suspend|
+events. |Start| will receive the same data that was passed into |Preload|.<br>
+In the |STARTED| state, the application is in the foreground and can expect
+to do all of the normal things it might want to do. Once in the |STARTED|
+state, it may receive a |Pause| event, putting the application into the
+|PAUSED| state.<br>
+In the |PAUSED| state, the application is still visible, but has lost
+focus, or it is partially obscured by a modal dialog, or it is on its way
+to being shut down. The application should pause activity in this state.
+In this state, it can receive |Unpause| to be brought back to the foreground
+state (|STARTED|), or |Suspend| to be pushed further in the background
+to the |SUSPENDED| state.<br>
+In the |SUSPENDED| state, the application is generally not visible. It
+should immediately release all graphics and video resources, and shut down
+all background activity (timers, rendering, etc). Additionally, the
+application should flush storage to ensure that if the application is
+killed, the storage will be up-to-date. The application may be killed at
+this point, but will ideally receive a |Stop| event for a more graceful
+shutdown.<br>
+Note that the application is always expected to transition through |PAUSED|
+to |SUSPENDED| before receiving |Stop| or being killed.
+
+## Enums
+
+### SbEventType
+
+An enumeration of all possible event types dispatched directly by the
+system. Each event is accompanied by a void* data argument, and each event
+must define the type of the value pointed to by that data argument, if any.
+
+**Values**
+
+*   `kSbEventTypePreload` - Applications should perform initialization and prepare to react tosubsequent events, but must not initialize any graphics resources (throughGL or SbBlitter). The intent of this event is to allow the application todo as much work as possible ahead of time, so that when the application isfirst brought to the foreground, it's as fast as a resume.<br>The |kSbEventTypeStart| event may be sent at any time, regardless ofinitialization state. Input events will not be sent in the |PRELOADING|state. This event will only be sent once for a given process launch.SbEventStartData is passed as the data argument.<br>The system may send |kSbEventTypeSuspend| in |PRELOADING| if it wants topush the app into a lower resource consumption state. Applications can alocall SbSystemRequestSuspend() when they are done preloading to requestthis.
+*   `kSbEventTypeStart` - The first event that an application receives on startup when startingnormally (i.e. not being preloaded). Applications should performinitialization, start running, and prepare to react to subsequentevents. Applications that wish to run and then exit must call|SbSystemRequestStop()| to terminate. This event will only be sent once fora given process launch. |SbEventStartData| is passed as the dataargument. In case of preload, the |SbEventStartData| will be the same aswhat was passed to |kSbEventTypePreload|.
+*   `kSbEventTypePause` - A dialog will be raised or the application will otherwise be put into abackground-but-visible or partially-obscured state (PAUSED). Graphics andvideo resources will still be available, but the application should pauseforeground activity like animations and video playback. Can only bereceived after a Start event. The only events that should be dispatchedafter a Pause event are Unpause or Suspend. No data argument.
+*   `kSbEventTypeUnpause` - The application is returning to the foreground (STARTED) after having beenput in the PAUSED (e.g. partially-obscured) state. The application shouldunpause foreground activity like animations and video playback. Can only bereceived after a Pause or Resume event. No data argument.
+*   `kSbEventTypeSuspend` - The operating system will put the application into a Suspended state afterthis event is handled. The application is expected to stop periodicbackground work, release ALL graphics and video resources, and flush anypending SbStorage writes. Some platforms will terminate the application ifwork is done or resources are retained after suspension. Can only bereceived after a Pause event. The only events that should be dispatchedafter a Suspend event are Resume or Stop. On some platforms, the processmay also be killed after Suspend without a Stop event. No data argument.
+*   `kSbEventTypeResume` - The operating system has restored the application to the PAUSED state fromthe SUSPENDED state. This is the first event the application will receivecoming out of SUSPENDED, and it will only be received after a Suspendevent. The application will now be in the PAUSED state. No data argument.
+*   `kSbEventTypeStop` - The operating system will shut the application down entirely after thisevent is handled. Can only be recieved after a Suspend event, in theSUSPENDED state. No data argument.
+*   `kSbEventTypeInput` - A user input event, including keyboard, mouse, gesture, or something else.SbInputData (from input.h) is passed as the data argument.
+*   `kSbEventTypeUser` - A user change event, which means a new user signed-in or signed-out, or thecurrent user changed. No data argument, call SbUserGetSignedIn() andSbUserGetCurrent() to get the latest changes.
+*   `kSbEventTypeLink` - A navigational link has come from the system, and the application shouldconsider handling it by navigating to the corresponding applicationlocation. The data argument is an application-specific, null-terminatedstring.
+*   `kSbEventTypeVerticalSync` - The beginning of a vertical sync has been detected. This event is verytiming-sensitive, so as little work as possible should be done on the mainthread if the application wants to receive this event in a timely manner.No data argument.
+*   `kSbEventTypeNetworkDisconnect` - The platform has detected a network disconnection. The platform should makea best effort to send an event of this type when the network disconnects,but there are likely to be cases where the platform cannot detect thedisconnection (e.g. if the connection is via a powered hub which becomesdisconnected), so the current network state cannot always be inferred fromthe sequence of Connect/Disconnect events.
+*   `kSbEventTypeNetworkConnect` - The platform has detected a network connection. This event may be sent atapplication start-up, and should always be sent if the network reconnectssince a disconnection event was sent.
+*   `kSbEventTypeScheduled` - An event type reserved for scheduled callbacks. It will only be sent inresponse to an application call to SbEventSchedule(), and it will call thecallback directly, so SbEventHandle should never receive this eventdirectly. The data type is an internally-defined structure.
+*   `kSbEventTypeAccessiblitySettingsChanged` - The platform's accessibility settings have changed. The application shouldquery the accessibility settings using the appropriate APIs to get thenew settings.
+*   `kSbEventTypeLowMemory` - An optional event that platforms may send to indicate that the applicationmay soon be terminated (or crash) due to low memory availability. Theapplication may respond by reducing memory consumption by running a GarbageCollection, flushing caches, or something similar. There is no requirementto respond to or handle this event, it is only advisory.
+
+## Structs
+
+### SbEvent
+
+Structure representing a Starboard event and its data.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>SbEventType</code><br>        <code>type</code></td>    <td></td>  </tr>
+</table>
+
+### SbEventStartData
+
+Event data for kSbEventTypeStart events.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>argument_count</code></td>    <td>The command-line argument count (argc).</td>  </tr>
+  <tr>
+    <td><code>const</code><br>        <code>char* link</code></td>    <td>The startup link, if any.</td>  </tr>
+</table>
+
+## Functions
+
+### SbEventCancel
+
+**Description**
+
+Cancels the specified `event_id`. Note that this function is a no-op
+if the event already fired. This function can be safely called from any
+thread, but the only way to guarantee that the event does not run anyway
+is to call it from the main Starboard event loop thread.
+
+**Declaration**
+
+```
+SB_EXPORT void SbEventCancel(SbEventId event_id);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbEventId</code><br>
+        <code>event_id</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbEventHandle
+
+**Description**
+
+The entry point that Starboard applications MUST implement. Any memory
+pointed at by `event` or the `data` field inside `event` is owned by the
+system, and that memory is reclaimed after this function returns, so the
+implementation must copy this data to extend its life. This behavior should
+also be assumed of all fields within the `data` object, unless otherwise
+explicitly specified.<br>
+This function is only called from the main Starboard thread. There is no
+specification about what other work might happen on this thread, so the
+application should generally do as little work as possible on this thread,
+and just dispatch it over to another thread.
+
+**Declaration**
+
+```
+SB_IMPORT void SbEventHandle(const SbEvent* event);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const SbEvent*</code><br>
+        <code>event</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbEventIsIdValid
+
+**Description**
+
+Returns whether the given event handle is valid.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE bool SbEventIsIdValid(SbEventId handle) {
+  return handle != kSbEventIdInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbEventId</code><br>
+        <code>handle</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbEventSchedule
+
+**Description**
+
+Schedules an event `callback` into the main Starboard event loop.
+This function may be called from any thread, but `callback` is always
+called from the main Starboard thread, queued with other pending events.
+
+**Declaration**
+
+```
+SB_EXPORT SbEventId SbEventSchedule(SbEventCallback callback,
+                                    void* context,
+                                    SbTime delay);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbEventCallback</code><br>        <code>callback</code></td>
+    <td>The callback function to be called.</td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>        <code>context</code></td>
+    <td>The context that is passed to the <code>callback</code> function.</td>
+  </tr>
+  <tr>
+    <td><code>SbTime</code><br>        <code>delay</code></td>
+    <td>The minimum number of microseconds to wait before calling the
+<code>callback</code> function. Set <code>delay</code> to <code>0</code> to call the callback as soon as
+possible.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/export.md b/src/cobalt/site/docs/reference/starboard/modules/export.md
new file mode 100644
index 0000000..d17360b
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/export.md
@@ -0,0 +1,99 @@
+---
+layout: doc
+title: "Starboard Module Reference: export.h"
+---
+
+Provides macros for properly exporting or importing symbols from shared
+libraries.
+
+## Macros
+
+<div id="macro-documentation-section">
+
+<h3 id="sb_export" class="small-h3">SB_EXPORT</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_export_private" class="small-h3">SB_EXPORT_PRIVATE</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_import" class="small-h3">SB_IMPORT</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+</div>
+
+## Functions
+
+### means
+
+**Description**
+
+COMPONENT_BUILD is defined when generating shared libraries for each project,
+
+**Declaration**
+
+```
+// rather than static libraries. This means we need to be careful about
+// EXPORT/IMPORT.
+// SB_IS_LIBRARY is defined when building Starboard as a shared library to be
+// linked into a client app. In this case, we want to explicitly define
+// EXPORT/IMPORT so that Starboard's symbols are visible to such clients.
+#if defined(STARBOARD_IMPLEMENTATION)
+// STARBOARD_IMPLEMENTATION is defined when building the Starboard library
+// sources, and shouldn't be defined when building sources that are clients of
+// Starboard.
+#else  // defined(STARBOARD_IMPLEMENTATION)
+#endif
+#else  // defined(COMPONENT_BUILD) || SB_IS(LIBRARY)
+#define SB_EXPORT
+#define SB_EXPORT_PRIVATE
+#define SB_IMPORT
+#endif  // defined(COMPONENT_BUILD)
+#endif  // STARBOARD_EXPORT_H_
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>we need to be careful</code><br>
+        <code>about</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>//</code><br>
+        <code>EXPORT/IMPORT.</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>// SB_IS_LIBRARY is defined when building Starboard as a shared library to</code><br>
+        <code>be</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>// linked into a client app. In this</code><br>
+        <code>case</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>we want to explicitly</code><br>
+        <code>define</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>// EXPORT/IMPORT so that Starboard's symbols are visible to such</code><br>
+        <code>clients.</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>#if</code><br>
+        <code>defined(STARBOARD_IMPLEMENTATION</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/file.md b/src/cobalt/site/docs/reference/starboard/modules/file.md
new file mode 100644
index 0000000..5d16c4a
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/file.md
@@ -0,0 +1,868 @@
+---
+layout: doc
+title: "Starboard Module Reference: file.h"
+---
+
+Defines file system input/output functions.
+
+## Enums
+
+### SbFileError
+
+kSbFileErrorAccessDenied is returned when a call fails because of a
+filesystem restriction. kSbFileErrorSecurity is returned when a security
+policy doesn't allow the operation to be executed.
+
+**Values**
+
+*   `kSbFileOk`
+*   `kSbFileErrorFailed`
+*   `kSbFileErrorInUse`
+*   `kSbFileErrorExists`
+*   `kSbFileErrorNotFound`
+*   `kSbFileErrorAccessDenied`
+*   `kSbFileErrorTooManyOpened`
+*   `kSbFileErrorNoMemory`
+*   `kSbFileErrorNoSpace`
+*   `kSbFileErrorNotADirectory`
+*   `kSbFileErrorInvalidOperation`
+*   `kSbFileErrorSecurity`
+*   `kSbFileErrorAbort`
+*   `kSbFileErrorNotAFile`
+*   `kSbFileErrorNotEmpty`
+*   `kSbFileErrorInvalidUrl`
+*   `kSbFileErrorMax` - Put new entries here and increment kSbFileErrorMax.
+
+### SbFileFlags
+
+Flags that define how a file is used in the application. These flags should
+be or'd together when passed to SbFileOpen to open or create a file.<br>
+The following five flags are mutually exclusive. You must specify exactly one
+of them:
+<ul><li>`kSbFileOpenAlways`
+</li><li>`kSbFileOpenOnly`
+</li><li>`kSbFileOpenTruncated`
+</li><li>`kSbFileCreateAlways`
+</li><li>`kSbFileCreateOnly`</li></ul>
+In addition, one or more of the following flags must be specified:
+<ul><li>`kSbFileRead`
+</li><li>`kSbFileWrite`</li></ul>
+The `kSbFileAsync` flag is optional.
+
+**Values**
+
+*   `kSbFileOpenOnly` - Opens a file, only if it exists.
+*   `kSbFileCreateOnly` - Creates a new file, only if it does not already exist.
+*   `kSbFileOpenAlways` - Opens an existing file at the specified path or creates a new file at that path.
+*   `kSbFileCreateAlways` - Creates a new file at the specified path or overwrites an existing file at that path.
+*   `kSbFileOpenTruncated` - Opens a file and truncates it to zero, only if it exists.
+*   `kSbFileRead`
+*   `kSbFileWrite`
+*   `kSbFileAsync` - May allow asynchronous I/O on some platforms, meaning that calls to Read or Write will only return the data that is readily available.
+
+### SbFileWhence
+
+This explicit mapping matches both FILE_ on Windows and SEEK_ on Linux.
+
+**Values**
+
+*   `kSbFileFromBegin`
+*   `kSbFileFromCurrent`
+*   `kSbFileFromEnd`
+
+## Structs
+
+### SbFileInfo
+
+Used to hold information about a file.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>int64_t</code><br>        <code>size</code></td>    <td>The size of the file in bytes. Undefined when is_directory is true.</td>  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>is_directory</code></td>    <td>Whether the file corresponds to a directory.</td>  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>is_symbolic_link</code></td>    <td>Whether the file corresponds to a symbolic link.</td>  </tr>
+  <tr>
+    <td><code>SbTime</code><br>        <code>last_modified</code></td>    <td>The last modified time of a file.</td>  </tr>
+  <tr>
+    <td><code>SbTime</code><br>        <code>last_accessed</code></td>    <td>The last accessed time of a file.</td>  </tr>
+  <tr>
+    <td><code>SbTime</code><br>        <code>creation_time</code></td>    <td>The creation time of a file.</td>  </tr>
+</table>
+
+### SbFilePrivate
+
+Private structure representing an open file.
+
+## Functions
+
+### SbFileCanOpen
+
+**Description**
+
+Indicates whether <code><a href="#sbfileopen">SbFileOpen()</a></code> with the given `flags` is allowed for `path`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbFileCanOpen-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbFileCanOpen-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbFileCanOpen-declaration">
+<pre>
+SB_EXPORT bool SbFileCanOpen(const char* path, int flags);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbFileCanOpen-stub">
+
+```
+#include "starboard/file.h"
+
+bool SbFileCanOpen(const char* /*path*/, int /*flags*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>path</code></td>
+    <td>The absolute path to be checked.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>flags</code></td>
+    <td>The flags that are being evaluated for the given <code>path</code>.</td>
+  </tr>
+</table>
+
+### SbFileClose
+
+**Description**
+
+Closes `file`. The return value indicates whether the file was closed
+successfully.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbFileClose-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbFileClose-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbFileClose-declaration">
+<pre>
+SB_EXPORT bool SbFileClose(SbFile file);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbFileClose-stub">
+
+```
+#include "starboard/file.h"
+
+bool SbFileClose(SbFile /*file*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbFile</code><br>        <code>file</code></td>
+    <td>The absolute path of the file to be closed.</td>
+  </tr>
+</table>
+
+### SbFileDelete
+
+**Description**
+
+Deletes the regular file, symlink, or empty directory at `path`. This
+function is used primarily to clean up after unit tests. On some platforms,
+this function fails if the file in question is being held open.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbFileDelete-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbFileDelete-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbFileDelete-declaration">
+<pre>
+SB_EXPORT bool SbFileDelete(const char* path);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbFileDelete-stub">
+
+```
+#include "starboard/file.h"
+
+bool SbFileDelete(const char* /*path*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>path</code></td>
+    <td>The absolute path fo the file, symlink, or directory to be deleted.</td>
+  </tr>
+</table>
+
+### SbFileExists
+
+**Description**
+
+Indicates whether a file or directory exists at `path`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbFileExists-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbFileExists-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbFileExists-declaration">
+<pre>
+SB_EXPORT bool SbFileExists(const char* path);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbFileExists-stub">
+
+```
+#include "starboard/file.h"
+
+bool SbFileExists(const char* /*path*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>path</code></td>
+    <td>The absolute path of the file or directory being checked.</td>
+  </tr>
+</table>
+
+### SbFileFlush
+
+**Description**
+
+Flushes the write buffer to `file`. Data written via <code><a href="#sbfilewrite">SbFileWrite</a></code> is not
+necessarily committed until the SbFile is flushed or closed.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbFileFlush-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbFileFlush-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbFileFlush-declaration">
+<pre>
+SB_EXPORT bool SbFileFlush(SbFile file);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbFileFlush-stub">
+
+```
+#include "starboard/file.h"
+
+bool SbFileFlush(SbFile /*file*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbFile</code><br>        <code>file</code></td>
+    <td>The SbFile to which the write buffer is flushed.</td>
+  </tr>
+</table>
+
+### SbFileGetInfo
+
+**Description**
+
+Retrieves information about `file`. The return value indicates whether the
+file information was retrieved successfully.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbFileGetInfo-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbFileGetInfo-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbFileGetInfo-declaration">
+<pre>
+SB_EXPORT bool SbFileGetInfo(SbFile file, SbFileInfo* out_info);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbFileGetInfo-stub">
+
+```
+#include "starboard/file.h"
+
+bool SbFileGetInfo(SbFile /*file*/, SbFileInfo* /*out_info*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbFile</code><br>        <code>file</code></td>
+    <td>The SbFile for which information is retrieved.</td>
+  </tr>
+  <tr>
+    <td><code>SbFileInfo*</code><br>        <code>out_info</code></td>
+    <td>The variable into which the retrieved data is placed. This
+variable is not touched if the operation is not successful.</td>
+  </tr>
+</table>
+
+### SbFileGetPathInfo
+
+**Description**
+
+Retrieves information about the file at `path`. The return value indicates
+whether the file information was retrieved successfully.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbFileGetPathInfo-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbFileGetPathInfo-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbFileGetPathInfo-declaration">
+<pre>
+SB_EXPORT bool SbFileGetPathInfo(const char* path, SbFileInfo* out_info);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbFileGetPathInfo-stub">
+
+```
+#include "starboard/file.h"
+
+bool SbFileGetPathInfo(const char* /*path*/, SbFileInfo* /*out_info*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>path</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>SbFileInfo*</code><br>        <code>out_info</code></td>
+    <td>The variable into which the retrieved data is placed. This
+variable is not touched if the operation is not successful.</td>
+  </tr>
+</table>
+
+### SbFileIsValid
+
+**Description**
+
+Returns whether the given file handle is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbFileIsValid(SbFile file) {
+  return file != kSbFileInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbFile</code><br>
+        <code>file</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbFileModeStringToFlags
+
+**Description**
+
+Converts an ISO `fopen()` mode string into flags that can be equivalently
+passed into <code><a href="#sbfileopen">SbFileOpen()</a></code>.
+
+**Declaration**
+
+```
+SB_EXPORT int SbFileModeStringToFlags(const char* mode);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>mode</code></td>
+    <td>The mode string to be converted into flags.</td>
+  </tr>
+</table>
+
+### SbFileOpen
+
+**Description**
+
+Opens the file at `path`, which must be absolute, creating it if specified by
+`flags`. The read/write position is at the beginning of the file.<br>
+Note that this function only guarantees the correct behavior when `path`
+points to a file. The behavior is undefined if `path` points to a directory.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbFileOpen-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbFileOpen-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbFileOpen-declaration">
+<pre>
+SB_EXPORT SbFile SbFileOpen(const char* path,
+                            int flags,
+                            bool* out_created,
+                            SbFileError* out_error);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbFileOpen-stub">
+
+```
+#include "starboard/file.h"
+
+SbFile SbFileOpen(const char* /*path*/,
+                  int /*flags*/,
+                  bool* /*out_created*/,
+                  SbFileError* /*out_error*/) {
+  return kSbFileInvalid;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>path</code></td>
+    <td>The absolute path of the file to be opened.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>flags</code></td>
+    <td><code>SbFileFlags</code> that determine how the file is used in the
+application. Among other things, <code>flags</code> can indicate whether the
+application should create <code>path</code> if <code>path</code> does not already exist.</td>
+  </tr>
+  <tr>
+    <td><code>bool*</code><br>        <code>out_created</code></td>
+    <td>Starboard sets this value to <code>true</code> if a new file is created
+or if an old file is truncated to zero length to simulate a new file,
+which can happen if the <code>kSbFileCreateAlways</code> flag is set. Otherwise,
+Starboard sets this value to <code>false</code>.</td>
+  </tr>
+  <tr>
+    <td><code>SbFileError*</code><br>        <code>out_error</code></td>
+    <td>If <code>path</code> cannot be created, this is set to <code>kSbFileInvalid</code>.
+Otherwise, it is <code>NULL</code>.</td>
+  </tr>
+</table>
+
+### SbFileRead
+
+**Description**
+
+Reads `size` bytes (or until EOF is reached) from `file` into `data`,
+starting at the file's current position.<br>
+The return value specifies the number of bytes read or `-1` if there was
+an error. Note that this function does NOT make a best effort to read all
+data on all platforms; rather, it just reads however many bytes are quickly
+available. However, this function can be run in a loop to make it a
+best-effort read.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbFileRead-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbFileRead-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbFileRead-declaration">
+<pre>
+SB_EXPORT int SbFileRead(SbFile file, char* data, int size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbFileRead-stub">
+
+```
+#include "starboard/file.h"
+
+int SbFileRead(SbFile /*file*/, char* /*data*/, int /*size*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbFile</code><br>        <code>file</code></td>
+    <td>The SbFile from which to read data.</td>
+  </tr>
+  <tr>
+    <td><code>char*</code><br>        <code>data</code></td>
+    <td>The variable to which data is read.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>size</code></td>
+    <td>The amount of data (in bytes) to read.</td>
+  </tr>
+</table>
+
+### SbFileReadAll
+
+**Description**
+
+Reads `size` bytes (or until EOF is reached) from `file` into `data`,
+starting from the beginning of the file.<br>
+The return value specifies the number of bytes read or `-1` if there was
+an error. Note that, unlike `SbFileRead`, this function does make a best
+effort to read all data on all platforms. As such, it is not intended for
+stream-oriented files but instead for cases when the normal expectation is
+that `size` bytes can be read unless there is an error.
+
+**Declaration**
+
+```
+static inline int SbFileReadAll(SbFile file, char* data, int size) {
+  if (!SbFileIsValid(file) || size < 0) {
+    return -1;
+  }
+  int bytes_read = 0;
+  int rv;
+  do {
+    rv = SbFileRead(file, data + bytes_read, size - bytes_read);
+    if (bytes_read <= 0) {
+      break;
+    }
+    bytes_read += rv;
+  } while (bytes_read < size);
+  return bytes_read ? bytes_read : rv;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbFile</code><br>        <code>file</code></td>
+    <td>The SbFile from which to read data.</td>
+  </tr>
+  <tr>
+    <td><code>char*</code><br>        <code>data</code></td>
+    <td>The variable to which data is read.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>size</code></td>
+    <td>The amount of data (in bytes) to read.</td>
+  </tr>
+</table>
+
+### SbFileSeek
+
+**Description**
+
+Changes the current read/write position in `file`. The return value
+identifies the resultant current read/write position in the file (relative
+to the start) or `-1` in case of an error. This function might not support
+seeking past the end of the file on some platforms.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbFileSeek-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbFileSeek-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbFileSeek-declaration">
+<pre>
+SB_EXPORT int64_t SbFileSeek(SbFile file, SbFileWhence whence, int64_t offset);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbFileSeek-stub">
+
+```
+#include "starboard/file.h"
+
+int64_t SbFileSeek(SbFile /*file*/,
+                   SbFileWhence /*whence*/,
+                   int64_t /*offset*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbFile</code><br>        <code>file</code></td>
+    <td>The SbFile in which the read/write position will be changed.</td>
+  </tr>
+  <tr>
+    <td><code>SbFileWhence</code><br>        <code>whence</code></td>
+    <td>The starting read/write position. The position is modified relative
+to this value.</td>
+  </tr>
+  <tr>
+    <td><code>int64_t</code><br>        <code>offset</code></td>
+    <td>The amount that the read/write position is changed, relative to
+<code>whence</code>.</td>
+  </tr>
+</table>
+
+### SbFileTruncate
+
+**Description**
+
+Truncates the given `file` to the given `length`. The return value indicates
+whether the file was truncated successfully.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbFileTruncate-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbFileTruncate-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbFileTruncate-declaration">
+<pre>
+SB_EXPORT bool SbFileTruncate(SbFile file, int64_t length);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbFileTruncate-stub">
+
+```
+#include "starboard/file.h"
+
+bool SbFileTruncate(SbFile /*file*/, int64_t /*length*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbFile</code><br>        <code>file</code></td>
+    <td>The file to be truncated.</td>
+  </tr>
+  <tr>
+    <td><code>int64_t</code><br>        <code>length</code></td>
+    <td>The expected length of the file after it is truncated. If <code>length</code>
+is greater than the current size of the file, then the file is extended
+with zeros. If <code>length</code> is negative, then the function is a no-op and
+returns <code>false</code>.</td>
+  </tr>
+</table>
+
+### SbFileWrite
+
+**Description**
+
+Writes the given buffer into `file` at the file's current position,
+overwriting any data that was previously there.<br>
+The return value identifies the number of bytes written, or `-1` on error.
+Note that this function does NOT make a best effort to write all data;
+rather, it writes however many bytes can be written quickly. Generally, this
+means that it writes however many bytes as possible without blocking on IO.
+Run this function in a loop to ensure that all data is written.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbFileWrite-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbFileWrite-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbFileWrite-declaration">
+<pre>
+SB_EXPORT int SbFileWrite(SbFile file, const char* data, int size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbFileWrite-stub">
+
+```
+#include "starboard/file.h"
+
+int SbFileWrite(SbFile /*file*/, const char* /*data*/, int /*size*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbFile</code><br>        <code>file</code></td>
+    <td>The SbFile to which data will be written.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>data</code></td>
+    <td>The data to be written.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>size</code></td>
+    <td>The amount of data (in bytes) to write.</td>
+  </tr>
+</table>
+
+### SbFileWriteAll
+
+**Description**
+
+Writes the given buffer into `file`, starting at the beginning of the file,
+and overwriting any data that was previously there. Unlike <code><a href="#sbfilewrite">SbFileWrite</a></code>, this
+function does make a best effort to write all data on all platforms.<br>
+The return value identifies the number of bytes written, or `-1` on error.
+
+**Declaration**
+
+```
+static inline int SbFileWriteAll(SbFile file, const char* data, int size) {
+  if (!SbFileIsValid(file) || size < 0) {
+    return -1;
+  }
+  int bytes_written = 0;
+  int rv;
+  do {
+    rv = SbFileWrite(file, data + bytes_written, size - bytes_written);
+    if (bytes_written <= 0) {
+      break;
+    }
+    bytes_written += rv;
+  } while (bytes_written < size);
+  return bytes_written ? bytes_written : rv;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbFile</code><br>        <code>file</code></td>
+    <td>The file to which data will be written.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>data</code></td>
+    <td>The data to be written.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>size</code></td>
+    <td>The amount of data (in bytes) to write.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/image.md b/src/cobalt/site/docs/reference/starboard/modules/image.md
new file mode 100644
index 0000000..d2985f1
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/image.md
@@ -0,0 +1,195 @@
+---
+layout: doc
+title: "Starboard Module Reference: image.h"
+---
+
+API for hardware accelerated image decoding. This module allows for the
+client to feed in raw, encoded data to be decoded directly into an
+SbDecodeTarget.  It also provides an interface for the client to query what
+combinations of encoded image formats and SbDecodeTargetFormats are
+supported or not.<br>
+All functions in this module are safe to call from any thread at any point
+in time.<br>
+#### SbImageIsDecodeSupported and SbImageDecode Example
+
+
+Let's assume that we're on a Blitter platform.<br>
+SbDecodeTargetProvider* provider = GetProviderFromSomewhere();
+void* data = GetCompressedJPEGFromSomewhere();
+int data_size = GetCompressedJPEGSizeFromSomewhere();
+const char* mime_type = "image/jpeg";
+SbDecodeTargetFormat format = kSbDecodeTargetFormat1PlaneRGBA;<br>
+if (!SbImageIsDecodeSupported(mime_type, format)) {
+return;
+}<br>
+SbDecodeTarget result_target = SbDecodeImage(provider, data, data_size,
+mime_type, format);
+SbBlitterSurface surface =
+SbDecodeTargetGetPlane(target, kSbDecodeTargetPlaneRGBA);
+// Do stuff with surface...<br>
+
+## Functions
+
+### SbImageDecode
+
+**Description**
+
+Attempt to decode encoded `mime_type` image data `data` of size `data_size`
+into an SbDecodeTarget of SbDecodeFormatType `format`, possibly using
+SbDecodeTargetProvider `provider`, if it is non-null.  Thus, four following
+scenarios regarding the provider may happen:<br>
+<ol><li>The provider is required by the `SbImageDecode` implementation and no
+provider is given.  The implementation should gracefully fail by
+immediately returning kSbDecodeTargetInvalid.
+</li><li>The provider is required and is passed in.  The implementation will
+proceed forward, using the SbDecodeTarget from the provider.
+</li><li>The provider is not required and is passed in.  The provider will NOT be
+called, and the implementation will proceed to decoding however it
+desires.
+</li><li>The provider is not required and is not passed in.  The implementation
+will proceed forward.</li></ol>
+Thus, it is NOT safe for clients of this API to assume that the `provider`
+it passes in will be called.  Finally, if the decode succeeds, a new
+SbDecodeTarget will be allocated. If `mime_type` image decoding for the
+requested format is not supported or the decode fails,
+kSbDecodeTargetInvalid will be returned, with any intermediate allocations
+being cleaned up in the implementation.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbImageDecode-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbImageDecode-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbImageDecode-declaration">
+<pre>
+SB_EXPORT SbDecodeTarget SbImageDecode(
+    SbDecodeTargetGraphicsContextProvider* context_provider,
+    void* data,
+    int data_size,
+    const char* mime_type,
+    SbDecodeTargetFormat format);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbImageDecode-stub">
+
+```
+#include "starboard/configuration.h"
+#include "starboard/image.h"
+
+#if !SB_HAS(GRAPHICS)
+#error "SbImageDecode requires SB_HAS(GRAPHICS)."
+#endif
+
+SbDecodeTarget SbImageDecode(SbDecodeTargetGraphicsContextProvider* provider,
+                             void* data,
+                             int data_size,
+                             const char* mime_type,
+                             SbDecodeTargetFormat format) {
+  SB_UNREFERENCED_PARAMETER(data);
+  SB_UNREFERENCED_PARAMETER(data_size);
+  SB_UNREFERENCED_PARAMETER(format);
+  SB_UNREFERENCED_PARAMETER(mime_type);
+  SB_UNREFERENCED_PARAMETER(provider);
+  return kSbDecodeTargetInvalid;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbDecodeTargetGraphicsContextProvider*</code><br>
+        <code>context_provider</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>
+        <code>data</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>data_size</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>
+        <code>mime_type</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbDecodeTargetFormat</code><br>
+        <code>format</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbImageIsDecodeSupported
+
+**Description**
+
+Whether the current platform supports hardware accelerated decoding an
+image of mime type `mime_type` into SbDecodeTargetFormat `format`.  The
+result of this function must not change over the course of the program,
+which means that the results of this function may be cached indefinitely.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbImageIsDecodeSupported-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbImageIsDecodeSupported-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbImageIsDecodeSupported-declaration">
+<pre>
+SB_EXPORT bool SbImageIsDecodeSupported(const char* mime_type,
+                                        SbDecodeTargetFormat format);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbImageIsDecodeSupported-stub">
+
+```
+#include "starboard/configuration.h"
+#include "starboard/image.h"
+
+#if !SB_HAS(GRAPHICS)
+#error "Requires SB_HAS(GRAPHICS)."
+#endif
+
+bool SbImageIsDecodeSupported(const char* mime_type,
+                              SbDecodeTargetFormat format) {
+  SB_UNREFERENCED_PARAMETER(mime_type);
+  SB_UNREFERENCED_PARAMETER(format);
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>
+        <code>mime_type</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbDecodeTargetFormat</code><br>
+        <code>format</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/index.md b/src/cobalt/site/docs/reference/starboard/modules/index.md
new file mode 100644
index 0000000..4ac923e
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/index.md
@@ -0,0 +1,5 @@
+---
+layout: doc
+title: "Starboard Modules - Reference Guide"
+---
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/input.md b/src/cobalt/site/docs/reference/starboard/modules/input.md
new file mode 100644
index 0000000..289a832
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/input.md
@@ -0,0 +1,113 @@
+---
+layout: doc
+title: "Starboard Module Reference: input.h"
+---
+
+Defines input events and associated data types.
+
+## Enums
+
+### SbInputDeviceType
+
+Identifies possible input subsystem types. The types of events that each
+device type produces correspond to `SbInputEventType` values.
+
+**Values**
+
+*   `kSbInputDeviceTypeGesture` - Input from a gesture-detection mechanism. Examples include Kinect,Wiimotes, etc...<br>Produces |Move|, |Press| and |Unpress| events.
+*   `kSbInputDeviceTypeGamepad` - Input from a gamepad, following the layout provided in the W3C Web GamepadAPI. [https://www.w3.org/TR/gamepad/]<br>Produces |Move|, |Press| and |Unpress| events.
+*   `kSbInputDeviceTypeKeyboard` - Keyboard input from a traditional keyboard or game controller chatpad.<br>Produces |Press| and |Unpress| events.
+*   `kSbInputDeviceTypeMicrophone` - Input from a microphone that would provide audio data to the caller, whomay then find some way to detect speech or other sounds within it. It mayhave processed or filtered the audio in some way before it arrives.<br>Produces |Audio| events.
+*   `kSbInputDeviceTypeMouse` - Input from a traditional mouse.<br>Produces |Move|, |Press|, and |Unpress| events.
+*   `kSbInputDeviceTypeRemote` - Input from a TV remote-control-style device.<br>Produces |Press| and |Unpress| events.
+*   `kSbInputDeviceTypeSpeechCommand` - Input from a speech command analyzer, which is some hardware or softwarethat, given a set of known phrases, activates when one of the registeredphrases is heard.<br>Produces |Command| events.
+*   `kSbInputDeviceTypeTouchScreen` - Input from a single- or multi-touchscreen.<br>Produces |Move|, |Press|, and |Unpress| events.
+*   `kSbInputDeviceTypeTouchPad` - Input from a touchpad that is not masquerading as a mouse.<br>Produces |Move|, |Press|, and |Unpress| events.
+
+### SbInputEventType
+
+The action that an input event represents.
+
+**Values**
+
+*   `kSbInputEventTypeAudio` - Receipt of Audio. Some audio data was received by the input microphone.
+*   `kSbInputEventTypeCommand` - Receipt of a command. A command was received from some semantic source,like a speech recognizer.
+*   `kSbInputEventTypeGrab` - Grab activation. This event type is deprecated.
+*   `kSbInputEventTypeMove` - Device Movement. In the case of |Mouse|, and perhaps |Gesture|, themovement tracks an absolute cursor position. In the case of |TouchPad|,only relative movements are provided.
+*   `kSbInputEventTypePress` - Key or button press activation. This could be a key on a keyboard, a buttonon a mouse or game controller, a push from a touch screen, or a gesture. An|Unpress| event is subsequently delivered when the |Press| eventterminates, such as when the key/button/finger is raised. Injecting repeatpresses is up to the client.
+*   `kSbInputEventTypeUngrab` - Grab deactivation. This event type is deprecated.
+*   `kSbInputEventTypeUnpress` - Key or button deactivation. The counterpart to the |Press| event, thisevent is sent when the key or button being pressed is released.
+*   `kSbInputEventTypeWheel` - Wheel movement. Provides relative movements of the |Mouse| wheel.
+
+## Structs
+
+### SbInputData
+
+Event data for `kSbEventTypeInput` events.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>SbWindow</code><br>        <code>window</code></td>    <td>The window in which the input was generated.</td>  </tr>
+  <tr>
+    <td><code>SbInputEventType</code><br>        <code>type</code></td>    <td>The type of input event that this represents.</td>  </tr>
+  <tr>
+    <td><code>SbInputDeviceType</code><br>        <code>device_type</code></td>    <td>The type of device that generated this input event.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>device_id</code></td>    <td>An identifier that is unique among all connected devices.</td>  </tr>
+  <tr>
+    <td><code>SbKey</code><br>        <code>key</code></td>    <td>An identifier that indicates which keyboard key or mouse button was
+involved in this event, if any. All known keys for all devices are mapped
+to a single ID space, defined by the <code>SbKey</code> enum in <code>key.h</code>.</td>  </tr>
+  <tr>
+    <td><code>wchar_t</code><br>        <code>character</code></td>    <td>The character that corresponds to the key. For an external keyboard, this
+character also depends on the keyboard language. The value is <code>0</code> if there
+is no corresponding character.</td>  </tr>
+  <tr>
+    <td><code>SbKeyLocation</code><br>        <code>key_location</code></td>    <td>The location of the specified key, in cases where there are multiple
+instances of the button on the keyboard. For example, some keyboards have
+more than one "shift" key.</td>  </tr>
+  <tr>
+    <td><code>unsigned</code><br>        <code>int key_modifiers</code></td>    <td>Key modifiers (e.g. <code>Ctrl</code>, <code>Shift</code>) held down during this input event.</td>  </tr>
+  <tr>
+    <td><code>SbInputVector</code><br>        <code>position</code></td>    <td>The (x, y) coordinates of the persistent cursor controlled by this device.
+The value is <code>0</code> if this data is not applicable. For events with type
+kSbInputEventTypeMove and device_type kSbInputDeviceTypeGamepad, this field
+is interpreted as a stick position with the range [-1, 1], with positive
+values for the down and right direction.</td>  </tr>
+  <tr>
+    <td><code>SbInputVector</code><br>        <code>delta</code></td>    <td>The relative motion vector of this input. The value is <code>0</code> if this data is
+not applicable.</td>  </tr>
+  <tr>
+    <td><code>float</code><br>        <code>pressure</code></td>    <td>The normalized pressure of the pointer input in the range of [0,1], where 0
+and 1 represent the minimum and maximum pressure the hardware is capable of
+detecting, respectively. Use NaN for devices that do not report pressure.
+This value is used for input events with device type mouse or touch screen.</td>  </tr>
+  <tr>
+    <td><code>SbInputVector</code><br>        <code>size</code></td>    <td>The (width, height) of the contact geometry of the pointer. This defines
+the size of the area under the pointer position. If (NaN, NaN) is
+specified, the value (0,0) will be used. This value is used for input
+events with device type mouse or touch screen.</td>  </tr>
+  <tr>
+    <td><code>SbInputVector</code><br>        <code>tilt</code></td>    <td>The (x, y) angle in degrees, in the range of [-90, 90] of the pointer,
+relative to the z axis. Positive values are for tilt to the right (x), and
+towards the user (y). Use (NaN, NaN) for devices that do not report tilt.
+This value is used for input events with device type mouse or touch screen.</td>  </tr>
+</table>
+
+### SbInputVector
+
+A 2-dimensional vector used to represent points and motion vectors.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>float</code><br>        <code>x</code></td>    <td></td>  </tr>
+  <tr>
+    <td><code>float</code><br>        <code>y</code></td>    <td></td>  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/key.md b/src/cobalt/site/docs/reference/starboard/modules/key.md
new file mode 100644
index 0000000..f32b7b4
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/key.md
@@ -0,0 +1,259 @@
+---
+layout: doc
+title: "Starboard Module Reference: key.h"
+---
+
+Defines the canonical set of Starboard key codes.
+
+## Enums
+
+### SbKey
+
+A standard set of key codes, ordered by value, that represent each possible
+input key across all kinds of devices. Starboard uses the semi-standard
+Windows virtual key codes documented at:
+https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
+
+**Values**
+
+*   `kSbKeyUnknown`
+*   `kSbKeyCancel`
+*   `kSbKeyBackspace`
+*   `kSbKeyBack` - You probably want kSbKeyEscape for a semantic "back".
+*   `kSbKeyTab`
+*   `kSbKeyBacktab`
+*   `kSbKeyClear`
+*   `kSbKeyReturn` - Return/Enter key
+*   `kSbKeyShift`
+*   `kSbKeyControl`
+*   `kSbKeyMenu` - Alt key
+*   `kSbKeyPause`
+*   `kSbKeyCapital`
+*   `kSbKeyKana`
+*   `kSbKeyHangul`
+*   `kSbKeyJunja`
+*   `kSbKeyFinal`
+*   `kSbKeyHanja`
+*   `kSbKeyKanji`
+*   `kSbKeyEscape`
+*   `kSbKeyConvert`
+*   `kSbKeyNonconvert`
+*   `kSbKeyAccept`
+*   `kSbKeyModechange`
+*   `kSbKeySpace`
+*   `kSbKeyPrior`
+*   `kSbKeyNext`
+*   `kSbKeyEnd`
+*   `kSbKeyHome`
+*   `kSbKeyLeft`
+*   `kSbKeyUp`
+*   `kSbKeyRight`
+*   `kSbKeyDown`
+*   `kSbKeySelect`
+*   `kSbKeyPrint`
+*   `kSbKeyExecute`
+*   `kSbKeySnapshot`
+*   `kSbKeyInsert`
+*   `kSbKeyDelete`
+*   `kSbKeyHelp`
+*   `kSbKey0`
+*   `kSbKey1`
+*   `kSbKey2`
+*   `kSbKey3`
+*   `kSbKey4`
+*   `kSbKey5`
+*   `kSbKey6`
+*   `kSbKey7`
+*   `kSbKey8`
+*   `kSbKey9`
+*   `kSbKeyA`
+*   `kSbKeyB`
+*   `kSbKeyC`
+*   `kSbKeyD`
+*   `kSbKeyE`
+*   `kSbKeyF`
+*   `kSbKeyG`
+*   `kSbKeyH`
+*   `kSbKeyI`
+*   `kSbKeyJ`
+*   `kSbKeyK`
+*   `kSbKeyL`
+*   `kSbKeyM`
+*   `kSbKeyN`
+*   `kSbKeyO`
+*   `kSbKeyP`
+*   `kSbKeyQ`
+*   `kSbKeyR`
+*   `kSbKeyS`
+*   `kSbKeyT`
+*   `kSbKeyU`
+*   `kSbKeyV`
+*   `kSbKeyW`
+*   `kSbKeyX`
+*   `kSbKeyY`
+*   `kSbKeyZ`
+*   `kSbKeyLwin`
+*   `kSbKeyCommand` - Provide the Mac name for convenience.
+*   `kSbKeyRwin`
+*   `kSbKeyApps`
+*   `kSbKeySleep`
+*   `kSbKeyNumpad0`
+*   `kSbKeyNumpad1`
+*   `kSbKeyNumpad2`
+*   `kSbKeyNumpad3`
+*   `kSbKeyNumpad4`
+*   `kSbKeyNumpad5`
+*   `kSbKeyNumpad6`
+*   `kSbKeyNumpad7`
+*   `kSbKeyNumpad8`
+*   `kSbKeyNumpad9`
+*   `kSbKeyMultiply`
+*   `kSbKeyAdd`
+*   `kSbKeySeparator`
+*   `kSbKeySubtract`
+*   `kSbKeyDecimal`
+*   `kSbKeyDivide`
+*   `kSbKeyF1`
+*   `kSbKeyF2`
+*   `kSbKeyF3`
+*   `kSbKeyF4`
+*   `kSbKeyF5`
+*   `kSbKeyF6`
+*   `kSbKeyF7`
+*   `kSbKeyF8`
+*   `kSbKeyF9`
+*   `kSbKeyF10`
+*   `kSbKeyF11`
+*   `kSbKeyF12`
+*   `kSbKeyF13`
+*   `kSbKeyF14`
+*   `kSbKeyF15`
+*   `kSbKeyF16`
+*   `kSbKeyF17`
+*   `kSbKeyF18`
+*   `kSbKeyF19`
+*   `kSbKeyF20`
+*   `kSbKeyF21`
+*   `kSbKeyF22`
+*   `kSbKeyF23`
+*   `kSbKeyF24`
+*   `kSbKeyNumlock`
+*   `kSbKeyScroll`
+*   `kSbKeyWlan`
+*   `kSbKeyPower`
+*   `kSbKeyLshift`
+*   `kSbKeyRshift`
+*   `kSbKeyLcontrol`
+*   `kSbKeyRcontrol`
+*   `kSbKeyLmenu`
+*   `kSbKeyRmenu`
+*   `kSbKeyBrowserBack`
+*   `kSbKeyBrowserForward`
+*   `kSbKeyBrowserRefresh`
+*   `kSbKeyBrowserStop`
+*   `kSbKeyBrowserSearch`
+*   `kSbKeyBrowserFavorites`
+*   `kSbKeyBrowserHome`
+*   `kSbKeyVolumeMute`
+*   `kSbKeyVolumeDown`
+*   `kSbKeyVolumeUp`
+*   `kSbKeyMediaNextTrack`
+*   `kSbKeyMediaPrevTrack`
+*   `kSbKeyMediaStop`
+*   `kSbKeyMediaPlayPause`
+*   `kSbKeyMediaLaunchMail`
+*   `kSbKeyMediaLaunchMediaSelect`
+*   `kSbKeyMediaLaunchApp1`
+*   `kSbKeyMediaLaunchApp2`
+*   `kSbKeyOem1`
+*   `kSbKeyOemPlus`
+*   `kSbKeyOemComma`
+*   `kSbKeyOemMinus`
+*   `kSbKeyOemPeriod`
+*   `kSbKeyOem2`
+*   `kSbKeyOem3`
+*   `kSbKeyBrightnessDown`
+*   `kSbKeyBrightnessUp`
+*   `kSbKeyKbdBrightnessDown`
+*   `kSbKeyOem4`
+*   `kSbKeyOem5`
+*   `kSbKeyOem6`
+*   `kSbKeyOem7`
+*   `kSbKeyOem8`
+*   `kSbKeyOem102`
+*   `kSbKeyKbdBrightnessUp`
+*   `kSbKeyDbeSbcschar`
+*   `kSbKeyDbeDbcschar`
+*   `kSbKeyPlay`
+*   `kSbKeyMediaRewind` - Other supported CEA 2014 keys.
+*   `kSbKeyMediaFastForward`
+*   `kSbKeyRed` - Key codes from the DTV Application Software Environment,http://www.atsc.org/wp-content/uploads/2015/03/a_100_4.pdf
+*   `kSbKeyGreen`
+*   `kSbKeyYellow`
+*   `kSbKeyBlue`
+*   `kSbKeyChannelUp`
+*   `kSbKeyChannelDown`
+*   `kSbKeySubtitle`
+*   `kSbKeyClosedCaption`
+*   `kSbKeyInfo`
+*   `kSbKeyGuide`
+*   `kSbKeyLast` - Key codes from OCAP,https://apps.cablelabs.com/specification/opencable-application-platform-ocap/
+*   `kSbKeyPreviousChannel`
+*   `kSbKeyLaunchThisApplication` - A button that will directly launch the current application.
+*   `kSbKeyMediaAudioTrack` - A button that will switch between different available audio tracks.
+*   `kSbKeyMouse1` - Mouse buttons, starting with the left mouse button.
+*   `kSbKeyMouse2`
+*   `kSbKeyMouse3`
+*   `kSbKeyMouse4`
+*   `kSbKeyMouse5`
+*   `kSbKeyGamepad1` - Xbox A, PS O or X (depending on region), WiiU B
+*   `kSbKeyGamepad2` - Xbox B, PS X or O (depending on region), WiiU A key
+*   `kSbKeyGamepad3` - Xbox X, PS square, WiiU Y
+*   `kSbKeyGamepad4` - Xbox Y, PS triangle, WiiU X
+*   `kSbKeyGamepadLeftBumper` - Pretty much every gamepad has bumpers at the top front of the controller,and triggers at the bottom front of the controller.
+*   `kSbKeyGamepadRightBumper`
+*   `kSbKeyGamepadLeftTrigger`
+*   `kSbKeyGamepadRightTrigger`
+*   `kSbKeyGamepad5` - Xbox 360 Back, XB1 minimize, PS and WiiU Select
+*   `kSbKeyGamepad6` - Xbox 360 Play, XB1 Menu, PS and WiiU Start
+*   `kSbKeyGamepadLeftStick` - This refers to pressing the left stick like a button.
+*   `kSbKeyGamepadRightStick` - This refers to pressing the right stick like a button.
+*   `kSbKeyGamepadDPadUp`
+*   `kSbKeyGamepadDPadDown`
+*   `kSbKeyGamepadDPadLeft`
+*   `kSbKeyGamepadDPadRight`
+*   `kSbKeyGamepadSystem` - The system key in the middle of the gamepad, if it exists.
+*   `kSbKeyGamepadLeftStickUp` - Codes for thumbstick to virtual dpad conversions.
+*   `kSbKeyGamepadLeftStickDown`
+*   `kSbKeyGamepadLeftStickLeft`
+*   `kSbKeyGamepadLeftStickRight`
+*   `kSbKeyGamepadRightStickUp`
+*   `kSbKeyGamepadRightStickDown`
+*   `kSbKeyGamepadRightStickLeft`
+*   `kSbKeyGamepadRightStickRight`
+
+### SbKeyLocation
+
+**Values**
+
+*   `kSbKeyLocationUnspecified`
+*   `kSbKeyLocationLeft`
+*   `kSbKeyLocationRight`
+
+### SbKeyModifiers
+
+Bit-mask of key modifiers.
+
+**Values**
+
+*   `kSbKeyModifiersNone`
+*   `kSbKeyModifiersAlt`
+*   `kSbKeyModifiersCtrl`
+*   `kSbKeyModifiersMeta`
+*   `kSbKeyModifiersShift`
+*   `kSbKeyModifiersPointerButtonLeft`
+*   `kSbKeyModifiersPointerButtonRight`
+*   `kSbKeyModifiersPointerButtonMiddle`
+*   `kSbKeyModifiersPointerButtonBack`
+*   `kSbKeyModifiersPointerButtonForward`
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/log.md b/src/cobalt/site/docs/reference/starboard/modules/log.md
new file mode 100644
index 0000000..7e9fe6b
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/log.md
@@ -0,0 +1,605 @@
+---
+layout: doc
+title: "Starboard Module Reference: log.h"
+---
+
+Defines debug logging functions.
+
+## Enums
+
+### SbLogPriority
+
+The priority at which a message should be logged. The platform may be
+configured to filter logs by priority, or render them differently.
+
+**Values**
+
+*   `kSbLogPriorityUnknown`
+*   `kSbLogPriorityInfo`
+*   `kSbLogPriorityWarning`
+*   `kSbLogPriorityError`
+*   `kSbLogPriorityFatal`
+
+## Macros
+
+<div id="macro-documentation-section">
+
+<h3 id="sb_check" class="small-h3">SB_CHECK</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_dcheck" class="small-h3">SB_DCHECK</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_dlog" class="small-h3">SB_DLOG</h3>
+
+<h3 id="sb_dlog_if" class="small-h3">SB_DLOG_IF</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_dlog_is_on" class="small-h3">SB_DLOG_IS_ON</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_dstack" class="small-h3">SB_DSTACK</h3>
+
+<h3 id="sb_eat_stream_parameters" class="small-h3">SB_EAT_STREAM_PARAMETERS</h3>
+
+<h3 id="sb_lazy_stream" class="small-h3">SB_LAZY_STREAM</h3>
+
+<h3 id="sb_log" class="small-h3">SB_LOG</h3>
+
+<h3 id="sb_logging_is_official_build" class="small-h3">SB_LOGGING_IS_OFFICIAL_BUILD</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_log_if" class="small-h3">SB_LOG_IF</h3>
+
+<h3 id="sb_log_is_on" class="small-h3">SB_LOG_IS_ON</h3>
+
+<h3 id="sb_log_message_0" class="small-h3">SB_LOG_MESSAGE_0</h3>
+
+Compatibility with base/logging.h which defines ERROR to be 0 to workaround
+some system header defines that do the same thing.
+
+<h3 id="sb_log_message_error" class="small-h3">SB_LOG_MESSAGE_ERROR</h3>
+
+<h3 id="sb_log_message_fatal" class="small-h3">SB_LOG_MESSAGE_FATAL</h3>
+
+<h3 id="sb_log_message_info" class="small-h3">SB_LOG_MESSAGE_INFO</h3>
+
+<h3 id="sb_log_message_warning" class="small-h3">SB_LOG_MESSAGE_WARNING</h3>
+
+<h3 id="sb_log_stream" class="small-h3">SB_LOG_STREAM</h3>
+
+<h3 id="sb_notimplemented" class="small-h3">SB_NOTIMPLEMENTED</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_notimplemented_in" class="small-h3">SB_NOTIMPLEMENTED_IN</h3>
+
+<h3 id="sb_notimplemented_msg" class="small-h3">SB_NOTIMPLEMENTED_MSG</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_notimplemented_policy" class="small-h3">SB_NOTIMPLEMENTED_POLICY</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_notreached" class="small-h3">SB_NOTREACHED</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="sb_stack" class="small-h3">SB_STACK</h3>
+
+<h3 id="sb_stack_if" class="small-h3">SB_STACK_IF</h3>
+
+</div>
+
+## Functions
+
+### Break
+
+**Declaration**
+
+```
+SB_EXPORT void Break();
+```
+
+### GetMinLogLevel
+
+**Declaration**
+
+```
+SB_EXPORT SbLogPriority GetMinLogLevel();
+```
+
+### SbLog
+
+**Description**
+
+Writes `message` to the platform's debug output log.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbLog-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbLog-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbLog-declaration">
+<pre>
+SB_EXPORT void SbLog(SbLogPriority priority, const char* message);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbLog-stub">
+
+```
+#include "starboard/log.h"
+
+void SbLog(SbLogPriority /*priority*/, const char* /*message*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbLogPriority</code><br>        <code>priority</code></td>
+    <td>The <code>SbLog</code>Priority at which the message should be logged. Note
+that passing <code>kSbLogPriorityFatal</code> does not terminate the program. Such a
+policy must be enforced at the application level. In fact, <code>priority</code> may
+be completely ignored on many platforms.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>message</code></td>
+    <td>The message to be logged. No formatting is required to be done
+on the value, including newline termination. That said, platforms can
+adjust the message to be more suitable for their output method by
+wrapping the text, stripping unprintable characters, etc.</td>
+  </tr>
+</table>
+
+### SbLogFlush
+
+**Description**
+
+Flushes the log buffer on some platforms.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbLogFlush-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbLogFlush-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbLogFlush-declaration">
+<pre>
+SB_EXPORT void SbLogFlush();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbLogFlush-stub">
+
+```
+#include "starboard/log.h"
+
+void SbLogFlush() {
+}
+```
+
+  </div>
+</div>
+
+### SbLogFormat
+
+**Description**
+
+A log output method that additionally performs a string format on the
+data being logged.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbLogFormat-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbLogFormat-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbLogFormat-declaration">
+<pre>
+SB_EXPORT void SbLogFormat(const char* format, va_list args)
+    SB_PRINTF_FORMAT(1, 0);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbLogFormat-stub">
+
+```
+#include "starboard/log.h"
+
+void SbLogFormat(const char* /*format*/, va_list /*arguments*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>
+        <code>format</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>va_list</code><br>
+        <code>args</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbLogFormatF
+
+**Description**
+
+Inline wrapper of <code><a href="#sblog">SbLog</a></code>Format that converts from ellipsis to va_args.
+
+**Declaration**
+
+```
+static SB_C_INLINE void SbLogFormatF(const char* format, ...)
+    SB_PRINTF_FORMAT(1, 2);
+void SbLogFormatF(const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  SbLogFormat(format, args);
+  va_end(args);
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>
+        <code>format</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code></code><br>
+        <code>...</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbLogIsTty
+
+**Description**
+
+Indicates whether the log output goes to a TTY or is being redirected.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbLogIsTty-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbLogIsTty-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbLogIsTty-declaration">
+<pre>
+SB_EXPORT bool SbLogIsTty();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbLogIsTty-stub">
+
+```
+#include "starboard/log.h"
+
+bool SbLogIsTty() {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+### SbLogRaw
+
+**Description**
+
+A bare-bones log output method that is async-signal-safe, i.e. safe to call
+from an asynchronous signal handler (e.g. a `SIGSEGV` handler). It should not
+do any additional formatting.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbLogRaw-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbLogRaw-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbLogRaw-declaration">
+<pre>
+SB_EXPORT void SbLogRaw(const char* message);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbLogRaw-stub">
+
+```
+#include "starboard/log.h"
+
+void SbLogRaw(const char* /*message*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>message</code></td>
+    <td>The message to be logged.</td>
+  </tr>
+</table>
+
+### SbLogRawDumpStack
+
+**Description**
+
+Dumps the stack of the current thread to the log in an async-signal-safe
+manner, i.e. safe to call from an asynchronous signal handler (e.g. a
+`SIGSEGV` handler). Does not include <code>SbLogRawDumpStack</code> itself.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbLogRawDumpStack-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbLogRawDumpStack-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbLogRawDumpStack-declaration">
+<pre>
+SB_EXPORT void SbLogRawDumpStack(int frames_to_skip);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbLogRawDumpStack-stub">
+
+```
+#include "starboard/log.h"
+
+void SbLogRawDumpStack(int /*frames_to_skip*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>frames_to_skip</code></td>
+    <td>The number of frames to skip from the top of the stack
+when dumping the current thread to the log. This parameter lets you remove
+noise from helper functions that might end up on top of every stack dump
+so that the stack dump is just the relevant function stack where the
+problem occurred.</td>
+  </tr>
+</table>
+
+### SbLogRawFormat
+
+**Description**
+
+A formatted log output method that is async-signal-safe, i.e. safe to call
+from an asynchronous signal handler (e.g. a `SIGSEGV` handler).
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbLogRawFormat-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbLogRawFormat-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbLogRawFormat-declaration">
+<pre>
+SB_EXPORT void SbLogRawFormat(const char* format, va_list args)
+    SB_PRINTF_FORMAT(1, 0);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbLogRawFormat-stub">
+
+```
+#include "starboard/log.h"
+
+void SbLogRawFormat(const char* /*format*/, va_list /*arguments*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>
+        <code>format</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>va_list</code><br>
+        <code>args</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbLogRawFormatF
+
+**Description**
+
+Inline wrapper of <code><a href="#sblog">SbLog</a></code>Format to convert from ellipsis to va_args.
+
+**Declaration**
+
+```
+static SB_C_INLINE void SbLogRawFormatF(const char* format, ...)
+    SB_PRINTF_FORMAT(1, 2);
+void SbLogRawFormatF(const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  SbLogRawFormat(format, args);
+  va_end(args);
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>
+        <code>format</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code></code><br>
+        <code>...</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SetMinLogLevel
+
+**Declaration**
+
+```
+SB_EXPORT void SetMinLogLevel(SbLogPriority level);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbLogPriority</code><br>
+        <code>level</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### causes
+
+**Declaration**
+
+```
+// SB_EXPORT'd. Using SB_EXPORT here directly causes issues on Windows because
+// it uses std classes which also need to be exported.
+class LogMessage {
+ public:
+  LogMessage(const char* file, int line, SbLogPriority priority);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>issues on Windows</code><br>
+        <code>because</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>// it uses std classes which also need to be</code><br>
+        <code>exported.</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>class LogMessage</code><br>
+        <code>{</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code></code><br>
+        <code>public:</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>LogMessage(const char*</code><br>
+        <code>file</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>line</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbLogPriority</code><br>
+        <code>priority</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### count 
+
+**Declaration**
+
+```
+    static int count = 0;                                \
+    if (0 == count++) {                                  \
+      SbLog(kSbLogPriorityError, SB_NOTIMPLEMENTED_MSG); \
+    }                                                    \
+  } while (0)
+#endif
+#endif  // __cplusplus
+#endif  // STARBOARD_LOG_H_
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>= 0;                               </code><br>
+        <code>\</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>if (0 ==</code><br>
+        <code>count++</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/media.md b/src/cobalt/site/docs/reference/starboard/modules/media.md
new file mode 100644
index 0000000..c561621
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/media.md
@@ -0,0 +1,709 @@
+---
+layout: doc
+title: "Starboard Module Reference: media.h"
+---
+
+Provides media definitions that are common between the Decoder and Player
+interfaces.
+
+## Enums
+
+### SbMediaAudioCodec
+
+Types of audio elementary streams that can be supported.
+
+**Values**
+
+*   `kSbMediaAudioCodecNone`
+*   `kSbMediaAudioCodecAac`
+*   `kSbMediaAudioCodecOpus`
+*   `kSbMediaAudioCodecVorbis`
+
+### SbMediaAudioCodingType
+
+Possible audio coding types.
+
+**Values**
+
+*   `kSbMediaAudioCodingTypeNone`
+*   `kSbMediaAudioCodingTypeAac`
+*   `kSbMediaAudioCodingTypeAc3`
+*   `kSbMediaAudioCodingTypeAtrac`
+*   `kSbMediaAudioCodingTypeBitstream`
+*   `kSbMediaAudioCodingTypeDolbyDigitalPlus`
+*   `kSbMediaAudioCodingTypeDts`
+*   `kSbMediaAudioCodingTypeMpeg1`
+*   `kSbMediaAudioCodingTypeMpeg2`
+*   `kSbMediaAudioCodingTypeMpeg3`
+*   `kSbMediaAudioCodingTypePcm`
+
+### SbMediaAudioConnector
+
+Possible audio connector types.
+
+**Values**
+
+*   `kSbMediaAudioConnectorNone`
+*   `kSbMediaAudioConnectorAnalog`
+*   `kSbMediaAudioConnectorBluetooth`
+*   `kSbMediaAudioConnectorHdmi`
+*   `kSbMediaAudioConnectorNetwork`
+*   `kSbMediaAudioConnectorSpdif`
+*   `kSbMediaAudioConnectorUsb`
+
+### SbMediaAudioFrameStorageType
+
+Possible audio frame storage types.
+
+**Values**
+
+*   `kSbMediaAudioFrameStorageTypeInterleaved` - The samples of a multi-channel audio stream are stored in one continuousbuffer. Samples at the same timestamp are stored one after another. Forexample, for a stereo stream with channels L and R that contains sampleswith timestamps 0, 1, 2, etc., the samples are stored in one buffer as"L0 R0 L1 R1 L2 R2 ...".
+*   `kSbMediaAudioFrameStorageTypePlanar` - The samples of each channel are stored in their own continuous buffer.For example, for a stereo stream with channels L and R that containssamples with timestamps 0, 1, 2, etc., the samples are stored in twobuffers "L0 L1 L2 ..." and "R0 R1 R2 ...".
+
+### SbMediaAudioSampleType
+
+Possible audio sample types.
+
+**Values**
+
+*   `kSbMediaAudioSampleTypeInt16`
+*   `kSbMediaAudioSampleTypeFloat32`
+
+### SbMediaMatrixId
+
+**Values**
+
+*   `kSbMediaMatrixIdRgb` - The first 0-255 values should match the H264 specification (see Table E-5Matrix Coefficients in https://www.itu.int/rec/T-REC-H.264/en).
+*   `kSbMediaMatrixIdBt709`
+*   `kSbMediaMatrixIdUnspecified`
+*   `kSbMediaMatrixIdReserved`
+*   `kSbMediaMatrixIdFcc`
+*   `kSbMediaMatrixIdBt470Bg`
+*   `kSbMediaMatrixIdSmpte170M`
+*   `kSbMediaMatrixIdSmpte240M`
+*   `kSbMediaMatrixIdYCgCo`
+*   `kSbMediaMatrixIdBt2020NonconstantLuminance`
+*   `kSbMediaMatrixIdBt2020ConstantLuminance`
+*   `kSbMediaMatrixIdYDzDx`
+*   `kSbMediaMatrixIdLastStandardValue`
+*   `kSbMediaMatrixIdUnknown` - Chrome-specific values start at 1000
+*   `kSbMediaMatrixIdLast`
+
+### SbMediaPrimaryId
+
+**Values**
+
+*   `kSbMediaPrimaryIdReserved0` - The first 0-255 values should match the H264 specification (see Table E-3Colour Primaries in https://www.itu.int/rec/T-REC-H.264/en).
+*   `kSbMediaPrimaryIdBt709`
+*   `kSbMediaPrimaryIdUnspecified`
+*   `kSbMediaPrimaryIdReserved`
+*   `kSbMediaPrimaryIdBt470M`
+*   `kSbMediaPrimaryIdBt470Bg`
+*   `kSbMediaPrimaryIdSmpte170M`
+*   `kSbMediaPrimaryIdSmpte240M`
+*   `kSbMediaPrimaryIdFilm`
+*   `kSbMediaPrimaryIdBt2020`
+*   `kSbMediaPrimaryIdSmpteSt4281`
+*   `kSbMediaPrimaryIdSmpteSt4312`
+*   `kSbMediaPrimaryIdSmpteSt4321`
+*   `kSbMediaPrimaryIdLastStandardValue`
+*   `kSbMediaPrimaryIdUnknown` - Chrome-specific values start at 1000.
+*   `kSbMediaPrimaryIdXyzD50`
+*   `kSbMediaPrimaryIdCustom`
+
+### SbMediaRangeId
+
+This corresponds to the WebM Range enum which is part of WebM color data
+(see http://www.webmproject.org/docs/container/#Range).
+H.264 only uses a bool, which corresponds to the LIMITED/FULL values.
+Chrome-specific values start at 1000.
+
+**Values**
+
+*   `kSbMediaRangeIdUnspecified` - Range is not explicitly specified / unknown.
+*   `kSbMediaRangeIdLimited` - Limited Rec. 709 color range with RGB values ranging from 16 to 235.
+*   `kSbMediaRangeIdFull` - Full RGB color range with RGB valees from 0 to 255.
+*   `kSbMediaRangeIdDerived` - Range is defined by TransferId/MatrixId.
+
+### SbMediaSupportType
+
+Indicates how confident the device is that it can play media resources
+of the given type. The values are a direct map of the canPlayType() method
+specified at the following link:
+https://www.w3.org/TR/2011/WD-html5-20110113/video.html#dom-navigator-canplaytype
+
+**Values**
+
+*   `kSbMediaSupportTypeNotSupported` - The media type cannot be played.
+*   `kSbMediaSupportTypeMaybe` - Cannot determinate if the media type is playable without playing it.
+*   `kSbMediaSupportTypeProbably` - The media type seems to be playable.
+
+### SbMediaTransferId
+
+**Values**
+
+*   `kSbMediaTransferIdReserved0` - The first 0-255 values should match the H264 specification (see Table E-4Transfer Characteristics in https://www.itu.int/rec/T-REC-H.264/en).
+*   `kSbMediaTransferIdBt709`
+*   `kSbMediaTransferIdUnspecified`
+*   `kSbMediaTransferIdReserved`
+*   `kSbMediaTransferIdGamma22`
+*   `kSbMediaTransferIdGamma28`
+*   `kSbMediaTransferIdSmpte170M`
+*   `kSbMediaTransferIdSmpte240M`
+*   `kSbMediaTransferIdLinear`
+*   `kSbMediaTransferIdLog`
+*   `kSbMediaTransferIdLogSqrt`
+*   `kSbMediaTransferIdIec6196624`
+*   `kSbMediaTransferIdBt1361Ecg`
+*   `kSbMediaTransferIdIec6196621`
+*   `kSbMediaTransferId10BitBt2020`
+*   `kSbMediaTransferId12BitBt2020`
+*   `kSbMediaTransferIdSmpteSt2084`
+*   `kSbMediaTransferIdSmpteSt4281`
+*   `kSbMediaTransferIdAribStdB67` - AKA hybrid-log gamma, HLG.
+*   `kSbMediaTransferIdLastStandardValue`
+*   `kSbMediaTransferIdUnknown` - Chrome-specific values start at 1000.
+*   `kSbMediaTransferIdGamma24`
+*   `kSbMediaTransferIdSmpteSt2084NonHdr` - This is an ad-hoc transfer function that decodes SMPTE 2084 contentinto a 0-1 range more or less suitable for viewing on a non-hdrdisplay.
+*   `kSbMediaTransferIdCustom` - TODO: Need to store an approximation of the gamma function(s).
+*   `kSbMediaTransferIdLast`
+
+### SbMediaType
+
+Types of media component streams.
+
+**Values**
+
+*   `kSbMediaTypeAudio` - Value used for audio streams.
+*   `kSbMediaTypeVideo` - Value used for video streams.
+
+### SbMediaVideoCodec
+
+Types of video elementary streams that could be supported.
+
+**Values**
+
+*   `kSbMediaVideoCodecNone`
+*   `kSbMediaVideoCodecH264`
+*   `kSbMediaVideoCodecH265`
+*   `kSbMediaVideoCodecMpeg2`
+*   `kSbMediaVideoCodecTheora`
+*   `kSbMediaVideoCodecVc1`
+*   `kSbMediaVideoCodecVp10`
+*   `kSbMediaVideoCodecVp8`
+*   `kSbMediaVideoCodecVp9`
+
+## Structs
+
+### SbMediaAudioConfiguration
+
+A structure describing the audio configuration parameters of a single audio
+output.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>index</code></td>    <td>The platform-defined index of the associated audio output.</td>  </tr>
+  <tr>
+    <td><code>SbMediaAudioConnector</code><br>        <code>connector</code></td>    <td>The type of audio connector. Will be the empty <code>kSbMediaAudioConnectorNone</code>
+if this device cannot provide this information.</td>  </tr>
+  <tr>
+    <td><code>SbTime</code><br>        <code>latency</code></td>    <td>The expected latency of audio over this output, in microseconds, or <code>0</code> if
+this device cannot provide this information.</td>  </tr>
+  <tr>
+    <td><code>SbMediaAudioCodingType</code><br>        <code>coding_type</code></td>    <td>The type of audio coding used over this connection.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>number_of_channels</code></td>    <td>The number of audio channels currently supported by this device output, or
+<code>0</code> if this device cannot provide this information, in which case the
+caller can probably assume stereo output.</td>  </tr>
+</table>
+
+### SbMediaAudioHeader
+
+An audio sequence header, which is a description of a given audio stream.
+This, in hexadecimal string form, acts as a set of instructions to the audio
+decoder.<br>
+The Sequence Header consists of a little-endian hexadecimal encoded
+`WAVEFORMATEX` structure followed by an Audio-specific configuration field.
+The `WAVEFORMATEX` structure is specified at:
+http://msdn.microsoft.com/en-us/library/dd390970(v=vs.85).aspx
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>uint16_t</code><br>        <code>format_tag</code></td>    <td>The waveform-audio format type code.</td>  </tr>
+  <tr>
+    <td><code>uint16_t</code><br>        <code>number_of_channels</code></td>    <td>The number of audio channels in this format. <code>1</code> for mono, <code>2</code> for stereo.</td>  </tr>
+  <tr>
+    <td><code>uint32_t</code><br>        <code>samples_per_second</code></td>    <td>The sampling rate.</td>  </tr>
+  <tr>
+    <td><code>uint32_t</code><br>        <code>average_bytes_per_second</code></td>    <td>The number of bytes per second expected with this format.</td>  </tr>
+  <tr>
+    <td><code>uint16_t</code><br>        <code>block_alignment</code></td>    <td>Byte block alignment, e.g, 4.</td>  </tr>
+  <tr>
+    <td><code>uint16_t</code><br>        <code>bits_per_sample</code></td>    <td>The bit depth for the stream this represents, e.g. <code>8</code> or <code>16</code>.</td>  </tr>
+  <tr>
+    <td><code>uint16_t</code><br>        <code>audio_specific_config_size</code></td>    <td>The size, in bytes, of the audio_specific_config.</td>  </tr>
+  <tr>
+    <td><code>const</code><br>        <code>void* audio_specific_config</code></td>    <td>The AudioSpecificConfig, as specified in ISO/IEC-14496-3, section 1.6.2.1:
+http://read.pudn.com/downloads98/doc/comm/401153/14496/ISO_IEC_14496-3%20Part%203%20Audio/C036083E_SUB1.PDF</td>  </tr>
+  <tr>
+    <td><code>int8_t</code><br>        <code>audio_specific_config[8]</code></td>    <td></td>  </tr>
+</table>
+
+### SbMediaColorMetadata
+
+HDR (High Dynamic Range) Metadata common for HDR10 and
+WebM/VP9-based HDR formats, together with the ColorSpace. HDR
+reproduces a greater dynamic range of luminosity than is possible
+with standard digital imaging. See the Consumer Electronics
+Association press release:
+https://www.cta.tech/News/Press-Releases/2015/August/CEA-Defines-%E2%80%98HDR-Compatible%E2%80%99-Displays.aspx
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>unsigned</code><br>        <code>int bits_per_channel</code></td>    <td>Number of decoded bits per channel. A value of 0 indicates that
+the BitsPerChannel is unspecified.</td>  </tr>
+  <tr>
+    <td><code>unsigned</code><br>        <code>int chroma_subsampling_horizontal</code></td>    <td>The amount of pixels to remove in the Cr and Cb channels for
+every pixel not removed horizontally. Example: For video with
+4:2:0 chroma subsampling, the <code>chroma_subsampling_horizontal</code> should be set
+to 1.</td>  </tr>
+  <tr>
+    <td><code>unsigned</code><br>        <code>int chroma_subsampling_vertical</code></td>    <td>The amount of pixels to remove in the Cr and Cb channels for
+every pixel not removed vertically. Example: For video with
+4:2:0 chroma subsampling, the <code>chroma_subsampling_vertical</code> should be set
+to 1.</td>  </tr>
+  <tr>
+    <td><code>unsigned</code><br>        <code>int cb_subsampling_horizontal</code></td>    <td>The amount of pixels to remove in the Cb channel for every pixel
+not removed horizontally. This is additive with
+ChromaSubsamplingHorz. Example: For video with 4:2:1 chroma
+subsampling, the <code>chroma_subsampling_horizontal</code> should be set to 1 and
+<code>cb_subsampling_horizontal</code> should be set to 1.</td>  </tr>
+  <tr>
+    <td><code>unsigned</code><br>        <code>int cb_subsampling_vertical</code></td>    <td>The amount of pixels to remove in the Cb channel for every pixel
+not removed vertically. This is additive with
+<code>chroma_subsampling_vertical</code>.</td>  </tr>
+  <tr>
+    <td><code>unsigned</code><br>        <code>int chroma_siting_horizontal</code></td>    <td>How chroma is subsampled horizontally. (0: Unspecified, 1: Left
+Collocated, 2: Half)</td>  </tr>
+  <tr>
+    <td><code>unsigned</code><br>        <code>int chroma_siting_vertical</code></td>    <td>How chroma is subsampled vertically. (0: Unspecified, 1: Top
+Collocated, 2: Half)</td>  </tr>
+  <tr>
+    <td><code>SbMediaMasteringMetadata</code><br>        <code>mastering_metadata</code></td>    <td>[HDR Metadata field] SMPTE 2086 mastering data.</td>  </tr>
+  <tr>
+    <td><code>unsigned</code><br>        <code>int max_cll</code></td>    <td>[HDR Metadata field] Maximum brightness of a single pixel (Maximum
+Content Light Level) in candelas per square meter (cd/m^2).</td>  </tr>
+  <tr>
+    <td><code>unsigned</code><br>        <code>int max_fall</code></td>    <td>[HDR Metadata field] Maximum brightness of a single full frame
+(Maximum Frame-Average Light Level) in candelas per square meter
+(cd/m^2).</td>  </tr>
+  <tr>
+    <td><code>SbMediaPrimaryId</code><br>        <code>primaries</code></td>    <td>[Color Space field] The colour primaries of the video. For
+clarity, the value and meanings for Primaries are adopted from
+Table 2 of ISO/IEC 23001-8:2013/DCOR1. (0: Reserved, 1: ITU-R
+BT.709, 2: Unspecified, 3: Reserved, 4: ITU-R BT.470M, 5: ITU-R
+BT.470BG, 6: SMPTE 170M, 7: SMPTE 240M, 8: FILM, 9: ITU-R
+BT.2020, 10: SMPTE ST 428-1, 22: JEDEC P22 phosphors)</td>  </tr>
+  <tr>
+    <td><code>SbMediaTransferId</code><br>        <code>transfer</code></td>    <td>[Color Space field] The transfer characteristics of the
+video. For clarity, the value and meanings for
+TransferCharacteristics 1-15 are adopted from Table 3 of ISO/IEC
+23001-8:2013/DCOR1. TransferCharacteristics 16-18 are proposed
+values. (0: Reserved, 1: ITU-R BT.709, 2: Unspecified, 3:
+Reserved, 4: Gamma 2.2 curve, 5: Gamma 2.8 curve, 6: SMPTE 170M,
+7: SMPTE 240M, 8: Linear, 9: Log, 10: Log Sqrt, 11: IEC
+61966-2-4, 12: ITU-R BT.1361 Extended Colour Gamut, 13: IEC
+61966-2-1, 14: ITU-R BT.2020 10 bit, 15: ITU-R BT.2020 12 bit,
+16: SMPTE ST 2084, 17: SMPTE ST 428-1 18: ARIB STD-B67 (HLG))</td>  </tr>
+  <tr>
+    <td><code>SbMediaMatrixId</code><br>        <code>matrix</code></td>    <td>[Color Space field] The Matrix Coefficients of the video used to
+derive luma and chroma values from red, green, and blue color
+primaries. For clarity, the value and meanings for
+MatrixCoefficients are adopted from Table 4 of ISO/IEC
+23001-8:2013/DCOR1. (0:GBR, 1: BT709, 2: Unspecified, 3:
+Reserved, 4: FCC, 5: BT470BG, 6: SMPTE 170M, 7: SMPTE 240M, 8:
+YCOCG, 9: BT2020 Non-constant Luminance, 10: BT2020 Constant
+Luminance)</td>  </tr>
+  <tr>
+    <td><code>SbMediaRangeId</code><br>        <code>range</code></td>    <td>[Color Space field] Clipping of the color ranges. (0:
+Unspecified, 1: Broadcast Range, 2: Full range (no clipping), 3:
+Defined by MatrixCoefficients/TransferCharacteristics)</td>  </tr>
+  <tr>
+    <td><code>float</code><br>        <code>custom_primary_matrix[12]</code></td>    <td>[Color Space field] Only used if primaries ==
+kSbMediaPrimaryIdCustom.  This a row-major ordered 3 x 4
+submatrix of the 4 x 4 transform matrix.  The 4th row is
+completed as (0, 0, 0, 1).</td>  </tr>
+</table>
+
+### SbMediaMasteringMetadata
+
+SMPTE 2086 mastering data
+http://ieeexplore.ieee.org/document/7291707/
+This standard specifies the metadata items to specify the color
+volume (the color primaries, white point, and luminance range) of
+the display that was used in mastering video content. The metadata
+is specified as a set of values independent of any specific digital
+representation.
+Also see the WebM container guidelines:
+https://www.webmproject.org/docs/container/
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>float</code><br>        <code>primary_r_chromaticity_x</code></td>    <td>Red X chromaticity coordinate as defined by CIE 1931. In range [0, 1].</td>  </tr>
+  <tr>
+    <td><code>float</code><br>        <code>primary_r_chromaticity_y</code></td>    <td>Red Y chromaticity coordinate as defined by CIE 1931. In range [0, 1].</td>  </tr>
+  <tr>
+    <td><code>float</code><br>        <code>primary_g_chromaticity_x</code></td>    <td>Green X chromaticity coordinate as defined by CIE 1931. In range [0, 1].</td>  </tr>
+  <tr>
+    <td><code>float</code><br>        <code>primary_g_chromaticity_y</code></td>    <td>Green Y chromaticity coordinate as defined by CIE 1931. In range [0, 1].</td>  </tr>
+  <tr>
+    <td><code>float</code><br>        <code>primary_b_chromaticity_x</code></td>    <td>Blue X chromaticity coordinate as defined by CIE 1931. In range [0, 1].</td>  </tr>
+  <tr>
+    <td><code>float</code><br>        <code>primary_b_chromaticity_y</code></td>    <td>Blue Y chromaticity coordinate as defined by CIE 1931. In range [0, 1].</td>  </tr>
+  <tr>
+    <td><code>float</code><br>        <code>white_point_chromaticity_x</code></td>    <td>White X chromaticity coordinate as defined by CIE 1931. In range [0, 1].</td>  </tr>
+  <tr>
+    <td><code>float</code><br>        <code>white_point_chromaticity_y</code></td>    <td>White Y chromaticity coordinate as defined by CIE 1931. In range [0, 1].</td>  </tr>
+  <tr>
+    <td><code>float</code><br>        <code>luminance_max</code></td>    <td>Maximum luminance. Shall be represented in candelas per square
+meter (cd/m^2). In range [0, 9999.99].</td>  </tr>
+  <tr>
+    <td><code>float</code><br>        <code>luminance_min</code></td>    <td>Minimum luminance. Shall be represented in candelas per square
+meter (cd/m^2). In range [0, 9999.99].</td>  </tr>
+</table>
+
+### SbMediaVideoSampleInfo
+
+The set of information required by the decoder or player for each video
+sample.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>bool</code><br>        <code>is_key_frame</code></td>    <td>Indicates whether the associated sample is a key frame (I-frame).
+Video key frames must always start with SPS and PPS NAL units.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>frame_width</code></td>    <td>The frame width of this sample, in pixels. Also could be parsed from the
+Sequence Parameter Set (SPS) NAL Unit. Frame dimensions must only change on
+key frames, but may change on any key frame.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>frame_height</code></td>    <td>The frame height of this sample, in pixels. Also could be parsed from the
+Sequence Parameter Set (SPS) NAL Unit. Frame dimensions must only change on
+key frames, but may change on any key frame.</td>  </tr>
+</table>
+
+## Functions
+
+### SbMediaCanPlayMimeAndKeySystem
+
+**Description**
+
+Returns information about whether the playback of the specific media
+described by `mime` and encrypted using `key_system` can be played.<br>
+Note that neither `mime` nor `key_system` can be NULL. This function returns
+`kSbMediaSupportNotSupported` if either is NULL.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMediaCanPlayMimeAndKeySystem-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMediaCanPlayMimeAndKeySystem-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMediaCanPlayMimeAndKeySystem-declaration">
+<pre>
+SB_EXPORT SbMediaSupportType
+SbMediaCanPlayMimeAndKeySystem(const char* mime, const char* key_system);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMediaCanPlayMimeAndKeySystem-stub">
+
+```
+#include "starboard/media.h"
+
+SbMediaSupportType SbMediaCanPlayMimeAndKeySystem(const char* mime,
+                                                  const char* key_system) {
+  SB_UNREFERENCED_PARAMETER(mime);
+  SB_UNREFERENCED_PARAMETER(key_system);
+  return kSbMediaSupportTypeNotSupported;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>mime</code></td>
+    <td>The mime information of the media in the form of <code>video/webm</code>
+or <code>video/mp4; codecs="avc1.42001E"</code>. It may include arbitrary parameters
+like "codecs", "channels", etc.  Note that the "codecs" parameter may
+contain more than one codec, delimited by comma.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>key_system</code></td>
+    <td>A lowercase value in fhe form of "com.example.somesystem"
+as suggested by https://w3c.github.io/encrypted-media/#key-system
+that can be matched exactly with known DRM key systems of the platform.
+When <code>key_system</code> is an empty string, the return value is an indication for
+non-encrypted media.</td>
+  </tr>
+</table>
+
+### SbMediaGetAudioConfiguration
+
+**Description**
+
+Retrieves the current physical audio configuration of audio output
+`output_index` on this device and places it in `out_configuration`,
+which must not be NULL.<br>
+This function returns `false` if nothing could be determined on this
+platform or if `output_index` does not exist on this device.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMediaGetAudioConfiguration-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMediaGetAudioConfiguration-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMediaGetAudioConfiguration-declaration">
+<pre>
+SB_EXPORT bool SbMediaGetAudioConfiguration(
+    int output_index,
+    SbMediaAudioConfiguration* out_configuration);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMediaGetAudioConfiguration-stub">
+
+```
+#include "starboard/media.h"
+
+bool SbMediaGetAudioConfiguration(
+    int output_index,
+    SbMediaAudioConfiguration* out_configuration) {
+  SB_UNREFERENCED_PARAMETER(output_index);
+  SB_UNREFERENCED_PARAMETER(out_configuration);
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>output_index</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>SbMediaAudioConfiguration*</code><br>        <code>out_configuration</code></td>
+    <td>The variable that holds the audio configuration
+information.</td>
+  </tr>
+</table>
+
+### SbMediaGetAudioOutputCount
+
+**Description**
+
+Returns the number of audio outputs currently available on this device.
+Even if the number of outputs or their audio configurations can't be
+determined, it is expected that the platform will at least return a single
+output that supports at least stereo.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMediaGetAudioOutputCount-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMediaGetAudioOutputCount-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMediaGetAudioOutputCount-declaration">
+<pre>
+SB_EXPORT int SbMediaGetAudioOutputCount();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMediaGetAudioOutputCount-stub">
+
+```
+#include "starboard/media.h"
+
+int SbMediaGetAudioOutputCount() {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+### SbMediaIsOutputProtected
+
+**Description**
+
+Indicates whether output copy protection is currently enabled on all capable
+outputs. If `true`, then non-protection-capable outputs are expected to be
+blanked.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMediaIsOutputProtected-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMediaIsOutputProtected-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMediaIsOutputProtected-declaration">
+<pre>
+SB_EXPORT bool SbMediaIsOutputProtected();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMediaIsOutputProtected-stub">
+
+```
+#include "starboard/media.h"
+
+#include "starboard/log.h"
+
+bool SbMediaIsOutputProtected() {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+### SbMediaIsSupported
+
+**Description**
+
+Indicates whether this platform supports decoding `video_codec` and
+`audio_codec` along with decrypting using `key_system`. If `video_codec` is
+`kSbMediaVideoCodecNone` or if `audio_codec` is `kSbMediaAudioCodecNone`,
+this function should return `true` as long as `key_system` is supported on
+the platform to decode any supported input formats.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMediaIsSupported-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMediaIsSupported-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMediaIsSupported-declaration">
+<pre>
+SB_EXPORT bool SbMediaIsSupported(SbMediaVideoCodec video_codec,
+                                  SbMediaAudioCodec audio_codec,
+                                  const char* key_system);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMediaIsSupported-stub">
+
+```
+#include "starboard/media.h"
+
+SB_EXPORT bool SbMediaIsSupported(SbMediaVideoCodec /*video_codec*/,
+                                  SbMediaAudioCodec /*audio_codec*/,
+                                  const char* /*key_system*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMediaVideoCodec</code><br>        <code>video_codec</code></td>
+    <td>The <code>SbMediaVideoCodec</code> being checked for platform
+compatibility.</td>
+  </tr>
+  <tr>
+    <td><code>SbMediaAudioCodec</code><br>        <code>audio_codec</code></td>
+    <td>The <code>SbMediaAudioCodec</code> being checked for platform
+compatibility.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>key_system</code></td>
+    <td>The key system being checked for platform compatibility.</td>
+  </tr>
+</table>
+
+### SbMediaSetOutputProtection
+
+**Description**
+
+Enables or disables output copy protection on all capable outputs. If
+enabled, then non-protection-capable outputs are expected to be blanked.<br>
+The return value indicates whether the operation was successful, and the
+function returns a success even if the call is redundant in that it doesn't
+change the current value.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMediaSetOutputProtection-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMediaSetOutputProtection-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMediaSetOutputProtection-declaration">
+<pre>
+SB_EXPORT bool SbMediaSetOutputProtection(bool enabled);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMediaSetOutputProtection-stub">
+
+```
+#include "starboard/media.h"
+
+#include "starboard/log.h"
+
+bool SbMediaSetOutputProtection(bool enabled) {
+  SB_UNREFERENCED_PARAMETER(enabled);
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>bool</code><br>        <code>enabled</code></td>
+    <td>Indicates whether output protection is enabled (<code>true</code>) or
+disabled.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/memory.md b/src/cobalt/site/docs/reference/starboard/modules/memory.md
new file mode 100644
index 0000000..a453c3e
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/memory.md
@@ -0,0 +1,1302 @@
+---
+layout: doc
+title: "Starboard Module Reference: memory.h"
+---
+
+Defines functions for memory allocation, alignment, copying, and comparing.<br>
+#### Porters
+
+
+All of the "Unchecked" and "Free" functions must be implemented, but they
+should not be called directly. The Starboard platform wraps them with extra
+accounting under certain circumstances.<br>
+#### Porters and Application Developers
+
+
+Nobody should call the "Checked", "Unchecked" or "Free" functions directly
+because that evades Starboard's memory tracking. In both port
+implementations and Starboard client application code, you should always
+call SbMemoryAllocate and SbMemoryDeallocate rather than
+SbMemoryAllocateUnchecked and SbMemoryFree.<br>
+<ul><li>The "checked" functions are SbMemoryAllocateChecked(),
+SbMemoryReallocateChecked(), and SbMemoryAllocateAlignedChecked().
+</li><li>The "unchecked" functions are SbMemoryAllocateUnchecked(),
+SbMemoryReallocateUnchecked(), and SbMemoryAllocateAlignedUnchecked().
+</li><li>The "free" functions are SbMemoryFree() and SbMemoryFreeAligned().</li></ul>
+
+## Enums
+
+### SbMemoryMapFlags
+
+The bitwise OR of these flags should be passed to SbMemoryMap to indicate
+how the mapped memory can be used.
+
+**Values**
+
+*   `kSbMemoryMapProtectRead` - Mapped memory can be read.
+*   `kSbMemoryMapProtectWrite` - Mapped memory can be written to.
+*   `kSbMemoryMapProtectExec` - Mapped memory can be executed.
+*   `kSbMemoryMapProtectRead`
+
+## Macros
+
+<div id="macro-documentation-section">
+
+<h3 id="sb_memory_map_failed" class="small-h3">SB_MEMORY_MAP_FAILED</h3>
+
+</div>
+
+## Functions
+
+### SbAbortIfAllocationFailed
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE void SbAbortIfAllocationFailed(size_t requested_bytes,
+                                                        void* address) {
+  if (SB_UNLIKELY(requested_bytes > 0 && address == NULL)) {
+    // Will abort the program if no debugger is attached.
+    SbSystemBreakIntoDebugger();
+  }
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>requested_bytes</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>
+        <code>address</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryAlignToPageSize
+
+**Description**
+
+Rounds `size` up to SB_MEMORY_PAGE_SIZE.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE size_t SbMemoryAlignToPageSize(size_t size) {
+  return (size + SB_MEMORY_PAGE_SIZE - 1) & ~(SB_MEMORY_PAGE_SIZE - 1);
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryAllocate
+
+**Description**
+
+Allocates and returns a chunk of memory of at least `size` bytes. This
+function should be called from the client codebase. It is intended to be a
+drop-in replacement for `malloc`.<br>
+Note that this function returns `NULL` if it is unable to allocate the
+memory.
+
+**Declaration**
+
+```
+SB_EXPORT void* SbMemoryAllocate(size_t size);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The amount of memory to be allocated. If <code>size</code> is 0, the function
+may return <code>NULL</code> or it may return a unique pointer value that can be
+passed to <code><a href="#sbmemorydeallocate">SbMemoryDeallocate</a></code>.</td>
+  </tr>
+</table>
+
+### SbMemoryAllocateAligned
+
+**Description**
+
+Allocates and returns a chunk of memory of at least `size` bytes, aligned to
+`alignment`. This function should be called from the client codebase. It is
+meant to be a drop-in replacement for `memalign`.<br>
+The function returns `NULL` if it cannot allocate the memory. In addition,
+the function's behavior is undefined if `alignment` is not a power of two.
+
+**Declaration**
+
+```
+SB_EXPORT void* SbMemoryAllocateAligned(size_t alignment, size_t size);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>alignment</code></td>
+    <td>The way that data is arranged and accessed in memory. The value
+must be a power of two.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The size of the memory to be allocated. If <code>size</code> is <code>0</code>, the
+function may return <code>NULL</code> or it may return a unique aligned pointer value
+that can be passed to <code><a href="#sbmemorydeallocate">SbMemoryDeallocate</a></code>Aligned.</td>
+  </tr>
+</table>
+
+### SbMemoryAllocateAlignedChecked
+
+**Description**
+
+Same as <code><a href="#sbmemoryallocate">SbMemoryAllocate</a></code>AlignedUnchecked, but will abort() in the case of an
+allocation failure.<br>
+DO NOT CALL. Call <code><a href="#sbmemoryallocate">SbMemoryAllocate</a></code>Aligned(...) instead.
+
+**Declaration**
+
+```
+    SB_EXPORT void* SbMemoryAllocateAlignedChecked(size_t alignment,
+                                                   size_t size));
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>alignment</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryAllocateAlignedUnchecked
+
+**Description**
+
+This is the implementation of <code><a href="#sbmemoryallocate">SbMemoryAllocate</a></code>Aligned that must be
+provided by Starboard ports.<br>
+DO NOT CALL. Call <code><a href="#sbmemoryallocate">SbMemoryAllocate</a></code>Aligned(...) instead.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryAllocateAlignedUnchecked-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMemoryAllocateAlignedUnchecked-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMemoryAllocateAlignedUnchecked-declaration">
+<pre>
+    SB_EXPORT void* SbMemoryAllocateAlignedUnchecked(size_t alignment,
+                                                     size_t size));
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMemoryAllocateAlignedUnchecked-stub">
+
+```
+#include "starboard/memory.h"
+
+void* SbMemoryAllocateAlignedUnchecked(size_t /*alignment*/, size_t /*size*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>alignment</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryAllocateChecked
+
+**Description**
+
+Same as <code><a href="#sbmemoryallocate">SbMemoryAllocate</a></code>Unchecked, but will abort() in the case of an
+allocation failure.<br>
+DO NOT CALL. Call <code><a href="#sbmemoryallocate">SbMemoryAllocate</a></code>(...) instead.
+
+**Declaration**
+
+```
+    SB_EXPORT void* SbMemoryAllocateChecked(size_t size));
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryAllocateNoReport
+
+**Description**
+
+Same as <code><a href="#sbmemoryallocate">SbMemoryAllocate()</a></code> but will not report memory to the tracker. Avoid
+using this unless absolutely necessary.
+
+**Declaration**
+
+```
+SB_EXPORT void* SbMemoryAllocateNoReport(size_t size);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryAllocateUnchecked
+
+**Description**
+
+This is the implementation of <code><a href="#sbmemoryallocate">SbMemoryAllocate</a></code> that must be
+provided by Starboard ports.<br>
+DO NOT CALL. Call <code><a href="#sbmemoryallocate">SbMemoryAllocate</a></code>(...) instead.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryAllocateUnchecked-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMemoryAllocateUnchecked-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMemoryAllocateUnchecked-declaration">
+<pre>
+    SB_EXPORT void* SbMemoryAllocateUnchecked(size_t size));
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMemoryAllocateUnchecked-stub">
+
+```
+#include "starboard/memory.h"
+
+void* SbMemoryAllocateUnchecked(size_t /*size*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryCalloc
+
+**Description**
+
+A wrapper that implements a drop-in replacement for `calloc`, which is used
+in some packages.
+
+**Declaration**
+
+```
+static SB_C_INLINE void* SbMemoryCalloc(size_t count, size_t size) {
+  size_t total = count * size;
+  void* result = SbMemoryAllocate(total);
+  if (result) {
+    SbMemorySet(result, 0, total);
+  }
+  return result;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>count</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryCompare
+
+**Description**
+
+Compares the contents of the first `count` bytes of `buffer1` and `buffer2`.
+This function returns:
+<ul><li>`-1` if `buffer1` is "less-than" `buffer2`
+</li><li>`0` if `buffer1` and `buffer2` are equal
+</li><li>`1` if `buffer1` is "greater-than" `buffer2`.</li></ul>
+This function is meant to be a drop-in replacement for `memcmp`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryCompare-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMemoryCompare-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMemoryCompare-declaration">
+<pre>
+SB_EXPORT int SbMemoryCompare(const void* buffer1,
+                              const void* buffer2,
+                              size_t count);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMemoryCompare-stub">
+
+```
+#include "starboard/memory.h"
+
+int SbMemoryCompare(const void* /*buffer1*/, const void* /*buffer2*/,
+                    size_t /*count*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>buffer1</code></td>
+    <td>The first buffer to be compared.</td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>buffer2</code></td>
+    <td>The second buffer to be compared.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of bytes to be compared.</td>
+  </tr>
+</table>
+
+### SbMemoryCopy
+
+**Description**
+
+Copies `count` sequential bytes from `source` to `destination`, without
+support for the `source` and `destination` regions overlapping. This
+function is meant to be a drop-in replacement for `memcpy`.<br>
+The function's behavior is undefined if `destination` or `source` are NULL,
+and the function is a no-op if `count` is 0. The return value is
+`destination`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryCopy-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMemoryCopy-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMemoryCopy-declaration">
+<pre>
+SB_EXPORT void* SbMemoryCopy(void* destination,
+                             const void* source,
+                             size_t count);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMemoryCopy-stub">
+
+```
+#include "starboard/memory.h"
+
+void* SbMemoryCopy(void* /*destination*/, const void* /*source*/,
+                   size_t /*count*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>destination</code></td>
+    <td>The destination of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>source</code></td>
+    <td>The source of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of sequential bytes to be copied.</td>
+  </tr>
+</table>
+
+### SbMemoryDeallocate
+
+**Description**
+
+Frees a previously allocated chunk of memory. If `memory` is NULL, then the
+operation is a no-op. This function should be called from the client
+codebase. It is meant to be a drop-in replacement for `free`.
+
+**Declaration**
+
+```
+SB_EXPORT void SbMemoryDeallocate(void* memory);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>memory</code></td>
+    <td>The chunk of memory to be freed.</td>
+  </tr>
+</table>
+
+### SbMemoryDeallocateAligned
+
+**Declaration**
+
+```
+SB_EXPORT void SbMemoryDeallocateAligned(void* memory);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>memory</code></td>
+    <td>The chunk of memory to be freed. If <code>memory</code> is NULL, then the
+function is a no-op.</td>
+  </tr>
+</table>
+
+### SbMemoryDeallocateNoReport
+
+**Description**
+
+Same as <code><a href="#sbmemorydeallocate">SbMemoryDeallocate()</a></code> but will not report memory deallocation to the
+tracker. This function must be matched with <code><a href="#sbmemoryallocate">SbMemoryAllocate</a></code>NoReport().
+
+**Declaration**
+
+```
+SB_EXPORT void SbMemoryDeallocateNoReport(void* memory);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>
+        <code>memory</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryFindByte
+
+**Description**
+
+Finds the lower 8-bits of `value` in the first `count` bytes of `buffer`
+and returns either a pointer to the first found occurrence or `NULL` if
+the value is not found. This function is meant to be a drop-in replacement
+for `memchr`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryFindByte-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMemoryFindByte-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMemoryFindByte-declaration">
+<pre>
+SB_EXPORT const void* SbMemoryFindByte(const void* buffer,
+                                       int value,
+                                       size_t count);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMemoryFindByte-stub">
+
+```
+#include "starboard/memory.h"
+
+const void* SbMemoryFindByte(const void* /*buffer*/, int /*value*/,
+                             size_t /*count*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const void*</code><br>
+        <code>buffer</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>value</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>count</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryFlush
+
+**Description**
+
+Flushes any data in the given virtual address range that is cached locally in
+the current processor core to physical memory, ensuring that data and
+instruction caches are cleared. This is required to be called on executable
+memory that has been written to and might be executed in the future.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryFlush-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMemoryFlush-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMemoryFlush-declaration">
+<pre>
+SB_EXPORT void SbMemoryFlush(void* virtual_address, int64_t size_bytes);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMemoryFlush-stub">
+
+```
+#include "starboard/memory.h"
+
+void SbMemoryFlush(void* /*virtual_address*/, int64_t /*size_bytes*/) {}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>
+        <code>virtual_address</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int64_t</code><br>
+        <code>size_bytes</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryFree
+
+**Description**
+
+This is the implementation of <code><a href="#sbmemorydeallocate">SbMemoryDeallocate</a></code> that must be provided by
+Starboard ports.<br>
+DO NOT CALL. Call <code><a href="#sbmemorydeallocate">SbMemoryDeallocate</a></code>(...) instead.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryFree-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMemoryFree-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMemoryFree-declaration">
+<pre>
+    SB_EXPORT void SbMemoryFree(void* memory));
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMemoryFree-stub">
+
+```
+#include "starboard/memory.h"
+
+void SbMemoryFree(void* /*memory*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>
+        <code>memory</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryFreeAligned
+
+**Description**
+
+This is the implementation of <code>SbMemoryFreeAligned</code> that must be provided by
+Starboard ports.<br>
+DO NOT CALL. Call <code><a href="#sbmemorydeallocate">SbMemoryDeallocate</a></code>Aligned(...) instead.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryFreeAligned-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMemoryFreeAligned-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMemoryFreeAligned-declaration">
+<pre>
+    SB_EXPORT void SbMemoryFreeAligned(void* memory));
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMemoryFreeAligned-stub">
+
+```
+#include "starboard/memory.h"
+
+void SbMemoryFreeAligned(void* /*memory*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>
+        <code>memory</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryGetStackBounds
+
+**Description**
+
+Gets the stack bounds for the current thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryGetStackBounds-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMemoryGetStackBounds-stub" class="mdl-tabs__tab">stub</a>
+    <a href="#SbMemoryGetStackBounds-bsd" class="mdl-tabs__tab">bsd</a>
+    <a href="#SbMemoryGetStackBounds-linux" class="mdl-tabs__tab">linux</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMemoryGetStackBounds-declaration">
+<pre>
+SB_EXPORT void SbMemoryGetStackBounds(void** out_high, void** out_low);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMemoryGetStackBounds-stub">
+
+```
+#include "starboard/memory.h"
+
+void SbMemoryGetStackBounds(void** /*out_high*/, void** /*out_low*/) {
+}
+```
+
+  </div>
+  <div class="mdl-tabs__panel" id="SbMemoryGetStackBounds-bsd">
+
+```
+#include "starboard/memory.h"
+
+#include <pthread.h>
+#include <pthread_np.h>
+
+void SbMemoryGetStackBounds(void** out_high, void** out_low) {
+  pthread_attr_t attr;
+  pthread_attr_init(&attr);
+  pthread_attr_get_np(pthread_self(), &attr);
+
+  void* stack_address;
+  size_t stack_size;
+  pthread_attr_getstack(&attr, &stack_address, &stack_size);
+  *out_high = static_cast<uint8_t*>(stack_address) + stack_size;
+  *out_low = stack_address;
+
+  pthread_attr_destroy(&attr);
+}
+```
+
+  </div>
+  <div class="mdl-tabs__panel" id="SbMemoryGetStackBounds-linux">
+
+```
+#include "starboard/memory.h"
+
+#include <pthread.h>
+
+#include "starboard/log.h"
+
+void SbMemoryGetStackBounds(void** out_high, void** out_low) {
+  void* stackBase = 0;
+  size_t stackSize = 0;
+
+  pthread_t thread = pthread_self();
+  pthread_attr_t sattr;
+  pthread_attr_init(&sattr);
+  pthread_getattr_np(thread, &sattr);
+  int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
+  SB_DCHECK(rc == 0);
+  SB_DCHECK(stackBase);
+  pthread_attr_destroy(&sattr);
+  *out_high = static_cast<char*>(stackBase) + stackSize;
+  *out_low = stackBase;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void**</code><br>        <code>out_high</code></td>
+    <td>The highest addressable byte + 1 for the current thread.</td>
+  </tr>
+  <tr>
+    <td><code>void**</code><br>        <code>out_low</code></td>
+    <td>The lowest addressable byte for the current thread.</td>
+  </tr>
+</table>
+
+### SbMemoryIsAligned
+
+**Description**
+
+Checks whether `memory` is aligned to `alignment` bytes.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE bool SbMemoryIsAligned(const void* memory,
+                                                size_t alignment) {
+  return ((uintptr_t)memory) % alignment == 0;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const void*</code><br>
+        <code>memory</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>alignment</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryIsZero
+
+**Description**
+
+Returns true if the first `count` bytes of `buffer` are set to zero.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbMemoryIsZero(const void* buffer, size_t count) {
+  if (count == 0) {
+    return true;
+  }
+  const char* char_buffer = (const char*)(buffer);
+  return char_buffer[0] == 0 &&
+         SbMemoryCompare(char_buffer, char_buffer + 1, count - 1) == 0;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const void*</code><br>
+        <code>buffer</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>count</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryMap
+
+**Description**
+
+Allocates `size_bytes` worth of physical memory pages and maps them into an
+available virtual region. This function returns `SB_MEMORY_MAP_FAILED` on
+failure. `NULL` is a valid return value.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryMap-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMemoryMap-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMemoryMap-declaration">
+<pre>
+SB_EXPORT void* SbMemoryMap(int64_t size_bytes, int flags, const char* name);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMemoryMap-stub">
+
+```
+#include "starboard/memory.h"
+
+void* SbMemoryMap(int64_t /*size_bytes*/, int /*flags*/, const char* /*name*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int64_t</code><br>        <code>size_bytes</code></td>
+    <td>The amount of physical memory pages to be allocated.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>flags</code></td>
+    <td>The bitwise OR of the protection flags for the mapped memory
+as specified in <code>SbMemoryMapFlags</code>.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>name</code></td>
+    <td>A value that appears in the debugger on some platforms. The value
+can be up to 32 bytes.</td>
+  </tr>
+</table>
+
+### SbMemoryMove
+
+**Description**
+
+Copies `count` sequential bytes from `source` to `destination`, with support
+for the `source` and `destination` regions overlapping. This function is
+meant to be a drop-in replacement for `memmove`.<br>
+The function's behavior is undefined if `destination` or `source` are NULL,
+and the function is a no-op if `count` is 0. The return value is
+`destination`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryMove-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMemoryMove-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMemoryMove-declaration">
+<pre>
+SB_EXPORT void* SbMemoryMove(void* destination,
+                             const void* source,
+                             size_t count);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMemoryMove-stub">
+
+```
+#include "starboard/memory.h"
+
+void* SbMemoryMove(void* /*destination*/, const void* /*source*/,
+                   size_t /*count*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>destination</code></td>
+    <td>The destination of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>source</code></td>
+    <td>The source of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of sequential bytes to be copied.</td>
+  </tr>
+</table>
+
+### SbMemoryReallocate
+
+**Description**
+
+Attempts to resize `memory` to be at least `size` bytes, without touching
+the contents of memory.
+<ul><li>If the function cannot perform the fast resize, it allocates a new chunk
+of memory, copies the contents over, and frees the previous chunk,
+returning a pointer to the new chunk.
+</li><li>If the function cannot perform the slow resize, it returns `NULL`,
+leaving the given memory chunk unchanged.</li></ul>
+This function should be called from the client codebase. It is meant to be a
+drop-in replacement for `realloc`.
+
+**Declaration**
+
+```
+SB_EXPORT void* SbMemoryReallocate(void* memory, size_t size);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>memory</code></td>
+    <td>The chunk of memory to be resized. <code>memory</code> may be NULL, in which
+case it behaves exactly like <code><a href="#sbmemoryallocate">SbMemoryAllocate</a></code>Unchecked.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The size to which <code>memory</code> will be resized. If <code>size</code> is <code>0</code>,
+the function may return <code>NULL</code> or it may return a unique pointer value
+that can be passed to <code><a href="#sbmemorydeallocate">SbMemoryDeallocate</a></code>.</td>
+  </tr>
+</table>
+
+### SbMemoryReallocateChecked
+
+**Description**
+
+Same as <code><a href="#sbmemoryreallocate">SbMemoryReallocate</a></code>Unchecked, but will abort() in the case of an
+allocation failure.<br>
+DO NOT CALL. Call <code><a href="#sbmemoryreallocate">SbMemoryReallocate</a></code>(...) instead.
+
+**Declaration**
+
+```
+    SB_EXPORT void* SbMemoryReallocateChecked(void* memory, size_t size));
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>
+        <code>memory</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemoryReallocateUnchecked
+
+**Description**
+
+This is the implementation of <code><a href="#sbmemoryreallocate">SbMemoryReallocate</a></code> that must be
+provided by Starboard ports.<br>
+DO NOT CALL. Call <code><a href="#sbmemoryreallocate">SbMemoryReallocate</a></code>(...) instead.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryReallocateUnchecked-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMemoryReallocateUnchecked-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMemoryReallocateUnchecked-declaration">
+<pre>
+    SB_EXPORT void* SbMemoryReallocateUnchecked(void* memory, size_t size));
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMemoryReallocateUnchecked-stub">
+
+```
+#include "starboard/memory.h"
+
+void* SbMemoryReallocateUnchecked(void* /*memory*/, size_t /*size*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>
+        <code>memory</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMemorySet
+
+**Description**
+
+Fills `count` sequential bytes starting at `destination`, with the unsigned
+char coercion of `byte_value`. This function is meant to be a drop-in
+replacement for `memset`.<br>
+The function's behavior is undefined if `destination` is NULL, and the
+function is a no-op if `count` is 0. The return value is `destination`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemorySet-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMemorySet-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMemorySet-declaration">
+<pre>
+SB_EXPORT void* SbMemorySet(void* destination, int byte_value, size_t count);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMemorySet-stub">
+
+```
+#include "starboard/memory.h"
+
+void* SbMemorySet(void* /*destination*/, int /*byte_value*/, size_t /*count*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>destination</code></td>
+    <td>The destination of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>byte_value</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of sequential bytes to be set.</td>
+  </tr>
+</table>
+
+### SbMemoryUnmap
+
+**Description**
+
+Unmap `size_bytes` of physical pages starting from `virtual_address`,
+returning `true` on success. After this function completes,
+[virtual_address, virtual_address + size_bytes) will not be read/writable.
+This function can unmap multiple contiguous regions that were mapped with
+separate calls to <code><a href="#sbmemorymap">SbMemoryMap()</a></code>. For example, if one call to
+`SbMemoryMap(0x1000)` returns `(void*)0xA000`, and another call to
+`SbMemoryMap(0x1000)` returns `(void*)0xB000`,
+`SbMemoryUnmap(0xA000, 0x2000)` should free both regions.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryUnmap-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMemoryUnmap-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMemoryUnmap-declaration">
+<pre>
+SB_EXPORT bool SbMemoryUnmap(void* virtual_address, int64_t size_bytes);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMemoryUnmap-stub">
+
+```
+#include "starboard/memory.h"
+
+bool SbMemoryUnmap(void* /*virtual_address*/, int64_t /*size_bytes*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>
+        <code>virtual_address</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int64_t</code><br>
+        <code>size_bytes</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/memory.md.new b/src/cobalt/site/docs/reference/starboard/modules/memory.md.new
new file mode 100644
index 0000000..cc4e82f
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/memory.md.new
@@ -0,0 +1,802 @@
+---
+layout: doc
+title: "Starboard Module Reference: memory.h"
+---
+
+This module defines functions for memory allocation, alignment, copying, 
+and comparing.
+
+## Enums
+
+### SbMemoryMapFlags
+
+The bitwise OR of these flags should be passed to SbMemoryMap to indicate 
+how the mapped memory can be used.
+
+**Values**
+
+*   `kSbMemoryMapProtectRead` - Mapped memory can be read.
+*   `kSbMemoryMapProtectWrite` - Mapped memory can be written to.
+*   `kSbMemoryMapProtectExec` - Mapped memory can be executed.
+*   `kSbMemoryMapProtectRead`
+
+## Macros
+
+<div id="macro-documentation-section">
+
+<h3 id="sb_memory_map_failed" class="small-h3">SB_MEMORY_MAP_FAILED</h3>
+
+</div>
+
+## Functions
+
+### SbAbortIfAllocationFailed
+
+**Definition**
+
+```
+static SB_C_FORCE_INLINE void SbAbortIfAllocationFailed(size_t requested_bytes,
+                                                        void* address) {
+  if (SB_UNLIKELY(requested_bytes > 0 && address == NULL)) {
+    // Will abort the program if no debugger is attached.
+    SbSystemBreakIntoDebugger();
+  }
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code></td>
+    <td><code>requested_bytes</code></td>
+  </tr>
+  <tr>
+    <td><code>void*</code></td>
+    <td><code>address</code></td>
+  </tr>
+</table>
+
+### SbMemoryAlignToPageSize
+
+**Description**
+
+Rounds `size` up to SB_MEMORY_PAGE_SIZE.
+
+**Definition**
+
+```
+static SB_C_FORCE_INLINE size_t SbMemoryAlignToPageSize(size_t size) {
+  return (size + SB_MEMORY_PAGE_SIZE - 1) & ~(SB_MEMORY_PAGE_SIZE - 1);
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code></td>
+    <td><code>size</code></td>
+  </tr>
+</table>
+
+### SbMemoryAllocateAlignedChecked
+
+**Description**
+
+This function is identical to <code><a href="#sbmemoryallocatealignedunchecked">SbMemoryAllocateAlignedUnchecked</a></code>, but it 
+aborts (`abort()`) in the case of an allocation failure.
+
+**Definition**
+
+```
+static SB_C_FORCE_INLINE void* SbMemoryAllocateAlignedChecked(size_t alignment,
+                                                              size_t size) {
+  void* address = SbMemoryAllocateAlignedUnchecked(alignment, size);
+  SbAbortIfAllocationFailed(size, address);
+  return address;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>alignment</code></td>
+    <td>The way that data is arranged and accessed in memory. The value 
+must be a power of two.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The size of the memory to be allocated. If <code>size</code> is <code>0</code>, the 
+function may return <code>NULL</code> or it may return a unique aligned pointer value 
+that can be passed to <code><a href="#sbmemoryfree">SbMemoryFree</a></code>Aligned.</td>
+  </tr>
+</table>
+
+### SbMemoryAllocateAlignedUnchecked
+
+**Description**
+
+Allocates and returns a chunk of memory of at least `size` bytes, aligned 
+to `alignment`. This function is meant to be a drop-in replacement for 
+`memalign`.<br><br>
+
+ 
+The function returns `NULL` if it cannot allocate the memory. In addition, 
+the function's behavior is undefined if `alignment` is not a power of two.
+
+**Definition**
+
+```
+SB_EXPORT void* SbMemoryAllocateAlignedUnchecked(size_t alignment, size_t size);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>alignment</code></td>
+    <td>The way that data is arranged and accessed in memory. The value 
+must be a power of two.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The size of the memory to be allocated. If <code>size</code> is <code>0</code>, the 
+function may return <code>NULL</code> or it may return a unique aligned pointer value 
+that can be passed to <code><a href="#sbmemoryfree">SbMemoryFree</a></code>Aligned.</td>
+  </tr>
+</table>
+
+### SbMemoryAllocateChecked
+
+**Description**
+
+This function is identical to <code><a href="#sbmemoryallocateunchecked">SbMemoryAllocateUnchecked</a></code>, but it aborts 
+(`abort()`) in the case of an allocation failure.
+
+**Definition**
+
+```
+static SB_C_FORCE_INLINE void* SbMemoryAllocateChecked(size_t size) {
+  void* address = SbMemoryAllocateUnchecked(size);
+  SbAbortIfAllocationFailed(size, address);
+  return address;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The amount of memory to be allocated. If <code>size</code> is 0, the function 
+may return <code>NULL</code> or it may return a unique pointer value that can be 
+passed to <code><a href="#sbmemoryfree">SbMemoryFree</a></code>.</td>
+  </tr>
+</table>
+
+### SbMemoryAllocateUnchecked
+
+**Description**
+
+Allocates and returns a chunk of memory of at least `size` bytes. This 
+function is intended to be a drop-in replacement for `malloc`.<br><br>
+
+ 
+Note that this function returns `NULL` if it is unable to allocate the 
+memory.
+
+**Definition**
+
+```
+SB_EXPORT void* SbMemoryAllocateUnchecked(size_t size);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The amount of memory to be allocated. If <code>size</code> is 0, the function 
+may return <code>NULL</code> or it may return a unique pointer value that can be 
+passed to <code><a href="#sbmemoryfree">SbMemoryFree</a></code>.</td>
+  </tr>
+</table>
+
+### SbMemoryCalloc
+
+**Description**
+
+A wrapper that implements a drop-in replacement for `calloc`, which is used 
+in some packages.
+
+**Definition**
+
+```
+static SB_C_INLINE void* SbMemoryCalloc(size_t count, size_t size) {
+  size_t total = count * size;
+  void* result = SbMemoryAllocate(total);
+  if (result) {
+    SbMemorySet(result, 0, total);
+  }
+  return result;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td></td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td></td>
+  </tr>
+</table>
+
+### SbMemoryCompare
+
+**Description**
+
+Compares the contents of the first `count` bytes of `buffer1` and `buffer2`. 
+This function returns: 
+<ul><li>`-1` if `buffer1` is "less-than" `buffer2` 
+</li><li>`0` if `buffer1` and `buffer2` are equal 
+</li><li>`1` if `buffer1` is "greater-than" `buffer2`. 
+This function is meant to be a drop-in replacement for `memcmp`.
+
+**Definition**
+
+```
+SB_EXPORT int SbMemoryCompare(const void* buffer1,
+                              const void* buffer2,
+                              size_t count);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>buffer1</code></td>
+    <td>The first buffer to be compared.</td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>buffer2</code></td>
+    <td>The second buffer to be compared.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of bytes to be compared.</td>
+  </tr>
+</table>
+
+### SbMemoryCopy
+
+**Description**
+
+Copies `count` sequential bytes from `source` to `destination`, without 
+support for the `source` and `destination` regions overlapping. This 
+function is meant to be a drop-in replacement for `memcpy`.<br><br>
+
+ 
+The function's behavior is undefined if `destination` or `source` are NULL, 
+and the function is a no-op if `count` is 0. The return value is 
+`destination`.
+
+**Definition**
+
+```
+SB_EXPORT void* SbMemoryCopy(void* destination,
+                             const void* source,
+                             size_t count);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>destination</code></td>
+    <td>The destination of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>source</code></td>
+    <td>The source of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of sequential bytes to be copied.</td>
+  </tr>
+</table>
+
+### SbMemoryFindByte
+
+**Description**
+
+Finds the lower 8-bits of `value` in the first `count` bytes of `buffer` 
+and returns either a pointer to the first found occurrence or `NULL` if 
+the value is not found. This function is meant to be a drop-in replacement 
+for `memchr`.
+
+**Definition**
+
+```
+SB_EXPORT const void* SbMemoryFindByte(const void* buffer,
+                                       int value,
+                                       size_t count);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>buffer</code></td>
+    <td></td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>value</code></td>
+    <td></td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td></td>
+  </tr>
+</table>
+
+### SbMemoryFlush
+
+**Description**
+
+Flushes any data in the given virtual address range that is cached locally in 
+the current processor core to physical memory, ensuring that data and 
+instruction caches are cleared. This is required to be called on executable 
+memory that has been written to and might be executed in the future.
+
+**Definition**
+
+```
+SB_EXPORT void SbMemoryFlush(void* virtual_address, int64_t size_bytes);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code></td>
+    <td><code>virtual_address</code></td>
+  </tr>
+  <tr>
+    <td><code>int64_t</code></td>
+    <td><code>size_bytes</code></td>
+  </tr>
+</table>
+
+### SbMemoryFree
+
+**Description**
+
+Frees a previously allocated chunk of memory. If `memory` is NULL, then the 
+operation is a no-op. This function is meant to be a drop-in replacement for 
+`free`.
+
+**Definition**
+
+```
+SB_EXPORT void SbMemoryFree(void* memory);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>memory</code></td>
+    <td>The chunk of memory to be freed.</td>
+  </tr>
+</table>
+
+### SbMemoryFreeAligned
+
+**Definition**
+
+```
+SB_EXPORT void SbMemoryFreeAligned(void* memory);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>memory</code></td>
+    <td>The chunk of memory to be freed. If <code>memory</code> is NULL, then the 
+function is a no-op.</td>
+  </tr>
+</table>
+
+### SbMemoryGetStackBounds
+
+**Description**
+
+Gets the stack bounds for the current thread.
+
+**Definition**
+
+```
+SB_EXPORT void SbMemoryGetStackBounds(void** out_high, void** out_low);
+```
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryGetStackBounds-stub" class="mdl-tabs__tab is-active">stub</a>
+    <a href="#SbMemoryGetStackBounds-bsd" class="mdl-tabs__tab">bsd</a>
+    <a href="#SbMemoryGetStackBounds-linux" class="mdl-tabs__tab">linux</a>
+  </div>
+  <div class="mdl-tabs__panel  is-active" id="SbMemoryGetStackBounds-stub">
+<pre>
+#include "starboard/memory.h"
+
+void SbMemoryGetStackBounds(void** /*out_high*/, void** /*out_low*/) {
+}
+</pre>
+  </div>
+  <div class="mdl-tabs__panel " id="SbMemoryGetStackBounds-bsd">
+<pre>
+#include "starboard/memory.h"
+
+#include &lt;pthread.h>
+#include &lt;pthread_np.h>
+
+void SbMemoryGetStackBounds(void** out_high, void** out_low) {
+  pthread_attr_t attr;
+  pthread_attr_init(&attr);
+  pthread_attr_get_np(pthread_self(), &attr);
+
+  void* stack_address;
+  size_t stack_size;
+  pthread_attr_getstack(&attr, &stack_address, &stack_size);
+  *out_high = static_cast&lt;uint8_t*>(stack_address) + stack_size;
+  *out_low = stack_address;
+
+  pthread_attr_destroy(&attr);
+}
+</pre>
+  </div>
+  <div class="mdl-tabs__panel " id="SbMemoryGetStackBounds-linux">
+<pre>
+#include "starboard/memory.h"
+
+#include &lt;pthread.h>
+
+#include "starboard/log.h"
+
+void SbMemoryGetStackBounds(void** out_high, void** out_low) {
+  void* stackBase = 0;
+  size_t stackSize = 0;
+
+  pthread_t thread = pthread_self();
+  pthread_attr_t sattr;
+  pthread_attr_init(&sattr);
+  pthread_getattr_np(thread, &sattr);
+  int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
+  SB_DCHECK(rc == 0);
+  SB_DCHECK(stackBase);
+  pthread_attr_destroy(&sattr);
+  *out_high = static_cast&lt;char*>(stackBase) + stackSize;
+  *out_low = stackBase;
+}
+</pre>
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void**</code><br>        <code>out_high</code></td>
+    <td>The highest addressable byte + 1 for the current thread.</td>
+  </tr>
+  <tr>
+    <td><code>void**</code><br>        <code>out_low</code></td>
+    <td>The lowest addressable byte for the current thread.</td>
+  </tr>
+</table>
+
+### SbMemoryIsAligned
+
+**Description**
+
+Checks whether `memory` is aligned to `alignment` bytes.
+
+**Definition**
+
+```
+static SB_C_FORCE_INLINE bool SbMemoryIsAligned(const void* memory,
+                                                size_t alignment) {
+  return ((uintptr_t)memory) % alignment == 0;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const void*</code></td>
+    <td><code>memory</code></td>
+  </tr>
+  <tr>
+    <td><code>size_t</code></td>
+    <td><code>alignment</code></td>
+  </tr>
+</table>
+
+### SbMemoryMap
+
+**Description**
+
+Allocates `size_bytes` worth of physical memory pages and maps them into an 
+available virtual region. This function returns `SB_MEMORY_MAP_FAILED` on 
+failure. `NULL` is a valid return value.
+
+**Definition**
+
+```
+SB_EXPORT void* SbMemoryMap(int64_t size_bytes, int flags, const char* name);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int64_t</code><br>        <code>size_bytes</code></td>
+    <td>The amount of physical memory pages to be allocated.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>flags</code></td>
+    <td>The bitwise OR of the protection flags for the mapped memory 
+as specified in <code>SbMemoryMapFlags</code>.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>name</code></td>
+    <td>A value that appears in the debugger on some platforms. The value 
+can be up to 32 bytes.</td>
+  </tr>
+</table>
+
+### SbMemoryMove
+
+**Description**
+
+Copies `count` sequential bytes from `source` to `destination`, with support 
+for the `source` and `destination` regions overlapping. This function is 
+meant to be a drop-in replacement for `memmove`.<br><br>
+
+ 
+The function's behavior is undefined if `destination` or `source` are NULL, 
+and the function is a no-op if `count` is 0. The return value is 
+`destination`.
+
+**Definition**
+
+```
+SB_EXPORT void* SbMemoryMove(void* destination,
+                             const void* source,
+                             size_t count);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>destination</code></td>
+    <td>The destination of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>source</code></td>
+    <td>The source of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of sequential bytes to be copied.</td>
+  </tr>
+</table>
+
+### SbMemoryReallocateChecked
+
+**Description**
+
+This function is identical to <code><a href="#sbmemoryreallocateunchecked">SbMemoryReallocateUnchecked</a></code>, but it aborts 
+(`abort()`) in the case of an allocation failure.
+
+**Definition**
+
+```
+static SB_C_FORCE_INLINE void* SbMemoryReallocateChecked(void* memory,
+                                                         size_t size) {
+  void* address = SbMemoryReallocateUnchecked(memory, size);
+  SbAbortIfAllocationFailed(size, address);
+  return address;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>memory</code></td>
+    <td>The chunk of memory to be resized. <code>memory</code> may be NULL, in which 
+case it behaves exactly like <code><a href="#sbmemoryallocateunchecked">SbMemoryAllocateUnchecked</a></code>.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The size to which <code>memory</code> will be resized. If <code>size</code> is <code>0</code>, 
+the function may return <code>NULL</code> or it may return a unique pointer value 
+that can be passed to <code><a href="#sbmemoryfree">SbMemoryFree</a></code>.</td>
+  </tr>
+</table>
+
+### SbMemoryReallocateUnchecked
+
+**Description**
+
+Attempts to resize `memory` to be at least `size` bytes, without touching 
+the contents of memory. 
+<ul><li>If the function cannot perform the fast resize, it allocates a new chunk 
+of memory, copies the contents over, and frees the previous chunk, 
+returning a pointer to the new chunk. 
+</li><li>If the function cannot perform the slow resize, it returns `NULL`, 
+leaving the given memory chunk unchanged. 
+This function is meant to be a drop-in replacement for `realloc`.
+
+**Definition**
+
+```
+SB_EXPORT void* SbMemoryReallocateUnchecked(void* memory, size_t size);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>memory</code></td>
+    <td>The chunk of memory to be resized. <code>memory</code> may be NULL, in which 
+case it behaves exactly like <code><a href="#sbmemoryallocateunchecked">SbMemoryAllocateUnchecked</a></code>.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The size to which <code>memory</code> will be resized. If <code>size</code> is <code>0</code>, 
+the function may return <code>NULL</code> or it may return a unique pointer value 
+that can be passed to <code><a href="#sbmemoryfree">SbMemoryFree</a></code>.</td>
+  </tr>
+</table>
+
+### SbMemorySet
+
+**Description**
+
+Fills `count` sequential bytes starting at `destination`, with the unsigned 
+char coercion of `byte_value`. This function is meant to be a drop-in 
+replacement for `memset`.<br><br>
+
+ 
+The function's behavior is undefined if `destination` is NULL, and the 
+function is a no-op if `count` is 0. The return value is `destination`.
+
+**Definition**
+
+```
+SB_EXPORT void* SbMemorySet(void* destination, int byte_value, size_t count);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>destination</code></td>
+    <td>The destination of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>byte_value</code></td>
+    <td></td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of sequential bytes to be set.</td>
+  </tr>
+</table>
+
+### SbMemoryUnmap
+
+**Description**
+
+Unmap `size_bytes` of physical pages starting from `virtual_address`, 
+returning `true` on success. After this function completes, 
+[virtual_address, virtual_address + size_bytes) will not be read/writable. 
+This function can unmap multiple contiguous regions that were mapped with 
+separate calls to <code><a href="#sbmemorymap">SbMemoryMap()</a></code>. For example, if one call to 
+`SbMemoryMap(0x1000)` returns `(void*)0xA000`, and another call to 
+`SbMemoryMap(0x1000)` returns `(void*)0xB000`, 
+`SbMemoryUnmap(0xA000, 0x2000)` should free both regions.
+
+**Definition**
+
+```
+SB_EXPORT bool SbMemoryUnmap(void* virtual_address, int64_t size_bytes);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>virtual_address</code></td>
+    <td></td>
+  </tr>
+  <tr>
+    <td><code>int64_t</code><br>        <code>size_bytes</code></td>
+    <td></td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/memory.md.old b/src/cobalt/site/docs/reference/starboard/modules/memory.md.old
new file mode 100644
index 0000000..9858c9a
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/memory.md.old
@@ -0,0 +1,798 @@
+---
+layout: doc
+title: "Starboard Module Reference: memory.h"
+---
+
+This module defines functions for memory allocation, alignment, copying, 
+and comparing.
+
+## Enums
+
+### SbMemoryMapFlags
+
+The bitwise OR of these flags should be passed to SbMemoryMap to indicate 
+how the mapped memory can be used.
+
+**Values**
+
+*   `kSbMemoryMapProtectRead` - Mapped memory can be read.
+*   `kSbMemoryMapProtectWrite` - Mapped memory can be written to.
+*   `kSbMemoryMapProtectExec` - Mapped memory can be executed.
+*   `kSbMemoryMapProtectRead`
+
+## Macros
+
+<div id="macro-documentation-section">
+
+<h3 id="sb_memory_map_failed" class="small-h3">SB_MEMORY_MAP_FAILED</h3>
+
+</div>
+
+## Functions
+
+### SbAbortIfAllocationFailed
+
+**Definition**
+
+```
+static SB_C_FORCE_INLINE void SbAbortIfAllocationFailed(size_t requested_bytes,
+                                                        void* address) {
+  if (SB_UNLIKELY(requested_bytes > 0 && address == NULL)) {
+    // Will abort the program if no debugger is attached.
+    SbSystemBreakIntoDebugger();
+  }
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code></td>
+    <td><code>requested_bytes</code></td>
+  </tr>
+  <tr>
+    <td><code>void*</code></td>
+    <td><code>address</code></td>
+  </tr>
+</table>
+
+### SbMemoryAlignToPageSize
+
+**Description**
+
+Rounds `size` up to SB_MEMORY_PAGE_SIZE.
+
+**Definition**
+
+```
+static SB_C_FORCE_INLINE size_t SbMemoryAlignToPageSize(size_t size) {
+  return (size + SB_MEMORY_PAGE_SIZE - 1) & ~(SB_MEMORY_PAGE_SIZE - 1);
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code></td>
+    <td><code>size</code></td>
+  </tr>
+</table>
+
+### SbMemoryAllocateAlignedChecked
+
+**Description**
+
+This function is identical to <code><a href="#sbmemoryallocatealignedunchecked">SbMemoryAllocateAlignedUnchecked</a></code>, but it 
+aborts (`abort()`) in the case of an allocation failure.
+
+**Definition**
+
+```
+static SB_C_FORCE_INLINE void* SbMemoryAllocateAlignedChecked(size_t alignment,
+                                                              size_t size) {
+  void* address = SbMemoryAllocateAlignedUnchecked(alignment, size);
+  SbAbortIfAllocationFailed(size, address);
+  return address;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>alignment</code></td>
+    <td>The way that data is arranged and accessed in memory. The value 
+must be a power of two.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The size of the memory to be allocated. If <code>size</code> is <code>0</code>, the 
+function may return <code>NULL</code> or it may return a unique aligned pointer value 
+that can be passed to <code><a href="#sbmemoryfree">SbMemoryFree</a></code>Aligned.</td>
+  </tr>
+</table>
+
+### SbMemoryAllocateAlignedUnchecked
+
+**Description**
+
+Allocates and returns a chunk of memory of at least `size` bytes, aligned 
+to `alignment`. This function is meant to be a drop-in replacement for 
+`memalign`.<br><br>
+
+ 
+The function returns `NULL` if it cannot allocate the memory. In addition, 
+the function's behavior is undefined if `alignment` is not a power of two.
+
+**Definition**
+
+```
+SB_EXPORT void* SbMemoryAllocateAlignedUnchecked(size_t alignment, size_t size);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>alignment</code></td>
+    <td>The way that data is arranged and accessed in memory. The value 
+must be a power of two.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The size of the memory to be allocated. If <code>size</code> is <code>0</code>, the 
+function may return <code>NULL</code> or it may return a unique aligned pointer value 
+that can be passed to <code><a href="#sbmemoryfree">SbMemoryFree</a></code>Aligned.</td>
+  </tr>
+</table>
+
+### SbMemoryAllocateChecked
+
+**Description**
+
+This function is identical to <code><a href="#sbmemoryallocateunchecked">SbMemoryAllocateUnchecked</a></code>, but it aborts 
+(`abort()`) in the case of an allocation failure.
+
+**Definition**
+
+```
+static SB_C_FORCE_INLINE void* SbMemoryAllocateChecked(size_t size) {
+  void* address = SbMemoryAllocateUnchecked(size);
+  SbAbortIfAllocationFailed(size, address);
+  return address;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The amount of memory to be allocated. If <code>size</code> is 0, the function 
+may return <code>NULL</code> or it may return a unique pointer value that can be 
+passed to <code><a href="#sbmemoryfree">SbMemoryFree</a></code>.</td>
+  </tr>
+</table>
+
+### SbMemoryAllocateUnchecked
+
+**Description**
+
+Allocates and returns a chunk of memory of at least `size` bytes. This 
+function is intended to be a drop-in replacement for `malloc`.<br><br>
+
+ 
+Note that this function returns `NULL` if it is unable to allocate the 
+memory.
+
+**Definition**
+
+```
+SB_EXPORT void* SbMemoryAllocateUnchecked(size_t size);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The amount of memory to be allocated. If <code>size</code> is 0, the function 
+may return <code>NULL</code> or it may return a unique pointer value that can be 
+passed to <code><a href="#sbmemoryfree">SbMemoryFree</a></code>.</td>
+  </tr>
+</table>
+
+### SbMemoryCalloc
+
+**Description**
+
+A wrapper that implements a drop-in replacement for `calloc`, which is used 
+in some packages.
+
+**Definition**
+
+```
+static SB_C_INLINE void* SbMemoryCalloc(size_t count, size_t size) {
+  size_t total = count * size;
+  void* result = SbMemoryAllocate(total);
+  if (result) {
+    SbMemorySet(result, 0, total);
+  }
+  return result;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td></td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td></td>
+  </tr>
+</table>
+
+### SbMemoryCompare
+
+**Description**
+
+Compares the contents of the first `count` bytes of `buffer1` and `buffer2`. 
+This function returns: 
+<ul><li>`-1` if `buffer1` is "less-than" `buffer2` 
+</li><li>`0` if `buffer1` and `buffer2` are equal 
+</li><li>`1` if `buffer1` is "greater-than" `buffer2`. 
+This function is meant to be a drop-in replacement for `memcmp`.
+
+**Definition**
+
+```
+SB_EXPORT int SbMemoryCompare(const void* buffer1,
+                              const void* buffer2,
+                              size_t count);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>buffer1</code></td>
+    <td>The first buffer to be compared.</td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>buffer2</code></td>
+    <td>The second buffer to be compared.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of bytes to be compared.</td>
+  </tr>
+</table>
+
+### SbMemoryCopy
+
+**Description**
+
+Copies `count` sequential bytes from `source` to `destination`, without 
+support for the `source` and `destination` regions overlapping. This 
+function is meant to be a drop-in replacement for `memcpy`.<br><br>
+
+ 
+The function's behavior is undefined if `destination` or `source` are NULL, 
+and the function is a no-op if `count` is 0. The return value is 
+`destination`.
+
+**Definition**
+
+```
+SB_EXPORT void* SbMemoryCopy(void* destination,
+                             const void* source,
+                             size_t count);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>destination</code></td>
+    <td>The destination of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>source</code></td>
+    <td>The source of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of sequential bytes to be copied.</td>
+  </tr>
+</table>
+
+### SbMemoryFindByte
+
+**Description**
+
+Finds the lower 8-bits of `value` in the first `count` bytes of `buffer` 
+and returns either a pointer to the first found occurrence or `NULL` if 
+the value is not found. This function is meant to be a drop-in replacement 
+for `memchr`.
+
+**Definition**
+
+```
+SB_EXPORT const void* SbMemoryFindByte(const void* buffer,
+                                       int value,
+                                       size_t count);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>buffer</code></td>
+    <td></td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>value</code></td>
+    <td></td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td></td>
+  </tr>
+</table>
+
+### SbMemoryFlush
+
+**Description**
+
+Flushes any data in the given virtual address range that is cached locally in 
+the current processor core to physical memory, ensuring that data and 
+instruction caches are cleared. This is required to be called on executable 
+memory that has been written to and might be executed in the future.
+
+**Definition**
+
+```
+SB_EXPORT void SbMemoryFlush(void* virtual_address, int64_t size_bytes);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code></td>
+    <td><code>virtual_address</code></td>
+  </tr>
+  <tr>
+    <td><code>int64_t</code></td>
+    <td><code>size_bytes</code></td>
+  </tr>
+</table>
+
+### SbMemoryFree
+
+**Description**
+
+Frees a previously allocated chunk of memory. If `memory` is NULL, then the 
+operation is a no-op. This function is meant to be a drop-in replacement for 
+`free`.
+
+**Definition**
+
+```
+SB_EXPORT void SbMemoryFree(void* memory);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>memory</code></td>
+    <td>The chunk of memory to be freed.</td>
+  </tr>
+</table>
+
+### SbMemoryFreeAligned
+
+**Definition**
+
+```
+SB_EXPORT void SbMemoryFreeAligned(void* memory);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>memory</code></td>
+    <td>The chunk of memory to be freed. If <code>memory</code> is NULL, then the 
+function is a no-op.</td>
+  </tr>
+</table>
+
+### SbMemoryGetStackBounds
+
+**Description**
+
+Gets the stack bounds for the current thread.
+
+**Definition**
+
+```
+SB_EXPORT void SbMemoryGetStackBounds(void** out_high, void** out_low);
+```
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMemoryGetStackBounds-stub" class="mdl-tabs__tab is-active">stub</a>
+    <a href="#SbMemoryGetStackBounds-bsd" class="mdl-tabs__tab">bsd</a>
+    <a href="#SbMemoryGetStackBounds-linux" class="mdl-tabs__tab">linux</a>
+  </div>
+    <div class="mdl-tabs__panel  is-active" id="SbMemoryGetStackBounds-stub">
+<pre>
+#include "starboard/memory.h"
+
+void SbMemoryGetStackBounds(void** /*out_high*/, void** /*out_low*/) {
+}
+</pre>
+
+</div>
+<div class="mdl-tabs__panel " id="SbMemoryGetStackBounds-bsd">
+
+<pre>
+#include &lt;pthread_np.h>
+
+void SbMemoryGetStackBounds(void** out_high, void** out_low) {
+  pthread_attr_t attr;
+  pthread_attr_init(&attr);
+  pthread_attr_get_np(pthread_self(), &attr);
+
+  void* stack_address;
+  size_t stack_size;
+  pthread_attr_getstack(&attr, &stack_address, &stack_size);
+  *out_high = static_cast<uint8_t*>(stack_address) + stack_size;
+  *out_low = stack_address;
+
+  pthread_attr_destroy(&attr);
+}
+</pre>
+
+</div>
+<div class="mdl-tabs__panel " id="SbMemoryGetStackBounds-linux">
+<pre>
+#include "starboard/log.h"
+
+void SbMemoryGetStackBounds(void** out_high, void** out_low) {
+  void* stackBase = 0;
+  size_t stackSize = 0;
+
+  pthread_t thread = pthread_self();
+  pthread_attr_t sattr;
+  pthread_attr_init(&sattr);
+  pthread_getattr_np(thread, &sattr);
+  int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
+  SB_DCHECK(rc == 0);
+  SB_DCHECK(stackBase);
+  pthread_attr_destroy(&sattr);
+  *out_high = static_cast<char*>(stackBase) + stackSize;
+  *out_low = stackBase;
+}
+</pre>
+</div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void**</code><br>        <code>out_high</code></td>
+    <td>The highest addressable byte + 1 for the current thread.</td>
+  </tr>
+  <tr>
+    <td><code>void**</code><br>        <code>out_low</code></td>
+    <td>The lowest addressable byte for the current thread.</td>
+  </tr>
+</table>
+
+### SbMemoryIsAligned
+
+**Description**
+
+Checks whether `memory` is aligned to `alignment` bytes.
+
+**Definition**
+
+```
+static SB_C_FORCE_INLINE bool SbMemoryIsAligned(const void* memory,
+                                                size_t alignment) {
+  return ((uintptr_t)memory) % alignment == 0;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const void*</code></td>
+    <td><code>memory</code></td>
+  </tr>
+  <tr>
+    <td><code>size_t</code></td>
+    <td><code>alignment</code></td>
+  </tr>
+</table>
+
+### SbMemoryMap
+
+**Description**
+
+Allocates `size_bytes` worth of physical memory pages and maps them into an 
+available virtual region. This function returns `SB_MEMORY_MAP_FAILED` on 
+failure. `NULL` is a valid return value.
+
+**Definition**
+
+```
+SB_EXPORT void* SbMemoryMap(int64_t size_bytes, int flags, const char* name);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int64_t</code><br>        <code>size_bytes</code></td>
+    <td>The amount of physical memory pages to be allocated.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>flags</code></td>
+    <td>The bitwise OR of the protection flags for the mapped memory 
+as specified in <code>SbMemoryMapFlags</code>.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>name</code></td>
+    <td>A value that appears in the debugger on some platforms. The value 
+can be up to 32 bytes.</td>
+  </tr>
+</table>
+
+### SbMemoryMove
+
+**Description**
+
+Copies `count` sequential bytes from `source` to `destination`, with support 
+for the `source` and `destination` regions overlapping. This function is 
+meant to be a drop-in replacement for `memmove`.<br><br>
+
+ 
+The function's behavior is undefined if `destination` or `source` are NULL, 
+and the function is a no-op if `count` is 0. The return value is 
+`destination`.
+
+**Definition**
+
+```
+SB_EXPORT void* SbMemoryMove(void* destination,
+                             const void* source,
+                             size_t count);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>destination</code></td>
+    <td>The destination of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>source</code></td>
+    <td>The source of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of sequential bytes to be copied.</td>
+  </tr>
+</table>
+
+### SbMemoryReallocateChecked
+
+**Description**
+
+This function is identical to <code><a href="#sbmemoryreallocateunchecked">SbMemoryReallocateUnchecked</a></code>, but it aborts 
+(`abort()`) in the case of an allocation failure.
+
+**Definition**
+
+```
+static SB_C_FORCE_INLINE void* SbMemoryReallocateChecked(void* memory,
+                                                         size_t size) {
+  void* address = SbMemoryReallocateUnchecked(memory, size);
+  SbAbortIfAllocationFailed(size, address);
+  return address;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>memory</code></td>
+    <td>The chunk of memory to be resized. <code>memory</code> may be NULL, in which 
+case it behaves exactly like <code><a href="#sbmemoryallocateunchecked">SbMemoryAllocateUnchecked</a></code>.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The size to which <code>memory</code> will be resized. If <code>size</code> is <code>0</code>, 
+the function may return <code>NULL</code> or it may return a unique pointer value 
+that can be passed to <code><a href="#sbmemoryfree">SbMemoryFree</a></code>.</td>
+  </tr>
+</table>
+
+### SbMemoryReallocateUnchecked
+
+**Description**
+
+Attempts to resize `memory` to be at least `size` bytes, without touching 
+the contents of memory. 
+<ul><li>If the function cannot perform the fast resize, it allocates a new chunk 
+of memory, copies the contents over, and frees the previous chunk, 
+returning a pointer to the new chunk. 
+</li><li>If the function cannot perform the slow resize, it returns `NULL`, 
+leaving the given memory chunk unchanged. 
+This function is meant to be a drop-in replacement for `realloc`.
+
+**Definition**
+
+```
+SB_EXPORT void* SbMemoryReallocateUnchecked(void* memory, size_t size);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>memory</code></td>
+    <td>The chunk of memory to be resized. <code>memory</code> may be NULL, in which 
+case it behaves exactly like <code><a href="#sbmemoryallocateunchecked">SbMemoryAllocateUnchecked</a></code>.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>size</code></td>
+    <td>The size to which <code>memory</code> will be resized. If <code>size</code> is <code>0</code>, 
+the function may return <code>NULL</code> or it may return a unique pointer value 
+that can be passed to <code><a href="#sbmemoryfree">SbMemoryFree</a></code>.</td>
+  </tr>
+</table>
+
+### SbMemorySet
+
+**Description**
+
+Fills `count` sequential bytes starting at `destination`, with the unsigned 
+char coercion of `byte_value`. This function is meant to be a drop-in 
+replacement for `memset`.<br><br>
+
+ 
+The function's behavior is undefined if `destination` is NULL, and the 
+function is a no-op if `count` is 0. The return value is `destination`.
+
+**Definition**
+
+```
+SB_EXPORT void* SbMemorySet(void* destination, int byte_value, size_t count);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>destination</code></td>
+    <td>The destination of the copied memory.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>byte_value</code></td>
+    <td></td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of sequential bytes to be set.</td>
+  </tr>
+</table>
+
+### SbMemoryUnmap
+
+**Description**
+
+Unmap `size_bytes` of physical pages starting from `virtual_address`, 
+returning `true` on success. After this function completes, 
+[virtual_address, virtual_address + size_bytes) will not be read/writable. 
+This function can unmap multiple contiguous regions that were mapped with 
+separate calls to <code><a href="#sbmemorymap">SbMemoryMap()</a></code>. For example, if one call to 
+`SbMemoryMap(0x1000)` returns `(void*)0xA000`, and another call to 
+`SbMemoryMap(0x1000)` returns `(void*)0xB000`, 
+`SbMemoryUnmap(0xA000, 0x2000)` should free both regions.
+
+**Definition**
+
+```
+SB_EXPORT bool SbMemoryUnmap(void* virtual_address, int64_t size_bytes);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>virtual_address</code></td>
+    <td></td>
+  </tr>
+  <tr>
+    <td><code>int64_t</code><br>        <code>size_bytes</code></td>
+    <td></td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/memory_reporter.md b/src/cobalt/site/docs/reference/starboard/modules/memory_reporter.md
new file mode 100644
index 0000000..1a7c0d1
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/memory_reporter.md
@@ -0,0 +1,53 @@
+---
+layout: doc
+title: "Starboard Module Reference: memory_reporter.h"
+---
+
+Provides an interface for memory reporting.
+
+## Functions
+
+### SbMemorySetReporter
+
+**Description**
+
+Sets the MemoryReporter. Any previous memory reporter is unset. No lifetime
+management is done internally on input pointer.<br>
+Returns true if the memory reporter was set with no errors. If an error
+was reported then check the log for why it failed.<br>
+Note that other than a thread-barrier-write of the input pointer, there is
+no thread safety guarantees with this function due to performance
+considerations. It's recommended that this be called once during the
+lifetime of the program, or not at all. Do not delete the supplied pointer,
+ever.
+Example (Good):
+SbMemoryReporter* mem_reporter = new ...;
+SbMemorySetReporter(&mem_reporter);
+...
+SbMemorySetReporter(NULL);  // allow value to leak.
+Example (Bad):
+SbMemoryReporter* mem_reporter = new ...;
+SbMemorySetReporter(&mem_reporter);
+...
+SbMemorySetReporter(NULL);
+delete mem_reporter;        // May crash.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbMemorySetReporter(struct SbMemoryReporter* tracker);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>struct SbMemoryReporter*</code><br>
+        <code>tracker</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/microphone.md b/src/cobalt/site/docs/reference/starboard/modules/microphone.md
new file mode 100644
index 0000000..ced29f5
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/microphone.md
@@ -0,0 +1,529 @@
+---
+layout: doc
+title: "Starboard Module Reference: microphone.h"
+---
+
+Defines functions for microphone creation, control, audio data fetching,
+and destruction. This module supports multiple calls to |SbMicrophoneOpen|
+and |SbMicrophoneClose|, and the implementation should handle multiple calls
+to one of those functions on the same microphone. For example, your
+implementation should handle cases where |SbMicrophoneOpen| is called twice
+on the same microphone without a call to |SbMicrophoneClose| in between.<br>
+This API is not thread-safe and must be called from a single thread.<br>
+How to use this API:
+<ol><li>Call |SbMicrophoneGetAvailableInfos| to get a list of available microphone
+information.
+</li><li>Create a supported microphone, using |SbMicrophoneCreate|, with enough
+buffer size and sample rate. Use |SbMicrophoneIsSampleRateSupported| to
+verify the sample rate.
+</li><li>Use |SbMicrophoneOpen| to open the microphone port and start recording
+audio data.
+</li><li>Periodically read out the data from microphone with |SbMicrophoneRead|.
+</li><li>Call |SbMicrophoneClose| to close the microphone port and stop recording
+audio data.
+</li><li>Destroy the microphone with |SbMicrophoneDestroy|.</li></ol>
+
+## Enums
+
+### SbMicrophoneType
+
+All possible microphone types.
+
+**Values**
+
+*   `kSbMicrophoneCamera` - Built-in microphone in camera.
+*   `kSbMicrophoneUSBHeadset` - Microphone in the headset that can be a wired or wireless USB headset.
+*   `kSbMicrophoneVRHeadset` - Microphone in the VR headset.
+*   `kSBMicrophoneAnalogHeadset` - Microphone in the analog headset.
+*   `kSbMicrophoneUnknown` - Unknown microphone type. The microphone could be different than the otherenum descriptions or could fall under one of those descriptions.
+
+## Structs
+
+### SbMicrophoneId
+
+An opaque handle to an implementation-private structure that represents a
+microphone ID.
+
+### SbMicrophoneInfo
+
+Microphone information.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>SbMicrophoneId</code><br>        <code>id</code></td>    <td>Microphone id.</td>  </tr>
+  <tr>
+    <td><code>SbMicrophoneType</code><br>        <code>type</code></td>    <td>Microphone type.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>max_sample_rate_hz</code></td>    <td>The microphone's maximum supported sampling rate.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>min_read_size</code></td>    <td>The minimum read size required for each read from microphone.</td>  </tr>
+</table>
+
+### SbMicrophone
+
+An opaque handle to an implementation-private structure that represents a
+microphone.
+
+## Functions
+
+### SbMicrophoneClose
+
+**Description**
+
+Closes the microphone port, stops recording audio on `microphone`, and
+clears the unread buffer if it is not empty. If the microphone has already
+been stopped, this call is ignored. The return value indicates whether the
+microphone is closed.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMicrophoneClose-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMicrophoneClose-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMicrophoneClose-declaration">
+<pre>
+SB_EXPORT bool SbMicrophoneClose(SbMicrophone microphone);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMicrophoneClose-stub">
+
+```
+#include "starboard/microphone.h"
+
+#if !SB_HAS(MICROPHONE)
+#error "SB_HAS_MICROPHONE must be set to build this file."
+#endif
+
+bool SbMicrophoneClose(SbMicrophone microphone) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMicrophone</code><br>        <code>microphone</code></td>
+    <td>The microphone to close.</td>
+  </tr>
+</table>
+
+### SbMicrophoneCreate
+
+**Description**
+
+Creates a microphone with the specified ID, audio sample rate, and cached
+audio buffer size. Starboard only requires support for creating one
+microphone at a time, and implementations may return an error if a second
+microphone is created before the first is destroyed.<br>
+The function returns the newly created SbMicrophone object. However, if you
+try to create a microphone that has already been initialized, if the sample
+rate is unavailable, or if the buffer size is invalid, the function should
+return `kSbMicrophoneInvalid`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMicrophoneCreate-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMicrophoneCreate-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMicrophoneCreate-declaration">
+<pre>
+SB_EXPORT SbMicrophone SbMicrophoneCreate(SbMicrophoneId id,
+                                          int sample_rate_in_hz,
+                                          int buffer_size_bytes);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMicrophoneCreate-stub">
+
+```
+#include "starboard/microphone.h"
+
+#if !SB_HAS(MICROPHONE)
+#error "SB_HAS_MICROPHONE must be set to build this file."
+#endif
+
+SbMicrophone SbMicrophoneCreate(SbMicrophoneId id,
+                                int sample_rate_in_hz,
+                                int buffer_size) {
+  return kSbMicrophoneInvalid;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMicrophoneId</code><br>        <code>id</code></td>
+    <td>The ID that will be assigned to the newly created SbMicrophone.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>sample_rate_in_hz</code></td>
+    <td>The new microphone's audio sample rate in Hz.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>buffer_size_bytes</code></td>
+    <td>The size of the buffer where signed 16-bit integer
+audio data is temporarily cached to during the capturing. The audio data
+is removed from the audio buffer if it has been read, and new audio data
+can be read from this buffer in smaller chunks than this size. This
+parameter must be set to a value greater than zero and the ideal size is
+<code>2^n</code>.</td>
+  </tr>
+</table>
+
+### SbMicrophoneDestroy
+
+**Description**
+
+Destroys a microphone. If the microphone is in started state, it is first
+stopped and then destroyed. Any data that has been recorded and not read
+is thrown away.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMicrophoneDestroy-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMicrophoneDestroy-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMicrophoneDestroy-declaration">
+<pre>
+SB_EXPORT void SbMicrophoneDestroy(SbMicrophone microphone);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMicrophoneDestroy-stub">
+
+```
+#include "starboard/microphone.h"
+
+#if !SB_HAS(MICROPHONE)
+#error "SB_HAS_MICROPHONE must be set to build this file."
+#endif
+
+void SbMicrophoneDestroy(SbMicrophone microphone) {}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMicrophone</code><br>
+        <code>microphone</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMicrophoneGetAvailable
+
+**Description**
+
+Retrieves all currently available microphone information and stores it in
+`out_info_array`. The return value is the number of the available
+microphones. If the number of available microphones is larger than
+`info_array_size`, then `out_info_array` is filled up with as many available
+microphones as possible and the actual number of available microphones is
+returned. A negative return value indicates that an internal error occurred.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMicrophoneGetAvailable-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMicrophoneGetAvailable-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMicrophoneGetAvailable-declaration">
+<pre>
+SB_EXPORT int SbMicrophoneGetAvailable(SbMicrophoneInfo* out_info_array,
+                                       int info_array_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMicrophoneGetAvailable-stub">
+
+```
+#include "starboard/microphone.h"
+
+#if !SB_HAS(MICROPHONE)
+#error "SB_HAS_MICROPHONE must be set to build this file."
+#endif
+
+int SbMicrophoneGetAvailable(SbMicrophoneInfo* out_info_array,
+                             int info_array_size) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMicrophoneInfo*</code><br>        <code>out_info_array</code></td>
+    <td>All currently available information about the microphone
+is placed into this output parameter.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>info_array_size</code></td>
+    <td>The size of <code>out_info_array</code>.</td>
+  </tr>
+</table>
+
+### SbMicrophoneIdIsValid
+
+**Description**
+
+Indicates whether the given microphone ID is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbMicrophoneIdIsValid(SbMicrophoneId id) {
+  return id != kSbMicrophoneIdInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMicrophoneId</code><br>
+        <code>id</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMicrophoneIsSampleRateSupported
+
+**Description**
+
+Indicates whether the microphone supports the sample rate.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMicrophoneIsSampleRateSupported-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMicrophoneIsSampleRateSupported-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMicrophoneIsSampleRateSupported-declaration">
+<pre>
+SB_EXPORT bool SbMicrophoneIsSampleRateSupported(SbMicrophoneId id,
+                                                 int sample_rate_in_hz);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMicrophoneIsSampleRateSupported-stub">
+
+```
+#include "starboard/microphone.h"
+
+#if !SB_HAS(MICROPHONE)
+#error "SB_HAS_MICROPHONE must be set to build this file."
+#endif
+
+bool SbMicrophoneIsSampleRateSupported(SbMicrophoneId id,
+                                       int sample_rate_in_hz) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMicrophoneId</code><br>
+        <code>id</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>sample_rate_in_hz</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMicrophoneIsValid
+
+**Description**
+
+Indicates whether the given microphone is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbMicrophoneIsValid(SbMicrophone microphone) {
+  return microphone != kSbMicrophoneInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMicrophone</code><br>
+        <code>microphone</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbMicrophoneOpen
+
+**Description**
+
+Opens the microphone port and starts recording audio on `microphone`.<br>
+Once started, the client needs to periodically call `SbMicrophoneRead` to
+receive the audio data. If the microphone has already been started, this call
+clears the unread buffer. The return value indicates whether the microphone
+is open.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMicrophoneOpen-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMicrophoneOpen-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMicrophoneOpen-declaration">
+<pre>
+SB_EXPORT bool SbMicrophoneOpen(SbMicrophone microphone);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMicrophoneOpen-stub">
+
+```
+#include "starboard/microphone.h"
+
+#if !SB_HAS(MICROPHONE)
+#error "SB_HAS_MICROPHONE must be set to build this file."
+#endif
+
+bool SbMicrophoneOpen(SbMicrophone microphone) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMicrophone</code><br>        <code>microphone</code></td>
+    <td>The microphone that will be opened and will start recording
+audio.</td>
+  </tr>
+</table>
+
+### SbMicrophoneRead
+
+**Description**
+
+Retrieves the recorded audio data from the microphone and writes that data
+to `out_audio_data`.<br>
+The return value is zero or the positive number of bytes that were read.
+Neither the return value nor `audio_data_size` exceeds the buffer size.
+A negative return value indicates that an error occurred.<br>
+This function should be called frequently. Otherwise, the microphone only
+buffers `buffer_size` bytes as configured in `SbMicrophoneCreate` and the
+new audio data is thrown out. No audio data is read from a stopped
+microphone.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMicrophoneRead-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMicrophoneRead-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMicrophoneRead-declaration">
+<pre>
+SB_EXPORT int SbMicrophoneRead(SbMicrophone microphone,
+                               void* out_audio_data,
+                               int audio_data_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMicrophoneRead-stub">
+
+```
+#include "starboard/microphone.h"
+
+#if !SB_HAS(MICROPHONE)
+#error "SB_HAS_MICROPHONE must be set to build this file."
+#endif
+
+int SbMicrophoneRead(SbMicrophone microphone,
+                     void* out_audio_data,
+                     int audio_data_size) {
+  return -1;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMicrophone</code><br>        <code>microphone</code></td>
+    <td>The microphone from which to retrieve recorded audio data.</td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>        <code>out_audio_data</code></td>
+    <td>The buffer to which the retrieved data will be written.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>audio_data_size</code></td>
+    <td>The number of requested bytes. If <code>audio_data_size</code> is
+smaller than <code>min_read_size</code> of <code>SbMicrophoneInfo</code>, the extra audio data
+that has already been read from the device is discarded.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/mutex.md b/src/cobalt/site/docs/reference/starboard/modules/mutex.md
new file mode 100644
index 0000000..5496079
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/mutex.md
@@ -0,0 +1,272 @@
+---
+layout: doc
+title: "Starboard Module Reference: mutex.h"
+---
+
+Defines a mutually exclusive lock that can be used to coordinate with other
+threads.
+
+## Enums
+
+### SbMutexResult
+
+Enumeration of possible results from acquiring a mutex.
+
+**Values**
+
+*   `kSbMutexAcquired` - The mutex was acquired successfully.
+*   `kSbMutexBusy` - The mutex was not acquired because it was held by someone else.
+*   `kSbMutexDestroyed` - The mutex has already been destroyed.
+
+## Functions
+
+### SbMutexAcquire
+
+**Description**
+
+Acquires `mutex`, blocking indefinitely. The return value identifies
+the acquisition result. SbMutexes are not reentrant, so a recursive
+acquisition blocks forever.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMutexAcquire-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMutexAcquire-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMutexAcquire-declaration">
+<pre>
+SB_EXPORT SbMutexResult SbMutexAcquire(SbMutex* mutex);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMutexAcquire-stub">
+
+```
+#include "starboard/mutex.h"
+
+SbMutexResult SbMutexAcquire(SbMutex* /*mutex*/) {
+  return kSbMutexDestroyed;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMutex*</code><br>        <code>mutex</code></td>
+    <td>The mutex to be acquired.</td>
+  </tr>
+</table>
+
+### SbMutexAcquireTry
+
+**Description**
+
+Acquires `mutex`, without blocking. The return value identifies
+the acquisition result. SbMutexes are not reentrant, so a recursive
+acquisition always fails.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMutexAcquireTry-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMutexAcquireTry-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMutexAcquireTry-declaration">
+<pre>
+SB_EXPORT SbMutexResult SbMutexAcquireTry(SbMutex* mutex);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMutexAcquireTry-stub">
+
+```
+#include "starboard/mutex.h"
+
+SbMutexResult SbMutexAcquireTry(SbMutex* /*mutex*/) {
+  return kSbMutexDestroyed;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMutex*</code><br>        <code>mutex</code></td>
+    <td>The mutex to be acquired.</td>
+  </tr>
+</table>
+
+### SbMutexCreate
+
+**Description**
+
+Creates a new mutex. The return value indicates whether the function
+was able to create a new mutex.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMutexCreate-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMutexCreate-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMutexCreate-declaration">
+<pre>
+SB_EXPORT bool SbMutexCreate(SbMutex* out_mutex);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMutexCreate-stub">
+
+```
+#include "starboard/mutex.h"
+
+bool SbMutexCreate(SbMutex* /*mutex*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMutex*</code><br>        <code>out_mutex</code></td>
+    <td>The handle to the newly created mutex.</td>
+  </tr>
+</table>
+
+### SbMutexDestroy
+
+**Description**
+
+Destroys a mutex. The return value indicates whether the destruction was
+successful.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMutexDestroy-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMutexDestroy-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMutexDestroy-declaration">
+<pre>
+SB_EXPORT bool SbMutexDestroy(SbMutex* mutex);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMutexDestroy-stub">
+
+```
+#include "starboard/mutex.h"
+
+bool SbMutexDestroy(SbMutex* /*mutex*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMutex*</code><br>        <code>mutex</code></td>
+    <td>The mutex to be invalidated.</td>
+  </tr>
+</table>
+
+### SbMutexIsSuccess
+
+**Description**
+
+Indicates whether the given result is a success. A value of `true` indicates
+that the mutex was acquired.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE bool SbMutexIsSuccess(SbMutexResult result) {
+  return result == kSbMutexAcquired;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMutexResult</code><br>        <code>result</code></td>
+    <td>The result being checked.</td>
+  </tr>
+</table>
+
+### SbMutexRelease
+
+**Description**
+
+Releases `mutex` held by the current thread. The return value indicates
+whether the release was successful. Releases should always be successful
+if `mutex` is held by the current thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbMutexRelease-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbMutexRelease-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbMutexRelease-declaration">
+<pre>
+SB_EXPORT bool SbMutexRelease(SbMutex* mutex);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbMutexRelease-stub">
+
+```
+#include "starboard/mutex.h"
+
+bool SbMutexRelease(SbMutex* /*mutex*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbMutex*</code><br>        <code>mutex</code></td>
+    <td>The mutex to be released.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/once.md b/src/cobalt/site/docs/reference/starboard/modules/once.md
new file mode 100644
index 0000000..dfc1559
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/once.md
@@ -0,0 +1,161 @@
+---
+layout: doc
+title: "Starboard Module Reference: once.h"
+---
+
+Onces represent initializations that should only ever happen once per
+process, in a thread-safe way.
+
+## Macros
+
+<div id="macro-documentation-section">
+
+<h3 id="sb_once_initialize_function" class="small-h3">SB_ONCE_INITIALIZE_FUNCTION</h3>
+
+Defines a function that will initialize the indicated type once and return
+it. This initialization is thread safe if the type being created is side
+effect free.<br>
+These macros CAN ONLY BE USED IN A CC file, never in a header file.<br>
+Example (in cc file):
+SB_ONCE_INITIALIZE_FUNCTION(MyClass, GetOrCreateMyClass)
+..
+MyClass* instance = GetOrCreateMyClass();
+MyClass* instance2 = GetOrCreateMyClass();
+DCHECK_EQ(instance, instance2);
+
+</div>
+
+## Functions
+
+### Init
+
+**Declaration**
+
+```
+    static void Init() {                                   \
+      s_singleton = new Type();                            \
+    }                                                      \
+  };                                                       \
+  SbOnce(&s_once_flag, Local::Init);                       \
+  return s_singleton;                                      \
+}
+```
+
+### SbOnce
+
+**Description**
+
+Thread-safely runs `init_routine` only once.
+<ul><li>If this `once_control` has not run a function yet, this function runs
+`init_routine` in a thread-safe way and then returns `true`.
+</li><li>If <code>SbOnce()</code> was called with `once_control` before, the function returns
+`true` immediately.
+</li><li>If `once_control` or `init_routine` is invalid, the function returns
+`false`.</li></ul>
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbOnce-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbOnce-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbOnce-declaration">
+<pre>
+SB_EXPORT bool SbOnce(SbOnceControl* once_control,
+                      SbOnceInitRoutine init_routine);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbOnce-stub">
+
+```
+#include "starboard/once.h"
+
+bool SbOnce(SbOnceControl* /*once_control*/,
+            SbOnceInitRoutine /*init_routine*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbOnceControl*</code><br>
+        <code>once_control</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbOnceInitRoutine</code><br>
+        <code>init_routine</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### s_once_flag 
+
+**Description**
+
+Defines a function that will initialize the indicated type once and return
+it. This initialization is thread safe if the type being created is side
+effect free.<br>
+These macros CAN ONLY BE USED IN A CC file, never in a header file.<br>
+Example (in cc file):
+SB_ONCE_INITIALIZE_FUNCTION(MyClass, GetOrCreateMyClass)
+..
+MyClass* instance = GetOrCreateMyClass();
+MyClass* instance2 = GetOrCreateMyClass();
+DCHECK_EQ(instance, instance2);
+
+**Declaration**
+
+```
+  static SbOnceControl s_once_flag = SB_ONCE_INITIALIZER;  \
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>= SB_ONCE_INITIALIZER; </code><br>
+        <code>\</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### s_singleton 
+
+**Declaration**
+
+```
+  static Type* s_singleton = NULL;                         \
+  struct Local {                                           \
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>= NULL;                        </code><br>
+        <code>\</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>struct Local {                                          </code><br>
+        <code>\</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/player.md b/src/cobalt/site/docs/reference/starboard/modules/player.md
new file mode 100644
index 0000000..5cffbf7
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/player.md
@@ -0,0 +1,1133 @@
+---
+layout: doc
+title: "Starboard Module Reference: player.h"
+---
+
+Defines an interface for controlling playback of media elementary streams.
+
+## Enums
+
+### SbPlayerDecoderState
+
+An indicator of whether the decoder can accept more samples.
+
+**Values**
+
+*   `kSbPlayerDecoderStateNeedsData` - The decoder is asking for one more sample.
+*   `kSbPlayerDecoderStateBufferFull` - The decoder is not ready for any more samples, so do not send them.Note that this enum value has been deprecated and the SbPlayerimplementation should no longer use this value.
+*   `kSbPlayerDecoderStateDestroyed` - The player has been destroyed, and will send no more callbacks.
+
+### SbPlayerOutputMode
+
+**Values**
+
+*   `kSbPlayerOutputModeDecodeToTexture` - Requests for SbPlayer to produce an OpenGL texture that the client mustdraw every frame with its graphics rendering. It may be that we get atexture handle, but cannot perform operations like glReadPixels on it if itis DRM-protected, or it may not support DRM-protected content at all.  Whenthis output mode is provided to SbPlayerCreate(), the application will beable to pull frames via calls to SbPlayerGetCurrentFrame().
+*   `kSbPlayerOutputModePunchOut` - Requests for SbPlayer to use a "punch-out" output mode, where video isrendered to the far background, and the graphics plane is automaticallycomposited on top of the video by the platform. The client must punch analpha hole out of the graphics plane for video to show through.  In thiscase, changing the video bounds must be tightly synchronized between theplayer and the graphics plane.
+*   `kSbPlayerOutputModeInvalid` - An invalid output mode.
+
+### SbPlayerState
+
+An indicator of the general playback state.
+
+**Values**
+
+*   `kSbPlayerStateInitialized` - The player has just been initialized. It is expecting an SbPlayerSeek()call to enter the prerolling state.
+*   `kSbPlayerStatePrerolling` - The player is prerolling, collecting enough data to fill the pipelinebefore presentation starts. After the first preroll is completed, thereshould always be a video frame to render, even if the player goes back toPrerolling after a Seek.
+*   `kSbPlayerStatePresenting` - The player is presenting media, and it is either paused or activelyplaying in real-time. Note that the implementation should use thisstate to signal that the preroll has been finished.
+*   `kSbPlayerStateEndOfStream` - The player is presenting media, but it is paused at the end of the stream.
+*   `kSbPlayerStateDestroyed` - The player has been destroyed, and will send no more callbacks.
+*   `kSbPlayerStateError` - The player encountered an error. It expects an SbPlayerDestroy() callto tear down the player. Calls to other functions may be ignored andcallbacks may not be triggered.
+
+## Macros
+
+<div id="macro-documentation-section">
+
+<h3 id="sb_player_initial_ticket" class="small-h3">SB_PLAYER_INITIAL_TICKET</h3>
+
+The value of the initial ticket held by the player before the first seek.
+The player will use this ticket value to make the first call to
+SbPlayerStatusFunc with kSbPlayerStateInitialized.
+
+<h3 id="sb_player_no_duration" class="small-h3">SB_PLAYER_NO_DURATION</h3>
+
+The value to pass into SbPlayerCreate's `duration_ptr` argument for cases
+where the duration is unknown, such as for live streams.
+
+</div>
+
+## Structs
+
+### SbPlayerInfo
+
+Information about the current media playback state.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>SbMediaTime</code><br>        <code>current_media_pts</code></td>    <td>The position of the playback head, as precisely as possible, in 90KHz ticks
+(PTS).</td>  </tr>
+  <tr>
+    <td><code>SbMediaTime</code><br>        <code>duration_pts</code></td>    <td>The known duration of the currently playing media stream, in 90KHz ticks
+(PTS).</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>frame_width</code></td>    <td>The width of the currently displayed frame, in pixels, or 0 if not provided
+by this player.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>frame_height</code></td>    <td>The height of the currently displayed frame, in pixels, or 0 if not
+provided by this player.</td>  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>is_paused</code></td>    <td>Whether playback is currently paused.</td>  </tr>
+  <tr>
+    <td><code>double</code><br>        <code>volume</code></td>    <td>The current player volume in [0, 1].</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>total_video_frames</code></td>    <td>The number of video frames sent to the player since the creation of the
+player.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>dropped_video_frames</code></td>    <td>The number of video frames decoded but not displayed since the creation of
+the player.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>corrupted_video_frames</code></td>    <td>The number of video frames that failed to be decoded since the creation of
+the player.</td>  </tr>
+  <tr>
+    <td><code>double</code><br>        <code>playback_rate</code></td>    <td>The rate of playback.  The video is played back in a speed that is
+proportional to this.  By default it is 1.0 which indicates that the
+playback is at normal speed.  When it is greater than one, the video is
+played in a faster than normal speed.  When it is less than one, the video
+is played in a slower than normal speed.  Negative speeds are not
+supported.</td>  </tr>
+</table>
+
+### SbPlayer
+
+An opaque handle to an implementation-private structure representing a
+player.
+
+## Functions
+
+### SbPlayerCreate
+
+**Description**
+
+Creates a player that will be displayed on `window` for the specified
+`video_codec` and `audio_codec`, acquiring all resources needed to operate
+it, and returning an opaque handle to it. The expectation is that a new
+player will be created and destroyed for every playback.<br>
+This function returns the created player. Note the following:
+<ul><li>The associated decoder of the returned player should be assumed to not be
+in `kSbPlayerDecoderStateNeedsData` until <code><a href="#sbplayerseek">SbPlayerSeek()</a></code> has been called
+on it.
+</li><li>It is expected either that the thread that calls <code>SbPlayerCreate</code> is the same
+thread that calls the other `SbPlayer` functions for that player, or that
+there is a mutex guarding calls into each `SbPlayer` instance.
+</li><li>If there is a platform limitation on how many players can coexist
+simultaneously, then calls made to this function that attempt to exceed
+that limit will return `kSbPlayerInvalid`.</li></ul>
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbPlayerCreate-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbPlayerCreate-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbPlayerCreate-declaration">
+<pre>
+SB_EXPORT SbPlayer
+SbPlayerCreate(SbWindow window,
+               SbMediaVideoCodec video_codec,
+               SbMediaAudioCodec audio_codec,
+               SbMediaTime duration_pts,
+               SbDrmSystem drm_system,
+               const SbMediaAudioHeader* audio_header,
+               SbPlayerDeallocateSampleFunc sample_deallocate_func,
+               SbPlayerDecoderStatusFunc decoder_status_func,
+               SbPlayerStatusFunc player_status_func,
+               void* context,
+               SbPlayerOutputMode output_mode,
+               SbDecodeTargetGraphicsContextProvider* context_provider);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbPlayerCreate-stub">
+
+```
+#include "starboard/player.h"
+
+#if !SB_HAS(PLAYER)
+#error "SbPlayerCreate requires SB_HAS(PLAYER)."
+#endif
+
+SbPlayer SbPlayerCreate(SbWindow /*window*/,
+                        SbMediaVideoCodec /*video_codec*/,
+                        SbMediaAudioCodec /*audio_codec*/,
+                        SbMediaTime /*duration_pts*/,
+                        SbDrmSystem /*drm_system*/,
+                        const SbMediaAudioHeader* /*audio_header*/,
+                        SbPlayerDeallocateSampleFunc /*sample_deallocate_func*/,
+                        SbPlayerDecoderStatusFunc /*decoder_status_func*/,
+                        SbPlayerStatusFunc /*player_status_func*/,
+                        void* /*context*/,
+                        SbPlayerOutputMode /*output_mode*/,
+                        SbDecodeTargetGraphicsContextProvider* /*provider*/) {
+  return kSbPlayerInvalid;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbWindow</code><br>        <code>window</code></td>
+    <td>The window that will display the player. <code>window</code> can be
+<code>kSbWindowInvalid</code> for platforms where video is only displayed on a
+particular window that the underlying implementation already has access to.</td>
+  </tr>
+  <tr>
+    <td><code>SbMediaVideoCodec</code><br>        <code>video_codec</code></td>
+    <td>The video codec used for the player. If <code>video_codec</code> is
+<code>kSbMediaVideoCodecNone</code>, the player is an audio-only player. If
+<code>video_codec</code> is any other value, the player is an audio/video decoder.</td>
+  </tr>
+  <tr>
+    <td><code>SbMediaAudioCodec</code><br>        <code>audio_codec</code></td>
+    <td>The audio codec used for the player. The value should never
+be <code>kSbMediaAudioCodecNone</code>. In addition, the caller must provide a
+populated <code>audio_header</code> if the audio codec is <code>kSbMediaAudioCodecAac</code>.</td>
+  </tr>
+  <tr>
+    <td><code>SbMediaTime</code><br>        <code>duration_pts</code></td>
+    <td>The expected media duration in 90KHz ticks (PTS). It may be
+set to <code>SB_PLAYER_NO_DURATION</code> for live streams.</td>
+  </tr>
+  <tr>
+    <td><code>SbDrmSystem</code><br>        <code>drm_system</code></td>
+    <td>If the media stream has encrypted portions, then this
+parameter provides an appropriate DRM system, created with
+<code>SbDrmCreateSystem()</code>. If the stream does not have encrypted portions,
+then <code>drm_system</code> may be <code>kSbDrmSystemInvalid</code>.</td>
+  </tr>
+  <tr>
+    <td><code>const SbMediaAudioHeader*</code><br>        <code>audio_header</code></td>
+    <td>Note that the caller must provide a populated <code>audio_header</code>
+if the audio codec is <code>kSbMediaAudioCodecAac</code>. Otherwise, <code>audio_header</code>
+can be NULL. See media.h for the format of the <code>SbMediaAudioHeader</code> struct.
+Note that <code>audio_specific_config</code> is a pointer and the content it points to
+is no longer valid after this function returns.  The implementation has to
+make a copy of the content if it is needed after the function returns.</td>
+  </tr>
+  <tr>
+    <td><code>SbPlayerDeallocateSampleFunc</code><br>        <code>sample_deallocate_func</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>SbPlayerDecoderStatusFunc</code><br>        <code>decoder_status_func</code></td>
+    <td>If not <code>NULL</code>, the decoder calls this function on an
+internal thread to provide an update on the decoder's status. No work
+should be done on this thread. Rather, it should just signal the client
+thread interacting with the decoder.</td>
+  </tr>
+  <tr>
+    <td><code>SbPlayerStatusFunc</code><br>        <code>player_status_func</code></td>
+    <td>If not <code>NULL</code>, the player calls this function on an
+internal thread to provide an update on the playback status. No work
+should be done on this thread. Rather, it should just signal the client
+thread interacting with the decoder.</td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>        <code>context</code></td>
+    <td>This is passed to all callbacks and is generally used to point
+at a class or struct that contains state associated with the player.</td>
+  </tr>
+  <tr>
+    <td><code>SbPlayerOutputMode</code><br>        <code>output_mode</code></td>
+    <td>Selects how the decoded video frames will be output.  For
+example, kSbPlayerOutputModePunchOut indicates that the decoded video
+frames will be output to a background video layer by the platform, and
+kSbPlayerOutputDecodeToTexture indicates that the decoded video frames
+should be made available for the application to pull via calls to
+SbPlayerGetCurrentFrame().</td>
+  </tr>
+  <tr>
+    <td><code>SbDecodeTargetGraphicsContextProvider*</code><br>        <code>context_provider</code></td>
+    <td> </td>  </tr>
+</table>
+
+### SbPlayerCreateWithUrl
+
+**Description**
+
+Creates a URL-based SbPlayer that will be displayed on `window` for
+the specified URL `url`, acquiring all resources needed to operate
+it, and returning an opaque handle to it. The expectation is that a
+new player will be created and destroyed for every playback.<br>
+In many ways this function is similar to <code><a href="#sbplayercreate">SbPlayerCreate</a></code>, but it is
+missing the input arguments related to the configuration and format
+of the audio and video stream, as well as the DRM system. The DRM
+system for a player created with <code>SbPlayerCreateWithUrl</code> can be set
+after creation using <code><a href="#sbplayersetdrmsystem">SbPlayerSetDrmSystem</a></code>. Because the DRM system
+is not available at the time of <code>SbPlayerCreateWithUrl</code>, it takes in
+a callback, `encrypted_media_init_data_encountered_cb`, which is
+run when encrypted media initial data is encountered.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbPlayerCreateWithUrl-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbPlayerCreateWithUrl-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbPlayerCreateWithUrl-declaration">
+<pre>
+SB_EXPORT SbPlayer
+SbPlayerCreateWithUrl(const char* url,
+                      SbWindow window,
+                      SbMediaTime duration_pts,
+                      SbPlayerStatusFunc player_status_func,
+                      SbPlayerEncryptedMediaInitDataEncounteredCB
+                          encrypted_media_init_data_encountered_cb,
+                      void* context);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbPlayerCreateWithUrl-stub">
+
+```
+#include "starboard/player.h"
+
+#if !SB_HAS(PLAYER)
+#error "SbPlayerCreateWithUrl requires SB_HAS(PLAYER)."
+#endif
+
+#if SB_HAS(PLAYER_WITH_URL)
+
+SbPlayer SbPlayerCreateWithUrl(
+    const char* /* url */,
+    SbWindow /* window */,
+    SbMediaTime /* duration_pts */,
+    SbPlayerStatusFunc /* player_status_func */,
+    SbPlayerEncryptedMediaInitDataEncounteredCB /* cb */,
+    void* /* context */) {
+  // Stub.
+  return kSbPlayerInvalid;
+}
+
+// TODO: Actually move this to a separate file or get rid of these URL
+// player stubs altogether.
+void SbPlayerSetDrmSystem(SbPlayer player, SbDrmSystem drm_system) { /* Stub */
+}
+
+#endif  // SB_HAS(PLAYER_WITH_URL)
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>
+        <code>url</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbWindow</code><br>
+        <code>window</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbMediaTime</code><br>
+        <code>duration_pts</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbPlayerStatusFunc</code><br>
+        <code>player_status_func</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code></code><br>
+        <code>SbPlayerEncryptedMediaInitDataEncounteredCB</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code></code><br>
+        <code>encrypted_media_init_data_encountered_cb</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>
+        <code>context</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbPlayerDestroy
+
+**Description**
+
+Destroys `player`, freeing all associated resources. Each callback must
+receive one more callback to say that the player was destroyed. Callbacks
+may be in-flight when <code>SbPlayerDestroy</code> is called, and should be ignored once
+this function is called.<br>
+It is not allowed to pass `player` into any other `SbPlayer` function once
+SbPlayerDestroy has been called on that player.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbPlayerDestroy-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbPlayerDestroy-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbPlayerDestroy-declaration">
+<pre>
+SB_EXPORT void SbPlayerDestroy(SbPlayer player);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbPlayerDestroy-stub">
+
+```
+#include "starboard/player.h"
+
+void SbPlayerDestroy(SbPlayer /*player*/) {}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbPlayer</code><br>        <code>player</code></td>
+    <td>The player to be destroyed.</td>
+  </tr>
+</table>
+
+### SbPlayerGetCurrentFrame
+
+**Description**
+
+Given a player created with the kSbPlayerOutputModeDecodeToTexture
+output mode, it will return a SbDecodeTarget representing the current frame
+to be rasterized.  On GLES systems, this function must be called on a
+thread with an EGLContext current, and specifically the EGLContext that will
+be used to eventually render the frame.  If this function is called with a
+`player` object that was created with an output mode other than
+kSbPlayerOutputModeDecodeToTexture, kSbDecodeTargetInvalid is returned.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbPlayerGetCurrentFrame-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbPlayerGetCurrentFrame-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbPlayerGetCurrentFrame-declaration">
+<pre>
+SB_EXPORT SbDecodeTarget SbPlayerGetCurrentFrame(SbPlayer player);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbPlayerGetCurrentFrame-stub">
+
+```
+#include "starboard/player.h"
+
+#if !SB_HAS(PLAYER)
+#error "This file requires SB_HAS(PLAYER)."
+#endif
+
+SbDecodeTarget SbPlayerGetCurrentFrame(SbPlayer /*player*/) {
+  return kSbDecodeTargetInvalid;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbPlayer</code><br>
+        <code>player</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbPlayerGetInfo
+
+**Description**
+
+Gets a snapshot of the current player state and writes it to
+`out_player_info`. This function may be called very frequently and is
+expected to be inexpensive.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbPlayerGetInfo-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbPlayerGetInfo-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbPlayerGetInfo-declaration">
+<pre>
+SB_EXPORT void SbPlayerGetInfo(SbPlayer player, SbPlayerInfo* out_player_info);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbPlayerGetInfo-stub">
+
+```
+#include "starboard/player.h"
+
+void SbPlayerGetInfo(SbPlayer /*player*/, SbPlayerInfo* /*out_player_info*/) {}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbPlayer</code><br>        <code>player</code></td>
+    <td>The player about which information is being retrieved.</td>
+  </tr>
+  <tr>
+    <td><code>SbPlayerInfo*</code><br>        <code>out_player_info</code></td>
+    <td>The information retrieved for the player.</td>
+  </tr>
+</table>
+
+### SbPlayerIsValid
+
+**Description**
+
+Returns whether the given player handle is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbPlayerIsValid(SbPlayer player) {
+  return player != kSbPlayerInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbPlayer</code><br>
+        <code>player</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbPlayerOutputModeSupported
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbPlayerOutputModeSupported-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbPlayerOutputModeSupported-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbPlayerOutputModeSupported-declaration">
+<pre>
+SB_EXPORT bool SbPlayerOutputModeSupported(SbPlayerOutputMode output_mode,
+                                           SbMediaVideoCodec codec,
+                                           SbDrmSystem drm_system);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbPlayerOutputModeSupported-stub">
+
+```
+#include "starboard/player.h"
+
+#if !SB_HAS(PLAYER)
+#error "This file requires SB_HAS(PLAYER)."
+#endif
+
+bool SbPlayerOutputModeSupported(SbPlayerOutputMode /*output_mode*/,
+                                 SbMediaVideoCodec /*codec*/,
+                                 SbDrmSystem /*drm_system*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbPlayerOutputMode</code><br>
+        <code>output_mode</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbMediaVideoCodec</code><br>
+        <code>codec</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbDrmSystem</code><br>
+        <code>drm_system</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbPlayerOutputModeSupportedWithUrl
+
+**Description**
+
+Returns true if the given URL player output mode is supported by
+the platform.  If this function returns true, it is okay to call
+SbPlayerCreate() with the given `output_mode`.
+
+**Declaration**
+
+```
+SB_EXPORT bool SbPlayerOutputModeSupportedWithUrl(
+    SbPlayerOutputMode output_mode);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbPlayerOutputMode</code><br>
+        <code>output_mode</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbPlayerSeek
+
+**Description**
+
+Tells the player to freeze playback (if playback has already started),
+reset or flush the decoder pipeline, and go back to the Prerolling state.
+The player should restart playback once it can display the frame at
+`seek_to_pts`, or the closest it can get. (Some players can only seek to
+I-Frames, for example.)<br>
+<ul><li>Seek must be called before samples are sent when starting playback for
+the first time, or the client never receives the
+`kSbPlayerDecoderStateNeedsData` signal.
+</li><li>A call to seek may interrupt another seek.
+</li><li>After this function is called, the client should not send any more audio
+or video samples until `SbPlayerDecoderStatusFunc` is called back with
+`kSbPlayerDecoderStateNeedsData` for each required media type.
+`SbPlayerDecoderStatusFunc` is the `decoder_status_func` callback function
+that was specified when the player was created (SbPlayerCreate).</li></ul><br>
+The `ticket` value is used to filter calls that may have been in flight
+when <code>SbPlayerSeek</code> was called. To be very specific, once <code>SbPlayerSeek</code> has
+been called with ticket X, a client should ignore all
+`SbPlayerDecoderStatusFunc` calls that do not pass in ticket X.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbPlayerSeek-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbPlayerSeek-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbPlayerSeek-declaration">
+<pre>
+SB_EXPORT void SbPlayerSeek(SbPlayer player,
+                            SbMediaTime seek_to_pts,
+                            int ticket);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbPlayerSeek-stub">
+
+```
+#include "starboard/player.h"
+
+void SbPlayerSeek(SbPlayer /*player*/,
+                  SbMediaTime /*seek_to_pts*/,
+                  int /*ticket*/) {}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbPlayer</code><br>        <code>player</code></td>
+    <td>The SbPlayer in which the seek operation is being performed.</td>
+  </tr>
+  <tr>
+    <td><code>SbMediaTime</code><br>        <code>seek_to_pts</code></td>
+    <td>The frame at which playback should begin.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>ticket</code></td>
+    <td>A user-supplied unique ID that is be passed to all subsequent
+<code>SbPlayerDecoderStatusFunc</code> calls. (That is the <code>decoder_status_func</code>
+callback function specified when calling <code><a href="#sbplayercreate">SbPlayerCreate</a></code>.)</td>
+  </tr>
+</table>
+
+### SbPlayerSetBounds
+
+**Description**
+
+Sets the player bounds to the given graphics plane coordinates. The changes
+do not take effect until the next graphics frame buffer swap. The default
+bounds for a player is the full screen.  This function is only relevant when
+the `player` is created with the kSbPlayerOutputModePunchOut output mode, and
+if this is not the case then this function call can be ignored.<br>
+This function is called on every graphics frame that changes the video
+bounds. For example, if the video bounds are being animated, then this will
+be called at up to 60 Hz. Since the function could be called up to once per
+frame, implementors should take care to avoid related performance concerns
+with such frequent calls.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbPlayerSetBounds-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbPlayerSetBounds-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbPlayerSetBounds-declaration">
+<pre>
+SB_EXPORT void SbPlayerSetBounds(SbPlayer player,
+                                 int z_index,
+                                 int x,
+                                 int y,
+                                 int width,
+                                 int height);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbPlayerSetBounds-stub">
+
+```
+#include "starboard/player.h"
+
+#if !SB_HAS(PLAYER)
+#error "This file requires SB_HAS(PLAYER)."
+#endif
+
+void SbPlayerSetBounds(SbPlayer /*player*/,
+                       int /*z_index*/,
+                       int /*x*/,
+                       int /*y*/,
+                       int /*width*/,
+                       int /*height*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbPlayer</code><br>        <code>player</code></td>
+    <td>The player that is being resized.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>z_index</code></td>
+    <td>The z-index of the player.  When the bounds of multiple players
+are overlapped, the one with larger z-index will be rendered on
+top of the ones with smaller z-index.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>x</code></td>
+    <td>The x-coordinate of the upper-left corner of the player.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>y</code></td>
+    <td>The y-coordinate of the upper-left corner of the player.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>width</code></td>
+    <td>The width of the player, in pixels.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>height</code></td>
+    <td>The height of the player, in pixels.</td>
+  </tr>
+</table>
+
+### SbPlayerSetDrmSystem
+
+**Description**
+
+Sets the DRM system of a running URL-based SbPlayer created with
+SbPlayerCreateWithUrl. This may only be run once for a given
+SbPlayer.
+
+**Declaration**
+
+```
+SB_EXPORT void SbPlayerSetDrmSystem(SbPlayer player, SbDrmSystem drm_system);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbPlayer</code><br>
+        <code>player</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>SbDrmSystem</code><br>
+        <code>drm_system</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbPlayerSetPlaybackRate
+
+**Description**
+
+Set the playback rate of the `player`.  `rate` is default to 1.0 which
+indicates the playback is at its original speed.  A `rate` greater than one
+will make the playback faster than its original speed.  For example, when
+`rate` is 2, the video will be played at twice the speed as its original
+speed.  A `rate` less than 1.0 will make the playback slower than its
+original speed.  When `rate` is 0, the playback will be paused.
+The function returns true when the playback rate is set to `playback_rate` or
+to a rate that is close to `playback_rate` which the implementation supports.
+It returns false when the playback rate is unchanged, this can happen when
+`playback_rate` is negative or if it is too high to support.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbPlayerSetPlaybackRate-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbPlayerSetPlaybackRate-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbPlayerSetPlaybackRate-declaration">
+<pre>
+SB_EXPORT bool SbPlayerSetPlaybackRate(SbPlayer player, double playback_rate);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbPlayerSetPlaybackRate-stub">
+
+```
+#include "starboard/player.h"
+
+#if !SB_HAS(PLAYER)
+#error "This file requires SB_HAS(PLAYER)."
+#endif
+
+bool SbPlayerSetPlaybackRate(SbPlayer /*player*/, double /*playback_rate*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbPlayer</code><br>
+        <code>player</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>double</code><br>
+        <code>playback_rate</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbPlayerSetVolume
+
+**Description**
+
+Sets the player's volume.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbPlayerSetVolume-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbPlayerSetVolume-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbPlayerSetVolume-declaration">
+<pre>
+SB_EXPORT void SbPlayerSetVolume(SbPlayer player, double volume);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbPlayerSetVolume-stub">
+
+```
+#include "starboard/player.h"
+
+void SbPlayerSetVolume(SbPlayer /*player*/, double /*volume*/) {}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbPlayer</code><br>        <code>player</code></td>
+    <td>The player in which the volume is being adjusted.</td>
+  </tr>
+  <tr>
+    <td><code>double</code><br>        <code>volume</code></td>
+    <td>The new player volume. The value must be between <code>0.0</code> and <code>1.0</code>,
+inclusive. A value of <code>0.0</code> means that the audio should be muted, and a
+value of <code>1.0</code> means that it should be played at full volume.</td>
+  </tr>
+</table>
+
+### SbPlayerWriteEndOfStream
+
+**Description**
+
+Writes a marker to `player`'s input stream of `stream_type` indicating that
+there are no more samples for that media type for the remainder of this
+media stream. This marker is invalidated, along with the rest of the stream's
+contents, after a call to <code><a href="#sbplayerseek">SbPlayerSeek</a></code>.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbPlayerWriteEndOfStream-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbPlayerWriteEndOfStream-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbPlayerWriteEndOfStream-declaration">
+<pre>
+SB_EXPORT void SbPlayerWriteEndOfStream(SbPlayer player,
+                                        SbMediaType stream_type);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbPlayerWriteEndOfStream-stub">
+
+```
+#include "starboard/player.h"
+
+void SbPlayerWriteEndOfStream(SbPlayer /*player*/,
+                              SbMediaType /*stream_type*/) {}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbPlayer</code><br>        <code>player</code></td>
+    <td>The player to which the marker is written.</td>
+  </tr>
+  <tr>
+    <td><code>SbMediaType</code><br>        <code>stream_type</code></td>
+    <td>The type of stream for which the marker is written.</td>
+  </tr>
+</table>
+
+### SbPlayerWriteSample
+
+**Description**
+
+Writes a single sample of the given media type to `player`'s input stream.
+Its data may be passed in via more than one buffers.  The lifetime of
+`sample_buffers`, `sample_buffer_sizes`, `video_sample_info`, and
+`sample_drm_info` (as well as member `subsample_mapping` contained inside it)
+are not guaranteed past the call to <code>SbPlayerWriteSample</code>. That means that
+before returning, the implementation must synchronously copy any information
+it wants to retain from those structures.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbPlayerWriteSample-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbPlayerWriteSample-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbPlayerWriteSample-declaration">
+<pre>
+SB_EXPORT void SbPlayerWriteSample(
+    SbPlayer player,
+    SbMediaType sample_type,
+#if SB_API_VERSION >= 6
+    const void* const* sample_buffers,
+    const int* sample_buffer_sizes,
+#else   // SB_API_VERSION >= 6
+    const void** sample_buffers,
+    int* sample_buffer_sizes,
+#endif  // SB_API_VERSION >= 6
+    int number_of_sample_buffers,
+    SbMediaTime sample_pts,
+    const SbMediaVideoSampleInfo* video_sample_info,
+    const SbDrmSampleInfo* sample_drm_info);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbPlayerWriteSample-stub">
+
+```
+#include "starboard/player.h"
+
+#if !SB_HAS(PLAYER)
+#error "This file requires SB_HAS(PLAYER)."
+#endif
+
+void SbPlayerWriteSample(SbPlayer /*player*/,
+                         SbMediaType /*sample_type*/,
+#if SB_API_VERSION >= 6
+                         const void* const* /*sample_buffers*/,
+                         const int* /*sample_buffer_sizes*/,
+#else   // SB_API_VERSION >= 6
+                         const void** /*sample_buffers*/,
+                         int* /*sample_buffer_sizes*/,
+#endif  // SB_API_VERSION >= 6
+                         int /*number_of_sample_buffers*/,
+                         SbMediaTime /*sample_pts*/,
+                         const SbMediaVideoSampleInfo* /*video_sample_info*/,
+                         const SbDrmSampleInfo* /*sample_drm_info*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbPlayer</code><br>        <code>player</code></td>
+    <td>The player to which the sample is written.</td>
+  </tr>
+  <tr>
+    <td><code>SbMediaType</code><br>        <code>sample_type</code></td>
+    <td>The type of sample being written. See the <code>SbMediaType</code>
+enum in media.h.</td>
+  </tr>
+  <tr>
+    <td><code>#if SB_API_VERSION >=</code><br>        <code>6</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>const void* const*</code><br>        <code>sample_buffers</code></td>
+    <td>A pointer to an array of buffers with
+<code>number_of_sample_buffers</code> elements that hold the data for this sample. The
+buffers are expected to be a portion of a bytestream of the codec type that
+the player was created with. The buffers should contain a sequence of whole
+NAL Units for video, or a complete audio frame.  <code>sample_buffers</code> cannot be
+assumed to live past the call into <code>SbPlayerWriteSample()</code>, so it must be
+copied if its content will be used after <code>SbPlayerWriteSample()</code> returns.</td>
+  </tr>
+  <tr>
+    <td><code>const int*</code><br>        <code>sample_buffer_sizes</code></td>
+    <td>A pointer to an array of sizes with
+<code>number_of_sample_buffers</code> elements.  Each of them specify the number of
+bytes in the corresponding buffer contained in <code>sample_buffers</code>.  None of
+them can be 0.  <code>sample_buffer_sizes</code> cannot be assumed to live past the
+call into <code>SbPlayerWriteSample()</code>, so it must be copied if its content will
+be used after <code>SbPlayerWriteSample()</code> returns.</td>
+  </tr>
+  <tr>
+    <td><code>#else   // SB_API_VERSION >=</code><br>        <code>6</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>const void**</code><br>        <code>sample_buffers</code></td>
+    <td>A pointer to an array of buffers with
+<code>number_of_sample_buffers</code> elements that hold the data for this sample. The
+buffers are expected to be a portion of a bytestream of the codec type that
+the player was created with. The buffers should contain a sequence of whole
+NAL Units for video, or a complete audio frame.  <code>sample_buffers</code> cannot be
+assumed to live past the call into <code>SbPlayerWriteSample()</code>, so it must be
+copied if its content will be used after <code>SbPlayerWriteSample()</code> returns.</td>
+  </tr>
+  <tr>
+    <td><code>int*</code><br>        <code>sample_buffer_sizes</code></td>
+    <td>A pointer to an array of sizes with
+<code>number_of_sample_buffers</code> elements.  Each of them specify the number of
+bytes in the corresponding buffer contained in <code>sample_buffers</code>.  None of
+them can be 0.  <code>sample_buffer_sizes</code> cannot be assumed to live past the
+call into <code>SbPlayerWriteSample()</code>, so it must be copied if its content will
+be used after <code>SbPlayerWriteSample()</code> returns.</td>
+  </tr>
+  <tr>
+    <td><code>#endif  // SB_API_VERSION >=</code><br>        <code>6</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>number_of_sample_buffers</code></td>
+    <td>Specify the number of elements contained inside
+<code>sample_buffers</code> and <code>sample_buffer_sizes</code>.  It has to be at least one, or
+the call will be ignored.</td>
+  </tr>
+  <tr>
+    <td><code>SbMediaTime</code><br>        <code>sample_pts</code></td>
+    <td>The timestamp of the sample in 90KHz ticks (PTS). Note that
+samples MAY be written "slightly" out of order.</td>
+  </tr>
+  <tr>
+    <td><code>const SbMediaVideoSampleInfo*</code><br>        <code>video_sample_info</code></td>
+    <td>Information about a video sample. This value is
+required if <code>sample_type</code> is <code>kSbMediaTypeVideo</code>. Otherwise, it must be
+<code>NULL</code>.</td>
+  </tr>
+  <tr>
+    <td><code>const SbDrmSampleInfo*</code><br>        <code>sample_drm_info</code></td>
+    <td>The DRM system for the media sample. This value is
+required for encrypted samples. Otherwise, it must be <code>NULL</code>.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/queue.md b/src/cobalt/site/docs/reference/starboard/modules/queue.md
new file mode 100644
index 0000000..65f659f
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/queue.md
@@ -0,0 +1,9 @@
+---
+layout: doc
+title: "Starboard Module Reference: queue.h"
+---
+
+Defines a C++-only synchronized queue implementation, built entirely on top
+of Starboard synchronization primitives. It can be safely used by both
+clients and implementations.
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/socket.md b/src/cobalt/site/docs/reference/starboard/modules/socket.md
new file mode 100644
index 0000000..8fd08bc
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/socket.md
@@ -0,0 +1,1759 @@
+---
+layout: doc
+title: "Starboard Module Reference: socket.h"
+---
+
+Defines Starboard socket I/O functions. Starboard supports IPv4 and IPv6,
+TCP and UDP, server and client sockets. Some platforms may not support IPv6,
+some may not support listening sockets, and some may not support any kind
+of sockets at all (or only allow them in debug builds).<br>
+Starboard ONLY supports non-blocking socket I/O, so all sockets are
+non-blocking at creation time.<br>
+Note that, on some platforms, API calls on one end of a socket connection
+may not be instantaneously aware of manipulations on the socket at the other
+end of the connection, thus requiring use of either an SbSocketWaiter or
+spin-polling.<br>
+TODO: For platforms that do not support sockets at all, they must
+support at least a high-level HTTP client API (to be defined later).
+
+## Enums
+
+### SbSocketAddressType
+
+All possible address types.
+
+**Values**
+
+*   `kSbSocketAddressTypeIpv4` - An IPv4 address, using only the first 4 entries of the address buffer.
+*   `kSbSocketAddressTypeIpv6` - An IPv6 address, which uses 16 entries of the address buffer.
+
+### SbSocketError
+
+Enumeration of all Starboard socket operation results. Despite the enum
+name, note that the value actually describes the outcome of an operation,
+which is not always an error.
+
+**Values**
+
+*   `kSbSocketOk` - The operation succeeded.
+*   `kSbSocketPending` - The operation is blocked on I/O. Either try again "later," or be veryclever and wait on it with a SbSocketWaiter.
+*   `kSbSocketErrorFailed` - The operation failed for some reason.<br>TODO: It's unclear if we actually care about why, so leaving the restof this enumeration blank until it becomes clear that we do.
+
+### SbSocketProtocol
+
+All possible IP socket types.
+
+**Values**
+
+*   `kSbSocketProtocolTcp` - The TCP/IP protocol, a reliable, stateful, streaming protocol.
+*   `kSbSocketProtocolUdp` - The UDP/IP protocol, an unreliable, connectionless, discrete packet(datagram) protocol.
+
+### SbSocketResolveFilter
+
+Bits that can be set when calling SbSocketResolve to filter the results.
+
+**Values**
+
+*   `kSbSocketResolveFilterNone` - No filters, include everything.
+*   `kSbSocketResolveFilterIpv4` - Include Ipv4 addresses.
+*   `kSbSocketResolveFilterIpv6` - Include Ipv6 addresses.
+
+## Structs
+
+### SbSocketAddress
+
+A representation of any possible supported address type.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>uint8_t</code><br>        <code>address[16]</code></td>    <td>The storage for the address. For IPv4, only the first 4 bytes make up the
+address. For IPv6, the entire buffer of 16 bytes is meaningful. An address
+of all zeros means that the address is unspecified.</td>  </tr>
+  <tr>
+    <td><code>SbSocketAddressType</code><br>        <code>type</code></td>    <td>The type of address this represents (IPv4 vs IPv6).</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>port</code></td>    <td>The port component of this socket address. If not specified, it will be
+zero, which is officially undefined.</td>  </tr>
+</table>
+
+### SbSocketPrivate
+
+Private structure representing a socket, which may or may not be connected or
+listening.
+
+### SbSocketResolution
+
+The result of a host name resolution.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>address_count</code></td>    <td>The length of the <code>addresses</code> array.</td>  </tr>
+</table>
+
+## Functions
+
+### SbSocketAccept
+
+**Description**
+
+Accepts a pending connection on `socket` and returns a new SbSocket
+representing that connection. This function sets the error on `socket`
+and returns `kSbSocketInvalid` if it is unable to accept a new connection.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketAccept-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketAccept-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketAccept-declaration">
+<pre>
+SB_EXPORT SbSocket SbSocketAccept(SbSocket socket);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketAccept-stub">
+
+```
+#include "starboard/socket.h"
+
+SbSocket SbSocketAccept(SbSocket /*socket*/) {
+  return kSbSocketInvalid;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket that is accepting a pending connection.</td>
+  </tr>
+</table>
+
+### SbSocketBind
+
+**Description**
+
+Binds `socket` to a specific local interface and port specified by
+`local_address`. This function sets and returns the socket error if it
+is unable to bind to `local_address`.<br></li></ul>
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketBind-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketBind-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketBind-declaration">
+<pre>
+SB_EXPORT SbSocketError SbSocketBind(SbSocket socket,
+                                     const SbSocketAddress* local_address);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketBind-stub">
+
+```
+#include "starboard/socket.h"
+
+SbSocketError SbSocketBind(SbSocket /*socket*/,
+                           const SbSocketAddress* /*local_address*/) {
+  return kSbSocketErrorFailed;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket to be bound to the local interface.</td>
+  </tr>
+  <tr>
+    <td><code>const SbSocketAddress*</code><br>        <code>local_address</code></td>
+    <td>The local address to which the socket is to be bound.
+This value must not be <code>NULL</code>.
+<ul><li>Setting the local address to port <code>0</code> (or not specifying a port) indicates
+that the function should choose a port for you.
+</li><li>Setting the IP address to <code>0.0.0.0</code> means that the socket should be bound
+to all interfaces.</td>
+  </tr>
+</table>
+
+### SbSocketClearLastError
+
+**Description**
+
+Clears the last error set on `socket`. The return value indicates whether
+the socket error was cleared.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketClearLastError-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketClearLastError-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketClearLastError-declaration">
+<pre>
+SB_EXPORT bool SbSocketClearLastError(SbSocket socket);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketClearLastError-stub">
+
+```
+#include "starboard/socket.h"
+
+bool SbSocketClearLastError(SbSocket /*socket*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>
+        <code>socket</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbSocketConnect
+
+**Description**
+
+Opens a connection of `socket`'s type to the host and port specified by
+`address`. This function sets and returns the socket error if it is unable
+to connect to `address`. (It returns `kSbSocketOk` if it creates the
+connection successfully.)
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketConnect-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketConnect-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketConnect-declaration">
+<pre>
+SB_EXPORT SbSocketError SbSocketConnect(SbSocket socket,
+                                        const SbSocketAddress* address);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketConnect-stub">
+
+```
+#include "starboard/socket.h"
+
+SbSocketError SbSocketConnect(SbSocket /*socket*/,
+                              const SbSocketAddress* /*address*/) {
+  return kSbSocketErrorFailed;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The type of connection that should be opened.</td>
+  </tr>
+  <tr>
+    <td><code>const SbSocketAddress*</code><br>        <code>address</code></td>
+    <td>The host and port to which the socket should connect.</td>
+  </tr>
+</table>
+
+### SbSocketCreate
+
+**Description**
+
+Creates a new non-blocking socket for protocol `protocol` using address
+family `address_type`.<br>
+<ul><li>If successful, this function returns the newly created handle.
+</li><li>If unsuccessful, this function returns `kSbSocketInvalid` and also sets
+the last system error appropriately.</li></ul>
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketCreate-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketCreate-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketCreate-declaration">
+<pre>
+SB_EXPORT SbSocket SbSocketCreate(SbSocketAddressType address_type,
+                                  SbSocketProtocol protocol);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketCreate-stub">
+
+```
+#include "starboard/socket.h"
+
+SbSocket SbSocketCreate(SbSocketAddressType /*address_type*/,
+                        SbSocketProtocol /*protocol*/) {
+  return kSbSocketInvalid;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocketAddressType</code><br>        <code>address_type</code></td>
+    <td>The type of IP address to use for the socket.</td>
+  </tr>
+  <tr>
+    <td><code>SbSocketProtocol</code><br>        <code>protocol</code></td>
+    <td>The protocol to use for the socket.</td>
+  </tr>
+</table>
+
+### SbSocketDestroy
+
+**Description**
+
+Destroys the `socket` by flushing it, closing any connection that may be
+active on it, and reclaiming any resources associated with it, including
+any registration with an `SbSocketWaiter`.<br>
+The return value indicates whether the destruction was successful. However,
+even if this function returns `false`, you should not be able to use the
+socket any more.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketDestroy-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketDestroy-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketDestroy-declaration">
+<pre>
+SB_EXPORT bool SbSocketDestroy(SbSocket socket);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketDestroy-stub">
+
+```
+#include "starboard/socket.h"
+
+bool SbSocketDestroy(SbSocket /*socket*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket to be destroyed.</td>
+  </tr>
+</table>
+
+### SbSocketFreeResolution
+
+**Description**
+
+Frees a resolution allocated by <code><a href="#sbsocketresolve">SbSocketResolve</a></code>.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketFreeResolution-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketFreeResolution-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketFreeResolution-declaration">
+<pre>
+SB_EXPORT void SbSocketFreeResolution(SbSocketResolution* resolution);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketFreeResolution-stub">
+
+```
+#include "starboard/socket.h"
+
+void SbSocketFreeResolution(SbSocketResolution* /*resolution*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocketResolution*</code><br>        <code>resolution</code></td>
+    <td>The resolution to be freed.</td>
+  </tr>
+</table>
+
+### SbSocketGetInterfaceAddress
+
+**Description**
+
+Gets the source address and the netmask that would be used to connect to the
+destination.  The netmask parameter is optional, and only populated if a
+non-NULL parameter is passed in.  To determine which source IP will be used,
+the kernel takes into account the protocol, routes, destination
+ip, etc.  The subnet mask, aka netmask, is used to find the routing prefix.
+In IPv6, this should be derived from the prefix value.<br>
+Returns whether it was possible to determine the source address and the
+netmask (if non-NULL value is passed) to be used to connect to the
+destination.  This function could fail if the destination is not reachable,
+if it an invalid address, etc.<br>
+If the destination address is 0.0.0.0, and its `type` is
+`kSbSocketAddressTypeIpv4`, then any IPv4 local interface that is up and not
+a loopback interface is a valid return value.<br>
+If the destination address is ::, and its `type` is
+`kSbSocketAddressTypeIpv6` then any IPv6 local interface that is up and not
+loopback or a link-local IP is a valid return value.  However, in the case of
+IPv6, the address with the biggest scope must be returned.  E.g., a globally
+scoped and routable IP is prefered over a unique local address (ULA).  Also,
+the IP address that is returned must be permanent.<br>
+If destination address is NULL, then any IP address that is valid for
+`destination` set to 0.0.0.0 (IPv4) or :: (IPv6) can be returned.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketGetInterfaceAddress-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketGetInterfaceAddress-stub" class="mdl-tabs__tab">stub</a>
+    <a href="#SbSocketGetInterfaceAddress-linux" class="mdl-tabs__tab">linux</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketGetInterfaceAddress-declaration">
+<pre>
+SB_EXPORT bool SbSocketGetInterfaceAddress(
+    const SbSocketAddress* const destination,
+    SbSocketAddress* out_source_address,
+    SbSocketAddress* out_netmask);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketGetInterfaceAddress-stub">
+
+```
+#include "starboard/socket.h"
+
+bool SbSocketGetInterfaceAddress(const SbSocketAddress* const /*destination*/,
+                                 SbSocketAddress* /*out_source_address*/,
+                                 SbSocketAddress* /*out_netmask*/) {
+  return false;
+}
+```
+
+  </div>
+  <div class="mdl-tabs__panel" id="SbSocketGetInterfaceAddress-linux">
+
+```
+#include "starboard/socket.h"
+
+// linux/if.h assumes the symbols for structs defined in ifaddrs.h are
+// already present. These includes must be above <linux/if.h> below.
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+
+#if SB_HAS_QUIRK(SOCKET_BSD_HEADERS)
+#include <errno.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#else
+#include <linux/if.h>
+#include <linux/if_addr.h>
+#include <netdb.h>
+#endif
+
+#include <netinet/in.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include "starboard/byte_swap.h"
+#include "starboard/log.h"
+#include "starboard/memory.h"
+#include "starboard/shared/posix/socket_internal.h"
+
+namespace sbposix = starboard::shared::posix;
+
+namespace {
+
+// TODO: Move this constant to socket.h.
+const int kIPv6AddressSize = 16;
+
+bool IsAnyAddress(const SbSocketAddress& address) {
+  switch (address.type) {
+    case kSbSocketAddressTypeIpv4:
+      return (address.address[0] == 0 && address.address[1] == 0 &&
+              address.address[2] == 0 && address.address[3] == 0);
+#if SB_HAS(IPV6)
+    case kSbSocketAddressTypeIpv6: {
+      bool found_nonzero = false;
+      for (std::size_t i = 0; i != kIPv6AddressSize; ++i) {
+        found_nonzero |= (address.address[i] != 0);
+      }
+      return !found_nonzero;
+    }
+#endif
+    default:
+      SB_NOTREACHED() << "Invalid address type " << address.type;
+      break;
+  }
+
+  return false;
+}
+
+template <typename T, int source_size>
+void CopyIntoObjectFromArray(T* out_destination,
+                             const unsigned char(&source)[source_size]) {
+  SB_COMPILE_ASSERT(sizeof(T) <= source_size, destination_is_too_small);
+  SbMemoryCopy(out_destination, source, sizeof(T));
+}
+
+bool GetPotentialMatch(const sockaddr* input_addr,
+                       const in_addr** out_interface_addr) {
+  if (!input_addr || input_addr->sa_family != AF_INET) {
+    *out_interface_addr = NULL;
+    return false;
+  }
+
+  const sockaddr_in* v4input_addr =
+      reinterpret_cast<const sockaddr_in*>(input_addr);
+  *out_interface_addr = &(v4input_addr->sin_addr);
+  return true;
+}
+
+bool GetPotentialMatch(const sockaddr* input_addr,
+                       const in6_addr** out_interface_addr) {
+  if (!input_addr || input_addr->sa_family != AF_INET6) {
+    *out_interface_addr = NULL;
+    return false;
+  }
+
+  const sockaddr_in6* v6input_addr =
+      reinterpret_cast<const sockaddr_in6*>(input_addr);
+  *out_interface_addr = &(v6input_addr->sin6_addr);
+  return true;
+}
+
+template <typename in_addr_type>
+bool GetNetmaskForInterfaceAddress(const SbSocketAddress& interface_address,
+                                   SbSocketAddress* out_netmask) {
+  SB_DCHECK((interface_address.type == kSbSocketAddressTypeIpv4) ||
+            (interface_address.type == kSbSocketAddressTypeIpv6));
+  struct ifaddrs* interface_addrs = NULL;
+
+  int retval = getifaddrs(&interface_addrs);
+  if (retval != 0) {
+    return false;
+  }
+
+  in_addr_type to_match;
+  CopyIntoObjectFromArray(&to_match, interface_address.address);
+
+  bool found_netmask = false;
+  for (struct ifaddrs* interface = interface_addrs; interface != NULL;
+       interface = interface->ifa_next) {
+    if (!(IFF_UP & interface->ifa_flags) ||
+        (IFF_LOOPBACK & interface->ifa_flags)) {
+      continue;
+    }
+
+    const in_addr_type* potential_match;
+    if (!GetPotentialMatch(interface->ifa_addr, &potential_match))
+      continue;
+
+    if (SbMemoryCompare(&to_match, potential_match, sizeof(in_addr_type)) !=
+        0) {
+      continue;
+    }
+
+    sbposix::SockAddr sock_addr;
+    sock_addr.FromSockaddr(interface->ifa_netmask);
+    if (sock_addr.ToSbSocketAddress(out_netmask)) {
+      found_netmask = true;
+      break;
+    }
+  }
+
+  freeifaddrs(interface_addrs);
+
+  return found_netmask;
+}
+
+bool GetNetMaskForInterfaceAddress(const SbSocketAddress& interface_address,
+                                   SbSocketAddress* out_netmask) {
+  SB_DCHECK(out_netmask);
+
+  switch (interface_address.type) {
+    case kSbSocketAddressTypeIpv4:
+      return GetNetmaskForInterfaceAddress<in_addr>(interface_address,
+                                                    out_netmask);
+#if SB_HAS(IPV6)
+    case kSbSocketAddressTypeIpv6:
+      return GetNetmaskForInterfaceAddress<in6_addr>(interface_address,
+                                                     out_netmask);
+#endif
+    default:
+      SB_NOTREACHED() << "Invalid address type " << interface_address.type;
+      break;
+  }
+
+  return false;
+}
+
+bool FindIPv4InterfaceIP(SbSocketAddress* out_interface_ip,
+                         SbSocketAddress* out_netmask) {
+  if (out_interface_ip == NULL) {
+    SB_NOTREACHED() << "out_interface_ip must be specified";
+    return false;
+  }
+  struct ifaddrs* interface_addrs = NULL;
+
+  int retval = getifaddrs(&interface_addrs);
+  if (retval != 0) {
+    return false;
+  }
+
+  bool success = false;
+  for (struct ifaddrs* interface = interface_addrs; interface != NULL;
+       interface = interface->ifa_next) {
+    if (!(IFF_UP & interface->ifa_flags) ||
+        (IFF_LOOPBACK & interface->ifa_flags)) {
+      continue;
+    }
+
+    const struct sockaddr* addr = interface->ifa_addr;
+    const struct sockaddr* netmask = interface->ifa_netmask;
+    if (!addr || !netmask || (addr->sa_family != AF_INET)) {
+      // IPv4 addresses only.
+      continue;
+    }
+
+    sbposix::SockAddr sock_addr;
+    sock_addr.FromSockaddr(addr);
+    if (sock_addr.ToSbSocketAddress(out_interface_ip)) {
+      if (out_netmask) {
+        sbposix::SockAddr netmask_addr;
+        netmask_addr.FromSockaddr(netmask);
+        if (!netmask_addr.ToSbSocketAddress(out_netmask)) {
+          continue;
+        }
+      }
+
+      success = true;
+      break;
+    }
+  }
+
+  freeifaddrs(interface_addrs);
+
+  return success;
+}
+
+#if SB_HAS(IPV6)
+bool IsUniqueLocalAddress(const unsigned char ip[16]) {
+  // Unique Local Addresses are in fd08::/8.
+  return ip[0] == 0xfd && ip[1] == 0x08;
+}
+
+bool FindIPv6InterfaceIP(SbSocketAddress* out_interface_ip,
+                         SbSocketAddress* out_netmask) {
+  if (!out_interface_ip) {
+    SB_NOTREACHED() << "out_interface_ip must be specified";
+    return false;
+  }
+  struct ifaddrs* interface_addrs = NULL;
+
+  int retval = getifaddrs(&interface_addrs);
+  if (retval != 0) {
+    return false;
+  }
+
+  int max_scope_interface_value = -1;
+
+  bool ip_found = false;
+  SbSocketAddress temp_interface_ip;
+  SbSocketAddress temp_netmask;
+
+  for (struct ifaddrs* interface = interface_addrs; interface != NULL;
+       interface = interface->ifa_next) {
+    if (!(IFF_UP & interface->ifa_flags) ||
+        (IFF_LOOPBACK & interface->ifa_flags)) {
+      continue;
+    }
+
+    const struct sockaddr* addr = interface->ifa_addr;
+    const struct sockaddr* netmask = interface->ifa_netmask;
+    if (!addr || !netmask || addr->sa_family != AF_INET6) {
+      // IPv6 addresses only.
+      continue;
+    }
+
+    const in6_addr* potential_match;
+    if (!GetPotentialMatch(interface->ifa_addr, &potential_match))
+      continue;
+
+    // Check the IP for loopback again, just in case flags were incorrect.
+    if (IN6_IS_ADDR_LOOPBACK(potential_match) ||
+        IN6_IS_ADDR_LINKLOCAL(potential_match)) {
+      continue;
+    }
+
+    const sockaddr_in6* v6addr =
+        reinterpret_cast<const sockaddr_in6*>(interface->ifa_addr);
+    if (!v6addr) {
+      continue;
+    }
+
+    int current_interface_scope = v6addr->sin6_scope_id;
+
+    if (IsUniqueLocalAddress(v6addr->sin6_addr.s6_addr)) {
+      // ULAs have global scope, but not globally routable.  So prefer
+      // non ULA addresses with global scope by adjusting their "scope"
+      current_interface_scope -= 1;
+    }
+
+    if (current_interface_scope <= max_scope_interface_value) {
+      continue;
+    }
+    max_scope_interface_value = current_interface_scope;
+
+    sbposix::SockAddr sock_addr;
+    sock_addr.FromSockaddr(addr);
+    if (sock_addr.ToSbSocketAddress(&temp_interface_ip)) {
+      if (netmask) {
+        sbposix::SockAddr netmask_addr;
+        netmask_addr.FromSockaddr(netmask);
+        if (!netmask_addr.ToSbSocketAddress(&temp_netmask)) {
+          continue;
+        }
+      }
+
+      ip_found = true;
+    }
+  }
+
+  freeifaddrs(interface_addrs);
+
+  if (!ip_found) {
+    return false;
+  }
+
+  SbMemoryCopy(out_interface_ip, &temp_interface_ip, sizeof(SbSocketAddress));
+  if (out_netmask != NULL) {
+    SbMemoryCopy(out_netmask, &temp_netmask, sizeof(SbSocketAddress));
+  }
+
+  return true;
+}
+#endif
+
+bool FindInterfaceIP(const SbSocketAddressType type,
+                     SbSocketAddress* out_interface_ip,
+                     SbSocketAddress* out_netmask) {
+  switch (type) {
+    case kSbSocketAddressTypeIpv4:
+      return FindIPv4InterfaceIP(out_interface_ip, out_netmask);
+#if SB_HAS(IPV6)
+    case kSbSocketAddressTypeIpv6:
+      return FindIPv6InterfaceIP(out_interface_ip, out_netmask);
+#endif
+    default:
+      SB_NOTREACHED() << "Invalid socket address type " << type;
+  }
+
+  return false;
+}
+
+bool FindSourceAddressForDestination(const SbSocketAddress& destination,
+                                     SbSocketAddress* out_source_address) {
+  SbSocket socket = SbSocketCreate(destination.type, kSbSocketProtocolUdp);
+  if (!SbSocketIsValid(socket)) {
+    return false;
+  }
+
+  SbSocketError connect_retval = SbSocketConnect(socket, &destination);
+  if (connect_retval != kSbSocketOk) {
+    bool socket_destroyed = SbSocketDestroy(socket);
+    SB_DCHECK(socket_destroyed);
+    return false;
+  }
+
+  bool success = SbSocketGetLocalAddress(socket, out_source_address);
+  bool socket_destroyed = SbSocketDestroy(socket);
+  SB_DCHECK(socket_destroyed);
+  return success;
+}
+
+}  // namespace
+
+bool SbSocketGetInterfaceAddress(const SbSocketAddress* const destination,
+                                 SbSocketAddress* out_source_address,
+                                 SbSocketAddress* out_netmask) {
+  if (!out_source_address) {
+    return false;
+  }
+
+  if (destination == NULL) {
+#if SB_HAS(IPV6)
+    // Return either a v4 or a v6 address.  Per spec.
+    return (FindIPv4InterfaceIP(out_source_address, out_netmask) ||
+            FindIPv6InterfaceIP(out_source_address, out_netmask));
+#else
+    return FindIPv4InterfaceIP(out_source_address, out_netmask);
+#endif
+
+  } else if (IsAnyAddress(*destination)) {
+    return FindInterfaceIP(destination->type, out_source_address, out_netmask);
+  } else {
+    return (FindSourceAddressForDestination(*destination, out_source_address) &&
+            GetNetMaskForInterfaceAddress(*out_source_address, out_netmask));
+  }
+
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const SbSocketAddress* const</code><br>        <code>destination</code></td>
+    <td>The destination IP to be connected to.  If IP addresses is not
+0.0.0.0 or ::, then temporary addresses may be returned.</td>
+  </tr>
+  <tr>
+    <td><code>SbSocketAddress*</code><br>        <code>out_source_address</code></td>
+    <td>This function places the address of the local interface
+in this output variable.</td>
+  </tr>
+  <tr>
+    <td><code>SbSocketAddress*</code><br>        <code>out_netmask</code></td>
+    <td>This parameter is optional.  If a non-NULL value is passed in,
+this function places the netmask associated with the source address in this
+output variable.</td>
+  </tr>
+</table>
+
+### SbSocketGetLastError
+
+**Description**
+
+Returns the last error set on `socket`. If `socket` is not valid, this
+function returns `kSbSocketErrorFailed`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketGetLastError-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketGetLastError-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketGetLastError-declaration">
+<pre>
+SB_EXPORT SbSocketError SbSocketGetLastError(SbSocket socket);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketGetLastError-stub">
+
+```
+#include "starboard/socket.h"
+
+SbSocketError SbSocketGetLastError(SbSocket /*socket*/) {
+  return kSbSocketErrorFailed;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket that the last error is returned for.</td>
+  </tr>
+</table>
+
+### SbSocketGetLocalAddress
+
+**Description**
+
+Gets the address that this socket is bound to locally, if the socket is
+connected. The return value indicates whether the address was retrieved
+successfully.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketGetLocalAddress-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketGetLocalAddress-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketGetLocalAddress-declaration">
+<pre>
+SB_EXPORT bool SbSocketGetLocalAddress(SbSocket socket,
+                                       SbSocketAddress* out_address);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketGetLocalAddress-stub">
+
+```
+#include "starboard/socket.h"
+
+bool SbSocketGetLocalAddress(SbSocket /*socket*/,
+                             SbSocketAddress* /*out_address*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket for which the local address is retrieved.</td>
+  </tr>
+  <tr>
+    <td><code>SbSocketAddress*</code><br>        <code>out_address</code></td>
+    <td>The SbSocket's local address.</td>
+  </tr>
+</table>
+
+### SbSocketIsConnected
+
+**Description**
+
+Indicates whether `socket` is connected to anything. Invalid sockets are not
+connected.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketIsConnected-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketIsConnected-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketIsConnected-declaration">
+<pre>
+SB_EXPORT bool SbSocketIsConnected(SbSocket socket);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketIsConnected-stub">
+
+```
+#include "starboard/socket.h"
+
+bool SbSocketIsConnected(SbSocket /*socket*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket to be checked.</td>
+  </tr>
+</table>
+
+### SbSocketIsConnectedAndIdle
+
+**Description**
+
+Returns whether `socket` is connected to anything, and, if so, whether it is
+receiving any data.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketIsConnectedAndIdle-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketIsConnectedAndIdle-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketIsConnectedAndIdle-declaration">
+<pre>
+SB_EXPORT bool SbSocketIsConnectedAndIdle(SbSocket socket);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketIsConnectedAndIdle-stub">
+
+```
+#include "starboard/socket.h"
+
+bool SbSocketIsConnectedAndIdle(SbSocket /*socket*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket to be checked.</td>
+  </tr>
+</table>
+
+### SbSocketIsValid
+
+**Description**
+
+Returns whether the given socket handle is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbSocketIsValid(SbSocket socket) {
+  return socket != kSbSocketInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>
+        <code>socket</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbSocketJoinMulticastGroup
+
+**Description**
+
+Joins `socket` to an IP multicast group identified by `address`. The
+equivalent of IP_ADD_MEMBERSHIP. The return value indicates whether the
+socket was joined to the group successfully.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketJoinMulticastGroup-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketJoinMulticastGroup-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketJoinMulticastGroup-declaration">
+<pre>
+SB_EXPORT bool SbSocketJoinMulticastGroup(SbSocket socket,
+                                          const SbSocketAddress* address);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketJoinMulticastGroup-stub">
+
+```
+#include "starboard/socket.h"
+
+bool SbSocketJoinMulticastGroup(SbSocket /*socket*/,
+                                const SbSocketAddress* /*address*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket to be joined to the IP multicast group.</td>
+  </tr>
+  <tr>
+    <td><code>const SbSocketAddress*</code><br>        <code>address</code></td>
+    <td>The location of the IP multicast group.</td>
+  </tr>
+</table>
+
+### SbSocketListen
+
+**Description**
+
+Causes `socket` to listen on the local address that `socket` was previously
+bound to by <code><a href="#sbsocketbind">SbSocketBind</a></code>. This function sets and returns the socket error if
+it is unable to listen for some reason. (It returns `kSbSocketOk` if it
+creates the connection successfully.)
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketListen-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketListen-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketListen-declaration">
+<pre>
+SB_EXPORT SbSocketError SbSocketListen(SbSocket socket);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketListen-stub">
+
+```
+#include "starboard/socket.h"
+
+SbSocketError SbSocketListen(SbSocket /*socket*/) {
+  return kSbSocketErrorFailed;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket on which the function operates.</td>
+  </tr>
+</table>
+
+### SbSocketReceiveFrom
+
+**Description**
+
+Reads up to `data_size` bytes from `socket` into `out_data` and places the
+source address of the packet in `out_source` if out_source is not NULL.
+Returns the number of bytes read, or a negative number if there is an error,
+in which case <code><a href="#sbsocketgetlasterror">SbSocketGetLastError</a></code> can provide the precise error encountered.<br>
+Note that this function is NOT specified to make a best effort to read all
+data on all platforms, but it MAY still do so. It is specified to read
+however many bytes are available conveniently, meaning that it should avoid
+blocking until there is data. It can be run in a loop until
+SbSocketGetLastError returns `kSbSocketPending` to make it a best-effort
+read (but still only up to not blocking, unless you want to spin).<br>
+The primary use of `out_source` is to receive datagram packets from
+multiple sources on a UDP server socket. TCP has two endpoints connected
+persistently, so the address is unnecessary, but allowed.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketReceiveFrom-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketReceiveFrom-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketReceiveFrom-declaration">
+<pre>
+SB_EXPORT int SbSocketReceiveFrom(SbSocket socket,
+                                  char* out_data,
+                                  int data_size,
+                                  SbSocketAddress* out_source);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketReceiveFrom-stub">
+
+```
+#include "starboard/socket.h"
+
+int SbSocketReceiveFrom(SbSocket /*socket*/,
+                        char* /*out_data*/,
+                        int /*data_size*/,
+                        SbSocketAddress* /*out_source*/) {
+  return -1;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket from which data is read.</td>
+  </tr>
+  <tr>
+    <td><code>char*</code><br>        <code>out_data</code></td>
+    <td>The data read from the socket.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>data_size</code></td>
+    <td>The number of bytes to read.</td>
+  </tr>
+  <tr>
+    <td><code>SbSocketAddress*</code><br>        <code>out_source</code></td>
+    <td>The source address of the packet.</td>
+  </tr>
+</table>
+
+### SbSocketResolve
+
+**Description**
+
+Synchronously resolves `hostname` into the returned SbSocketResolution,
+which must be freed with <code><a href="#sbsocketfreeresolution">SbSocketFreeResolution</a></code>. The function returns
+`NULL` if it is unable to resolve `hostname`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketResolve-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketResolve-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketResolve-declaration">
+<pre>
+SB_EXPORT SbSocketResolution* SbSocketResolve(const char* hostname,
+                                              int filters);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketResolve-stub">
+
+```
+#include "starboard/socket.h"
+
+SbSocketResolution* SbSocketResolve(const char* /*hostname*/, int /*filters*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>hostname</code></td>
+    <td>The hostname to be resolved.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>filters</code></td>
+    <td>A mask of <code>SbSocketResolve</code>Filter values used to filter the
+resolution. If <code>filters</code> does not specify an IP address family filter,
+all address families are included. However, if one IP address family filter
+is specified, only that address family is included. The function ignores
+unrecognized filter bits.</td>
+  </tr>
+</table>
+
+### SbSocketSendTo
+
+**Description**
+
+Writes up to `data_size` bytes of `data` to `destination` via
+`socket`. Returns the number of bytes written, or a negative number if
+there is an error, in which case `SbSocketGetLastError` can provide the
+precise error encountered.<br>
+Note that this function is NOT specified to make a best effort to write all
+data on all platforms, but it MAY still do so. It is specified to write
+however many bytes are available conveniently. It can be run in a loop
+until <code><a href="#sbsocketgetlasterror">SbSocketGetLastError</a></code> returns `kSbSocketPending` to make it a
+best-effort write (but still only up to not blocking, unless you want to
+spin).<br>
+The primary use of `destination` is to send datagram packets, which can
+go out to multiple sources from a single UDP server socket. TCP has two
+endpoints connected persistently, so setting `destination` when sending
+to a TCP socket will cause an error.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketSendTo-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketSendTo-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketSendTo-declaration">
+<pre>
+SB_EXPORT int SbSocketSendTo(SbSocket socket,
+                             const char* data,
+                             int data_size,
+                             const SbSocketAddress* destination);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketSendTo-stub">
+
+```
+#include "starboard/socket.h"
+
+int SbSocketSendTo(SbSocket /*socket*/,
+                   const char* /*data*/,
+                   int /*data_size*/,
+                   const SbSocketAddress* /*destination*/) {
+  return -1;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket to use to write data.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>data</code></td>
+    <td>The data read from the socket.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>data_size</code></td>
+    <td>The number of bytes of <code>data</code> to write.</td>
+  </tr>
+  <tr>
+    <td><code>const SbSocketAddress*</code><br>        <code>destination</code></td>
+    <td>The location to which data is written. This value must be
+<code>NULL</code> for TCP connections, which can only have a single endpoint.</td>
+  </tr>
+</table>
+
+### SbSocketSetBroadcast
+
+**Description**
+
+Sets the `SO_BROADCAST`, or equivalent, option to `value` on `socket`. The
+return value indicates whether the option was actually set.<br>
+This option is only meaningful for UDP sockets and allows the socket to
+send to the broadcast address.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketSetBroadcast-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketSetBroadcast-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketSetBroadcast-declaration">
+<pre>
+SB_EXPORT bool SbSocketSetBroadcast(SbSocket socket, bool value);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketSetBroadcast-stub">
+
+```
+#include "starboard/socket.h"
+
+bool SbSocketSetBroadcast(SbSocket /*socket*/, bool /*value*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket for which the option is set.</td>
+  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>value</code></td>
+    <td>The new value for the option.</td>
+  </tr>
+</table>
+
+### SbSocketSetReceiveBufferSize
+
+**Description**
+
+Sets the `SO_RCVBUF`, or equivalent, option to `size` on `socket`. The
+return value indicates whether the option was actually set.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketSetReceiveBufferSize-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketSetReceiveBufferSize-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketSetReceiveBufferSize-declaration">
+<pre>
+SB_EXPORT bool SbSocketSetReceiveBufferSize(SbSocket socket, int32_t size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketSetReceiveBufferSize-stub">
+
+```
+#include "starboard/socket.h"
+
+bool SbSocketSetReceiveBufferSize(SbSocket /*socket*/, int32_t /*size*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket for which the option is set.</td>
+  </tr>
+  <tr>
+    <td><code>int32_t</code><br>        <code>size</code></td>
+    <td>The value for the option.</td>
+  </tr>
+</table>
+
+### SbSocketSetReuseAddress
+
+**Description**
+
+Sets the `SO_REUSEADDR`, or equivalent, option to `value` on `socket`.
+The return value indicates whether the option was actually set.<br>
+This option allows a bound address to be reused if a socket isn't actively
+bound to it.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketSetReuseAddress-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketSetReuseAddress-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketSetReuseAddress-declaration">
+<pre>
+SB_EXPORT bool SbSocketSetReuseAddress(SbSocket socket, bool value);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketSetReuseAddress-stub">
+
+```
+#include "starboard/socket.h"
+
+bool SbSocketSetReuseAddress(SbSocket /*socket*/, bool /*value*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket for which the option is set.</td>
+  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>value</code></td>
+    <td>The new value for the option.</td>
+  </tr>
+</table>
+
+### SbSocketSetSendBufferSize
+
+**Description**
+
+Sets the `SO_SNDBUF`, or equivalent, option to `size` on `socket`. The
+return value indicates whether the option was actually set.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketSetSendBufferSize-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketSetSendBufferSize-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketSetSendBufferSize-declaration">
+<pre>
+SB_EXPORT bool SbSocketSetSendBufferSize(SbSocket socket, int32_t size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketSetSendBufferSize-stub">
+
+```
+#include "starboard/socket.h"
+
+bool SbSocketSetSendBufferSize(SbSocket /*socket*/, int32_t /*size*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket for which the option is set.</td>
+  </tr>
+  <tr>
+    <td><code>int32_t</code><br>        <code>size</code></td>
+    <td>The value for the option.</td>
+  </tr>
+</table>
+
+### SbSocketSetTcpKeepAlive
+
+**Description**
+
+Sets the `SO_KEEPALIVE`, or equivalent, option to `value` on `socket`. The
+return value indicates whether the option was actually set.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketSetTcpKeepAlive-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketSetTcpKeepAlive-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketSetTcpKeepAlive-declaration">
+<pre>
+SB_EXPORT bool SbSocketSetTcpKeepAlive(SbSocket socket,
+                                       bool value,
+                                       SbTime period);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketSetTcpKeepAlive-stub">
+
+```
+#include "starboard/socket.h"
+
+bool SbSocketSetTcpKeepAlive(SbSocket /*socket*/,
+                             bool /*value*/,
+                             SbTime /*period*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket for which the option is set.</td>
+  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>value</code></td>
+    <td>If set to <code>true</code>, then <code>period</code> specifies the minimum time
+(SbTime) is always in microseconds) between keep-alive packets. If
+set to <code>false</code>, <code>period</code> is ignored.</td>
+  </tr>
+  <tr>
+    <td><code>SbTime</code><br>        <code>period</code></td>
+    <td>The time between keep-alive packets. This value is only relevant
+if <code>value</code> is <code>true</code>.</td>
+  </tr>
+</table>
+
+### SbSocketSetTcpNoDelay
+
+**Description**
+
+Sets the `TCP_NODELAY`, or equivalent, option to `value` on `socket`. The
+return value indicates whether the option was actually set.<br>
+This function disables the Nagle algorithm for reducing the number of
+packets sent when converting from a stream to packets. Disabling Nagle
+generally puts the data for each Send call into its own packet, but does
+not guarantee that behavior.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketSetTcpNoDelay-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketSetTcpNoDelay-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketSetTcpNoDelay-declaration">
+<pre>
+SB_EXPORT bool SbSocketSetTcpNoDelay(SbSocket socket, bool value);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketSetTcpNoDelay-stub">
+
+```
+#include "starboard/socket.h"
+
+bool SbSocketSetTcpNoDelay(SbSocket /*socket*/, bool /*value*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket for which the option is set.</td>
+  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>value</code></td>
+    <td>Indicates whether the Nagle algorithm should be disabled
+(<code>value</code>=<code>true</code>).</td>
+  </tr>
+</table>
+
+### SbSocketSetTcpWindowScaling
+
+**Description**
+
+Sets the `SO_WINSCALE`, or equivalent, option to `value` on `socket`. The
+return value indicates whether the option was actually set.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketSetTcpWindowScaling-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketSetTcpWindowScaling-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketSetTcpWindowScaling-declaration">
+<pre>
+SB_EXPORT bool SbSocketSetTcpWindowScaling(SbSocket socket, bool value);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketSetTcpWindowScaling-stub">
+
+```
+#include "starboard/socket.h"
+
+bool SbSocketSetTcpWindowScaling(SbSocket /*socket*/, bool /*value*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket for which the option is set.</td>
+  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>value</code></td>
+    <td>The value for the option.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/socket_waiter.md b/src/cobalt/site/docs/reference/starboard/modules/socket_waiter.md
new file mode 100644
index 0000000..c9e95db
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/socket_waiter.md
@@ -0,0 +1,452 @@
+---
+layout: doc
+title: "Starboard Module Reference: socket_waiter.h"
+---
+
+Allows a thread to wait on many sockets at once. The standard
+usage pattern would be for a single I/O thread to:
+<ol><li>Create its own SbSocketWaiter.
+</li><li>Wait on the SbSocketWaiter, indefinitely if no scheduled tasks, or timed
+if there are scheduled future tasks.
+</li><li>While waiting, the SbSocketWaiter will call back to service ready
+SbSockets.
+</li><li>Wake up, if signaled to do so.
+</li><li>If ready to exit, go to 7.
+</li><li>Add and remove SbSockets to and from the SbSocketWaiter, and go to 2.
+</li><li>Destroy its SbSocketWaiter and exit.</li></ol>
+If another thread wants to queue immediate or schedule future work on the I/O
+thread, it needs to call SbSocketWaiterWakeUp() on the SbSocketWaiter after
+queuing the work item, or the SbSocketWaiter is not otherwise guaranteed to
+wake up.
+
+## Enums
+
+### SbSocketWaiterInterest
+
+All the interests that a socket may register for on a waiter.
+
+**Values**
+
+*   `kSbSocketWaiterInterestNone` - No interests whatsoever.
+*   `kSbSocketWaiterInterestRead` - An interest in or readiness to read from a socket without blocking.
+*   `kSbSocketWaiterInterestWrite` - An interest in or readiness to write to a socket without blocking.
+
+### SbSocketWaiterResult
+
+Possible reasons why a call to SbSocketWaiterWaitTimed returned.
+
+**Values**
+
+*   `kSbSocketWaiterResultInvalid` - The wait didn't block because the waiter was invalid.
+*   `kSbSocketWaiterResultTimedOut` - The wait stopped because the timeout expired.
+*   `kSbSocketWaiterResultWokenUp` - The wait stopped because a call to SbSocketWaiterWakeUp was consumed.
+
+## Structs
+
+### SbSocketWaiterPrivate
+
+Private structure representing a waiter that can wait for many sockets at
+once on a single thread.
+
+## Functions
+
+### SbSocketWaiterAdd
+
+**Description**
+
+Adds a new socket to be waited on by the `waiter` with a bitfield of
+`interests`. This function should only be called on the thread that
+waits on this waiter.<br>
+If `socket` is already registered with this or another waiter, the function
+does nothing and returns `false`. The client must remove the socket and then
+add it back with the new `interests`.<br>
+If `socket` is already ready for one or more of the operations set in the
+`interests` mask, then the callback will be called on the next call to
+either <code><a href="#sbsocketwaiterwait">SbSocketWaiterWait()</a></code> or <code><a href="#sbsocketwaiterwait">SbSocketWaiterWait</a></code>Timed().<br></li></ul>
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketWaiterAdd-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketWaiterAdd-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketWaiterAdd-declaration">
+<pre>
+SB_EXPORT bool SbSocketWaiterAdd(SbSocketWaiter waiter,
+                                 SbSocket socket,
+                                 void* context,
+                                 SbSocketWaiterCallback callback,
+                                 int interests,
+                                 bool persistent);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketWaiterAdd-stub">
+
+```
+#include "starboard/socket_waiter.h"
+
+bool SbSocketWaiterAdd(SbSocketWaiter /*waiter*/,
+                       SbSocket /*socket*/,
+                       void* /*context*/,
+                       SbSocketWaiterCallback /*callback*/,
+                       int /*interests*/,
+                       bool /*persistent*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocketWaiter</code><br>        <code>waiter</code></td>
+    <td>An SbSocketWaiter that waits on the socket for the specified set
+of operations (<code>interests</code>).</td>
+  </tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The SbSocket on which the waiter waits.</td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>        <code>context</code></td>
+    <td></td>
+  </tr>
+  <tr>
+    <td><code>SbSocketWaiterCallback</code><br>        <code>callback</code></td>
+    <td>The function that is called when the event fires. The <code>waiter</code>,
+<code>socket</code>, <code>context</code> are all passed to the callback, along with a bitfield
+of <code>interests</code> that the socket is actually ready for.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>interests</code></td>
+    <td>A bitfield that identifies operations for which the socket is
+waiting.</td>
+  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>persistent</code></td>
+    <td>Identifies the procedure that will be followed for removing
+the socket:
+<ul><li>If <code>persistent</code> is <code>true</code>, then <code>socket</code> stays registered with <code>waiter</code>
+until <code><a href="#sbsocketwaiterremove">SbSocketWaiterRemove()</a></code> is called with <code>waiter</code> and <code>socket</code>.
+</li><li>If <code>persistent</code> is <code>false</code>, then <code>socket</code> is removed after the next call
+to <code>callback</code>, even if not all registered <code>interests</code> became ready.</td>
+  </tr>
+</table>
+
+### SbSocketWaiterCreate
+
+**Description**
+
+The results of two threads waiting on the same waiter is undefined and will
+not work. Except for the <code><a href="#sbsocketwaiterwakeup">SbSocketWaiterWakeUp()</a></code> function, SbSocketWaiters
+are not thread-safe and don't expect to be modified concurrently.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketWaiterCreate-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketWaiterCreate-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketWaiterCreate-declaration">
+<pre>
+SB_EXPORT SbSocketWaiter SbSocketWaiterCreate();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketWaiterCreate-stub">
+
+```
+#include "starboard/socket_waiter.h"
+
+SbSocketWaiter SbSocketWaiterCreate() {
+  return kSbSocketWaiterInvalid;
+}
+```
+
+  </div>
+</div>
+
+### SbSocketWaiterDestroy
+
+**Description**
+
+Destroys `waiter` and removes all sockets still registered by way of
+SbSocketWaiterAdd. This function may be called on any thread as long as
+there is no risk of concurrent access to the waiter.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketWaiterDestroy-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketWaiterDestroy-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketWaiterDestroy-declaration">
+<pre>
+SB_EXPORT bool SbSocketWaiterDestroy(SbSocketWaiter waiter);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketWaiterDestroy-stub">
+
+```
+#include "starboard/socket_waiter.h"
+
+bool SbSocketWaiterDestroy(SbSocketWaiter /*waiter*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocketWaiter</code><br>        <code>waiter</code></td>
+    <td>The SbSocketWaiter to be destroyed.</td>
+  </tr>
+</table>
+
+### SbSocketWaiterIsValid
+
+**Description**
+
+Returns whether the given socket handle is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbSocketWaiterIsValid(SbSocketWaiter watcher) {
+  return watcher != kSbSocketWaiterInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocketWaiter</code><br>
+        <code>watcher</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbSocketWaiterRemove
+
+**Description**
+
+Removes a socket, previously added with <code><a href="#sbsocketwaiteradd">SbSocketWaiterAdd()</a></code>, from a waiter.
+This function should only be called on the thread that waits on this waiter.<br>
+The return value indicates whether the waiter still waits on the socket.
+If `socket` wasn't registered with `waiter`, then the function is a no-op
+and returns `true`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketWaiterRemove-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketWaiterRemove-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketWaiterRemove-declaration">
+<pre>
+SB_EXPORT bool SbSocketWaiterRemove(SbSocketWaiter waiter, SbSocket socket);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketWaiterRemove-stub">
+
+```
+#include "starboard/socket_waiter.h"
+
+bool SbSocketWaiterRemove(SbSocketWaiter /*waiter*/, SbSocket /*socket*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocketWaiter</code><br>        <code>waiter</code></td>
+    <td>The waiter from which the socket is removed.</td>
+  </tr>
+  <tr>
+    <td><code>SbSocket</code><br>        <code>socket</code></td>
+    <td>The socket to remove from the waiter.</td>
+  </tr>
+</table>
+
+### SbSocketWaiterWait
+
+**Description**
+
+Waits on all registered sockets, calling the registered callbacks if and when
+the corresponding sockets become ready for an interested operation. This
+version exits only after <code><a href="#sbsocketwaiterwakeup">SbSocketWaiterWakeUp()</a></code> is called. This function
+should only be called on the thread that waits on this waiter.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketWaiterWait-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketWaiterWait-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketWaiterWait-declaration">
+<pre>
+SB_EXPORT void SbSocketWaiterWait(SbSocketWaiter waiter);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketWaiterWait-stub">
+
+```
+#include "starboard/socket_waiter.h"
+
+void SbSocketWaiterWait(SbSocketWaiter /*waiter*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocketWaiter</code><br>
+        <code>waiter</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbSocketWaiterWaitTimed
+
+**Description**
+
+Behaves similarly to <code><a href="#sbsocketwaiterwait">SbSocketWaiterWait()</a></code>, but this function also causes
+`waiter` to exit on its own after at least `duration` has passed if
+SbSocketWaiterWakeUp() it not called by that time.<br>
+The return value indicates the reason that the socket waiter exited.
+This function should only be called on the thread that waits on this waiter.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketWaiterWaitTimed-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketWaiterWaitTimed-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketWaiterWaitTimed-declaration">
+<pre>
+SB_EXPORT SbSocketWaiterResult SbSocketWaiterWaitTimed(SbSocketWaiter waiter,
+                                                       SbTime duration);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketWaiterWaitTimed-stub">
+
+```
+#include "starboard/socket_waiter.h"
+
+SbSocketWaiterResult SbSocketWaiterWaitTimed(SbSocketWaiter /*waiter*/,
+                                             SbTime /*duration*/) {
+  return kSbSocketWaiterResultInvalid;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocketWaiter</code><br>        <code>waiter</code></td>
+    <td> </td>  </tr>
+  <tr>
+    <td><code>SbTime</code><br>        <code>duration</code></td>
+    <td>The minimum amount of time after which the socket waiter should
+exit if it is not woken up before then. As with SbThreadSleep() (see
+thread.h), this function may wait longer than <code>duration</code>, such as if the
+timeout expires while a callback is being fired.</td>
+  </tr>
+</table>
+
+### SbSocketWaiterWakeUp
+
+**Description**
+
+Wakes up `waiter` once. This is the only thread-safe waiter function.
+It can can be called from a SbSocketWaiterCallback to wake up its own waiter,
+and it can also be called from another thread at any time. In either case,
+the waiter will exit the next wait gracefully, first completing any
+in-progress callback.<br>
+Each time this function is called, it causes the waiter to wake up once,
+regardless of whether the waiter is currently waiting. If the waiter is not
+waiting, the function takes effect immediately the next time the waiter
+waits. The number of wake-ups accumulates, and the queue is only consumed
+as the waiter waits and then is subsequently woken up again. For example,
+if you call this function 7 times, then <code><a href="#sbsocketwaiterwait">SbSocketWaiterWait()</a></code> and WaitTimed()
+will not block the next 7 times they are called.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSocketWaiterWakeUp-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSocketWaiterWakeUp-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSocketWaiterWakeUp-declaration">
+<pre>
+SB_EXPORT void SbSocketWaiterWakeUp(SbSocketWaiter waiter);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSocketWaiterWakeUp-stub">
+
+```
+#include "starboard/socket_waiter.h"
+
+void SbSocketWaiterWakeUp(SbSocketWaiter /*waiter*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSocketWaiter</code><br>        <code>waiter</code></td>
+    <td>The socket waiter to be woken up.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/speech_recognizer.md b/src/cobalt/site/docs/reference/starboard/modules/speech_recognizer.md
new file mode 100644
index 0000000..7caba11
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/speech_recognizer.md
@@ -0,0 +1,373 @@
+---
+layout: doc
+title: "Starboard Module Reference: speech_recognizer.h"
+---
+
+Defines a streaming speech recognizer API. It provides access to the platform
+speech recognition service.<br>
+Note that there can be only one speech recognizer. Attempting to create a
+second speech recognizer without destroying the first one will result in
+undefined behavior.<br>
+|SbSpeechRecognizerCreate|, |SbSpeechRecognizerStart|,
+|SbSpeechRecognizerStop|, |SbSpeechRecognizerCancel| and
+|SbSpeechRecognizerDestroy| should be called from a single thread. Callbacks
+defined in |SbSpeechRecognizerHandler| will happen on another thread, so
+calls back into the SbSpeechRecognizer from the callback thread are
+disallowed.
+
+## Enums
+
+### SbSpeechRecognizerError
+
+Indicates what has gone wrong with the recognition.
+
+**Values**
+
+*   `kSbNoSpeechError` - No speech was detected. Speech timed out.
+*   `kSbAborted` - Speech input was aborted somehow.
+*   `kSbAudioCaptureError` - Audio capture failed.
+*   `kSbNetworkError` - Some network communication that was required to complete the recognitionfailed.
+*   `kSbNotAllowed` - The implementation is not allowing any speech input to occur for reasons ofsecurity, privacy or user preference.
+*   `kSbServiceNotAllowed` - The implementation is not allowing the application requested speechservice, but would allow some speech service, to be used either because theimplementation doesn't support the selected one or because of reasons ofsecurity, privacy or user preference.
+*   `kSbBadGrammar` - There was an error in the speech recognition grammar or semantic tags, orthe grammar format or semantic tag format is supported.
+*   `kSbLanguageNotSupported` - The language was not supported.
+
+## Structs
+
+### SbSpeechConfiguration
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>bool</code><br>        <code>continuous</code></td>    <td>When the continuous value is set to false, the implementation MUST
+return no more than one final result in response to starting recognition.
+When the continuous attribute is set to true, the implementation MUST
+return zero or more final results representing multiple consecutive
+recognitions in response to starting recognition. This attribute setting
+does not affect interim results.</td>  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>interim_results</code></td>    <td>Controls whether interim results are returned. When set to true, interim
+results SHOULD be returned. When set to false, interim results MUST NOT be
+returned. This value setting does not affect final results.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>max_alternatives</code></td>    <td>This sets the maximum number of SbSpeechResult in
+<code>SbSpeechRecognizerOnResults</code> callback.</td>  </tr>
+</table>
+
+### SbSpeechRecognizer
+
+An opaque handle to an implementation-private structure that represents a
+speech recognizer.
+
+### SbSpeechResult
+
+The recognition response that is received from the recognizer.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>float</code><br>        <code>confidence</code></td>    <td>The raw words that the user spoke.
+A numeric estimate between 0 and 1 of how confident the recognition system
+is that the recognition is correct. A higher number means the system is
+more confident. NaN represents an unavailable confidence score.</td>  </tr>
+</table>
+
+## Functions
+
+### SbSpeechRecognizerCancel
+
+**Description**
+
+Cancels speech recognition. The speech recognizer stops listening to
+audio and does not return any information. When `SbSpeechRecognizerCancel` is
+called, the implementation MUST NOT collect additional audio, MUST NOT
+continue to listen to the user, and MUST stop recognizing. This is important
+for privacy reasons. If `SbSpeechRecognizerCancel` is called on a speech
+recognizer which is already stopped or cancelled, the implementation MUST
+ignore the call.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSpeechRecognizerCancel-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSpeechRecognizerCancel-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSpeechRecognizerCancel-declaration">
+<pre>
+SB_EXPORT void SbSpeechRecognizerCancel(SbSpeechRecognizer recognizer);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSpeechRecognizerCancel-stub">
+
+```
+#include "starboard/speech_recognizer.h"
+
+#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+
+void SbSpeechRecognizerCancel(SbSpeechRecognizer /*recognizer*/) {}
+
+#endif  // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSpeechRecognizer</code><br>
+        <code>recognizer</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbSpeechRecognizerCreate
+
+**Description**
+
+Creates a speech recognizer with a speech recognizer handler.<br>
+If the system has a speech recognition service available, this function
+returns the newly created handle.<br>
+If no speech recognition service is available on the device, this function
+returns `kSbSpeechRecognizerInvalid`.<br>
+`SbSpeechRecognizerCreate` does not expect the passed
+SbSpeechRecognizerHandler structure to live after `SbSpeechRecognizerCreate`
+is called, so the implementation must copy the contents if necessary.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSpeechRecognizerCreate-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSpeechRecognizerCreate-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSpeechRecognizerCreate-declaration">
+<pre>
+SB_EXPORT SbSpeechRecognizer
+SbSpeechRecognizerCreate(const SbSpeechRecognizerHandler* handler);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSpeechRecognizerCreate-stub">
+
+```
+#include "starboard/speech_recognizer.h"
+
+#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+
+SbSpeechRecognizer SbSpeechRecognizerCreate(
+    const SbSpeechRecognizerHandler* /*handler*/) {
+  return kSbSpeechRecognizerInvalid;
+}
+
+#endif  // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const SbSpeechRecognizerHandler*</code><br>        <code>handler</code></td>
+    <td> </td>  </tr>
+</table>
+
+### SbSpeechRecognizerDestroy
+
+**Description**
+
+Destroys the given speech recognizer. If the speech recognizer is in the
+started state, it is first stopped and then destroyed.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSpeechRecognizerDestroy-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSpeechRecognizerDestroy-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSpeechRecognizerDestroy-declaration">
+<pre>
+SB_EXPORT void SbSpeechRecognizerDestroy(SbSpeechRecognizer recognizer);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSpeechRecognizerDestroy-stub">
+
+```
+#include "starboard/speech_recognizer.h"
+
+#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+
+void SbSpeechRecognizerDestroy(SbSpeechRecognizer /*recognizer*/) {}
+
+#endif  // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSpeechRecognizer</code><br>
+        <code>recognizer</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbSpeechRecognizerIsValid
+
+**Description**
+
+Indicates whether the given speech recognizer is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbSpeechRecognizerIsValid(
+    SbSpeechRecognizer recognizer) {
+  return recognizer != kSbSpeechRecognizerInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSpeechRecognizer</code><br>
+        <code>recognizer</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbSpeechRecognizerStart
+
+**Description**
+
+Starts listening to audio and recognizing speech with the specified speech
+configuration. If `SbSpeechRecognizerStart` is called on an already
+started speech recognizer, the implementation MUST ignore the call and return
+false.<br>
+Returns whether the speech recognizer is started successfully.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSpeechRecognizerStart-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSpeechRecognizerStart-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSpeechRecognizerStart-declaration">
+<pre>
+SB_EXPORT bool SbSpeechRecognizerStart(
+    SbSpeechRecognizer recognizer,
+    const SbSpeechConfiguration* configuration);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSpeechRecognizerStart-stub">
+
+```
+#include "starboard/speech_recognizer.h"
+
+#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+
+bool SbSpeechRecognizerStart(SbSpeechRecognizer /*recognizer*/,
+                             const SbSpeechConfiguration* /*configuration*/) {
+  return false;
+}
+
+#endif  // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSpeechRecognizer</code><br>
+        <code>recognizer</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>const SbSpeechConfiguration*</code><br>
+        <code>configuration</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbSpeechRecognizerStop
+
+**Description**
+
+Stops listening to audio and returns a result using just the audio that it
+has already received. Once `SbSpeechRecognizerStop` is called, the
+implementation MUST NOT collect additional audio and MUST NOT continue to
+listen to the user. This is important for privacy reasons. If
+`SbSpeechRecognizerStop` is called on a speech recognizer which is already
+stopped or being stopped, the implementation MUST ignore the call.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSpeechRecognizerStop-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSpeechRecognizerStop-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSpeechRecognizerStop-declaration">
+<pre>
+SB_EXPORT void SbSpeechRecognizerStop(SbSpeechRecognizer recognizer);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSpeechRecognizerStop-stub">
+
+```
+#include "starboard/speech_recognizer.h"
+
+#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+
+void SbSpeechRecognizerStop(SbSpeechRecognizer /*recognizer*/) {}
+
+#endif  // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSpeechRecognizer</code><br>
+        <code>recognizer</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/speech_synthesis.md b/src/cobalt/site/docs/reference/starboard/modules/speech_synthesis.md
new file mode 100644
index 0000000..e89a7fd
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/speech_synthesis.md
@@ -0,0 +1,101 @@
+---
+layout: doc
+title: "Starboard Module Reference: speech_synthesis.h"
+---
+
+A basic text-to-speech API intended to be used for audio accessibilty.<br>
+Implementations of this API should audibly play back text to assist
+users in non-visual navigation of the application.<br>
+Note that these functions do not have to be thread-safe. They must
+only be called from a single application thread.
+
+## Functions
+
+### SbSpeechSynthesisCancel
+
+**Description**
+
+Cancels all speaking and queued speech synthesis audio. Must
+return immediately.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSpeechSynthesisCancel-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSpeechSynthesisCancel-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSpeechSynthesisCancel-declaration">
+<pre>
+SB_EXPORT void SbSpeechSynthesisCancel();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSpeechSynthesisCancel-stub">
+
+```
+#include "starboard/speech_synthesis.h"
+
+#if !SB_HAS(SPEECH_SYNTHESIS)
+#error If speech synthesis not enabled on this platform, please exclude it\
+       from the build
+#endif
+
+void SbSpeechSynthesisCancel() {}
+```
+
+  </div>
+</div>
+
+### SbSpeechSynthesisSpeak
+
+**Description**
+
+Enqueues `text`, a UTF-8 string, to be spoken.
+Returns immediately.<br>
+Spoken language for the text should be the same as the locale returned
+by SbSystemGetLocaleId().<br>
+If audio from previous <code>SbSpeechSynthesisSpeak()</code> invocations is still
+processing, the current speaking should continue and this new
+text should be queued to play when the previous utterances are complete.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSpeechSynthesisSpeak-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSpeechSynthesisSpeak-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSpeechSynthesisSpeak-declaration">
+<pre>
+SB_EXPORT void SbSpeechSynthesisSpeak(const char* text);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSpeechSynthesisSpeak-stub">
+
+```
+#include "starboard/speech_synthesis.h"
+
+#if !SB_HAS(SPEECH_SYNTHESIS)
+#error If speech synthesis not enabled on this platform, please exclude it\
+       from the build
+#endif
+
+void SbSpeechSynthesisSpeak(const char* text) {}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>
+        <code>text</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/spin_lock.md b/src/cobalt/site/docs/reference/starboard/modules/spin_lock.md
new file mode 100644
index 0000000..5cfe60a
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/spin_lock.md
@@ -0,0 +1,9 @@
+---
+layout: doc
+title: "Starboard Module Reference: spin_lock.h"
+---
+
+Defines a C++-only spin-lock implementation, built entirely on top of
+Starboard atomics and threads. It can be safely used by both clients and
+implementations.
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/storage.md b/src/cobalt/site/docs/reference/starboard/modules/storage.md
new file mode 100644
index 0000000..ae32a9f
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/storage.md
@@ -0,0 +1,384 @@
+---
+layout: doc
+title: "Starboard Module Reference: storage.h"
+---
+
+Defines a user-based Storage API. This is a simple, all-at-once BLOB storage
+and retrieval API that is intended for robust long-term, per-user storage.
+Some platforms have different mechanisms for this kind of storage, so this
+API exists to allow a client application to access this kind of storage.<br>
+Note that there can be only one storage record per user and, thus, a maximum
+of one open storage record can exist for each user. Attempting to open a
+second record for a user will result in undefined behavior.<br>
+These APIs are NOT expected to be thread-safe, so either call them from a
+single thread, or perform proper synchronization around all calls.
+
+## Structs
+
+### SbStorageRecordPrivate
+
+Private structure representing a single storage record.
+
+## Functions
+
+### SbStorageCloseRecord
+
+**Description**
+
+Closes `record`, synchronously ensuring that all written data is flushed.
+This function performs blocking I/O on the calling thread.<br>
+The return value indicates whether the operation succeeded. Storage writes
+should be as atomic as possible, so the record should either be fully
+written or deleted (or, even better, untouched).
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStorageCloseRecord-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStorageCloseRecord-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStorageCloseRecord-declaration">
+<pre>
+SB_EXPORT bool SbStorageCloseRecord(SbStorageRecord record);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStorageCloseRecord-stub">
+
+```
+#include "starboard/storage.h"
+
+bool SbStorageCloseRecord(SbStorageRecord /*record*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbStorageRecord</code><br>        <code>record</code></td>
+    <td>The storage record to close. <code>record</code> is invalid after this point,
+and subsequent calls referring to <code>record</code> will fail.</td>
+  </tr>
+</table>
+
+### SbStorageDeleteRecord
+
+**Description**
+
+Deletes the `SbStorageRecord` for `user` named `name`. The return value
+indicates whether the record existed and was successfully deleted. If the
+record did not exist or could not be deleted, the function returns `false`.<br>
+If `name` is NULL, deletes the default storage record for the user, like what
+would have been deleted with the previous version of <code>SbStorageDeleteRecord</code>.<br>
+This function must not be called while the user's storage record is open.
+This function performs blocking I/O on the calling thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStorageDeleteRecord-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStorageDeleteRecord-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStorageDeleteRecord-declaration">
+<pre>
+SB_EXPORT bool SbStorageDeleteRecord(SbUser user, const char* name);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStorageDeleteRecord-stub">
+
+```
+#include "starboard/storage.h"
+
+bool SbStorageDeleteRecord(SbUser /*user*/
+#if SB_API_VERSION >= 6
+                           ,
+                           const char* /*name*/
+#endif  // SB_API_VERSION >= 6
+                           ) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbUser</code><br>        <code>user</code></td>
+    <td>The user for whom the record will be deleted.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>name</code></td>
+    <td>The filesystem-safe name of the record to open.</td>
+  </tr>
+</table>
+
+### SbStorageGetRecordSize
+
+**Description**
+
+Returns the size of `record`, or `-1` if there is an error. This function
+performs blocking I/O on the calling thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStorageGetRecordSize-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStorageGetRecordSize-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStorageGetRecordSize-declaration">
+<pre>
+SB_EXPORT int64_t SbStorageGetRecordSize(SbStorageRecord record);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStorageGetRecordSize-stub">
+
+```
+#include "starboard/storage.h"
+
+int64_t SbStorageGetRecordSize(SbStorageRecord /*record*/) {
+  return -1;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbStorageRecord</code><br>        <code>record</code></td>
+    <td>The record to retrieve the size of.</td>
+  </tr>
+</table>
+
+### SbStorageIsValidRecord
+
+**Description**
+
+Returns whether the given storage record handle is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbStorageIsValidRecord(SbStorageRecord record) {
+  return record != kSbStorageInvalidRecord;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbStorageRecord</code><br>
+        <code>record</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbStorageOpenRecord
+
+**Description**
+
+Opens and returns the SbStorageRecord for `user` named `name`, blocking I/O
+on the calling thread until the open is completed. If `user` is not a valid
+`SbUser`, the function returns `kSbStorageInvalidRecord`. Will return an
+`SbStorageRecord` of size zero if the record does not yet exist. Opening an
+already-open `SbStorageRecord` has undefined behavior.<br>
+If `name` is NULL, opens the default storage record for the user, like what
+would have been saved with the previous version of <code>SbStorageOpenRecord</code>.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStorageOpenRecord-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStorageOpenRecord-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStorageOpenRecord-declaration">
+<pre>
+SB_EXPORT SbStorageRecord SbStorageOpenRecord(SbUser user, const char* name);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStorageOpenRecord-stub">
+
+```
+#include "starboard/storage.h"
+
+SbStorageRecord SbStorageOpenRecord(SbUser /*user*/
+#if SB_API_VERSION >= 6
+                                    ,
+                                    const char* /*name*/
+#endif  // SB_API_VERSION >= 6
+                                    ) {
+  return kSbStorageInvalidRecord;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbUser</code><br>        <code>user</code></td>
+    <td>The user for which the storage record will be opened.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>name</code></td>
+    <td>The filesystem-safe name of the record to open.</td>
+  </tr>
+</table>
+
+### SbStorageReadRecord
+
+**Description**
+
+Reads up to `data_size` bytes from `record`, starting at the beginning of
+the record. The function returns the actual number of bytes read, which
+must be <= `data_size`. The function returns `-1` in the event of an error.
+This function makes a best-effort to read the entire record, and it performs
+blocking I/O on the calling thread until the entire record is read or an
+error is encountered.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStorageReadRecord-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStorageReadRecord-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStorageReadRecord-declaration">
+<pre>
+SB_EXPORT int64_t SbStorageReadRecord(SbStorageRecord record,
+                                      char* out_data,
+                                      int64_t data_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStorageReadRecord-stub">
+
+```
+#include "starboard/storage.h"
+
+int64_t SbStorageReadRecord(SbStorageRecord /*record*/,
+                            char* /*out_data*/,
+                            int64_t /*data_size*/) {
+  return -1;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbStorageRecord</code><br>        <code>record</code></td>
+    <td>The record to be read.</td>
+  </tr>
+  <tr>
+    <td><code>char*</code><br>        <code>out_data</code></td>
+    <td>The data read from the record.</td>
+  </tr>
+  <tr>
+    <td><code>int64_t</code><br>        <code>data_size</code></td>
+    <td>The amount of data, in bytes, to read.</td>
+  </tr>
+</table>
+
+### SbStorageWriteRecord
+
+**Description**
+
+Replaces the data in `record` with `data_size` bytes from `data`. This
+function always deletes any previous data in that record. The return value
+indicates whether the write succeeded. This function makes a best-effort to
+write the entire record, and it may perform blocking I/O on the calling
+thread until the entire record is written or an error is encountered.<br>
+While `SbStorageWriteRecord()` may defer the persistence,
+`SbStorageReadRecord()` is expected to work as expected immediately
+afterwards, even without a call to `SbStorageCloseRecord()`. The data should
+be persisted after a short time, even if there is an unexpected process
+termination before `SbStorageCloseRecord()` is called.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStorageWriteRecord-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStorageWriteRecord-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStorageWriteRecord-declaration">
+<pre>
+SB_EXPORT bool SbStorageWriteRecord(SbStorageRecord record,
+                                    const char* data,
+                                    int64_t data_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStorageWriteRecord-stub">
+
+```
+#include "starboard/storage.h"
+
+bool SbStorageWriteRecord(SbStorageRecord /*record*/,
+                          const char* /*data*/,
+                          int64_t /*data_size*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbStorageRecord</code><br>        <code>record</code></td>
+    <td>The record to be written to.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>data</code></td>
+    <td>The data to write to the record.</td>
+  </tr>
+  <tr>
+    <td><code>int64_t</code><br>        <code>data_size</code></td>
+    <td>The amount of <code>data</code>, in bytes, to write to the record. Thus,
+if <code>data_size</code> is smaller than the total size of <code>data</code>, only part of
+<code>data</code> is written to the record.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/string.md b/src/cobalt/site/docs/reference/starboard/modules/string.md
new file mode 100644
index 0000000..6003269
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/string.md
@@ -0,0 +1,1497 @@
+---
+layout: doc
+title: "Starboard Module Reference: string.h"
+---
+
+Defines functions for interacting with c-style strings.
+
+## Functions
+
+### SbStringAToI
+
+**Description**
+
+Parses a string into a base-10 integer. This is a shorthand replacement for
+`atoi`.
+
+**Declaration**
+
+```
+static SB_C_INLINE int SbStringAToI(const char* value) {
+  // NOLINTNEXTLINE(readability/casting)
+  return (int)SbStringParseSignedInteger(value, NULL, 10);
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>value</code></td>
+    <td>The string to be converted.</td>
+  </tr>
+</table>
+
+### SbStringAToL
+
+**Description**
+
+Parses a string into a base-10, long integer. This is a shorthand
+replacement for `atol`.
+
+**Declaration**
+
+```
+static SB_C_INLINE long SbStringAToL(const char* value) {
+  // NOLINTNEXTLINE(readability/casting)
+  return SbStringParseSignedInteger(value, NULL, 10);
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>value</code></td>
+    <td>The string to be converted.
+NOLINTNEXTLINE(runtime/int)</td>
+  </tr>
+</table>
+
+### SbStringCompare
+
+**Description**
+
+Compares the first `count` characters of two 8-bit character strings.
+The return value is:
+<ul><li>`< 0` if `string1` is ASCII-betically lower than `string2`.
+</li><li>`0` if the two strings are equal.
+</li><li>`> 0` if `string1` is ASCII-betically higher than `string2`.</li></ul>
+This function is meant to be a drop-in replacement for `strncmp`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringCompare-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringCompare-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringCompare-declaration">
+<pre>
+SB_EXPORT int SbStringCompare(const char* string1,
+                              const char* string2,
+                              size_t count);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringCompare-stub">
+
+```
+#include "starboard/string.h"
+
+int SbStringCompare(const char* /*string1*/,
+                    const char* /*string2*/,
+                    size_t /*count*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>string1</code></td>
+    <td>The first 8-bit character string to compare.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>string2</code></td>
+    <td>The second 8-bit character string to compare.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of characters to compare.</td>
+  </tr>
+</table>
+
+### SbStringCompareAll
+
+**Description**
+
+Compares two entire 8-bit character strings. The return value is:
+<ul><li>`< 0` if `string1` is ASCII-betically lower than `string2`.
+</li><li>`0` if the two strings are equal.
+</li><li>`> 0` if `string1` is ASCII-betically higher than `string2`.</li></ul>
+This function is meant to be a drop-in replacement for `strcmp`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringCompareAll-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringCompareAll-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringCompareAll-declaration">
+<pre>
+SB_EXPORT int SbStringCompareAll(const char* string1, const char* string2);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringCompareAll-stub">
+
+```
+#include "starboard/string.h"
+
+int SbStringCompareAll(const char* /*string1*/, const char* /*string2*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>string1</code></td>
+    <td>The first 8-bit character string to compare.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>string2</code></td>
+    <td>The second 8-bit character string to compare.</td>
+  </tr>
+</table>
+
+### SbStringCompareNoCase
+
+**Description**
+
+Compares two strings, ignoring differences in case. The return value is:
+<ul><li>`< 0` if `string1` is ASCII-betically lower than `string2`.
+</li><li>`0` if the two strings are equal.
+</li><li>`> 0` if `string1` is ASCII-betically higher than `string2`.</li></ul>
+This function is meant to be a drop-in replacement for `strcasecmp`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringCompareNoCase-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringCompareNoCase-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringCompareNoCase-declaration">
+<pre>
+SB_EXPORT int SbStringCompareNoCase(const char* string1, const char* string2);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringCompareNoCase-stub">
+
+```
+#include "starboard/string.h"
+
+int SbStringCompareNoCase(const char* /*string1*/, const char* /*string2*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>string1</code></td>
+    <td>The first string to compare.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>string2</code></td>
+    <td>The second string to compare.</td>
+  </tr>
+</table>
+
+### SbStringCompareNoCaseN
+
+**Description**
+
+Compares the first `count` characters of two strings, ignoring differences
+in case. The return value is:
+<ul><li>`< 0` if `string1` is ASCII-betically lower than `string2`.
+</li><li>`0` if the two strings are equal.
+</li><li>`> 0` if `string1` is ASCII-betically higher than `string2`.</li></ul>
+This function is meant to be a drop-in replacement for `strncasecmp`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringCompareNoCaseN-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringCompareNoCaseN-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringCompareNoCaseN-declaration">
+<pre>
+SB_EXPORT int SbStringCompareNoCaseN(const char* string1,
+                                     const char* string2,
+                                     size_t count);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringCompareNoCaseN-stub">
+
+```
+#include "starboard/string.h"
+
+int SbStringCompareNoCaseN(const char* /*string1*/,
+                           const char* /*string2*/,
+                           size_t /*count*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>string1</code></td>
+    <td>The first string to compare.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>string2</code></td>
+    <td>The second string to compare.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of characters to compare.</td>
+  </tr>
+</table>
+
+### SbStringCompareWide
+
+**Description**
+
+Compares the first `count` characters of two 16-bit character strings.
+The return value is:
+<ul><li>`< 0` if `string1` is ASCII-betically lower than `string2`.
+</li><li>`0` if the two strings are equal.
+</li><li>`> 0` if `string1` is ASCII-betically higher than `string2`.</li></ul>
+This function is meant to be a drop-in replacement for `wcsncmp`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringCompareWide-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringCompareWide-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringCompareWide-declaration">
+<pre>
+SB_EXPORT int SbStringCompareWide(const wchar_t* string1,
+                                  const wchar_t* string2,
+                                  size_t count);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringCompareWide-stub">
+
+```
+#include "starboard/string.h"
+
+int SbStringCompareWide(const wchar_t* /*string1*/,
+                        const wchar_t* /*string2*/,
+                        size_t /*count*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const wchar_t*</code><br>        <code>string1</code></td>
+    <td>The first 16-bit character string to compare.weird</td>
+  </tr>
+  <tr>
+    <td><code>const wchar_t*</code><br>        <code>string2</code></td>
+    <td>The second 16-bit character string to compare.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>count</code></td>
+    <td>The number of characters to compare.</td>
+  </tr>
+</table>
+
+### SbStringConcat
+
+**Description**
+
+Appends `source` to `out_destination` as long as `out_destination` has
+enough storage space to hold the concatenated string.<br>
+This function is meant to be a drop-in replacement for `strlcat`. Also note
+that this function's signature is NOT compatible with `strncat`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringConcat-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringConcat-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringConcat-declaration">
+<pre>
+SB_EXPORT int SbStringConcat(char* out_destination,
+                             const char* source,
+                             int destination_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringConcat-stub">
+
+```
+#include "starboard/string.h"
+
+int SbStringConcat(char* /*out_destination*/,
+                   const char* /*source*/,
+                   int /*destination_size*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>char*</code><br>        <code>out_destination</code></td>
+    <td>The string to which the <code>source</code> string is appended.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>source</code></td>
+    <td>The string to be appended to the destination string.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>destination_size</code></td>
+    <td>The amount of storage space available for the
+concatenated string.</td>
+  </tr>
+</table>
+
+### SbStringConcatUnsafe
+
+**Description**
+
+An inline wrapper for an unsafe <code><a href="#sbstringconcat">SbStringConcat</a></code> that assumes that the
+`out_destination` provides enough storage space for the concatenated string.
+Note that this function's signature is NOT compatible with `strcat`.
+
+**Declaration**
+
+```
+static SB_C_INLINE int SbStringConcatUnsafe(char* out_destination,
+                                            const char* source) {
+  return SbStringConcat(out_destination, source, INT_MAX);
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>char*</code><br>        <code>out_destination</code></td>
+    <td>The string to which the <code>source</code> string is appended.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>source</code></td>
+    <td>The string to be appended to the destination string.</td>
+  </tr>
+</table>
+
+### SbStringConcatWide
+
+**Description**
+
+Identical to SbStringCat, but for wide characters.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringConcatWide-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringConcatWide-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringConcatWide-declaration">
+<pre>
+SB_EXPORT int SbStringConcatWide(wchar_t* out_destination,
+                                 const wchar_t* source,
+                                 int destination_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringConcatWide-stub">
+
+```
+#include "starboard/string.h"
+
+int SbStringConcatWide(wchar_t* /*out_destination*/,
+                       const wchar_t* /*source*/,
+                       int /*destination_size*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>wchar_t*</code><br>        <code>out_destination</code></td>
+    <td>The string to which the <code>source</code> string is appended.</td>
+  </tr>
+  <tr>
+    <td><code>const wchar_t*</code><br>        <code>source</code></td>
+    <td>The string to be appended to the destination string.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>destination_size</code></td>
+    <td>The amount of storage space available for the
+concatenated string.</td>
+  </tr>
+</table>
+
+### SbStringCopy
+
+**Description**
+
+Copies as much of a `source` string as possible and null-terminates it,
+given that `destination_size` characters of storage are available. This
+function is meant to be a drop-in replacement for `strlcpy`.<br>
+The return value specifies the length of `source`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringCopy-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringCopy-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringCopy-declaration">
+<pre>
+SB_EXPORT int SbStringCopy(char* out_destination,
+                           const char* source,
+                           int destination_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringCopy-stub">
+
+```
+#include "starboard/string.h"
+
+int SbStringCopy(char* /*out_destination*/,
+                 const char* /*source*/,
+                 int /*destination_size*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>char*</code><br>        <code>out_destination</code></td>
+    <td>The location to which the string is copied.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>source</code></td>
+    <td>The string to be copied.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>destination_size</code></td>
+    <td>The amount of the source string to copy.</td>
+  </tr>
+</table>
+
+### SbStringCopyUnsafe
+
+**Description**
+
+An inline wrapper for an unsafe <code><a href="#sbstringcopy">SbStringCopy</a></code> that assumes that the
+destination provides enough storage space for the entire string. The return
+value is a pointer to the destination string. This function is meant to be
+a drop-in replacement for `strcpy`.
+
+**Declaration**
+
+```
+static SB_C_INLINE char* SbStringCopyUnsafe(char* out_destination,
+                                            const char* source) {
+  SbStringCopy(out_destination, source, INT_MAX);
+  return out_destination;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>char*</code><br>        <code>out_destination</code></td>
+    <td>The location to which the string is copied.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>source</code></td>
+    <td>The string to be copied.</td>
+  </tr>
+</table>
+
+### SbStringCopyWide
+
+**Description**
+
+Identical to <code><a href="#sbstringcopy">SbStringCopy</a></code>, but for wide characters.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringCopyWide-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringCopyWide-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringCopyWide-declaration">
+<pre>
+SB_EXPORT int SbStringCopyWide(wchar_t* out_destination,
+                               const wchar_t* source,
+                               int destination_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringCopyWide-stub">
+
+```
+#include "starboard/string.h"
+
+int SbStringCopyWide(wchar_t* /*out_destination*/,
+                     const wchar_t* /*source*/,
+                     int /*destination_size*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>wchar_t*</code><br>        <code>out_destination</code></td>
+    <td>The location to which the string is copied.</td>
+  </tr>
+  <tr>
+    <td><code>const wchar_t*</code><br>        <code>source</code></td>
+    <td>The string to be copied.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>destination_size</code></td>
+    <td>The amount of the source string to copy.</td>
+  </tr>
+</table>
+
+### SbStringDuplicate
+
+**Description**
+
+Copies `source` into a buffer that is allocated by this function and that
+can be freed with SbMemoryDeallocate. This function is meant to be a drop-in
+replacement for `strdup`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringDuplicate-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringDuplicate-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringDuplicate-declaration">
+<pre>
+SB_EXPORT char* SbStringDuplicate(const char* source);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringDuplicate-stub">
+
+```
+#include "starboard/string.h"
+
+char* SbStringDuplicate(const char* /*source*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>source</code></td>
+    <td>The string to be copied.</td>
+  </tr>
+</table>
+
+### SbStringFindCharacter
+
+**Description**
+
+Finds the first occurrence of a `character` in `str`. The return value is a
+pointer to the found character in the given string or `NULL` if the
+character is not found. Note that this function's signature does NOT match
+that of the `strchr` function.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringFindCharacter-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringFindCharacter-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringFindCharacter-declaration">
+<pre>
+SB_EXPORT const char* SbStringFindCharacter(const char* str, char character);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringFindCharacter-stub">
+
+```
+#include "starboard/string.h"
+
+const char* SbStringFindCharacter(const char* /*str*/, char /*character*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>str</code></td>
+    <td>The string to search for the character.</td>
+  </tr>
+  <tr>
+    <td><code>char</code><br>        <code>character</code></td>
+    <td>The character to find in the string.</td>
+  </tr>
+</table>
+
+### SbStringFindLastCharacter
+
+**Description**
+
+Finds the last occurrence of a specified character in a string.
+The return value is a pointer to the found character in the given string or
+`NULL` if the character is not found. Note that this function's signature
+does NOT match that of the `strrchr` function.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringFindLastCharacter-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringFindLastCharacter-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringFindLastCharacter-declaration">
+<pre>
+SB_EXPORT const char* SbStringFindLastCharacter(const char* str,
+                                                char character);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringFindLastCharacter-stub">
+
+```
+#include "starboard/string.h"
+
+const char* SbStringFindLastCharacter(const char* /*str*/, char /*character*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>str</code></td>
+    <td>The string to search for the character.</td>
+  </tr>
+  <tr>
+    <td><code>char</code><br>        <code>character</code></td>
+    <td>The character to find in the string.</td>
+  </tr>
+</table>
+
+### SbStringFindString
+
+**Description**
+
+Finds the first occurrence of `str2` in `str1`. The return value is a
+pointer to the beginning of the found string or `NULL` if the string is
+not found. This function is meant to be a drop-in replacement for `strstr`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringFindString-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringFindString-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringFindString-declaration">
+<pre>
+SB_EXPORT const char* SbStringFindString(const char* str1, const char* str2);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringFindString-stub">
+
+```
+#include "starboard/string.h"
+
+const char* SbStringFindString(const char* /*str1*/, const char* /*str2*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>str1</code></td>
+    <td>The string in which to search for the presence of <code>str2</code>.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>str2</code></td>
+    <td>The string to locate in <code>str1</code>.</td>
+  </tr>
+</table>
+
+### SbStringFormat
+
+**Description**
+
+Produces a string formatted with `format` and `arguments`, placing as much
+of the result that will fit into `out_buffer`. The return value specifies
+the number of characters that the format would produce if `buffer_size` were
+infinite.<br>
+This function is meant to be a drop-in replacement for `vsnprintf`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringFormat-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringFormat-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringFormat-declaration">
+<pre>
+SB_EXPORT int SbStringFormat(char* out_buffer,
+                             size_t buffer_size,
+                             const char* format,
+                             va_list arguments) SB_PRINTF_FORMAT(3, 0);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringFormat-stub">
+
+```
+#include "starboard/string.h"
+
+int SbStringFormat(char* /*out_buffer*/,
+                   size_t /*buffer_size*/,
+                   const char* /*format*/,
+                   va_list /*arguments*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>char*</code><br>        <code>out_buffer</code></td>
+    <td>The location where the formatted string is stored.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>buffer_size</code></td>
+    <td>The size of <code>out_buffer</code>.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>format</code></td>
+    <td>A string that specifies how the data should be formatted.</td>
+  </tr>
+  <tr>
+    <td><code>va_list</code><br>        <code>arguments</code></td>
+    <td>Variable arguments used in the string.</td>
+  </tr>
+</table>
+
+### SbStringFormatF
+
+**Declaration**
+
+```
+static SB_C_INLINE int SbStringFormatF(char* out_buffer,
+                                       size_t buffer_size,
+                                       const char* format,
+                                       ...) {
+  va_list arguments;
+  va_start(arguments, format);
+  int result = SbStringFormat(out_buffer, buffer_size, format, arguments);
+  va_end(arguments);
+  return result;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>char*</code><br>
+        <code>out_buffer</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>
+        <code>buffer_size</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>
+        <code>format</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code></code><br>
+        <code>...</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbStringFormatUnsafeF
+
+**Declaration**
+
+```
+static SB_C_INLINE int SbStringFormatUnsafeF(char* out_buffer,
+                                             const char* format,
+                                             ...) {
+  va_list arguments;
+  va_start(arguments, format);
+  int result = SbStringFormat(out_buffer, UINT_MAX, format, arguments);
+  va_end(arguments);
+  return result;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>char*</code><br>
+        <code>out_buffer</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>
+        <code>format</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code></code><br>
+        <code>...</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbStringFormatWide
+
+**Description**
+
+This function is identical to <code><a href="#sbstringformat">SbStringFormat</a></code>, but is for wide characters.
+It is meant to be a drop-in replacement for `vswprintf`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringFormatWide-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringFormatWide-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringFormatWide-declaration">
+<pre>
+SB_EXPORT int SbStringFormatWide(wchar_t* out_buffer,
+                                 size_t buffer_size,
+                                 const wchar_t* format,
+                                 va_list arguments);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringFormatWide-stub">
+
+```
+#include "starboard/string.h"
+
+int SbStringFormatWide(wchar_t* /*out_buffer*/,
+                       size_t /*buffer_size*/,
+                       const wchar_t* /*format*/,
+                       va_list /*arguments*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>wchar_t*</code><br>        <code>out_buffer</code></td>
+    <td>The location where the formatted string is stored.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>buffer_size</code></td>
+    <td>The size of <code>out_buffer</code>.</td>
+  </tr>
+  <tr>
+    <td><code>const wchar_t*</code><br>        <code>format</code></td>
+    <td>A string that specifies how the data should be formatted.</td>
+  </tr>
+  <tr>
+    <td><code>va_list</code><br>        <code>arguments</code></td>
+    <td>Variable arguments used in the string.</td>
+  </tr>
+</table>
+
+### SbStringFormatWideF
+
+**Description**
+
+An inline wrapper of <code><a href="#sbstringformat">SbStringFormat</a></code>Wide that converts from ellipsis to
+`va_args`.
+
+**Declaration**
+
+```
+static SB_C_INLINE int SbStringFormatWideF(wchar_t* out_buffer,
+                                           size_t buffer_size,
+                                           const wchar_t* format,
+                                           ...) {
+  va_list arguments;
+  va_start(arguments, format);
+  int result = SbStringFormatWide(out_buffer, buffer_size, format, arguments);
+  va_end(arguments);
+  return result;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>wchar_t*</code><br>        <code>out_buffer</code></td>
+    <td>The location where the formatted string is stored.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>buffer_size</code></td>
+    <td>The size of <code>out_buffer</code>.</td>
+  </tr>
+  <tr>
+    <td><code>const wchar_t*</code><br>        <code>format</code></td>
+    <td>A string that specifies how the data should be formatted.</td>
+  </tr>
+  <tr>
+    <td><code></code><br>        <code>...</code></td>
+    <td>Arguments used in the string.</td>
+  </tr>
+</table>
+
+### SbStringGetLength
+
+**Description**
+
+Returns the length, in characters, of `str`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringGetLength-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringGetLength-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringGetLength-declaration">
+<pre>
+SB_EXPORT size_t SbStringGetLength(const char* str);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringGetLength-stub">
+
+```
+#include "starboard/string.h"
+
+size_t SbStringGetLength(const char* /*str*/) {
+  return static_cast<size_t>(0);
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>str</code></td>
+    <td>A zero-terminated ASCII string.</td>
+  </tr>
+</table>
+
+### SbStringGetLengthWide
+
+**Description**
+
+Returns the length of a wide character string. (This function is the same
+as <code><a href="#sbstringgetlength">SbStringGetLength</a></code>, but for a string comprised of wide characters.) This
+function assumes that there are no multi-element characters.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringGetLengthWide-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringGetLengthWide-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringGetLengthWide-declaration">
+<pre>
+SB_EXPORT size_t SbStringGetLengthWide(const wchar_t* str);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringGetLengthWide-stub">
+
+```
+#include "starboard/string.h"
+
+size_t SbStringGetLengthWide(const wchar_t* /*str*/) {
+  return static_cast<size_t>(0);
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const wchar_t*</code><br>        <code>str</code></td>
+    <td>A zero-terminated ASCII string.</td>
+  </tr>
+</table>
+
+### SbStringParseDouble
+
+**Description**
+
+Extracts a string that represents an integer from the beginning of `start`
+into a double.<br>
+This function is meant to be a drop-in replacement for `strtod`, except
+that it is explicitly declared to return a double.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringParseDouble-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringParseDouble-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringParseDouble-declaration">
+<pre>
+SB_EXPORT double SbStringParseDouble(const char* start, char** out_end);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringParseDouble-stub">
+
+```
+#include "starboard/string.h"
+
+double SbStringParseDouble(const char* start, char** out_end) {
+  if (out_end != NULL)
+    *out_end = NULL;
+  return 0.0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>start</code></td>
+    <td>The string that begins with the number to be converted.</td>
+  </tr>
+  <tr>
+    <td><code>char**</code><br>        <code>out_end</code></td>
+    <td>If provided, the function places a pointer to the end of the
+consumed portion of the string into <code>out_end</code>.</td>
+  </tr>
+</table>
+
+### SbStringParseSignedInteger
+
+**Description**
+
+Extracts a string that represents an integer from the beginning of `start`
+into a signed integer in the given `base`. This function is meant to be a
+drop-in replacement for `strtol`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringParseSignedInteger-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringParseSignedInteger-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringParseSignedInteger-declaration">
+<pre>
+SB_EXPORT long SbStringParseSignedInteger(const char* start,
+                                          char** out_end,
+                                          int base);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringParseSignedInteger-stub">
+
+```
+#include "starboard/string.h"
+
+// NOLINTNEXTLINE(runtime/int)
+long SbStringParseSignedInteger(const char* /*start*/,
+                                char** /*out_end*/,
+                                int /*base*/) {
+  return 0L;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>start</code></td>
+    <td>The string that begins with the number to be converted.</td>
+  </tr>
+  <tr>
+    <td><code>char**</code><br>        <code>out_end</code></td>
+    <td>If provided, the function places a pointer to the end of the
+consumed portion of the string into <code>out_end</code>.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>base</code></td>
+    <td>The base into which the number will be converted. The value must
+be between <code>2</code> and <code>36</code>, inclusive.
+NOLINTNEXTLINE(runtime/int)</td>
+  </tr>
+</table>
+
+### SbStringParseUInt64
+
+**Description**
+
+Extracts a string that represents an integer from the beginning of `start`
+into an unsigned 64-bit integer in the given `base`.<br>
+This function is meant to be a drop-in replacement for `strtoull`, except
+that it is explicitly declared to return `uint64_t`.
+
+**Declaration**
+
+```
+SB_EXPORT uint64_t SbStringParseUInt64(const char* start,
+                                       char** out_end,
+                                       int base);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>start</code></td>
+    <td>The string that begins with the number to be converted.</td>
+  </tr>
+  <tr>
+    <td><code>char**</code><br>        <code>out_end</code></td>
+    <td>If provided, the function places a pointer to the end of the
+consumed portion of the string into <code>out_end</code>.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>base</code></td>
+    <td>The base into which the number will be converted. The value must
+be between <code>2</code> and <code>36</code>, inclusive.</td>
+  </tr>
+</table>
+
+### SbStringParseUnsignedInteger
+
+**Description**
+
+Extracts a string that represents an integer from the beginning of `start`
+into an unsigned integer in the given `base`.
+This function is meant to be a drop-in replacement for `strtoul`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringParseUnsignedInteger-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringParseUnsignedInteger-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringParseUnsignedInteger-declaration">
+<pre>
+SB_EXPORT unsigned long SbStringParseUnsignedInteger(const char* start,
+                                                     char** out_end,
+                                                     int base);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringParseUnsignedInteger-stub">
+
+```
+#include "starboard/string.h"
+
+// NOLINTNEXTLINE(runtime/int)
+unsigned long SbStringParseUnsignedInteger(const char* /*start*/,
+                                           char** /*out_end*/,
+                                           int /*base*/) {
+  return 0UL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>start</code></td>
+    <td>The string that begins with the number to be converted.</td>
+  </tr>
+  <tr>
+    <td><code>char**</code><br>        <code>out_end</code></td>
+    <td>If provided, the function places a pointer to the end of the
+consumed portion of the string into <code>out_end</code>.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>base</code></td>
+    <td>The base into which the number will be converted. The value must
+be between <code>2</code> and <code>36</code>, inclusive.
+NOLINTNEXTLINE(runtime/int)</td>
+  </tr>
+</table>
+
+### SbStringScan
+
+**Description**
+
+Scans `buffer` for `pattern`, placing the extracted values in `arguments`.
+The return value specifies the number of successfully matched items, which
+may be `0`.<br>
+This function is meant to be a drop-in replacement for `vsscanf`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbStringScan-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbStringScan-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbStringScan-declaration">
+<pre>
+SB_EXPORT int SbStringScan(const char* buffer,
+                           const char* pattern,
+                           va_list arguments);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbStringScan-stub">
+
+```
+#include "starboard/string.h"
+
+int SbStringScan(const char* /*buffer*/,
+                 const char* /*pattern*/,
+                 va_list /*arguments*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>buffer</code></td>
+    <td>The string to scan for the pattern.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>pattern</code></td>
+    <td>The string to search for in <code>buffer</code>.</td>
+  </tr>
+  <tr>
+    <td><code>va_list</code><br>        <code>arguments</code></td>
+    <td>Values matching <code>pattern</code> that were extracted from <code>buffer</code>.</td>
+  </tr>
+</table>
+
+### SbStringScanF
+
+**Description**
+
+An inline wrapper of <code><a href="#sbstringscan">SbStringScan</a></code> that converts from ellipsis to `va_args`.
+This function is meant to be a drop-in replacement for `sscanf`.
+
+**Declaration**
+
+```
+static SB_C_INLINE int SbStringScanF(const char* buffer,
+                                     const char* pattern,
+                                     ...) {
+  va_list arguments;
+  va_start(arguments, pattern);
+  int result = SbStringScan(buffer, pattern, arguments);
+  va_end(arguments);
+  return result;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>buffer</code></td>
+    <td>The string to scan for the pattern.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>pattern</code></td>
+    <td>The string to search for in <code>buffer</code>.</td>
+  </tr>
+  <tr>
+    <td><code></code><br>        <code>...</code></td>
+    <td>Values matching <code>pattern</code> that were extracted from <code>buffer</code>.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/system.md b/src/cobalt/site/docs/reference/starboard/modules/system.md
new file mode 100644
index 0000000..d21bbf0
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/system.md
@@ -0,0 +1,1726 @@
+---
+layout: doc
+title: "Starboard Module Reference: system.h"
+---
+
+Defines a broad set of APIs that allow the client application to query
+build and runtime properties of the enclosing system.
+
+## Enums
+
+### SbSystemCapabilityId
+
+Runtime capabilities are boolean properties of a platform that can't be
+determined at compile-time. They may vary from device to device, but they
+will not change over the course of a single execution. They often specify
+particular behavior of other APIs within the bounds of their operating range.
+
+**Values**
+
+*   `kSbSystemCapabilityReversedEnterAndBack` - Whether this system has reversed Enter and Back keys.
+*   `kSbSystemCapabilityCanQueryGPUMemoryStats` - Whether this system has the ability to report on GPU memory usage.If (and only if) a system has this capcability willSbSystemGetTotalGPUMemory() and SbSystemGetUsedGPUMemory() be valid tocall.
+
+### SbSystemConnectionType
+
+Enumeration of network connection types.
+
+**Values**
+
+*   `kSbSystemConnectionTypeWired` - The system is on a wired connection.
+*   `kSbSystemConnectionTypeWireless` - The system is on a wireless connection.
+*   `kSbSystemConnectionTypeUnknown` - The system connection type is unknown.
+
+### SbSystemDeviceType
+
+Enumeration of device types.
+
+**Values**
+
+*   `kSbSystemDeviceTypeBlueRayDiskPlayer` - Blue-ray Disc Player (BDP).
+*   `kSbSystemDeviceTypeGameConsole` - A relatively high-powered TV device used primarily for playing games.
+*   `kSbSystemDeviceTypeOverTheTopBox` - Over the top (OTT) devices stream content via the Internet over anothertype of network, e.g. cable or satellite.
+*   `kSbSystemDeviceTypeSetTopBox` - Set top boxes (STBs) stream content primarily over cable or satellite.Some STBs can also stream OTT content via the Internet.
+*   `kSbSystemDeviceTypeTV` - A Smart TV is a TV that can directly run applications that stream OTTcontent via the Internet.
+*   `kSbSystemDeviceTypeDesktopPC` - Desktop PC.
+*   `kSbSystemDeviceTypeAndroidTV` - An Android TV Device.
+*   `kSbSystemDeviceTypeUnknown` - Unknown device.
+
+### SbSystemPathId
+
+Enumeration of special paths that the platform can define.
+
+**Values**
+
+*   `kSbSystemPathContentDirectory` - Path to where the local content files that ship with the binary areavailable.
+*   `kSbSystemPathCacheDirectory` - Path to the directory that can be used as a local file cache, ifavailable.
+*   `kSbSystemPathDebugOutputDirectory` - Path to the directory where debug output (e.g. logs, trace output,screenshots) can be written into.
+*   `kSbSystemPathFontDirectory` - Path to a directory where system font files can be found. Should only bespecified on platforms that provide fonts usable by Starboard applications.
+*   `kSbSystemPathFontConfigurationDirectory` - Path to a directory where system font configuration metadata can befound. May be the same directory as |kSbSystemPathFontDirectory|, but notnecessarily. Should only be specified on platforms that provide fontsusable by Starboard applications.
+*   `kSbSystemPathSourceDirectory` - Path to the directory containing the root of the source tree.
+*   `kSbSystemPathTempDirectory` - Path to a directory where temporary files can be written.
+*   `kSbSystemPathTestOutputDirectory` - Path to a directory where test results can be written.
+*   `kSbSystemPathExecutableFile` - Full path to the executable file.
+
+### SbSystemPlatformErrorResponse
+
+Possible responses for `SbSystemPlatformErrorCallback`.
+
+**Values**
+
+*   `kSbSystemPlatformErrorResponsePositive`
+*   `kSbSystemPlatformErrorResponseNegative`
+
+### SbSystemPlatformErrorType
+
+Enumeration of possible values for the `type` parameter passed to  the
+`SbSystemRaisePlatformError` function.
+
+**Values**
+
+*   `kSbSystemPlatformErrorTypeConnectionError` - Cobalt received a network connection error, or a network disconnectionevent. If the |response| passed to |SbSystemPlatformErrorCallback| is|kSbSystemPlatformErrorResponsePositive| then the request should beretried, otherwise the app should be stopped.
+*   `kSbSystemPlatformErrorTypeUserSignedOut` - The current user is not signed in.
+
+### SbSystemPropertyId
+
+System properties that can be queried for. Many of these are used in
+User-Agent string generation.
+
+**Values**
+
+*   `kSbSystemPropertyChipsetModelNumber` - The full model number of the main platform chipset, including anyvendor-specific prefixes.
+*   `kSbSystemPropertyFirmwareVersion` - The production firmware version number which the device is currentlyrunning.
+*   `kSbSystemPropertyFriendlyName` - A friendly name for this actual device. It may include user-personalizationlike "Upstairs Bedroom." It may be displayed to users as part of some kindof device selection (e.g. in-app DIAL).
+*   `kSbSystemPropertyManufacturerName` - A deprecated alias for |kSbSystemPropertyBrandName|.
+*   `kSbSystemPropertyBrandName` - The name of the brand under which the device is being sold.
+*   `kSbSystemPropertyModelName` - The final production model number of the device.
+*   `kSbSystemPropertyModelYear` - The year the device was launched, e.g. "2016".
+*   `kSbSystemPropertyNetworkOperatorName` - The name of the network operator that owns the target device, ifapplicable.
+*   `kSbSystemPropertyPlatformName` - The name of the operating system and platform, suitable for inclusion in aUser-Agent, say.
+*   `kSbSystemPropertyPlatformUuid` - A universally-unique ID for the current user.
+*   `kSbSystemPropertySpeechApiKey` - The Google Speech API key. The platform manufacturer is responsiblefor registering a Google Speech API key for their products. In the APIConsole (http://developers.google.com/console), you can enable theSpeech APIs and generate a Speech API key.
+*   `kSbSystemPropertyUserAgentAuxField` - A field that, if available, is appended to the user agent
+
+## Structs
+
+### SbSystemPlatformErrorPrivate
+
+Private structure used to represent a raised platform error.
+
+## Functions
+
+### SbSystemBinarySearch
+
+**Description**
+
+Binary searches a sorted table `base` of `element_count` objects, each
+element `element_width` bytes in size for an element that `comparator`
+compares equal to `key`.<br>
+This function is meant to be a drop-in replacement for `bsearch`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemBinarySearch-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemBinarySearch-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemBinarySearch-declaration">
+<pre>
+SB_EXPORT void* SbSystemBinarySearch(const void* key,
+                                     const void* base,
+                                     size_t element_count,
+                                     size_t element_width,
+                                     SbSystemComparator comparator);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemBinarySearch-stub">
+
+```
+#include "starboard/system.h"
+
+void* SbSystemBinarySearch(const void* /*key*/,
+                           const void* /*base*/,
+                           size_t /*element_count*/,
+                           size_t /*element_width*/,
+                           SbSystemComparator /*comparator*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>key</code></td>
+    <td>The key to search for in the table.</td>
+  </tr>
+  <tr>
+    <td><code>const void*</code><br>        <code>base</code></td>
+    <td>The sorted table of elements to be searched.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>element_count</code></td>
+    <td>The number of elements in the table.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>element_width</code></td>
+    <td>The size, in bytes, of each element in the table.</td>
+  </tr>
+  <tr>
+    <td><code>SbSystemComparator</code><br>        <code>comparator</code></td>
+    <td>A value that indicates how the element in the table should
+compare to the specified <code>key</code>.</td>
+  </tr>
+</table>
+
+### SbSystemBreakIntoDebugger
+
+**Description**
+
+Breaks the current program into the debugger, if a debugger is attached.
+If a debugger is not attached, this function aborts the program.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemBreakIntoDebugger-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemBreakIntoDebugger-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemBreakIntoDebugger-declaration">
+<pre>
+SB_NORETURN SB_EXPORT void SbSystemBreakIntoDebugger();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemBreakIntoDebugger-stub">
+
+```
+#include "starboard/system.h"
+
+void SbSystemBreakIntoDebugger() {
+#if SB_IS(COMPILER_GCC)
+  __builtin_unreachable();
+#endif
+}
+```
+
+  </div>
+</div>
+
+### SbSystemClearLastError
+
+**Description**
+
+Clears the last error set by a Starboard call in the current thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemClearLastError-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemClearLastError-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemClearLastError-declaration">
+<pre>
+SB_EXPORT void SbSystemClearLastError();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemClearLastError-stub">
+
+```
+#include "starboard/system.h"
+
+void SbSystemClearLastError() {
+}
+```
+
+  </div>
+</div>
+
+### SbSystemClearPlatformError
+
+**Description**
+
+Clears a platform error that was previously raised by a call to
+`SbSystemRaisePlatformError`. The platform may use this, for example,
+to close a dialog that was opened in response to the error.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemClearPlatformError-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemClearPlatformError-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemClearPlatformError-declaration">
+<pre>
+SB_EXPORT void SbSystemClearPlatformError(SbSystemPlatformError handle);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemClearPlatformError-stub">
+
+```
+#include "starboard/system.h"
+
+void SbSystemClearPlatformError(SbSystemPlatformError handle) {
+  SB_UNREFERENCED_PARAMETER(handle);
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSystemPlatformError</code><br>        <code>handle</code></td>
+    <td>The platform error to be cleared.</td>
+  </tr>
+</table>
+
+### SbSystemGetConnectionType
+
+**Description**
+
+Returns the device's current network connection type.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemGetConnectionType-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemGetConnectionType-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemGetConnectionType-declaration">
+<pre>
+SB_EXPORT SbSystemConnectionType SbSystemGetConnectionType();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemGetConnectionType-stub">
+
+```
+#include "starboard/system.h"
+
+SbSystemConnectionType SbSystemGetConnectionType() {
+  return kSbSystemConnectionTypeUnknown;
+}
+```
+
+  </div>
+</div>
+
+### SbSystemGetDeviceType
+
+**Description**
+
+Returns the type of the device.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemGetDeviceType-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemGetDeviceType-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemGetDeviceType-declaration">
+<pre>
+SB_EXPORT SbSystemDeviceType SbSystemGetDeviceType();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemGetDeviceType-stub">
+
+```
+#include "starboard/system.h"
+
+SbSystemDeviceType SbSystemGetDeviceType() {
+  return kSbSystemDeviceTypeUnknown;
+}
+```
+
+  </div>
+</div>
+
+### SbSystemGetErrorString
+
+**Description**
+
+Generates a human-readable string for an error. The return value specifies
+the total desired length of the string.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemGetErrorString-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemGetErrorString-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemGetErrorString-declaration">
+<pre>
+SB_EXPORT int SbSystemGetErrorString(SbSystemError error,
+                                     char* out_string,
+                                     int string_length);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemGetErrorString-stub">
+
+```
+#include "starboard/system.h"
+
+int SbSystemGetErrorString(SbSystemError /*error*/,
+                           char* /*out_string*/,
+                           int /*string_length*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSystemError</code><br>        <code>error</code></td>
+    <td>The error for which a human-readable string is generated.</td>
+  </tr>
+  <tr>
+    <td><code>char*</code><br>        <code>out_string</code></td>
+    <td>The generated string. This value may be null, and it is
+always terminated with a null byte.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>string_length</code></td>
+    <td>The maximum length of the error string.</td>
+  </tr>
+</table>
+
+### SbSystemGetLastError
+
+**Description**
+
+Gets the last platform-specific error code produced by any Starboard call in
+the current thread for diagnostic purposes. Semantic reactions to Starboard
+function call results should be modeled explicitly.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemGetLastError-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemGetLastError-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemGetLastError-declaration">
+<pre>
+SB_EXPORT SbSystemError SbSystemGetLastError();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemGetLastError-stub">
+
+```
+#include "starboard/system.h"
+
+SbSystemError SbSystemGetLastError() {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+### SbSystemGetLocaleId
+
+**Description**
+
+Gets the system's current POSIX-style Locale ID. The locale represents the
+location, language, and cultural conventions that the system wants to use,
+which affects which text is displayed to the user as well as how displayed
+numbers, dates, currency, and similar values are formatted.<br>
+At its simplest, the locale ID can just be a BCP 47 language code, like
+`en_US`. Currently, POSIX also wants to include the encoding as in
+`en_US.UTF8`. POSIX also allows a couple very bare-bones locales, like "C"
+or "POSIX", but they are not supported here. POSIX also supports different
+locale settings for a few different purposes, but Starboard only exposes one
+locale at a time.<br>
+RFC 5646 describes BCP 47 language codes:
+https://tools.ietf.org/html/bcp47<br>
+For more information than you probably want about POSIX locales, see:
+http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemGetLocaleId-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemGetLocaleId-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemGetLocaleId-declaration">
+<pre>
+SB_EXPORT const char* SbSystemGetLocaleId();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemGetLocaleId-stub">
+
+```
+#include "starboard/system.h"
+
+const char* SbSystemGetLocaleId() {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+### SbSystemGetNumberOfProcessors
+
+**Description**
+
+Returns the number of processor cores available to this application. If the
+process is sandboxed to a subset of the physical cores, the function returns
+that sandboxed limit.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemGetNumberOfProcessors-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemGetNumberOfProcessors-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemGetNumberOfProcessors-declaration">
+<pre>
+SB_EXPORT int SbSystemGetNumberOfProcessors();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemGetNumberOfProcessors-stub">
+
+```
+#include "starboard/system.h"
+
+int SbSystemGetNumberOfProcessors() {
+  return 1;
+}
+```
+
+  </div>
+</div>
+
+### SbSystemGetPath
+
+**Description**
+
+Retrieves the platform-defined system path specified by `path_id` and
+places it as a zero-terminated string into the user-allocated `out_path`
+unless it is longer than `path_length` - 1. This implementation must be
+thread-safe.<br>
+This function returns `true` if the path is retrieved successfully. It
+returns `false` under any of the following conditions and, in any such
+case, `out_path` is not changed:
+<ul><li>`path_id` is invalid for this platform
+</li><li>`path_length` is too short for the given result
+</li><li>`out_path` is NULL</li></ul>
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemGetPath-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemGetPath-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemGetPath-declaration">
+<pre>
+SB_EXPORT bool SbSystemGetPath(SbSystemPathId path_id,
+                               char* out_path,
+                               int path_length);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemGetPath-stub">
+
+```
+#include "starboard/system.h"
+
+bool SbSystemGetPath(SbSystemPathId /*path_id*/, char* /*out_path*/,
+                     int /*path_size*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSystemPathId</code><br>        <code>path_id</code></td>
+    <td>The system path to be retrieved.</td>
+  </tr>
+  <tr>
+    <td><code>char*</code><br>        <code>out_path</code></td>
+    <td>The platform-defined system path specified by <code>path_id</code>.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>path_length</code></td>
+    <td>The length of the system path.</td>
+  </tr>
+</table>
+
+### SbSystemGetProperty
+
+**Description**
+
+Retrieves the platform-defined system property specified by `property_id` and
+places its value as a zero-terminated string into the user-allocated
+`out_value` unless it is longer than `value_length` - 1. This implementation
+must be thread-safe.<br>
+This function returns `true` if the property is retrieved successfully. It
+returns `false` under any of the following conditions and, in any such
+case, `out_value` is not changed:
+<ul><li>`property_id` is invalid for this platform
+</li><li>`value_length` is too short for the given result
+</li><li>`out_value` is NULL</li></ul>
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemGetProperty-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemGetProperty-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemGetProperty-declaration">
+<pre>
+SB_EXPORT bool SbSystemGetProperty(SbSystemPropertyId property_id,
+                                   char* out_value,
+                                   int value_length);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemGetProperty-stub">
+
+```
+#include "starboard/system.h"
+
+bool SbSystemGetProperty(SbSystemPropertyId /*property_id*/,
+                         char* /*out_value*/,
+                         int /*value_length*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSystemPropertyId</code><br>        <code>property_id</code></td>
+    <td>The system path to be retrieved.</td>
+  </tr>
+  <tr>
+    <td><code>char*</code><br>        <code>out_value</code></td>
+    <td>The platform-defined system property specified by <code>property_id</code>.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>value_length</code></td>
+    <td>The length of the system property.</td>
+  </tr>
+</table>
+
+### SbSystemGetRandomData
+
+**Description**
+
+A cryptographically secure random number generator that produces an
+arbitrary, non-negative number of `buffer_size` random, non-negative bytes.
+The generated number is placed in `out_buffer`. This function does not
+require manual seeding.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemGetRandomData-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemGetRandomData-stub" class="mdl-tabs__tab">stub</a>
+    <a href="#SbSystemGetRandomData-linux" class="mdl-tabs__tab">linux</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemGetRandomData-declaration">
+<pre>
+SB_EXPORT void SbSystemGetRandomData(void* out_buffer, int buffer_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemGetRandomData-stub">
+
+```
+#include "starboard/system.h"
+
+void SbSystemGetRandomData(void* /*out_buffer*/, int /*buffer_size*/) {
+}
+```
+
+  </div>
+  <div class="mdl-tabs__panel" id="SbSystemGetRandomData-linux">
+
+```
+#include "starboard/system.h"
+
+#include "starboard/file.h"
+#include "starboard/log.h"
+#include "starboard/mutex.h"
+#include "starboard/once.h"
+
+namespace {
+
+// We keep the open file descriptor for /dev/urandom around so we don't need to
+// reopen it (which is expensive).
+class URandomFile {
+ public:
+  URandomFile() {
+    file_ =
+        SbFileOpen("/dev/urandom", kSbFileOpenOnly | kSbFileRead, NULL, NULL);
+    SB_DCHECK(SbFileIsValid(file_)) << "Cannot open /dev/urandom";
+  }
+
+  ~URandomFile() { SbFileClose(file_); }
+
+  SbFile file() const { return file_; }
+
+ private:
+  SbFile file_;
+};
+
+// A file that will produce any number of very random bytes.
+URandomFile* g_urandom_file = NULL;
+
+// Control to initialize g_urandom_file.
+SbOnceControl g_urandom_file_once = SB_ONCE_INITIALIZER;
+
+// Lazily initialize g_urandom_file.
+void InitializeRandom() {
+  SB_DCHECK(g_urandom_file == NULL);
+  g_urandom_file = new URandomFile();
+}
+
+}  // namespace
+
+void SbSystemGetRandomData(void* out_buffer, int buffer_size) {
+  SB_DCHECK(out_buffer);
+  char* buffer = reinterpret_cast<char*>(out_buffer);
+  int remaining = buffer_size;
+  bool once_result = SbOnce(&g_urandom_file_once, &InitializeRandom);
+  SB_DCHECK(once_result);
+
+  SbFile file = g_urandom_file->file();
+  do {
+    // This is unsynchronized access to the File that could happen from multiple
+    // threads. It doesn't appear that there is any locking in the Chromium
+    // POSIX implementation that is very similar.
+    int result = SbFileRead(file, buffer, remaining);
+    if (result <= 0)
+      break;
+
+    remaining -= result;
+    buffer += result;
+  } while (remaining);
+
+  SB_CHECK(remaining == 0);
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>out_buffer</code></td>
+    <td>A pointer for the generated random number. This value must
+not be null.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>buffer_size</code></td>
+    <td>The size of the random number, in bytes.</td>
+  </tr>
+</table>
+
+### SbSystemGetRandomUInt64
+
+**Description**
+
+A cryptographically secure random number generator that gets 64 random bits
+and returns them as an `uint64_t`. This function does not require manual
+seeding.
+
+**Declaration**
+
+```
+SB_EXPORT uint64_t SbSystemGetRandomUInt64();
+```
+
+### SbSystemGetStack
+
+**Description**
+
+Places up to `stack_size` instruction pointer addresses of the current
+execution stack into `out_stack`. The return value specifies the number
+of entries added.<br>
+The returned stack frames are in "downward" order from the calling frame
+toward the entry point of the thread. So, if all the stack frames do not
+fit, the ones truncated will be the less interesting ones toward the thread
+entry point.<br>
+This function is used in crash signal handlers and, therefore, it must
+be async-signal-safe on platforms that support signals. The following
+document discusses what it means to be async-signal-safe on POSIX:
+http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html#tag_02_04_03
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemGetStack-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemGetStack-stub" class="mdl-tabs__tab">stub</a>
+    <a href="#SbSystemGetStack-linux" class="mdl-tabs__tab">linux</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemGetStack-declaration">
+<pre>
+SB_EXPORT int SbSystemGetStack(void** out_stack, int stack_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemGetStack-stub">
+
+```
+#include "starboard/system.h"
+
+int SbSystemGetStack(void** /*out_stack*/, int /*stack_size*/) {
+  return 0;
+}
+```
+
+  </div>
+  <div class="mdl-tabs__panel" id="SbSystemGetStack-linux">
+
+```
+#include "starboard/system.h"
+
+#include <execinfo.h>
+
+#include <algorithm>
+
+int SbSystemGetStack(void** out_stack, int stack_size) {
+  int count = std::max(backtrace(out_stack, stack_size), 0);
+
+  if (count < 1) {
+    // No stack, for some reason.
+    return count;
+  }
+
+  // We have an extra stack frame (for this very function), so let's remove it.
+  for (int i = 1; i < count; ++i) {
+    out_stack[i - 1] = out_stack[i];
+  }
+
+  return count - 1;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void**</code><br>        <code>out_stack</code></td>
+    <td>A non-NULL array of <code>void *</code> of at least <code>stack_size</code> entries.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>stack_size</code></td>
+    <td>The maximum number of instruction pointer addresses to be
+placed into <code>out_stack</code> from the current execution stack.</td>
+  </tr>
+</table>
+
+### SbSystemGetTotalCPUMemory
+
+**Description**
+
+Returns the total CPU memory (in bytes) potentially available to this
+application. If the process is sandboxed to a maximum allowable limit,
+the function returns the lesser of the physical and sandbox limits.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemGetTotalCPUMemory-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemGetTotalCPUMemory-stub" class="mdl-tabs__tab">stub</a>
+    <a href="#SbSystemGetTotalCPUMemory-linux" class="mdl-tabs__tab">linux</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemGetTotalCPUMemory-declaration">
+<pre>
+SB_EXPORT int64_t SbSystemGetTotalCPUMemory();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemGetTotalCPUMemory-stub">
+
+```
+#include "starboard/system.h"
+
+int64_t SbSystemGetTotalCPUMemory() {
+  return 0;
+}
+```
+
+  </div>
+  <div class="mdl-tabs__panel" id="SbSystemGetTotalCPUMemory-linux">
+
+```
+#include "starboard/system.h"
+
+#include <unistd.h>
+
+#include "starboard/log.h"
+
+int64_t SbSystemGetTotalCPUMemory() {
+  long pages = sysconf(_SC_PHYS_PAGES);     // NOLINT[runtime/int]
+  long page_size = sysconf(_SC_PAGE_SIZE);  // NOLINT[runtime/int]
+  if (pages == -1 || page_size == -1) {
+    SB_NOTREACHED();
+    return 0;
+  }
+
+  return static_cast<int64_t>(pages) * page_size;
+}
+```
+
+  </div>
+</div>
+
+### SbSystemGetTotalGPUMemory
+
+**Description**
+
+Returns the total GPU memory (in bytes) available for use by this
+application. This function may only be called the return value for calls to
+SbSystemHasCapability(kSbSystemCapabilityCanQueryGPUMemoryStats) is `true`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemGetTotalGPUMemory-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemGetTotalGPUMemory-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemGetTotalGPUMemory-declaration">
+<pre>
+SB_EXPORT int64_t SbSystemGetTotalGPUMemory();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemGetTotalGPUMemory-stub">
+
+```
+#include "starboard/system.h"
+
+int64_t SbSystemGetTotalGPUMemory() {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+### SbSystemGetUsedCPUMemory
+
+**Description**
+
+Returns the total physical CPU memory (in bytes) used by this application.
+This value should always be less than (or, in particularly exciting
+situations, equal to) <code><a href="#sbsystemgettotalcpumemory">SbSystemGetTotalCPUMemory()</a></code>.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemGetUsedCPUMemory-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemGetUsedCPUMemory-stub" class="mdl-tabs__tab">stub</a>
+    <a href="#SbSystemGetUsedCPUMemory-linux" class="mdl-tabs__tab">linux</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemGetUsedCPUMemory-declaration">
+<pre>
+SB_EXPORT int64_t SbSystemGetUsedCPUMemory();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemGetUsedCPUMemory-stub">
+
+```
+#include "starboard/system.h"
+
+int64_t SbSystemGetUsedCPUMemory() {
+  return 0;
+}
+```
+
+  </div>
+  <div class="mdl-tabs__panel" id="SbSystemGetUsedCPUMemory-linux">
+
+```
+#include "starboard/system.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/sysinfo.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "starboard/file.h"
+#include "starboard/log.h"
+#include "starboard/string.h"
+
+// We find the current amount of used memory on Linux by opening
+// '/proc/self/status' and scan the file for its "VmRSS" entry.  Essentially,
+// we need to parse a buffer that has the following format:
+//
+// xxxxxx:       45327 kB
+// yyyyyy:          23 kB
+// VmRSS:        87432 kB
+// zzzzzz:        3213 kB
+// ...
+//
+// And here, we would want to return the value 87432 * 1024.
+// See http://man7.org/linux/man-pages/man5/proc.5.html for more details.
+
+// Searches for the value of VmRSS and returns it.  Will modify |buffer| in
+// order to do so quickly and easily.
+int64_t SearchForVmRSSValue(char* buffer, size_t length) {
+  // Search for the string ""VmRSS:".
+  const char kSearchString[] = "\nVmRSS:";
+  enum State {
+    // We are currently searching for kSearchString
+    kSearchingForSearchString,
+    // We found the search string and are advancing through spaces/tabs until
+    // we see a number.
+    kAdvancingSpacesToNumber,
+    // We found the number and are now searching for the end of it.
+    kFindingEndOfNumber,
+  };
+  State state = kSearchingForSearchString;
+  const char* number_start = NULL;
+  for (size_t i = 0; i < length - sizeof(kSearchString); ++i) {
+    if (state == kSearchingForSearchString) {
+      if (SbStringCompare(&buffer[i], kSearchString,
+                          sizeof(kSearchString) - 1) == 0) {
+        // Advance until we find a number.
+        state = kAdvancingSpacesToNumber;
+        i += sizeof(kSearchString) - 2;
+      }
+    } else if (state == kAdvancingSpacesToNumber) {
+      if (buffer[i] >= '0' && buffer[i] <= '9') {
+        // We found the start of the number, record where that is and then
+        // continue searching for the end of the number.
+        number_start = &buffer[i];
+        state = kFindingEndOfNumber;
+      }
+    } else {
+      SB_DCHECK(state == kFindingEndOfNumber);
+      if (buffer[i] < '0' || buffer[i] > '9') {
+        // Drop a null at the end of the number so that we can call atoi() on
+        // it and return.
+        buffer[i] = '\0';
+        return SbStringAToI(number_start);
+      }
+    }
+  }
+
+  SB_LOG(ERROR) << "Could not find 'VmRSS:' in /proc/self/status.";
+  return 0;
+}
+
+int64_t SbSystemGetUsedCPUMemory() {
+  // Read our process' current physical memory usage from /proc/self/status.
+  // This requires a bit of parsing through the output to find the value for
+  // the "VmRSS" field which indicates used physical memory.
+  starboard::ScopedFile status_file("/proc/self/status",
+                                    kSbFileOpenOnly | kSbFileRead);
+  if (!status_file.IsValid()) {
+    SB_LOG(ERROR)
+        << "Error opening /proc/self/status in order to query self memory "
+           "usage.";
+    return 0;
+  }
+
+  // Read the entire file into memory.
+  const int kBufferSize = 2048;
+  char buffer[kBufferSize];
+  int remaining = kBufferSize;
+  char* output_pointer = buffer;
+  do {
+    int result = status_file.Read(output_pointer, remaining);
+    if (result <= 0)
+      break;
+
+    remaining -= result;
+    output_pointer += result;
+  } while (remaining);
+
+  // Return the result, multiplied by 1024 because it is given in kilobytes.
+  return SearchForVmRSSValue(buffer,
+                             static_cast<size_t>(output_pointer - buffer)) *
+         1024;
+}
+```
+
+  </div>
+</div>
+
+### SbSystemGetUsedGPUMemory
+
+**Description**
+
+Returns the current amount of GPU memory (in bytes) that is currently being
+used by this application. This function may only be called if the return
+value for calls to
+SbSystemHasCapability(kSbSystemCapabilityCanQueryGPUMemoryStats) is `true`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemGetUsedGPUMemory-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemGetUsedGPUMemory-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemGetUsedGPUMemory-declaration">
+<pre>
+SB_EXPORT int64_t SbSystemGetUsedGPUMemory();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemGetUsedGPUMemory-stub">
+
+```
+#include "starboard/system.h"
+
+int64_t SbSystemGetUsedGPUMemory() {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+### SbSystemHasCapability
+
+**Description**
+
+Returns whether the platform has the runtime capability specified by
+`capability_id`. Returns false for any unknown capabilities. This
+implementation must be thread-safe.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemHasCapability-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemHasCapability-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemHasCapability-declaration">
+<pre>
+SB_EXPORT bool SbSystemHasCapability(SbSystemCapabilityId capability_id);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemHasCapability-stub">
+
+```
+#include "starboard/system.h"
+
+bool SbSystemHasCapability(SbSystemCapabilityId /*capability_id*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSystemCapabilityId</code><br>        <code>capability_id</code></td>
+    <td>The runtime capability to check.</td>
+  </tr>
+</table>
+
+### SbSystemHideSplashScreen
+
+**Description**
+
+Hides the system splash screen on systems that support a splash screen that
+is displayed while the application is loading. This function may be called
+from any thread and must be idempotent.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemHideSplashScreen-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemHideSplashScreen-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemHideSplashScreen-declaration">
+<pre>
+SB_EXPORT void SbSystemHideSplashScreen();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemHideSplashScreen-stub">
+
+```
+#include "starboard/system.h"
+
+void SbSystemHideSplashScreen() {}
+```
+
+  </div>
+</div>
+
+### SbSystemIsDebuggerAttached
+
+**Description**
+
+Attempts to determine whether the current program is running inside or
+attached to a debugger. The function returns `false` if neither of those
+cases is true.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemIsDebuggerAttached-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemIsDebuggerAttached-stub" class="mdl-tabs__tab">stub</a>
+    <a href="#SbSystemIsDebuggerAttached-linux" class="mdl-tabs__tab">linux</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemIsDebuggerAttached-declaration">
+<pre>
+SB_EXPORT bool SbSystemIsDebuggerAttached();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemIsDebuggerAttached-stub">
+
+```
+#include "starboard/system.h"
+
+bool SbSystemIsDebuggerAttached() {
+  return false;
+}
+```
+
+  </div>
+  <div class="mdl-tabs__panel" id="SbSystemIsDebuggerAttached-linux">
+
+```
+#include "starboard/system.h"
+
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "starboard/log.h"
+
+#include "starboard/shared/posix/file_internal.h"
+#include "starboard/shared/posix/handle_eintr.h"
+
+// Adapted from base/debug/debugger_posix.cc
+bool SbSystemIsDebuggerAttached() {
+  // We can look in /proc/self/status for TracerPid.  We are likely used in
+  // crash handling, so we are careful not to use the heap or have side effects.
+  // Another option that is common is to try to ptrace yourself, but then we
+  // can't detach without forking(), and that's not so great.
+
+  // NOTE: This code MUST be async-signal safe (it's used by in-process stack
+  // dumping signal handler). NO malloc or stdio is allowed here.
+
+  int status_fd = open("/proc/self/status", O_RDONLY);
+  if (status_fd == -1)
+    return false;
+
+  // We assume our line will be in the first 1024 characters and that we can
+  // read this much all at once.  In practice this will generally be true.
+  // This simplifies and speeds up things considerably.
+  char buf[1024];
+
+  ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf) - 1));
+  SB_DCHECK(num_read < sizeof(buf));
+  if (HANDLE_EINTR(close(status_fd)) < 0)
+    return false;
+
+  if (num_read <= 0)
+    return false;
+
+  buf[num_read] = '\0';
+  const char tracer[] = "TracerPid:\t";
+  char* pid_index = strstr(buf, tracer);
+  if (pid_index == NULL)
+    return false;
+
+  // Our pid is 0 without a debugger, assume this for any pid starting with 0.
+  pid_index += strlen(tracer);
+  return pid_index < (buf + num_read) && *pid_index != '0';
+}
+```
+
+  </div>
+</div>
+
+### SbSystemPlatformErrorIsValid
+
+**Description**
+
+Checks whether a `SbSystemPlatformError` is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbSystemPlatformErrorIsValid(
+    SbSystemPlatformError handle) {
+  return handle != kSbSystemPlatformErrorInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSystemPlatformError</code><br>
+        <code>handle</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbSystemRaisePlatformError
+
+**Description**
+
+Cobalt calls this function to notify the platform that an error has occurred
+in the application that the platform may need to handle. The platform is
+expected to then notify the user of the error and to provide a means for
+any required interaction, such as by showing a dialog.<br>
+The return value is a handle that may be used in a subsequent call to
+`SbClearPlatformError`. For example, the handle could be used to
+programatically dismiss a dialog that was raised in response to the error.
+The lifetime of the object referenced by the handle is until the user reacts
+to the error or the error is dismissed by a call to
+SbSystemClearPlatformError, whichever happens first. Note that if the
+platform cannot respond to the error, then this function should return
+`kSbSystemPlatformErrorInvalid`.<br>
+This function may be called from any thread, and it is the platform's
+responsibility to decide how to handle an error received while a previous
+error is still pending. If that platform can only handle one error at a
+time, then it may queue the second error or ignore it by returning
+`kSbSystemPlatformErrorInvalid`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemRaisePlatformError-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemRaisePlatformError-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemRaisePlatformError-declaration">
+<pre>
+SB_EXPORT SbSystemPlatformError
+SbSystemRaisePlatformError(SbSystemPlatformErrorType type,
+                           SbSystemPlatformErrorCallback callback,
+                           void* user_data);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemRaisePlatformError-stub">
+
+```
+#include "starboard/system.h"
+
+#include "starboard/log.h"
+
+SbSystemPlatformError SbSystemRaisePlatformError(
+    SbSystemPlatformErrorType type,
+    SbSystemPlatformErrorCallback callback,
+    void* user_data) {
+  SB_UNREFERENCED_PARAMETER(callback);
+  SB_UNREFERENCED_PARAMETER(user_data);
+  std::string message;
+  switch (type) {
+    case kSbSystemPlatformErrorTypeConnectionError:
+      message = "Connection error.";
+      break;
+#if SB_API_VERSION < 6
+    case kSbSystemPlatformErrorTypeUserSignedOut:
+      message = "User is not signed in.";
+      break;
+    case kSbSystemPlatformErrorTypeUserAgeRestricted:
+      message = "User is age restricted.";
+      break;
+#endif
+    default:
+      message = "<unknown>";
+      break;
+  }
+  SB_DLOG(INFO) << "SbSystemRaisePlatformError: " << message;
+  return kSbSystemPlatformErrorInvalid;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbSystemPlatformErrorType</code><br>        <code>type</code></td>
+    <td>An error type, from the SbSystemPlatformErrorType enum,
+that defines the error.</td>
+  </tr>
+  <tr>
+    <td><code>SbSystemPlatformErrorCallback</code><br>        <code>callback</code></td>
+    <td>A function that may be called by the platform to let the caller
+know that the user has reacted to the error.</td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>        <code>user_data</code></td>
+    <td>An opaque pointer that the platform should pass as an argument
+to the callback function, if it is called.</td>
+  </tr>
+</table>
+
+### SbSystemRequestPause
+
+**Description**
+
+Requests that the application move into the Paused state at the next
+convenient point. This should roughly correspond to "unfocused application"
+in a traditional window manager, where the application may be partially
+visible.<br>
+This function eventually causes a `kSbEventTypePause` event to be dispatched
+to the application. Before the `kSbEventTypePause` event is dispatched, some
+work may continue to be done, and unrelated system events may be dispatched.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemRequestPause-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemRequestPause-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemRequestPause-declaration">
+<pre>
+SB_EXPORT void SbSystemRequestPause();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemRequestPause-stub">
+
+```
+#include "starboard/system.h"
+
+void SbSystemRequestPause() {
+}
+```
+
+  </div>
+</div>
+
+### SbSystemRequestStop
+
+**Description**
+
+Requests that the application be terminated gracefully at the next
+convenient point. In the meantime, some work may continue to be done, and
+unrelated system events may be dispatched. This function eventually causes
+a `kSbEventTypeStop` event to be dispatched to the application. When the
+process finally terminates, it returns `error_level`, if that has any
+meaning on the current platform.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemRequestStop-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemRequestStop-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemRequestStop-declaration">
+<pre>
+SB_EXPORT void SbSystemRequestStop(int error_level);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemRequestStop-stub">
+
+```
+#include "starboard/system.h"
+
+void SbSystemRequestStop(int /*error_level*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>error_level</code></td>
+    <td>An integer that serves as the return value for the process
+that is eventually terminated as a result of a call to this function.</td>
+  </tr>
+</table>
+
+### SbSystemRequestSuspend
+
+**Description**
+
+Requests that the application move into the Suspended state at the next
+convenient point. This should roughly correspond to "minimization" in a
+traditional window manager, where the application is no longer visible.<br>
+This function eventually causes a `kSbEventTypeSuspend` event to be
+dispatched to the application. Before the `kSbEventTypeSuspend` event is
+dispatched, some work may continue to be done, and unrelated system events
+may be dispatched.<br>
+In the Suspended state, the application will be resident, but probably not
+running. The expectation is that an external system event will bring the
+application out of the Suspended state.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemRequestSuspend-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemRequestSuspend-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemRequestSuspend-declaration">
+<pre>
+SB_EXPORT void SbSystemRequestSuspend();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemRequestSuspend-stub">
+
+```
+#include "starboard/system.h"
+
+void SbSystemRequestSuspend() {
+}
+```
+
+  </div>
+</div>
+
+### SbSystemRequestUnpause
+
+**Description**
+
+Requests that the application move into the Started state at the next
+convenient point. This should roughly correspond to a "focused application"
+in a traditional window manager, where the application is fully visible and
+the primary receiver of input events.<br>
+This function eventually causes a `kSbEventTypeUnpause` event to be
+dispatched to the application. Before `kSbEventTypeUnpause` is dispatched,
+some work may continue to be done, and unrelated system events may be
+dispatched.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemRequestUnpause-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemRequestUnpause-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemRequestUnpause-declaration">
+<pre>
+SB_EXPORT void SbSystemRequestUnpause();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemRequestUnpause-stub">
+
+```
+#include "starboard/system.h"
+
+void SbSystemRequestUnpause() {
+}
+```
+
+  </div>
+</div>
+
+### SbSystemSort
+
+**Description**
+
+Sorts an array of elements `base`, with `element_count` elements of
+`element_width` bytes each, using `comparator` as the comparison function.<br>
+This function is meant to be a drop-in replacement for `qsort`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemSort-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemSort-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemSort-declaration">
+<pre>
+SB_EXPORT void SbSystemSort(void* base,
+                            size_t element_count,
+                            size_t element_width,
+                            SbSystemComparator comparator);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemSort-stub">
+
+```
+#include "starboard/system.h"
+
+void SbSystemSort(void* /*base*/,
+                  size_t /*element_count*/,
+                  size_t /*element_width*/,
+                  SbSystemComparator /*comparator*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>void*</code><br>        <code>base</code></td>
+    <td>The array of elements to be sorted.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>element_count</code></td>
+    <td>The number of elements in the array.</td>
+  </tr>
+  <tr>
+    <td><code>size_t</code><br>        <code>element_width</code></td>
+    <td>The size, in bytes, of each element in the array.</td>
+  </tr>
+  <tr>
+    <td><code>SbSystemComparator</code><br>        <code>comparator</code></td>
+    <td>A value that indicates how the array should be sorted.</td>
+  </tr>
+</table>
+
+### SbSystemSymbolize
+
+**Description**
+
+Looks up `address` as an instruction pointer and places up to
+(`buffer_size - 1`) characters of the symbol associated with it in
+`out_buffer`, which must not be NULL. `out_buffer` will be NULL-terminated.<br>
+The return value indicates whether the function found a reasonable match
+for `address`. If the return value is `false`, then `out_buffer` is not
+modified.<br>
+This function is used in crash signal handlers and, therefore, it must
+be async-signal-safe on platforms that support signals.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbSystemSymbolize-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbSystemSymbolize-stub" class="mdl-tabs__tab">stub</a>
+    <a href="#SbSystemSymbolize-linux" class="mdl-tabs__tab">linux</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbSystemSymbolize-declaration">
+<pre>
+SB_EXPORT bool SbSystemSymbolize(const void* address,
+                                 char* out_buffer,
+                                 int buffer_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbSystemSymbolize-stub">
+
+```
+#include "starboard/system.h"
+
+bool SbSystemSymbolize(const void* /*address*/, char* /*out_buffer*/,
+                       int /*buffer_size*/) {
+  return false;
+}
+```
+
+  </div>
+  <div class="mdl-tabs__panel" id="SbSystemSymbolize-linux">
+
+```
+#include "starboard/system.h"
+
+#include "base/third_party/symbolize/symbolize.h"
+
+bool SbSystemSymbolize(const void* address, char* out_buffer, int buffer_size) {
+  // I believe this casting-away const in the implementation is better than the
+  // alternative of removing const-ness from the address parameter.
+  return google::Symbolize(const_cast<void*>(address), out_buffer, buffer_size);
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const void*</code><br>
+        <code>address</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>char*</code><br>
+        <code>out_buffer</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>buffer_size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/thread.md b/src/cobalt/site/docs/reference/starboard/modules/thread.md
new file mode 100644
index 0000000..6697bca
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/thread.md
@@ -0,0 +1,923 @@
+---
+layout: doc
+title: "Starboard Module Reference: thread.h"
+---
+
+Defines functionality related to thread creation and cleanup.
+
+## Enums
+
+### SbThreadPriority
+
+A spectrum of thread priorities. Platforms map them appropriately to their
+own priority system. Note that scheduling is platform-specific, and what
+these priorities mean, if they mean anything at all, is also
+platform-specific.<br>
+In particular, several of these priority values can map to the same priority
+on a given platform. The only guarantee is that each lower priority should be
+treated less-than-or-equal-to a higher priority.
+
+**Values**
+
+*   `kSbThreadPriorityLowest` - The lowest thread priority available on the current platform.
+*   `kSbThreadPriorityLow` - A lower-than-normal thread priority, if available on the current platform.
+*   `kSbThreadPriorityNormal` - Really, what is normal? You should spend time pondering that question morethan you consider less-important things, but less than you think aboutmore-important things.
+*   `kSbThreadPriorityHigh` - A higher-than-normal thread priority, if available on the current platform.
+*   `kSbThreadPriorityHighest` - The highest thread priority available on the current platform that isn'tconsidered "real-time" or "time-critical," if those terms have any meaningon the current platform.
+*   `kSbThreadPriorityRealTime` - If the platform provides any kind of real-time or time-critical scheduling,this priority will request that treatment. Real-time scheduling generallymeans that the thread will have more consistency in scheduling thannon-real-time scheduled threads, often by being more deterministic in howthreads run in relation to each other. But exactly how being real-timeaffects the thread scheduling is platform-specific.<br>For platforms where that is not offered, or otherwise not meaningful, thiswill just be the highest priority available in the platform's scheme, whichmay be the same as kSbThreadPriorityHighest.
+*   `kSbThreadNoPriority` - Well-defined constant value to mean "no priority."  This means to use thedefault priority assignment method of that platform. This may mean toinherit the priority of the spawning thread, or it may mean a specificdefault priority, or it may mean something else, depending on the platform.
+
+## Structs
+
+### SbThreadLocalKeyPrivate
+
+Private structure representing a thread-local key.
+
+## Functions
+
+### SbThreadCreate
+
+**Description**
+
+Creates a new thread, which starts immediately.
+<ul><li>If the function succeeds, the return value is a handle to the newly
+created thread.
+</li><li>If the function fails, the return value is `kSbThreadInvalid`.</li></ul>
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbThreadCreate-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbThreadCreate-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbThreadCreate-declaration">
+<pre>
+SB_EXPORT SbThread SbThreadCreate(int64_t stack_size,
+                                  SbThreadPriority priority,
+                                  SbThreadAffinity affinity,
+                                  bool joinable,
+                                  const char* name,
+                                  SbThreadEntryPoint entry_point,
+                                  void* context);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbThreadCreate-stub">
+
+```
+#include "starboard/thread.h"
+
+SbThread SbThreadCreate(int64_t /*stack_size*/,
+                        SbThreadPriority /*priority*/,
+                        SbThreadAffinity /*affinity*/,
+                        bool /*joinable*/,
+                        const char* /*name*/,
+                        SbThreadEntryPoint /*entry_point*/,
+                        void* /*context*/) {
+  return kSbThreadInvalid;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int64_t</code><br>        <code>stack_size</code></td>
+    <td>The amount of memory reserved for the thread. Set the value
+to <code>0</code> to indicate that the default stack size should be used.</td>
+  </tr>
+  <tr>
+    <td><code>SbThreadPriority</code><br>        <code>priority</code></td>
+    <td>The thread's priority. This value can be set to
+<code>kSbThreadNoPriority</code> to use the platform's default priority. As examples,
+it could be set to a fixed, standard priority or to a priority inherited
+from the thread that is calling <code>SbThreadCreate()</code>, or to something else.</td>
+  </tr>
+  <tr>
+    <td><code>SbThreadAffinity</code><br>        <code>affinity</code></td>
+    <td>The thread's affinity. This value can be set to
+<code>kSbThreadNoAffinity</code> to use the platform's default affinity.</td>
+  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>joinable</code></td>
+    <td>Indicates whether the thread can be joined (<code>true</code>) or should
+start out "detached" (<code>false</code>). Note that for joinable threads, when
+you are done with the thread handle, you must call <code>SbThreadJoin</code> to
+release system resources associated with the thread. This is not necessary
+for detached threads, but detached threads cannot be joined.</td>
+  </tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>name</code></td>
+    <td>A name used to identify the thread. This value is used mainly for
+debugging, it can be <code>NULL</code>, and it might not be used in production builds.</td>
+  </tr>
+  <tr>
+    <td><code>SbThreadEntryPoint</code><br>        <code>entry_point</code></td>
+    <td>A pointer to a function that will be executed on the newly
+created thread.</td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>        <code>context</code></td>
+    <td>This value will be passed to the <code>entry_point</code> function.</td>
+  </tr>
+</table>
+
+### SbThreadCreateLocalKey
+
+**Description**
+
+Creates and returns a new, unique key for thread local data. If the function
+does not succeed, the function returns `kSbThreadLocalKeyInvalid`.<br>
+If `destructor` is specified, it will be called in the owning thread, and
+only in the owning thread, when the thread exits. In that case, it is called
+on the local value associated with the key in the current thread as long as
+the local value is not NULL.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbThreadCreateLocalKey-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbThreadCreateLocalKey-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbThreadCreateLocalKey-declaration">
+<pre>
+SB_EXPORT SbThreadLocalKey
+SbThreadCreateLocalKey(SbThreadLocalDestructor destructor);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbThreadCreateLocalKey-stub">
+
+```
+#include "starboard/thread.h"
+
+SbThreadLocalKey SbThreadCreateLocalKey(
+    SbThreadLocalDestructor /*destructor*/) {
+  return kSbThreadLocalKeyInvalid;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbThreadLocalDestructor</code><br>        <code>destructor</code></td>
+    <td>A pointer to a function. The value may be NULL if no clean up
+is needed.</td>
+  </tr>
+</table>
+
+### SbThreadDestroyLocalKey
+
+**Description**
+
+Destroys thread local data for the specified key. The function is a no-op
+if the key is invalid (kSbThreadLocalKeyInvalid`) or has already been
+destroyed. This function does NOT call the destructor on any stored values.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbThreadDestroyLocalKey-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbThreadDestroyLocalKey-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbThreadDestroyLocalKey-declaration">
+<pre>
+SB_EXPORT void SbThreadDestroyLocalKey(SbThreadLocalKey key);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbThreadDestroyLocalKey-stub">
+
+```
+#include "starboard/thread.h"
+
+void SbThreadDestroyLocalKey(SbThreadLocalKey /*key*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbThreadLocalKey</code><br>        <code>key</code></td>
+    <td>The key for which to destroy thread local data.</td>
+  </tr>
+</table>
+
+### SbThreadDetach
+
+**Description**
+
+Detaches `thread`, which prevents it from being joined. This is sort of like
+a non-blocking join. This function is a no-op if the thread is already
+detached or if the thread is already being joined by another thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbThreadDetach-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbThreadDetach-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbThreadDetach-declaration">
+<pre>
+SB_EXPORT void SbThreadDetach(SbThread thread);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbThreadDetach-stub">
+
+```
+#include "starboard/thread.h"
+
+void SbThreadDetach(SbThread /*thread*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbThread</code><br>        <code>thread</code></td>
+    <td>The thread to be detached.</td>
+  </tr>
+</table>
+
+### SbThreadGetCurrent
+
+**Description**
+
+Returns the handle of the currently executing thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbThreadGetCurrent-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbThreadGetCurrent-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbThreadGetCurrent-declaration">
+<pre>
+SB_EXPORT SbThread SbThreadGetCurrent();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbThreadGetCurrent-stub">
+
+```
+#include "starboard/thread.h"
+
+SbThread SbThreadGetCurrent() {
+  return kSbThreadInvalid;
+}
+```
+
+  </div>
+</div>
+
+### SbThreadGetId
+
+**Description**
+
+Returns the Thread ID of the currently executing thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbThreadGetId-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbThreadGetId-stub" class="mdl-tabs__tab">stub</a>
+    <a href="#SbThreadGetId-linux" class="mdl-tabs__tab">linux</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbThreadGetId-declaration">
+<pre>
+SB_EXPORT SbThreadId SbThreadGetId();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbThreadGetId-stub">
+
+```
+#include "starboard/thread.h"
+
+SbThreadId SbThreadGetId() {
+  return 0;
+}
+```
+
+  </div>
+  <div class="mdl-tabs__panel" id="SbThreadGetId-linux">
+
+```
+#include "starboard/thread.h"
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+SbThreadId SbThreadGetId() {
+  // This is not portable outside of Linux.
+  return static_cast<SbThreadId>(syscall(SYS_gettid));
+}
+```
+
+  </div>
+</div>
+
+### SbThreadGetLocalValue
+
+**Description**
+
+Returns the pointer-sized value for `key` in the currently executing thread's
+local storage. Returns `NULL` if key is `kSbThreadLocalKeyInvalid` or if the
+key has already been destroyed.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbThreadGetLocalValue-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbThreadGetLocalValue-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbThreadGetLocalValue-declaration">
+<pre>
+SB_EXPORT void* SbThreadGetLocalValue(SbThreadLocalKey key);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbThreadGetLocalValue-stub">
+
+```
+#include "starboard/thread.h"
+
+void* SbThreadGetLocalValue(SbThreadLocalKey /*key*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbThreadLocalKey</code><br>        <code>key</code></td>
+    <td>The key for which to return the value.</td>
+  </tr>
+</table>
+
+### SbThreadGetName
+
+**Description**
+
+Returns the debug name of the currently executing thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbThreadGetName-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbThreadGetName-stub" class="mdl-tabs__tab">stub</a>
+    <a href="#SbThreadGetName-linux" class="mdl-tabs__tab">linux</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbThreadGetName-declaration">
+<pre>
+SB_EXPORT void SbThreadGetName(char* buffer, int buffer_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbThreadGetName-stub">
+
+```
+#include "starboard/thread.h"
+
+void SbThreadGetName(char* /*buffer*/, int /*buffer_size*/) {
+}
+```
+
+  </div>
+  <div class="mdl-tabs__panel" id="SbThreadGetName-linux">
+
+```
+#include "starboard/thread.h"
+
+#include <pthread.h>
+
+void SbThreadGetName(char* buffer, int buffer_size) {
+  pthread_getname_np(pthread_self(), buffer, static_cast<size_t>(buffer_size));
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>char*</code><br>
+        <code>buffer</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>
+        <code>buffer_size</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbThreadIsCurrent
+
+**Description**
+
+Returns whether `thread` is the current thread.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbThreadIsCurrent(SbThread thread) {
+  return SbThreadGetCurrent() == thread;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbThread</code><br>        <code>thread</code></td>
+    <td>The thread to check.</td>
+  </tr>
+</table>
+
+### SbThreadIsEqual
+
+**Description**
+
+Indicates whether `thread1` and `thread2` refer to the same thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbThreadIsEqual-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbThreadIsEqual-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbThreadIsEqual-declaration">
+<pre>
+SB_EXPORT bool SbThreadIsEqual(SbThread thread1, SbThread thread2);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbThreadIsEqual-stub">
+
+```
+#include "starboard/thread.h"
+
+bool SbThreadIsEqual(SbThread /*thread1*/, SbThread /*thread2*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbThread</code><br>        <code>thread1</code></td>
+    <td>The first thread to compare.</td>
+  </tr>
+  <tr>
+    <td><code>SbThread</code><br>        <code>thread2</code></td>
+    <td>The second thread to compare.</td>
+  </tr>
+</table>
+
+### SbThreadIsValid
+
+**Description**
+
+Returns whether the given thread handle is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbThreadIsValid(SbThread thread) {
+  return thread != kSbThreadInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbThread</code><br>
+        <code>thread</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbThreadIsValidAffinity
+
+**Description**
+
+Returns whether the given thread affinity is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbThreadIsValidAffinity(SbThreadAffinity affinity) {
+  return affinity != kSbThreadNoAffinity;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbThreadAffinity</code><br>
+        <code>affinity</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbThreadIsValidId
+
+**Description**
+
+Returns whether the given thread ID is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbThreadIsValidId(SbThreadId id) {
+  return id != kSbThreadInvalidId;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbThreadId</code><br>
+        <code>id</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbThreadIsValidLocalKey
+
+**Description**
+
+Returns whether the given thread local variable key is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbThreadIsValidLocalKey(SbThreadLocalKey key) {
+  return key != kSbThreadLocalKeyInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbThreadLocalKey</code><br>
+        <code>key</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbThreadIsValidPriority
+
+**Description**
+
+Returns whether the given thread priority is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbThreadIsValidPriority(SbThreadPriority priority) {
+  return priority != kSbThreadNoPriority;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbThreadPriority</code><br>
+        <code>priority</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbThreadJoin
+
+**Description**
+
+Joins the thread on which this function is called with joinable `thread`.
+This function blocks the caller until the designated thread exits, and then
+cleans up that thread's resources. The cleanup process essentially detaches
+thread.<br>
+The return value is `true` if the function is successful and `false` if
+`thread` is invalid or detached.<br>
+Each joinable thread can only be joined once and must be joined to be fully
+cleaned up. Once <code>SbThreadJoin</code> is called, the thread behaves as if it were
+detached to all threads other than the joining thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbThreadJoin-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbThreadJoin-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbThreadJoin-declaration">
+<pre>
+SB_EXPORT bool SbThreadJoin(SbThread thread, void** out_return);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbThreadJoin-stub">
+
+```
+#include "starboard/thread.h"
+
+bool SbThreadJoin(SbThread /*thread*/, void** /*out_return*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbThread</code><br>        <code>thread</code></td>
+    <td>The thread to which the current thread will be joined. The
+<code>thread</code> must have been created with <code><a href="#sbthreadcreate">SbThreadCreate</a></code>.</td>
+  </tr>
+  <tr>
+    <td><code>void**</code><br>        <code>out_return</code></td>
+    <td>If this is not <code>NULL</code>, then the <code>SbThreadJoin</code> function populates
+it with the return value of the thread's <code>main</code> function.</td>
+  </tr>
+</table>
+
+### SbThreadSetLocalValue
+
+**Description**
+
+Sets the pointer-sized value for `key` in the currently executing thread's
+local storage. The return value indicates whether `key` is valid and has
+not already been destroyed.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbThreadSetLocalValue-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbThreadSetLocalValue-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbThreadSetLocalValue-declaration">
+<pre>
+SB_EXPORT bool SbThreadSetLocalValue(SbThreadLocalKey key, void* value);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbThreadSetLocalValue-stub">
+
+```
+#include "starboard/thread.h"
+
+bool SbThreadSetLocalValue(SbThreadLocalKey /*key*/, void* /*value*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbThreadLocalKey</code><br>        <code>key</code></td>
+    <td>The key for which to set the key value.</td>
+  </tr>
+  <tr>
+    <td><code>void*</code><br>        <code>value</code></td>
+    <td>The new pointer-sized key value.</td>
+  </tr>
+</table>
+
+### SbThreadSetName
+
+**Description**
+
+Sets the debug name of the currently executing thread by copying the
+specified name string.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbThreadSetName-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbThreadSetName-stub" class="mdl-tabs__tab">stub</a>
+    <a href="#SbThreadSetName-linux" class="mdl-tabs__tab">linux</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbThreadSetName-declaration">
+<pre>
+SB_EXPORT void SbThreadSetName(const char* name);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbThreadSetName-stub">
+
+```
+#include "starboard/thread.h"
+
+void SbThreadSetName(const char* /*name*/) {
+}
+```
+
+  </div>
+  <div class="mdl-tabs__panel" id="SbThreadSetName-linux">
+
+```
+#include "starboard/thread.h"
+
+#include <errno.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "starboard/log.h"
+#include "starboard/string.h"
+
+void SbThreadSetName(const char* name) {
+  // We don't want to rename the main thread.
+  if (SbThreadGetId() == getpid()) {
+    return;
+  }
+
+  const int kMaxThreadNameLength = 16;
+  char buffer[kMaxThreadNameLength];
+
+  if (SbStringGetLength(name) >= SB_ARRAY_SIZE_INT(buffer)) {
+    SbStringCopy(buffer, name, SB_ARRAY_SIZE_INT(buffer));
+    SB_DLOG(WARNING) << "Thread name \"" << name << "\" was truncated to \""
+                     << buffer << "\"";
+    name = buffer;
+  }
+
+  if (pthread_setname_np(pthread_self(), name) != 0) {
+    SB_DLOG(ERROR) << "Failed to set thread name to " << name;
+  }
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const char*</code><br>        <code>name</code></td>
+    <td>The name to assign to the thread.</td>
+  </tr>
+</table>
+
+### SbThreadSleep
+
+**Description**
+
+Sleeps the currently executing thread.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbThreadSleep-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbThreadSleep-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbThreadSleep-declaration">
+<pre>
+SB_EXPORT void SbThreadSleep(SbTime duration);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbThreadSleep-stub">
+
+```
+#include "starboard/thread.h"
+
+void SbThreadSleep(SbTime /*duration*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbTime</code><br>        <code>duration</code></td>
+    <td>The minimum amount of time, in microseconds, that the currently
+executing thread should sleep. The function is a no-op if this value is
+negative or <code>0</code>.</td>
+  </tr>
+</table>
+
+### SbThreadYield
+
+**Description**
+
+Yields the currently executing thread, so another thread has a chance to run.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbThreadYield-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbThreadYield-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbThreadYield-declaration">
+<pre>
+SB_EXPORT void SbThreadYield();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbThreadYield-stub">
+
+```
+#include "starboard/thread.h"
+
+void SbThreadYield() {
+}
+```
+
+  </div>
+</div>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/thread_types.md b/src/cobalt/site/docs/reference/starboard/modules/thread_types.md
new file mode 100644
index 0000000..5d4f667
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/thread_types.md
@@ -0,0 +1,10 @@
+---
+layout: doc
+title: "Starboard Module Reference: thread_types.h"
+---
+
+Defines platform-specific threading and synchronization primitive types and
+initializers. We hide, but pass through, the platform's primitives to avoid
+doing a lot of work to replicate initialization-less synchronization
+primitives.
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/time.md b/src/cobalt/site/docs/reference/starboard/modules/time.md
new file mode 100644
index 0000000..ea38ff9
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/time.md
@@ -0,0 +1,194 @@
+---
+layout: doc
+title: "Starboard Module Reference: time.h"
+---
+
+Provides access to system time and timers.
+
+## Functions
+
+### SbTimeFromPosix
+
+**Description**
+
+Converts microseconds from the POSIX epoch into an `SbTime`.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE SbTime SbTimeFromPosix(int64_t time) {
+  return time - kSbTimeToPosixDelta;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int64_t</code><br>        <code>time</code></td>
+    <td>A time that measures the number of microseconds since
+January 1, 1970, 00:00:00, UTC.</td>
+  </tr>
+</table>
+
+### SbTimeGetMonotonicNow
+
+**Description**
+
+Gets a monotonically increasing time representing right now.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbTimeGetMonotonicNow-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbTimeGetMonotonicNow-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbTimeGetMonotonicNow-declaration">
+<pre>
+SB_EXPORT SbTimeMonotonic SbTimeGetMonotonicNow();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbTimeGetMonotonicNow-stub">
+
+```
+#include "starboard/time.h"
+
+SbTimeMonotonic SbTimeGetMonotonicNow() {
+  return SbTimeMonotonic();
+}
+```
+
+  </div>
+</div>
+
+### SbTimeGetMonotonicThreadNow
+
+**Description**
+
+Gets a monotonically increasing time representing how long the current
+thread has been in the executing state (i.e. not pre-empted nor waiting
+on an event). This is not necessarily total time and is intended to allow
+measuring thread execution time between two timestamps. If this is not
+available then <code><a href="#sbtimegetmonotonicnow">SbTimeGetMonotonicNow()</a></code> should be used.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbTimeGetMonotonicThreadNow-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbTimeGetMonotonicThreadNow-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbTimeGetMonotonicThreadNow-declaration">
+<pre>
+SB_EXPORT SbTimeMonotonic SbTimeGetMonotonicThreadNow();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbTimeGetMonotonicThreadNow-stub">
+
+```
+#include "starboard/time.h"
+
+SbTimeMonotonic SbTimeGetMonotonicThreadNow() {
+  return SbTimeMonotonic(0);
+}
+```
+
+  </div>
+</div>
+
+### SbTimeGetNow
+
+**Description**
+
+Gets the current system time as an `SbTime`.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbTimeGetNow-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbTimeGetNow-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbTimeGetNow-declaration">
+<pre>
+SB_EXPORT SbTime SbTimeGetNow();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbTimeGetNow-stub">
+
+```
+#include "starboard/time.h"
+
+SbTime SbTimeGetNow() {
+  return SbTime();
+}
+```
+
+  </div>
+</div>
+
+### SbTimeNarrow
+
+**Description**
+
+Safely narrows a number from a more precise unit to a less precise one. This
+function rounds negative values toward negative infinity.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE int64_t SbTimeNarrow(int64_t time, int64_t divisor) {
+  return time >= 0 ? time / divisor : (time - divisor + 1) / divisor;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>int64_t</code><br>
+        <code>time</code></td>
+    <td> </td>
+  </tr>
+  <tr>
+    <td><code>int64_t</code><br>
+        <code>divisor</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbTimeToPosix
+
+**Description**
+
+Converts `SbTime` into microseconds from the POSIX epoch.
+
+**Declaration**
+
+```
+static SB_C_FORCE_INLINE int64_t SbTimeToPosix(SbTime time) {
+  return time + kSbTimeToPosixDelta;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbTime</code><br>        <code>time</code></td>
+    <td>A time that is either measured in microseconds since the epoch of
+January 1, 1601, UTC, or that measures the number of microseconds
+between two times.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/time_zone.md b/src/cobalt/site/docs/reference/starboard/modules/time_zone.md
new file mode 100644
index 0000000..9518ce8
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/time_zone.md
@@ -0,0 +1,112 @@
+---
+layout: doc
+title: "Starboard Module Reference: time_zone.h"
+---
+
+Provides access to the system time zone information.
+
+## Functions
+
+### SbTimeZoneGetCurrent
+
+**Description**
+
+Gets the system's current SbTimeZone in minutes.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbTimeZoneGetCurrent-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbTimeZoneGetCurrent-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbTimeZoneGetCurrent-declaration">
+<pre>
+SB_EXPORT SbTimeZone SbTimeZoneGetCurrent();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbTimeZoneGetCurrent-stub">
+
+```
+#include "starboard/time_zone.h"
+
+SbTimeZone SbTimeZoneGetCurrent() {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+### SbTimeZoneGetDstName
+
+**Description**
+
+Gets the three-letter code of the current timezone in Daylight Savings Time,
+regardless of current DST status. (e.g. "PDT")
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbTimeZoneGetDstName-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbTimeZoneGetDstName-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbTimeZoneGetDstName-declaration">
+<pre>
+SB_EXPORT const char* SbTimeZoneGetDstName();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbTimeZoneGetDstName-stub">
+
+```
+#include "starboard/time_zone.h"
+
+#if SB_API_VERSION < 6
+const char* SbTimeZoneGetDstName() {
+  return "GMT";
+}
+#endif  // SB_API_VERSION < 6
+```
+
+  </div>
+</div>
+
+### SbTimeZoneGetName
+
+**Description**
+
+Gets the three-letter code of the current timezone in standard time,
+regardless of current Daylight Savings Time status. (e.g. "PST")
+Gets a string representation of the current timezone. Note that the string
+representation can either be standard or daylight saving time. The output
+can be of the form:
+1) A three-letter abbreviation such as "PST" or "PDT" (preferred).
+2) A time zone identifier such as "America/Los_Angeles"
+3) An un-abbreviated name such as "Pacific Standard Time".
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbTimeZoneGetName-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbTimeZoneGetName-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbTimeZoneGetName-declaration">
+<pre>
+SB_EXPORT const char* SbTimeZoneGetName();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbTimeZoneGetName-stub">
+
+```
+#include "starboard/time_zone.h"
+
+const char* SbTimeZoneGetName() {
+  return "GMT";
+}
+```
+
+  </div>
+</div>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/types.md b/src/cobalt/site/docs/reference/starboard/modules/types.md
new file mode 100644
index 0000000..6fa3adc
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/types.md
@@ -0,0 +1,318 @@
+---
+layout: doc
+title: "Starboard Module Reference: types.h"
+---
+
+Provides a suite of standard types that should be universally available on
+all platforms, specifically focused on explicitly-sized integer types and
+booleans. This module also includes some related ubiquitous definitions like
+limits of the explicitly-sized integer types, and standard pointer and int32
+sentinel values.
+
+## Macros
+
+<div id="macro-documentation-section">
+
+<h3 id="dbl_mant_dig" class="small-h3">DBL_MANT_DIG</h3>
+
+<h3 id="int_max" class="small-h3">INT_MAX</h3>
+
+<h3 id="int_min" class="small-h3">INT_MIN</h3>
+
+<h3 id="long_max" class="small-h3">LONG_MAX</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="long_min" class="small-h3">LONG_MIN</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+<h3 id="null" class="small-h3">NULL</h3>
+
+Simulate stddef.h for platforms that don't provide it.
+
+<h3 id="uint_max" class="small-h3">UINT_MAX</h3>
+
+Assume int is 32-bits until we find a platform for which that fails.
+
+<h3 id="ulong_max" class="small-h3">ULONG_MAX</h3>
+
+Note that this macro's definition varies depending on the values of one or more other variables.
+
+</div>
+
+## Functions
+
+### kSbInt16Max
+
+**Declaration**
+
+```
+static const int16_t kSbInt16Max = ((int16_t)0x7FFF);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>=</code><br>
+        <code>((int16_t</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### kSbInt16Min
+
+**Declaration**
+
+```
+static const int16_t kSbInt16Min = ((int16_t)0x8000);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>=</code><br>
+        <code>((int16_t</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### kSbInt32Max
+
+**Declaration**
+
+```
+static const int32_t kSbInt32Max = ((int32_t)0x7FFFFFFF);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>=</code><br>
+        <code>((int32_t</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### kSbInt64Max
+
+**Declaration**
+
+```
+static const int64_t kSbInt64Max = ((int64_t)SB_INT64_C(0x7FFFFFFFFFFFFFFF));
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>=</code><br>
+        <code>((int64_t</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### kSbInt64Min
+
+**Declaration**
+
+```
+static const int64_t kSbInt64Min = ((int64_t)SB_INT64_C(0x8000000000000000));
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>=</code><br>
+        <code>((int64_t</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### kSbInt8Max
+
+**Declaration**
+
+```
+static const int8_t kSbInt8Max = ((int8_t)0x7F);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>=</code><br>
+        <code>((int8_t</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### kSbInt8Min
+
+**Declaration**
+
+```
+static const int8_t kSbInt8Min = ((int8_t)0x80);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>=</code><br>
+        <code>((int8_t</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### kSbUInt16Max
+
+**Declaration**
+
+```
+static const uint16_t kSbUInt16Max = ((uint16_t)0xFFFF);
+#define kSbInt32Min ((int32_t)0x80000000)
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>=</code><br>
+        <code>((uint16_t</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### kSbUInt32Max
+
+**Declaration**
+
+```
+static const uint32_t kSbUInt32Max = ((uint32_t)0xFFFFFFFF);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>=</code><br>
+        <code>((uint32_t</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### kSbUInt64Max
+
+**Declaration**
+
+```
+static const uint64_t kSbUInt64Max = ((uint64_t)SB_INT64_C(0xFFFFFFFFFFFFFFFF));
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+// A value that represents an int that is probably invalid.
+#define kSbInvalidInt kSbInt32Min
+#if !SB_HAS(FLOAT_H)
+#endif
+// --- Standard Include Emulation Audits ---------------------------------------
+#if !defined(UINT_MAX) || !defined(INT_MIN) || !defined(INT_MAX) || \
+    !defined(LONG_MIN) || !defined(LONG_MAX)
+#error "limits.h or emulation did not provide a needed limit macro."
+#endif
+#if (UINT_MIN + 1 == UINT_MAX - 1) || (INT_MIN + 1 == INT_MAX - 1) || \
+    (LONG_MIN + 1 == LONG_MAX - 1)
+// This should always evaluate to false, but ensures that the limits macros can
+// be used arithmetically in the preprocessor.
+#endif
+#if !defined(PRId32)
+#error "inttypes.h should provide the portable formatting macros."
+#endif
+// --- Standard Type Audits ----------------------------------------------------
+#if SB_IS(WCHAR_T_UTF16)
+SB_COMPILE_ASSERT(sizeof(wchar_t) == 2,
+                  SB_IS_WCHAR_T_UTF16_is_inconsistent_with_sizeof_wchar_t);
+#endif
+#if SB_IS(WCHAR_T_UTF32)
+SB_COMPILE_ASSERT(sizeof(wchar_t) == 4,
+                  SB_IS_WCHAR_T_UTF32_is_inconsistent_with_sizeof_wchar_t);
+#endif
+#if SB_IS(WCHAR_T_SIGNED)
+SB_COMPILE_ASSERT((wchar_t)(-1) < 0,
+                  SB_IS_WCHAR_T_SIGNED_is_defined_incorrectly);
+#endif
+#if SB_IS(WCHAR_T_UNSIGNED)
+SB_COMPILE_ASSERT((wchar_t)(-1) > 0,
+                  SB_IS_WCHAR_T_UNSIGNED_is_defined_incorrectly);
+#endif
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+#endif  // STARBOARD_TYPES_H_
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>=</code><br>
+        <code>((uint64_t</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### kSbUInt8Max
+
+**Declaration**
+
+```
+static const uint8_t kSbUInt8Max = ((uint8_t)0xFF);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>=</code><br>
+        <code>((uint8_t</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/user.md b/src/cobalt/site/docs/reference/starboard/modules/user.md
new file mode 100644
index 0000000..a621f14
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/user.md
@@ -0,0 +1,247 @@
+---
+layout: doc
+title: "Starboard Module Reference: user.h"
+---
+
+Defines a user management API. This module defines functions only for
+managing signed-in users. Platforms that do not have users must still
+implement this API, always reporting a single user that is current and
+signed in.<br>
+These APIs are NOT expected to be thread-safe, so either call them from a
+single thread, or perform proper synchronization around all calls.
+
+## Enums
+
+### SbUserPropertyId
+
+A set of string properties that can be queried on a user.
+
+**Values**
+
+*   `kSbUserPropertyAvatarUrl` - The URL to the avatar for a user. Avatars are not provided on allplatforms.
+*   `kSbUserPropertyHomeDirectory` - The path to a user's home directory, if supported on this platform.
+*   `kSbUserPropertyUserName` - The username of a user, which may be the same as the User ID, or it may befriendlier.
+*   `kSbUserPropertyUserId` - A unique user ID of a user.
+
+## Structs
+
+### SbUserPrivate
+
+Private structure representing a device user.
+
+## Functions
+
+### SbUserGetCurrent
+
+**Description**
+
+Gets the current primary user, if one exists. This is the user that is
+determined, in a platform-specific way, to be the primary user controlling
+the application. For example, the determination might be made because that
+user launched the app, though it should be made using whatever criteria are
+appropriate for the platform.<br>
+It is expected that there will be a unique SbUser per signed-in user, and
+that the referenced objects will persist for the lifetime of the app.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbUserGetCurrent-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbUserGetCurrent-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbUserGetCurrent-declaration">
+<pre>
+SB_EXPORT SbUser SbUserGetCurrent();
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbUserGetCurrent-stub">
+
+```
+#include "starboard/user.h"
+
+SbUser SbUserGetCurrent() {
+  return kSbUserInvalid;
+}
+```
+
+  </div>
+</div>
+
+### SbUserGetProperty
+
+**Description**
+
+Retrieves the value of `property_id` for `user` and places it in `out_value`.
+The function returns:
+<ul><li>`true` if the property value is retrieved successfully
+</li><li>`false` if `user` is invalid; if `property_id` isn't recognized, supported,
+or set for `user`; or if `value_size` is too small.</li></ul>
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbUserGetProperty-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbUserGetProperty-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbUserGetProperty-declaration">
+<pre>
+SB_EXPORT bool SbUserGetProperty(SbUser user,
+                                 SbUserPropertyId property_id,
+                                 char* out_value,
+                                 int value_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbUserGetProperty-stub">
+
+```
+#include "starboard/user.h"
+
+int SbUserGetPropertySize(SbUser /*user*/, SbUserPropertyId /*property_id*/) {
+  return 0;
+}
+
+bool SbUserGetProperty(SbUser /*user*/,
+                       SbUserPropertyId /*property_id*/,
+                       char* /*out_value*/,
+                       int /*value_size*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbUser</code><br>        <code>user</code></td>
+    <td>The user for which property size data is being retrieved.</td>
+  </tr>
+  <tr>
+    <td><code>SbUserPropertyId</code><br>        <code>property_id</code></td>
+    <td>The property for which the data is requested.</td>
+  </tr>
+  <tr>
+    <td><code>char*</code><br>        <code>out_value</code></td>
+    <td>The retrieved property value.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>value_size</code></td>
+    <td>The size of the retrieved property value.</td>
+  </tr>
+</table>
+
+### SbUserGetPropertySize
+
+**Description**
+
+Returns the size of the value of `property_id` for `user`, INCLUDING the
+terminating null character. The function returns `0` if `user` is invalid
+or if `property_id` is not recognized, supported, or set for the user.
+
+**Declaration**
+
+```
+SB_EXPORT int SbUserGetPropertySize(SbUser user, SbUserPropertyId property_id);
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbUser</code><br>        <code>user</code></td>
+    <td>The user for which property size data is being retrieved.</td>
+  </tr>
+  <tr>
+    <td><code>SbUserPropertyId</code><br>        <code>property_id</code></td>
+    <td>The property for which the data is requested.</td>
+  </tr>
+</table>
+
+### SbUserGetSignedIn
+
+**Description**
+
+Gets a list of up to `users_size` signed-in users and places the results in
+`out_users`. The return value identifies the actual number of signed-in
+users, which may be greater or less than `users_size`.<br>
+It is expected that there will be a unique `SbUser` per signed-in user and
+that the referenced objects will persist for the lifetime of the app.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbUserGetSignedIn-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbUserGetSignedIn-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbUserGetSignedIn-declaration">
+<pre>
+SB_EXPORT int SbUserGetSignedIn(SbUser* out_users, int users_size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbUserGetSignedIn-stub">
+
+```
+#include "starboard/user.h"
+
+int SbUserGetSignedIn(SbUser* /*out_users*/, int /*users_size*/) {
+  return 0;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbUser*</code><br>        <code>out_users</code></td>
+    <td>Handles for the retrieved users.</td>
+  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>users_size</code></td>
+    <td>The maximum number of signed-in users to retrieve.</td>
+  </tr>
+</table>
+
+### SbUserIsValid
+
+**Description**
+
+Returns whether the given user handle is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbUserIsValid(SbUser user) {
+  return user != kSbUserInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbUser</code><br>
+        <code>user</code></td>
+    <td> </td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/reference/starboard/modules/window.md b/src/cobalt/site/docs/reference/starboard/modules/window.md
new file mode 100644
index 0000000..576fb2a
--- /dev/null
+++ b/src/cobalt/site/docs/reference/starboard/modules/window.md
@@ -0,0 +1,326 @@
+---
+layout: doc
+title: "Starboard Module Reference: window.h"
+---
+
+Provides functionality to handle Window creation and management.
+
+## Structs
+
+### SbWindowOptions
+
+Options that can be requested at window creation time.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>SbWindowSize</code><br>        <code>size</code></td>    <td>The requested size of the new window. The value of <code>video_pixel_ratio</code> will
+not be used or looked at.</td>  </tr>
+  <tr>
+    <td><code>bool</code><br>        <code>windowed</code></td>    <td>Whether the new window should be windowed or not. If not, the requested
+size is really the requested resolution.</td>  </tr>
+  <tr>
+    <td><code>const</code><br>        <code>char* name</code></td>    <td>The name of the window to create.</td>  </tr>
+</table>
+
+### SbWindowPrivate
+
+Private structure representing a system window.
+
+### SbWindowSize
+
+The size of a window in graphics rendering coordinates. The width and height
+of a window should correspond to the size of the graphics surface used for
+drawing that would be created to back that window.
+
+**Members**
+
+<table class="responsive">
+  <tr><th colspan="2">Members</th></tr>
+  <tr>
+    <td><code>int</code><br>        <code>width</code></td>    <td>The width of the window in graphics pixels.</td>  </tr>
+  <tr>
+    <td><code>int</code><br>        <code>height</code></td>    <td>The height of the window in graphics pixels.</td>  </tr>
+  <tr>
+    <td><code>float</code><br>        <code>video_pixel_ratio</code></td>    <td>The ratio of video pixels to graphics pixels. This ratio must be applied
+equally to width and height, meaning the aspect ratio is maintained.<br>
+A value of 1.0f means the video resolution is the same as the graphics
+resolution. This is the most common case.<br>
+Values greater than 1.0f mean that the video resolution is higher (denser,
+larger) than the graphics resolution. This is a common case as devices
+often have more video decoding capabilities than graphics rendering
+capabilities (or memory, etc...).<br>
+Values less than 1.0f mean that the maximum video resolution is smaller
+than the graphics resolution.<br>
+A value of 0.0f means the ratio could not be determined, it should be
+assumed to be the same as the graphics resolution (i.e. 1.0f).</td>  </tr>
+</table>
+
+## Functions
+
+### SbWindowCreate
+
+**Description**
+
+Creates and returns a new system window with the given `options`, which may
+be `NULL`. The function returns `kSbWindowInvalid` if it cannot create the
+requested `SbWindow` due to policy, unsatisfiable options, or any other
+reason.<br>
+If `options` are not specified, this function uses all defaults, which must
+work on every platform. In general, it defaults to creating a fullscreen
+window at the highest 16:9 resolution possible. If the platform does not
+support fullscreen windows, then it creates a normal, windowed window.<br>
+Some devices are fullscreen-only, including many production targets for
+Starboard. In those cases, only one SbWindow may be created, and it must be
+fullscreen. Additionally, in those cases, the requested size will actually
+be the requested resolution.<br>
+An SbWindow must be created to receive window-based events, like input
+events, even on fullscreen-only devices. These events are dispatched to
+the Starboard entry point.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbWindowCreate-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbWindowCreate-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbWindowCreate-declaration">
+<pre>
+SB_EXPORT SbWindow SbWindowCreate(const SbWindowOptions* options);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbWindowCreate-stub">
+
+```
+#include "starboard/window.h"
+
+SbWindow SbWindowCreate(const SbWindowOptions* /*options*/) {
+  return kSbWindowInvalid;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>const SbWindowOptions*</code><br>        <code>options</code></td>
+    <td>Options that specify parameters for the window being created.</td>
+  </tr>
+</table>
+
+### SbWindowDestroy
+
+**Description**
+
+Destroys `window`, reclaiming associated resources.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbWindowDestroy-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbWindowDestroy-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbWindowDestroy-declaration">
+<pre>
+SB_EXPORT bool SbWindowDestroy(SbWindow window);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbWindowDestroy-stub">
+
+```
+#include "starboard/window.h"
+
+bool SbWindowDestroy(SbWindow /*window*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbWindow</code><br>        <code>window</code></td>
+    <td>The <code>SbWindow</code> to destroy.</td>
+  </tr>
+</table>
+
+### SbWindowGetPlatformHandle
+
+**Description**
+
+Gets the platform-specific handle for `window`, which can be passed as an
+EGLNativeWindowType to initialize EGL/GLES. This return value is entirely
+platform-specific, so there are no constraints about expected ranges.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbWindowGetPlatformHandle-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbWindowGetPlatformHandle-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbWindowGetPlatformHandle-declaration">
+<pre>
+SB_EXPORT void* SbWindowGetPlatformHandle(SbWindow window);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbWindowGetPlatformHandle-stub">
+
+```
+#include "starboard/window.h"
+
+void* SbWindowGetPlatformHandle(SbWindow /*window*/) {
+  return NULL;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbWindow</code><br>        <code>window</code></td>
+    <td>The SbWindow to retrieve the platform handle for.</td>
+  </tr>
+</table>
+
+### SbWindowGetSize
+
+**Description**
+
+Retrieves the dimensions of `window` and sets `size` accordingly. This
+function returns `true` if it completes successfully. If the function
+returns `false`, then `size` will not have been modified.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbWindowGetSize-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbWindowGetSize-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbWindowGetSize-declaration">
+<pre>
+SB_EXPORT bool SbWindowGetSize(SbWindow window, SbWindowSize* size);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbWindowGetSize-stub">
+
+```
+#include "starboard/window.h"
+
+bool SbWindowGetSize(SbWindow /*window*/, SbWindowSize* /*size*/) {
+  return false;
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbWindow</code><br>        <code>window</code></td>
+    <td>The SbWindow to retrieve the size of.</td>
+  </tr>
+  <tr>
+    <td><code>SbWindowSize*</code><br>        <code>size</code></td>
+    <td>The retrieved size.</td>
+  </tr>
+</table>
+
+### SbWindowIsValid
+
+**Description**
+
+Returns whether the given window handle is valid.
+
+**Declaration**
+
+```
+static SB_C_INLINE bool SbWindowIsValid(SbWindow window) {
+  return window != kSbWindowInvalid;
+}
+```
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbWindow</code><br>
+        <code>window</code></td>
+    <td> </td>
+  </tr>
+</table>
+
+### SbWindowSetDefaultOptions
+
+**Description**
+
+Sets the default options for system windows.
+
+**Declaration and definitions**
+
+<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
+  <div class="mdl-tabs__tab-bar">
+    <a href="#SbWindowSetDefaultOptions-declaration" class="mdl-tabs__tab is-active">Declaration</a>
+    <a href="#SbWindowSetDefaultOptions-stub" class="mdl-tabs__tab">stub</a>
+  </div>
+  <div class="mdl-tabs__panel is-active" id="SbWindowSetDefaultOptions-declaration">
+<pre>
+SB_EXPORT void SbWindowSetDefaultOptions(SbWindowOptions* options);
+</pre>
+</div>
+  <div class="mdl-tabs__panel" id="SbWindowSetDefaultOptions-stub">
+
+```
+#include "starboard/window.h"
+
+void SbWindowSetDefaultOptions(SbWindowOptions* /*options*/) {
+}
+```
+
+  </div>
+</div>
+
+**Parameters**
+
+
+
+<table class="responsive">
+  <tr><th colspan="2">Parameters</th></tr>
+  <tr>
+    <td><code>SbWindowOptions*</code><br>        <code>options</code></td>
+    <td>The option values to use as default values. This object must not
+be <code>NULL</code>.</td>
+  </tr>
+</table>
+
diff --git a/src/cobalt/site/docs/starboard/porting.md b/src/cobalt/site/docs/starboard/porting.md
new file mode 100644
index 0000000..4ce6cb9
--- /dev/null
+++ b/src/cobalt/site/docs/starboard/porting.md
@@ -0,0 +1,364 @@
+---
+layout: doc
+title: "Porting Cobalt to your Platform with Starboard"
+---
+
+This document provides step-by-step instructions for porting Cobalt to run
+on your platform. To do so, you'll use Starboard, which is Cobalt's porting
+layer and OS abstraction. Starboard encapsulates only the platform-specific
+functionality that Cobalt uses.
+
+To complete a port, you need to add code to the Cobalt source tree. We
+recognize that many porters will not want to actually share details of
+their Starboard implementation with external users. These porters likely
+have their own source control and will fork Cobalt into their software
+configuration management (SCM) tools. These instructions take that use
+case into account and explain how to add your port in a way that will not
+conflict with future Cobalt source code changes.
+
+## Prerequisites
+
+To complete the instructions below, you first need to clone the Cobalt source
+code repository:
+
+```sh
+$ git clone https://cobalt.googlesource.com/cobalt
+```
+
+If you prefer, you can instead complete the instructions for
+[setting up a Cobalt development environment on Linux](
+/cobalt/development/setup-linux.html). Checking out the Cobalt source
+code is one step in that process.
+
+## Porting steps
+
+### 1. Enumerate and name your platform configurations
+
+Your first step is to define canonical names for your set of platform
+configurations. You will later use these names to organize the code
+for your platforms.
+
+A platform configuration has a one-to-one mapping to a production binary.
+As such, you will need to create a new platform configuration any time you
+need to produce a new binary.
+
+A platform configuration name has two components:
+
+*   The `<family-name>` is a name that encompasses a group of products that
+    you are porting to Starboard.
+*   The `<binary-variant>` is a string that uniquely describes specifics
+    of the binary being produced for that configuration.
+
+The recommended naming convention for a platform configuration is:
+
+    <family-name>-<binary-variant>
+
+For example, suppose a company named BobCo produces a variety of BobBox
+devices. Some of the devices use big-endian MIPS chips, while others use
+little-endian MIPS chips. BobCo might define two platform configurations:
+
+*   `bobbox-mipseb`
+*   `bobbox-mipsel`
+
+In this example, `bobbox` is the family name and is used in both (all)
+of BobCo's platform configurations. The `binary-variant` for devices with
+big-endian MIPS chips is `mipseb`. For devices with little-endian MIPS chips,
+the `binary-variant` is `mipsel`.
+
+Starboard also supports sub-variant configurations to maximize your ability
+to share code between configurations. For example, if some of BobCo's devices
+that use little-endian chips use DirectFB, but other devices use OpenGL ES,
+BobCo could create two different configurations for little-endian chips:
+
+*   `bobbox-mipsel-dfb`
+*   `bobbox-mipsel-gles`
+
+### 2. Add Source Tree Directories for your Starboard Port
+
+Add the following directories to the source tree for the `<family-name>`
+that you selected in step 1:
+
+*   `src/third_party/starboard/<family-name>/`
+
+*   `src/third_party/starboard/<family-name>/shared/`
+
+    This subdirectory contains code that is shared between architectures
+    within a product family. For example, if BobBox devices run on many
+    different platforms, then BobCo needs to define a different configuration
+    for each platform. However, if all of the configurations can use the same
+    Starboard function implementation, BobCo can put that function in the
+    `shared` directory to make it accessible in every binary variant.
+
+*   `src/third_party/starboard/<family-name>/<binary-variant>/`
+
+    You should create one directory for _each_ `<binary-variant>`. So, for
+    example, BobCo could create the following directories:
+
+    *   `src/third_party/starboard/bobbox/shared/`
+    *   `src/third_party/starboard/bobbox/mipseb/`
+    *   `src/third_party/starboard/bobbox/mipsel/`
+    *   `src/third_party/starboard/bobbox/mipsel/dfb/`
+    *   `src/third_party/starboard/bobbox/mipsel/gles/`
+
+Again, functions that work for all of the configurations would go in the
+`shared` directory. Functions that work for all little-endian devices would go
+in the `mipsel` directory. And functions specific to little-endian devices
+that use DirectFB or that use OpenGL ES would go in the `mipsel/dfb` or
+`mipsel/gles` directory.
+
+### 3. Add required `binary-variant` files
+
+Each `binary-variant` directory that you created in step 2 must contain
+the following files:
+
+*   `atomic_public.h`
+*   `configuration_public.h`
+*   `gyp_configuration.gypi`
+*   `gyp_configuration.py`
+*   `starboard_platform.gyp`
+*   `thread_types_public.h`
+
+We recommend that you copy the files from the Stub reference implementation,
+located at `src/third_party/stub/` to your `binary-variant` directories.
+In this approach, you will essentially start with a clean slate of stub
+interfaces that need to be modified to work with your platform.
+
+An alternate approach is to copy either the Desktop Linux or Raspberry Pi
+ports and then work backward to fix the things that don't compile or work
+on your platform.
+
+If you are copying the Stub implementation, you would run the following
+command for each `binary-variant` directory:
+
+```sh
+cp -R src/starboard/stub
+      src/third_party/starboard/<family-name>/<binary-variant>
+```
+
+After copying these files, you should be able to compile Cobalt and link it
+with your toolchain even though the code itself will not yet work.
+
+
+#### 3a. Additional files in the stub implementation
+
+The stub implementation contains three additional files that are not listed
+among the required files for each `binary-variant` directory:
+
+*   `application_stub.cc`
+*   `application_stub.h`
+*   `main.cc`
+
+The Starboard `Application` class is designed to do the following:
+
+*   Integrate a generic message loop function with a system message pump that
+    can deliver either input or application lifecycle events like
+    suspend/resume.
+*   Provide a place for graceful platform-specific initialization and teardown.
+*   Provide a universally accessible place to store global platform-specific
+    state, such as managed UI windows.
+
+Thus, these files provide a framework for fulfilling Starboard's event
+dispatching requirements, even though they don't implement any specific
+Starboard interface and aren't strictly necessary for any given port. Even so,
+anyone who is porting Cobalt will likely need to adapt a copy of
+`application_stub.cc` and `application_stub.h` to their platforms needs.
+
+The `application` files do not necessarily need to be per-variant files. Even
+if you have multiple variants, it's still possible that you only need one copy
+of these files in your `shared` directory. Similarly, you might have a shared
+base class along with variant-specific subclasses.
+
+### 4. Make required file modifications
+
+To port your code, you must make the following modifications to the files
+that you copied in step 3:
+
+
+1.  **`atomic_public.h`** - Ensure that this file points at the appropriate
+    shared or custom implementation.
+
+1.  **`configuration_public.h`** - Adjust all of the [configuration values](
+    ../../reference/starboard/configuration-public.html) as appropriate for
+    your platform.
+
+1.  **`gyp_configuration.py`**
+    1.  Modify the `CreatePlatformConfig()` function to return the platform
+        configuration that you defined in step 1. The example below shows that
+        function as it appears in the Stub implementation and the Desktop
+        Linux port:
+
+        <pre>
+        # Stub:
+        def CreatePlatformConfig():
+          try:
+            return PlatformConfig('<b>stub</b>')
+          except RuntimeError as e:
+            logging.critical(e)
+            return None
+
+        # Desktop Linux
+        def CreatePlatformConfig():
+          try:
+            return gyp_configuration.PlatformConfig('<b>linux-x64x11</b>')
+          except RuntimeError as e:
+            logging.critical(e)
+            return None
+        </pre>
+
+        Note that the third line is the only one that is different. The
+        key difference in terms of these instructions is changing `stub`
+        to `linux-x64x11`. The Desktop Linux port also uses a shared copy
+        of `gyp_configuration.py`, which is why the rest of the line is
+        different.
+
+    1.  In the `GetVariables` function, ensure that the `clang` variable
+        is set to `1` if your toolchain uses clang:
+
+        <pre>
+        variables = super(PlatformConfig, self).GetVariables(configuration)
+        <b>variables.update({'clang': 1,})</b>
+        return variables
+        </pre>
+
+    1.  In the `GetEnvironmentVariables` function, set these dictionary values
+        to the toolchain analogs for your platform. Note that "target platform"
+        refers to the platform being targeted by the port (e.g. Android TV,
+        Raspberry Pi) and "host platform" is the workstation platform running
+        the cross-compiler to the target (e.g. desktop Linux, desktop Windows).
+        *   `CC` - the C compiler for the target platform. Example: `clang`.
+        *   `CXX` - the C++ compiler for the target platform.
+            Example: `clang++`.
+        *   `CC_HOST` - the C compiler for the host platform. Example: `clang`.
+        *   `CXX_HOST` - the C++ compiler for the host platform.
+            Example: `clang++`.
+        *   `LD_HOST` - the C++ linker for the host platform.
+            Example: `clang++`.
+        *   `ARFLAGS_HOST` - Archiver flags for the host platform. The
+            archiver is the toolchain program that creates static libraries.
+            Example: `rcs`.
+        *   `ARTHINFLAGS_HOST` - Archiver flags for the host platform for
+            creating "thin" archives, which are faster for intermediate
+            libraries that aren't for direct publishing. Example: `rcsT`.
+
+1.  **`gyp_configuration.gypi`**
+    1.  Update the value of the `default_configuration` property and the keys
+        in the `configurations` property to be
+        `<platform-configuration>_<build-type>` where:
+        1.  `<platform-configuration>` is the value that you defined in step 1.
+        1.  `<build-type>` is one of the following values:
+            *   `debug`
+            *   `devel`
+            *   `qa`
+            *   `gold`
+
+        The following snippet from the configuration file shows how these
+        properties appear in the Stub implementation. The Desktop Linux port
+        replaces the string `stub` with `linux-x64x11` everywhere that it
+        appears:
+
+        ```
+        'target_defaults': {
+          'default_configuration': 'stub_debug',
+          'configurations': {
+            'stub_debug': {
+              'inherit_from': ['debug_base'],
+            },
+            'stub_devel': {
+              'inherit_from': ['devel_base'],
+            },
+            'stub_qa': {
+              'inherit_from': ['qa_base'],
+            },
+            'stub_gold': {
+              'inherit_from': ['gold_base'],
+            },
+          }, # end of configurations
+          ...
+        }
+        ```
+
+    1.  Update the following properties in the `variables` dictionary:
+        *   `target_arch` - Identifies your architecture. Supported values
+            are `arm`, `mips`, `ppc`, `x64`, and `x86`.
+        *   `target_os` - Set to `linux` if your platform is Linux-based.
+            Otherwise, remove this variable.
+        *   `gl_type` - Set to `system_gles2` if you are using the system EGL
+            + GLES2 implementation or to `system_gles3` if you are using the
+            system EGL + GLES3 implementation. Otherwise, set the value to
+            `none`.
+        *   `in_app_dial` - Enables (or disables) the DIAL server that runs
+            inside Cobalt. (This server only runs when Cobalt is running.)
+            The [DIAL protocol](http://www.dial-multiscreen.org/home) enables
+            second-screen devices (like tablets and phones) to discover,
+            launch, and interface with applications on first-screen devices
+            (like televisions, set-top boxes, and Blu-ray players).
+            *   Set this value to `0` if you already have system-wide DIAL
+                support. In that case, a DIAL server running inside Cobalt would
+                be redundant.
+            *   Set this value to `1` if you want Cobalt to run a DIAL server
+                whenever it is running. That server could only be used to
+                connect with the current Cobalt application (e.g. YouTube).
+
+
+    1.  Update your toolchain command-line flags and libraries. Ensure that
+        you do not assume a particular workstation layout since that layout
+        may vary from user to user.
+
+    1.  Update the global defines in the `target_defaults.defines` dictionary,
+        if necessary.
+
+1.  **`thread_types_public.h`** - Ensure that this file points at the
+    appropriate shared or custom implementation.
+
+### 5. Port modules to work on your platform
+
+The `starboard_platform.gyp` file points to all of the source files included
+in your new Starboard implementation. If you are starting with a copy of the
+Stub implementation, then that file will initially include a lot of files
+from the `src/starboard/shared/stub/` directory. Similarly, if you are starting
+starting with a copy of the Desktop Linux port, then that file will initially
+point to files in the `src/starboard/shared/posix` directory.
+
+The modules are defined so that each one has a set of functions, and each
+function is defined in its own file with a consistent naming convention.
+For example, the `SbSystemBreakIntoDebugger()` function is defined in the
+`system_break_into_debugger.cc` file. The list of files in the
+`src/starboard/shared/stub/` directory represents an authoritative list of
+supported functions.
+
+Function-by-function and module-by-module, you can now replace stub
+implementations with either custom implementations or with other ported
+implementations from the `src/starboard/shared/` directory until you have
+gone through all of the modules. As you do, update the
+`starboard_platform.gyp` file to identify the appropriate source files.
+
+Due to dependencies between modules, you will find it easier to get some
+modules to pass the NPLB tests before other modules. We recommend porting
+modules in the following order to account for such dependencies:
+
+1.  Configuration
+1.  main(), Application, and Event Pump - This is the call into `SbEventHandle`.
+1.  Memory
+1.  Byte Swap
+1.  Time
+1.  String/Character/Double
+1.  Log
+1.  File
+1.  Directory
+1.  System
+1.  Atomic
+1.  Thread & Thread Types
+1.  Mutex
+1.  Condition Variable
+1.  Once
+1.  Socket
+1.  SocketWaiter
+1.  Window
+1.  Input
+1.  Blitter (if applicable)
+1.  Audio Sink
+1.  Media & Player
+1.  DRM
+1.  TimeZone
+1.  User
+1.  Storage
diff --git a/src/cobalt/site/docs/starboard/testing.md b/src/cobalt/site/docs/starboard/testing.md
new file mode 100644
index 0000000..6af1b9b
--- /dev/null
+++ b/src/cobalt/site/docs/starboard/testing.md
@@ -0,0 +1,39 @@
+---
+layout: doc
+title: "Testing"
+---
+
+Starboard attempts to make the porting process as easy as possible. To that
+end, Starboard provides a compliance test suite, called NPLB
+(No Platform Left Behind), that porters can use to gauge their progress.
+
+## Current State
+
+All of the APIs that Cobalt defines are at least called by NPLB, and most of
+those APIs are verified in one way or another. The APIs that are most likely
+to just be implemented by a single system call, such as the Starboard functions
+defined in [string.h](modules/string.md) and [memory.h](modules/memory.md)
+are not exhaustively tested.
+
+NPLB tests must work on all Starboard implementations, so they may make no
+assumptions about platform-specific details. Rather, they attempt to define
+a living contract for the APIs on all platforms.
+
+## Test Organization
+
+NPLB tests can be found in the `src/starboard/nplb/` directory and are broken
+out into files by Starboard module and function:
+
+```
+src/starboard/nplb/<module>_<function>_test.cc
+```
+
+Although each test may incidentally test other functions, there is an attempt
+to keep things as self-contained as possible within a function and module.
+At the same time, the tests also aim to avoid avoid testing behavior that is
+effectively tested as part of another test.
+
+For example, the `SbSocketSendTo` and `SbSocketReceiveFrom` are tested
+together, ensuring that the API is self-consistent on both sides of a
+connection. Therefore, only one set of tests exist to cover those use cases,
+in `src/starboard/nplb/socket_receive_from_test.cc`.
diff --git a/src/cobalt/site/images/cobalt-logo.png b/src/cobalt/site/images/cobalt-logo.png
new file mode 100644
index 0000000..513409c
--- /dev/null
+++ b/src/cobalt/site/images/cobalt-logo.png
Binary files differ
diff --git a/src/cobalt/site/images/cobalt-word-logo.png b/src/cobalt/site/images/cobalt-word-logo.png
new file mode 100644
index 0000000..94bf5c9
--- /dev/null
+++ b/src/cobalt/site/images/cobalt-word-logo.png
Binary files differ
diff --git a/src/cobalt/site/images/favicon.ico b/src/cobalt/site/images/favicon.ico
new file mode 100644
index 0000000..90d1722
--- /dev/null
+++ b/src/cobalt/site/images/favicon.ico
Binary files differ
diff --git a/src/cobalt/speech/sandbox/speech_sandbox.cc b/src/cobalt/speech/sandbox/speech_sandbox.cc
index 29b09c5..f5db2a9 100644
--- a/src/cobalt/speech/sandbox/speech_sandbox.cc
+++ b/src/cobalt/speech/sandbox/speech_sandbox.cc
@@ -75,7 +75,7 @@
     const dom::DOMSettings::Options& dom_settings_options) {
   scoped_ptr<script::EnvironmentSettings> environment_settings(
       new dom::DOMSettings(kDOMMaxElementDepth, NULL, network_module_.get(),
-                           NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                           NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                            dom_settings_options));
   DCHECK(environment_settings);
 
diff --git a/src/cobalt/system_window/system_window.cc b/src/cobalt/system_window/system_window.cc
index 7b2529e..61d3b47 100644
--- a/src/cobalt/system_window/system_window.cc
+++ b/src/cobalt/system_window/system_window.cc
@@ -211,6 +211,10 @@
   }
 }
 
+SystemWindow* SystemWindow::PrimaryWindow() {
+  return g_the_window;
+}
+
 void HandleInputEvent(const SbEvent* event) {
   if (event->type != kSbEventTypeInput) {
     return;
diff --git a/src/cobalt/system_window/system_window.h b/src/cobalt/system_window/system_window.h
index 121313c..613b3e4 100644
--- a/src/cobalt/system_window/system_window.h
+++ b/src/cobalt/system_window/system_window.h
@@ -59,6 +59,11 @@
   // Handles a single Starboard input event, dispatching any appropriate events.
   void HandleInputEvent(const SbInputData& data);
 
+  // Returns the primary SystemWindow currently in use by the application.
+  // Only one SystemWindow is currently supported, and this method will return
+  // that window, or |nullptr| if it does not exist.
+  static SystemWindow* PrimaryWindow();
+
  private:
   void UpdateModifiers(SbKey key, bool pressed);
   InputEvent::Modifiers GetModifiers();
diff --git a/src/cobalt/tools/webdriver_benchmark_config.py b/src/cobalt/tools/webdriver_benchmark_config.py
new file mode 100644
index 0000000..5b920ed
--- /dev/null
+++ b/src/cobalt/tools/webdriver_benchmark_config.py
@@ -0,0 +1,35 @@
+#
+# Copyright 2017 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.
+"""Class for configuring Webdriver Benchmarks."""
+
+
+PERFORMANCE_TEST = 'performance'
+SANITY_TEST = 'sanity'
+
+# WEBDRIVER SCRIPT CONFIGURATION PARAMETERS
+MINIMAL_SIZE = 'minimal'
+REDUCED_SIZE = 'reduced'
+STANDARD_SIZE = 'standard'
+
+DISABLE_VIDEOS = '--disable_videos'
+
+SAMPLE_SIZES = [
+    MINIMAL_SIZE,
+    REDUCED_SIZE,
+    STANDARD_SIZE
+]
+
+# COBALT COMMAND LINE PARAMETERS
+DISABLE_SPLASH_SCREEN_ON_RELOADS = '--disable_splash_screen_on_reloads'
diff --git a/src/cobalt/webdriver/script_executor.cc b/src/cobalt/webdriver/script_executor.cc
index 1bbcaf3..609fbc3 100644
--- a/src/cobalt/webdriver/script_executor.cc
+++ b/src/cobalt/webdriver/script_executor.cc
@@ -81,8 +81,8 @@
 
   // Evaluate the harness initialization script.
   std::string result;
-  if (!global_environment->EvaluateScript(source, &result,
-                                          false /*mute_errors*/)) {
+  if (!global_environment->EvaluateScript(source, false /*mute_errors*/,
+                                          &result)) {
     return NULL;
   }
 
diff --git a/src/cobalt/webdriver/script_executor_params.cc b/src/cobalt/webdriver/script_executor_params.cc
index 262ecc7..b00e7e6 100644
--- a/src/cobalt/webdriver/script_executor_params.cc
+++ b/src/cobalt/webdriver/script_executor_params.cc
@@ -40,8 +40,8 @@
           function.c_str(), base::SourceLocation("[webdriver]", 1, 1));
 
   if (!global_environment->EvaluateScript(function_source, params.get(),
-                                          &params->function_object_,
-                                          false /*mute_errors*/)) {
+                                          false /*mute_errors*/,
+                                          &params->function_object_)) {
     DLOG(ERROR) << "Failed to create Function object";
   }
   return {params, global_environment.get()};
diff --git a/src/cobalt/websocket/web_socket_test.cc b/src/cobalt/websocket/web_socket_test.cc
index d2803e7..bdb2e6a 100644
--- a/src/cobalt/websocket/web_socket_test.cc
+++ b/src/cobalt/websocket/web_socket_test.cc
@@ -39,7 +39,7 @@
  public:
   FakeSettings()
       : dom::DOMSettings(0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                         NULL, NULL),
+                         NULL),
         base_("https://example.com") {
     this->set_network_module(NULL);
   }
diff --git a/src/cobalt/xhr/xml_http_request.cc b/src/cobalt/xhr/xml_http_request.cc
index 7b7d15e..af1bdf9 100644
--- a/src/cobalt/xhr/xml_http_request.cc
+++ b/src/cobalt/xhr/xml_http_request.cc
@@ -909,6 +909,7 @@
 
 void XMLHttpRequest::TerminateRequest() {
   error_ = true;
+  corspreflight_.reset(NULL);
   url_fetcher_.reset(NULL);
 }
 
@@ -920,7 +921,7 @@
       << __FUNCTION__ << " (" << RequestErrorTypeName(request_error_type)
       << ") " << *this << std::endl
       << script::StackTraceToString(
-             settings_->global_environment()->GetStackTrace());
+             settings_->global_environment()->GetStackTrace(0 /*max_frames*/));
   stop_timeout_ = true;
   // Step 1
   TerminateRequest();
@@ -1136,10 +1137,7 @@
 }
 
 void XMLHttpRequest::CORSPreflightSuccessCallback() {
-  if (!url_fetcher_) {
-    HandleRequestError(XMLHttpRequest::kNetworkError);
-  } else {
-    DCHECK(url_fetcher_);
+  if (url_fetcher_) {
     url_fetcher_->Start();
   }
 }
diff --git a/src/cobalt/xhr/xml_http_request_test.cc b/src/cobalt/xhr/xml_http_request_test.cc
index 5863f7f..329e9e8 100644
--- a/src/cobalt/xhr/xml_http_request_test.cc
+++ b/src/cobalt/xhr/xml_http_request_test.cc
@@ -94,7 +94,7 @@
  public:
   FakeSettings()
       : dom::DOMSettings(0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                         NULL, NULL),
+                         NULL),
         example_("http://example.com") {}
   const GURL& base_url() const OVERRIDE { return example_; }
 
diff --git a/src/starboard/CHANGELOG.md b/src/starboard/CHANGELOG.md
index 4bf24e5..174eff4 100644
--- a/src/starboard/CHANGELOG.md
+++ b/src/starboard/CHANGELOG.md
@@ -8,6 +8,17 @@
 
 **NOTE: Starboard versions 3 and below are no longer supported.**
 
+## Version 8
+
+### Add SbPlayerCreateWithUrl(), SbPlayerSetDrmSystem(), SbPlayerOutputModeSupportedWithUrl()
+
+For platform media players that rely on using a URL (like an m3u playlist URL)
+for playback, add SbPlayerCreateWithUrl() which takes in a URL, no video or audio
+configs, and no DRM system. Allow the DRM system to be set on a running SbPlayer
+exactly once for SbPlayers created with a URL. Also, since URL players will not
+expose codec information, use a custom SbPlayerOutputModeSupportedWithUrl() to
+query player output mode support.
+
 ## Version 7
 
 ### `SbDecodeTargetInfoPlane` can specify color plane information
diff --git a/src/starboard/README.md b/src/starboard/README.md
index 9f2d47f..c5f3be7 100644
--- a/src/starboard/README.md
+++ b/src/starboard/README.md
@@ -14,22 +14,27 @@
 now.
 
 
+## Documentation
+
+See [`src/starboard/doc`](doc) for more detailed documentation.
+
+
 ## Interesting Source Locations
 
 All source locations are specified relative to `src/starboard/` (this directory).
 
-  * `.` - This is the root directory for the Starboard project, and contains all
-    the public headers that Starboard defines.
-  * `examples/` - Example code demonstrating various aspects of Starboard API
-    usage.
-  * `stub/` - The home of the Stub Starboard implementation. This contains a
-    `starboard_platform.gyp` file that defines a library with all the source
-    files needed to provide a complete linkable Starboard implementation.
-  * `nplb/` - "No Platform Left Behind," Starboard's platform verification test
-    suite.
-  * `shared/` - The home of all code that can be shared between Starboard
-    implementations. Subdirectories delimit code that can be shared between
-    platforms that share some facet of their OS API.
+  * [`.`](.) - This is the root directory for the Starboard project, and
+    contains all the public headers that Starboard defines.
+  * [`examples/`](examples) - Example code demonstrating various aspects of
+    Starboard API usage.
+  * [`stub/`](stub) - The home of the Stub Starboard implementation. This
+    contains a `starboard_platform.gyp` file that defines a library with all the
+    source files needed to provide a complete linkable Starboard implementation.
+  * [`nplb/`](nplb) - "No Platform Left Behind," Starboard's platform
+    verification test suite.
+  * [`shared/`](shared) - The home of all code that can be shared between
+    Starboard implementations. Subdirectories delimit code that can be shared
+    between platforms that share some facet of their OS API.
 
 
 ## Quick Guide to Starting a Port
diff --git a/src/starboard/common/common.cc b/src/starboard/common/common.cc
index 82102fb..acf6e63 100644
--- a/src/starboard/common/common.cc
+++ b/src/starboard/common/common.cc
@@ -23,7 +23,8 @@
     "own risk!  We don't recommend this for third parties.")
 #endif
 
-#if SB_API_VERSION >= SB_RELEASE_CANDIDATE_API_VERSION && \
+#if defined(SB_RELEASE_CANDIDATE_API_VERSION) && \
+    SB_API_VERSION >= SB_RELEASE_CANDIDATE_API_VERSION && \
     SB_API_VERSION < SB_EXPERIMENTAL_API_VERSION
 #pragma message( \
     "Your platform's SB_API_VERSION >= SB_RELEASE_CANDIDATE_API_VERSION. " \
diff --git a/src/starboard/configuration.h b/src/starboard/configuration.h
index 057bb38..7962f1f 100644
--- a/src/starboard/configuration.h
+++ b/src/starboard/configuration.h
@@ -53,7 +53,8 @@
 // changes. It is reasonable to base a port on the Release Candidate API
 // version, but be aware that small incompatible changes may still be made to
 // it.
-#define SB_RELEASE_CANDIDATE_API_VERSION 7
+// The following will be uncommented when an API version is a release candidate.
+// #define SB_RELEASE_CANDIDATE_API_VERSION 8
 
 // --- Experimental Feature Defines ------------------------------------------
 
@@ -67,8 +68,9 @@
 //   //   exposes functionality for my new feature.
 //   #define SB_MY_EXPERIMENTAL_FEATURE_VERSION SB_EXPERIMENTAL_API_VERSION
 
+#define SB_PLAYER_WITH_URL_API_VERSION SB_EXPERIMENTAL_API_VERSION
+
 // --- Release Candidate Feature Defines -------------------------------------
-#define SB_DECODE_TARGET_PLANE_FORMAT_VERSION SB_RELEASE_CANDIDATE_API_VERSION
 
 // --- Common Detected Features ----------------------------------------------
 
@@ -459,11 +461,15 @@
 #error "Your platform must define SB_HAS_TIME_THREAD_NOW in API 3 or later."
 #endif
 
-#if defined(SB_IS_PLAYER_COMPOSITITED) || defined(SB_IS_PLAYER_PUNCHED_OUT) || \
+#if defined(SB_IS_PLAYER_COMPOSITED) || defined(SB_IS_PLAYER_PUNCHED_OUT) || \
     defined(SB_IS_PLAYER_PRODUCING_TEXTURE)
 #error "New versions of Starboard specify player output mode at runtime."
 #endif
 
+#if SB_HAS(PLAYER_WITH_URL) && SB_API_VERSION < SB_PLAYER_WITH_URL_API_VERSION
+#error "SB_HAS_PLAYER_WITH_URL is not supported in this API version."
+#endif
+
 #if (SB_HAS(MANY_CORES) && (SB_HAS(1_CORE) || SB_HAS(2_CORES) ||    \
                             SB_HAS(4_CORES) || SB_HAS(6_CORES))) || \
     (SB_HAS(1_CORE) &&                                              \
diff --git a/src/starboard/decode_target.h b/src/starboard/decode_target.h
index 2bb46e5..1badf86 100644
--- a/src/starboard/decode_target.h
+++ b/src/starboard/decode_target.h
@@ -251,14 +251,14 @@
   // that it be set to something else like GL_TEXTURE_EXTERNAL_OES.
   uint32_t gl_texture_target;
 
-#if SB_API_VERSION >= SB_DECODE_TARGET_PLANE_FORMAT_VERSION
+#if SB_API_VERSION >= 7
   // For kSbDecodeTargetFormat2PlaneYUVNV12 planes: the format of the
   // texture. Usually, for the luma plane, this is either GL_ALPHA or
   // GL_RED_EXT. For the chroma plane, this is usually GL_LUMINANCE_ALPHA
   // or GL_RG_EXT.
   // Ignored for other plane types.
   uint32_t gl_texture_format;
-#endif  // SB_API_VERSION >= SB_DECODE_TARGET_NV12_R_RG_API_VERSION
+#endif  // SB_API_VERSION >= 7
 
 #endif  // SB_HAS(BLITTER)
 
diff --git a/src/starboard/linux/shared/BUILD.gn b/src/starboard/linux/shared/BUILD.gn
index 69a8502..9de47d9 100644
--- a/src/starboard/linux/shared/BUILD.gn
+++ b/src/starboard/linux/shared/BUILD.gn
@@ -486,6 +486,9 @@
     "//starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc",
     "//starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h",
     "//starboard/shared/starboard/player/filter/audio_renderer_internal.h",
+    "//starboard/shared/starboard/player/filter/audio_renderer_sink.h",
+    "//starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc",
+    "//starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h",
     "//starboard/shared/starboard/player/filter/audio_time_stretcher.cc",
     "//starboard/shared/starboard/player/filter/audio_time_stretcher.h",
     "//starboard/shared/starboard/player/filter/decoded_audio_queue.cc",
diff --git a/src/starboard/linux/shared/gyp_configuration.py b/src/starboard/linux/shared/gyp_configuration.py
index 212a904..af21937 100644
--- a/src/starboard/linux/shared/gyp_configuration.py
+++ b/src/starboard/linux/shared/gyp_configuration.py
@@ -63,6 +63,9 @@
     launcher_module = imp.load_source('launcher', module_path)
     return launcher_module
 
+  def WebdriverBenchmarksEnabled(self):
+    return True
+
   def GetTestFilters(self):
     """Gets all tests to be excluded from a unit test run.
 
diff --git a/src/starboard/linux/shared/launcher.py b/src/starboard/linux/shared/launcher.py
index fa70644..d1f3872 100644
--- a/src/starboard/linux/shared/launcher.py
+++ b/src/starboard/linux/shared/launcher.py
@@ -38,19 +38,16 @@
 class Launcher(abstract_launcher.AbstractLauncher):
   """Class for launching Cobalt/tools on Linux."""
 
-  def __init__(self, platform, target_name, config, device_id, args,
-               output_file, out_directory):
+  def __init__(self, platform, target_name, config, device_id, **kwargs):
     super(Launcher, self).__init__(platform, target_name, config, device_id,
-                                   args, output_file, out_directory)
+                                   **kwargs)
     if not self.device_id:
       if socket.has_ipv6:  #  If the device supports IPv6:
         self.device_id = "::1"  #  Use the only IPv6 loopback address
       else:
         self.device_id = socket.gethostbyname("localhost")
 
-    self.executable = abstract_launcher.GetDefaultTargetPath(
-        platform, config, target_name)
-
+    self.executable = self.GetTargetPath()
     self.pid = None
 
   def Run(self):
@@ -67,5 +64,5 @@
     if self.pid:
       try:
         os.kill(self.pid, signal.SIGTERM)
-      except OSError:  # Process is already dead
-        raise OSError("Process already closed.")
+      except OSError as e:
+        sys.stderr.write("Cannot kill launcher.  Process already closed.\n")
diff --git a/src/starboard/linux/shared/player_components_impl.cc b/src/starboard/linux/shared/player_components_impl.cc
index 49c8850..53b0e45 100644
--- a/src/starboard/linux/shared/player_components_impl.cc
+++ b/src/starboard/linux/shared/player_components_impl.cc
@@ -19,6 +19,7 @@
 #include "starboard/shared/ffmpeg/ffmpeg_video_decoder.h"
 #include "starboard/shared/libvpx/vpx_video_decoder.h"
 #include "starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h"
 #include "starboard/shared/starboard/player/filter/video_renderer_impl_internal.h"
 
 namespace starboard {
@@ -67,9 +68,10 @@
     video_decoder.reset(ffmpeg_video_decoder);
   }
 
-  AudioRendererImpl* audio_renderer =
-      new AudioRendererImpl(scoped_ptr<AudioDecoder>(audio_decoder).Pass(),
-                            audio_parameters.audio_header);
+  AudioRendererImpl* audio_renderer = new AudioRendererImpl(
+      make_scoped_ptr<AudioDecoder>(audio_decoder),
+      make_scoped_ptr<AudioRendererSink>(new AudioRendererSinkImpl),
+      audio_parameters.audio_header);
   VideoRendererImpl* video_renderer =
       new VideoRendererImpl(video_decoder.Pass());
 
diff --git a/src/starboard/linux/shared/starboard_platform.gypi b/src/starboard/linux/shared/starboard_platform.gypi
index 8c4aee7..f22145a 100644
--- a/src/starboard/linux/shared/starboard_platform.gypi
+++ b/src/starboard/linux/shared/starboard_platform.gypi
@@ -241,6 +241,9 @@
       '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc',
       '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h',
       '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.h',
+      '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink.h',
+      '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h',
       '<(DEPTH)/starboard/shared/starboard/player/filter/audio_time_stretcher.cc',
       '<(DEPTH)/starboard/shared/starboard/player/filter/audio_time_stretcher.h',
       '<(DEPTH)/starboard/shared/starboard/player/filter/decoded_audio_queue.cc',
diff --git a/src/starboard/linux/x64directfb/gyp_configuration.gypi b/src/starboard/linux/x64directfb/gyp_configuration.gypi
index 98b7048..7005f6f 100644
--- a/src/starboard/linux/x64directfb/gyp_configuration.gypi
+++ b/src/starboard/linux/x64directfb/gyp_configuration.gypi
@@ -24,11 +24,6 @@
     ],
 
     'gl_type': 'none',
-
-    # This should have a default value in cobalt/base.gypi. See the comment
-    # there for acceptable values for this variable.
-    'javascript_engine': 'mozjs-45',
-    'cobalt_enable_jit': 0,
   },
 
   'target_defaults': {
diff --git a/src/starboard/linux/x64directfb/gyp_configuration.py b/src/starboard/linux/x64directfb/gyp_configuration.py
index 483e5dd..4f6ddc5 100644
--- a/src/starboard/linux/x64directfb/gyp_configuration.py
+++ b/src/starboard/linux/x64directfb/gyp_configuration.py
@@ -56,5 +56,5 @@
         test_filter.TestFilter(
             'web_platform_tests', 'streams/WebPlatformTest.Run/11', 'debug'),
         test_filter.TestFilter(
-            'starboard_platform_tests', test_filter.FILTER_ALL, 'debug')
+            'starboard_platform_tests', test_filter.FILTER_ALL)
     ]
diff --git a/src/starboard/linux/x64directfb/starboard_platform.gypi b/src/starboard/linux/x64directfb/starboard_platform.gypi
index d38e23c..3ac3e76 100644
--- a/src/starboard/linux/x64directfb/starboard_platform.gypi
+++ b/src/starboard/linux/x64directfb/starboard_platform.gypi
@@ -58,6 +58,7 @@
         '<(DEPTH)/starboard/shared/directfb/window_internal.cc',
         '<(DEPTH)/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc',
         '<(DEPTH)/starboard/shared/starboard/blitter_blit_rects_to_rects.cc',
+        '<(DEPTH)/starboard/shared/stub/player_create_with_url.cc',
     ],
   },
 }
diff --git a/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.gypi b/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.gypi
index f1961e0..4b85d62 100644
--- a/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.gypi
@@ -14,10 +14,6 @@
 
 {
   'variables': {
-    # This should have a default value in cobalt/base.gypi. See the comment
-    # there for acceptable values for this variable.
-    'javascript_engine': 'mozjs-45',
-    'cobalt_enable_jit': 0,
     'linker_flags!': [
             '-Wl,--wrap=malloc',
             '-Wl,--wrap=free',
diff --git a/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.gypi b/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.gypi
index e781887..dc9ec62 100644
--- a/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.gypi
@@ -13,12 +13,6 @@
 # limitations under the License.
 
 {
-  'variables': {
-    # This should have a default value in cobalt/base.gypi. See the comment
-    # there for acceptable values for this variable.
-    'javascript_engine': 'mozjs-45',
-    'cobalt_enable_jit': 0,
-  },
   'target_defaults': {
     'default_configuration': 'linux-x64x11-gcc-6-3_debug',
     'configurations': {
diff --git a/src/starboard/linux/x64x11/gyp_configuration.gypi b/src/starboard/linux/x64x11/gyp_configuration.gypi
index 0521206..1f18553 100644
--- a/src/starboard/linux/x64x11/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/gyp_configuration.gypi
@@ -14,10 +14,6 @@
 
 {
   'variables': {
-    # This should have a default value in cobalt/base.gypi. See the comment
-    # there for acceptable values for this variable.
-    'javascript_engine': 'mozjs-45',
-    'cobalt_enable_jit': 0,
     'enable_map_to_mesh%': 1,
   },
   'target_defaults': {
diff --git a/src/starboard/linux/x64x11/mock/gyp_configuration.gypi b/src/starboard/linux/x64x11/mock/gyp_configuration.gypi
index f76e9ea..ed8ff0f 100644
--- a/src/starboard/linux/x64x11/mock/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/mock/gyp_configuration.gypi
@@ -22,12 +22,6 @@
     # No GL drivers available.
     'gl_type': 'none',
 
-    # This should have a default value in cobalt/base.gypi. See the comment
-    # there for acceptable values for this variable.
-    'javascript_engine': 'mozjs-45',
-
-    'cobalt_enable_jit': 0,
-
     'cobalt_media_source_2016': 1,
     'cobalt_encrypted_media_extension_enable_key_statuses_update': 0,
 
diff --git a/src/starboard/linux/x64x11/v8/atomic_public.h b/src/starboard/linux/x64x11/v8/atomic_public.h
new file mode 100644
index 0000000..ac3dc77
--- /dev/null
+++ b/src/starboard/linux/x64x11/v8/atomic_public.h
@@ -0,0 +1,20 @@
+// Copyright 2017 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.
+
+#ifndef STARBOARD_LINUX_X64X11_V8_ATOMIC_PUBLIC_H_
+#define STARBOARD_LINUX_X64X11_V8_ATOMIC_PUBLIC_H_
+
+#include "starboard/linux/shared/atomic_public.h"
+
+#endif  // STARBOARD_LINUX_X64X11_V8_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/v8/configuration_public.h b/src/starboard/linux/x64x11/v8/configuration_public.h
new file mode 100644
index 0000000..d408b03
--- /dev/null
+++ b/src/starboard/linux/x64x11/v8/configuration_public.h
@@ -0,0 +1,24 @@
+// Copyright 2017 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.
+
+// The Starboard configuration for Desktop X86 Linux configured for the future
+// starboard API.
+
+#ifndef STARBOARD_LINUX_X64X11_V8_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_LINUX_X64X11_V8_CONFIGURATION_PUBLIC_H_
+
+// Include the X64X11 Linux configuration.
+#include "starboard/linux/x64x11/configuration_public.h"
+
+#endif  // STARBOARD_LINUX_X64X11_V8_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/v8/gyp_configuration.gypi b/src/starboard/linux/x64x11/v8/gyp_configuration.gypi
new file mode 100644
index 0000000..28d6ee5
--- /dev/null
+++ b/src/starboard/linux/x64x11/v8/gyp_configuration.gypi
@@ -0,0 +1,41 @@
+# Copyright 2017 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.
+
+{
+  'variables': {
+    'javascript_engine': 'v8',
+    'cobalt_enable_jit': 1,
+  },
+  'target_defaults': {
+    'default_configuration': 'linux-x64x11-v8_debug',
+    'configurations': {
+      'linux-x64x11-v8_debug': {
+        'inherit_from': ['debug_base'],
+      },
+      'linux-x64x11-v8_devel': {
+        'inherit_from': ['devel_base'],
+      },
+      'linux-x64x11-v8_qa': {
+        'inherit_from': ['qa_base'],
+      },
+      'linux-x64x11-v8_gold': {
+        'inherit_from': ['gold_base'],
+      },
+    }, # end of configurations
+  },
+
+  'includes': [
+    '../gyp_configuration.gypi',
+  ],
+}
diff --git a/src/starboard/linux/x64x11/v8/gyp_configuration.py b/src/starboard/linux/x64x11/v8/gyp_configuration.py
new file mode 100644
index 0000000..7488433
--- /dev/null
+++ b/src/starboard/linux/x64x11/v8/gyp_configuration.py
@@ -0,0 +1,27 @@
+# Copyright 2017 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.
+"""Starboard Linux X64 X11 V8 platform configuration for gyp_cobalt."""
+
+import logging
+
+# Import the shared Linux platform configuration.
+from starboard.linux.shared import gyp_configuration
+
+
+def CreatePlatformConfig():
+  try:
+    return gyp_configuration.PlatformConfig('linux-x64x11-v8')
+  except RuntimeError as e:
+    logging.critical(e)
+    return None
diff --git a/src/starboard/linux/x64x11/v8/starboard_platform.gyp b/src/starboard/linux/x64x11/v8/starboard_platform.gyp
new file mode 100644
index 0000000..42b0bf5
--- /dev/null
+++ b/src/starboard/linux/x64x11/v8/starboard_platform.gyp
@@ -0,0 +1,33 @@
+# Copyright 2017 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.
+{
+  'includes': [
+    '../starboard_platform.gypi'
+  ],
+  'targets': [
+    {
+      'target_name': 'starboard_platform',
+      'type': 'static_library',
+      'sources': ['<@(starboard_platform_sources)'],
+      'defines': [
+        # This must be defined when building Starboard, and must not when
+        # building Starboard client code.
+        'STARBOARD_IMPLEMENTATION',
+      ],
+      'dependencies': [
+        '<@(starboard_platform_dependencies)',
+      ],
+    },
+  ],
+}
diff --git a/src/starboard/linux/x64x11/v8/thread_types_public.h b/src/starboard/linux/x64x11/v8/thread_types_public.h
new file mode 100644
index 0000000..dd50ad8
--- /dev/null
+++ b/src/starboard/linux/x64x11/v8/thread_types_public.h
@@ -0,0 +1,20 @@
+// Copyright 2017 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.
+
+#ifndef STARBOARD_LINUX_X64X11_V8_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_LINUX_X64X11_V8_THREAD_TYPES_PUBLIC_H_
+
+#include "starboard/linux/shared/thread_types_public.h"
+
+#endif  // STARBOARD_LINUX_X64X11_V8_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp
index ec4439d..297019f 100644
--- a/src/starboard/nplb/nplb.gyp
+++ b/src/starboard/nplb/nplb.gyp
@@ -148,6 +148,7 @@
         'once_test.cc',
         'optional_test.cc',
         'player_create_test.cc',
+        'player_create_with_url_test.cc',
         'random_helpers.cc',
         'rwlock_test.cc',
         'semaphore_test.cc',
diff --git a/src/starboard/nplb/player_create_test.cc b/src/starboard/nplb/player_create_test.cc
index f9cbe22..58e96ad 100644
--- a/src/starboard/nplb/player_create_test.cc
+++ b/src/starboard/nplb/player_create_test.cc
@@ -23,6 +23,9 @@
 namespace {
 
 #if SB_HAS(PLAYER)
+#if SB_HAS(PLAYER_WITH_URL)
+// This test does not apply. See player_create_with_url_test.cc instead.
+#else
 
 #if SB_HAS(GLES2)
 void GlesContextRunner(
@@ -97,6 +100,7 @@
   SbWindowDestroy(window);
 }
 
+#endif  // SB_HAS(PLAYER_WITH_URL)
 #endif  // SB_HAS(PLAYER)
 
 }  // namespace
diff --git a/src/starboard/nplb/player_create_with_url_test.cc b/src/starboard/nplb/player_create_with_url_test.cc
new file mode 100644
index 0000000..2f82201
--- /dev/null
+++ b/src/starboard/nplb/player_create_with_url_test.cc
@@ -0,0 +1,63 @@
+// Copyright 2017 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/blitter.h"
+#include "starboard/decode_target.h"
+#include "starboard/player.h"
+#include "starboard/window.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace nplb {
+namespace {
+
+#if SB_HAS(PLAYER) && SB_HAS(PLAYER_WITH_URL)
+TEST(SbPlayerUrlTest, SunnyDay) {
+  SbWindowOptions window_options;
+  SbWindowSetDefaultOptions(&window_options);
+
+  SbWindow window = SbWindowCreate(&window_options);
+  EXPECT_TRUE(SbWindowIsValid(window));
+
+  SbPlayerOutputMode output_modes[] = {kSbPlayerOutputModeDecodeToTexture,
+                                       kSbPlayerOutputModePunchOut};
+
+  for (int i = 0; i < SB_ARRAY_SIZE_INT(output_modes); ++i) {
+    SbPlayerOutputMode output_mode = output_modes[i];
+    if (!SbPlayerOutputModeSupportedWithUrl(output_mode)) {
+      continue;
+    }
+    // TODO: change this URL to something that will create a valid player.
+    char url[] = "about:blank";
+    SB_DLOG(ERROR) << "Creating player";
+    SbPlayer player = SbPlayerCreateWithUrl(url, window, SB_PLAYER_NO_DURATION,
+                                            NULL, NULL, NULL);
+
+    EXPECT_TRUE(SbPlayerIsValid(player));
+
+    if (output_mode == kSbPlayerOutputModeDecodeToTexture) {
+      SbDecodeTarget current_frame = SbPlayerGetCurrentFrame(player);
+    }
+
+    SbPlayerDestroy(player);
+  }
+
+  SbWindowDestroy(window);
+}
+
+#endif  // SB_HAS(PLAYER) && SB_HAS(PLAYER_WITH_URL)
+
+}  // namespace
+}  // namespace nplb
+}  // namespace starboard
diff --git a/src/starboard/player.h b/src/starboard/player.h
index b97e354..dc2b716 100644
--- a/src/starboard/player.h
+++ b/src/starboard/player.h
@@ -182,6 +182,21 @@
                                              void* context,
                                              const void* sample_buffer);
 
+#if SB_HAS(PLAYER_WITH_URL)
+// Callback to queue an encrypted event for initialization data
+// encountered in media data. |init_data_type| should be a string
+// matching one of the EME initialization data types : "cenc",
+// "fairplay", "keyids", or "webm", |init_data| is the initialization
+// data, and |init_data_length| is the length of the data.
+typedef void (*SbPlayerEncryptedMediaInitDataEncounteredCB)(
+    SbPlayer player,
+    void* context,
+    const char* init_data_type,
+    const unsigned char* init_data,
+    unsigned int init_data_length);
+#endif  // SB_API_VERSION >= SB_PLAYER_WITH_URL_API_VERSION  &&
+        // SB_HAS(PLAYER_WITH_URL)
+
 // --- Constants -------------------------------------------------------------
 
 // The value to pass into SbPlayerCreate's |duration_ptr| argument for cases
@@ -203,6 +218,43 @@
 
 // --- Functions -------------------------------------------------------------
 
+#if SB_HAS(PLAYER_WITH_URL)
+
+// Creates a URL-based SbPlayer that will be displayed on |window| for
+// the specified URL |url|, acquiring all resources needed to operate
+// it, and returning an opaque handle to it. The expectation is that a
+// new player will be created and destroyed for every playback.
+//
+// In many ways this function is similar to SbPlayerCreate, but it is
+// missing the input arguments related to the configuration and format
+// of the audio and video stream, as well as the DRM system. The DRM
+// system for a player created with SbPlayerCreateWithUrl can be set
+// after creation using SbPlayerSetDrmSystem. Because the DRM system
+// is not available at the time of SbPlayerCreateWithUrl, it takes in
+// a callback, |encrypted_media_init_data_encountered_cb|, which is
+// run when encrypted media initial data is encountered.
+SB_EXPORT SbPlayer
+SbPlayerCreateWithUrl(const char* url,
+                      SbWindow window,
+                      SbMediaTime duration_pts,
+                      SbPlayerStatusFunc player_status_func,
+                      SbPlayerEncryptedMediaInitDataEncounteredCB
+                          encrypted_media_init_data_encountered_cb,
+                      void* context);
+
+// Sets the DRM system of a running URL-based SbPlayer created with
+// SbPlayerCreateWithUrl. This may only be run once for a given
+// SbPlayer.
+SB_EXPORT void SbPlayerSetDrmSystem(SbPlayer player, SbDrmSystem drm_system);
+
+// Returns true if the given URL player output mode is supported by
+// the platform.  If this function returns true, it is okay to call
+// SbPlayerCreate() with the given |output_mode|.
+SB_EXPORT bool SbPlayerOutputModeSupportedWithUrl(
+    SbPlayerOutputMode output_mode);
+
+#else  // SB_HAS(PLAYER_WITH_URL)
+
 // Creates a player that will be displayed on |window| for the specified
 // |video_codec| and |audio_codec|, acquiring all resources needed to operate
 // it, and returning an opaque handle to it. The expectation is that a new
@@ -291,7 +343,6 @@
                void* context,
                SbPlayerOutputMode output_mode,
                SbDecodeTargetGraphicsContextProvider* context_provider);
-
 // Returns true if the given player output mode is supported by the platform.
 // If this function returns true, it is okay to call SbPlayerCreate() with
 // the given |output_mode|.
@@ -299,6 +350,8 @@
                                            SbMediaVideoCodec codec,
                                            SbDrmSystem drm_system);
 
+#endif  // SB_HAS(PLAYER_WITH_URL)
+
 // Destroys |player|, freeing all associated resources. Each callback must
 // receive one more callback to say that the player was destroyed. Callbacks
 // may be in-flight when SbPlayerDestroy is called, and should be ignored once
diff --git a/src/starboard/raspi/0/gyp_configuration.py b/src/starboard/raspi/0/gyp_configuration.py
index b36cab7..a7bf3fe 100644
--- a/src/starboard/raspi/0/gyp_configuration.py
+++ b/src/starboard/raspi/0/gyp_configuration.py
@@ -20,13 +20,23 @@
 _SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
 sys.path.insert(0, os.path.join(_SCRIPT_DIR, '..'))
 
+import cobalt.tools.webdriver_benchmark_config as wb_config
 # pylint: disable=g-import-not-at-top
 from shared.gyp_configuration import RaspiPlatformConfig
 
 
 def CreatePlatformConfig():
   try:
-    return RaspiPlatformConfig('raspi-0')
+    return RaspiZeroPlatformConfig('raspi-0')
   except RuntimeError as e:
     logging.critical(e)
     return None
+
+
+class RaspiZeroPlatformConfig(RaspiPlatformConfig):
+
+  def __init__(self, platform):
+    super(RaspiZeroPlatformConfig, self).__init__(platform)
+
+  def GetDefaultSampleSize(self):
+    return wb_config.REDUCED_SIZE
diff --git a/src/starboard/raspi/2/skia/gyp_configuration.py b/src/starboard/raspi/2/skia/gyp_configuration.py
index ccf358f..6b4926b 100644
--- a/src/starboard/raspi/2/skia/gyp_configuration.py
+++ b/src/starboard/raspi/2/skia/gyp_configuration.py
@@ -30,3 +30,4 @@
   except RuntimeError as e:
     logging.critical(e)
     return None
+
diff --git a/src/starboard/raspi/shared/gyp_configuration.gypi b/src/starboard/raspi/shared/gyp_configuration.gypi
index 2954044..b578f02 100644
--- a/src/starboard/raspi/shared/gyp_configuration.gypi
+++ b/src/starboard/raspi/shared/gyp_configuration.gypi
@@ -28,10 +28,6 @@
     # renderer.
     'scratch_surface_cache_size_in_bytes' : 0,
 
-    # This should have a default value in cobalt/base.gypi. See the comment
-    # there for acceptable values for this variable.
-    'javascript_engine': 'mozjs-45',
-    'cobalt_enable_jit': 0,
     'cobalt_media_source_2016': 1,
 
     # This atlas size works better than the auto-mem setting.
diff --git a/src/starboard/raspi/shared/gyp_configuration.py b/src/starboard/raspi/shared/gyp_configuration.py
index a750f06..5608043 100644
--- a/src/starboard/raspi/shared/gyp_configuration.py
+++ b/src/starboard/raspi/shared/gyp_configuration.py
@@ -66,6 +66,9 @@
     })
     return env_variables
 
+  def WebdriverBenchmarksEnabled(self):
+    return True
+
   def GetTestFilters(self):
     """Gets all tests to be excluded from a unit test run.
 
diff --git a/src/starboard/raspi/shared/open_max/video_decoder.cc b/src/starboard/raspi/shared/open_max/video_decoder.cc
index 7c96b7d..5a6c506 100644
--- a/src/starboard/raspi/shared/open_max/video_decoder.cc
+++ b/src/starboard/raspi/shared/open_max/video_decoder.cc
@@ -98,27 +98,24 @@
 }
 
 bool VideoDecoder::TryToDeliverOneFrame() {
-  OMX_BUFFERHEADERTYPE* buffer = NULL;
+  scoped_refptr<VideoFrame> frame;
   {
     ScopedLock scoped_lock(mutex_);
-    if (!filled_buffers_.empty()) {
-      buffer = filled_buffers_.front();
+    if (filled_buffers_.empty()) {
+      return false;
     }
-  }
-  if (buffer) {
-    if (scoped_refptr<VideoFrame> frame = CreateFrame(buffer)) {
-      host_->OnDecoderStatusUpdate(kNeedMoreInput, frame);
-      {
-        ScopedLock scoped_lock(mutex_);
-        SB_DCHECK(!filled_buffers_.empty());
-        filled_buffers_.pop();
-        freed_buffers_.push(buffer);
-      }
-      return true;
+    OMX_BUFFERHEADERTYPE* buffer = filled_buffers_.front();
+    frame = CreateFrame(buffer);
+    if (!frame) {
+      return false;
     }
-  }
 
-  return false;
+    SB_DCHECK(!filled_buffers_.empty());
+    filled_buffers_.pop();
+    freed_buffers_.push(buffer);
+  }
+  host_->OnDecoderStatusUpdate(kNeedMoreInput, frame);
+  return true;
 }
 
 // static
@@ -204,11 +201,11 @@
       eos_written = component.WriteEOS();
       stream_ended = true;
     } else if (event->type == Event::kReset) {
+      ScopedLock scoped_lock(mutex_);
       component.Flush();
       stream_ended = false;
       eos_written = false;
 
-      ScopedLock scoped_lock(mutex_);
       while (!freed_buffers_.empty()) {
         component.DropOutputBuffer(freed_buffers_.front());
         freed_buffers_.pop();
@@ -228,6 +225,7 @@
     delete event;
   }
 
+  ScopedLock scoped_lock(mutex_);
   while (!freed_buffers_.empty()) {
     component.DropOutputBuffer(freed_buffers_.front());
     freed_buffers_.pop();
diff --git a/src/starboard/raspi/shared/player_components_impl.cc b/src/starboard/raspi/shared/player_components_impl.cc
index 4d5c678..31835b9 100644
--- a/src/starboard/raspi/shared/player_components_impl.cc
+++ b/src/starboard/raspi/shared/player_components_impl.cc
@@ -17,6 +17,7 @@
 #include "starboard/raspi/shared/open_max/video_decoder.h"
 #include "starboard/shared/ffmpeg/ffmpeg_audio_decoder.h"
 #include "starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h"
 #include "starboard/shared/starboard/player/filter/video_renderer_impl_internal.h"
 
 namespace starboard {
@@ -42,12 +43,13 @@
   VideoDecoderImpl* video_decoder = new VideoDecoderImpl(
       video_parameters.video_codec, video_parameters.job_queue);
 
-  AudioRendererImpl* audio_renderer =
-      new AudioRendererImpl(scoped_ptr<AudioDecoder>(audio_decoder).Pass(),
-                            audio_parameters.audio_header);
+  AudioRendererImpl* audio_renderer = new AudioRendererImpl(
+      make_scoped_ptr<AudioDecoder>(audio_decoder),
+      make_scoped_ptr<AudioRendererSink>(new AudioRendererSinkImpl),
+      audio_parameters.audio_header);
 
-  VideoRendererImpl* video_renderer = new VideoRendererImpl(
-      scoped_ptr<HostedVideoDecoder>(video_decoder).Pass());
+  VideoRendererImpl* video_renderer =
+      new VideoRendererImpl(make_scoped_ptr<HostedVideoDecoder>(video_decoder));
 
   return scoped_ptr<PlayerComponents>(
       new PlayerComponents(audio_renderer, video_renderer));
diff --git a/src/starboard/raspi/shared/starboard_platform.gypi b/src/starboard/raspi/shared/starboard_platform.gypi
index 7acc475..c19cf18 100644
--- a/src/starboard/raspi/shared/starboard_platform.gypi
+++ b/src/starboard/raspi/shared/starboard_platform.gypi
@@ -281,6 +281,9 @@
         '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc',
         '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h',
         '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.h',
+        '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink.h',
+        '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc',
+        '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h',
         '<(DEPTH)/starboard/shared/starboard/player/filter/audio_time_stretcher.cc',
         '<(DEPTH)/starboard/shared/starboard/player/filter/audio_time_stretcher.h',
         '<(DEPTH)/starboard/shared/starboard/player/filter/decoded_audio_queue.cc',
diff --git a/src/starboard/shared/__init__.py b/src/starboard/shared/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/starboard/shared/__init__.py
diff --git a/src/starboard/shared/gcc/atomic_gcc_sync_public.h b/src/starboard/shared/gcc/atomic_gcc_sync_public.h
deleted file mode 100644
index fc5d803..0000000
--- a/src/starboard/shared/gcc/atomic_gcc_sync_public.h
+++ /dev/null
@@ -1,227 +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.
-
-// An SbAtomic* implementation using the older "__sync_*" GCC intrinsics.
-// These may be useful if, for example, you are using a GCC version prior to
-// 4.7, or your toolchain has a broken implementation of the newer
-// "__atomic_*" intrinsics.
-//
-// These definitions were mostly extracted from Chromium's
-// base/atomicops_internals_gcc.h.
-
-#ifndef STARBOARD_SHARED_GCC_ATOMIC_GCC_SYNC_PUBLIC_H_
-#define STARBOARD_SHARED_GCC_ATOMIC_GCC_SYNC_PUBLIC_H_
-
-#include "starboard/atomic.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-static SB_C_FORCE_INLINE SbAtomic32
-SbAtomicNoBarrier_CompareAndSwap(volatile SbAtomic32* ptr,
-                                 SbAtomic32 old_value,
-                                 SbAtomic32 new_value) {
-  SbAtomic32 prev_value;
-  do {
-    if (__sync_bool_compare_and_swap(ptr, old_value, new_value))
-      return old_value;
-    prev_value = *ptr;
-  } while (prev_value == old_value);
-  return prev_value;
-}
-
-static SB_C_FORCE_INLINE SbAtomic32
-SbAtomicNoBarrier_Exchange(volatile SbAtomic32* ptr, SbAtomic32 new_value) {
-  SbAtomic32 old_value;
-  do {
-    old_value = *ptr;
-  } while (!__sync_bool_compare_and_swap(ptr, old_value, new_value));
-  return old_value;
-}
-
-static SB_C_FORCE_INLINE SbAtomic32
-SbAtomicNoBarrier_Increment(volatile SbAtomic32* ptr, SbAtomic32 increment) {
-  return SbAtomicBarrier_Increment(ptr, increment);
-}
-
-static SB_C_FORCE_INLINE SbAtomic32
-SbAtomicBarrier_Increment(volatile SbAtomic32* ptr,
-                          SbAtomic32 increment) {
-  for (;;) {
-    // Atomic exchange the old value with an incremented one.
-    SbAtomic32 old_value = *ptr;
-    SbAtomic32 new_value = old_value + increment;
-    if (__sync_bool_compare_and_swap(ptr, old_value, new_value)) {
-      // The exchange took place as expected.
-      return new_value;
-    }
-    // Otherwise, *ptr changed mid-loop and we need to retry.
-  }
-}
-
-static SB_C_FORCE_INLINE SbAtomic32
-SbAtomicAcquire_CompareAndSwap(volatile SbAtomic32* ptr,
-                               SbAtomic32 old_value,
-                               SbAtomic32 new_value) {
-  // Since NoBarrier_CompareAndSwap uses __sync_bool_compare_and_swap, which
-  // is a full memory barrier, none is needed here or below in Release.
-  return SbAtomicNoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-static SB_C_FORCE_INLINE SbAtomic32
-SbAtomicRelease_CompareAndSwap(volatile SbAtomic32* ptr,
-                               SbAtomic32 old_value,
-                               SbAtomic32 new_value) {
-  return SbAtomicNoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-static SB_C_FORCE_INLINE void SbAtomicMemoryBarrier() {
-  __sync_synchronize();
-}
-
-static SB_C_FORCE_INLINE void SbAtomicNoBarrier_Store(volatile SbAtomic32* ptr,
-                                                      SbAtomic32 value) {
-  *ptr = value;
-}
-
-static SB_C_FORCE_INLINE void SbAtomicAcquire_Store(volatile SbAtomic32* ptr,
-                                                    SbAtomic32 value) {
-  *ptr = value;
-  SbAtomicMemoryBarrier();
-}
-
-static SB_C_FORCE_INLINE void SbAtomicRelease_Store(volatile SbAtomic32* ptr,
-                                                    SbAtomic32 value) {
-  SbAtomicMemoryBarrier();
-  *ptr = value;
-}
-
-static SB_C_FORCE_INLINE SbAtomic32
-SbAtomicNoBarrier_Load(volatile const SbAtomic32* ptr) {
-  return *ptr;
-}
-
-static SB_C_FORCE_INLINE SbAtomic32
-SbAtomicAcquire_Load(volatile const SbAtomic32* ptr) {
-  SbAtomic32 value = *ptr;
-  SbAtomicMemoryBarrier();
-  return value;
-}
-
-static SB_C_FORCE_INLINE SbAtomic32
-SbAtomicRelease_Load(volatile const SbAtomic32* ptr) {
-  SbAtomicMemoryBarrier();
-  return *ptr;
-}
-
-// 64-bit atomic operations (only available on 64-bit processors).
-#if SB_HAS(64_BIT_ATOMICS)
-static SB_C_FORCE_INLINE SbAtomic64
-SbAtomicNoBarrier_CompareAndSwap64(volatile SbAtomic64* ptr,
-                                   SbAtomic64 old_value,
-                                   SbAtomic64 new_value) {
-  SbAtomic64 prev_value;
-  do {
-    if (__sync_bool_compare_and_swap(ptr, old_value, new_value))
-      return old_value;
-    prev_value = *ptr;
-  } while (prev_value == old_value);
-  return prev_value;
-}
-
-static SB_C_FORCE_INLINE SbAtomic64
-SbAtomicNoBarrier_Exchange64(volatile SbAtomic64* ptr, SbAtomic64 new_value) {
-  SbAtomic64 old_value;
-  do {
-    old_value = *ptr;
-  } while (!__sync_bool_compare_and_swap(ptr, old_value, new_value));
-  return old_value;
-}
-
-static SB_C_FORCE_INLINE SbAtomic64
-SbAtomicNoBarrier_Increment64(volatile SbAtomic64* ptr, SbAtomic64 increment) {
-  return SbAtomicBarrier_Increment64(ptr, increment);
-}
-
-static SB_C_FORCE_INLINE SbAtomic64
-SbAtomicBarrier_Increment64(volatile SbAtomic64* ptr, SbAtomic64 increment) {
-  for (;;) {
-    // Atomic exchange the old value with an incremented one.
-    SbAtomic64 old_value = *ptr;
-    SbAtomic64 new_value = old_value + increment;
-    if (__sync_bool_compare_and_swap(ptr, old_value, new_value)) {
-      // The exchange took place as expected.
-      return new_value;
-    }
-    // Otherwise, *ptr changed mid-loop and we need to retry.
-  }
-}
-
-static SB_C_FORCE_INLINE SbAtomic64
-SbAtomicAcquire_CompareAndSwap64(volatile SbAtomic64* ptr,
-                                 SbAtomic64 old_value,
-                                 SbAtomic64 new_value) {
-  return SbAtomicNoBarrier_CompareAndSwap64(ptr, old_value, new_value);
-}
-
-static SB_C_FORCE_INLINE SbAtomic64
-SbAtomicRelease_CompareAndSwap64(volatile SbAtomic64* ptr,
-                                 SbAtomic64 old_value,
-                                 SbAtomic64 new_value) {
-  return SbAtomicNoBarrier_CompareAndSwap64(ptr, old_value, new_value);
-}
-
-static SB_C_FORCE_INLINE void
-SbAtomicNoBarrier_Store64(volatile SbAtomic64* ptr,
-                          SbAtomic64 value) {
-  *ptr = value;
-}
-
-static SB_C_FORCE_INLINE void SbAtomicAcquire_Store64(volatile SbAtomic64* ptr,
-                                                      SbAtomic64 value) {
-  *ptr = value;
-  SbAtomicMemoryBarrier();
-}
-
-static SB_C_FORCE_INLINE void SbAtomicRelease_Store64(volatile SbAtomic64* ptr,
-                                                      SbAtomic64 value) {
-  SbAtomicMemoryBarrier();
-  *ptr = value;
-}
-
-static SB_C_FORCE_INLINE SbAtomic64
-SbAtomicNoBarrier_Load64(volatile const SbAtomic64* ptr) {
-  return *ptr;
-}
-
-static SB_C_FORCE_INLINE SbAtomic64
-SbAtomicAcquire_Load64(volatile const SbAtomic64* ptr) {
-  SbAtomic64 value = *ptr;
-  SbAtomicMemoryBarrier();
-  return value;
-}
-
-static SB_C_FORCE_INLINE SbAtomic64
-SbAtomicRelease_Load64(volatile const SbAtomic64* ptr) {
-  SbAtomicMemoryBarrier();
-  return *ptr;
-}
-#endif  // SB_HAS(64_BIT_ATOMICS)
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#endif  // STARBOARD_SHARED_GCC_ATOMIC_GCC_SYNC_PUBLIC_H_
diff --git a/src/starboard/shared/libevent/socket_waiter_internal.cc b/src/starboard/shared/libevent/socket_waiter_internal.cc
index a1d27b5..8112c35 100644
--- a/src/starboard/shared/libevent/socket_waiter_internal.cc
+++ b/src/starboard/shared/libevent/socket_waiter_internal.cc
@@ -267,9 +267,11 @@
   timeout_set(&event, &SbSocketWaiterPrivate::LibeventTimeoutCallback, this);
   event_base_set(base_, &event);
 
-  struct timeval tv;
-  ToTimevalDuration(duration, &tv);
-  timeout_add(&event, &tv);
+  if (duration < kSbTimeMax) {
+    struct timeval tv;
+    ToTimevalDuration(duration, &tv);
+    timeout_add(&event, &tv);
+  }
 
   waiting_ = true;
   event_base_loop(base_, 0);
@@ -279,9 +281,11 @@
       woken_up_ ? kSbSocketWaiterResultWokenUp : kSbSocketWaiterResultTimedOut;
   woken_up_ = false;
 
-  // We clean this up, in case we were bewakened early, to prevent a suprious
-  // wake-up later.
-  timeout_del(&event);
+  if (duration < kSbTimeMax) {
+    // We clean this up, in case we were awakened early, to prevent a spurious
+    // wake-up later.
+    timeout_del(&event);
+  }
 
   return result;
 }
diff --git a/src/starboard/shared/starboard/application.cc b/src/starboard/shared/starboard/application.cc
index 926545b..e935128 100644
--- a/src/starboard/shared/starboard/application.cc
+++ b/src/starboard/shared/starboard/application.cc
@@ -274,7 +274,7 @@
         return true;
       }
 
-      if (state() == kStatePaused) {
+      if (state() == kStatePaused || state() == kStatePreloading) {
         Inject(new Event(kSbEventTypeSuspend, NULL, NULL));
         Inject(scoped_event.release());
         return true;
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 66f21c3..5048b82 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
@@ -17,7 +17,6 @@
 #include <algorithm>
 
 #include "starboard/memory.h"
-#include "starboard/shared/starboard/audio_sink/audio_sink_internal.h"
 #include "starboard/shared/starboard/media/media_util.h"
 
 namespace starboard {
@@ -56,22 +55,25 @@
 // when float32 is not supported.  To use kSbMediaAudioSampleTypeFloat32 will
 // cause an extra conversion from float32 to int16 before the samples are sent
 // to the audio sink.
-SbMediaAudioSampleType GetSinkAudioSampleType() {
-  return SbAudioSinkIsAudioSampleTypeSupported(kSbMediaAudioSampleTypeFloat32)
+SbMediaAudioSampleType GetSinkAudioSampleType(
+    AudioRendererSink* audio_renderer_sink) {
+  return audio_renderer_sink->IsAudioSampleTypeSupported(
+             kSbMediaAudioSampleTypeFloat32)
              ? kSbMediaAudioSampleTypeFloat32
              : kSbMediaAudioSampleTypeInt16;
 }
 
 }  // namespace
 
-AudioRendererImpl::AudioRendererImpl(scoped_ptr<AudioDecoder> decoder,
-                                     const SbMediaAudioHeader& audio_header)
+AudioRendererImpl::AudioRendererImpl(
+    scoped_ptr<AudioDecoder> decoder,
+    scoped_ptr<AudioRendererSink> audio_renderer_sink,
+    const SbMediaAudioHeader& audio_header)
     : eos_state_(kEOSNotReceived),
       channels_(audio_header.number_of_channels),
-      sink_sample_type_(GetSinkAudioSampleType()),
+      sink_sample_type_(GetSinkAudioSampleType(audio_renderer_sink.get())),
       bytes_per_frame_(media::GetBytesPerSample(sink_sample_type_) * channels_),
       playback_rate_(1.0),
-      volume_(1.0),
       paused_(true),
       consume_frames_called_(false),
       seeking_(false),
@@ -82,12 +84,12 @@
       frames_consumed_by_sink_(0),
       frames_consumed_set_at_(SbTimeGetMonotonicNow()),
       decoder_(decoder.Pass()),
-      audio_sink_(kSbAudioSinkInvalid),
       can_accept_more_data_(true),
       process_audio_data_scheduled_(false),
       process_audio_data_closure_(
           Bind(&AudioRendererImpl::ProcessAudioData, this)),
-      decoder_needs_full_reset_(false) {
+      decoder_needs_full_reset_(false),
+      audio_renderer_sink_(audio_renderer_sink.Pass()) {
   SB_DCHECK(decoder_ != NULL);
 
   frame_buffers_[0] = &frame_buffer_[0];
@@ -109,16 +111,13 @@
   // ensure that implicit HEAAC is properly handled.
   int source_sample_rate = decoder_->GetSamplesPerSecond();
   int destination_sample_rate =
-      SbAudioSinkGetNearestSupportedSampleFrequency(source_sample_rate);
+      audio_renderer_sink_->GetNearestSupportedSampleFrequency(
+          source_sample_rate);
   time_stretcher_.Initialize(channels_, destination_sample_rate);
 }
 
 AudioRendererImpl::~AudioRendererImpl() {
   SB_DCHECK(BelongsToCurrentThread());
-
-  if (audio_sink_ != kSbAudioSinkInvalid) {
-    SbAudioSinkDestroy(audio_sink_);
-  }
 }
 
 void AudioRendererImpl::WriteSample(
@@ -180,10 +179,11 @@
 
   playback_rate_.store(playback_rate);
 
-  if (audio_sink_) {
+  audio_renderer_sink_->SetPlaybackRate(playback_rate_.load() > 0.0 ? 1.0
+                                                                    : 0.0);
+  if (audio_renderer_sink_->HasStarted()) {
     // TODO: Remove SetPlaybackRate() support from audio sink as it only need to
     // support play/pause.
-    audio_sink_->SetPlaybackRate(playback_rate_.load() > 0.0 ? 1.0 : 0.0);
     if (playback_rate_.load() > 0.0) {
       if (process_audio_data_scheduled_) {
         Remove(process_audio_data_closure_);
@@ -195,22 +195,17 @@
 
 void AudioRendererImpl::SetVolume(double volume) {
   SB_DCHECK(BelongsToCurrentThread());
-  volume_ = volume;
-  if (audio_sink_) {
-    audio_sink_->SetVolume(volume_);
-  }
+  audio_renderer_sink_->SetVolume(volume);
 }
 
 void AudioRendererImpl::Seek(SbMediaTime seek_to_pts) {
   SB_DCHECK(BelongsToCurrentThread());
   SB_DCHECK(seek_to_pts >= 0);
 
-  SbAudioSinkDestroy(audio_sink_);
+  audio_renderer_sink_->Stop();
 
-  // Now the sink is destroyed and the callbacks will no longer be called, so
-  // the following modifications are safe without lock.
-  audio_sink_ = kSbAudioSinkInvalid;
-
+  // Now the sink is stopped and the callbacks will no longer be called, so the
+  // following modifications are safe without lock.
   if (resampler_) {
     resampler_.reset();
     time_stretcher_.FlushBuffers();
@@ -285,13 +280,40 @@
          frames_played * kSbMediaTimeSecond / samples_per_second;
 }
 
+void AudioRendererImpl::OnUpdateSourceStatus(int* frames_in_buffer,
+                                             int* offset_in_frames,
+                                             bool* is_playing,
+                                             bool* is_eos_reached) {
+  *is_eos_reached = eos_state_.load() >= kEOSSentToSink;
+
+  *is_playing = !paused_.load() && !seeking_.load();
+
+  if (*is_playing) {
+    *frames_in_buffer = static_cast<int>(frames_sent_to_sink_.load() -
+                                         frames_consumed_by_sink_.load());
+    *offset_in_frames = frames_consumed_by_sink_.load() % kMaxCachedFrames;
+  } else {
+    *frames_in_buffer = *offset_in_frames = 0;
+  }
+}
+
+void AudioRendererImpl::OnConsumeFrames(int frames_consumed) {
+  frames_consumed_by_sink_.fetch_add(frames_consumed);
+  SB_DCHECK(frames_consumed_by_sink_.load() <= frames_sent_to_sink_.load());
+  frames_consumed_by_sink_since_last_get_current_time_.fetch_add(
+      frames_consumed);
+  frames_consumed_set_at_.store(SbTimeGetMonotonicNow());
+  consume_frames_called_.store(true);
+}
+
 void AudioRendererImpl::CreateAudioSinkAndResampler() {
   int source_sample_rate = decoder_->GetSamplesPerSecond();
   SbMediaAudioSampleType source_sample_type = decoder_->GetSampleType();
   SbMediaAudioFrameStorageType source_storage_type = decoder_->GetStorageType();
 
   int destination_sample_rate =
-      SbAudioSinkGetNearestSupportedSampleFrequency(source_sample_rate);
+      audio_renderer_sink_->GetNearestSupportedSampleFrequency(
+          source_sample_rate);
 
   // AudioTimeStretcher only supports interleaved float32 samples.
   if (source_sample_rate != destination_sample_rate ||
@@ -308,44 +330,12 @@
   }
 
   // TODO: Support planar only audio sink.
-  audio_sink_ = SbAudioSinkCreate(
+  audio_renderer_sink_->Start(
       channels_, destination_sample_rate, sink_sample_type_,
       kSbMediaAudioFrameStorageTypeInterleaved,
       reinterpret_cast<SbAudioSinkFrameBuffers>(frame_buffers_),
-      kMaxCachedFrames, &AudioRendererImpl::UpdateSourceStatusFunc,
-      &AudioRendererImpl::ConsumeFramesFunc, this);
-  SB_DCHECK(SbAudioSinkIsValid(audio_sink_));
-
-  // TODO: Remove SetPlaybackRate() support from audio sink as it only need to
-  // support play/pause.
-  audio_sink_->SetPlaybackRate(playback_rate_.load() > 0.0 ? 1.0 : 0.0);
-  audio_sink_->SetVolume(volume_);
-}
-
-void AudioRendererImpl::UpdateSourceStatus(int* frames_in_buffer,
-                                           int* offset_in_frames,
-                                           bool* is_playing,
-                                           bool* is_eos_reached) {
-  *is_eos_reached = eos_state_.load() >= kEOSSentToSink;
-
-  *is_playing = !paused_.load() && !seeking_.load();
-
-  if (*is_playing) {
-    *frames_in_buffer = static_cast<int>(frames_sent_to_sink_.load() -
-                                         frames_consumed_by_sink_.load());
-    *offset_in_frames = frames_consumed_by_sink_.load() % kMaxCachedFrames;
-  } else {
-    *frames_in_buffer = *offset_in_frames = 0;
-  }
-}
-
-void AudioRendererImpl::ConsumeFrames(int frames_consumed) {
-  frames_consumed_by_sink_.fetch_add(frames_consumed);
-  SB_DCHECK(frames_consumed_by_sink_.load() <= frames_sent_to_sink_.load());
-  frames_consumed_by_sink_since_last_get_current_time_.fetch_add(
-      frames_consumed);
-  frames_consumed_set_at_.store(SbTimeGetMonotonicNow());
-  consume_frames_called_.store(true);
+      kMaxCachedFrames, this);
+  SB_DCHECK(audio_renderer_sink_->HasStarted());
 }
 
 void AudioRendererImpl::LogFramesConsumed() {
@@ -388,10 +378,12 @@
 void AudioRendererImpl::ProcessAudioData() {
   process_audio_data_scheduled_ = false;
 
-  if (!SbAudioSinkIsValid(audio_sink_)) {
+  if (!audio_renderer_sink_->HasStarted()) {
     CreateAudioSinkAndResampler();
   }
 
+  SB_DCHECK(resampler_);
+
   // Loop until no audio is appended, i.e. AppendAudioToFrameBuffer() returns
   // false.
   while (AppendAudioToFrameBuffer()) {
@@ -518,31 +510,6 @@
   return frames_appended > 0;
 }
 
-// static
-void AudioRendererImpl::UpdateSourceStatusFunc(int* frames_in_buffer,
-                                               int* offset_in_frames,
-                                               bool* is_playing,
-                                               bool* is_eos_reached,
-                                               void* context) {
-  AudioRendererImpl* audio_renderer = static_cast<AudioRendererImpl*>(context);
-  SB_DCHECK(audio_renderer);
-  SB_DCHECK(frames_in_buffer);
-  SB_DCHECK(offset_in_frames);
-  SB_DCHECK(is_playing);
-  SB_DCHECK(is_eos_reached);
-
-  audio_renderer->UpdateSourceStatus(frames_in_buffer, offset_in_frames,
-                                     is_playing, is_eos_reached);
-}
-
-// static
-void AudioRendererImpl::ConsumeFramesFunc(int frames_consumed, void* context) {
-  AudioRendererImpl* audio_renderer = static_cast<AudioRendererImpl*>(context);
-  SB_DCHECK(audio_renderer);
-
-  audio_renderer->ConsumeFrames(frames_consumed);
-}
-
 }  // namespace filter
 }  // namespace player
 }  // namespace starboard
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 9d7f63c..221cb12 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
@@ -18,7 +18,6 @@
 #include <vector>
 
 #include "starboard/atomic.h"
-#include "starboard/audio_sink.h"
 #include "starboard/common/scoped_ptr.h"
 #include "starboard/log.h"
 #include "starboard/media.h"
@@ -28,6 +27,7 @@
 #include "starboard/shared/starboard/player/filter/audio_decoder_internal.h"
 #include "starboard/shared/starboard/player/filter/audio_frame_tracker.h"
 #include "starboard/shared/starboard/player/filter/audio_renderer_internal.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_sink.h"
 #include "starboard/shared/starboard/player/filter/audio_resampler.h"
 #include "starboard/shared/starboard/player/filter/audio_time_stretcher.h"
 #include "starboard/shared/starboard/player/input_buffer_internal.h"
@@ -42,9 +42,12 @@
 
 // A default implementation of |AudioRenderer| that only depends on the
 // |AudioDecoder| interface, rather than a platform specific implementation.
-class AudioRendererImpl : public AudioRenderer, private JobQueue::JobOwner {
+class AudioRendererImpl : public AudioRenderer,
+                          private AudioRendererSink::RenderCallback,
+                          private JobQueue::JobOwner {
  public:
   AudioRendererImpl(scoped_ptr<AudioDecoder> decoder,
+                    scoped_ptr<AudioRendererSink> audio_renderer_sink,
                     const SbMediaAudioHeader& audio_header);
   ~AudioRendererImpl() SB_OVERRIDE;
 
@@ -100,12 +103,14 @@
   // the sink buffer.
   static const size_t kFrameAppendUnit = 16384;
 
+  // AudioRendererSink methods
+  void OnUpdateSourceStatus(int* frames_in_buffer,
+                            int* offset_in_frames,
+                            bool* is_playing,
+                            bool* is_eos_reached) SB_OVERRIDE;
+  void OnConsumeFrames(int frames_consumed) SB_OVERRIDE;
+
   void CreateAudioSinkAndResampler();
-  void UpdateSourceStatus(int* frames_in_buffer,
-                          int* offset_in_frames,
-                          bool* is_playing,
-                          bool* is_eos_reached);
-  void ConsumeFrames(int frames_consumed);
   void LogFramesConsumed();
 
   void OnDecoderConsumed();
@@ -114,14 +119,6 @@
   void FillResamplerAndTimeStretcher();
   bool AppendAudioToFrameBuffer();
 
-  // SbAudioSink callbacks
-  static void UpdateSourceStatusFunc(int* frames_in_buffer,
-                                     int* offset_in_frames,
-                                     bool* is_playing,
-                                     bool* is_eos_reached,
-                                     void* context);
-  static void ConsumeFramesFunc(int frames_consumed, void* context);
-
   atomic_int32_t eos_state_;
   const int channels_;
   const SbMediaAudioSampleType sink_sample_type_;
@@ -129,7 +126,6 @@
 
   scoped_ptr<AudioResampler> resampler_;
   AudioTimeStretcher time_stretcher_;
-  double volume_;
 
   std::vector<uint8_t> frame_buffer_;
   uint8_t* frame_buffers_[1];
@@ -137,8 +133,6 @@
   int32_t pending_decoder_outputs_;
   Closure log_frames_consumed_closure_;
 
-  SbAudioSink audio_sink_;
-
   bool can_accept_more_data_;
   bool process_audio_data_scheduled_;
   Closure process_audio_data_closure_;
@@ -149,6 +143,8 @@
   // performance by keeping track of whether we already have a fresh decoder,
   // and can thus avoid doing a full reset.
   bool decoder_needs_full_reset_;
+
+  scoped_ptr<AudioRendererSink> audio_renderer_sink_;
 };
 
 }  // namespace filter
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 8dc94ca..85c8515 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
@@ -20,7 +20,9 @@
 #include "starboard/media.h"
 #include "starboard/memory.h"
 #include "starboard/shared/starboard/media/media_util.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h"
 #include "starboard/shared/starboard/player/filter/mock_audio_decoder.h"
+#include "starboard/shared/starboard/player/filter/mock_audio_renderer_sink.h"
 #include "starboard/thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -33,14 +35,14 @@
 namespace {
 
 using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::AtLeast;
 using ::testing::DoAll;
+using ::testing::InSequence;
+using ::testing::InvokeWithoutArgs;
 using ::testing::Return;
 using ::testing::SaveArg;
 
-// TODO: Inject and test the renderer using SbAudioSink mock.  Otherwise the
-// tests rely on a correctly implemented audio sink and may fail on other audio
-// sinks.
-
 class AudioRendererImplTest : public ::testing::Test {
  protected:
   static const int kDefaultNumberOfChannels = 2;
@@ -62,13 +64,74 @@
     audio_renderer_.reset(NULL);
     sample_type_ = sample_type;
     storage_type_ = storage_type;
+    audio_renderer_sink_ = new ::testing::StrictMock<MockAudioRendererSink>;
     audio_decoder_ = new MockAudioDecoder(sample_type_, storage_type_,
                                           kDefaultSamplesPerSecond);
+
+    ON_CALL(*audio_renderer_sink_, Start(_, _, _, _, _, _, _))
+        .WillByDefault(DoAll(InvokeWithoutArgs([this]() {
+                               audio_renderer_sink_->SetHasStarted(true);
+                             }),
+                             SaveArg<6>(&renderer_callback_)));
+    ON_CALL(*audio_renderer_sink_, Stop())
+        .WillByDefault(InvokeWithoutArgs(
+            [this]() { audio_renderer_sink_->SetHasStarted(false); }));
+
+    ON_CALL(*audio_renderer_sink_, HasStarted())
+        .WillByDefault(::testing::ReturnPointee(
+            audio_renderer_sink_->HasStartedPointer()));
+    EXPECT_CALL(*audio_renderer_sink_, HasStarted()).Times(AnyNumber());
+
+    // This allows audio renderers to query different sample types, and only
+    // same type of float32 will be returned as supported.
+    ON_CALL(*audio_renderer_sink_,
+            IsAudioSampleTypeSupported(kSbMediaAudioSampleTypeFloat32))
+        .WillByDefault(Return(true));
+    EXPECT_CALL(*audio_renderer_sink_, IsAudioSampleTypeSupported(_))
+        .Times(AnyNumber());
+
+    // This allows audio renderers to query different sample types, and only
+    // sample frequency of 100Khz will be supported.
+    const int kSupportedSampleFrequency = 100000;
+    ON_CALL(*audio_renderer_sink_,
+            GetNearestSupportedSampleFrequency(kSupportedSampleFrequency))
+        .WillByDefault(Return(kSupportedSampleFrequency));
+    EXPECT_CALL(*audio_renderer_sink_, GetNearestSupportedSampleFrequency(_))
+        .Times(AnyNumber());
+
     EXPECT_CALL(*audio_decoder_, Initialize(_))
         .WillOnce(SaveArg<0>(&output_cb_));
-    audio_renderer_.reset(
-        new AudioRendererImpl(make_scoped_ptr<AudioDecoder>(audio_decoder_),
-                              GetDefaultAudioHeader()));
+
+    audio_renderer_.reset(new AudioRendererImpl(
+        make_scoped_ptr<AudioDecoder>(audio_decoder_),
+        make_scoped_ptr<AudioRendererSink>(audio_renderer_sink_),
+        GetDefaultAudioHeader()));
+  }
+
+  // Creates audio buffers, decodes them, and passes them onto the renderer,
+  // until the renderer reaches its preroll threshold.
+  // Once the renderer is "full", an EndOfStream is written.
+  // Returns the number of frames written.
+  int FillRendererWithDecodedAudioAndWriteEOS() {
+    const int kFramesPerBuffer = 1024;
+
+    int frames_written = 0;
+
+    while (audio_renderer_->IsSeekingInProgress()) {
+      SbMediaTime pts =
+          frames_written * kSbMediaTimeSecond / kDefaultSamplesPerSecond;
+      scoped_refptr<InputBuffer> input_buffer = CreateInputBuffer(pts);
+      WriteSample(input_buffer);
+      CallConsumedCB();
+      scoped_refptr<DecodedAudio> decoded_audio =
+          CreateDecodedAudio(pts, kFramesPerBuffer);
+      SendDecoderOutput(decoded_audio);
+      frames_written += kFramesPerBuffer;
+    }
+
+    WriteEndOfStream();
+
+    return frames_written;
   }
 
   void WriteSample(const scoped_refptr<InputBuffer>& input_buffer) {
@@ -138,8 +201,9 @@
 
   scoped_ptr<AudioRenderer> audio_renderer_;
   MockAudioDecoder* audio_decoder_;
+  MockAudioRendererSink* audio_renderer_sink_;
+  AudioRendererSink::RenderCallback* renderer_callback_;
 
- private:
   void OnDeallocateSample(const void* sample_buffer) {
     ASSERT_TRUE(buffers_in_decoder_.find(sample_buffer) !=
                 buffers_in_decoder_.end());
@@ -180,22 +244,18 @@
 }
 
 TEST_F(AudioRendererImplTest, SunnyDay) {
-  Seek(0);
-
-  const int kFramesPerBuffer = 1024;
-
-  int frames_written = 0;
-
-  while (audio_renderer_->IsSeekingInProgress()) {
-    SbMediaTime pts =
-        frames_written * kSbMediaTimeSecond / kDefaultSamplesPerSecond;
-    WriteSample(CreateInputBuffer(pts));
-    CallConsumedCB();
-    SendDecoderOutput(CreateDecodedAudio(pts, kFramesPerBuffer));
-    frames_written += kFramesPerBuffer;
+  {
+    InSequence seq;
+    EXPECT_CALL(*audio_renderer_sink_, Stop()).Times(AnyNumber());
+    EXPECT_CALL(
+        *audio_renderer_sink_,
+        Start(kDefaultNumberOfChannels, kDefaultSamplesPerSecond,
+              kDefaultAudioSampleType, kDefaultAudioFrameStorageType, _, _, _));
   }
 
-  WriteEndOfStream();
+  Seek(0);
+
+  int frames_written = FillRendererWithDecodedAudioAndWriteEOS();
 
   EXPECT_EQ(audio_renderer_->GetCurrentTime(), 0);
   EXPECT_FALSE(audio_renderer_->IsSeekingInProgress());
@@ -206,37 +266,61 @@
 
   SbMediaTime media_time = audio_renderer_->GetCurrentTime();
 
-  while (!audio_renderer_->IsEndOfStreamPlayed()) {
-    SbThreadSleep(kSbTimeMillisecond);
-    SbMediaTime new_media_time = audio_renderer_->GetCurrentTime();
-    EXPECT_GE(new_media_time, media_time);
-    media_time = new_media_time;
-  }
+  int frames_in_buffer;
+  int offset_in_frames;
+  bool is_playing;
+  bool is_eos_reached;
+  renderer_callback_->OnUpdateSourceStatus(&frames_in_buffer, &offset_in_frames,
+                                           &is_playing, &is_eos_reached);
+  EXPECT_GT(frames_in_buffer, 0);
+  EXPECT_GE(offset_in_frames, 0);
+  EXPECT_TRUE(is_playing);
+  EXPECT_TRUE(is_eos_reached);
+
+  // Consume frames in two batches, so we can test if |GetCurrentTime()|
+  // is incrementing in an expected manner.
+  const int frames_to_consume = frames_in_buffer / 4;
+  SbMediaTime new_media_time;
+
+  EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
+
+  renderer_callback_->OnConsumeFrames(frames_to_consume);
+  new_media_time = audio_renderer_->GetCurrentTime();
+  EXPECT_GT(new_media_time, media_time);
+  media_time = new_media_time;
+
+  const int remaining_frames = frames_in_buffer - frames_to_consume;
+  renderer_callback_->OnConsumeFrames(remaining_frames);
+  new_media_time = audio_renderer_->GetCurrentTime();
+  EXPECT_GT(new_media_time, media_time);
+
+  EXPECT_TRUE(audio_renderer_->IsEndOfStreamPlayed());
 }
 
 TEST_F(AudioRendererImplTest, SunnyDayWithDoublePlaybackRateAndInt16Samples) {
   const int kPlaybackRate = 2;
 
+  // Resets |audio_renderer_sink_|, so all the gtest codes need to be below
+  // this line.
   ResetToFormat(kSbMediaAudioSampleTypeInt16,
                 kSbMediaAudioFrameStorageTypeInterleaved);
+
+  {
+    ::testing::InSequence seq;
+    EXPECT_CALL(*audio_renderer_sink_, Stop()).Times(AnyNumber());
+    EXPECT_CALL(
+        *audio_renderer_sink_,
+        Start(kDefaultNumberOfChannels, kDefaultSamplesPerSecond,
+              kDefaultAudioSampleType, kDefaultAudioFrameStorageType, _, _, _));
+  }
+
+  // It is OK to set the rate to 1.0 any number of times.
+  EXPECT_CALL(*audio_renderer_sink_, SetPlaybackRate(1.0)).Times(AnyNumber());
   audio_renderer_->SetPlaybackRate(static_cast<float>(kPlaybackRate));
 
   Seek(0);
 
-  const int kFramesPerBuffer = 1024;
-
-  int frames_written = 0;
-
-  while (audio_renderer_->IsSeekingInProgress()) {
-    SbMediaTime pts =
-        frames_written * kSbMediaTimeSecond / kDefaultSamplesPerSecond;
-    WriteSample(CreateInputBuffer(pts));
-    CallConsumedCB();
-    SendDecoderOutput(CreateDecodedAudio(pts, kFramesPerBuffer));
-    frames_written += kFramesPerBuffer;
-  }
-
-  WriteEndOfStream();
+  int frames_written = FillRendererWithDecodedAudioAndWriteEOS();
 
   EXPECT_EQ(audio_renderer_->GetCurrentTime(), 0);
   EXPECT_FALSE(audio_renderer_->IsSeekingInProgress());
@@ -247,46 +331,99 @@
 
   SbMediaTime media_time = audio_renderer_->GetCurrentTime();
 
-  while (!audio_renderer_->IsEndOfStreamPlayed()) {
-    SbThreadSleep(kSbTimeMillisecond);
-    SbMediaTime new_media_time = audio_renderer_->GetCurrentTime();
-    EXPECT_GE(new_media_time, media_time);
-    media_time = new_media_time;
-  }
+  int frames_in_buffer;
+  int offset_in_frames;
+  bool is_playing;
+  bool is_eos_reached;
+  renderer_callback_->OnUpdateSourceStatus(&frames_in_buffer, &offset_in_frames,
+                                           &is_playing, &is_eos_reached);
+
+  EXPECT_GT(frames_in_buffer, 0);
+  EXPECT_GE(offset_in_frames, 0);
+  EXPECT_TRUE(is_playing);
+  EXPECT_TRUE(is_eos_reached);
+
+  // Consume frames in two batches, so we can test if |GetCurrentTime()|
+  // is incrementing in an expected manner.
+  const int frames_to_consume = frames_in_buffer / 4;
+  SbMediaTime new_media_time;
+
+  EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
+
+  renderer_callback_->OnConsumeFrames(frames_to_consume);
+  new_media_time = audio_renderer_->GetCurrentTime();
+  EXPECT_GT(new_media_time, media_time);
+  media_time = new_media_time;
+
+  const int remaining_frames = frames_in_buffer - frames_to_consume;
+  renderer_callback_->OnConsumeFrames(remaining_frames);
+  new_media_time = audio_renderer_->GetCurrentTime();
+  EXPECT_GT(new_media_time, media_time);
+
+  EXPECT_TRUE(audio_renderer_->IsEndOfStreamPlayed());
 }
 
 TEST_F(AudioRendererImplTest, StartPlayBeforePreroll) {
-  Seek(0);
+  {
+    ::testing::InSequence seq;
+    EXPECT_CALL(*audio_renderer_sink_, Stop()).Times(AnyNumber());
+    EXPECT_CALL(
+        *audio_renderer_sink_,
+        Start(kDefaultNumberOfChannels, kDefaultSamplesPerSecond,
+              kDefaultAudioSampleType, kDefaultAudioFrameStorageType, _, _, _));
+  }
 
-  const int kFramesPerBuffer = 1024;
+  Seek(0);
 
   audio_renderer_->Play();
 
-  int frames_written = 0;
+  int frames_written = FillRendererWithDecodedAudioAndWriteEOS();
 
-  while (audio_renderer_->IsSeekingInProgress()) {
-    SbMediaTime pts =
-        frames_written * kSbMediaTimeSecond / kDefaultSamplesPerSecond;
-    WriteSample(CreateInputBuffer(pts));
-    CallConsumedCB();
-    SendDecoderOutput(CreateDecodedAudio(pts, kFramesPerBuffer));
-    frames_written += kFramesPerBuffer;
-  }
-
-  WriteEndOfStream();
   SendDecoderOutput(new DecodedAudio);
 
   SbMediaTime media_time = audio_renderer_->GetCurrentTime();
 
-  while (!audio_renderer_->IsEndOfStreamPlayed()) {
-    SbThreadSleep(kSbTimeMillisecond);
-    SbMediaTime new_media_time = audio_renderer_->GetCurrentTime();
-    EXPECT_GE(new_media_time, media_time);
-    media_time = new_media_time;
-  }
+  int frames_in_buffer;
+  int offset_in_frames;
+  bool is_playing;
+  bool is_eos_reached;
+  renderer_callback_->OnUpdateSourceStatus(&frames_in_buffer, &offset_in_frames,
+                                           &is_playing, &is_eos_reached);
+  EXPECT_GT(frames_in_buffer, 0);
+  EXPECT_GE(offset_in_frames, 0);
+  EXPECT_TRUE(is_playing);
+  EXPECT_TRUE(is_eos_reached);
+
+  // Consume frames in two batches, so we can test if |GetCurrentTime()|
+  // is incrementing in an expected manner.
+  const int frames_to_consume = frames_in_buffer / 4;
+  SbMediaTime new_media_time;
+
+  EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
+
+  renderer_callback_->OnConsumeFrames(frames_to_consume);
+  new_media_time = audio_renderer_->GetCurrentTime();
+  EXPECT_GE(new_media_time, media_time);
+  media_time = new_media_time;
+
+  const int remaining_frames = frames_in_buffer - frames_to_consume;
+  renderer_callback_->OnConsumeFrames(remaining_frames);
+  new_media_time = audio_renderer_->GetCurrentTime();
+  EXPECT_GE(new_media_time, media_time);
+
+  EXPECT_TRUE(audio_renderer_->IsEndOfStreamPlayed());
 }
 
 TEST_F(AudioRendererImplTest, DecoderReturnsEOSWithoutAnyData) {
+  {
+    ::testing::InSequence seq;
+    EXPECT_CALL(*audio_renderer_sink_, Stop()).Times(AnyNumber());
+    EXPECT_CALL(
+        *audio_renderer_sink_,
+        Start(kDefaultNumberOfChannels, kDefaultSamplesPerSecond,
+              kDefaultAudioSampleType, kDefaultAudioFrameStorageType, _, _, _));
+  }
+
   Seek(0);
 
   WriteSample(CreateInputBuffer(0));
@@ -308,6 +445,15 @@
 
 // Test decoders that take many input samples before returning any output.
 TEST_F(AudioRendererImplTest, DecoderConsumeAllInputBeforeReturningData) {
+  {
+    ::testing::InSequence seq;
+    EXPECT_CALL(*audio_renderer_sink_, Stop()).Times(AnyNumber());
+    EXPECT_CALL(
+        *audio_renderer_sink_,
+        Start(kDefaultNumberOfChannels, kDefaultSamplesPerSecond,
+              kDefaultAudioSampleType, kDefaultAudioFrameStorageType, _, _, _));
+  }
+
   Seek(0);
 
   for (int i = 0; i < 128; ++i) {
@@ -335,6 +481,15 @@
 }
 
 TEST_F(AudioRendererImplTest, MoreNumberOfOuputBuffersThanInputBuffers) {
+  {
+    ::testing::InSequence seq;
+    EXPECT_CALL(*audio_renderer_sink_, Stop()).Times(AnyNumber());
+    EXPECT_CALL(
+        *audio_renderer_sink_,
+        Start(kDefaultNumberOfChannels, kDefaultSamplesPerSecond,
+              kDefaultAudioSampleType, kDefaultAudioFrameStorageType, _, _, _));
+  }
+
   Seek(0);
 
   const int kFramesPerBuffer = 1024;
@@ -364,15 +519,52 @@
 
   SbMediaTime media_time = audio_renderer_->GetCurrentTime();
 
-  while (!audio_renderer_->IsEndOfStreamPlayed()) {
-    SbThreadSleep(kSbTimeMillisecond);
-    SbMediaTime new_media_time = audio_renderer_->GetCurrentTime();
-    EXPECT_GE(new_media_time, media_time);
-    media_time = new_media_time;
-  }
+  int frames_in_buffer;
+  int offset_in_frames;
+  bool is_playing;
+  bool is_eos_reached;
+  renderer_callback_->OnUpdateSourceStatus(&frames_in_buffer, &offset_in_frames,
+                                           &is_playing, &is_eos_reached);
+  EXPECT_GT(frames_in_buffer, 0);
+  EXPECT_GE(offset_in_frames, 0);
+  EXPECT_TRUE(is_playing);
+  EXPECT_TRUE(is_eos_reached);
+
+  // Consume frames in two batches, so we can test if |GetCurrentTime()|
+  // is incrementing in an expected manner.
+  const int frames_to_consume = frames_in_buffer / 4;
+  SbMediaTime new_media_time;
+
+  EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
+
+  renderer_callback_->OnConsumeFrames(frames_to_consume);
+  new_media_time = audio_renderer_->GetCurrentTime();
+  EXPECT_GE(new_media_time, media_time);
+  media_time = new_media_time;
+
+  const int remaining_frames = frames_in_buffer - frames_to_consume;
+  renderer_callback_->OnConsumeFrames(remaining_frames);
+  new_media_time = audio_renderer_->GetCurrentTime();
+  EXPECT_GE(new_media_time, media_time);
+
+  EXPECT_TRUE(audio_renderer_->IsEndOfStreamPlayed());
 }
 
 TEST_F(AudioRendererImplTest, LessNumberOfOuputBuffersThanInputBuffers) {
+  {
+    ::testing::InSequence seq;
+    EXPECT_CALL(*audio_renderer_sink_, Stop()).Times(AnyNumber());
+    EXPECT_CALL(*audio_renderer_sink_, HasStarted())
+        .WillRepeatedly(Return(false));
+    EXPECT_CALL(
+        *audio_renderer_sink_,
+        Start(kDefaultNumberOfChannels, kDefaultSamplesPerSecond,
+              kDefaultAudioSampleType, kDefaultAudioFrameStorageType, _, _, _))
+        .WillOnce(SaveArg<6>(&renderer_callback_));
+    EXPECT_CALL(*audio_renderer_sink_, HasStarted())
+        .WillRepeatedly(Return(true));
+  }
+
   Seek(0);
 
   const int kFramesPerBuffer = 1024;
@@ -404,16 +596,113 @@
 
   SbMediaTime media_time = audio_renderer_->GetCurrentTime();
 
-  while (!audio_renderer_->IsEndOfStreamPlayed()) {
-    SbThreadSleep(kSbTimeMillisecond);
-    SbMediaTime new_media_time = audio_renderer_->GetCurrentTime();
-    EXPECT_GE(new_media_time, media_time);
-    media_time = new_media_time;
-  }
+  int frames_in_buffer;
+  int offset_in_frames;
+  bool is_playing;
+  bool is_eos_reached;
+  renderer_callback_->OnUpdateSourceStatus(&frames_in_buffer, &offset_in_frames,
+                                           &is_playing, &is_eos_reached);
+  EXPECT_GT(frames_in_buffer, 0);
+  EXPECT_GE(offset_in_frames, 0);
+  EXPECT_TRUE(is_playing);
+  EXPECT_TRUE(is_eos_reached);
+
+  // Consume frames in two batches, so we can test if |GetCurrentTime()|
+  // is incrementing in an expected manner.
+  const int frames_to_consume = frames_in_buffer / 4;
+  SbMediaTime new_media_time;
+
+  EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
+
+  renderer_callback_->OnConsumeFrames(frames_to_consume);
+  new_media_time = audio_renderer_->GetCurrentTime();
+  EXPECT_GE(new_media_time, media_time);
+  media_time = new_media_time;
+
+  const int remaining_frames = frames_in_buffer - frames_to_consume;
+  renderer_callback_->OnConsumeFrames(remaining_frames);
+  new_media_time = audio_renderer_->GetCurrentTime();
+  EXPECT_GE(new_media_time, media_time);
+
+  EXPECT_TRUE(audio_renderer_->IsEndOfStreamPlayed());
 }
 
-// TODO: Implement test for Seek()
-TEST_F(AudioRendererImplTest, Seek) {}
+TEST_F(AudioRendererImplTest, Seek) {
+  {
+    ::testing::InSequence seq;
+    EXPECT_CALL(*audio_renderer_sink_, Stop()).Times(AnyNumber());
+    EXPECT_CALL(
+        *audio_renderer_sink_,
+        Start(kDefaultNumberOfChannels, kDefaultSamplesPerSecond,
+              kDefaultAudioSampleType, kDefaultAudioFrameStorageType, _, _, _));
+    EXPECT_CALL(*audio_renderer_sink_, Stop());
+    EXPECT_CALL(*audio_decoder_, Reset());
+    EXPECT_CALL(
+        *audio_renderer_sink_,
+        Start(kDefaultNumberOfChannels, kDefaultSamplesPerSecond,
+              kDefaultAudioSampleType, kDefaultAudioFrameStorageType, _, _, _));
+  }
+
+  Seek(0);
+
+  int frames_written = FillRendererWithDecodedAudioAndWriteEOS();
+
+  EXPECT_EQ(audio_renderer_->GetCurrentTime(), 0);
+  EXPECT_FALSE(audio_renderer_->IsSeekingInProgress());
+
+  audio_renderer_->Play();
+
+  SendDecoderOutput(new DecodedAudio);
+
+  SbMediaTime media_time = audio_renderer_->GetCurrentTime();
+
+  int frames_in_buffer;
+  int offset_in_frames;
+  bool is_playing;
+  bool is_eos_reached;
+  renderer_callback_->OnUpdateSourceStatus(&frames_in_buffer, &offset_in_frames,
+                                           &is_playing, &is_eos_reached);
+  EXPECT_GT(frames_in_buffer, 0);
+  EXPECT_GE(offset_in_frames, 0);
+  EXPECT_TRUE(is_playing);
+  EXPECT_TRUE(is_eos_reached);
+
+  // Consume frames in multiple batches, so we can test if |GetCurrentTime()|
+  // is incrementing in an expected manner.
+  const double seek_time = 0.5 * kSbMediaTimeSecond;
+  const int frames_to_consume = frames_in_buffer / 10;
+  SbMediaTime new_media_time;
+
+  EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
+
+  renderer_callback_->OnConsumeFrames(frames_to_consume);
+  new_media_time = audio_renderer_->GetCurrentTime();
+  EXPECT_GE(new_media_time, media_time);
+  Seek(seek_time);
+
+  frames_written = FillRendererWithDecodedAudioAndWriteEOS();
+
+  EXPECT_GE(audio_renderer_->GetCurrentTime(), seek_time);
+  EXPECT_FALSE(audio_renderer_->IsSeekingInProgress());
+
+  audio_renderer_->Play();
+  SendDecoderOutput(new DecodedAudio);
+
+  renderer_callback_->OnUpdateSourceStatus(&frames_in_buffer, &offset_in_frames,
+                                           &is_playing, &is_eos_reached);
+  EXPECT_GT(frames_in_buffer, 0);
+  EXPECT_GE(offset_in_frames, 0);
+  EXPECT_TRUE(is_playing);
+  EXPECT_TRUE(is_eos_reached);
+  const int remaining_frames = frames_in_buffer - offset_in_frames;
+  renderer_callback_->OnConsumeFrames(remaining_frames);
+  new_media_time = audio_renderer_->GetCurrentTime();
+  EXPECT_GE(new_media_time, seek_time);
+
+  EXPECT_TRUE(audio_renderer_->IsEndOfStreamPlayed());
+}
+
+// TODO: Add more Seek tests.
 
 }  // namespace
 }  // namespace testing
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_sink.h b/src/starboard/shared/starboard/player/filter/audio_renderer_sink.h
new file mode 100644
index 0000000..31b517f
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_sink.h
@@ -0,0 +1,70 @@
+// Copyright 2017 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.
+
+#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_SINK_H_
+#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_SINK_H_
+
+#include "starboard/audio_sink.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace player {
+namespace filter {
+
+// The interface used by AudioRendererImpl to output audio samples.
+class AudioRendererSink {
+ public:
+  class RenderCallback {
+   public:
+    virtual void OnUpdateSourceStatus(int* frames_in_buffer,
+                                      int* offset_in_frames,
+                                      bool* is_playing,
+                                      bool* is_eos_reached) = 0;
+    virtual void OnConsumeFrames(int frames_consumed) = 0;
+
+   protected:
+    ~RenderCallback() {}
+  };
+
+  virtual ~AudioRendererSink() {}
+
+  virtual bool IsAudioSampleTypeSupported(
+      SbMediaAudioSampleType audio_sample_type) const = 0;
+  virtual bool IsAudioFrameStorageTypeSupported(
+      SbMediaAudioFrameStorageType audio_frame_storage_type) const = 0;
+  virtual int GetNearestSupportedSampleFrequency(
+      int sampling_frequency_hz) const = 0;
+
+  virtual bool HasStarted() const = 0;
+  virtual void Start(int channels,
+                     int sampling_frequency_hz,
+                     SbMediaAudioSampleType audio_sample_type,
+                     SbMediaAudioFrameStorageType audio_frame_storage_type,
+                     SbAudioSinkFrameBuffers frame_buffers,
+                     int frames_per_channel,
+                     RenderCallback* render_callback) = 0;
+  virtual void Stop() = 0;
+
+  virtual void SetVolume(double volume) = 0;
+  virtual void SetPlaybackRate(double playback_rate) = 0;
+};
+
+}  // namespace filter
+}  // namespace player
+}  // namespace starboard
+}  // namespace shared
+}  // namespace starboard
+
+#endif  // STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_SINK_H_
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc
new file mode 100644
index 0000000..cd4eb6f
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc
@@ -0,0 +1,149 @@
+// Copyright 2017 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/player/filter/audio_renderer_sink_impl.h"
+
+#include "starboard/audio_sink.h"
+#include "starboard/log.h"
+#include "starboard/shared/starboard/thread_checker.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace player {
+namespace filter {
+
+AudioRendererSinkImpl::AudioRendererSinkImpl()
+    : audio_sink_(kSbAudioSinkInvalid),
+      render_callback_(NULL),
+      playback_rate_(1.0),
+      volume_(1.0) {}
+
+AudioRendererSinkImpl::~AudioRendererSinkImpl() {
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
+
+  Stop();
+}
+
+bool AudioRendererSinkImpl::IsAudioSampleTypeSupported(
+    SbMediaAudioSampleType audio_sample_type) const {
+  return SbAudioSinkIsAudioSampleTypeSupported(audio_sample_type);
+}
+
+bool AudioRendererSinkImpl::IsAudioFrameStorageTypeSupported(
+    SbMediaAudioFrameStorageType audio_frame_storage_type) const {
+  return SbAudioSinkIsAudioFrameStorageTypeSupported(audio_frame_storage_type);
+}
+
+int AudioRendererSinkImpl::GetNearestSupportedSampleFrequency(
+    int sampling_frequency_hz) const {
+  return SbAudioSinkGetNearestSupportedSampleFrequency(sampling_frequency_hz);
+}
+
+bool AudioRendererSinkImpl::HasStarted() const {
+  return SbAudioSinkIsValid(audio_sink_);
+}
+
+void AudioRendererSinkImpl::Start(
+    int channels,
+    int sampling_frequency_hz,
+    SbMediaAudioSampleType audio_sample_type,
+    SbMediaAudioFrameStorageType audio_frame_storage_type,
+    SbAudioSinkFrameBuffers frame_buffers,
+    int frames_per_channel,
+    RenderCallback* render_callback) {
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
+  SB_DCHECK(!HasStarted());
+
+  Stop();
+  render_callback_ = render_callback;
+  audio_sink_ = SbAudioSinkCreate(
+      channels, sampling_frequency_hz, audio_sample_type,
+      audio_frame_storage_type, frame_buffers, frames_per_channel,
+      &AudioRendererSinkImpl::UpdateSourceStatusFunc,
+      &AudioRendererSinkImpl::ConsumeFramesFunc, this);
+  // TODO: Remove SetPlaybackRate() support from audio sink as it only need to
+  // support play/pause.
+  audio_sink_->SetPlaybackRate(playback_rate_);
+  audio_sink_->SetVolume(volume_);
+}
+
+void AudioRendererSinkImpl::Stop() {
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
+
+  if (HasStarted()) {
+    SbAudioSinkDestroy(audio_sink_);
+    audio_sink_ = kSbAudioSinkInvalid;
+    render_callback_ = NULL;
+  }
+}
+
+void AudioRendererSinkImpl::SetVolume(double volume) {
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
+
+  volume_ = volume;
+  if (HasStarted()) {
+    audio_sink_->SetVolume(volume);
+  }
+}
+
+void AudioRendererSinkImpl::SetPlaybackRate(double playback_rate) {
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
+  SB_DCHECK(playback_rate == 0.0 || playback_rate == 1.0)
+      << "Playback rate on audio sink can only be set to 0 or 1, "
+      << "but is now set to " << playback_rate;
+
+  playback_rate_ = playback_rate;
+  if (HasStarted()) {
+    // TODO: Remove SetPlaybackRate() support from audio sink as it only need to
+    // support play/pause.
+    audio_sink_->SetPlaybackRate(playback_rate);
+  }
+}
+
+// static
+void AudioRendererSinkImpl::UpdateSourceStatusFunc(int* frames_in_buffer,
+                                                   int* offset_in_frames,
+                                                   bool* is_playing,
+                                                   bool* is_eos_reached,
+                                                   void* context) {
+  AudioRendererSinkImpl* audio_renderer_sink =
+      static_cast<AudioRendererSinkImpl*>(context);
+  SB_DCHECK(audio_renderer_sink);
+  SB_DCHECK(audio_renderer_sink->render_callback_);
+  SB_DCHECK(frames_in_buffer);
+  SB_DCHECK(offset_in_frames);
+  SB_DCHECK(is_playing);
+  SB_DCHECK(is_eos_reached);
+
+  audio_renderer_sink->render_callback_->OnUpdateSourceStatus(
+      frames_in_buffer, offset_in_frames, is_playing, is_eos_reached);
+}
+
+// static
+void AudioRendererSinkImpl::ConsumeFramesFunc(int frames_consumed,
+                                              void* context) {
+  AudioRendererSinkImpl* audio_renderer_sink =
+      static_cast<AudioRendererSinkImpl*>(context);
+  SB_DCHECK(audio_renderer_sink);
+  SB_DCHECK(audio_renderer_sink->render_callback_);
+
+  audio_renderer_sink->render_callback_->OnConsumeFrames(frames_consumed);
+}
+
+}  // namespace filter
+}  // namespace player
+}  // namespace starboard
+}  // namespace shared
+}  // namespace starboard
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h b/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h
new file mode 100644
index 0000000..ea626f4
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h
@@ -0,0 +1,77 @@
+// Copyright 2017 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.
+
+#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_SINK_IMPL_H_
+#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_SINK_IMPL_H_
+
+#include "starboard/shared/starboard/player/filter/audio_renderer_sink.h"
+
+#include "starboard/shared/starboard/audio_sink/audio_sink_internal.h"
+#include "starboard/shared/starboard/thread_checker.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace player {
+namespace filter {
+
+class AudioRendererSinkImpl : public AudioRendererSink {
+ public:
+  AudioRendererSinkImpl();
+  ~AudioRendererSinkImpl() SB_OVERRIDE;
+
+ private:
+  // AudioRendererSink methods
+  bool IsAudioSampleTypeSupported(
+      SbMediaAudioSampleType audio_sample_type) const SB_OVERRIDE;
+  bool IsAudioFrameStorageTypeSupported(
+      SbMediaAudioFrameStorageType audio_frame_storage_type) const SB_OVERRIDE;
+  int GetNearestSupportedSampleFrequency(int sampling_frequency_hz) const
+      SB_OVERRIDE;
+
+  bool HasStarted() const SB_OVERRIDE;
+  void Start(int channels,
+             int sampling_frequency_hz,
+             SbMediaAudioSampleType audio_sample_type,
+             SbMediaAudioFrameStorageType audio_frame_storage_type,
+             SbAudioSinkFrameBuffers frame_buffers,
+             int frames_per_channel,
+             RenderCallback* render_callback) SB_OVERRIDE;
+  void Stop() SB_OVERRIDE;
+
+  void SetVolume(double volume) SB_OVERRIDE;
+  void SetPlaybackRate(double playback_rate) SB_OVERRIDE;
+
+  // SbAudioSink callbacks
+  static void UpdateSourceStatusFunc(int* frames_in_buffer,
+                                     int* offset_in_frames,
+                                     bool* is_playing,
+                                     bool* is_eos_reached,
+                                     void* context);
+  static void ConsumeFramesFunc(int frames_consumed, void* context);
+
+  ThreadChecker thread_checker_;
+  SbAudioSinkPrivate* audio_sink_;
+  RenderCallback* render_callback_;
+  double playback_rate_;
+  double volume_;
+};
+
+}  // namespace filter
+}  // namespace player
+}  // namespace starboard
+}  // namespace shared
+}  // namespace starboard
+
+#endif  //  STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_SINK_IMPL_H_
diff --git a/src/starboard/shared/starboard/player/filter/mock_audio_renderer_sink.h b/src/starboard/shared/starboard/player/filter/mock_audio_renderer_sink.h
new file mode 100644
index 0000000..f57d0b4
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/mock_audio_renderer_sink.h
@@ -0,0 +1,67 @@
+// Copyright 2017 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.
+
+#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_MOCK_AUDIO_RENDERER_SINK_H_
+#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_MOCK_AUDIO_RENDERER_SINK_H_
+
+#include "starboard/shared/starboard/player/filter/audio_renderer_sink.h"
+
+#include "starboard/media.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace player {
+namespace filter {
+
+class MockAudioRendererSink : public AudioRendererSink {
+ public:
+  MOCK_CONST_METHOD1(IsAudioSampleTypeSupported,
+                     bool(SbMediaAudioSampleType audio_sample_type));
+  MOCK_CONST_METHOD1(
+      IsAudioFrameStorageTypeSupported,
+      bool(SbMediaAudioFrameStorageType audio_frame_storage_type));
+  MOCK_CONST_METHOD1(GetNearestSupportedSampleFrequency,
+                     int(int sampling_frequency_hz));
+  MOCK_CONST_METHOD0(HasStarted, bool());
+  MOCK_METHOD7(Start,
+               void(int channels,
+                    int sampling_frequency_hz,
+                    SbMediaAudioSampleType audio_sample_type,
+                    SbMediaAudioFrameStorageType audio_frame_storage_type,
+                    SbAudioSinkFrameBuffers frame_buffers,
+                    int frames_per_channel,
+                    RenderCallback* render_callback));
+  MOCK_METHOD0(Stop, void());
+  MOCK_METHOD1(SetVolume, void(double volume));
+  MOCK_METHOD1(SetPlaybackRate, void(double playback_rate));
+
+  void SetHasStarted(bool started) { has_started_ = started; }
+  const bool* HasStartedPointer() { return &has_started_; }
+
+ private:
+  bool has_started_ = false;
+  SbMediaAudioSampleType audio_sample_type_ = kSbMediaAudioSampleTypeFloat32;
+  SbMediaAudioFrameStorageType audio_frame_storage_type_ =
+      kSbMediaAudioFrameStorageTypeInterleaved;
+};
+
+}  // namespace filter
+}  // namespace player
+}  // namespace starboard
+}  // namespace shared
+}  // namespace starboard
+
+#endif  // STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_MOCK_AUDIO_RENDERER_SINK_H_
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 7e4e0bd..487c1d7 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
@@ -18,6 +18,7 @@
 #include "starboard/log.h"
 #include "starboard/shared/starboard/player/closure.h"
 #include "starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h"
 #include "starboard/shared/starboard/player/filter/player_components.h"
 #include "starboard/shared/starboard/player/filter/video_renderer_impl_internal.h"
 #include "starboard/shared/starboard/player/job_queue.h"
@@ -194,11 +195,12 @@
   StubAudioDecoder* audio_decoder =
       new StubAudioDecoder(audio_parameters.audio_header);
   StubVideoDecoder* video_decoder = new StubVideoDecoder();
-  AudioRendererImpl* audio_renderer =
-      new AudioRendererImpl(scoped_ptr<AudioDecoder>(audio_decoder).Pass(),
-                            audio_parameters.audio_header);
-  VideoRendererImpl* video_renderer = new VideoRendererImpl(
-      scoped_ptr<HostedVideoDecoder>(video_decoder).Pass());
+  AudioRendererImpl* audio_renderer = new AudioRendererImpl(
+      make_scoped_ptr<AudioDecoder>(audio_decoder),
+      make_scoped_ptr<AudioRendererSink>(new AudioRendererSinkImpl),
+      audio_parameters.audio_header);
+  VideoRendererImpl* video_renderer =
+      new VideoRendererImpl(make_scoped_ptr<HostedVideoDecoder>(video_decoder));
 
   return scoped_ptr<PlayerComponents>(
       new PlayerComponents(audio_renderer, video_renderer));
diff --git a/src/starboard/shared/starboard/player/player_create.cc b/src/starboard/shared/starboard/player/player_create.cc
index 3a948db..e29c6c0 100644
--- a/src/starboard/shared/starboard/player/player_create.cc
+++ b/src/starboard/shared/starboard/player/player_create.cc
@@ -30,6 +30,10 @@
     FilterBasedPlayerWorkerHandler;
 using starboard::shared::starboard::player::PlayerWorker;
 
+#if SB_HAS(PLAYER_WITH_URL)
+// No implementation : use SbPlayerCreateWithUrl instead.
+#else
+
 SbPlayer SbPlayerCreate(SbWindow window,
                         SbMediaVideoCodec video_codec,
                         SbMediaAudioCodec audio_codec,
@@ -80,3 +84,5 @@
                              decoder_status_func, player_status_func, context,
                              handler.Pass());
 }
+
+#endif  // SB_HAS(PLAYER_WITH_URL)
diff --git a/src/starboard/shared/starboard/player/player_output_mode_supported.cc b/src/starboard/shared/starboard/player/player_output_mode_supported.cc
index 25dcfe6..518845c 100644
--- a/src/starboard/shared/starboard/player/player_output_mode_supported.cc
+++ b/src/starboard/shared/starboard/player/player_output_mode_supported.cc
@@ -18,9 +18,20 @@
 #include "starboard/log.h"
 #include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
 
+#if SB_HAS(PLAYER_WITH_URL)
+
+bool SbPlayerOutputModeSupportedWithUrl(SbPlayerOutputMode output_mode) {
+  // Stub.
+  return false;
+}
+
+#else
+
 bool SbPlayerOutputModeSupported(SbPlayerOutputMode output_mode,
                                  SbMediaVideoCodec codec,
                                  SbDrmSystem drm_system) {
   return starboard::shared::starboard::player::filter::VideoDecoder::
       OutputModeSupported(output_mode, codec, drm_system);
 }
+
+#endif  // SB_HAS(PLAYER_WITH_URL)
diff --git a/src/starboard/shared/stub/player_create_with_url.cc b/src/starboard/shared/stub/player_create_with_url.cc
new file mode 100644
index 0000000..cbad413
--- /dev/null
+++ b/src/starboard/shared/stub/player_create_with_url.cc
@@ -0,0 +1,39 @@
+// Copyright 2017 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/player.h"
+
+#if !SB_HAS(PLAYER)
+#error "SbPlayerCreateWithUrl requires SB_HAS(PLAYER)."
+#endif
+
+#if SB_HAS(PLAYER_WITH_URL)
+
+SbPlayer SbPlayerCreateWithUrl(
+    const char* /* url */,
+    SbWindow /* window */,
+    SbMediaTime /* duration_pts */,
+    SbPlayerStatusFunc /* player_status_func */,
+    SbPlayerEncryptedMediaInitDataEncounteredCB /* cb */,
+    void* /* context */) {
+  // Stub.
+  return kSbPlayerInvalid;
+}
+
+// TODO: Actually move this to a separate file or get rid of these URL
+// player stubs altogether.
+void SbPlayerSetDrmSystem(SbPlayer player, SbDrmSystem drm_system) { /* Stub */
+}
+
+#endif  // SB_HAS(PLAYER_WITH_URL)
diff --git a/src/starboard/shared/uwp/analog_thumbstick_input.cc b/src/starboard/shared/uwp/analog_thumbstick_input.cc
index e4ab130..202a12d 100644
--- a/src/starboard/shared/uwp/analog_thumbstick_input.cc
+++ b/src/starboard/shared/uwp/analog_thumbstick_input.cc
@@ -1,100 +1,100 @@
-/*

- * Copyright 2017 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/uwp/analog_thumbstick_input.h"

-

-#include <Windows.Gaming.Input.h>

-#include <algorithm>

-

-#include "starboard/log.h"

-#include "starboard/shared/win32/error_utils.h"

-#include "starboard/types.h"

-

-#pragma comment(lib, "xinput9_1_0.lib")

-

-using Windows::Foundation::Collections::IVectorView;

-using Windows::Gaming::Input::Gamepad;

-using Windows::Gaming::Input::GamepadReading;

-using Windows::Gaming::Input::RawGameController;

-

-namespace starboard {

-namespace shared {

-namespace uwp {

-namespace {

-

-const int kMaxPlayerCounter = 4;

-const float kDeadZoneThreshold = .24f;

-

-float ApplyLinearDeadZone(float value, float maxValue, float deadZoneSize) {

-  if (value < -deadZoneSize) {

-    // Increase negative values to remove the deadzone discontinuity.

-    value += deadZoneSize;

-  } else if (value > deadZoneSize) {

-    // Decrease positive values to remove the deadzone discontinuity.

-    value -= deadZoneSize;

-  } else {

-    // Values inside the deadzone come out zero.

-    return 0;

-  }

-

-  // Scale into 0-1 range.

-  float scaledValue = value / (maxValue - deadZoneSize);

-  return std::max(-1.f, std::min(scaledValue, 1.f));

-}

-

-void ApplyStickDeadZone(float x,

-                        float y,

-                        float max_value,

-                        float dead_zone_size,

-                        float* result_x,

-                        float* result_y) {

-  *result_x = ApplyLinearDeadZone(x, max_value, dead_zone_size);

-  *result_y = ApplyLinearDeadZone(y, max_value, dead_zone_size);

-}

-

-ThumbSticks ReadThumbStick(Gamepad ^ controller) {

-  ThumbSticks output;

-  GamepadReading reading = controller->GetCurrentReading();

-

-  ApplyStickDeadZone(static_cast<float>(reading.LeftThumbstickX),

-                     static_cast<float>(reading.LeftThumbstickY), 1.f,

-                     kDeadZoneThreshold, &output.left_x, &output.left_y);

-

-  ApplyStickDeadZone(static_cast<float>(reading.RightThumbstickX),

-                     static_cast<float>(reading.RightThumbstickY), 1.f,

-                     kDeadZoneThreshold, &output.right_x, &output.right_y);

-  return output;

-}

-}  // namespace

-

-void GetGamepadThumbSticks(std::vector<ThumbSticks>* destination) {

-  destination->erase(destination->begin(), destination->end());

-

-  // This profiled to an average time of 33us to execute.

-  IVectorView<Gamepad ^> ^ gamepads = Gamepad::Gamepads;

-

-  // This profiled to take on average 9us of time to read controller state.

-  const uint32_t n = gamepads->Size;

-  for (uint32_t i = 0; i < n; ++i) {

-    Gamepad ^ gamepad = gamepads->GetAt(i);

-    ThumbSticks thumb_stick = ReadThumbStick(gamepad);

-    destination->push_back(thumb_stick);

-  }

-}

-

-}  // namespace uwp

-}  // namespace shared

-}  // namespace starboard

+/*
+ * Copyright 2017 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/uwp/analog_thumbstick_input.h"
+
+#include <Windows.Gaming.Input.h>
+#include <algorithm>
+
+#include "starboard/log.h"
+#include "starboard/shared/win32/error_utils.h"
+#include "starboard/types.h"
+
+#pragma comment(lib, "xinput9_1_0.lib")
+
+using Windows::Foundation::Collections::IVectorView;
+using Windows::Gaming::Input::Gamepad;
+using Windows::Gaming::Input::GamepadReading;
+using Windows::Gaming::Input::RawGameController;
+
+namespace starboard {
+namespace shared {
+namespace uwp {
+namespace {
+
+const int kMaxPlayerCounter = 4;
+const float kDeadZoneThreshold = .24f;
+
+float ApplyLinearDeadZone(float value, float maxValue, float deadZoneSize) {
+  if (value < -deadZoneSize) {
+    // Increase negative values to remove the deadzone discontinuity.
+    value += deadZoneSize;
+  } else if (value > deadZoneSize) {
+    // Decrease positive values to remove the deadzone discontinuity.
+    value -= deadZoneSize;
+  } else {
+    // Values inside the deadzone come out zero.
+    return 0;
+  }
+
+  // Scale into 0-1 range.
+  float scaledValue = value / (maxValue - deadZoneSize);
+  return std::max(-1.f, std::min(scaledValue, 1.f));
+}
+
+void ApplyStickDeadZone(float x,
+                        float y,
+                        float max_value,
+                        float dead_zone_size,
+                        float* result_x,
+                        float* result_y) {
+  *result_x = ApplyLinearDeadZone(x, max_value, dead_zone_size);
+  *result_y = ApplyLinearDeadZone(y, max_value, dead_zone_size);
+}
+
+ThumbSticks ReadThumbStick(Gamepad ^ controller) {
+  ThumbSticks output;
+  GamepadReading reading = controller->GetCurrentReading();
+
+  ApplyStickDeadZone(static_cast<float>(reading.LeftThumbstickX),
+                     static_cast<float>(reading.LeftThumbstickY), 1.f,
+                     kDeadZoneThreshold, &output.left_x, &output.left_y);
+
+  ApplyStickDeadZone(static_cast<float>(reading.RightThumbstickX),
+                     static_cast<float>(reading.RightThumbstickY), 1.f,
+                     kDeadZoneThreshold, &output.right_x, &output.right_y);
+  return output;
+}
+}  // namespace
+
+void GetGamepadThumbSticks(std::vector<ThumbSticks>* destination) {
+  destination->erase(destination->begin(), destination->end());
+
+  // This profiled to an average time of 33us to execute.
+  IVectorView<Gamepad ^> ^ gamepads = Gamepad::Gamepads;
+
+  // This profiled to take on average 9us of time to read controller state.
+  const uint32_t n = gamepads->Size;
+  for (uint32_t i = 0; i < n; ++i) {
+    Gamepad ^ gamepad = gamepads->GetAt(i);
+    ThumbSticks thumb_stick = ReadThumbStick(gamepad);
+    destination->push_back(thumb_stick);
+  }
+}
+
+}  // namespace uwp
+}  // namespace shared
+}  // namespace starboard
diff --git a/src/starboard/shared/uwp/analog_thumbstick_input.h b/src/starboard/shared/uwp/analog_thumbstick_input.h
index 490bc23..3af0d42 100644
--- a/src/starboard/shared/uwp/analog_thumbstick_input.h
+++ b/src/starboard/shared/uwp/analog_thumbstick_input.h
@@ -1,44 +1,44 @@
-/*

- * Copyright 2017 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.

- */

-

-#ifndef STARBOARD_SHARED_UWP_ANALOG_THUMBSTICK_INPUT_H_

-#define STARBOARD_SHARED_UWP_ANALOG_THUMBSTICK_INPUT_H_

-

-#include <vector>

-

-#include "starboard/types.h"

-

-namespace starboard {

-namespace shared {

-namespace uwp {

-

-struct ThumbSticks {

-  float left_x = 0.0f;

-  float left_y = 0.0f;

-  float right_x = 0.0f;

-  float right_y = 0.0f;

-};

-

-// Reads all connected game pads and stores the joystick states in the

-// destination vector. Note that the destination vector is unconditionally

-// cleared before being populated.

-void GetGamepadThumbSticks(std::vector<ThumbSticks>* destination);

-

-}  // namespace uwp

-}  // namespace shared

-}  // namespace starboard

-

-#endif  // STARBOARD_SHARED_UWP_ANALOG_THUMBSTICK_INPUT_H_

+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef STARBOARD_SHARED_UWP_ANALOG_THUMBSTICK_INPUT_H_
+#define STARBOARD_SHARED_UWP_ANALOG_THUMBSTICK_INPUT_H_
+
+#include <vector>
+
+#include "starboard/types.h"
+
+namespace starboard {
+namespace shared {
+namespace uwp {
+
+struct ThumbSticks {
+  float left_x = 0.0f;
+  float left_y = 0.0f;
+  float right_x = 0.0f;
+  float right_y = 0.0f;
+};
+
+// Reads all connected game pads and stores the joystick states in the
+// destination vector. Note that the destination vector is unconditionally
+// cleared before being populated.
+void GetGamepadThumbSticks(std::vector<ThumbSticks>* destination);
+
+}  // namespace uwp
+}  // namespace shared
+}  // namespace starboard
+
+#endif  // STARBOARD_SHARED_UWP_ANALOG_THUMBSTICK_INPUT_H_
diff --git a/src/starboard/shared/uwp/app_accessors.h b/src/starboard/shared/uwp/app_accessors.h
new file mode 100644
index 0000000..5c279a4
--- /dev/null
+++ b/src/starboard/shared/uwp/app_accessors.h
@@ -0,0 +1,53 @@
+// Copyright 2017 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.
+
+#ifndef STARBOARD_SHARED_UWP_APP_ACCESSORS_H_
+#define STARBOARD_SHARED_UWP_APP_ACCESSORS_H_
+
+// A set of application and main-thread accessors
+// so as to avoid including application_uwp.h
+
+#include <agile.h>
+
+namespace starboard {
+namespace shared {
+namespace uwp {
+
+// Returns the main window's CoreDispatcher.
+Platform::Agile<Windows::UI::Core::CoreDispatcher> GetDispatcher();
+
+// Returns the main window's SystemMediaTransportControls.
+Platform::Agile<Windows::Media::SystemMediaTransportControls>
+    GetTransportControls();
+
+// Asks the screen to remain active via
+// Windows::System::DisplayRequest->RequestActive()
+void DisplayRequestActive();
+
+// Releases previous screen active request via
+// Windows::System::DisplayRequest->RequestRelease()
+void DisplayRequestRelease();
+
+// Schedules a lambda to run on the main thread and returns immediately.
+template<typename T>
+void RunInMainThreadAsync(const T& lambda) {
+  GetDispatcher()->RunAsync(
+    CoreDispatcherPriority::Normal,
+    ref new DispatchedHandler(lambda));
+}
+
+}  // namespace uwp
+}  // namespace shared
+}  // namespace starboard
+#endif  // STARBOARD_SHARED_UWP_APP_ACCESSORS_H_
diff --git a/src/starboard/shared/uwp/application_uwp.cc b/src/starboard/shared/uwp/application_uwp.cc
index 8087ee5..d9bfee3 100644
--- a/src/starboard/shared/uwp/application_uwp.cc
+++ b/src/starboard/shared/uwp/application_uwp.cc
@@ -18,6 +18,7 @@
 #include <mfapi.h>
 #include <ppltasks.h>
 #include <windows.h>
+#include <windows.system.display.h>
 #include <D3D11.h>
 
 #include <memory>
@@ -32,6 +33,7 @@
 #include "starboard/shared/starboard/audio_sink/audio_sink_internal.h"
 #include "starboard/shared/starboard/player/video_frame_internal.h"
 #include "starboard/shared/uwp/analog_thumbstick_input_thread.h"
+#include "starboard/shared/uwp/app_accessors.h"
 #include "starboard/shared/uwp/async_utils.h"
 #include "starboard/shared/uwp/log_file_impl.h"
 #include "starboard/shared/uwp/window_internal.h"
@@ -47,7 +49,7 @@
 using starboard::shared::starboard::Application;
 using starboard::shared::starboard::CommandLine;
 using starboard::shared::uwp::ApplicationUwp;
-using starboard::shared::uwp::GetArgvZero;
+using starboard::shared::uwp::RunInMainThreadAsync;
 using starboard::shared::uwp::WaitForResult;
 using starboard::shared::win32::stringToPlatformString;
 using starboard::shared::win32::wchar_tToUTF8;
@@ -100,9 +102,32 @@
 
 const char kDialParamPrefix[] = "cobalt-dial:?";
 const char kLogPathSwitch[] = "xb1_log_file";
+const char kStarboardArgumentsPath[] = "arguments\\starboard_arguments.txt";
+const int64_t kMaxArgumentFileSizeBytes = 4 * 1024 * 1024;
 
 int main_return_value = 0;
 
+// IDisplayRequest is both "non-agile" and apparently
+// incompatible with Platform::Agile (it doesn't fully implement
+// a thread marshaller). We must neither use ComPtr or Platform::Agile
+// here. We manually create, access release on the main app thread only.
+ABI::Windows::System::Display::IDisplayRequest* display_request = nullptr;
+
+// If an argv[0] is required, fill it in with the result of
+// GetModuleFileName()
+std::string GetArgvZero() {
+  const size_t kMaxModuleNameSize = SB_FILE_MAX_NAME;
+  wchar_t buffer[kMaxModuleNameSize];
+  DWORD result = GetModuleFileName(NULL, buffer, kMaxModuleNameSize);
+  std::string arg;
+  if (result == 0) {
+    arg = "unknown";
+  } else {
+    arg = wchar_tToUTF8(buffer, result).c_str();
+  }
+  return arg;
+}
+
 int MakeDeviceId() {
   // TODO: Devices MIGHT have colliding hashcodes. Some other unique int
   // ID generation tool would be better.
@@ -115,6 +140,20 @@
 
 #if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
 
+void SplitArgumentsIntoVector(std::string* args,
+                              std::vector<std::string> *result) {
+  SB_DCHECK(args);
+  SB_DCHECK(result);
+  while (!args->empty()) {
+    size_t next = args->find(';');
+    result->push_back(args->substr(0, next));
+    if (next == std::string::npos) {
+      return;
+    }
+    *args = args->substr(next + 1);
+  }
+}
+
 // Parses a starboard: URI scheme by splitting args at ';' boundaries.
 std::vector<std::string> ParseStarboardUri(const std::string& uri) {
   std::vector<std::string> result;
@@ -126,18 +165,41 @@
   }
 
   std::string args = uri.substr(index + 1);
+  SplitArgumentsIntoVector(&args, &result);
 
-  while (!args.empty()) {
-    size_t next = args.find(';');
-    result.push_back(args.substr(0, next));
-    if (next == std::string::npos) {
-      return result;
-    }
-    args = args.substr(next + 1);
-  }
   return result;
 }
 
+void AddArgumentsFromFile(const char* path,
+  std::vector<std::string>* args) {
+  starboard::ScopedFile file(path, kSbFileOpenOnly | kSbFileRead);
+  if (!file.IsValid()) {
+    SB_LOG(INFO) << path << " is not valid for arguments.";
+    return;
+  }
+
+  int64_t file_size = file.GetSize();
+  if (file_size > kMaxArgumentFileSizeBytes) {
+    SB_DLOG(ERROR) << "The arguments file is too big.";
+    return;
+  }
+
+  if (file_size <= 0) {
+    SB_DLOG(INFO) << "Arguments file is empty.";
+    return;
+  }
+
+  std::string argument_string(file_size, '\0');
+  int return_value = file.ReadAll(&argument_string[0], file_size);
+  if (return_value < 0) {
+    SB_DLOG(ERROR) << "Error while reading arguments from file.";
+    return;
+  }
+  argument_string.resize(return_value);
+
+  SplitArgumentsIntoVector(&argument_string, args);
+}
+
 #endif  // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
 
 std::unique_ptr<Application::Event> MakeDeepLinkEvent(
@@ -194,8 +256,8 @@
       : callback_(callback), user_data_(user_data) {
     SB_DCHECK(type == kSbSystemPlatformErrorTypeConnectionError);
 
-    ApplicationUwp* app = ApplicationUwp::Get();
-    app->RunInMainThreadAsync([this, callback, user_data, app]() {
+    RunInMainThreadAsync([this, callback, user_data]() {
+      ApplicationUwp* app = ApplicationUwp::Get();
       MessageDialog^ dialog = ref new MessageDialog(
           app->GetString("UNABLE_TO_CONTACT_YOUTUBE_1",
               "Sorry, could not connect to YouTube."));
@@ -232,7 +294,7 @@
   }
 
   void Clear() {
-    ApplicationUwp::Get()->RunInMainThreadAsync([this]() {
+    RunInMainThreadAsync([this]() {
       dialog_operation_->Cancel();
     });
   }
@@ -249,6 +311,14 @@
 
   // IFrameworkView methods.
   virtual void Initialize(CoreApplicationView^ applicationView) {
+    // The following incantation creates a DisplayRequest and obtains
+    // it's underlying COM interface.
+    ComPtr<IInspectable> inspectable = reinterpret_cast<IInspectable*>(
+        ref new Windows::System::Display::DisplayRequest());
+    ComPtr<ABI::Windows::System::Display::IDisplayRequest> dr;
+    inspectable.As(&dr);
+    display_request = dr.Detach();
+
     SbAudioSinkPrivate::Initialize();
     CoreApplication::Suspending +=
         ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending);
@@ -295,12 +365,20 @@
     window->KeyDown += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(
       this, &App::OnKeyDown);
   }
-  virtual void Load(Platform::String^ entryPoint) {}
+
+  virtual void Load(Platform::String^ entry_point) {
+    entry_point_ = wchar_tToUTF8(entry_point->Data());
+  }
+
   virtual void Run() {
     main_return_value = application_.Run(
         static_cast<int>(argv_.size()), const_cast<char**>(argv_.data()));
   }
-  virtual void Uninitialize() { SbAudioSinkPrivate::TearDown(); }
+  virtual void Uninitialize() {
+    SbAudioSinkPrivate::TearDown();
+    display_request->Release();
+    display_request = nullptr;
+  }
 
   void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) {
     SB_DLOG(INFO) << "Suspending application.";
@@ -387,9 +465,8 @@
           kDialParamPrefix + sbwin32::platformStringToString(arguments);
         ProcessDeepLinkUri(&uri_string);
       } else {
-        const char kYouTubeTVurl[] = "--url=https://www.youtube.com/tv?";
         std::string activation_args =
-            kYouTubeTVurl + sbwin32::platformStringToString(arguments);
+            entry_point_ + "?" + sbwin32::platformStringToString(arguments);
         SB_DLOG(INFO) << "Dial Activation url: " << activation_args;
         args_.push_back(GetArgvZero());
         args_.push_back(activation_args);
@@ -405,7 +482,23 @@
     if (!previously_activated_) {
       if (!command_line_set) {
         args_.push_back(GetArgvZero());
-        argv_.push_back(args_.begin()->c_str());
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
+        char content_directory[SB_FILE_MAX_NAME];
+        content_directory[0] = '\0';
+        if (SbSystemGetPath(kSbSystemPathContentDirectory,
+                            content_directory,
+                            SB_ARRAY_SIZE_INT(content_directory))) {
+          std::string arguments_file_path = content_directory;
+          arguments_file_path += SB_FILE_SEP_STRING;
+          arguments_file_path += kStarboardArgumentsPath;
+          AddArgumentsFromFile(arguments_file_path.c_str(), &args_);
+        }
+#endif  // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
+
+        for (auto& arg : args_) {
+          argv_.push_back(arg.c_str());
+        }
+        argv_.push_back(entry_point_.c_str());
         ApplicationUwp::Get()->SetCommandLine(
             static_cast<int>(argv_.size()), argv_.data());
       }
@@ -413,6 +506,8 @@
       ApplicationUwp* application_uwp = ApplicationUwp::Get();
       CommandLine* command_line =
           ::starboard::shared::uwp::GetCommandLinePointer(application_uwp);
+
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
       if (command_line->HasSwitch(kLogPathSwitch)) {
         std::string switch_val = command_line->GetSwitchValue(kLogPathSwitch);
         sbuwp::OpenLogFile(
@@ -443,8 +538,9 @@
         } catch(Platform::Exception^) {
           SB_LOG(ERROR) << "Unable to open log file in RemovableDevices";
         }
-#endif
+#endif  // !defined(COBALT_BUILD_TYPE_GOLD)
       }
+#endif  // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
       SB_LOG(INFO) << "Starting " << GetBinaryName();
 
       CoreWindow::GetForCurrentThread()->Activate();
@@ -453,7 +549,7 @@
       // interacting with them, some things are disallowed during activation
       // (such as exiting), and DispatchStart (for example) runs
       // automated tests synchronously.
-      ApplicationUwp::Get()->RunInMainThreadAsync([this]() {
+      RunInMainThreadAsync([this]() {
         ApplicationUwp::Get()->DispatchStart();
       });
     }
@@ -498,6 +594,7 @@
     return false;
   }
 
+  std::string entry_point_;
   bool previously_activated_;
   bool has_internet_access_;
   // Only valid if previously_activated_ is true
@@ -520,21 +617,6 @@
 namespace shared {
 namespace uwp {
 
-// If an argv[0] is required, fill it in with the result of
-// GetModuleFileName()
-std::string GetArgvZero() {
-  const size_t kMaxModuleNameSize = SB_FILE_MAX_NAME;
-  wchar_t buffer[kMaxModuleNameSize];
-  DWORD result = GetModuleFileName(NULL, buffer, kMaxModuleNameSize);
-  std::string arg;
-  if (result == 0) {
-    arg = "unknown";
-  } else {
-    arg = wchar_tToUTF8(buffer, result).c_str();
-  }
-  return arg;
-}
-
 ApplicationUwp::ApplicationUwp()
     : window_(kSbWindowInvalid),
       localized_strings_(SbSystemGetLocaleId()),
@@ -771,6 +853,31 @@
   return success;
 }
 
+Platform::Agile<Windows::UI::Core::CoreDispatcher> GetDispatcher() {
+  return ApplicationUwp::Get()->GetDispatcher();
+}
+
+Platform::Agile<Windows::Media::SystemMediaTransportControls>
+    GetTransportControls() {
+  return ApplicationUwp::Get()->GetTransportControls();
+}
+
+void DisplayRequestActive() {
+  RunInMainThreadAsync([]() {
+    if (display_request != nullptr) {
+      display_request->RequestActive();
+    }
+  });
+}
+
+void DisplayRequestRelease() {
+  RunInMainThreadAsync([]() {
+    if (display_request != nullptr) {
+      display_request->RequestRelease();
+    }
+  });
+}
+
 }  // namespace uwp
 }  // namespace shared
 }  // namespace starboard
diff --git a/src/starboard/shared/uwp/application_uwp.h b/src/starboard/shared/uwp/application_uwp.h
index f961b79..5e7447b 100644
--- a/src/starboard/shared/uwp/application_uwp.h
+++ b/src/starboard/shared/uwp/application_uwp.h
@@ -1,164 +1,167 @@
-// Copyright 2017 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.

-

-#ifndef STARBOARD_SHARED_UWP_APPLICATION_UWP_H_

-#define STARBOARD_SHARED_UWP_APPLICATION_UWP_H_

-

-#include <agile.h>

-#include <string>

-#include <unordered_map>

-

-#include "starboard/configuration.h"

-#include "starboard/input.h"

-#include "starboard/key.h"

-#include "starboard/mutex.h"

-#include "starboard/shared/internal_only.h"

-#include "starboard/shared/starboard/application.h"

-#include "starboard/shared/starboard/command_line.h"

-#include "starboard/shared/starboard/localized_strings.h"

-#include "starboard/shared/uwp/analog_thumbstick_input_thread.h"

-#include "starboard/types.h"

-#include "starboard/window.h"

-

-namespace starboard {

-namespace shared {

-namespace uwp {

-

-using Windows::Media::Protection::HdcpSession;

-

-// Returns win32's GetModuleFileName(). For cases where we'd like an argv[0].

-std::string GetArgvZero();

-

-// Including <agile.h>, will eventually include <windows.h>, which includes

-// C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um\processenv.h,

-// line 164 in processenv.h redefines GetCommandLine to GetCommandLineW if

-// UNICODE is defined.

-// This function was added so that it could be used as a work around when

-// GetCommandLine() needed to be called.

-starboard::CommandLine* GetCommandLinePointer(starboard::Application* app);

-

-class ApplicationUwp : public shared::starboard::Application,

-                       private AnalogThumbstickThread::Callback {

- public:

-  ApplicationUwp();

-  ~ApplicationUwp() SB_OVERRIDE;

-

-  static ApplicationUwp* Get() {

-    return static_cast<ApplicationUwp*>(shared::starboard::Application::Get());

-  }

-

-  SbWindow CreateWindowForUWP(const SbWindowOptions* options);

-

-  bool DestroyWindow(SbWindow window);

-

-  void DispatchStart() {

-    shared::starboard::Application::DispatchStart();

-  }

-

-  // public for IFrameworkView subclass

-  void SetCommandLine(int argc, const char** argv) {

-    shared::starboard::Application::SetCommandLine(argc, argv);

-  }

-

-  // public for IFrameworkView subclass

-  bool DispatchAndDelete(Application::Event* event) {

-    return shared::starboard::Application::DispatchAndDelete(event);

-  }

-

-  Platform::Agile<Windows::UI::Core::CoreWindow> GetCoreWindow() const {

-    return core_window_;

-  }

-

-  // public for IFrameworkView subclass

-  void SetCoreWindow(Windows::UI::Core::CoreWindow^ window) {

-    core_window_ = window;

-  }

-

-  void OnKeyEvent(Windows::UI::Core::CoreWindow^ sender,

-      Windows::UI::Core::KeyEventArgs^ args, bool up);

-

-  void Inject(Event* event) SB_OVERRIDE;

-

-  void SetStartLink(const char* link) SB_OVERRIDE {

-    shared::starboard::Application::SetStartLink(link);

-  }

-

-  SbSystemPlatformError OnSbSystemRaisePlatformError(

-     SbSystemPlatformErrorType type,

-     SbSystemPlatformErrorCallback callback,

-     void* user_data);

-

-  void OnSbSystemClearPlatformError(SbSystemPlatformError handle);

-

-  // Schedules a lambda to run on the main thread and returns immediately.

-  template<typename T>

-  void RunInMainThreadAsync(const T& lambda) {

-    core_window_->Dispatcher->RunAsync(

-      CoreDispatcherPriority::Normal,

-      ref new DispatchedHandler(lambda));

-  }

-

-  Platform::String^ GetString(const char* id, const char* fallback) const;

-

-  bool IsHdcpOn();

-  // Returns true on success.

-  bool TurnOnHdcp();

-  // Returns true on success.

-  bool TurnOffHdcp();

-

- private:

-  // --- Application overrides ---

-  bool IsStartImmediate() SB_OVERRIDE { return false; }

-  void Initialize() SB_OVERRIDE;

-  void Teardown() SB_OVERRIDE;

-  Event* GetNextEvent() SB_OVERRIDE;

-  bool DispatchNextEvent() SB_OVERRIDE;

-  void InjectTimedEvent(TimedEvent* timed_event) SB_OVERRIDE;

-  void CancelTimedEvent(SbEventId event_id) SB_OVERRIDE;

-  TimedEvent* GetNextDueTimedEvent() SB_OVERRIDE;

-  SbTimeMonotonic GetNextTimedEventTargetTime() SB_OVERRIDE;

-

-  int device_id() const { return device_id_; }

-  void OnJoystickUpdate(SbKey key, SbInputVector value) SB_OVERRIDE;

-

-  // These two functions should only be called while holding

-  // |hdcp_session_mutex_|.

-  Windows::Media::Protection::HdcpSession^ GetHdcpSession();

-  void ResetHdcpSession();

-

-  // The single open window, if any.

-  SbWindow window_;

-  Platform::Agile<Windows::UI::Core::CoreWindow> core_window_;

-

-  shared::starboard::LocalizedStrings localized_strings_;

-

-  Mutex mutex_;

-  // |timer_event_map_| is locked by |mutex_|.

-  std::unordered_map<SbEventId, Windows::System::Threading::ThreadPoolTimer^>

-    timer_event_map_;

-

-  int device_id_;

-

-  // |hdcp_session_| is locked by |hdcp_session_mutex_|.

-  Mutex hdcp_session_mutex_;

-  Windows::Media::Protection::HdcpSession^ hdcp_session_;

-

-  scoped_ptr<AnalogThumbstickThread> analog_thumbstick_thread_;

-};

-

-}  // namespace uwp

-}  // namespace shared

-}  // namespace starboard

-

-#endif  // STARBOARD_SHARED_UWP_APPLICATION_UWP_H_
\ No newline at end of file
+// Copyright 2017 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.
+
+#ifndef STARBOARD_SHARED_UWP_APPLICATION_UWP_H_
+#define STARBOARD_SHARED_UWP_APPLICATION_UWP_H_
+
+#include <agile.h>
+#include <string>
+#include <unordered_map>
+
+#include "starboard/configuration.h"
+#include "starboard/input.h"
+#include "starboard/key.h"
+#include "starboard/mutex.h"
+#include "starboard/shared/internal_only.h"
+#include "starboard/shared/starboard/application.h"
+#include "starboard/shared/starboard/command_line.h"
+#include "starboard/shared/starboard/localized_strings.h"
+#include "starboard/shared/uwp/analog_thumbstick_input_thread.h"
+#include "starboard/types.h"
+#include "starboard/window.h"
+
+namespace starboard {
+namespace shared {
+namespace uwp {
+
+// Including <agile.h>, will eventually include <windows.h>, which includes
+// C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um\processenv.h,
+// line 164 in processenv.h redefines GetCommandLine to GetCommandLineW if
+// UNICODE is defined.
+// This function was added so that it could be used as a work around when
+// GetCommandLine() needed to be called.
+starboard::CommandLine* GetCommandLinePointer(starboard::Application* app);
+
+class ApplicationUwp : public shared::starboard::Application,
+                       private AnalogThumbstickThread::Callback {
+ public:
+  ApplicationUwp();
+  ~ApplicationUwp() SB_OVERRIDE;
+
+  static ApplicationUwp* Get() {
+    return static_cast<ApplicationUwp*>(shared::starboard::Application::Get());
+  }
+
+  SbWindow CreateWindowForUWP(const SbWindowOptions* options);
+
+  bool DestroyWindow(SbWindow window);
+
+  void DispatchStart() { shared::starboard::Application::DispatchStart(); }
+
+  // public for IFrameworkView subclass
+  void SetCommandLine(int argc, const char** argv) {
+    shared::starboard::Application::SetCommandLine(argc, argv);
+  }
+
+  // public for IFrameworkView subclass
+  bool DispatchAndDelete(Application::Event* event) {
+    return shared::starboard::Application::DispatchAndDelete(event);
+  }
+
+  Platform::Agile<Windows::UI::Core::CoreWindow> GetCoreWindow() const {
+    return core_window_;
+  }
+
+  Platform::Agile<Windows::UI::Core::CoreDispatcher> GetDispatcher() const {
+    return dispatcher_;
+  }
+
+  Platform::Agile<Windows::Media::SystemMediaTransportControls>
+      GetTransportControls() const {
+    return transport_controls_;
+  }
+
+  // public for IFrameworkView subclass
+  void SetCoreWindow(Windows::UI::Core::CoreWindow^ window) {
+    core_window_ = window;
+
+    dispatcher_ = window->Dispatcher;
+    transport_controls_ =
+        Windows::Media::SystemMediaTransportControls::GetForCurrentView();
+  }
+
+  void OnKeyEvent(Windows::UI::Core::CoreWindow^ sender,
+                  Windows::UI::Core::KeyEventArgs^ args,
+                  bool up);
+
+  void Inject(Event* event) SB_OVERRIDE;
+
+  void SetStartLink(const char* link) SB_OVERRIDE {
+    shared::starboard::Application::SetStartLink(link);
+  }
+
+  SbSystemPlatformError OnSbSystemRaisePlatformError(
+      SbSystemPlatformErrorType type,
+      SbSystemPlatformErrorCallback callback,
+      void* user_data);
+
+  void OnSbSystemClearPlatformError(SbSystemPlatformError handle);
+
+  Platform::String^ GetString(const char* id, const char* fallback) const;
+
+  bool IsHdcpOn();
+  // Returns true on success.
+  bool TurnOnHdcp();
+  // Returns true on success.
+  bool TurnOffHdcp();
+
+ private:
+  // --- Application overrides ---
+  bool IsStartImmediate() SB_OVERRIDE { return false; }
+  void Initialize() SB_OVERRIDE;
+  void Teardown() SB_OVERRIDE;
+  Event* GetNextEvent() SB_OVERRIDE;
+  bool DispatchNextEvent() SB_OVERRIDE;
+  void InjectTimedEvent(TimedEvent* timed_event) SB_OVERRIDE;
+  void CancelTimedEvent(SbEventId event_id) SB_OVERRIDE;
+  TimedEvent* GetNextDueTimedEvent() SB_OVERRIDE;
+  SbTimeMonotonic GetNextTimedEventTargetTime() SB_OVERRIDE;
+
+  int device_id() const { return device_id_; }
+  void OnJoystickUpdate(SbKey key, SbInputVector value) SB_OVERRIDE;
+
+  // These two functions should only be called while holding
+  // |hdcp_session_mutex_|.
+  Windows::Media::Protection::HdcpSession^ GetHdcpSession();
+  void ResetHdcpSession();
+
+  // The single open window, if any.
+  SbWindow window_;
+  Platform::Agile<Windows::UI::Core::CoreWindow> core_window_;
+
+  Platform::Agile<Windows::UI::Core::CoreDispatcher> dispatcher_;
+  Platform::Agile<Windows::Media::SystemMediaTransportControls>
+      transport_controls_;
+
+  shared::starboard::LocalizedStrings localized_strings_;
+
+  Mutex mutex_;
+  // |timer_event_map_| is locked by |mutex_|.
+  std::unordered_map<SbEventId, Windows::System::Threading::ThreadPoolTimer^>
+      timer_event_map_;
+
+  int device_id_;
+
+  // |hdcp_session_| is locked by |hdcp_session_mutex_|.
+  Mutex hdcp_session_mutex_;
+  Windows::Media::Protection::HdcpSession^ hdcp_session_;
+
+  scoped_ptr<AnalogThumbstickThread> analog_thumbstick_thread_;
+};
+
+}  // namespace uwp
+}  // namespace shared
+}  // namespace starboard
+
+#endif  // STARBOARD_SHARED_UWP_APPLICATION_UWP_H_
diff --git a/src/starboard/shared/uwp/application_uwp_get_commandline_pointer.cc b/src/starboard/shared/uwp/application_uwp_get_commandline_pointer.cc
index 669e6a3..fee0b9a 100644
--- a/src/starboard/shared/uwp/application_uwp_get_commandline_pointer.cc
+++ b/src/starboard/shared/uwp/application_uwp_get_commandline_pointer.cc
@@ -1,28 +1,28 @@
-// Copyright 2017 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/application.h"

-#include "starboard/shared/starboard/command_line.h"

-

-namespace starboard {

-namespace shared {

-namespace uwp {

-

-starboard::CommandLine* GetCommandLinePointer(starboard::Application* app) {

-  return app->GetCommandLine();

-}

-

-}  // namespace uwp

-}  // namespace shared

-}  // namespace starboard

+// Copyright 2017 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/application.h"
+#include "starboard/shared/starboard/command_line.h"
+
+namespace starboard {
+namespace shared {
+namespace uwp {
+
+starboard::CommandLine* GetCommandLinePointer(starboard::Application* app) {
+  return app->GetCommandLine();
+}
+
+}  // namespace uwp
+}  // namespace shared
+}  // namespace starboard
diff --git a/src/starboard/shared/uwp/log_raw.cc b/src/starboard/shared/uwp/log_raw.cc
index da8ca37..892e649 100644
--- a/src/starboard/shared/uwp/log_raw.cc
+++ b/src/starboard/shared/uwp/log_raw.cc
@@ -24,7 +24,22 @@
 
 void SbLogRaw(const char* message) {
   fprintf(stderr, "%s", message);
-  OutputDebugStringA(message);
   sbuwp::WriteToLogFile(
       message, static_cast<int>(SbStringGetLength(message)));
+
+  // OutputDebugStringA may stall for multiple seconds if the output string is
+  // too long. Split |message| into shorter strings for output.
+  char buffer[512];
+  for (;;) {
+    errno_t result = strncpy_s(buffer, message, _TRUNCATE);
+    if (result == 0) {
+      OutputDebugStringA(buffer);
+      break;
+    } else if (result == STRUNCATE) {
+      OutputDebugStringA(buffer);
+      message += sizeof(buffer) - 1;
+    } else {
+      break;
+    }
+  }
 }
diff --git a/src/starboard/shared/uwp/log_raw_format.cc b/src/starboard/shared/uwp/log_raw_format.cc
index 40354bf..4664fbe 100644
--- a/src/starboard/shared/uwp/log_raw_format.cc
+++ b/src/starboard/shared/uwp/log_raw_format.cc
@@ -15,22 +15,9 @@
 #include "starboard/log.h"
 
 #include <stdio.h>
-#include <windows.h>
-
-#include "starboard/shared/uwp/log_file_impl.h"
-
-static const int kMaxLogLineChars = 16 * 1024;
-
-namespace sbuwp = starboard::shared::uwp;
 
 void SbLogRawFormat(const char* format, va_list arguments) {
-  vfprintf(stderr, format, arguments);
-  char log_buffer[kMaxLogLineChars];
-  int result = vsprintf_s(log_buffer, kMaxLogLineChars, format, arguments);
-  if (result > 0) {
-    OutputDebugStringA(log_buffer);
-    sbuwp::WriteToLogFile(log_buffer, result);
-  } else {
-    OutputDebugStringA("[log line too long]");
-  }
+  char log_buffer[16 * 1024];
+  vsnprintf_s(log_buffer, _TRUNCATE, format, arguments);
+  SbLogRaw(log_buffer);
 }
diff --git a/src/starboard/shared/uwp/media_is_output_protected.cc b/src/starboard/shared/uwp/media_is_output_protected.cc
index 117f65a..cb08cb0 100644
--- a/src/starboard/shared/uwp/media_is_output_protected.cc
+++ b/src/starboard/shared/uwp/media_is_output_protected.cc
@@ -1,21 +1,21 @@
-// Copyright 2017 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/media.h"

-

-#include "starboard/shared/uwp/application_uwp.h"

-

-bool SbMediaIsOutputProtected() {

-  return starboard::shared::uwp::ApplicationUwp::Get()->IsHdcpOn();

-}

+// Copyright 2017 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/media.h"
+
+#include "starboard/shared/uwp/application_uwp.h"
+
+bool SbMediaIsOutputProtected() {
+  return starboard::shared::uwp::ApplicationUwp::Get()->IsHdcpOn();
+}
diff --git a/src/starboard/shared/uwp/media_set_output_protection.cc b/src/starboard/shared/uwp/media_set_output_protection.cc
index 1a3cc31..b29e94a 100644
--- a/src/starboard/shared/uwp/media_set_output_protection.cc
+++ b/src/starboard/shared/uwp/media_set_output_protection.cc
@@ -1,50 +1,51 @@
-// Copyright 2017 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/media.h"

-

-#include "starboard/log.h"

-#include "starboard/shared/uwp/application_uwp.h"

-#include "starboard/time.h"

-

-using starboard::shared::uwp::ApplicationUwp;

-

-bool SbMediaSetOutputProtection(bool should_enable_dhcp) {

-  bool is_hdcp_on = SbMediaIsOutputProtected();

-

-  if (is_hdcp_on == should_enable_dhcp) {

-    return true;

-  }

-

-  SB_LOG(INFO) << "Attempting to "

-               << (should_enable_dhcp ? "enable" : "disable")

-               << " output protection.  Current status: "

-               << (is_hdcp_on ? "enabled" : "disabled");

-  SbTimeMonotonic tick = SbTimeGetMonotonicNow();

-

-  bool hdcp_success = false;

-  if (should_enable_dhcp) {

-    hdcp_success = ApplicationUwp::Get()->TurnOnHdcp();

-  } else {

-    hdcp_success = ApplicationUwp::Get()->TurnOffHdcp();

-  }

-

-  is_hdcp_on = (hdcp_success ? should_enable_dhcp : !should_enable_dhcp);

-

-  SbTimeMonotonic tock = SbTimeGetMonotonicNow();

-  SB_LOG(INFO) << "Output protection is "

-    << (is_hdcp_on ? "enabled" : "disabled") << ".  Toggling HDCP took "

-    << (tock - tick) / kSbTimeMillisecond << " milliseconds.";

-  return hdcp_success;

-}

+// Copyright 2017 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/media.h"
+
+#include "starboard/log.h"
+#include "starboard/shared/uwp/application_uwp.h"
+#include "starboard/time.h"
+
+using starboard::shared::uwp::ApplicationUwp;
+
+bool SbMediaSetOutputProtection(bool should_enable_dhcp) {
+  bool is_hdcp_on = SbMediaIsOutputProtected();
+
+  if (is_hdcp_on == should_enable_dhcp) {
+    return true;
+  }
+
+  SB_LOG(INFO) << "Attempting to "
+               << (should_enable_dhcp ? "enable" : "disable")
+               << " output protection.  Current status: "
+               << (is_hdcp_on ? "enabled" : "disabled");
+  SbTimeMonotonic tick = SbTimeGetMonotonicNow();
+
+  bool hdcp_success = false;
+  if (should_enable_dhcp) {
+    hdcp_success = ApplicationUwp::Get()->TurnOnHdcp();
+  } else {
+    hdcp_success = ApplicationUwp::Get()->TurnOffHdcp();
+  }
+
+  is_hdcp_on = (hdcp_success ? should_enable_dhcp : !should_enable_dhcp);
+
+  SbTimeMonotonic tock = SbTimeGetMonotonicNow();
+  SB_LOG(INFO) << "Output protection is "
+               << (is_hdcp_on ? "enabled" : "disabled")
+               << ".  Toggling HDCP took " << (tock - tick) / kSbTimeMillisecond
+               << " milliseconds.";
+  return hdcp_success;
+}
diff --git a/src/starboard/shared/uwp/system_get_property.cc b/src/starboard/shared/uwp/system_get_property.cc
index 8249fb5..fbe65a3 100644
--- a/src/starboard/shared/uwp/system_get_property.cc
+++ b/src/starboard/shared/uwp/system_get_property.cc
@@ -1,188 +1,187 @@
-// Copyright 2017 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/system.h"

-

-#include <string>

-

-#include "starboard/log.h"

-#include "starboard/shared/uwp/application_uwp.h"

-#include "starboard/shared/win32/wchar_utils.h"

-#include "starboard/string.h"

-

-using Windows::Security::ExchangeActiveSyncProvisioning::

-    EasClientDeviceInformation;

-using Windows::System::Profile::AnalyticsInfo;

-using Windows::System::Profile::AnalyticsVersionInfo;

-

-namespace sbwin32 = starboard::shared::win32;

-

-namespace {

-bool CopyStringAndTestIfSuccess(char* out_value,

-                                int value_length,

-                                const char* from_value) {

-  if (SbStringGetLength(from_value) + 1 > value_length)

-    return false;

-  SbStringCopy(out_value, from_value, value_length);

-  return true;

-}

-

-const std::size_t kOsVersionSize = 128;

-

-struct WindowsVersion {

-  uint16_t major_version;

-  uint16_t minor_version;

-  uint16_t build_version;

-  uint16_t revision;

-};

-

-bool GetWindowsVersion(WindowsVersion* version) {

-  SB_DCHECK(version);

-  AnalyticsVersionInfo^ version_info = AnalyticsInfo::VersionInfo;

-  std::string device_family_version =

-      starboard::shared::win32::platformStringToString(

-          version_info->DeviceFamilyVersion);

-  if (device_family_version.empty()) {

-    return false;

-  }

-  uint64_t version_info_all =

-      SbStringParseUInt64(device_family_version.c_str(), nullptr, 10);

-  if (version_info_all == 0) {

-    return false;

-  }

-  version->major_version = (version_info_all >> 48) & 0xFFFF;

-  version->minor_version = (version_info_all >> 32) & 0xFFFF;

-  version->build_version = (version_info_all >> 16) & 0xFFFF;

-  version->revision = version_info_all & 0xFFFF;

-  return true;

-}

-

-}  // namespace

-

-bool SbSystemGetProperty(SbSystemPropertyId property_id,

-                         char* out_value,

-                         int value_length) {

-  if (!out_value || !value_length) {

-    return false;

-  }

-

-  using sbwin32::platformStringToString;

-

-  switch (property_id) {

-    case kSbSystemPropertyChipsetModelNumber:

-    case kSbSystemPropertyModelYear:

-    case kSbSystemPropertyNetworkOperatorName:

-    case kSbSystemPropertySpeechApiKey:

-    case kSbSystemPropertyUserAgentAuxField:

-      return false;

-    case kSbSystemPropertyBrandName: {

-      EasClientDeviceInformation^ current_device_info =

-          ref new EasClientDeviceInformation();

-      std::string brand_name =

-          platformStringToString(current_device_info->SystemManufacturer);

-      if (brand_name.empty()) {

-        return false;

-      }

-      return CopyStringAndTestIfSuccess(out_value, value_length,

-                                        brand_name.c_str());

-    }

-    case kSbSystemPropertyFirmwareVersion: {

-      WindowsVersion version = {0};

-      if (!GetWindowsVersion(&version)) {

-        return false;

-      }

-      int return_value = SbStringFormatF(

-          out_value, value_length, "%u.%u.%u.%u", version.major_version,

-          version.minor_version, version.build_version, version.revision);

-      return ((return_value > 0) && (return_value < value_length));

-    }

-    case kSbSystemPropertyModelName: {

-      EasClientDeviceInformation^ current_device_info =

-          ref new EasClientDeviceInformation();

-      std::string sku =

-        platformStringToString(current_device_info->SystemSku);

-

-      std::string friendly_name;

-

-      // TODO: Move this logic into xb1 specific directory.

-      if (sku == "XBOX_ONE_DU") {

-        friendly_name = "XboxOne";

-      } else if (sku == "XBOX_ONE_ED") {

-        friendly_name = "XboxOne S";

-      } else if (sku == "XBOX_ONE_CH" || sku == "XBOX_ONE_SC") {

-        friendly_name = "XboxOne X";

-      } else {

-        friendly_name = "XboxOne " + sku;

-      }

-

-      return CopyStringAndTestIfSuccess(out_value, value_length,

-                                        friendly_name.c_str());

-    }

-    case kSbSystemPropertyFriendlyName: {

-      EasClientDeviceInformation^ current_device_info =

-          ref new EasClientDeviceInformation();

-      std::string friendly_name =

-          platformStringToString(current_device_info->FriendlyName);

-      if (friendly_name.empty()) {

-        return false;

-      }

-      return CopyStringAndTestIfSuccess(out_value, value_length,

-                                        friendly_name.c_str());

-    }

-    case kSbSystemPropertyPlatformName: {

-      EasClientDeviceInformation^ current_device_info =

-          ref new EasClientDeviceInformation();

-      std::string operating_system =

-          platformStringToString(current_device_info->OperatingSystem);

-

-      AnalyticsVersionInfo^ version_info = AnalyticsInfo::VersionInfo;

-      std::string os_name_and_version =

-          starboard::shared::win32::platformStringToString(

-              current_device_info->OperatingSystem);

-      if (os_name_and_version.empty()) {

-        return false;

-      }

-

-      WindowsVersion os_version;

-      if (!GetWindowsVersion(&os_version)) {

-        return false;

-      }

-

-      os_name_and_version += " ";

-      char os_version_buffer[kOsVersionSize];

-      os_version_buffer[0] = '\0';

-

-      int return_value =

-          SbStringFormatF(os_version_buffer, value_length, "%u.%u",

-                          os_version.major_version, os_version.minor_version);

-      if ((return_value < 0) || (return_value >= value_length)) {

-        return false;

-      }

-

-      os_name_and_version.append(os_version_buffer);

-

-      return CopyStringAndTestIfSuccess(out_value, value_length,

-                                        os_name_and_version.c_str());

-    }

-    case kSbSystemPropertyPlatformUuid: {

-      SB_NOTIMPLEMENTED();

-      return CopyStringAndTestIfSuccess(out_value, value_length, "N/A");

-    }

-    default:

-      SB_DLOG(WARNING) << __FUNCTION__

-                       << ": Unrecognized property: " << property_id;

-      break;

-  }

-  return false;

-}

+// Copyright 2017 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/system.h"
+
+#include <string>
+
+#include "starboard/log.h"
+#include "starboard/shared/uwp/application_uwp.h"
+#include "starboard/shared/win32/wchar_utils.h"
+#include "starboard/string.h"
+
+using Windows::Security::ExchangeActiveSyncProvisioning::
+    EasClientDeviceInformation;
+using Windows::System::Profile::AnalyticsInfo;
+using Windows::System::Profile::AnalyticsVersionInfo;
+
+namespace sbwin32 = starboard::shared::win32;
+
+namespace {
+bool CopyStringAndTestIfSuccess(char* out_value,
+                                int value_length,
+                                const char* from_value) {
+  if (SbStringGetLength(from_value) + 1 > value_length)
+    return false;
+  SbStringCopy(out_value, from_value, value_length);
+  return true;
+}
+
+const std::size_t kOsVersionSize = 128;
+
+struct WindowsVersion {
+  uint16_t major_version;
+  uint16_t minor_version;
+  uint16_t build_version;
+  uint16_t revision;
+};
+
+bool GetWindowsVersion(WindowsVersion* version) {
+  SB_DCHECK(version);
+  AnalyticsVersionInfo^ version_info = AnalyticsInfo::VersionInfo;
+  std::string device_family_version =
+      starboard::shared::win32::platformStringToString(
+          version_info->DeviceFamilyVersion);
+  if (device_family_version.empty()) {
+    return false;
+  }
+  uint64_t version_info_all =
+      SbStringParseUInt64(device_family_version.c_str(), nullptr, 10);
+  if (version_info_all == 0) {
+    return false;
+  }
+  version->major_version = (version_info_all >> 48) & 0xFFFF;
+  version->minor_version = (version_info_all >> 32) & 0xFFFF;
+  version->build_version = (version_info_all >> 16) & 0xFFFF;
+  version->revision = version_info_all & 0xFFFF;
+  return true;
+}
+
+}  // namespace
+
+bool SbSystemGetProperty(SbSystemPropertyId property_id,
+                         char* out_value,
+                         int value_length) {
+  if (!out_value || !value_length) {
+    return false;
+  }
+
+  using sbwin32::platformStringToString;
+
+  switch (property_id) {
+    case kSbSystemPropertyChipsetModelNumber:
+    case kSbSystemPropertyModelYear:
+    case kSbSystemPropertyNetworkOperatorName:
+    case kSbSystemPropertySpeechApiKey:
+    case kSbSystemPropertyUserAgentAuxField:
+      return false;
+    case kSbSystemPropertyBrandName: {
+      EasClientDeviceInformation^ current_device_info =
+          ref new EasClientDeviceInformation();
+      std::string brand_name =
+          platformStringToString(current_device_info->SystemManufacturer);
+      if (brand_name.empty()) {
+        return false;
+      }
+      return CopyStringAndTestIfSuccess(out_value, value_length,
+                                        brand_name.c_str());
+    }
+    case kSbSystemPropertyFirmwareVersion: {
+      WindowsVersion version = {0};
+      if (!GetWindowsVersion(&version)) {
+        return false;
+      }
+      int return_value = SbStringFormatF(
+          out_value, value_length, "%u.%u.%u.%u", version.major_version,
+          version.minor_version, version.build_version, version.revision);
+      return ((return_value > 0) && (return_value < value_length));
+    }
+    case kSbSystemPropertyModelName: {
+      EasClientDeviceInformation^ current_device_info =
+          ref new EasClientDeviceInformation();
+      std::string sku = platformStringToString(current_device_info->SystemSku);
+
+      std::string friendly_name;
+
+      // TODO: Move this logic into xb1 specific directory.
+      if (sku == "XBOX_ONE_DU") {
+        friendly_name = "XboxOne";
+      } else if (sku == "XBOX_ONE_ED") {
+        friendly_name = "XboxOne S";
+      } else if (sku == "XBOX_ONE_CH" || sku == "XBOX_ONE_SC") {
+        friendly_name = "XboxOne X";
+      } else {
+        friendly_name = "XboxOne " + sku;
+      }
+
+      return CopyStringAndTestIfSuccess(out_value, value_length,
+                                        friendly_name.c_str());
+    }
+    case kSbSystemPropertyFriendlyName: {
+      EasClientDeviceInformation^ current_device_info =
+          ref new EasClientDeviceInformation();
+      std::string friendly_name =
+          platformStringToString(current_device_info->FriendlyName);
+      if (friendly_name.empty()) {
+        return false;
+      }
+      return CopyStringAndTestIfSuccess(out_value, value_length,
+                                        friendly_name.c_str());
+    }
+    case kSbSystemPropertyPlatformName: {
+      EasClientDeviceInformation^ current_device_info =
+          ref new EasClientDeviceInformation();
+      std::string operating_system =
+          platformStringToString(current_device_info->OperatingSystem);
+
+      AnalyticsVersionInfo^ version_info = AnalyticsInfo::VersionInfo;
+      std::string os_name_and_version =
+          starboard::shared::win32::platformStringToString(
+              current_device_info->OperatingSystem);
+      if (os_name_and_version.empty()) {
+        return false;
+      }
+
+      WindowsVersion os_version;
+      if (!GetWindowsVersion(&os_version)) {
+        return false;
+      }
+
+      os_name_and_version += " ";
+      char os_version_buffer[kOsVersionSize];
+      os_version_buffer[0] = '\0';
+
+      int return_value =
+          SbStringFormatF(os_version_buffer, value_length, "%u.%u",
+                          os_version.major_version, os_version.minor_version);
+      if ((return_value < 0) || (return_value >= value_length)) {
+        return false;
+      }
+
+      os_name_and_version.append(os_version_buffer);
+
+      return CopyStringAndTestIfSuccess(out_value, value_length,
+                                        os_name_and_version.c_str());
+    }
+    case kSbSystemPropertyPlatformUuid: {
+      SB_NOTIMPLEMENTED();
+      return CopyStringAndTestIfSuccess(out_value, value_length, "N/A");
+    }
+    default:
+      SB_DLOG(WARNING) << __FUNCTION__
+                       << ": Unrecognized property: " << property_id;
+      break;
+  }
+  return false;
+}
diff --git a/src/starboard/shared/win32/__init__.py b/src/starboard/shared/win32/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/starboard/shared/win32/__init__.py
diff --git a/src/starboard/shared/win32/application_win32_key_event.cc b/src/starboard/shared/win32/application_win32_key_event.cc
index 4e02faf..a661f3e 100644
--- a/src/starboard/shared/win32/application_win32_key_event.cc
+++ b/src/starboard/shared/win32/application_win32_key_event.cc
@@ -195,7 +195,7 @@
   data->key = VirtualKeyCodeToSbKey(w_param);
 
   const bool was_down = ((l_param & (1 << 30)) != 0);
-  const bool up = msg != WM_KEYDOWN && msg == WM_SYSKEYDOWN;
+  const bool up = msg != WM_KEYDOWN && msg != WM_SYSKEYDOWN;
 
   data->type = up ? kSbInputEventTypeUnpress : kSbInputEventTypePress;
 
diff --git a/src/starboard/shared/win32/drm_system_playready.cc b/src/starboard/shared/win32/drm_system_playready.cc
index bfa8dcd..c3c7f21 100644
--- a/src/starboard/shared/win32/drm_system_playready.cc
+++ b/src/starboard/shared/win32/drm_system_playready.cc
@@ -14,6 +14,7 @@
 
 #include "starboard/shared/win32/drm_system_playready.h"
 
+#include <cctype>
 #include <sstream>
 
 #include "starboard/configuration.h"
@@ -27,25 +28,41 @@
 
 namespace {
 
-#if defined(COBALT_BUILD_TYPE_GOLD)
-const bool kEnablePlayreadyLog = false;
-#else  // defined(COBALT_BUILD_TYPE_GOLD)
-const bool kEnablePlayreadyLog = true;
-#endif  // defined(COBALT_BUILD_TYPE_GOLD)
+const bool kLogPlayreadyChallengeResponse = false;
 
-std::string GetHexRepresentation(const GUID& guid) {
+std::string GetHexRepresentation(const void* data, size_t size) {
   const char kHex[] = "0123456789ABCDEF";
 
-  std::stringstream ss;
-  const uint8_t* binary = reinterpret_cast<const uint8_t*>(&guid);
-  for (size_t i = 0; i < sizeof(guid); ++i) {
-    if (i != 0) {
-      ss << ' ';
+  std::stringstream representation;
+  std::stringstream ascii;
+  const uint8_t* binary = static_cast<const uint8_t*>(data);
+  bool new_line = true;
+  for (size_t i = 0; i < size; ++i) {
+    if (new_line) {
+      new_line = false;
+    } else {
+      representation << ' ';
     }
-    ss << kHex[binary[i] / 16] << kHex[binary[i] % 16];
+    ascii << (std::isprint(binary[i]) ? static_cast<char>(binary[i]) : '?');
+    representation << kHex[binary[i] / 16] << kHex[binary[i] % 16];
+    if (i % 16 == 15 && i != size - 1) {
+      representation << " (" << ascii.str() << ')' << std::endl;
+      std::stringstream empty;
+      ascii.swap(empty);  // Clear the ascii stream
+      new_line = true;
+    }
   }
 
-  return ss.str();
+  if (!ascii.str().empty()) {
+    representation << '(' << ascii.str() << ')' << std::endl;
+  }
+
+  return representation.str();
+}
+
+template <typename T>
+std::string GetHexRepresentation(const T& value) {
+  return GetHexRepresentation(&value, sizeof(T));
 }
 
 }  // namespace
@@ -90,9 +107,11 @@
     return;
   }
 
-  SB_LOG_IF(INFO, kEnablePlayreadyLog)
-      << "Send challenge for key id " << GetHexRepresentation(license->key_id())
-      << " in session " << session_id;
+  SB_LOG(INFO) << "Send challenge for key id "
+               << GetHexRepresentation(license->key_id()) << " in session "
+               << session_id;
+  SB_LOG_IF(INFO, kLogPlayreadyChallengeResponse)
+      << GetHexRepresentation(challenge.data(), challenge.size());
 
   session_update_request_callback_(this, context_, ticket, session_id.c_str(),
                                    static_cast<int>(session_id.size()),
@@ -116,21 +135,28 @@
     SB_NOTREACHED() << "Invalid session id " << session_id_copy;
     return;
   }
-  iter->second->UpdateLicense(key, key_size);
 
-  if (iter->second->usable()) {
-    SB_LOG_IF(INFO, kEnablePlayreadyLog)
-        << "Successfully add key for key id "
-        << GetHexRepresentation(iter->second->key_id()) << " in session "
-        << session_id_copy;
+  scoped_refptr<License> license = iter->second;
+
+  SB_LOG(INFO) << "Adding playready response for key id "
+               << GetHexRepresentation(license->key_id());
+  SB_LOG_IF(INFO, kLogPlayreadyChallengeResponse)
+      << GetHexRepresentation(key, key_size);
+
+  license->UpdateLicense(key, key_size);
+
+  if (license->usable()) {
+    SB_LOG(INFO) << "Successfully add key for key id "
+                 << GetHexRepresentation(license->key_id()) << " in session "
+                 << session_id_copy;
     {
       ScopedLock lock(mutex_);
-      successful_requests_[iter->first] = iter->second;
+      successful_requests_[iter->first] = license;
     }
     session_updated_callback_(this, context_, ticket, session_id,
                               session_id_size, true);
 
-    GUID key_id = iter->second->key_id();
+    GUID key_id = license->key_id();
     SbDrmKeyId drm_key_id;
     SB_DCHECK(sizeof(drm_key_id.identifier) >= sizeof(key_id));
     SbMemoryCopy(&drm_key_id, &key_id, sizeof(key_id));
@@ -138,13 +164,33 @@
     SbDrmKeyStatus key_status = kSbDrmKeyStatusUsable;
     key_statuses_changed_callback_(this, context_, session_id, session_id_size,
                                    1, &drm_key_id, &key_status);
+    pending_requests_.erase(iter);
   } else {
-    SB_LOG_IF(INFO, kEnablePlayreadyLog)
-        << "Failed to add key for session " << session_id_copy;
+    SB_LOG(INFO) << "Failed to add key for session " << session_id_copy;
+    // Don't report it as a failure as otherwise the JS player is going to
+    // terminate the video.
     session_updated_callback_(this, context_, ticket, session_id,
-                              session_id_size, false);
+                              session_id_size, true);
+    // When UpdateLicense() fails, the |license| must have generated a new
+    // challenge internally.  Send this challenge again.
+    const std::string& challenge = license->license_challenge();
+    if (challenge.empty()) {
+      SB_NOTREACHED();
+      return;
+    }
+
+    SB_LOG(INFO) << "Send challenge again for key id "
+                 << GetHexRepresentation(license->key_id()) << " in session "
+                 << session_id;
+    SB_LOG_IF(INFO, kLogPlayreadyChallengeResponse)
+        << GetHexRepresentation(challenge.data(), challenge.size());
+
+    // We have use |kSbDrmTicketInvalid| as the license challenge is not a
+    // result of GenerateSessionUpdateRequest().
+    session_update_request_callback_(
+        this, context_, kSbDrmTicketInvalid, session_id, session_id_size,
+        challenge.c_str(), static_cast<int>(challenge.size()), NULL);
   }
-  pending_requests_.erase(iter);
 }
 
 void SbDrmSystemPlayready::CloseSession(const void* session_id,
diff --git a/src/starboard/shared/win32/gyp_configuration.py b/src/starboard/shared/win32/gyp_configuration.py
index 616a9c0..af643cb 100644
--- a/src/starboard/shared/win32/gyp_configuration.py
+++ b/src/starboard/shared/win32/gyp_configuration.py
@@ -11,6 +11,7 @@
 # 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.
+import imp
 import logging
 import os
 import sys
@@ -18,10 +19,9 @@
 import config.starboard
 
 from starboard.tools.paths import STARBOARD_ROOT
+import starboard.shared.win32.sdk_configuration as sdk_configuration
 import starboard.tools.testing.test_filter as test_filter
 
-import sdk_configuration
-
 def _QuotePath(path):
   return '"' + path + '"'
 
diff --git a/src/starboard/shared/win32/log_file_impl.cc b/src/starboard/shared/win32/log_file_impl.cc
index 89371cd..0cfb95d 100644
--- a/src/starboard/shared/win32/log_file_impl.cc
+++ b/src/starboard/shared/win32/log_file_impl.cc
@@ -83,10 +83,11 @@
 
   SbMutexAcquire(&log_mutex);
   CloseLogFileWithoutLock();
-  if ((path != nullptr) && (path != '\0')) {
+  if ((path != nullptr) && (path[0] != '\0')) {
     log_file = SbFileOpen(path, flags, nullptr, nullptr);
     SB_DCHECK(SbFileIsValid(log_file));
   }
+
   SbMutexRelease(&log_mutex);
 }
 
diff --git a/src/starboard/shared/win32/media_is_output_protected.cc b/src/starboard/shared/win32/media_is_output_protected.cc
index 03e6642..7eb3533 100644
--- a/src/starboard/shared/win32/media_is_output_protected.cc
+++ b/src/starboard/shared/win32/media_is_output_protected.cc
@@ -1,20 +1,20 @@
-// Copyright 2017 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/media.h"

-

-bool SbMediaIsOutputProtected() {

-  SB_NOTIMPLEMENTED();

-  return false;

-}

+// Copyright 2017 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/media.h"
+
+bool SbMediaIsOutputProtected() {
+  SB_NOTIMPLEMENTED();
+  return false;
+}
diff --git a/src/starboard/shared/win32/player_components_impl.cc b/src/starboard/shared/win32/player_components_impl.cc
index fa2c4af..c57bc8e 100644
--- a/src/starboard/shared/win32/player_components_impl.cc
+++ b/src/starboard/shared/win32/player_components_impl.cc
@@ -15,6 +15,7 @@
 #include "starboard/shared/starboard/player/filter/player_components.h"
 
 #include "starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h"
 #include "starboard/shared/starboard/player/filter/video_renderer_impl_internal.h"
 #include "starboard/shared/win32/audio_decoder.h"
 #include "starboard/shared/win32/video_decoder.h"
@@ -43,12 +44,13 @@
       video_parameters.decode_target_graphics_context_provider,
       video_parameters.drm_system);
 
-  AudioRendererImpl* audio_renderer =
-      new AudioRendererImpl(scoped_ptr<AudioDecoder>(audio_decoder).Pass(),
-                            audio_parameters.audio_header);
+  AudioRendererImpl* audio_renderer = new AudioRendererImpl(
+      make_scoped_ptr<AudioDecoder>(audio_decoder),
+      make_scoped_ptr<AudioRendererSink>(new AudioRendererSinkImpl),
+      audio_parameters.audio_header);
 
   VideoRendererImpl* video_renderer =
-      new VideoRendererImpl(scoped_ptr<VideoDecoderImpl>(video_decoder).Pass());
+      new VideoRendererImpl(make_scoped_ptr<VideoDecoderImpl>(video_decoder));
 
   return scoped_ptr<PlayerComponents>(
       new PlayerComponents(audio_renderer, video_renderer));
diff --git a/src/starboard/shared/win32/win32_video_decoder.cc b/src/starboard/shared/win32/win32_video_decoder.cc
index 098b156..93e717c 100644
--- a/src/starboard/shared/win32/win32_video_decoder.cc
+++ b/src/starboard/shared/win32/win32_video_decoder.cc
@@ -1,319 +1,318 @@
-// Copyright 2017 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/win32/win32_video_decoder.h"

-

-#include <Codecapi.h>

-#include <D3d11_1.h>

-

-#include <queue>

-#include <utility>

-

-#include "starboard/shared/starboard/thread_checker.h"

-#include "starboard/shared/win32/atomic_queue.h"

-#include "starboard/shared/win32/decrypting_decoder.h"

-#include "starboard/shared/win32/dx_context_video_decoder.h"

-#include "starboard/shared/win32/error_utils.h"

-#include "starboard/shared/win32/media_common.h"

-#include "starboard/shared/win32/media_foundation_utils.h"

-#include "starboard/shared/win32/video_texture.h"

-#include "starboard/shared/win32/video_transform.h"

-#include "starboard/window.h"

-

-namespace starboard {

-namespace shared {

-namespace win32 {

-

-using Microsoft::WRL::ComPtr;

-using ::starboard::shared::starboard::ThreadChecker;

-using ::starboard::shared::win32::CheckResult;

-

-namespace {

-

-// In MS sample it is set to 5 and we experienced issues when this is set to

-// below 5.  This can be further tuned to balance between playback smoothness

-// and memory consumption.

-const int kSampleAllocatorFramesMax = 12;

-// This is the minimum allocated frames in the output ring buffer.  Can be

-// further tuned to save memory.  Note that use a value that is too small leads

-// to hang when calling ProcessOutput().

-const int kMinimumOutputSampleCount = kSampleAllocatorFramesMax + 5;

-

-// CLSID_CMSVideoDecoderMFT {62CE7E72-4C71-4D20-B15D-452831A87D9D}

-const GUID CLSID_VideoDecoder = {0x62CE7E72, 0x4C71, 0x4d20, 0xB1, 0x5D, 0x45,

-                                 0x28,       0x31,   0xA8,   0x7D, 0x9D};

-

-class AbstractWin32VideoDecoderImpl : public AbstractWin32VideoDecoder {

- public:

-  AbstractWin32VideoDecoderImpl(SbMediaVideoCodec codec, SbDrmSystem drm_system)

-      : thread_checker_(ThreadChecker::kSetThreadIdOnFirstCheck),

-        codec_(codec) {

-    SbMemorySet(&display_aperture_, 0, sizeof(RECT));

-    Configure(drm_system);

-  }

-

-  void Consume(ComPtr<IMFSample> sample) {

-    SB_DCHECK(thread_checker_.CalledOnValidThread());

-    VideoFramePtr frame_output =

-        VideoFrameFactory::Construct(sample, display_aperture_,

-        video_blt_interfaces_);

-    output_queue_.push(frame_output);

-  }

-

-  void OnNewOutputType(const ComPtr<IMFMediaType>& type) {

-    SB_DCHECK(thread_checker_.CalledOnValidThread());

-

-    RECT rect = {};

-    MFVideoArea aperture;

-    HRESULT hr = type->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE,

-        reinterpret_cast<UINT8*>(&aperture), sizeof(MFVideoArea), nullptr);

-    if (SUCCEEDED(hr)) {

-      display_aperture_.left = aperture.OffsetX.value;

-      display_aperture_.right = rect.left + aperture.Area.cx;

-      display_aperture_.top = aperture.OffsetY.value;

-      display_aperture_.bottom = rect.top + aperture.Area.cy;

-      return;

-    }

-

-    uint32_t width;

-    uint32_t height;

-    hr = MFGetAttributeSize(type.Get(), MF_MT_FRAME_SIZE,

-                            &width, &height);

-    if (SUCCEEDED(hr)) {

-      display_aperture_.left = 0;

-      display_aperture_.top = 0;

-      display_aperture_.right = rect.left + width;

-      display_aperture_.bottom = rect.top + height;

-    }

-  }

-

-  void Configure(SbDrmSystem drm_system) {

-    scoped_ptr<MediaTransform> media_transform;

-

-    // If this is updated then media_is_video_supported.cc also needs to be

-    // updated.

-    switch (codec_) {

-      case kSbMediaVideoCodecH264: {

-        media_transform = CreateH264Transform(kVideoFormat_YV12);

-        break;

-      }

-      case kSbMediaVideoCodecVp9: {

-        // VP9 decoder needs a default resolution.

-        media_transform = TryCreateVP9Transform(kVideoFormat_YV12, 1024, 768);

-        break;

-      }

-      default: { SB_NOTREACHED(); }

-    }

-

-    impl_.reset(

-        new DecryptingDecoder("video", media_transform.Pass(), drm_system));

-    MediaTransform* decoder = impl_->GetDecoder();

-

-    dx_decoder_ctx_ = GetDirectXForHardwareDecoding();

-    video_blt_interfaces_.dx_device_ = dx_decoder_ctx_.dx_device_out;

-

-    DWORD input_stream_count = 0;

-    DWORD output_stream_count = 0;

-    decoder->GetStreamCount(&input_stream_count, &output_stream_count);

-    SB_DCHECK(1 == input_stream_count);

-    SB_DCHECK(1 == output_stream_count);

-

-    ComPtr<IMFAttributes> attributes = decoder->GetAttributes();

-

-    HRESULT hr = attributes->SetUINT32(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT,

-                                       kMinimumOutputSampleCount);

-    CheckResult(hr);

-

-    UINT32 value = 0;

-    hr = attributes->GetUINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, &value);

-    SB_DCHECK(hr == S_OK || hr == MF_E_ATTRIBUTENOTFOUND);

-

-    // TODO: handle the MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE correctly.

-    // SB_DCHECK(value == TRUE);

-

-    // Enables DirectX video acceleration for video decoding.

-    decoder->SendMessage(MFT_MESSAGE_SET_D3D_MANAGER,

-                         reinterpret_cast<ULONG_PTR>(

-                             dx_decoder_ctx_.dxgi_device_manager_out.Get()));

-

-    ComPtr<IMFMediaType> output_type = decoder->GetCurrentOutputType();

-    SB_DCHECK(output_type);

-

-    UINT32 width;

-    UINT32 height;

-    hr = MFGetAttributeSize(output_type.Get(), MF_MT_FRAME_SIZE,

-                            &width, &height);

-

-    display_aperture_.left = 0;

-    display_aperture_.top = 0;

-    display_aperture_.right = width;

-    display_aperture_.bottom = height;

-

-    if (FAILED(hr)) {

-      SB_NOTREACHED() << "could not get width & height, hr = " << hr;

-      return;

-    }

-

-    ComPtr<IMFAttributes> output_attributes =

-        decoder->GetOutputStreamAttributes();

-    // The decoder must output textures that are bound to shader resources,

-    // or we can't draw them later via ANGLE.

-    hr = output_attributes->SetUINT32(

-        MF_SA_D3D11_BINDFLAGS, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DECODER);

-    SB_DCHECK(SUCCEEDED(hr));

-

-    dx_decoder_ctx_.dx_device_out.As(&video_blt_interfaces_.video_device_);

-

-    D3D11_VIDEO_PROCESSOR_CONTENT_DESC video_processor_desc = {};

-    video_processor_desc.InputFrameFormat =

-        D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;

-    // Presumably changing the input/output frame rate would

-    // allow us to use the VideoProcessor to decide which frames to drop

-    // But we already have common code that does this, so presumably

-    // by setting the input and output frame rate the same, we instruct

-    // the VideoProcessor to give us one output for every input frame.

-    video_processor_desc.InputFrameRate.Numerator = 60;

-    video_processor_desc.InputFrameRate.Denominator = 1;

-    video_processor_desc.OutputFrameRate = video_processor_desc.InputFrameRate;

-

-    SbWindowOptions window_options;

-    SbWindowSetDefaultOptions(&window_options);

-    video_processor_desc.OutputWidth = window_options.size.width;

-    video_processor_desc.OutputHeight = window_options.size.height;

-

-    video_processor_desc.InputWidth = video_processor_desc.OutputWidth;

-    video_processor_desc.InputHeight = video_processor_desc.OutputHeight;

-    video_processor_desc.OutputFrameRate.Numerator = 60;

-    video_processor_desc.OutputFrameRate.Denominator = 1;

-    video_processor_desc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;

-

-    hr = video_blt_interfaces_.video_device_->CreateVideoProcessorEnumerator(

-        &video_processor_desc, &video_blt_interfaces_.video_processor_enum_);

-    CheckResult(hr);

-

-    hr = video_blt_interfaces_.video_device_->CreateVideoProcessor(

-        video_blt_interfaces_.video_processor_enum_.Get(), 0,

-        &video_blt_interfaces_.video_processor_);

-    CheckResult(hr);

-

-    ComPtr<ID3D11DeviceContext> device_context;

-    dx_decoder_ctx_.dx_device_out->GetImmediateContext(&device_context);

-

-    device_context.As(&video_blt_interfaces_.video_context_);

-    video_blt_interfaces_.video_context_->VideoProcessorSetStreamFrameFormat(

-        video_blt_interfaces_.video_processor_.Get(),

-        0, D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE);

-

-    // https://msdn.microsoft.com/en-us/library/windows/desktop/hh447754(v=vs.85).aspx

-    // "for example, if you provide your own pixel shader for the video

-    // processor, you might want to disable the driver's automatic

-    // processing."

-    // We do have our own pixel shader, so we do want to disable anything

-    // like this.

-    video_blt_interfaces_.video_context_->

-        VideoProcessorSetStreamAutoProcessingMode(

-            video_blt_interfaces_.video_processor_.Get(), 0, false);

-  }

-

-  bool TryWrite(const scoped_refptr<InputBuffer>& buff) {

-    SB_DCHECK(thread_checker_.CalledOnValidThread());

-

-    const bool write_ok = impl_->TryWriteInputBuffer(buff, 0);

-    return write_ok;

-  }

-

-  void WriteEndOfStream() SB_OVERRIDE {

-    SB_DCHECK(thread_checker_.CalledOnValidThread());

-

-    impl_->Drain();

-

-    ComPtr<IMFSample> sample;

-    ComPtr<IMFMediaType> media_type;

-    while (VideoFrameFactory::frames_in_flight() < kSampleAllocatorFramesMax &&

-           impl_->ProcessAndRead(&sample, &media_type)) {

-      if (media_type) {

-        OnNewOutputType(media_type);

-      }

-      if (sample) {

-        Consume(sample);

-      }

-    }

-  }

-

-  VideoFramePtr ProcessAndRead(bool* too_many_outstanding_frames) SB_OVERRIDE {

-    SB_DCHECK(thread_checker_.CalledOnValidThread());

-    SB_DCHECK(too_many_outstanding_frames);

-

-    *too_many_outstanding_frames =

-        VideoFrameFactory::frames_in_flight() >= kSampleAllocatorFramesMax;

-

-    if (!*too_many_outstanding_frames) {

-      ComPtr<IMFSample> sample;

-      ComPtr<IMFMediaType> media_type;

-      impl_->ProcessAndRead(&sample, &media_type);

-      if (media_type) {

-        OnNewOutputType(media_type);

-      }

-      if (sample) {

-        Consume(sample);

-      }

-    }

-    if (output_queue_.empty()) {

-      return NULL;

-    }

-    VideoFramePtr output = output_queue_.front();

-    output_queue_.pop();

-    return output;

-  }

-

-  void Reset() SB_OVERRIDE {

-    impl_->Reset();

-    std::queue<VideoFramePtr> empty;

-    output_queue_.swap(empty);

-    thread_checker_.Detach();

-  }

-

-  // The object is single-threaded and is driven by a dedicated thread.

-  // However the thread may gets destroyed and re-created over the life time of

-  // this object.  We enforce that certain member functions can only called

-  // from one thread while still allows this object to be driven by different

-  // threads by:

-  // 1. The |thread_checker_| is initially created without attaching to any

-  //    thread.

-  // 2. When a thread is destroyed, Reset() will be called which in turn calls

-  //    Detach() on the |thread_checker_| to allow the object to attach to a

-  //    new thread.

-  ::starboard::shared::starboard::ThreadChecker thread_checker_;

-  std::queue<VideoFramePtr> output_queue_;

-  const SbMediaVideoCodec codec_;

-  scoped_ptr<DecryptingDecoder> impl_;

-

-  RECT display_aperture_;

-  HardwareDecoderContext dx_decoder_ctx_;

-

-  VideoBltInterfaces video_blt_interfaces_;

-};

-

-}  // anonymous namespace.

-

-scoped_ptr<AbstractWin32VideoDecoder> AbstractWin32VideoDecoder::Create(

-    SbMediaVideoCodec codec,

-    SbDrmSystem drm_system) {

-  return scoped_ptr<AbstractWin32VideoDecoder>(

-      new AbstractWin32VideoDecoderImpl(codec, drm_system));

-}

-

-}  // namespace win32

-}  // namespace shared

-}  // namespace starboard

+// Copyright 2017 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/win32/win32_video_decoder.h"
+
+#include <Codecapi.h>
+#include <D3d11_1.h>
+
+#include <queue>
+#include <utility>
+
+#include "starboard/shared/starboard/thread_checker.h"
+#include "starboard/shared/win32/atomic_queue.h"
+#include "starboard/shared/win32/decrypting_decoder.h"
+#include "starboard/shared/win32/dx_context_video_decoder.h"
+#include "starboard/shared/win32/error_utils.h"
+#include "starboard/shared/win32/media_common.h"
+#include "starboard/shared/win32/media_foundation_utils.h"
+#include "starboard/shared/win32/video_texture.h"
+#include "starboard/shared/win32/video_transform.h"
+#include "starboard/window.h"
+
+namespace starboard {
+namespace shared {
+namespace win32 {
+
+using Microsoft::WRL::ComPtr;
+using ::starboard::shared::starboard::ThreadChecker;
+using ::starboard::shared::win32::CheckResult;
+
+namespace {
+
+// In MS sample it is set to 5 and we experienced issues when this is set to
+// below 5.  This can be further tuned to balance between playback smoothness
+// and memory consumption.
+const int kSampleAllocatorFramesMax = 12;
+// This is the minimum allocated frames in the output ring buffer.  Can be
+// further tuned to save memory.  Note that use a value that is too small leads
+// to hang when calling ProcessOutput().
+const int kMinimumOutputSampleCount = kSampleAllocatorFramesMax + 5;
+
+// CLSID_CMSVideoDecoderMFT {62CE7E72-4C71-4D20-B15D-452831A87D9D}
+const GUID CLSID_VideoDecoder = {0x62CE7E72, 0x4C71, 0x4d20, 0xB1, 0x5D, 0x45,
+                                 0x28,       0x31,   0xA8,   0x7D, 0x9D};
+
+class AbstractWin32VideoDecoderImpl : public AbstractWin32VideoDecoder {
+ public:
+  AbstractWin32VideoDecoderImpl(SbMediaVideoCodec codec, SbDrmSystem drm_system)
+      : thread_checker_(ThreadChecker::kSetThreadIdOnFirstCheck),
+        codec_(codec) {
+    SbMemorySet(&display_aperture_, 0, sizeof(RECT));
+    Configure(drm_system);
+  }
+
+  void Consume(ComPtr<IMFSample> sample) {
+    SB_DCHECK(thread_checker_.CalledOnValidThread());
+    VideoFramePtr frame_output = VideoFrameFactory::Construct(
+        sample, display_aperture_, video_blt_interfaces_);
+    output_queue_.push(frame_output);
+  }
+
+  void OnNewOutputType(const ComPtr<IMFMediaType>& type) {
+    SB_DCHECK(thread_checker_.CalledOnValidThread());
+
+    RECT rect = {};
+    MFVideoArea aperture;
+    HRESULT hr = type->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE,
+                               reinterpret_cast<UINT8*>(&aperture),
+                               sizeof(MFVideoArea), nullptr);
+    if (SUCCEEDED(hr)) {
+      display_aperture_.left = aperture.OffsetX.value;
+      display_aperture_.right = rect.left + aperture.Area.cx;
+      display_aperture_.top = aperture.OffsetY.value;
+      display_aperture_.bottom = rect.top + aperture.Area.cy;
+      return;
+    }
+
+    uint32_t width;
+    uint32_t height;
+    hr = MFGetAttributeSize(type.Get(), MF_MT_FRAME_SIZE, &width, &height);
+    if (SUCCEEDED(hr)) {
+      display_aperture_.left = 0;
+      display_aperture_.top = 0;
+      display_aperture_.right = rect.left + width;
+      display_aperture_.bottom = rect.top + height;
+    }
+  }
+
+  void Configure(SbDrmSystem drm_system) {
+    scoped_ptr<MediaTransform> media_transform;
+
+    // If this is updated then media_is_video_supported.cc also needs to be
+    // updated.
+    switch (codec_) {
+      case kSbMediaVideoCodecH264: {
+        media_transform = CreateH264Transform(kVideoFormat_YV12);
+        break;
+      }
+      case kSbMediaVideoCodecVp9: {
+        // VP9 decoder needs a default resolution.
+        media_transform = TryCreateVP9Transform(kVideoFormat_YV12, 1024, 768);
+        break;
+      }
+      default: { SB_NOTREACHED(); }
+    }
+
+    impl_.reset(
+        new DecryptingDecoder("video", media_transform.Pass(), drm_system));
+    MediaTransform* decoder = impl_->GetDecoder();
+
+    dx_decoder_ctx_ = GetDirectXForHardwareDecoding();
+    video_blt_interfaces_.dx_device_ = dx_decoder_ctx_.dx_device_out;
+
+    DWORD input_stream_count = 0;
+    DWORD output_stream_count = 0;
+    decoder->GetStreamCount(&input_stream_count, &output_stream_count);
+    SB_DCHECK(1 == input_stream_count);
+    SB_DCHECK(1 == output_stream_count);
+
+    ComPtr<IMFAttributes> attributes = decoder->GetAttributes();
+
+    HRESULT hr = attributes->SetUINT32(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT,
+                                       kMinimumOutputSampleCount);
+    CheckResult(hr);
+
+    UINT32 value = 0;
+    hr = attributes->GetUINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, &value);
+    SB_DCHECK(hr == S_OK || hr == MF_E_ATTRIBUTENOTFOUND);
+
+    // TODO: handle the MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE correctly.
+    // SB_DCHECK(value == TRUE);
+
+    // Enables DirectX video acceleration for video decoding.
+    decoder->SendMessage(MFT_MESSAGE_SET_D3D_MANAGER,
+                         reinterpret_cast<ULONG_PTR>(
+                             dx_decoder_ctx_.dxgi_device_manager_out.Get()));
+
+    ComPtr<IMFMediaType> output_type = decoder->GetCurrentOutputType();
+    SB_DCHECK(output_type);
+
+    UINT32 width;
+    UINT32 height;
+    hr = MFGetAttributeSize(output_type.Get(), MF_MT_FRAME_SIZE, &width,
+                            &height);
+
+    display_aperture_.left = 0;
+    display_aperture_.top = 0;
+    display_aperture_.right = width;
+    display_aperture_.bottom = height;
+
+    if (FAILED(hr)) {
+      SB_NOTREACHED() << "could not get width & height, hr = " << hr;
+      return;
+    }
+
+    ComPtr<IMFAttributes> output_attributes =
+        decoder->GetOutputStreamAttributes();
+    // The decoder must output textures that are bound to shader resources,
+    // or we can't draw them later via ANGLE.
+    hr = output_attributes->SetUINT32(
+        MF_SA_D3D11_BINDFLAGS, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DECODER);
+    SB_DCHECK(SUCCEEDED(hr));
+
+    dx_decoder_ctx_.dx_device_out.As(&video_blt_interfaces_.video_device_);
+
+    D3D11_VIDEO_PROCESSOR_CONTENT_DESC video_processor_desc = {};
+    video_processor_desc.InputFrameFormat =
+        D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
+    // Presumably changing the input/output frame rate would
+    // allow us to use the VideoProcessor to decide which frames to drop
+    // But we already have common code that does this, so presumably
+    // by setting the input and output frame rate the same, we instruct
+    // the VideoProcessor to give us one output for every input frame.
+    video_processor_desc.InputFrameRate.Numerator = 60;
+    video_processor_desc.InputFrameRate.Denominator = 1;
+    video_processor_desc.OutputFrameRate = video_processor_desc.InputFrameRate;
+
+    SbWindowOptions window_options;
+    SbWindowSetDefaultOptions(&window_options);
+    video_processor_desc.OutputWidth = window_options.size.width;
+    video_processor_desc.OutputHeight = window_options.size.height;
+
+    video_processor_desc.InputWidth = video_processor_desc.OutputWidth;
+    video_processor_desc.InputHeight = video_processor_desc.OutputHeight;
+    video_processor_desc.OutputFrameRate.Numerator = 60;
+    video_processor_desc.OutputFrameRate.Denominator = 1;
+    video_processor_desc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;
+
+    hr = video_blt_interfaces_.video_device_->CreateVideoProcessorEnumerator(
+        &video_processor_desc, &video_blt_interfaces_.video_processor_enum_);
+    CheckResult(hr);
+
+    hr = video_blt_interfaces_.video_device_->CreateVideoProcessor(
+        video_blt_interfaces_.video_processor_enum_.Get(), 0,
+        &video_blt_interfaces_.video_processor_);
+    CheckResult(hr);
+
+    ComPtr<ID3D11DeviceContext> device_context;
+    dx_decoder_ctx_.dx_device_out->GetImmediateContext(&device_context);
+
+    device_context.As(&video_blt_interfaces_.video_context_);
+    video_blt_interfaces_.video_context_->VideoProcessorSetStreamFrameFormat(
+        video_blt_interfaces_.video_processor_.Get(), 0,
+        D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE);
+
+    // https://msdn.microsoft.com/en-us/library/windows/desktop/hh447754(v=vs.85).aspx
+    // "for example, if you provide your own pixel shader for the video
+    // processor, you might want to disable the driver's automatic
+    // processing."
+    // We do have our own pixel shader, so we do want to disable anything
+    // like this.
+    video_blt_interfaces_.video_context_
+        ->VideoProcessorSetStreamAutoProcessingMode(
+            video_blt_interfaces_.video_processor_.Get(), 0, false);
+  }
+
+  bool TryWrite(const scoped_refptr<InputBuffer>& buff) {
+    SB_DCHECK(thread_checker_.CalledOnValidThread());
+
+    const bool write_ok = impl_->TryWriteInputBuffer(buff, 0);
+    return write_ok;
+  }
+
+  void WriteEndOfStream() SB_OVERRIDE {
+    SB_DCHECK(thread_checker_.CalledOnValidThread());
+
+    impl_->Drain();
+
+    ComPtr<IMFSample> sample;
+    ComPtr<IMFMediaType> media_type;
+    while (VideoFrameFactory::frames_in_flight() < kSampleAllocatorFramesMax &&
+           impl_->ProcessAndRead(&sample, &media_type)) {
+      if (media_type) {
+        OnNewOutputType(media_type);
+      }
+      if (sample) {
+        Consume(sample);
+      }
+    }
+  }
+
+  VideoFramePtr ProcessAndRead(bool* too_many_outstanding_frames) SB_OVERRIDE {
+    SB_DCHECK(thread_checker_.CalledOnValidThread());
+    SB_DCHECK(too_many_outstanding_frames);
+
+    *too_many_outstanding_frames =
+        VideoFrameFactory::frames_in_flight() >= kSampleAllocatorFramesMax;
+
+    if (!*too_many_outstanding_frames) {
+      ComPtr<IMFSample> sample;
+      ComPtr<IMFMediaType> media_type;
+      impl_->ProcessAndRead(&sample, &media_type);
+      if (media_type) {
+        OnNewOutputType(media_type);
+      }
+      if (sample) {
+        Consume(sample);
+      }
+    }
+    if (output_queue_.empty()) {
+      return NULL;
+    }
+    VideoFramePtr output = output_queue_.front();
+    output_queue_.pop();
+    return output;
+  }
+
+  void Reset() SB_OVERRIDE {
+    impl_->Reset();
+    std::queue<VideoFramePtr> empty;
+    output_queue_.swap(empty);
+    thread_checker_.Detach();
+  }
+
+  // The object is single-threaded and is driven by a dedicated thread.
+  // However the thread may gets destroyed and re-created over the life time of
+  // this object.  We enforce that certain member functions can only called
+  // from one thread while still allows this object to be driven by different
+  // threads by:
+  // 1. The |thread_checker_| is initially created without attaching to any
+  //    thread.
+  // 2. When a thread is destroyed, Reset() will be called which in turn calls
+  //    Detach() on the |thread_checker_| to allow the object to attach to a
+  //    new thread.
+  ::starboard::shared::starboard::ThreadChecker thread_checker_;
+  std::queue<VideoFramePtr> output_queue_;
+  const SbMediaVideoCodec codec_;
+  scoped_ptr<DecryptingDecoder> impl_;
+
+  RECT display_aperture_;
+  HardwareDecoderContext dx_decoder_ctx_;
+
+  VideoBltInterfaces video_blt_interfaces_;
+};
+
+}  // anonymous namespace.
+
+scoped_ptr<AbstractWin32VideoDecoder> AbstractWin32VideoDecoder::Create(
+    SbMediaVideoCodec codec,
+    SbDrmSystem drm_system) {
+  return scoped_ptr<AbstractWin32VideoDecoder>(
+      new AbstractWin32VideoDecoderImpl(codec, drm_system));
+}
+
+}  // namespace win32
+}  // namespace shared
+}  // namespace starboard
diff --git a/src/starboard/stub/gyp_configuration.gypi b/src/starboard/stub/gyp_configuration.gypi
index b93baf9..f290161 100644
--- a/src/starboard/stub/gyp_configuration.gypi
+++ b/src/starboard/stub/gyp_configuration.gypi
@@ -22,12 +22,6 @@
     # No GL drivers available.
     'gl_type': 'none',
 
-    # This should have a default value in cobalt/base.gypi. See the comment
-    # there for acceptable values for this variable.
-    'javascript_engine': 'mozjs-45',
-
-    'cobalt_enable_jit': 0,
-
     'cobalt_media_source_2016': 1,
 
     # Define platform specific compiler and linker flags.
diff --git a/src/starboard/tizen/armv7l/starboard_platform.gyp b/src/starboard/tizen/armv7l/starboard_platform.gyp
index 897e5cc..37371df 100644
--- a/src/starboard/tizen/armv7l/starboard_platform.gyp
+++ b/src/starboard/tizen/armv7l/starboard_platform.gyp
@@ -46,6 +46,9 @@
         '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc',
         '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h',
         '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.h',
+        '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink.h',
+        '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc',
+        '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h',
         '<(DEPTH)/starboard/shared/starboard/player/filter/audio_time_stretcher.cc',
         '<(DEPTH)/starboard/shared/starboard/player/filter/audio_time_stretcher.h',
         '<(DEPTH)/starboard/shared/starboard/player/filter/decoded_audio_queue.cc',
diff --git a/src/starboard/tools/abstract_launcher.py b/src/starboard/tools/abstract_launcher.py
index 3f2454b..a7e72df 100644
--- a/src/starboard/tools/abstract_launcher.py
+++ b/src/starboard/tools/abstract_launcher.py
@@ -65,8 +65,11 @@
     The module containing the platform's launcher implementation.
   """
 
-  gyp_module = GetGypModuleForPlatform(platform)
-  return gyp_module.CreatePlatformConfig().GetLauncher()
+  gyp_config = GetGypModuleForPlatform(platform).CreatePlatformConfig()
+  if not hasattr(gyp_config, "GetLauncher"):
+    return None
+  else:
+    return gyp_config.GetLauncher()
 
 
 def DynamicallyBuildOutDirectory(platform, config):
@@ -86,38 +89,21 @@
   return path
 
 
-def GetDefaultTargetPath(platform, config, target_name):
-  """Constructs the default path to an executable target.
-
-  The default path takes the form of:
-
-    "/path/to/out/<platform>_<config>/target_name"
-
-  Args:
-    platform: The platform to run the executable on, ex. "linux-x64x11".
-    config: The build configuration, ex. "qa".
-    target_name:  The name of the executable target, ex. "cobalt"
-
-  Returns:
-    The path to an executable target.
-  """
-  return os.path.join(DynamicallyBuildOutDirectory(platform, config),
-                      target_name)
-
-
-def LauncherFactory(platform, target_name, config, device_id, args,
-                    output_file=sys.stdout, out_directory=None):
+def LauncherFactory(platform, target_name, config, device_id=None,
+                    target_params=None, output_file=None,
+                    out_directory=None):
   """Creates the proper launcher based upon command line args.
 
   Args:
     platform:  The platform on which the app will run.
     target_name:  The name of the executable target (ex. "cobalt").
     config:  Type of configuration used by the launcher (ex. "qa", "devel").
-    device_id:  The identifier for the devkit being used.
-    args:  Any extra arguments to be passed on a platform-specific basis.
-    output_file:  The open file to which the launcher should write its output.
-    out_directory:  Path to directory where tool/test targets and/or their
-      components are stored.
+    device_id:  The identifier for the devkit being used.  Can be None.
+    target_params: Command line arguments to the executable.  Can be None.
+    output_file: Open file object used for storing the launcher's output. If
+      None, sys.stdout is used.
+    out_directory: Directory containing the executable target. If None is
+      provided, the path to the directory is dynamically generated.
 
   Returns:
     An instance of the concrete launcher class for the desired platform.
@@ -126,13 +112,28 @@
     RuntimeError: The platform does not exist, or there is no project root.
   """
 
-  if not out_directory:
-    out_directory = DynamicallyBuildOutDirectory(platform, config)
-
   #  Creates launcher for provided platform if the platform has a valid port
   launcher_module = _GetLauncherForPlatform(platform)
-  return launcher_module.Launcher(platform, target_name, config, device_id,
-                                  args, output_file, out_directory)
+
+  #  TODO: Refactor when all old launchers have been deleted
+  #  If a platform that does not have a new launcher is provided, attempt
+  #  to create an adapter to the old one.
+  if not launcher_module:
+    old_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
+                                            os.pardir, os.pardir, "tools",
+                                            "lbshell"))
+    if os.path.exists(os.path.join(old_path, "app_launcher.py")):
+      sys.path.append(old_path)
+      bridge_module = importlib.import_module("app_launcher_bridge")
+      return bridge_module.LauncherAdapter(
+          platform, target_name, config, device_id, target_params=target_params,
+          output_file=output_file, out_directory=out_directory)
+    else:
+      raise RuntimeError("No launcher implemented for the given platform.")
+  else:
+    return launcher_module.Launcher(
+        platform, target_name, config, device_id, target_params=target_params,
+        output_file=output_file, out_directory=out_directory)
 
 
 class AbstractLauncher(object):
@@ -140,18 +141,25 @@
 
   __metaclass__ = abc.ABCMeta
 
-  def __init__(self, platform, target_name, config, device_id,
-               args, output_file, out_directory):
+  def __init__(self, platform, target_name, config, device_id, **kwargs):
     self.platform = platform
     self.target_name = target_name
     self.config = config
     self.device_id = device_id
-    self.args = args
-    self.out_directory = out_directory
+    self.out_directory = kwargs.get("out_directory", None)
+
+    #  The following pattern makes sure that variables will be initialized
+    #  properly whether a kwarg is passed in with a value of None or it
+    #  is not passed in at all.
+    output_file = kwargs.get("output_file", None)
+    if not output_file:
+      output_file = sys.stdout
     self.output_file = output_file
-    self.target_command_line_params = []
-    if "target_params" in args:
-      self.target_command_line_params.extend(args["target_params"])
+
+    target_command_line_params = kwargs.get("target_params", None)
+    if not target_command_line_params:
+      target_command_line_params = []
+    self.target_command_line_params = target_command_line_params
 
     # Launchers that need different startup timeout times should reassign
     # this variable during initialization.
@@ -189,3 +197,21 @@
       (Host, port) tuple for use in connecting to the target device.
     """
     return self.device_id, port
+
+  def GetTargetPath(self):
+    """Constructs the path to an executable target.
+
+    The default path returned by this method takes the form of:
+
+      "/path/to/out/<platform>_<config>/target_name"
+
+    Returns:
+      The path to an executable target.
+    """
+    if self.out_directory:
+      out_directory = self.out_directory
+    else:
+      out_directory = DynamicallyBuildOutDirectory(self.platform, self.config)
+
+    return os.path.abspath(os.path.join(out_directory, self.target_name))
+
diff --git a/src/starboard/tools/testing/README.md b/src/starboard/tools/testing/README.md
index e3cab23..a191e91 100644
--- a/src/starboard/tools/testing/README.md
+++ b/src/starboard/tools/testing/README.md
@@ -76,4 +76,7 @@
 configurations.
 
 To filter out all tests for a particular target, provide
-"test_filter.FILTER_ALL" as the test name.
\ No newline at end of file
+"test_filter.FILTER_ALL" as the test name.
+
+To disable unit testing for all targets and all configurations, return a list
+containing "test_filter.DISABLE_TESTING".
\ No newline at end of file
diff --git a/src/starboard/tools/testing/test_filter.py b/src/starboard/tools/testing/test_filter.py
index 89c7794..161f52b 100644
--- a/src/starboard/tools/testing/test_filter.py
+++ b/src/starboard/tools/testing/test_filter.py
@@ -17,6 +17,7 @@
 # Constant to use for filtering all unit tests from a specific test executable.
 # Provide it as the "test_name" argument to TestFilter's constructor.
 FILTER_ALL = 'FILTER_ALL'
+DISABLE_TESTING = 'DISABLE_TESTING'
 
 
 class TestFilter(object):
diff --git a/src/starboard/tools/testing/test_runner.py b/src/starboard/tools/testing/test_runner.py
index cedc510..c2a72c4 100644
--- a/src/starboard/tools/testing/test_runner.py
+++ b/src/starboard/tools/testing/test_runner.py
@@ -33,6 +33,7 @@
 import signal
 import subprocess
 import threading
+import traceback
 
 import starboard.tools.abstract_launcher as abstract_launcher
 import starboard.tools.command_line as command_line
@@ -91,11 +92,11 @@
   """Runs unit tests."""
 
   def __init__(self, platform, config, device_id, single_target,
-               args, out_directory):
+               target_params, out_directory):
     self.platform = platform
     self.config = config
     self.device_id = device_id
-    self.args = args
+    self.target_params = target_params
     self.out_directory = out_directory
 
     # If a particular test binary has been provided, configure only that one.
@@ -128,6 +129,8 @@
     final_targets[single_target] = []
 
     for platform_filter in platform_filters:
+      if platform_filter == test_filter.DISABLE_TESTING:
+        return {}
       if platform_filter.target_name == single_target:
         # Only filter the tests specifying our config or all configs.
         if platform_filter.config == config or not platform_filter.config:
@@ -166,6 +169,8 @@
       final_targets[target] = []
 
     for platform_filter in platform_filters:
+      if platform_filter == test_filter.DISABLE_TESTING:
+        return {}
       # Only filter the tests specifying our config or all configs.
       if platform_filter.config == config or not platform_filter.config:
         if platform_filter.test_name == test_filter.FILTER_ALL:
@@ -189,9 +194,16 @@
     Args:
       ninja_flags: Command line flags to pass to ninja.
     """
-    args_list = ["ninja", "-C",
-                 abstract_launcher.DynamicallyBuildOutDirectory(
-                     self.platform, self.config)]
+    if not self.test_targets:
+      return
+
+    if self.out_directory:
+      build_dir = self.out_directory
+    else:
+      build_dir = abstract_launcher.DynamicallyBuildOutDirectory(
+          self.platform, self.config)
+
+    args_list = ["ninja", "-C", build_dir]
     args_list.extend([test_name for test_name in self.test_targets])
     if ninja_flags:
       args_list.append(ninja_flags)
@@ -221,13 +233,13 @@
 
     # Filter the specified tests for this platform, if any
     if self.test_targets[target_name]:
-      self.args["target_params"] = ["--gtest_filter=-{}".format(":".join(
-          self.test_targets[target_name]))]
+      self.target_params.append("--gtest_filter=-{}".format(":".join(
+          self.test_targets[target_name])))
 
     launcher = abstract_launcher.LauncherFactory(
         self.platform, target_name, self.config,
-        self.device_id, self.args, output_file=write_pipe,
-        out_directory=self.out_directory)
+        device_id=self.device_id, target_params=self.target_params,
+        output_file=write_pipe, out_directory=self.out_directory)
 
     reader = TestLineReader(read_pipe, write_pipe)
     #  If we need to manually exit the test runner at any point,
@@ -240,21 +252,30 @@
 
     signal.signal(signal.SIGINT, Abort)
     sys.stdout.write("Starting {}\n".format(target_name))
-    launcher.Run()
-    output = reader.GetLines()
 
-    return self._CollectTestResults(output, target_name)
+    return_code = 1
+    try:
+      return_code = launcher.Run()
+    except Exception as e:
+      sys.stderr.write("Error while running {}:\n".format(target_name))
+      traceback.print_exc(file=sys.stderr)
+    finally:
+      output = reader.GetLines()
 
-  def _CollectTestResults(self, results, target_name):
+    return self._CollectTestResults(output, target_name, return_code)
+
+  def _CollectTestResults(self, results, target_name, return_code):
     """Collects passing and failing tests for one test binary.
 
     Args:
       results: A list containing each line of test results.
       target_name: The name of the test target being run.
+      return_code: The return code of the test binary,
 
     Returns:
-      A tuple of length 5, of the format (target_name, number_of_total_tests,
-        number_of_passed_tests, number_of_failed_tests, list_of_failed_tests).
+      A tuple of length 6, of the format (target_name, number_of_total_tests,
+        number_of_passed_tests, number_of_failed_tests, list_of_failed_tests,
+        return_code).
     """
 
     total_count = 0
@@ -277,7 +298,8 @@
         # Descriptions of all failed tests appear after this line
         failed_tests = self._CollectFailedTests(results[idx + 1:])
 
-    return (target_name, total_count, passed_count, failed_count, failed_tests)
+    return (target_name, total_count, passed_count, failed_count, failed_tests,
+            return_code)
 
   def _CollectFailedTests(self, lines):
     """Collects the names of all failed tests.
@@ -308,7 +330,7 @@
     total_passed_count = 0
     total_failed_count = 0
 
-    # If the number of run or passed tests from a test binary cannot be
+    # If the number of run tests from a test binary cannot be
     # determined, assume an error occured while running it.
     error = False
 
@@ -321,33 +343,39 @@
       passed_count = result_set[2]
       failed_count = result_set[3]
       failed_tests = result_set[4]
+      return_code = result_set[5]
 
-      print "{}:".format(target_name)
-      if run_count == 0 or passed_count == 0:
+      test_status = "SUCCEEDED"
+      if return_code != 0:
         error = True
-        print "  ERROR OCCURED DURING TEST RUN (Did the test binary crash?)"
-      else:
-        print "  TOTAL TESTS RUN: {}".format(run_count)
-        total_run_count += run_count
-        print "  PASSED: {}".format(passed_count)
-        total_passed_count += passed_count
-        if failed_count > 0:
-          print "  FAILED: {}".format(failed_count)
-          total_failed_count += failed_count
-          print "\n  FAILED TESTS:"
-          for line in failed_tests:
-            print "    {}".format(line)
+        test_status = "FAILED"
+
+      print "{}: {}.".format(target_name, test_status)
+      if run_count == 0:
+        print"  Results not available.  Did the test crash?\n"
+        continue
+
+      print "  TOTAL TESTS RUN: {}".format(run_count)
+      total_run_count += run_count
+      print "  PASSED: {}".format(passed_count)
+      total_passed_count += passed_count
+      if failed_count > 0:
+        print "  FAILED: {}".format(failed_count)
+        total_failed_count += failed_count
+        print "\n  FAILED TESTS:"
+        for line in failed_tests:
+          print "    {}".format(line)
       # Print a single newline to separate results from each test run
       print
 
-    status = "SUCCEEDED"
+    overall_status = "SUCCEEDED"
     result = True
 
-    if total_failed_count > 0 or error:
-      status = "FAILED"
+    if error or total_failed_count > 0:
+      overall_status = "FAILED"
       result = False
 
-    print "TEST RUN {}.".format(status)
+    print "TEST RUN {}.".format(overall_status)
     print "  TOTAL TESTS RUN: {}".format(total_run_count)
     print "  TOTAL TESTS PASSED: {}".format(total_passed_count)
     print "  TOTAL TESTS FAILED: {}".format(total_failed_count)
@@ -410,11 +438,15 @@
       " as you would on the command line between a set of double quotation"
       " marks.")
 
-  extra_args = {}
   args = arg_parser.parse_args()
+
+  # Extra arguments for the test target
+  target_params = []
+  if args.target_params:
+    target_params = args.target_params.split(" ")
+
   runner = TestRunner(args.platform, args.config, args.device_id,
-                      args.target_name, extra_args,
-                      args.out_directory)
+                      args.target_name, target_params, args.out_directory)
   # If neither build nor run has been specified, assume the client
   # just wants to run.
   if not args.build and not args.run:
diff --git a/src/starboard/win/shared/starboard_platform.gypi b/src/starboard/win/shared/starboard_platform.gypi
index 260f790..84c3ed2 100644
--- a/src/starboard/win/shared/starboard_platform.gypi
+++ b/src/starboard/win/shared/starboard_platform.gypi
@@ -109,7 +109,9 @@
       '<(DEPTH)/starboard/shared/starboard/player/decoded_audio_internal.cc',
       '<(DEPTH)/starboard/shared/starboard/player/filter/audio_frame_tracker.cc',
       '<(DEPTH)/starboard/shared/starboard/player/filter/audio_frame_tracker.h',
-      '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink.h',
+      '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h',
       '<(DEPTH)/starboard/shared/starboard/player/filter/audio_resampler_impl.cc',
       '<(DEPTH)/starboard/shared/starboard/player/filter/audio_time_stretcher.cc',
       '<(DEPTH)/starboard/shared/starboard/player/filter/decoded_audio_queue.cc',
diff --git a/src/starboard/win/win32/gyp_configuration.gypi b/src/starboard/win/win32/gyp_configuration.gypi
index 3ba6c7c..a8795bd 100644
--- a/src/starboard/win/win32/gyp_configuration.gypi
+++ b/src/starboard/win/win32/gyp_configuration.gypi
@@ -14,8 +14,6 @@
 
 {
   'variables': {
-    'javascript_engine': 'mozjs-45',
-    'cobalt_enable_jit': 0,
     'angle_build_winrt': 0,
     'winrt': 0,
     'enable_d3d11_feature_level_11': 1,
diff --git a/src/starboard/win/win32/lib/gyp_configuration.gypi b/src/starboard/win/win32/lib/gyp_configuration.gypi
index 426c515..4e6657a 100644
--- a/src/starboard/win/win32/lib/gyp_configuration.gypi
+++ b/src/starboard/win/win32/lib/gyp_configuration.gypi
@@ -14,8 +14,6 @@
 
 {
   'variables': {
-    'javascript_engine': 'mozjs-45',
-    'cobalt_enable_jit': 0,
     # TODO: In theory, there are tools that can combine static libraries into
     # thick static libraries with all their transitive dependencies. Using
     # shared_library here can have unexpected consequences. Explore building
diff --git a/src/third_party/libwebp/libwebp.gyp b/src/third_party/libwebp/libwebp.gyp
index f2a17f3..353b472 100644
--- a/src/third_party/libwebp/libwebp.gyp
+++ b/src/third_party/libwebp/libwebp.gyp
@@ -59,7 +59,7 @@
     {
       'target_name': 'libwebp_dsp_neon',
       'conditions': [
-        ['(target_arch == "arm" and arm_version >= 7) or (OS == "lb_shell" and target_arch == "android")', {
+        ['(target_arch == "arm" and arm_version >= 7) or (target_arch == "arm64")', {
           'type': 'static_library',
           'include_dirs': ['.'],
           'sources': [
@@ -73,7 +73,7 @@
         },{  # "target_arch != "arm" or arm_version < 7"
           'type': 'none',
         }],
-        ['target_arch == "arm" and arm_version >= 8', {
+        ['(target_arch == "arm" and arm_version >= 8) or (target_arch == "arm64")', {
           # NEON is implicit on ARMv8, and both clang and gcc don't like the
           # redundant flag.
           'cflags!': [ '-mfpu=neon' ],
diff --git a/src/third_party/mozjs-45/mozjs-45.gyp b/src/third_party/mozjs-45/mozjs-45.gyp
index 91b74e0..c5f3ef9 100644
--- a/src/third_party/mozjs-45/mozjs-45.gyp
+++ b/src/third_party/mozjs-45/mozjs-45.gyp
@@ -45,7 +45,7 @@
       '<(DEPTH)/third_party/icu/source/common',
     ],
     'common_msvs_force_includes': [
-      'third_party/mozjs-45/cobalt_config/include/js-confdefs.h',

+      'third_party/mozjs-45/cobalt_config/include/js-confdefs.h',
     ],
     'common_msvs_disabled_warnings': [
       # Level 2, Possible loss of data due to type conversion.
@@ -109,12 +109,6 @@
         ],
       }],
 
-      ['cobalt_enable_jit != 1', {
-        'common_defines': [
-          'COBALT_DISABLE_JIT=1',
-        ],
-      }],
-
       # TODO: Remove once ps4 configuration todos are addressed.
       ['target_arch == "ps4" or sb_target_platform == "ps4"', {
         'common_defines': [
@@ -137,13 +131,23 @@
       }]
     ],
   },
-
+  # Required GYP massaging to allow |cobalt_enable_jit| to be a default
+  # variable.  Just pretend this is part of |variables| above.
+  'conditions': [
+    ['cobalt_enable_jit != 1', {
+      'variables': {
+        'common_defines': [
+          'COBALT_DISABLE_JIT=1',
+        ],
+      },
+    }],
+  ],
   'target_defaults': {
     'defines': [ '<@(common_defines)', ],
     'msvs_settings': {
-      'VCCLCompilerTool': {

-        'ForcedIncludeFiles': ['<@(common_msvs_force_includes)', ],

-      },

+      'VCCLCompilerTool': {
+        'ForcedIncludeFiles': ['<@(common_msvs_force_includes)', ],
+      },
     },
     'msvs_disabled_warnings': [
       '<@(common_msvs_disabled_warnings)',
@@ -160,9 +164,9 @@
     'direct_dependent_settings': {
       'msvs_disabled_warnings': [ '<@(common_msvs_disabled_warnings)', ],
       'msvs_settings': {
-        'VCCLCompilerTool': {

-          'ForcedIncludeFiles': [ '<@(common_msvs_force_includes)', ],

-        },

+        'VCCLCompilerTool': {
+          'ForcedIncludeFiles': [ '<@(common_msvs_force_includes)', ],
+        },
       },
     },
   },
diff --git a/src/tools/gyp/pylib/gyp/generator/ninja.py b/src/tools/gyp/pylib/gyp/generator/ninja.py
index 9f75af1..9f612d2 100755
--- a/src/tools/gyp/pylib/gyp/generator/ninja.py
+++ b/src/tools/gyp/pylib/gyp/generator/ninja.py
@@ -77,7 +77,8 @@
 is_linux = platform.system() == 'Linux'
 is_windows = platform.system() == 'Windows'
 
-microsoft_flavors = ['win', 'win-win32', 'win-win32-lib', 'xb1', 'xb1-future']
+microsoft_flavors = ['win', 'win-win32', 'win-win32-lib', 'xb1', 'xb1-future',
+    'xb1-youtubetv']
 sony_flavors = ['ps3', 'ps4']
 windows_host_flavors = microsoft_flavors + sony_flavors