Import Cobalt 22.master.0.305088
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..1fc585f
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,10 @@
+*.pyc
+# Settings directory for eclipse
+.settings/
+/buildbot
+/gyp-mac-tool
+/out
+.vscode
+.idea
+/venv/*
+_certs/
diff --git a/src/.pre-commit-config.yaml b/src/.pre-commit-config.yaml
index 7bc0f93..3813752 100644
--- a/src/.pre-commit-config.yaml
+++ b/src/.pre-commit-config.yaml
@@ -5,7 +5,7 @@
 default_language_version:
     python: python3
 
-exclude: '^(build|third_party|v8)/'
+exclude: '^(base|build|testing|third_party)/'
 
 repos:
 -   repo: https://cobalt.googlesource.com/pre-commit-hooks
@@ -21,6 +21,7 @@
     hooks:
     -   id: codespell
         name: Spell Check
+        exclude: '^cobalt/content/i18n/platform/'
 
 -   repo: local
     hooks:
@@ -72,7 +73,7 @@
         types: [java]
         args: [-i]
     -   id: gcheckstyle
-        name: gcheckstyle
+        name: Lint Java With gcheckstyle
         entry: python ./precommit_hooks/gcheckstyle_wrapper.py
         language: python
         types: [java]
@@ -83,6 +84,7 @@
         language: python
         types: [file, text]
         stages: [push]
+        exclude: '^cobalt/layout_tests/testdata/'
     -   id: check-if-starboard-interface-changed
         name: check if starboard interface changed
         entry: python ./precommit_hooks/warn_that_starboard_interface_changed_wrapper.py
@@ -137,6 +139,7 @@
         entry: python precommit_hooks/internal_file_check_wrapper.py
         language: python
         types: [text]
+        exclude: 'EXCLUDE\.FILES(\.RECURSIVE)?$'
     -   id: gn-format
         name: GN format
         entry: gn format
diff --git a/src/.pylintrc b/src/.pylintrc
index e167680..d955f5c 100644
--- a/src/.pylintrc
+++ b/src/.pylintrc
@@ -118,6 +118,7 @@
         old-raise-syntax,
         parameter-unpacking,
         print-statement,
+        raise-missing-from,
         raising-string,
         range-builtin-not-iterating,
         raw_input-builtin,
@@ -129,6 +130,7 @@
         setslice-method,
         signature-differs,
         standarderror-builtin,
+        super-with-arguments,
         suppressed-message,
         sys-max-int,
         too-few-public-methods,
@@ -147,6 +149,7 @@
         unicode-builtin,
         unnecessary-pass,
         unpacking-in-except,
+        unspecified-encoding,
         useless-else-on-loop,
         useless-object-inheritance,
         useless-suppression,
diff --git a/src/base/files/file_path.cc b/src/base/files/file_path.cc
index 4ce94c9..043d144 100644
--- a/src/base/files/file_path.cc
+++ b/src/base/files/file_path.cc
@@ -5,10 +5,11 @@
 #include "base/files/file_path.h"
 
 #include <string.h>
-
 #include <algorithm>
-#include <set>
-#include <string>
+
+#include "starboard/types.h"
+
+#include "starboard/common/string.h"
 
 #include "base/logging.h"
 #include "base/macros.h"
@@ -18,8 +19,6 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
-#include "starboard/common/string.h"
-#include "starboard/types.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/scoped_cftyperef.h"
@@ -58,28 +57,7 @@
        (path[0] >= L'a' && path[0] <= L'z'))) {
     return 1;
   }
-#elif defined(FILE_PATH_USES_MOUNT_POINT_NAME)
-  StringType::size_type delimiter_position = std::string(path).find(":");
-
-  auto has_disabled_symbols = [](std::string test_string) {
-    std::set<char> disabled_set = {'*', ':', '<', '>', '?', '|'};
-    std::set<char> tmp(test_string.begin(), test_string.end());
-    std::set<char> intersect;
-    std::set_intersection(disabled_set.begin(), disabled_set.end(), tmp.begin(),
-                          tmp.end(),
-                          std::inserter(intersect, intersect.begin()));
-    return !intersect.empty();
-  };
-  std::string mount_point = std::string(path).substr(0, delimiter_position);
-  std::string file_name = std::string(path).substr(delimiter_position + 1);
-  if (has_disabled_symbols(mount_point) || has_disabled_symbols(file_name)) {
-    return StringType::npos;
-  }
-
-  if (mount_point.size() >= 2 && delimiter_position != std::string::npos) {
-    return delimiter_position;
-  }
-#endif
+#endif  // FILE_PATH_USES_DRIVE_LETTERS
   return StringType::npos;
 }
 
@@ -103,8 +81,7 @@
 #endif  // defined(FILE_PATH_USES_DRIVE_LETTERS)
 
 bool IsPathAbsolute(StringPieceType path) {
-#if defined(FILE_PATH_USES_DRIVE_LETTERS) || \
-    defined(FILE_PATH_USES_MOUNT_POINT_NAME)
+#if defined(FILE_PATH_USES_DRIVE_LETTERS)
   StringType::size_type letter = FindDriveLetter(path);
   if (letter != StringType::npos) {
     // Look for a separator right after the drive specification.
@@ -114,10 +91,10 @@
   // Look for a pair of leading separators.
   return path.length() > 1 &&
       FilePath::IsSeparator(path[0]) && FilePath::IsSeparator(path[1]);
-#else  // FILE_PATH_USES_DRIVE_LETTERS || FILE_PATH_USES_MOUNT_POINT_NAME
+#else  // FILE_PATH_USES_DRIVE_LETTERS
   // Look for a separator in the first position.
   return path.length() > 0 && FilePath::IsSeparator(path[0]);
-#endif  // FILE_PATH_USES_DRIVE_LETTERS || FILE_PATH_USES_MOUNT_POINT_NAME
+#endif  // FILE_PATH_USES_DRIVE_LETTERS
 }
 
 bool AreAllSeparators(const StringType& input) {
diff --git a/src/base/files/file_path_unittest.cc b/src/base/files/file_path_unittest.cc
index afc30e7..593b1a0 100644
--- a/src/base/files/file_path_unittest.cc
+++ b/src/base/files/file_path_unittest.cc
@@ -415,31 +415,12 @@
     { FPL("c:/.."),  true },
     { FPL("C:/a"),   true },
     { FPL("d:/a"),   true },
-#elif defined(FILE_PATH_USES_MOUNT_POINT_NAME)
-    { FPL("/"),         false },
-    { FPL("/a"),        false },
-    { FPL("/."),        false },
-    { FPL("/.."),       false },
-    { FPL("ab:/."),     true  },
-    { FPL("ab:/"),      true  },
-    { FPL("ab:"),       false },
-    { FPL("b:"),        false },
-    { FPL("b:/"),       false },
-    { FPL("cache:/"),   true },
-    { FPL("rom:/"),     true },
-    { FPL("cache:/."),  true },
-    { FPL("rom:/."),    true },
-    { FPL("cache:/a"),  true },
-    { FPL("rom:/a"),    true },
-    { FPL("cache:/.."), true },
-    { FPL("rom:/.."),   true },
-#else  // !defined(FILE_PATH_USES_DRIVE_LETTERS) &&
-       // !defined(FILE_PATH_USES_MOUNT_POINT_NAME)
-    { FPL("/"),   true },
-    { FPL("/a"),  true },
-    { FPL("/."),  true },
-    { FPL("/.."), true },
-    { FPL("c:/"), false },
+#else  // FILE_PATH_USES_DRIVE_LETTERS
+    { FPL("/"),      true },
+    { FPL("/a"),     true },
+    { FPL("/."),     true },
+    { FPL("/.."),    true },
+    { FPL("c:/"),    false },
 #endif  // FILE_PATH_USES_DRIVE_LETTERS
 #if defined(FILE_PATH_USES_WIN_SEPARATORS)
     { FPL("a\\b"),   false },
diff --git a/src/base/test/scoped_task_environment.cc b/src/base/test/scoped_task_environment.cc
index 50a4632..92daedf 100644
--- a/src/base/test/scoped_task_environment.cc
+++ b/src/base/test/scoped_task_environment.cc
@@ -267,6 +267,11 @@
   mock_time_task_runner_->FastForwardBy(delta);
 }
 
+void ScopedTaskEnvironment::AdvanceMockTickClock(TimeDelta delta) {
+  DCHECK(mock_time_task_runner_);
+  mock_time_task_runner_->AdvanceMockTickClock(delta);
+}
+
 void ScopedTaskEnvironment::FastForwardUntilNoTasksRemain() {
   DCHECK(mock_time_task_runner_);
   mock_time_task_runner_->FastForwardUntilNoTasksRemain();
diff --git a/src/base/test/scoped_task_environment.h b/src/base/test/scoped_task_environment.h
index 2e46073..0f5aa59 100644
--- a/src/base/test/scoped_task_environment.h
+++ b/src/base/test/scoped_task_environment.h
@@ -116,6 +116,8 @@
   // (currently only main thread time is mocked).
   void FastForwardBy(TimeDelta delta);
 
+  void AdvanceMockTickClock(TimeDelta delta);
+
   // Only valid for instances with a MOCK_TIME MainThreadType.
   // Short for FastForwardBy(TimeDelta::Max()).
   void FastForwardUntilNoTasksRemain();
diff --git a/src/build/.gitignore b/src/build/.gitignore
new file mode 100644
index 0000000..2e96339
--- /dev/null
+++ b/src/build/.gitignore
@@ -0,0 +1,28 @@
+# This file is needed for projects that has this directory as a separate Git
+# mirror in DEPS. Without it, a lot is wiped and re-downloaded for each sync.
+*.pyc
+ciopfs
+/android/bin
+/android/binary_size/apks/**/*.apk
+/args/chromeos/*.gni
+/config/gclient_args.gni
+/cros_cache/
+/Debug
+/Debug_x64
+/fuchsia/internal/
+/goma
+/gomacc.lock
+/ipch/
+/lacros/prebuilt_ash_chrome/
+/Release
+/Release_x64
+/win_toolchain.json
+/util/LASTCHANGE*
+/util/support
+/x64/
+/linux/debian_*-sysroot/
+/linux/ubuntu_*-sysroot/
+/ios_files
+/mac_files
+
+!/util/LASTCHANGE.dummy
diff --git a/src/build/toolchain/win/rc/.gitignore b/src/build/toolchain/win/rc/.gitignore
new file mode 100644
index 0000000..e8fc4d3
--- /dev/null
+++ b/src/build/toolchain/win/rc/.gitignore
@@ -0,0 +1,3 @@
+linux64/rc
+mac/rc
+win/rc.exe
diff --git a/src/buildtools/.gitignore b/src/buildtools/.gitignore
new file mode 100644
index 0000000..c2c8dc2
--- /dev/null
+++ b/src/buildtools/.gitignore
@@ -0,0 +1,12 @@
+*.pyc
+third_party/libc++/trunk
+third_party/libc++abi/trunk
+third_party/libunwind/trunk
+linux64/gn
+linux64/clang-format
+mac/gn
+mac/clang-format
+win/gn.exe
+win/clang-format.exe
+android/doclava/
+android/doclava.tar.gz
diff --git a/src/buildtools/linux64/clang-format b/src/buildtools/linux64/clang-format
deleted file mode 100755
index a79160c..0000000
--- a/src/buildtools/linux64/clang-format
+++ /dev/null
Binary files differ
diff --git a/src/cobalt/.gitignore b/src/cobalt/.gitignore
new file mode 100644
index 0000000..5b69378
--- /dev/null
+++ b/src/cobalt/.gitignore
@@ -0,0 +1,5 @@
+*.pyc
+*.sublime-workspace
+*.swp
+*.tmp
+.DS_Store
diff --git a/src/cobalt/audio/audio_destination_node.cc b/src/cobalt/audio/audio_destination_node.cc
index 6f82ba8..3f0505f 100644
--- a/src/cobalt/audio/audio_destination_node.cc
+++ b/src/cobalt/audio/audio_destination_node.cc
@@ -62,11 +62,15 @@
     SB_LOG(INFO) << "Created audio device " << audio_device_.get() << '.';
     context()->PreventGarbageCollection();
   }
-  audio_device_to_delete_ = NULL;
+  delete_audio_device_ = false;
 }
 
 void AudioDestinationNode::FillAudioBus(bool all_consumed, AudioBus* audio_bus,
                                         bool* silence) {
+  if (delete_audio_device_) {
+    return;
+  }
+
   // This is called on Audio thread.
   AudioLock::AutoLock lock(audio_lock());
 
@@ -74,11 +78,10 @@
   DCHECK_EQ(number_of_inputs(), 1u);
   bool all_finished = true;
   Input(0)->FillAudioBus(audio_bus, silence, &all_finished);
-  if (all_consumed && all_finished &&
-      audio_device_to_delete_ != audio_device_.get()) {
+  if (all_consumed && all_finished) {
     SB_LOG(INFO) << "Schedule to destroy audio device " << audio_device_.get()
                  << '.';
-    audio_device_to_delete_ = audio_device_.get();
+    delete_audio_device_ = true;
     message_loop_->task_runner()->PostTask(
         FROM_HERE, base::Bind(&AudioDestinationNode::DestroyAudioDevice,
                               base::Unretained(this)));
@@ -90,10 +93,11 @@
   if (!audio_device_.get()) {
     return;
   }
-  if (audio_device_.get() == audio_device_to_delete_) {
+  if (delete_audio_device_) {
     SB_LOG(INFO) << "Destroying audio device " << audio_device_.get() << '.';
     audio_device_.reset();
     context()->AllowGarbageCollection();
+    delete_audio_device_ = false;
   }
 }
 
diff --git a/src/cobalt/audio/audio_destination_node.h b/src/cobalt/audio/audio_destination_node.h
index b758d92..77cee04 100644
--- a/src/cobalt/audio/audio_destination_node.h
+++ b/src/cobalt/audio/audio_destination_node.h
@@ -74,7 +74,7 @@
   uint32 max_channel_count_;
 
   std::unique_ptr<AudioDevice> audio_device_;
-  AudioDevice* audio_device_to_delete_ = NULL;
+  std::atomic_bool delete_audio_device_ = {false};
 
   DISALLOW_COPY_AND_ASSIGN(AudioDestinationNode);
 };
diff --git a/src/cobalt/black_box_tests/tests/web_debugger.py b/src/cobalt/black_box_tests/tests/web_debugger.py
index 6130376..be9b723 100644
--- a/src/cobalt/black_box_tests/tests/web_debugger.py
+++ b/src/cobalt/black_box_tests/tests/web_debugger.py
@@ -34,7 +34,7 @@
     os.path.join(
         os.path.dirname(__file__), '..', '..', '..', 'third_party',
         'websocket-client'))
-import websocket  # pylint: disable=g-bad-import-order,g-import-not-at-top
+import websocket  # pylint: disable=wrong-import-position
 
 # Set to True to add additional logging to debug the test.
 _DEBUG = False
@@ -78,9 +78,9 @@
     self.ws_url = ws_url
     self.timeout = timeout
     self.last_id = 0
-    self.commands = dict()
-    self.responses = dict()
-    self.events = list()
+    self.commands = {}
+    self.responses = {}
+    self.events = []
 
   def __enter__(self):
     websocket.enableTrace(_DEBUG)
@@ -216,24 +216,21 @@
 class WebDebuggerTest(black_box_tests.BlackBoxTestCase):
   """Test interaction with the web debugger over a WebSocket."""
 
-  def setUpWith(self, cm):
+  def set_up_with(self, cm):
     val = cm.__enter__()
     self.addCleanup(cm.__exit__, None, None, None)
     return val
 
   def setUp(self):
-    platform_vars = self.platform_config.GetVariables(
-        self.launcher_params.config)
-
     cobalt_vars = self.cobalt_config.GetVariables(self.launcher_params.config)
     if not cobalt_vars['enable_debugger']:
       self.skipTest('DevTools is disabled on this platform')
 
-    self.server = self.setUpWith(
+    self.server = self.set_up_with(
         ThreadedWebServer(binding_address=self.GetBindingAddress()))
     url = self.server.GetURL(file_name='testdata/web_debugger.html')
-    self.runner = self.setUpWith(self.CreateCobaltRunner(url=url))
-    self.debugger = self.setUpWith(self.create_debugger_connection())
+    self.runner = self.set_up_with(self.CreateCobaltRunner(url=url))
+    self.debugger = self.set_up_with(self.create_debugger_connection())
     self.runner.WaitForJSTestsSetup()
     self.debugger.enable_runtime()
 
diff --git a/src/cobalt/browser/browser.gyp b/src/cobalt/browser/browser.gyp
index 65444e2..6eb6f23 100644
--- a/src/cobalt/browser/browser.gyp
+++ b/src/cobalt/browser/browser.gyp
@@ -37,8 +37,6 @@
         'memory_settings/checker.cc',
         'memory_settings/checker.h',
         'memory_settings/constants.h',
-        'memory_settings/constrainer.cc',
-        'memory_settings/constrainer.h',
         'memory_settings/scaling_function.cc',
         'memory_settings/scaling_function.h',
         'memory_settings/memory_settings.cc',
@@ -209,7 +207,6 @@
         'memory_settings/auto_mem_test.cc',
         'memory_settings/auto_mem_settings_test.cc',
         'memory_settings/calculations_test.cc',
-        'memory_settings/constrainer_test.cc',
         'memory_settings/memory_settings_test.cc',
         'memory_settings/pretty_print_test.cc',
         'memory_settings/table_printer_test.cc',
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc
index 1f6e058..f66ed8b 100644
--- a/src/cobalt/browser/browser_module.cc
+++ b/src/cobalt/browser/browser_module.cc
@@ -1461,8 +1461,7 @@
   DCHECK_EQ(base::MessageLoop::current(), self_message_loop_);
   DCHECK(application_state_ == base::kApplicationStateStarted);
   application_state_ = base::kApplicationStateBlurred;
-  FOR_EACH_OBSERVER(LifecycleObserver,
-                    lifecycle_observers_, Blur(timestamp));
+  FOR_EACH_OBSERVER(LifecycleObserver, lifecycle_observers_, Blur(timestamp));
 }
 
 void BrowserModule::Conceal(SbTimeMonotonic timestamp) {
@@ -1477,8 +1476,7 @@
   TRACE_EVENT0("cobalt::browser", "BrowserModule::Focus()");
   DCHECK_EQ(base::MessageLoop::current(), self_message_loop_);
   DCHECK(application_state_ == base::kApplicationStateBlurred);
-  FOR_EACH_OBSERVER(LifecycleObserver,
-                    lifecycle_observers_, Focus(timestamp));
+  FOR_EACH_OBSERVER(LifecycleObserver, lifecycle_observers_, Focus(timestamp));
   application_state_ = base::kApplicationStateStarted;
 }
 
@@ -1629,12 +1627,12 @@
                                                options_.media_module_options));
 
     if (web_module_) {
-      web_module_->SetCamera3D(input_device_manager_->camera_3d());
       web_module_->SetMediaModule(media_module_.get());
     }
   }
 
   if (web_module_) {
+    web_module_->UpdateCamera3D(input_device_manager_->camera_3d());
     web_module_->GetUiNavRoot()->SetContainerWindow(
         system_window_->GetSbWindow());
   }
@@ -1782,8 +1780,7 @@
   FreezeMediaModule();
   // First freeze all our web modules which implies that they will release
   // their resource provider and all resources created through it.
-  FOR_EACH_OBSERVER(LifecycleObserver,
-                    lifecycle_observers_, Freeze(timestamp));
+  FOR_EACH_OBSERVER(LifecycleObserver, lifecycle_observers_, Freeze(timestamp));
 }
 
 void BrowserModule::RevealInternal(SbTimeMonotonic timestamp) {
@@ -2095,14 +2092,12 @@
 }
 
 void BrowserModule::SetApplicationStartOrPreloadTimestamp(
-  bool is_preload, SbTimeMonotonic timestamp) {
+    bool is_preload, SbTimeMonotonic timestamp) {
   DCHECK(web_module_);
-  web_module_->SetApplicationStartOrPreloadTimestamp(
-      is_preload, timestamp);
+  web_module_->SetApplicationStartOrPreloadTimestamp(is_preload, timestamp);
 }
 
-void BrowserModule::SetDeepLinkTimestamp(
-    SbTimeMonotonic timestamp) {
+void BrowserModule::SetDeepLinkTimestamp(SbTimeMonotonic timestamp) {
   DCHECK(web_module_);
   web_module_->SetDeepLinkTimestamp(timestamp);
 }
diff --git a/src/cobalt/browser/memory_settings/auto_mem.cc b/src/cobalt/browser/memory_settings/auto_mem.cc
index 30a040f..02e7140 100644
--- a/src/cobalt/browser/memory_settings/auto_mem.cc
+++ b/src/cobalt/browser/memory_settings/auto_mem.cc
@@ -20,6 +20,7 @@
 #include <cmath>
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/optional.h"
@@ -31,7 +32,6 @@
 #include "cobalt/browser/memory_settings/auto_mem_settings.h"
 #include "cobalt/browser/memory_settings/calculations.h"
 #include "cobalt/browser/memory_settings/constants.h"
-#include "cobalt/browser/memory_settings/constrainer.h"
 #include "cobalt/browser/memory_settings/memory_settings.h"
 #include "cobalt/browser/memory_settings/pretty_print.h"
 #include "cobalt/browser/memory_settings/scaling_function.h"
@@ -230,44 +230,6 @@
          "monotonically decreasing values as input goes from 1.0 -> 0.0";
 }
 
-int64_t GenerateTargetMemoryBytes(int64_t max_memory_bytes,
-                                  int64_t current_memory_bytes,
-                                  base::Optional<int64_t> reduce_memory_bytes) {
-  // Make sure values are sanitized.
-  max_memory_bytes = std::max<int64_t>(0, max_memory_bytes);
-  current_memory_bytes = std::max<int64_t>(0, current_memory_bytes);
-
-  // If reduce_memory_bytes is valid and it's a zero or positive value then
-  // this is a signal that the calculation should be based off of this setting.
-  bool use_reduce_memory_input =
-      (reduce_memory_bytes && (-1 < *reduce_memory_bytes));
-
-  if (use_reduce_memory_input) {
-    // If reducing_memory_bytes is set exactly to 0, then this
-    // this will disable max_memory_bytes setting. current_memory_bytes
-    // will be returned as the target memory consumption,
-    // which will prevent memory constraining.
-    if (*reduce_memory_bytes == 0) {
-      return current_memory_bytes;
-    } else {
-      // Reduce memory bytes will subtract from the current memory
-      // consumption.
-      const int64_t target_value = current_memory_bytes - *reduce_memory_bytes;
-      return math::Clamp<int64_t>(target_value, 0, std::abs(target_value));
-    }
-  } else {  // reduce_memory_bytes is not used. Use max_memory_bytes instead.
-    // max_memory_bytes == 0 is special, and signals that no constraining
-    // should happen.
-    if (max_memory_bytes == 0) {
-      return current_memory_bytes;
-    } else {
-      // A non-zero value means that max_memory_bytes is valid and should
-      // be used as the target value.
-      return max_memory_bytes;
-    }
-  }
-}
-
 }  // namespace
 
 AutoMem::AutoMem(const math::Size& ui_resolution,
@@ -276,28 +238,11 @@
   TRACE_EVENT0("cobalt::browser", "AutoMem::AutoMem()");
   ConstructSettings(ui_resolution, command_line_settings, build_settings);
 
-  const int64_t target_cpu_memory = GenerateTargetMemoryBytes(
-      max_cpu_bytes_->value(), SumAllMemoryOfType(MemorySetting::kCPU),
-      base::Optional<int64_t>(0));
-  const int64_t target_gpu_memory = GenerateTargetMemoryBytes(
-      max_gpu_bytes_->value(), SumAllMemoryOfType(MemorySetting::kGPU),
-      reduced_gpu_bytes_->optional_value());
-
   std::vector<MemorySetting*> memory_settings = AllMemorySettingsMutable();
-  ConstrainToMemoryLimits(target_cpu_memory, target_gpu_memory,
-                          &memory_settings, &error_msgs_);
 }
 
 AutoMem::~AutoMem() {}
 
-const IntSetting* AutoMem::misc_cobalt_cpu_size_in_bytes() const {
-  return misc_cobalt_cpu_size_in_bytes_.get();
-}
-
-const IntSetting* AutoMem::misc_cobalt_gpu_size_in_bytes() const {
-  return misc_cobalt_gpu_size_in_bytes_.get();
-}
-
 const IntSetting* AutoMem::remote_typeface_cache_size_in_bytes() const {
   return remote_typeface_cache_size_in_bytes_.get();
 }
@@ -350,8 +295,6 @@
   // Keep these in alphabetical order.
   all_settings.push_back(encoded_image_cache_size_in_bytes_.get());
   all_settings.push_back(image_cache_size_in_bytes_.get());
-  all_settings.push_back(misc_cobalt_cpu_size_in_bytes_.get());
-  all_settings.push_back(misc_cobalt_gpu_size_in_bytes_.get());
   all_settings.push_back(offscreen_target_cache_size_in_bytes_.get());
   all_settings.push_back(remote_typeface_cache_size_in_bytes_.get());
   all_settings.push_back(skia_atlas_texture_dimensions_.get());
@@ -421,15 +364,6 @@
   max_cpu_bytes_ = CreateCpuSetting(command_line_settings, build_settings);
   max_gpu_bytes_ = CreateGpuSetting(command_line_settings, build_settings);
 
-  reduced_gpu_bytes_ = CreateSystemMemorySetting(
-      switches::kReduceGpuMemoryBy, MemorySetting::kGPU,
-      command_line_settings.reduce_gpu_memory_by,
-      build_settings.reduce_gpu_memory_by, -1);
-  if (reduced_gpu_bytes_->value() == -1) {
-    // This effectively disables the value from being used in the constrainer.
-    reduced_gpu_bytes_->set_value(MemorySetting::kUnset, 0);
-  }
-
   // Set the encoded image cache capacity
   encoded_image_cache_size_in_bytes_ = CreateMemorySetting<IntSetting, int64_t>(
       switches::kEncodedImageCacheSizeInBytes,
@@ -454,19 +388,6 @@
   image_cache_size_in_bytes_->set_memory_scaling_function(
       MakeLinearMemoryScaler(.75, 1.0));
 
-  // Set the misc cobalt size to a specific size.
-  misc_cobalt_cpu_size_in_bytes_.reset(
-      new IntSetting("misc_cobalt_cpu_size_in_bytes"));
-  misc_cobalt_cpu_size_in_bytes_->set_value(MemorySetting::kAutoSet,
-                                            kMiscCobaltCpuSizeInBytes);
-
-  // Set the misc cobalt size to a specific size.
-  misc_cobalt_gpu_size_in_bytes_.reset(
-      new IntSetting("misc_cobalt_gpu_size_in_bytes"));
-  misc_cobalt_gpu_size_in_bytes_->set_memory_type(MemorySetting::kGPU);
-  misc_cobalt_gpu_size_in_bytes_->set_value(
-      MemorySetting::kAutoSet, CalculateMiscCobaltGpuSize(ui_resolution));
-
   // Set remote_type_face_cache size.
   remote_typeface_cache_size_in_bytes_ =
       CreateMemorySetting<IntSetting, int64_t>(
diff --git a/src/cobalt/browser/memory_settings/auto_mem.h b/src/cobalt/browser/memory_settings/auto_mem.h
index fd78576..6aa2b76 100644
--- a/src/cobalt/browser/memory_settings/auto_mem.h
+++ b/src/cobalt/browser/memory_settings/auto_mem.h
@@ -44,11 +44,8 @@
 
   const IntSetting* encoded_image_cache_size_in_bytes() const;
   const IntSetting* image_cache_size_in_bytes() const;
-  const IntSetting* javascript_gc_threshold_in_bytes() const;
   // This setting represents all others cpu-memory consuming systems within
   // the engine. This value has been hard coded.
-  const IntSetting* misc_cobalt_cpu_size_in_bytes() const;
-  const IntSetting* misc_cobalt_gpu_size_in_bytes() const;
   const IntSetting* remote_typeface_cache_size_in_bytes() const;
   const DimensionSetting* skia_atlas_texture_dimensions() const;
   const IntSetting* skia_cache_size_in_bytes() const;
@@ -82,9 +79,6 @@
   // All of the following are included in AllMemorySettings().
   std::unique_ptr<IntSetting> encoded_image_cache_size_in_bytes_;
   std::unique_ptr<IntSetting> image_cache_size_in_bytes_;
-  std::unique_ptr<IntSetting> javascript_gc_threshold_in_bytes_;
-  std::unique_ptr<IntSetting> misc_cobalt_cpu_size_in_bytes_;
-  std::unique_ptr<IntSetting> misc_cobalt_gpu_size_in_bytes_;
   std::unique_ptr<IntSetting> remote_typeface_cache_size_in_bytes_;
   std::unique_ptr<DimensionSetting> skia_atlas_texture_dimensions_;
   std::unique_ptr<IntSetting> skia_cache_size_in_bytes_;
@@ -95,18 +89,12 @@
   // in AllMemorySettings().
   std::unique_ptr<IntSetting> max_cpu_bytes_;
   std::unique_ptr<IntSetting> max_gpu_bytes_;
-  std::unique_ptr<IntSetting>
-      reduced_cpu_bytes_;  // Forces CPU memory reduction.
-  std::unique_ptr<IntSetting>
-      reduced_gpu_bytes_;  // Forces GPU memory reduction.
 
   std::vector<std::string> error_msgs_;
 
   FRIEND_TEST(AutoMem, AllMemorySettingsAreOrderedByName);
   FRIEND_TEST(AutoMem, ConstrainedCPUEnvironment);
   FRIEND_TEST(AutoMem, ConstrainedGPUEnvironment);
-  FRIEND_TEST(AutoMem, ExplicitReducedCPUMemoryConsumption);
-  FRIEND_TEST(AutoMem, ExplicitReducedGPUMemoryConsumption);
   FRIEND_TEST(AutoMem, MaxCpuIsIgnoredDuringExplicitMemoryReduction);
 };
 
diff --git a/src/cobalt/browser/memory_settings/auto_mem_settings.cc b/src/cobalt/browser/memory_settings/auto_mem_settings.cc
index 98ef408..1a089e9 100644
--- a/src/cobalt/browser/memory_settings/auto_mem_settings.cc
+++ b/src/cobalt/browser/memory_settings/auto_mem_settings.cc
@@ -264,8 +264,6 @@
       switches::kOffscreenTargetCacheSizeInBytes);
   Set(command_line, &settings.max_cpu_in_bytes, switches::kMaxCobaltCpuUsage);
   Set(command_line, &settings.max_gpu_in_bytes, switches::kMaxCobaltGpuUsage);
-  Set(command_line, &settings.reduce_gpu_memory_by,
-      switches::kReduceGpuMemoryBy);
 
   return settings;
 }
diff --git a/src/cobalt/browser/memory_settings/auto_mem_settings_test.cc b/src/cobalt/browser/memory_settings/auto_mem_settings_test.cc
index 5f2a555..3c710ca 100644
--- a/src/cobalt/browser/memory_settings/auto_mem_settings_test.cc
+++ b/src/cobalt/browser/memory_settings/auto_mem_settings_test.cc
@@ -81,8 +81,6 @@
                  max_cpu_in_bytes);
   TEST_PARSE_INT(expected, value, switches::kMaxCobaltGpuUsage,
                  max_gpu_in_bytes);
-  TEST_PARSE_INT(expected, value, switches::kReduceGpuMemoryBy,
-                 reduce_gpu_memory_by);
 #undef TEST_PARSE_INT
 }
 
@@ -122,7 +120,6 @@
   EXPECT_FALSE(settings.offscreen_target_cache_size_in_bytes);
   EXPECT_FALSE(settings.max_cpu_in_bytes);
   EXPECT_FALSE(settings.max_gpu_in_bytes);
-  EXPECT_FALSE(settings.reduce_gpu_memory_by);
 
   AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
   EXPECT_EQ(AutoMemSettings::kTypeBuild, build_settings.type);
diff --git a/src/cobalt/browser/memory_settings/auto_mem_test.cc b/src/cobalt/browser/memory_settings/auto_mem_test.cc
index 0891d87..64f76d3 100644
--- a/src/cobalt/browser/memory_settings/auto_mem_test.cc
+++ b/src/cobalt/browser/memory_settings/auto_mem_test.cc
@@ -37,12 +37,6 @@
 
 const math::Size kResolution1080p(1920, 1080);
 
-// Represents what the cobalt engine can scale down to under a default
-// environment.
-const int64_t kSmallEngineCpuMemorySize = 130 * 1024 * 1024;
-
-const int64_t kSmallEngineGpuMemorySize = 68 * 1024 * 1024;
-
 #define EXPECT_MEMORY_SETTING(SETTING, SOURCE, MEMORY_TYPE, VALUE)          \
   EXPECT_EQ(VALUE, SETTING->value()) << " failure for " << SETTING->name(); \
   EXPECT_EQ(MEMORY_TYPE, SETTING->memory_type())                            \
@@ -54,13 +48,6 @@
   return AutoMemSettings(AutoMemSettings::kTypeCommandLine);
 }
 
-std::unique_ptr<AutoMem> CreateDefaultAutoMem() {
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-  std::unique_ptr<AutoMem> auto_mem(
-      new AutoMem(kResolution1080p, EmptyCommandLine(), build_settings));
-  return auto_mem;
-}
-
 }  // namespace.
 
 // Tests the expectation that the command-line overrides will be applied.
@@ -230,156 +217,6 @@
   }
 }
 
-// Tests the expectation that constraining the CPU memory to kSmallEngineSize
-// will result in AutoMem reducing to the expected memory footprint.
-TEST(AutoMem, ConstrainedCPUEnvironment) {
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-  build_settings.max_cpu_in_bytes = kSmallEngineCpuMemorySize;
-
-  AutoMem auto_mem(kResolution1080p, EmptyCommandLine(), build_settings);
-
-  const int64_t cpu_memory_consumption =
-      auto_mem.SumAllMemoryOfType(MemorySetting::kCPU);
-  EXPECT_LE(cpu_memory_consumption, kSmallEngineCpuMemorySize);
-}
-
-// Tests the expectation that constraining the GPU memory will result
-// in AutoMem reducing the the memory footprint.
-TEST(AutoMem, ConstrainedGPUEnvironment) {
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-  build_settings.max_gpu_in_bytes = 57 * 1024 * 1024;
-  AutoMem auto_mem(kResolution1080p, EmptyCommandLine(), build_settings);
-
-  std::vector<const MemorySetting*> settings = auto_mem.AllMemorySettings();
-  const int64_t gpu_memory_consumption =
-      SumMemoryConsumption(MemorySetting::kGPU, settings);
-  EXPECT_LE(gpu_memory_consumption, *build_settings.max_gpu_in_bytes);
-}
-
-// Tests the expectation that constraining the CPU memory to 40MB will result
-// in AutoMem reducing the the memory footprint.
-TEST(AutoMem, ExplicitReducedGPUMemoryConsumption) {
-  // STEP ONE: Get the "natural" size of the engine at the default test
-  // settings.
-  std::unique_ptr<AutoMem> default_auto_mem = CreateDefaultAutoMem();
-
-  AutoMemSettings command_line_settings(AutoMemSettings::kTypeCommandLine);
-  command_line_settings.reduce_gpu_memory_by = 5 * 1024 * 1024;
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-  AutoMem reduced_gpu_memory_auto_mem(kResolution1080p, command_line_settings,
-                                      build_settings);
-  EXPECT_EQ(5 * 1024 * 1024,
-            reduced_gpu_memory_auto_mem.reduced_gpu_bytes_->value());
-
-  const int64_t original_memory_consumption =
-      default_auto_mem->SumAllMemoryOfType(MemorySetting::kGPU);
-  const int64_t reduced_memory_consumption =
-      reduced_gpu_memory_auto_mem.SumAllMemoryOfType(MemorySetting::kGPU);
-
-  EXPECT_LE(5 * 1024 * 1024,
-            original_memory_consumption - reduced_memory_consumption);
-}
-
-// Tests the expectation that the constrainer will not run on cpu memory if
-// --reduce_cpu_memory_by is set to 0.
-TEST(AutoMem, MaxCpuIsIgnoredWithZeroValueReduceCPUCommand) {
-  // STEP ONE: Get the "natural" size of the engine at the default test
-  // settings.
-  std::unique_ptr<AutoMem> default_auto_mem = CreateDefaultAutoMem();
-
-  AutoMemSettings command_line_settings(AutoMemSettings::kTypeCommandLine);
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-
-  // Max memory is 1-byte. We expect that the kReduceCpuMemoryBy = "0" will
-  // override the max_cpu_in_bytes setting.
-  build_settings.max_cpu_in_bytes = 1;
-  command_line_settings.reduce_cpu_memory_by = 0;
-
-  AutoMem auto_mem_no_reduce_cpu(kResolution1080p, command_line_settings,
-                                 build_settings);
-
-  const int64_t original_memory_consumption =
-      default_auto_mem->SumAllMemoryOfType(MemorySetting::kCPU);
-  const int64_t new_memory_consumption =
-      auto_mem_no_reduce_cpu.SumAllMemoryOfType(MemorySetting::kCPU);
-
-  // Max_cpu_in_bytes specifies one byte of memory, but reduce must override
-  // this for this test to pass.
-  EXPECT_EQ(original_memory_consumption, new_memory_consumption);
-}
-
-// Tests the expectation that the constrainer will not run on gpu memory if
-// --reduce_gpu_memory_by is set to 0.
-TEST(AutoMem, MaxCpuIsIgnoredWithZeroValueReduceGPUCommand) {
-  // STEP ONE: Get the "natural" size of the engine at the default test
-  // settings.
-  std::unique_ptr<AutoMem> default_auto_mem = CreateDefaultAutoMem();
-
-  AutoMemSettings command_line_settings(AutoMemSettings::kTypeCommandLine);
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-
-  // Max memory is 1-byte. We expect that the kReduceCpuMemoryBy = "0" will
-  // override the max_cpu_in_bytes setting.
-  build_settings.max_gpu_in_bytes = 1;
-  command_line_settings.reduce_gpu_memory_by = 0;
-
-  AutoMem auto_mem_no_reduce_cpu(kResolution1080p, command_line_settings,
-                                 build_settings);
-
-  const int64_t original_memory_consumption =
-      default_auto_mem->SumAllMemoryOfType(MemorySetting::kGPU);
-  const int64_t new_memory_consumption =
-      auto_mem_no_reduce_cpu.SumAllMemoryOfType(MemorySetting::kGPU);
-
-  // Max_gpu_in_bytes specifies one byte of memory, but reduce must override
-  // this for this test to pass.
-  EXPECT_EQ(original_memory_consumption, new_memory_consumption);
-}
-
-// Tests the expectation that if --reduce_cpu_memory_by is set to -1 that it
-// will be effectively disabled and --max_cpu_bytes be used as the memory
-// reduction means.
-TEST(AutoMem, MaxCpuIsEnabledWhenReduceCpuMemoryIsExplicitlyDisabled) {
-  AutoMemSettings command_line_settings(AutoMemSettings::kTypeCommandLine);
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-
-  // Max memory is 1-byte. We expect that the kReduceCpuMemoryBy = "-1"
-  // passed to the command line will cause max_cpu_in_bytes to be the
-  // dominating memory reduction mechanism.
-  build_settings.max_cpu_in_bytes = kSmallEngineGpuMemorySize;
-  command_line_settings.reduce_cpu_memory_by = -1;
-
-  AutoMem auto_mem_no_reduce_cpu(kResolution1080p, command_line_settings,
-                                 build_settings);
-  const int64_t memory_consumption =
-      auto_mem_no_reduce_cpu.SumAllMemoryOfType(MemorySetting::kCPU);
-  // Max_cpu_in_bytes specifies one byte of memory, but reduce must override
-  // this for this test to pass.
-  EXPECT_LE(memory_consumption, kSmallEngineCpuMemorySize);
-}
-
-// Tests the expectation that if --reduce_gpu_memory_by is set to -1 that it
-// will be effectively disabled and --max_gpu_bytes be used as the memory
-// reduction means.
-TEST(AutoMem, MaxGpuIsEnabledWhenReduceCpuMemoryIsExplicitlyDisabled) {
-  AutoMemSettings command_line_settings(AutoMemSettings::kTypeCommandLine);
-  AutoMemSettings build_settings(AutoMemSettings::kTypeBuild);
-
-  // Max memory is 1-byte. We expect that the kReduceCpuMemoryBy = "-1"
-  // passed to the command line will cause max_cpu_in_bytes to be the
-  // dominating memory reduction mechanism.
-  build_settings.max_gpu_in_bytes = kSmallEngineGpuMemorySize;
-  command_line_settings.reduce_gpu_memory_by = -1;
-
-  AutoMem auto_mem_no_reduce_cpu(kResolution1080p, command_line_settings,
-                                 build_settings);
-  const int64_t memory_consumption =
-      auto_mem_no_reduce_cpu.SumAllMemoryOfType(MemorySetting::kGPU);
-  // Max_cpu_in_bytes specifies one byte of memory, but reduce must override
-  // this for this test to pass.
-  EXPECT_LE(memory_consumption, kSmallEngineGpuMemorySize);
-}
-
 // Tests that if the gpu memory could not be queried then the resulting
 // max_gpu_bytes will not be valid.
 TEST(AutoMem, NoDefaultGpuMemory) {
diff --git a/src/cobalt/browser/memory_settings/calculations.cc b/src/cobalt/browser/memory_settings/calculations.cc
index 7b5a35f..0bf7d5c 100644
--- a/src/cobalt/browser/memory_settings/calculations.cc
+++ b/src/cobalt/browser/memory_settings/calculations.cc
@@ -182,16 +182,6 @@
   return std::max<int64_t>(output, kMinSkiaCacheSize);
 }
 
-int64_t CalculateMiscCobaltGpuSize(const math::Size& ui_resolution) {
-  // LinearRemap defines a mapping function which will map the number
-  // of ui_resolution pixels to the misc memory of the GPU. This mapping
-  // is linear such that:
-  // 1080p (1920x1080) => maps to => 24MB
-  LinearRemap remap(0, 1920 * 1080, 0, 24 * 1024 * 1024);
-
-  return static_cast<int64_t>(remap.Map(ui_resolution.GetArea()));
-}
-
 }  // namespace memory_settings
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/calculations.h b/src/cobalt/browser/memory_settings/calculations.h
index d034fa1..0f4b035 100644
--- a/src/cobalt/browser/memory_settings/calculations.h
+++ b/src/cobalt/browser/memory_settings/calculations.h
@@ -63,10 +63,6 @@
 // to be 4MB @ 1080p and scales accordingly.
 int64_t CalculateSkiaCacheSize(const math::Size& ui_resolution);
 
-// Calculates the GPU usage of the app to un-accounted systems. Scales linearly
-// with ui_resolution.
-int64_t CalculateMiscCobaltGpuSize(const math::Size& ui_resolution);
-
 }  // namespace memory_settings
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/calculations_test.cc b/src/cobalt/browser/memory_settings/calculations_test.cc
index c19359a..53e67a2 100644
--- a/src/cobalt/browser/memory_settings/calculations_test.cc
+++ b/src/cobalt/browser/memory_settings/calculations_test.cc
@@ -177,11 +177,6 @@
             CalculateSoftwareSurfaceCacheSizeInBytes(ui_resolution));
 }
 
-TEST(MemoryCalculations, CalculateMiscCobaltGpuSize) {
-  math::Size ui_resolution = GetDimensions(k1080p);
-  EXPECT_EQ(24 * 1024 * 1024, CalculateMiscCobaltGpuSize(ui_resolution));
-}
-
 }  // namespace memory_settings
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/constrainer.cc b/src/cobalt/browser/memory_settings/constrainer.cc
deleted file mode 100644
index 5be827e..0000000
--- a/src/cobalt/browser/memory_settings/constrainer.cc
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright 2017 The Cobalt Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/browser/memory_settings/constrainer.h"
-
-#include <algorithm>
-#include <iterator>
-#include <vector>
-
-#include "base/logging.h"
-#include "cobalt/browser/memory_settings/memory_settings.h"
-#include "cobalt/browser/memory_settings/pretty_print.h"
-#include "starboard/configuration.h"
-
-namespace cobalt {
-namespace browser {
-namespace memory_settings {
-namespace {
-
-// Any memory setting that matches the MemoryType and is an AutoSet type is
-// passed to the output.
-std::vector<MemorySetting*> FilterSettings(
-    MemorySetting::MemoryType memory_type,
-    const std::vector<MemorySetting*>& settings) {
-  std::vector<MemorySetting*> output;
-  for (size_t i = 0; i < settings.size(); ++i) {
-    MemorySetting* setting = settings[i];
-    if (setting->memory_type() == memory_type) {
-      output.push_back(setting);
-    }
-  }
-  return output;
-}
-
-// Sums the memory consumption at the given global_constraining_value. The
-// settings variable is read buy not modified (despite the non-const
-// declaration). If constrained_values_out is non-null, then the computed
-// constraining values are stored in this vector.
-// Returns: The amount of memory in bytes that the memory settings vector will
-//          consume at the given global_constraining_factor.
-int64_t SumMemoryConsumption(double global_constraining_factor,
-                             const std::vector<MemorySetting*>& memory_settings,
-                             std::vector<double>* constrained_values_out) {
-  if (constrained_values_out) {
-    constrained_values_out->clear();
-  }
-
-  int64_t sum = 0;
-
-  // Iterates through the MemorySettings and determines the total memory
-  // consumption at the current global_constraining_value.
-  for (size_t i = 0; i < memory_settings.size(); ++i) {
-    const MemorySetting* setting = memory_settings[i];
-
-    const int64_t requested_consumption = setting->MemoryConsumption();
-    double local_constraining_value = 1.0;
-    if (setting->source_type() == MemorySetting::kAutoSet) {
-      local_constraining_value =
-          setting->ComputeAbsoluteMemoryScale(global_constraining_factor);
-    }
-
-    const int64_t new_consumption_value =
-        static_cast<int64_t>(local_constraining_value * requested_consumption);
-
-    if (constrained_values_out) {
-      constrained_values_out->push_back(local_constraining_value);
-    }
-
-    sum += new_consumption_value;
-  }
-
-  return sum;
-}
-
-void CheckMemoryChange(const std::string& setting_name,
-                       int64_t old_memory_consumption,
-                       int64_t new_memory_consumption,
-                       double constraining_value) {
-  if (old_memory_consumption == 0) {
-    // If the system is already using no memory, then it can't use any less.
-    return;
-  }
-
-  // Represents 1% allowed difference.
-  static const double kErrorThreshold = 0.01;
-
-  const double actual_constraining_value =
-      static_cast<double>(new_memory_consumption) /
-      static_cast<double>(old_memory_consumption);
-
-  double diff = constraining_value - actual_constraining_value;
-  if (diff < 0.0) {
-    diff = -diff;
-  }
-
-  DCHECK_LE(diff, kErrorThreshold)
-      << "MemorySetting " << setting_name << " did not change it's memory by "
-      << "the expected value.\n"
-      << "  Expected Change: " << (constraining_value * 100) << "%\n"
-      << "  Actual Change: " << (diff * 100) << "%\n"
-      << "  Original memory consumption (bytes): " << old_memory_consumption
-      << "  New memory consumption (bytes):      " << new_memory_consumption
-      << "\n";
-}
-
-void ConstrainToMemoryLimit(int64_t memory_limit,
-                            std::vector<MemorySetting*>* memory_settings) {
-  if (memory_settings->empty()) {
-    return;
-  }
-
-  // If the memory consumed is already under the memory limit then no further
-  // work needs to be done.
-  if (SumMemoryConsumption(1.0, *memory_settings, NULL) <= memory_limit) {
-    return;
-  }
-
-  // Iterate by small steps the constraining value from 1.0 (100%) toward
-  // 0.0.
-  static const double kStep = 0.0001;  // .01% change per iteration.
-  std::vector<double> constrained_sizes;
-  // 1-1 mapping.
-  constrained_sizes.resize(memory_settings->size());
-  for (double global_constraining_factor = 1.0;
-       global_constraining_factor >= 0.0; global_constraining_factor -= kStep) {
-    global_constraining_factor = std::max(0.0, global_constraining_factor);
-    const int64_t new_global_memory_consumption = SumMemoryConsumption(
-        global_constraining_factor, *memory_settings, &constrained_sizes);
-
-    const bool finished = (global_constraining_factor == 0.0) ||
-                          (new_global_memory_consumption <= memory_limit);
-
-    if (finished) {
-      break;
-    }
-  }
-  DCHECK_EQ(memory_settings->size(), constrained_sizes.size());
-  for (size_t i = 0; i < memory_settings->size(); ++i) {
-    const double local_constraining_factor = constrained_sizes[i];
-    MemorySetting* setting = memory_settings->at(i);
-    if (local_constraining_factor != 1.0) {
-      const int64_t old_memory_consumption = setting->MemoryConsumption();
-      DCHECK_EQ(setting->source_type(), MemorySetting::kAutoSet);
-      setting->ScaleMemory(local_constraining_factor);
-      const int64_t new_memory_consumption = setting->MemoryConsumption();
-
-      // If the memory doesn't actually change as predicted by the constraining
-      // value then this check will catch it here.
-      CheckMemoryChange(setting->name(), old_memory_consumption,
-                        new_memory_consumption, local_constraining_factor);
-    }
-  }
-}
-
-void ConstrainMemoryType(MemorySetting::MemoryType memory_type,
-                         int64_t max_memory,
-                         std::vector<MemorySetting*>* memory_settings,
-                         std::vector<std::string>* error_msgs) {
-  if (max_memory == 0) {
-    return;
-  }
-  DCHECK_NE(MemorySetting::kNotApplicable, memory_type);
-  const char* memory_type_str = "UNKNOWN";
-  switch (memory_type) {
-    case MemorySetting::kCPU: {
-      memory_type_str = "CPU";
-      break;
-    }
-    case MemorySetting::kGPU: {
-      memory_type_str = "GPU";
-      break;
-    }
-    case MemorySetting::kNotApplicable: {
-      memory_type_str = "ERROR";
-      break;
-    }
-  }
-
-  std::vector<MemorySetting*> filtered_settings =
-      FilterSettings(memory_type, *memory_settings);
-
-  const int64_t current_consumption =
-      SumMemoryConsumption(memory_type, *memory_settings);
-
-  if (current_consumption < max_memory) {
-    return;
-  }
-
-  ConstrainToMemoryLimit(max_memory, &filtered_settings);
-
-  const int64_t new_memory_size =
-      SumMemoryConsumption(memory_type, *memory_settings);
-
-  if (new_memory_size > max_memory) {
-    std::stringstream ss;
-    ss << "WARNING - ATTEMPTED TO CONSTRAIN " << memory_type_str
-       << " MEMORY FROM " << ToMegabyteString(current_consumption, 2) << " TO "
-       << ToMegabyteString(max_memory, 2) << ".\nBUT STOPPED"
-       << " AT " << ToMegabyteString(new_memory_size, 2) << " because"
-       << " there was nothing left to\n"
-       << "constrain (settings refused to reduce any more memory). Try\n"
-       << "setting more memory setting(s) to -1 to allow autoset.\n"
-       << "Example: --image_cache_size_in_bytes=-1";
-    error_msgs->push_back(ss.str());
-  }
-}
-
-}  // namespace.
-
-void ConstrainToMemoryLimits(int64_t max_cpu_memory, int64_t max_gpu_memory,
-                             std::vector<MemorySetting*>* memory_settings,
-                             std::vector<std::string>* error_msgs) {
-  // Constrain cpu memory.
-  ConstrainMemoryType(MemorySetting::kCPU, max_cpu_memory, memory_settings,
-                      error_msgs);
-  // Constrain gpu memory.
-  ConstrainMemoryType(MemorySetting::kGPU, max_gpu_memory, memory_settings,
-                      error_msgs);
-}
-
-}  // namespace memory_settings
-}  // namespace browser
-}  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/constrainer.h b/src/cobalt/browser/memory_settings/constrainer.h
deleted file mode 100644
index 97d4e04..0000000
--- a/src/cobalt/browser/memory_settings/constrainer.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2017 The Cobalt Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_BROWSER_MEMORY_SETTINGS_CONSTRAINER_H_
-#define COBALT_BROWSER_MEMORY_SETTINGS_CONSTRAINER_H_
-
-#include <string>
-#include <vector>
-
-#include "base/optional.h"
-#include "cobalt/browser/memory_settings/memory_settings.h"
-#include "starboard/types.h"
-
-namespace cobalt {
-namespace browser {
-namespace memory_settings {
-
-// Constrains the memory in the memory_settings vector so that the target is
-// such that the sum of memory consumption is below max_cpu_memory and
-// max_gpu_memory.
-//
-// How the memory settings will reduce their memory usage is dependent on
-// the ConstrainerFunction they contain. It's possible that the memory
-// settings won't be able to match the target memory.
-//
-// The output variable error_msgs will be populated with any error messages
-// that result from this function call.
-void ConstrainToMemoryLimits(int64_t max_cpu_memory, int64_t max_gpu_memory,
-                             std::vector<MemorySetting*>* memory_settings,
-                             std::vector<std::string>* error_msgs);
-}  // namespace memory_settings
-}  // namespace browser
-}  // namespace cobalt
-
-#endif  // COBALT_BROWSER_MEMORY_SETTINGS_CONSTRAINER_H_
diff --git a/src/cobalt/browser/memory_settings/constrainer_test.cc b/src/cobalt/browser/memory_settings/constrainer_test.cc
deleted file mode 100644
index 1047d10..0000000
--- a/src/cobalt/browser/memory_settings/constrainer_test.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2017 The Cobalt Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cobalt/browser/memory_settings/constrainer.h"
-#include "base/bind.h"
-#include "base/callback.h"
-#include "cobalt/browser/memory_settings/memory_settings.h"
-#include "cobalt/browser/memory_settings/test_common.h"
-#include "starboard/configuration.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cobalt {
-namespace browser {
-namespace memory_settings {
-namespace {
-const int64_t kOneMegabyte = 1 * 1024 * 1024;
-const int64_t kTwoMegabytes = 2 * 1024 * 1024;
-const int64_t kFiveMegabytes = 5 * 1024 * 1024;
-const int64_t kNoGpuMemory = 0;
-
-ScalingFunction MakeLinearConstrainer() {
-  // Linearly scale, but clamp between 0 and 1.
-  return MakeLinearMemoryScaler(0.0, 1.0);
-}
-
-}  // namespace.
-
-// Tests the expectation that given one IntSetting which occupies 2MB of
-// the available memory, and max_cpu_setting of 1MB, that
-// ConstrainToMemoryLimits() function will reduce the memory setting
-// down 1MB.
-TEST(ConstrainToMemoryLimits, ConstrainCpuMemoryWithOneSetting) {
-  IntSetting int_setting("dummy_cpu_setting");
-  int_setting.set_memory_type(MemorySetting::kCPU);
-  int_setting.set_value(MemorySetting::kAutoSet, kTwoMegabytes);
-
-  ScalingFunction constrainer(MakeLinearConstrainer());
-
-  int_setting.set_memory_scaling_function(constrainer);
-
-  std::vector<MemorySetting*> settings;
-  settings.push_back(&int_setting);
-
-  std::vector<std::string> error_msgs;
-
-  // Will reduce the memory usage of the IntSetting.
-  ConstrainToMemoryLimits(kOneMegabyte, kNoGpuMemory, &settings, &error_msgs);
-  EXPECT_EQ(kOneMegabyte, int_setting.MemoryConsumption());
-  EXPECT_TRUE(error_msgs.empty());
-}
-
-// Tests the expectation that given two IntSettings, one that was AutoSet and
-// one that was set by the command line and one set by the build system, that
-// only the AutoSet IntSetting will be constrained.
-TEST(ConstrainToMemoryLimits, ConstrainerIgnoresNonAutosetVariables) {
-  IntSetting int_setting_autoset("autoset_cpu_setting");
-  int_setting_autoset.set_memory_type(MemorySetting::kCPU);
-  int_setting_autoset.set_value(MemorySetting::kAutoSet, kTwoMegabytes);
-  int_setting_autoset.set_memory_scaling_function(MakeLinearConstrainer());
-
-  IntSetting int_setting_cmdline("cmdline_cpu_setting");
-  int_setting_cmdline.set_memory_type(MemorySetting::kCPU);
-  int_setting_cmdline.set_value(MemorySetting::kCmdLine, kTwoMegabytes);
-  int_setting_cmdline.set_memory_scaling_function(MakeLinearConstrainer());
-
-  IntSetting int_setting_builtin("builtin_cpu_setting");
-  int_setting_builtin.set_memory_type(MemorySetting::kCPU);
-  int_setting_builtin.set_value(MemorySetting::kBuildSetting, kTwoMegabytes);
-  int_setting_builtin.set_memory_scaling_function(MakeLinearConstrainer());
-
-  std::vector<MemorySetting*> settings;
-  settings.push_back(&int_setting_autoset);
-  settings.push_back(&int_setting_cmdline);
-  settings.push_back(&int_setting_builtin);
-
-  std::vector<std::string> error_msgs;
-
-  // Right now we need to shave off 1MB, but this can only come from the
-  // MemorySetting that was autoset.
-  ConstrainToMemoryLimits(kFiveMegabytes, kNoGpuMemory, &settings, &error_msgs);
-
-  EXPECT_EQ(kOneMegabyte, int_setting_autoset.MemoryConsumption());
-  EXPECT_EQ(kTwoMegabytes, int_setting_cmdline.MemoryConsumption());
-  EXPECT_EQ(kTwoMegabytes, int_setting_builtin.MemoryConsumption());
-
-  EXPECT_TRUE(error_msgs.empty());
-}
-
-}  // namespace memory_settings
-}  // namespace browser
-}  // namespace cobalt
diff --git a/src/cobalt/browser/memory_settings/pretty_print.h b/src/cobalt/browser/memory_settings/pretty_print.h
index 868330c..2a58731 100644
--- a/src/cobalt/browser/memory_settings/pretty_print.h
+++ b/src/cobalt/browser/memory_settings/pretty_print.h
@@ -27,28 +27,22 @@
 namespace browser {
 namespace memory_settings {
 
+// clang-format off
+
 // Generates a table, ie:
-//
-//   NAME                                   VALUE                   TYPE   SOURCE
-//   _______________________________________________________________________________
-//  |                                      |             |         |      |         |
-//  | image_cache_size_in_bytes            |    33554432 | 32.0 MB |  GPU | AutoSet |
-//  |______________________________________|_____________|_________|______|_________|
-//  |                                      |             |         |      |         |
-//  | javascript_gc_threshold_in_bytes     |     8388608 |  8.0 MB |  CPU |   Build |
-//  |______________________________________|_____________|_________|______|_________|
-//  |                                      |             |         |      |         |
-//  | misc_cobalt_engine_size_in_bytes     |    33554432 | 32.0 MB |  CPU |   Build |
-//  |______________________________________|_____________|_________|______|_________|
-//  |                                      |             |         |      |         |
-//  | skia_atlas_texture_dimensions        | 4096x8192x2 | 64.0 MB |  GPU |   Build |
-//  |______________________________________|_____________|_________|______|_________|
-//  |                                      |             |         |      |         |
-//  | skia_cache_size_in_bytes             |     4194304 |  4.0 MB |  GPU |   Build |
-//  |______________________________________|_____________|_________|______|_________|
-//  |                                      |             |         |      |         |
-//  | software_surface_cache_size_in_bytes |         N/A |     N/A |  N/A |     N/A |
-//  |______________________________________|_____________|_________|______|_________|
+//  _______________________________________________________________________________
+// |SETTING NAME                          |VALUE        |         |TYPE  |SOURCE   |
+// | encoded_image_cache_size_in_bytes    |     1048576 |  1.0 MB |  CPU |   Build |
+// | image_cache_size_in_bytes            |    10485760 | 10.0 MB |  GPU | AutoSet |
+// | offscreen_target_cache_size_in_bytes |     2097152 |  2.0 MB |  GPU | AutoSet |
+// | remote_typeface_cache_size_in_bytes  |     4194304 |  4.0 MB |  CPU |   Build |
+// | skia_atlas_texture_dimensions        | 2048x2048x2 |  8.0 MB |  GPU | AutoSet |
+// | skia_cache_size_in_bytes             |     4194304 |  4.0 MB |  GPU |   Build |
+// | software_surface_cache_size_in_bytes |         N/A |     N/A |  N/A |     N/A |
+// |______________________________________|_____________|_________|______|_________|
+
+// clang-format on
+
 std::string GeneratePrettyPrintTable(
     bool use_color_ascii,
     const std::vector<const MemorySetting*>& memory_settings);
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc
index 9ff797a..e2743e9 100644
--- a/src/cobalt/browser/switches.cc
+++ b/src/cobalt/browser/switches.cc
@@ -337,11 +337,6 @@
     " and the number of locations can be overwritten by specifying it as the "
     " value of the command line parameter, like '--qr_code_overlay=6'.";
 
-const char kReduceGpuMemoryBy[] = "reduce_gpu_memory_by";
-const char kReduceGpuMemoryByHelp[] =
-    "Reduces the gpu-memory of the system by this amount. This causes AutoMem "
-    "to reduce the runtime size of the GPU-Memory caches.";
-
 const char kRemoteTypefaceCacheSizeInBytes[] =
     "remote_typeface_cache_size_in_bytes";
 const char kRemoteTypefaceCacheSizeInBytesHelp[] =
@@ -493,7 +488,6 @@
         {kOmitDeviceAuthenticationQueryParameters,
          kOmitDeviceAuthenticationQueryParametersHelp},
         {kProxy, kProxyHelp}, {kQrCodeOverlay, kQrCodeOverlayHelp},
-        {kReduceGpuMemoryBy, kReduceGpuMemoryByHelp},
         {kRemoteTypefaceCacheSizeInBytes, kRemoteTypefaceCacheSizeInBytesHelp},
         {kRetainRemoteTypefaceCacheDuringSuspend,
          kRetainRemoteTypefaceCacheDuringSuspendHelp},
diff --git a/src/cobalt/browser/switches.h b/src/cobalt/browser/switches.h
index bd69530..50e3b4c 100644
--- a/src/cobalt/browser/switches.h
+++ b/src/cobalt/browser/switches.h
@@ -133,8 +133,6 @@
 extern const char kProxyHelp[];
 extern const char kQrCodeOverlay[];
 extern const char kQrCodeOverlayHelp[];
-extern const char kReduceGpuMemoryBy[];
-extern const char kReduceGpuMemoryByHelp[];
 extern const char kRemoteTypefaceCacheSizeInBytes[];
 extern const char kRemoteTypefaceCacheSizeInBytesHelp[];
 extern const char kRetainRemoteTypefaceCacheDuringSuspend[];
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc
index ef84f3b..06600b8 100644
--- a/src/cobalt/browser/web_module.cc
+++ b/src/cobalt/browser/web_module.cc
@@ -217,7 +217,7 @@
 #endif  // defined(ENABLE_DEBUGGER)
 
   void SetSize(cssom::ViewportSize viewport_size);
-  void SetCamera3D(const scoped_refptr<input::Camera3D>& camera_3d);
+  void UpdateCamera3D(const scoped_refptr<input::Camera3D>& camera_3d);
   void SetMediaModule(media::MediaModule* media_module);
   void SetImageCacheCapacity(int64_t bytes);
   void SetRemoteTypefaceCacheCapacity(int64_t bytes);
@@ -1123,9 +1123,9 @@
   window_->SetSize(viewport_size);
 }
 
-void WebModule::Impl::SetCamera3D(
+void WebModule::Impl::UpdateCamera3D(
     const scoped_refptr<input::Camera3D>& camera_3d) {
-  window_->SetCamera3D(camera_3d);
+  window_->UpdateCamera3D(camera_3d);
 }
 
 void WebModule::Impl::SetMediaModule(media::MediaModule* media_module) {
@@ -1666,9 +1666,10 @@
                             base::Unretained(impl_.get()), viewport_size));
 }
 
-void WebModule::SetCamera3D(const scoped_refptr<input::Camera3D>& camera_3d) {
+void WebModule::UpdateCamera3D(
+    const scoped_refptr<input::Camera3D>& camera_3d) {
   message_loop()->task_runner()->PostTask(
-      FROM_HERE, base::Bind(&WebModule::Impl::SetCamera3D,
+      FROM_HERE, base::Bind(&WebModule::Impl::UpdateCamera3D,
                             base::Unretained(impl_.get()), camera_3d));
 }
 
diff --git a/src/cobalt/browser/web_module.h b/src/cobalt/browser/web_module.h
index 16c830d..20b39bb 100644
--- a/src/cobalt/browser/web_module.h
+++ b/src/cobalt/browser/web_module.h
@@ -370,7 +370,7 @@
   // from the current parameters.
   void SetSize(const cssom::ViewportSize& viewport_size);
 
-  void SetCamera3D(const scoped_refptr<input::Camera3D>& camera_3d);
+  void UpdateCamera3D(const scoped_refptr<input::Camera3D>& camera_3d);
   void SetMediaModule(media::MediaModule* media_module);
   void SetImageCacheCapacity(int64_t bytes);
   void SetRemoteTypefaceCacheCapacity(int64_t bytes);
@@ -412,6 +412,7 @@
   void SetApplicationStartOrPreloadTimestamp(bool is_preload,
                                              SbTimeMonotonic timestamp);
   void SetDeepLinkTimestamp(SbTimeMonotonic timestamp);
+
  private:
   // Data required to construct a WebModule, initialized in the constructor and
   // passed to |Initialize|.
diff --git a/src/cobalt/build/.gitignore b/src/cobalt/build/.gitignore
new file mode 100644
index 0000000..405fd00
--- /dev/null
+++ b/src/cobalt/build/.gitignore
@@ -0,0 +1 @@
+build.id
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
deleted file mode 100644
index 6409624..0000000
--- a/src/cobalt/build/build.id
+++ /dev/null
@@ -1 +0,0 @@
-304711
\ No newline at end of file
diff --git a/src/cobalt/build/sync_to_build_id.py b/src/cobalt/build/sync_to_build_id.py
index d873a00..f2fb1f4 100755
--- a/src/cobalt/build/sync_to_build_id.py
+++ b/src/cobalt/build/sync_to_build_id.py
@@ -12,7 +12,6 @@
 import argparse
 import json
 import os
-import platform
 import shutil
 import subprocess
 import sys
@@ -66,14 +65,13 @@
 
   """
   popen_args = ["git"] + gitargs
-  p = subprocess.Popen(popen_args, stdout=subprocess.PIPE, **kwargs)
-  output = p.stdout.read().splitlines()
-  return p.wait(), output
+  with subprocess.Popen(popen_args, stdout=subprocess.PIPE, **kwargs) as p:
+    output = p.stdout.read().splitlines()
+    return p.wait(), output
 
 
 def main():
-  dev_null_filename = "nul" if platform.system() == "Windows" else "/dev/null"
-  dev_null = open(dev_null_filename, "w")
+  dev_null = open(os.devnull, "w")  # pylint: disable=consider-using-with
   arg_parser = argparse.ArgumentParser(
       description="Syncs to a given Cobalt build id")
   arg_parser.add_argument("buildid", nargs=1)
@@ -97,7 +95,7 @@
   hashes = json.loads(outer_json["deps"])
   git_root = os.getcwd()
 
-  for relpath, rep_hash in hashes.iteritems():
+  for relpath, rep_hash in hashes.items():
     path = os.path.normpath(os.path.join(git_root, relpath))
     if not os.path.exists(path):
       # No warning in this case, we will attempt to clone the repository in
@@ -120,17 +118,21 @@
 
     (requested_repo, _) = rep_hash.split("@")
     remote_url = _RunGitCommand(["config", "--get", "remote.origin.url"],
-                                cwd=path)[0] + ".git"
+                                cwd=path)[0]
+    if requested_repo.endswith(".git"):
+      remote_url += ".git"
+
     if remote_url != requested_repo:
-      if args.force:
+      if args.force and path != git_root:
         shutil.rmtree(path)
       else:
         print(("{0} exists but does not point to the requested repo for that "
                "path, {1}. Either replace that directory manually or run this "
-               "script with --force.").format(path, requested_repo))
+               "script with --force. --force will not try to remove the top "
+               "level repository.").format(path, requested_repo))
         return 1
 
-  for relpath, rep_hash in hashes.iteritems():
+  for relpath, rep_hash in hashes.items():
     path = os.path.normpath(os.path.join(git_root, relpath))
 
     # repo_hash has a repo path prefix like this:
diff --git a/src/cobalt/configuration/configuration.h b/src/cobalt/configuration/configuration.h
index 6913ea1..0acaec1 100644
--- a/src/cobalt/configuration/configuration.h
+++ b/src/cobalt/configuration/configuration.h
@@ -53,7 +53,6 @@
   float CobaltImageCacheCapacityMultiplierWhenPlayingVideo();
   int CobaltSkiaGlyphAtlasWidth();
   int CobaltSkiaGlyphAtlasHeight();
-  int CobaltJsGarbageCollectionThresholdInBytes();
   int CobaltReduceCpuMemoryBy();
   int CobaltReduceGpuMemoryBy();
   bool CobaltGcZeal();
diff --git a/src/cobalt/css_parser/.gitignore b/src/cobalt/css_parser/.gitignore
new file mode 100644
index 0000000..74b59e4
--- /dev/null
+++ b/src/cobalt/css_parser/.gitignore
@@ -0,0 +1 @@
+~*
diff --git a/src/cobalt/debug/remote/devtools/copy_devtools_modules.rsp b/src/cobalt/debug/remote/devtools/copy_devtools_modules.rsp
new file mode 100644
index 0000000..39ad8b2
--- /dev/null
+++ b/src/cobalt/debug/remote/devtools/copy_devtools_modules.rsp
@@ -0,0 +1,476 @@
+front_end/network/network.js
+front_end/network/SignedExchangeInfoView.js
+front_end/network/ResourceWebSocketFrameView.js
+front_end/network/RequestTimingView.js
+front_end/network/RequestResponseView.js
+front_end/network/RequestPreviewView.js
+front_end/network/RequestInitiatorView.js
+front_end/network/RequestHeadersView.js
+front_end/network/RequestHTMLView.js
+front_end/network/RequestCookiesView.js
+front_end/network/NetworkWaterfallColumn.js
+front_end/network/NetworkTimeCalculator.js
+front_end/network/NetworkSearchScope.js
+front_end/network/NetworkPanel.js
+front_end/network/NetworkOverview.js
+front_end/network/NetworkManageCustomHeadersView.js
+front_end/network/NetworkLogViewColumns.js
+front_end/network/NetworkLogView.js
+front_end/network/NetworkItemView.js
+front_end/network/NetworkFrameGrouper.js
+front_end/network/NetworkDataGridNode.js
+front_end/network/NetworkConfigView.js
+front_end/network/HARWriter.js
+front_end/network/EventSourceMessagesView.js
+front_end/network/BlockedURLsPane.js
+front_end/network/BinaryResourceView.js
+front_end/test_runner/test_runner.js
+front_end/test_runner/TestRunner.js
+front_end/emulation/emulation.js
+front_end/emulation/SensorsView.js
+front_end/emulation/MediaQueryInspector.js
+front_end/emulation/InspectedPagePlaceholder.js
+front_end/emulation/GeolocationsSettingsTab.js
+front_end/emulation/EmulatedDevices.js
+front_end/emulation/DevicesSettingsTab.js
+front_end/emulation/DeviceModeWrapper.js
+front_end/emulation/DeviceModeView.js
+front_end/emulation/DeviceModeToolbar.js
+front_end/emulation/DeviceModeModel.js
+front_end/emulation/AdvancedApp.js
+front_end/inspector_main/inspector_main.js
+front_end/inspector_main/RenderingOptions.js
+front_end/inspector_main/InspectorMain.js
+front_end/js_main/js_main.js
+front_end/js_main/JsMain.js
+front_end/search/search.js
+front_end/search/SearchView.js
+front_end/search/SearchResultsPane.js
+front_end/search/SearchConfig.js
+front_end/screencast/screencast.js
+front_end/screencast/ScreencastView.js
+front_end/screencast/ScreencastApp.js
+front_end/screencast/InputModel.js
+front_end/performance_monitor/performance_monitor.js
+front_end/performance_monitor/PerformanceMonitor.js
+front_end/main/main.js
+front_end/main/SimpleApp.js
+front_end/main/MainImpl.js
+front_end/main/ExecutionContextSelector.js
+front_end/snippets/snippets.js
+front_end/snippets/SnippetsQuickOpen.js
+front_end/snippets/ScriptSnippetFileSystem.js
+front_end/settings/settings.js
+front_end/settings/SettingsScreen.js
+front_end/settings/FrameworkBlackboxSettingsTab.js
+front_end/security/security.js
+front_end/security/SecurityPanel.js
+front_end/security/SecurityModel.js
+front_end/javascript_metadata/javascript_metadata.js
+front_end/javascript_metadata/NativeFunctions.js
+front_end/javascript_metadata/JavaScriptMetadata.js
+front_end/har_importer/har_importer.js
+front_end/har_importer/HARImporter.js
+front_end/har_importer/HARFormat.js
+front_end/browser_debugger/browser_debugger.js
+front_end/browser_debugger/XHRBreakpointsSidebarPane.js
+front_end/browser_debugger/ObjectEventListenersSidebarPane.js
+front_end/browser_debugger/EventListenerBreakpointsSidebarPane.js
+front_end/browser_debugger/DOMBreakpointsSidebarPane.js
+front_end/layer_viewer/layer_viewer.js
+front_end/layer_viewer/TransformController.js
+front_end/layer_viewer/PaintProfilerView.js
+front_end/layer_viewer/Layers3DView.js
+front_end/layer_viewer/LayerViewHost.js
+front_end/layer_viewer/LayerTreeOutline.js
+front_end/layer_viewer/LayerDetailsView.js
+front_end/cm_web_modes/cm_web_modes.js
+front_end/cm_web_modes/cm_web_modes_cm.js
+front_end/cm_web_modes/cm_web_modes_headless.js
+front_end/cm_web_modes/css.js
+front_end/cm_web_modes/javascript.js
+front_end/cm_web_modes/xml.js
+front_end/cm_web_modes/htmlmixed.js
+front_end/cm_web_modes/htmlembedded.js
+front_end/text_editor/text_editor.js
+front_end/text_editor/TextEditorAutocompleteController.js
+front_end/text_editor/CodeMirrorUtils.js
+front_end/text_editor/CodeMirrorTextEditor.js
+front_end/quick_open/quick_open.js
+front_end/quick_open/QuickOpen.js
+front_end/quick_open/HelpQuickOpen.js
+front_end/quick_open/FilteredListWidget.js
+front_end/quick_open/CommandMenu.js
+front_end/elements/elements.js
+front_end/elements/elements-legacy.js
+front_end/elements/StylesSidebarPane.js
+front_end/elements/StylePropertyTreeElement.js
+front_end/elements/StylePropertyHighlighter.js
+front_end/elements/PropertiesWidget.js
+front_end/elements/PlatformFontsWidget.js
+front_end/elements/NodeStackTraceWidget.js
+front_end/elements/MetricsSidebarPane.js
+front_end/elements/MarkerDecorator.js
+front_end/elements/InspectElementModeController.js
+front_end/elements/EventListenersWidget.js
+front_end/elements/ElementsTreeOutline.js
+front_end/elements/ElementsTreeElement.js
+front_end/elements/ElementsTreeElementHighlighter.js
+front_end/elements/ElementStatePaneWidget.js
+front_end/elements/ElementsSidebarPane.js
+front_end/elements/ElementsPanel.js
+front_end/elements/ElementsBreadcrumbs.js
+front_end/elements/DOMPath.js
+front_end/elements/DOMLinkifier.js
+front_end/elements/ComputedStyleWidget.js
+front_end/elements/ComputedStyleModel.js
+front_end/elements/ColorSwatchPopoverIcon.js
+front_end/elements/ClassesPaneWidget.js
+front_end/timeline_model/timeline_model.js
+front_end/timeline_model/TracingLayerTree.js
+front_end/timeline_model/TimelineProfileTree.js
+front_end/timeline_model/TimelineModel.js
+front_end/timeline_model/TimelineModelFilter.js
+front_end/timeline_model/TimelineJSProfile.js
+front_end/timeline_model/TimelineIRModel.js
+front_end/timeline_model/TimelineFrameModel.js
+front_end/help/help.js
+front_end/help/ReleaseNoteView.js
+front_end/help/ReleaseNoteText.js
+front_end/help/HelpImpl.js
+front_end/workspace_diff/workspace_diff.js
+front_end/workspace_diff/WorkspaceDiff.js
+front_end/mobile_throttling/mobile_throttling.js
+front_end/mobile_throttling/ThrottlingSettingsTab.js
+front_end/mobile_throttling/ThrottlingPresets.js
+front_end/mobile_throttling/ThrottlingManager.js
+front_end/mobile_throttling/NetworkThrottlingSelector.js
+front_end/mobile_throttling/NetworkPanelIndicator.js
+front_end/mobile_throttling/MobileThrottlingSelector.js
+front_end/event_listeners/event_listeners.js
+front_end/event_listeners/EventListenersView.js
+front_end/event_listeners/EventListenersUtils.js
+front_end/object_ui/object_ui.js
+front_end/object_ui/RemoteObjectPreviewFormatter.js
+front_end/object_ui/ObjectPropertiesSection.js
+front_end/object_ui/ObjectPopoverHelper.js
+front_end/object_ui/JavaScriptREPL.js
+front_end/object_ui/JavaScriptAutocomplete.js
+front_end/object_ui/CustomPreviewComponent.js
+front_end/cookie_table/cookie_table.js
+front_end/cookie_table/CookiesTable.js
+front_end/cm_modes/cm_modes.js
+front_end/cm_modes/DefaultCodeMirrorMimeMode.js
+front_end/cm_modes/clike.js
+front_end/cm_modes/coffeescript.js
+front_end/cm_modes/php.js
+front_end/cm_modes/python.js
+front_end/cm_modes/shell.js
+front_end/cm_modes/livescript.js
+front_end/cm_modes/markdown.js
+front_end/cm_modes/clojure.js
+front_end/cm_modes/jsx.js
+front_end/css_overview/css_overview.js
+front_end/css_overview/CSSOverviewUnusedDeclarations.js
+front_end/css_overview/CSSOverviewStartView.js
+front_end/css_overview/CSSOverviewSidebarPanel.js
+front_end/css_overview/CSSOverviewProcessingView.js
+front_end/css_overview/CSSOverviewPanel.js
+front_end/css_overview/CSSOverviewModel.js
+front_end/css_overview/CSSOverviewController.js
+front_end/css_overview/CSSOverviewCompletedView.js
+front_end/console/console.js
+front_end/console/ConsoleContextSelector.js
+front_end/console/ConsoleFilter.js
+front_end/console/ConsoleSidebar.js
+front_end/console/ConsolePanel.js
+front_end/console/ConsolePinPane.js
+front_end/console/ConsolePrompt.js
+front_end/console/ConsoleView.js
+front_end/console/ConsoleViewMessage.js
+front_end/console/ConsoleViewport.js
+front_end/source_frame/source_frame.js
+front_end/source_frame/XMLView.js
+front_end/source_frame/SourcesTextEditor.js
+front_end/source_frame/SourceFrame.js
+front_end/source_frame/source_frame.js
+front_end/source_frame/SourceCodeDiff.js
+front_end/source_frame/ResourceSourceFrame.js
+front_end/source_frame/PreviewFactory.js
+front_end/source_frame/JSONView.js
+front_end/source_frame/ImageView.js
+front_end/source_frame/FontView.js
+front_end/source_frame/BinaryResourceViewFactory.js
+front_end/inline_editor/inline_editor.js
+front_end/inline_editor/SwatchPopoverHelper.js
+front_end/inline_editor/CSSShadowModel.js
+front_end/inline_editor/CSSShadowEditor.js
+front_end/inline_editor/ColorSwatch.js
+front_end/inline_editor/BezierUI.js
+front_end/inline_editor/BezierEditor.js
+front_end/diff/diff.js
+front_end/diff/diff_match_patch.js
+front_end/diff/DiffWrapper.js
+front_end/formatter/formatter.js
+front_end/formatter/ScriptFormatter.js
+front_end/formatter/FormatterWorkerPool.js
+front_end/color_picker/color_picker.js
+front_end/color_picker/Spectrum.js
+front_end/color_picker/ContrastOverlay.js
+front_end/color_picker/ContrastInfo.js
+front_end/color_picker/ContrastDetails.js
+front_end/cm/cm.js
+front_end/cm/active-line.js
+front_end/cm/brace-fold.js
+front_end/cm/closebrackets.js
+front_end/cm/codemirror.js
+front_end/cm/comment.js
+front_end/cm/foldcode.js
+front_end/cm/foldgutter.js
+front_end/cm/mark-selection.js
+front_end/cm/matchbrackets.js
+front_end/cm/multiplex.js
+front_end/cm/overlay.js
+front_end/formatter_worker.unbundled.js
+front_end/heap_snapshot_worker.unbundled.js
+front_end/heap_snapshot_model/heap_snapshot_model.js
+front_end/heap_snapshot_model/HeapSnapshotModel.js
+front_end/heap_snapshot_worker/heap_snapshot_worker.js
+front_end/heap_snapshot_worker/AllocationProfile.js
+front_end/heap_snapshot_worker/HeapSnapshot.js
+front_end/heap_snapshot_worker/HeapSnapshotLoader.js
+front_end/heap_snapshot_worker/HeapSnapshotWorker.js
+front_end/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.js
+front_end/text_utils/text_utils.js
+front_end/text_utils/TextUtils.js
+front_end/text_utils/TextRange.js
+front_end/text_utils/Text.js
+front_end/formatter_worker/formatter_worker.js
+front_end/formatter_worker/RelaxedJSONParser.js
+front_end/formatter_worker/JavaScriptOutline.js
+front_end/formatter_worker/JavaScriptFormatter.js
+front_end/formatter_worker/IdentityFormatter.js
+front_end/formatter_worker/HTMLFormatter.js
+front_end/formatter_worker/FormatterWorker.js
+front_end/formatter_worker/FormattedContentBuilder.js
+front_end/formatter_worker/ESTreeWalker.js
+front_end/formatter_worker/CSSRuleParser.js
+front_end/formatter_worker/CSSFormatter.js
+front_end/formatter_worker/AcornTokenizer.js
+front_end/cm_headless/cm_headless.js
+front_end/cm_headless/headlesscodemirror.js
+front_end/data_grid/data_grid.js
+front_end/data_grid/ViewportDataGrid.js
+front_end/data_grid/SortableDataGrid.js
+front_end/data_grid/ShowMoreDataGridNode.js
+front_end/data_grid/DataGrid.js
+front_end/protocol_monitor/protocol_monitor.js
+front_end/protocol_monitor/ProtocolMonitor.js
+front_end/console_counters/console_counters.js
+front_end/console_counters/WarningErrorCounter.js
+front_end/extensions/extensions.js
+front_end/extensions/ExtensionAPI.js
+front_end/extensions/ExtensionPanel.js
+front_end/extensions/ExtensionServer.js
+front_end/extensions/ExtensionTraceProvider.js
+front_end/extensions/ExtensionView.js
+front_end/browser_sdk/browser_sdk.js
+front_end/browser_sdk/LogManager.js
+front_end/persistence/persistence.js
+front_end/persistence/WorkspaceSettingsTab.js
+front_end/persistence/PlatformFileSystem.js
+front_end/persistence/PersistenceUtils.js
+front_end/persistence/PersistenceImpl.js
+front_end/persistence/PersistenceActions.js
+front_end/persistence/NetworkPersistenceManager.js
+front_end/persistence/IsolatedFileSystemManager.js
+front_end/persistence/IsolatedFileSystem.js
+front_end/persistence/FileSystemWorkspaceBinding.js
+front_end/persistence/EditFileSystemView.js
+front_end/persistence/Automapping.js
+front_end/components/components.js
+front_end/components/TargetDetachedDialog.js
+front_end/components/Reload.js
+front_end/components/Linkifier.js
+front_end/components/JSPresentationUtils.js
+front_end/components/ImagePreview.js
+front_end/components/DockController.js
+front_end/bindings/bindings.js
+front_end/bindings/TempFile.js
+front_end/bindings/StylesSourceMapping.js
+front_end/bindings/SASSSourceMapping.js
+front_end/bindings/ResourceUtils.js
+front_end/bindings/ResourceScriptMapping.js
+front_end/bindings/ResourceMapping.js
+front_end/bindings/PresentationConsoleMessageHelper.js
+front_end/bindings/NetworkProject.js
+front_end/bindings/LiveLocation.js
+front_end/bindings/FileUtils.js
+front_end/bindings/DefaultScriptMapping.js
+front_end/bindings/DebuggerWorkspaceBinding.js
+front_end/bindings/CSSWorkspaceBinding.js
+front_end/bindings/ContentProviderBasedProject.js
+front_end/bindings/CompilerScriptMapping.js
+front_end/bindings/BreakpointManager.js
+front_end/bindings/BlackboxManager.js
+front_end/workspace/workspace.js
+front_end/workspace/WorkspaceImpl.js
+front_end/workspace/UISourceCode.js
+front_end/workspace/FileManager.js
+front_end/services/services.js
+front_end/services/ServiceManager.js
+front_end/sdk/sdk.js
+front_end/sdk/TracingModel.js
+front_end/sdk/TracingManager.js
+front_end/sdk/TargetManager.js
+front_end/sdk/Target.js
+front_end/sdk/SourceMapManager.js
+front_end/sdk/SourceMap.js
+front_end/sdk/ServiceWorkerManager.js
+front_end/sdk/ServiceWorkerCacheModel.js
+front_end/sdk/ServerTiming.js
+front_end/sdk/SecurityOriginManager.js
+front_end/sdk/SDKModel.js
+front_end/sdk/Script.js
+front_end/sdk/ScreenCaptureModel.js
+front_end/sdk/RuntimeModel.js
+front_end/sdk/ResourceTreeModel.js
+front_end/sdk/Resource.js
+front_end/sdk/RemoteObject.js
+front_end/sdk/ProfileTreeModel.js
+front_end/sdk/IssuesModel.js
+front_end/sdk/PerformanceMetricsModel.js
+front_end/sdk/PaintProfiler.js
+front_end/sdk/OverlayModel.js
+front_end/sdk/NetworkRequest.js
+front_end/sdk/NetworkManager.js
+front_end/sdk/NetworkLog.js
+front_end/sdk/LogModel.js
+front_end/sdk/LayerTreeBase.js
+front_end/sdk/IsolateManager.js
+front_end/sdk/HeapProfilerModel.js
+front_end/sdk/HARLog.js
+front_end/sdk/FilmStripModel.js
+front_end/sdk/EmulationModel.js
+front_end/sdk/DOMModel.js
+front_end/sdk/DOMDebuggerModel.js
+front_end/sdk/DebuggerModel.js
+front_end/sdk/CSSStyleSheetHeader.js
+front_end/sdk/CSSStyleDeclaration.js
+front_end/sdk/CSSRule.js
+front_end/sdk/CSSProperty.js
+front_end/sdk/CSSModel.js
+front_end/sdk/CSSMetadata.js
+front_end/sdk/CSSMedia.js
+front_end/sdk/CSSMatchedStyles.js
+front_end/sdk/CPUProfilerModel.js
+front_end/sdk/CPUProfileDataModel.js
+front_end/sdk/CookieParser.js
+front_end/sdk/CookieModel.js
+front_end/sdk/CompilerSourceMappingContentProvider.js
+front_end/sdk/ConsoleModel.js
+front_end/sdk/Connections.js
+front_end/sdk/ChildTargetManager.js
+front_end/protocol/protocol.js
+front_end/protocol/NodeURL.js
+front_end/protocol/InspectorBackend.js
+front_end/host/host.js
+front_end/host/UserMetrics.js
+front_end/host/ResourceLoader.js
+front_end/host/Platform.js
+front_end/host/InspectorFrontendHost.js
+front_end/host/InspectorFrontendHostAPI.js
+front_end/dom_extension/DOMExtension.js
+front_end/dom_extension/dom_extension.js
+front_end/root.js
+front_end/Runtime.js
+front_end/platform/utilities.js
+front_end/platform/platform.js
+front_end/ui/ARIAUtils.js
+front_end/ui/ZoomManager.js
+front_end/ui/XWidget.js
+front_end/ui/XLink.js
+front_end/ui/XElement.js
+front_end/ui/Widget.js
+front_end/ui/View.js
+front_end/ui/ViewManager.js
+front_end/ui/UIUtils.js
+front_end/ui/ui.js
+front_end/ui/Treeoutline.js
+front_end/ui/Tooltip.js
+front_end/ui/Toolbar.js
+front_end/ui/ThrottledWidget.js
+front_end/ui/TextPrompt.js
+front_end/ui/TextEditor.js
+front_end/ui/TargetCrashedScreen.js
+front_end/ui/TabbedPane.js
+front_end/ui/SyntaxHighlighter.js
+front_end/ui/SuggestBox.js
+front_end/ui/SplitWidget.js
+front_end/ui/SoftDropDown.js
+front_end/ui/SoftContextMenu.js
+front_end/ui/ShortcutsScreen.js
+front_end/ui/ShortcutRegistry.js
+front_end/ui/SettingsUI.js
+front_end/ui/SegmentedButton.js
+front_end/ui/SearchableView.js
+front_end/ui/RootView.js
+front_end/ui/ResizerWidget.js
+front_end/ui/ReportView.js
+front_end/ui/RemoteDebuggingTerminatedScreen.js
+front_end/ui/ProgressIndicator.js
+front_end/ui/PopoverHelper.js
+front_end/ui/Panel.js
+front_end/ui/ListWidget.js
+front_end/ui/ListModel.js
+front_end/ui/ListControl.js
+front_end/ui/KeyboardShortcut.js
+front_end/ui/InspectorView.js
+front_end/ui/InplaceEditor.js
+front_end/ui/Infobar.js
+front_end/ui/Icon.js
+front_end/ui/HistoryInput.js
+front_end/ui/GlassPane.js
+front_end/ui/Geometry.js
+front_end/ui/Fragment.js
+front_end/ui/ForwardedInputEventHandler.js
+front_end/ui/FilterSuggestionBuilder.js
+front_end/ui/FilterBar.js
+front_end/ui/EmptyWidget.js
+front_end/ui/DropTarget.js
+front_end/ui/Dialog.js
+front_end/ui/ContextMenu.js
+front_end/ui/Context.js
+front_end/ui/ARIAUtils.js
+front_end/ui/ActionRegistry.js
+front_end/ui/Action.js
+front_end/ui/ActionDelegate.js
+front_end/ui/ContextFlavorListener.js
+front_end/root.js
+front_end/common/common.js
+front_end/common/common-legacy.js
+front_end/common/App.js
+front_end/common/AppProvider.js
+front_end/common/CharacterIdMap.js
+front_end/common/Color.js
+front_end/common/ContentProvider.js
+front_end/common/EventTarget.js
+front_end/common/JavaScriptMetaData.js
+front_end/common/Linkifier.js
+front_end/common/Object.js
+front_end/common/Console.js
+front_end/common/ParsedURL.js
+front_end/common/Progress.js
+front_end/common/QueryParamHandler.js
+front_end/common/ResourceType.js
+front_end/common/Revealer.js
+front_end/common/Runnable.js
+front_end/common/SegmentedRange.js
+front_end/common/Settings.js
+front_end/common/StaticContentProvider.js
+front_end/common/StringOutputStream.js
+front_end/common/TextDictionary.js
+front_end/common/Throttler.js
+front_end/common/Trie.js
+front_end/common/UIString.js
+front_end/common/Worker.js
diff --git a/src/cobalt/demos/content/media-element-demo/.gitignore b/src/cobalt/demos/content/media-element-demo/.gitignore
new file mode 100644
index 0000000..f06235c
--- /dev/null
+++ b/src/cobalt/demos/content/media-element-demo/.gitignore
@@ -0,0 +1,2 @@
+node_modules
+dist
diff --git a/src/cobalt/demos/content/mse-eme-conformance-tests/media/.gitignore b/src/cobalt/demos/content/mse-eme-conformance-tests/media/.gitignore
new file mode 100644
index 0000000..cc2ac4e
--- /dev/null
+++ b/src/cobalt/demos/content/mse-eme-conformance-tests/media/.gitignore
@@ -0,0 +1,3 @@
+# Ignore raw media files as they are not tracked inside git repository.  They
+# are synced via gclient hook "mse_eme_conformance_tests".
+*.mp4
diff --git a/src/cobalt/demos/content/performance-api-demo/performance-lifecycle-timing-demo.html b/src/cobalt/demos/content/performance-api-demo/performance-lifecycle-timing-demo.html
index 72e472f..b5e37ac 100644
--- a/src/cobalt/demos/content/performance-api-demo/performance-lifecycle-timing-demo.html
+++ b/src/cobalt/demos/content/performance-api-demo/performance-lifecycle-timing-demo.html
@@ -62,4 +62,4 @@
   </div>
 </body>
 
-</html>
\ No newline at end of file
+</html>
diff --git a/src/cobalt/demos/content/performance-api-demo/performance-resource-timing-demo.html b/src/cobalt/demos/content/performance-api-demo/performance-resource-timing-demo.html
index 930cc8c..3d07dac 100644
--- a/src/cobalt/demos/content/performance-api-demo/performance-resource-timing-demo.html
+++ b/src/cobalt/demos/content/performance-api-demo/performance-resource-timing-demo.html
@@ -37,4 +37,4 @@
     document.body.appendChild(img);
   }
   onload();
-</script>
\ No newline at end of file
+</script>
diff --git a/src/cobalt/doc/clients_performance_guide.md b/src/cobalt/doc/clients_performance_guide.md
index 1de5a4e..f7ea417 100644
--- a/src/cobalt/doc/clients_performance_guide.md
+++ b/src/cobalt/doc/clients_performance_guide.md
@@ -124,7 +124,7 @@
 desired background color or image on the `<body>` element which will cover the
 display anyway.  Otherwise, the `<body>` element will render its background, and
 then the `<div>` element will render over top of it (Cobalt is not smart enough
-to know if an element completely coveres another element), resulting in more
+to know if an element completely covers another element), resulting in more
 pixels being touched than is necessary.
 
 This type of optimization is related to the concept of "overdraw" from computer
diff --git a/src/cobalt/doc/gyp_gn_files.md b/src/cobalt/doc/gyp_gn_files.md
deleted file mode 100644
index 452bfa7..0000000
--- a/src/cobalt/doc/gyp_gn_files.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# GYP files and their corresponding GN files
-
-Generally, `foo/bar/bar.gyp` corresponds to `foo/bar/BUILD.gn`, while
-`foo/bar/baz.gyp` corresponds to either `foo/bar/baz/BUILD.gn` or
-`foo/bar/BUILD.gn` (depending on whether it made sense to combine `baz.gyp` with
-`bar.gyp`). `foo/bar/quux.gypi` typically corresponds to
-`foo/bar/quux.gni`. Here is a table of irregular correspondences:
-
-GYP File                                            | GN File                                                                   | Notes
---------------------------------------------------- | ------------------------------------------------------------------------- |------
-build/common.gypi                                   | cobalt/build/config/base.gni, starboard/build/config/base.gni (variables) | A few variables have been omitted, moved to `BUILDCONFIG.gn` instead, or refactored into configs. See the GYP -> GN cookbook for more info.
-build/common.gypi                                   | cobalt/build/config/BUILD.gn (target defaults)
-cobalt/build/all.gyp                                | BUILD.gn (in root directory)                                              | GN requires this location to be used
-cobalt/build/config/base.gypi                       | cobalt/build/config/base.gni, starboard/build/config/base.gni (variables) | See comments for `build/common.gypi`
-starboard/linux/shared/compiler_flags.gypi          | starboard/linux/shared/BUILD.gn                                           | "Compiler Defaults" section
-starboard/linux/shared/starboard_base_symbolize.gyp | starboard/linux/shared/BUILD.gn                                           | "starboard_platform Target" section
-starboard/linux/shared/starboard_platform.gypi      | starboard/linux/shared/BUILD.gn                                           | "starboard_platform Target" section
-starboard/linux/x64x11/libraries.gypi               | starboard/linux/x64x11/BUILD.gn                                           | `libs` variable of the `compiler_defaults` config
-starboard/starboard_base_target.gypi                | starboard/build/config/BUILD.gn                                           | "Compiler Defaults" section
diff --git a/src/cobalt/doc/memory_tuning.md b/src/cobalt/doc/memory_tuning.md
index da5f972..8f65ee8 100644
--- a/src/cobalt/doc/memory_tuning.md
+++ b/src/cobalt/doc/memory_tuning.md
@@ -7,12 +7,6 @@
 the memory allocations that will be assigned to the various subsystems in
 cobalt.
 
-As an example, at the cost of performance you can reduce CPU memory on your
-platform by 5MB and GPU memory usage on your platform by 10MB using these
-command line flags:
-
-`cobalt --reduce_cpu_memory_by=5MB --reduce_gpu_memory_by=10MB`
-
 Some settings will be "fixed" while others will be "flexible" so that their
 memory consumption will scale down for memory constrained platforms.
 
@@ -20,8 +14,7 @@
 
 **IMPORTANT**
 *Setting `--max_cobalt_cpu_usage` and `--max_cobalt_gpu_usage` on the
-command line is a beta feature. When reducing memory, please use
-`--reduce_cpu_memory_by` and `--reduce_gpu_memory_by`.*
+command line is a beta feature.*
 
 ### Memory Settings Table ###
 
@@ -29,33 +22,16 @@
 
 ~~~
 AutoMem:
-
- SETTING NAME                           VALUE                    TYPE   SOURCE
- ________________________________________________________________________________
-|                                      |             |          |      |         |
-| image_cache_size_in_bytes            |    33554432 |  32.0 MB |  GPU | AutoSet |
-|______________________________________|_____________|__________|______|_________|
-|                                      |             |          |      |         |
-| javascript_gc_threshold_in_bytes     |     8388608 |   8.0 MB |  CPU |   Build |
-|______________________________________|_____________|__________|______|_________|
-|                                      |             |          |      |         |
-| misc_cobalt_cpu_size_in_bytes        |   124780544 | 119.0 MB |  CPU | AutoSet |
-|______________________________________|_____________|__________|______|_________|
-|                                      |             |          |      |         |
-| misc_cobalt_gpu_size_in_bytes        |    25165824 |  24.0 MB |  GPU | AutoSet |
-|______________________________________|_____________|__________|______|_________|
-|                                      |             |          |      |         |
-| remote_typeface_cache_size_in_bytes  |     4194304 |   4.0 MB |  CPU |   Build |
-|______________________________________|_____________|__________|______|_________|
-|                                      |             |          |      |         |
-| skia_atlas_texture_dimensions        | 4096x8192x2 |  64.0 MB |  GPU |   Build |
-|______________________________________|_____________|__________|______|_________|
-|                                      |             |          |      |         |
-| skia_cache_size_in_bytes             |     4194304 |   4.0 MB |  GPU |   Build |
-|______________________________________|_____________|__________|______|_________|
-|                                      |             |          |      |         |
-| software_surface_cache_size_in_bytes |         N/A |      N/A |  N/A |     N/A |
-|______________________________________|_____________|__________|______|_________|
+ _______________________________________________________________________________
+|SETTING NAME                          |VALUE        |         |TYPE  |SOURCE   |
+| encoded_image_cache_size_in_bytes    |     1048576 |  1.0 MB |  CPU |   Build |
+| image_cache_size_in_bytes            |    10485760 | 10.0 MB |  GPU | AutoSet |
+| offscreen_target_cache_size_in_bytes |     2097152 |  2.0 MB |  GPU | AutoSet |
+| remote_typeface_cache_size_in_bytes  |     4194304 |  4.0 MB |  CPU |   Build |
+| skia_atlas_texture_dimensions        | 2048x2048x2 |  8.0 MB |  GPU | AutoSet |
+| skia_cache_size_in_bytes             |     4194304 |  4.0 MB |  GPU |   Build |
+| software_surface_cache_size_in_bytes |         N/A |     N/A |  N/A |     N/A |
+|______________________________________|_____________|_________|______|_________|
 
 ~~~
 This table shows the breakdown of how much memory is being allocated to each
@@ -101,8 +77,6 @@
     * `AutoSet (Constrained)`
       * This value was AutoSet to a default value, but then was reduced in
       response to `max_cobalt_cpu_usage` or `max_cobalt_gpu_usage being` set too low.
-      This will also trigger in response to `reduce_cpu_memory_by` or
-      `reduce_cpu_memory_by` being set. See "Memory Scaling" section below.
 
 ### Maximum Memory Table ###
 
@@ -183,18 +157,6 @@
 **TOTAL** value. The memory settings will be scaled down until their consumption is
 less than or equal the maximum allowed value **TOTAL**. See also **SETTINGS CONSUME**.
 
-Another way to scale down the memory size is by passing the flags
-`--reduce_cpu_memory_by=XX` and `--reduce_gpu_memory_by=XX` which will:
-1) Ignore the `--max_cobalt_cpu_usage` and `--max_cobalt_gpu_usage`.
-2) Use the current memory consumption of the settings and then reduce that by
-   the amount.
-
-For example, if cobalt uses 160MB of CPU memory then passing in
-`--reduce_cpu_memory_by=10MB` to the command line will attempt to reduce the
-footprint of cobalt by 10MB to 150MB. Note that this reduction is an an attempt,
-and it's possible this attempt will fail if the memory reduction is too aggressive
-or if memory settings have been explicitly set via the build or command line.
-
 *Forcing a Memory Setting to be flexible*
 
 If a memory setting is set via a build setting, then it's possible to make it
@@ -265,16 +227,6 @@
     * Note that `SbSystemGetTotalGPUMemory()` is optional. If no value exists
       for `max_cobalt_gpu_usage` in build/commandline/starboard settings then no
       GPU memory checking is performed.
-  * `reduce_cpu_memory_by`
-    * This setting will trigger CPU memory consumption to be reduced by the amount
-      specified. *This overrides the memory scaling behavior of `max_cobalt_cpu_usage`*.
-      But this will not affect memory checking of `max_cobalt_cpu_usage` otherwise.
-    * Set via command line or else the platform gyp build file.
-  * `reduce_cpu_memory_by`
-    * This setting will trigger GPU memory consumption to be reduced by the amount
-      specified. *This overrides the memory scaling behavior of `max_cobalt_gpu_usage`*.
-      But this will not affect memory checking of `max_cobalt_gpu_usage` otherwise.
-    * Set via command line or else the platform gyp build file.
 
 #### Memory Setting API ####
 
@@ -282,10 +234,6 @@
     * See documentation *Image cache capacity* in `performance_tuning.md` for what
       this setting does.
     * Set via command line, or else build system, or else automatically by Cobalt.
-  * `javascript_gc_threshold_in_bytes`
-    * See documentation *Garbage collection trigger threshold* in `performance_tuning.md`
-      for what this setting does.
-    * Set via command line, or else build system, or else automatically by Cobalt.
   * `remote_typeface_cache_size_in_bytes`
     * Determines the capacity of the remote typefaces cache which manages all typefaces
       downloaded from a web page.
diff --git a/src/cobalt/doc/net_log.md b/src/cobalt/doc/net_log.md
index dfc3c98..1654add 100644
--- a/src/cobalt/doc/net_log.md
+++ b/src/cobalt/doc/net_log.md
@@ -1,30 +1,30 @@
-# Cobalt NetLog

-

-Chromium has a very useful network diagnostic tool called the NetLog and Cobalt

-is hooked up to use it. It's the main tool to track network traffic and debug

-network code.

-

-### Activate the NetLog

-

-The following command line switch will activate the NetLog and store net log

-record to the specified location.

-`./cobalt --net_log=/PATH/TO/YOUR_NETLOG_NAME.json`

-The output json file will be stored at the file location you choose.

-

-

-### Read the NetLog records

-

-The produced json file is not human-friendly, use the

-[NetLog Viewer](https://netlog-viewer.appspot.com/#import)

-

-Cobalt's net_log can not enable some features in the web viewer, but all the

-network traffic is recorded in the event tab.

-

-

-### Add NetLog entries

-

-To Add NetLog entry, get the NetLog instance owned by NetworkModule to where you

-want to add entries and start/end your entry according to the NetLog interface.

-

-A NetLog object is created at each NetworkModule initialization and is passed

-into Chromium net through URLRequestContext.

+# Cobalt NetLog
+
+Chromium has a very useful network diagnostic tool called the NetLog and Cobalt
+is hooked up to use it. It's the main tool to track network traffic and debug
+network code.
+
+### Activate the NetLog
+
+The following command line switch will activate the NetLog and store net log
+record to the specified location.
+`./cobalt --net_log=/PATH/TO/YOUR_NETLOG_NAME.json`
+The output json file will be stored at the file location you choose.
+
+
+### Read the NetLog records
+
+The produced json file is not human-friendly, use the
+[NetLog Viewer](https://netlog-viewer.appspot.com/#import)
+
+Cobalt's net_log can not enable some features in the web viewer, but all the
+network traffic is recorded in the event tab.
+
+
+### Add NetLog entries
+
+To Add NetLog entry, get the NetLog instance owned by NetworkModule to where you
+want to add entries and start/end your entry according to the NetLog interface.
+
+A NetLog object is created at each NetworkModule initialization and is passed
+into Chromium net through URLRequestContext.
diff --git a/src/cobalt/doc/performance_tuning.md b/src/cobalt/doc/performance_tuning.md
index f0a91ad..2c29303 100644
--- a/src/cobalt/doc/performance_tuning.md
+++ b/src/cobalt/doc/performance_tuning.md
@@ -264,7 +264,7 @@
 ### Close the debug console when measuring performance
 
 Cobalt provides a debug console in non-gold builds to allow the display
-of variables overlayed on top of the application.  This can be helpful
+of variables overlaid on top of the application.  This can be helpful
 for debugging issues and keeping track of things like app lifetime, but
 the debug console consumes significant resources when it is visible in order
 to render it, so it should be hidden when performance is being evaluated.
diff --git a/src/cobalt/doc/web_debugging.md b/src/cobalt/doc/web_debugging.md
index bba8c48..cbf2fbb 100644
--- a/src/cobalt/doc/web_debugging.md
+++ b/src/cobalt/doc/web_debugging.md
@@ -133,8 +133,8 @@
 ##### Debug Console overlay
 
 This overlay is interactive and it shows messages from Cobalt, along with logs
-from Javacript `console.log()`. While it is active, you cannot interact directly
-with the underlying page.
+from Javascript `console.log()`. While it is active, you cannot interact
+directly with the underlying page.
 
 Additionally, it can act as a JS interpreter that will evaluate arbitrary
 expressions on the page being debugged. The output from these JS commands will
diff --git a/src/cobalt/dom/dom_stat_tracker.cc b/src/cobalt/dom/dom_stat_tracker.cc
index 544a218..586f8a3 100644
--- a/src/cobalt/dom/dom_stat_tracker.cc
+++ b/src/cobalt/dom/dom_stat_tracker.cc
@@ -26,10 +26,21 @@
       count_html_element_document_(
           base::StringPrintf("Count.%s.DOM.HtmlElement.Document", name.c_str()),
           0, "Number of HTML elements in the document."),
+      count_window_timers_interval_(
+          base::StringPrintf("Count.%s.DOM.WindowTimers.Interval",
+                             name.c_str()),
+          0, "Number of active WindowTimer Intervals."),
+      count_window_timers_timeout_(
+          base::StringPrintf("Count.%s.DOM.WindowTimers.Timeout", name.c_str()),
+          0, "Number of active WindowTimer Timeouts."),
       count_html_element_created_(0),
       count_html_element_destroyed_(0),
       count_html_element_document_added_(0),
       count_html_element_document_removed_(0),
+      count_window_timers_interval_created_(0),
+      count_window_timers_interval_destroyed_(0),
+      count_window_timers_timeout_created_(0),
+      count_window_timers_timeout_destroyed_(0),
       script_element_execute_count_(
           base::StringPrintf("Count.%s.DOM.HtmlScriptElement.Execute",
                              name.c_str()),
@@ -69,6 +80,8 @@
   // destroyed.
   DCHECK_EQ(count_html_element_, 0);
   DCHECK_EQ(count_html_element_document_, 0);
+  DCHECK_EQ(count_window_timers_interval_, 0);
+  DCHECK_EQ(count_window_timers_timeout_, 0);
 
   event_video_start_delay_stop_watch_.Stop();
 }
@@ -146,11 +159,20 @@
   count_html_element_document_ +=
       count_html_element_document_added_ - count_html_element_document_removed_;
 
+  count_window_timers_interval_ += count_window_timers_interval_created_ -
+                                   count_window_timers_interval_destroyed_;
+  count_window_timers_timeout_ += count_window_timers_timeout_created_ -
+                                  count_window_timers_timeout_destroyed_;
   // Now clear the values.
   count_html_element_created_ = 0;
   count_html_element_destroyed_ = 0;
   count_html_element_document_added_ = 0;
   count_html_element_document_removed_ = 0;
+
+  count_window_timers_interval_created_ = 0;
+  count_window_timers_interval_destroyed_ = 0;
+  count_window_timers_timeout_created_ = 0;
+  count_window_timers_timeout_destroyed_ = 0;
 }
 
 void DomStatTracker::StartTrackingEvent() {
diff --git a/src/cobalt/dom/dom_stat_tracker.h b/src/cobalt/dom/dom_stat_tracker.h
index 381b9f0..288444e 100644
--- a/src/cobalt/dom/dom_stat_tracker.h
+++ b/src/cobalt/dom/dom_stat_tracker.h
@@ -37,6 +37,19 @@
   explicit DomStatTracker(const std::string& name);
   ~DomStatTracker();
 
+  void OnWindowTimersIntervalCreated() {
+    ++count_window_timers_interval_created_;
+  }
+  void OnWindowTimersIntervalDestroyed() {
+    ++count_window_timers_interval_destroyed_;
+  }
+  void OnWindowTimersTimeoutCreated() {
+    ++count_window_timers_timeout_created_;
+  }
+  void OnWindowTimersTimeoutDestroyed() {
+    ++count_window_timers_timeout_destroyed_;
+  }
+
   void OnHtmlElementCreated();
   void OnHtmlElementDestroyed();
   void OnHtmlElementInsertedIntoDocument();
@@ -94,12 +107,19 @@
   base::CVal<int, base::CValPublic> count_html_element_;
   base::CVal<int, base::CValPublic> count_html_element_document_;
 
+  base::CVal<int, base::CValPublic> count_window_timers_interval_;
+  base::CVal<int, base::CValPublic> count_window_timers_timeout_;
+
   // Periodic counts. The counts are cleared after the CVals are updated in
   // |FlushPeriodicTracking|.
   int count_html_element_created_;
   int count_html_element_destroyed_;
   int count_html_element_document_added_;
   int count_html_element_document_removed_;
+  int count_window_timers_interval_created_;
+  int count_window_timers_interval_destroyed_;
+  int count_window_timers_timeout_created_;
+  int count_window_timers_timeout_destroyed_;
 
   // Count of HtmlScriptElement::Execute() calls, their total size in bytes, and
   // the time of last call.
diff --git a/src/cobalt/dom/dom_test.gyp b/src/cobalt/dom/dom_test.gyp
index 456965d..84aed7e 100644
--- a/src/cobalt/dom/dom_test.gyp
+++ b/src/cobalt/dom/dom_test.gyp
@@ -70,6 +70,7 @@
         'url_utils_test.cc',
         'user_agent_data_test.cc',
         'window_test.cc',
+        'window_timers_test.cc',
         'xml_document_test.cc',
       ],
       'dependencies': [
diff --git a/src/cobalt/dom/event_target.h b/src/cobalt/dom/event_target.h
index 66b4a3f..7aca7e7 100644
--- a/src/cobalt/dom/event_target.h
+++ b/src/cobalt/dom/event_target.h
@@ -400,6 +400,20 @@
     SetAttributeEventListener(base::Tokens::beforeunload(), event_listener);
   }
 
+  const EventListenerScriptValue* onoffline() {
+    return GetAttributeEventListener(base::Tokens::offline());
+  }
+  void set_onoffline(const EventListenerScriptValue& event_listener) {
+    SetAttributeEventListener(base::Tokens::offline(), event_listener);
+  }
+
+  const EventListenerScriptValue* ononline() {
+    return GetAttributeEventListener(base::Tokens::online());
+  }
+  void set_ononline(const EventListenerScriptValue& event_listener) {
+    SetAttributeEventListener(base::Tokens::online(), event_listener);
+  }
+
   const EventListenerScriptValue* ontransitionend() {
     return GetAttributeEventListener(base::Tokens::transitionend());
   }
diff --git a/src/cobalt/dom/font_cache.cc b/src/cobalt/dom/font_cache.cc
index ce58fe0..25c953d 100644
--- a/src/cobalt/dom/font_cache.cc
+++ b/src/cobalt/dom/font_cache.cc
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include <memory>
+#include <vector>
 
 #include "cobalt/dom/font_cache.h"
 #include "cobalt/dom/global_stats.h"
@@ -165,7 +166,7 @@
   FontFaceMap::iterator font_face_map_iterator = font_face_map_->find(family);
   if (font_face_map_iterator != font_face_map_->end()) {
     // Add all font-face entries that match the family.
-    std::vector<const FontFaceStyleSet::Entry*> entries =
+    std::vector<scoped_refptr<FontFaceStyleSet::Entry>> entries =
         font_face_map_iterator->second.GetEntriesThatMatchStyle(style);
     for (auto entry : entries) {
       FontFace* face = new FontFace();
diff --git a/src/cobalt/dom/font_cache.h b/src/cobalt/dom/font_cache.h
index 932743c..a7c2766 100644
--- a/src/cobalt/dom/font_cache.h
+++ b/src/cobalt/dom/font_cache.h
@@ -20,6 +20,7 @@
 #include <set>
 #include <string>
 #include <utility>
+#include <vector>
 
 #include "base/callback.h"
 #include "base/containers/hash_tables.h"
diff --git a/src/cobalt/dom/font_cache_test.cc b/src/cobalt/dom/font_cache_test.cc
index 1c22311..ec407c4 100644
--- a/src/cobalt/dom/font_cache_test.cc
+++ b/src/cobalt/dom/font_cache_test.cc
@@ -46,10 +46,11 @@
     const std::string& family_name, const base::StringPiece local_font_name) {
   std::unique_ptr<FontCache::FontFaceMap> ffm(new FontCache::FontFaceMap());
   dom::FontFaceStyleSet ffss;
-  dom::FontFaceStyleSet::Entry entry;
-  entry.sources.push_back(
+  scoped_refptr<dom::FontFaceStyleSet::Entry> entry =
+      base::MakeRefCounted<dom::FontFaceStyleSet::Entry>();
+  entry->sources.push_back(
       FontFaceSource(local_font_name.as_string()));  // local()
-  entry.sources.push_back(FontFaceSource(
+  entry->sources.push_back(FontFaceSource(
       GURL("https://example.com/Dancing-Regular.woff")));  // url()
   ffss.AddEntry(entry);
   ffm->insert(FontCache::FontFaceMap::value_type(family_name, ffss));
diff --git a/src/cobalt/dom/font_face.cc b/src/cobalt/dom/font_face.cc
index 6c44d75..1347eef 100644
--- a/src/cobalt/dom/font_face.cc
+++ b/src/cobalt/dom/font_face.cc
@@ -21,14 +21,13 @@
 namespace cobalt {
 namespace dom {
 
-void FontFaceStyleSet::AddEntry(const FontFaceStyleSet::Entry& entry) {
+void FontFaceStyleSet::AddEntry(scoped_refptr<FontFaceStyleSet::Entry> entry) {
   entries_.push_back(entry);
 }
 
 void FontFaceStyleSet::CollectUrlSources(std::set<GURL>* urls) const {
-  for (Entries::const_iterator entry_iterator = entries_.begin();
-       entry_iterator != entries_.end(); ++entry_iterator) {
-    const FontFaceSources& entry_sources = entry_iterator->sources;
+  for (auto entry : entries_) {
+    const FontFaceSources& entry_sources = entry->sources;
     for (FontFaceSources::const_iterator source_iterator =
              entry_sources.begin();
          source_iterator != entry_sources.end(); ++source_iterator) {
@@ -39,19 +38,19 @@
   }
 }
 
-std::vector<const FontFaceStyleSet::Entry*>
+std::vector<scoped_refptr<FontFaceStyleSet::Entry>>
 FontFaceStyleSet::GetEntriesThatMatchStyle(
     const render_tree::FontStyle& pattern) const {
-  std::vector<const FontFaceStyleSet::Entry*> entries;
+  std::vector<scoped_refptr<Entry>> entries;
   int max_score = std::numeric_limits<int>::min();
   for (const auto& entry : entries_) {
-    int score = MatchScore(pattern, entry.style);
+    int score = MatchScore(pattern, entry->style);
     if (score >= max_score) {
       if (score > max_score) {
         max_score = score;
         entries.clear();
       }
-      entries.push_back(&entry);
+      entries.push_back(entry);
     }
   }
   return entries;
diff --git a/src/cobalt/dom/font_face.h b/src/cobalt/dom/font_face.h
index a5f80cc..cd7621e 100644
--- a/src/cobalt/dom/font_face.h
+++ b/src/cobalt/dom/font_face.h
@@ -60,7 +60,7 @@
   // single @font-face rule.
   // https://www.w3.org/TR/css3-fonts/#descdef-src
   // https://www.w3.org/TR/css3-fonts/#font-prop-desc
-  struct Entry {
+  struct Entry : public base::RefCounted<Entry> {
    public:
     bool operator==(const Entry& other) const {
       return style.weight == other.style.weight &&
@@ -83,7 +83,7 @@
     FontFaceSources sources;
   };
 
-  void AddEntry(const Entry& entry);
+  void AddEntry(scoped_refptr<Entry> entry);
 
   // Walk all of the style set's entries, inserting any url sources encountered
   // into the set. All pre-existing url entries within the set are retained.
@@ -92,7 +92,7 @@
 
   // Returns a list of entries with the style that most closesly matches the
   // pattern.
-  std::vector<const Entry*> GetEntriesThatMatchStyle(
+  std::vector<scoped_refptr<Entry>> GetEntriesThatMatchStyle(
       const render_tree::FontStyle& pattern) const;
 
   bool operator==(const FontFaceStyleSet& other) const {
@@ -100,7 +100,7 @@
   }
 
  private:
-  typedef std::vector<Entry> Entries;
+  typedef std::vector<scoped_refptr<Entry>> Entries;
 
   // Returns the match score between two patterns. The score logic matches that
   // within SkFontStyleSet_Cobalt::match_score().
diff --git a/src/cobalt/dom/font_face_updater.cc b/src/cobalt/dom/font_face_updater.cc
index 940eaaa..9111114 100644
--- a/src/cobalt/dom/font_face_updater.cc
+++ b/src/cobalt/dom/font_face_updater.cc
@@ -15,6 +15,7 @@
 #include "cobalt/dom/font_face_updater.h"
 
 #include <string>
+#include <utility>
 
 #include "cobalt/cssom/css_font_face_rule.h"
 #include "cobalt/cssom/css_media_rule.h"
@@ -47,7 +48,9 @@
 // TODO: Handle unicode ranges.
 class FontFaceProvider : public cssom::NotReachedPropertyValueVisitor {
  public:
-  explicit FontFaceProvider(const GURL& base_url) : base_url_(base_url) {}
+  explicit FontFaceProvider(const GURL& base_url) : base_url_(base_url) {
+    style_set_entry_ = base::MakeRefCounted<FontFaceStyleSet::Entry>();
+  }
 
   void VisitFontStyle(cssom::FontStyleValue* font_style) override;
   void VisitFontWeight(cssom::FontWeightValue* font_weight) override;
@@ -62,7 +65,7 @@
   bool IsFontFaceValid() const;
 
   const std::string& font_family() const { return font_family_; }
-  const FontFaceStyleSet::Entry& style_set_entry() const {
+  const scoped_refptr<FontFaceStyleSet::Entry> style_set_entry() const {
     return style_set_entry_;
   }
 
@@ -70,13 +73,13 @@
   const GURL& base_url_;
 
   std::string font_family_;
-  FontFaceStyleSet::Entry style_set_entry_;
+  scoped_refptr<FontFaceStyleSet::Entry> style_set_entry_;
 
   DISALLOW_COPY_AND_ASSIGN(FontFaceProvider);
 };
 
 void FontFaceProvider::VisitFontStyle(cssom::FontStyleValue* font_style) {
-  style_set_entry_.style.slant =
+  style_set_entry_->style.slant =
       font_style->value() == cssom::FontStyleValue::kItalic
           ? render_tree::FontStyle::kItalicSlant
           : render_tree::FontStyle::kUprightSlant;
@@ -85,31 +88,32 @@
 void FontFaceProvider::VisitFontWeight(cssom::FontWeightValue* font_weight) {
   switch (font_weight->value()) {
     case cssom::FontWeightValue::kThinAka100:
-      style_set_entry_.style.weight = render_tree::FontStyle::kThinWeight;
+      style_set_entry_->style.weight = render_tree::FontStyle::kThinWeight;
       break;
     case cssom::FontWeightValue::kExtraLightAka200:
-      style_set_entry_.style.weight = render_tree::FontStyle::kExtraLightWeight;
+      style_set_entry_->style.weight =
+          render_tree::FontStyle::kExtraLightWeight;
       break;
     case cssom::FontWeightValue::kLightAka300:
-      style_set_entry_.style.weight = render_tree::FontStyle::kLightWeight;
+      style_set_entry_->style.weight = render_tree::FontStyle::kLightWeight;
       break;
     case cssom::FontWeightValue::kNormalAka400:
-      style_set_entry_.style.weight = render_tree::FontStyle::kNormalWeight;
+      style_set_entry_->style.weight = render_tree::FontStyle::kNormalWeight;
       break;
     case cssom::FontWeightValue::kMediumAka500:
-      style_set_entry_.style.weight = render_tree::FontStyle::kMediumWeight;
+      style_set_entry_->style.weight = render_tree::FontStyle::kMediumWeight;
       break;
     case cssom::FontWeightValue::kSemiBoldAka600:
-      style_set_entry_.style.weight = render_tree::FontStyle::kSemiBoldWeight;
+      style_set_entry_->style.weight = render_tree::FontStyle::kSemiBoldWeight;
       break;
     case cssom::FontWeightValue::kBoldAka700:
-      style_set_entry_.style.weight = render_tree::FontStyle::kBoldWeight;
+      style_set_entry_->style.weight = render_tree::FontStyle::kBoldWeight;
       break;
     case cssom::FontWeightValue::kExtraBoldAka800:
-      style_set_entry_.style.weight = render_tree::FontStyle::kExtraBoldWeight;
+      style_set_entry_->style.weight = render_tree::FontStyle::kExtraBoldWeight;
       break;
     case cssom::FontWeightValue::kBlackAka900:
-      style_set_entry_.style.weight = render_tree::FontStyle::kBlackWeight;
+      style_set_entry_->style.weight = render_tree::FontStyle::kBlackWeight;
       break;
   }
 }
@@ -199,7 +203,7 @@
 }
 
 void FontFaceProvider::VisitLocalSrc(cssom::LocalSrcValue* local_src) {
-  style_set_entry_.sources.push_back(FontFaceSource(local_src->value()));
+  style_set_entry_->sources.push_back(FontFaceSource(local_src->value()));
 }
 
 void FontFaceProvider::VisitPropertyList(
@@ -218,7 +222,7 @@
   FontFaceStyleSet::Entry::UnicodeRange range = {
       static_cast<uint32>(unicode_range->start()),
       static_cast<uint32>(unicode_range->end())};
-  style_set_entry_.unicode_range.insert(range);
+  style_set_entry_->unicode_range.insert(range);
 }
 
 // Check for a supported format. If no format hints are supplied, then the user
@@ -238,7 +242,7 @@
 void FontFaceProvider::VisitURL(cssom::URLValue* url) {
   GURL gurl = url->is_absolute() ? GURL(url->value()) : url->Resolve(base_url_);
   if (gurl.is_valid()) {
-    style_set_entry_.sources.push_back(FontFaceSource(gurl));
+    style_set_entry_->sources.push_back(FontFaceSource(gurl));
   }
 }
 
@@ -246,7 +250,7 @@
 //  https://www.w3.org/TR/css3-fonts/#descdef-font-family
 //  https://www.w3.org/TR/css3-fonts/#descdef-src
 bool FontFaceProvider::IsFontFaceValid() const {
-  return !font_family_.empty() && !style_set_entry_.sources.empty();
+  return !font_family_.empty() && !style_set_entry_->sources.empty();
 }
 
 }  // namespace
diff --git a/src/cobalt/dom/font_list.cc b/src/cobalt/dom/font_list.cc
index 1328c87..d423d2a 100644
--- a/src/cobalt/dom/font_list.cc
+++ b/src/cobalt/dom/font_list.cc
@@ -14,6 +14,8 @@
 
 #include "cobalt/dom/font_list.h"
 
+#include <set>
+
 #include "base/i18n/char_iterator.h"
 #include "cobalt/base/unicode/character_values.h"
 #include "cobalt/dom/font_cache.h"
diff --git a/src/cobalt/dom/font_list.h b/src/cobalt/dom/font_list.h
index 1d2ddbd..829c03f 100644
--- a/src/cobalt/dom/font_list.h
+++ b/src/cobalt/dom/font_list.h
@@ -47,7 +47,7 @@
     kUnavailableState,
   };
   State state = kUnrequestedState;
-  const FontFaceStyleSet::Entry* entry = nullptr;
+  scoped_refptr<FontFaceStyleSet::Entry> entry;
 
   // The render_tree::Font obtained via the font cache using |family_name_| in
   // font list font, along with |style_| and |size_| from the containing font
diff --git a/src/cobalt/dom/window.cc b/src/cobalt/dom/window.cc
index 34e0c86..0dea02f 100644
--- a/src/cobalt/dom/window.cc
+++ b/src/cobalt/dom/window.cc
@@ -149,7 +149,7 @@
           performance_.get(), enable_inline_script_warnings,
           video_playback_rate_multiplier)),
       ALLOW_THIS_IN_INITIALIZER_LIST(document_(new Document(
-          html_element_context_.get(),
+          html_element_context(),
           Document::Options(
               url, this,
               base::Bind(&Window::FireHashChangeEvent, base::Unretained(this)),
@@ -165,7 +165,8 @@
       ALLOW_THIS_IN_INITIALIZER_LIST(
           relay_on_load_event_(new RelayLoadEvent(this))),
       ALLOW_THIS_IN_INITIALIZER_LIST(window_timers_(
-          new WindowTimers(this, debugger_hooks(), initial_application_state))),
+          new WindowTimers(this, dom_stat_tracker, debugger_hooks(),
+                           initial_application_state))),
       ALLOW_THIS_IN_INITIALIZER_LIST(animation_frame_request_callback_list_(
           new AnimationFrameRequestCallbackList(this, debugger_hooks()))),
       crypto_(new Crypto()),
@@ -197,8 +198,8 @@
 #if !defined(ENABLE_TEST_RUNNER)
 #endif
   document_->AddObserver(relay_on_load_event_.get());
-  html_element_context_->application_lifecycle_state()->AddObserver(this);
-  SetCamera3D(camera_3d);
+  html_element_context()->application_lifecycle_state()->AddObserver(this);
+  UpdateCamera3D(camera_3d);
 
   // Document load start is deferred from this constructor so that we can be
   // guaranteed that this Window object is fully constructed before document
@@ -354,9 +355,9 @@
 }
 
 scoped_refptr<MediaQueryList> Window::MatchMedia(const std::string& query) {
-  DCHECK(html_element_context_->css_parser());
+  DCHECK(html_element_context()->css_parser());
   scoped_refptr<cssom::MediaList> media_list =
-      html_element_context_->css_parser()->ParseMediaList(
+      html_element_context()->css_parser()->ParseMediaList(
           query, GetInlineSourceLocation());
   return base::WrapRefCounted(new MediaQueryList(media_list, screen_));
 }
@@ -393,7 +394,7 @@
 
 int Window::SetTimeout(const WindowTimers::TimerCallbackArg& handler,
                        int timeout) {
-  DLOG_IF(WARNING, timeout < 0)
+  LOG_IF(WARNING, timeout < 0)
       << "Window::SetTimeout received negative timeout: " << timeout;
   timeout = std::max(timeout, 0);
 
@@ -401,7 +402,7 @@
   if (window_timers_) {
     return_value = window_timers_->SetTimeout(handler, timeout);
   } else {
-    DLOG(WARNING) << "window_timers_ does not exist.  Already destroyed?";
+    LOG(WARNING) << "window_timers_ does not exist.  Already destroyed?";
   }
 
   return return_value;
@@ -411,21 +412,21 @@
   if (window_timers_) {
     window_timers_->ClearTimeout(handle);
   } else {
-    DLOG(WARNING) << "window_timers_ does not exist.  Already destroyed?";
+    LOG(WARNING) << "window_timers_ does not exist.  Already destroyed?";
   }
 }
 
 int Window::SetInterval(const WindowTimers::TimerCallbackArg& handler,
                         int timeout) {
-  DLOG_IF(WARNING, timeout < 0)
-      << "Window::SetInterval received negative timeout: " << timeout;
+  LOG_IF(WARNING, timeout < 0)
+      << "Window::SetInterval received negative interval: " << timeout;
   timeout = std::max(timeout, 0);
 
   int return_value = 0;
   if (window_timers_) {
     return_value = window_timers_->SetInterval(handler, timeout);
   } else {
-    DLOG(WARNING) << "window_timers_ does not exist.  Already destroyed?";
+    LOG(WARNING) << "window_timers_ does not exist.  Already destroyed?";
   }
 
   return return_value;
@@ -471,10 +472,6 @@
   }
 }
 
-HTMLElementContext* Window::html_element_context() const {
-  return html_element_context_.get();
-}
-
 void Window::RunAnimationFrameCallbacks() {
   // Scope the StopWatch. It should not include any processing from
   // |ran_animation_frame_callbacks_callback_|.
@@ -536,7 +533,7 @@
 
 void Window::SetApplicationState(base::ApplicationState state,
                                  SbTimeMonotonic timestamp) {
-  html_element_context_->application_lifecycle_state()->SetApplicationState(
+  html_element_context()->application_lifecycle_state()->SetApplicationState(
       state);
   if (timestamp == 0) return;
   performance_->SetApplicationState(state, timestamp);
@@ -621,7 +618,8 @@
   // This will cause layout invalidation.
   document_->SetViewport(viewport_size_);
 
-  if (html_element_context_->application_lifecycle_state()
+  if (html_element_context()
+          ->application_lifecycle_state()
           ->GetVisibilityState() == kVisibilityStateVisible) {
     DispatchEvent(new Event(base::Tokens::resize()));
   } else {
@@ -629,9 +627,15 @@
   }
 }
 
-void Window::SetCamera3D(const scoped_refptr<input::Camera3D>& camera_3d) {
-  camera_3d_ = new Camera3D(camera_3d);
-  camera_3d_->StartOrientationEvents(base::AsWeakPtr(this));
+void Window::UpdateCamera3D(const scoped_refptr<input::Camera3D>& camera_3d) {
+  if (camera_3d_ && camera_3d_->impl()) {
+    // Update input object for existing camera.
+    camera_3d_->impl()->SetInput(camera_3d);
+  } else {
+    // Create a new camera which uses the given input camera object.
+    camera_3d_ = new Camera3D(camera_3d);
+    camera_3d_->StartOrientationEvents(base::AsWeakPtr(this));
+  }
 }
 
 void Window::OnWindowFocusChanged(bool has_focus) {
@@ -656,7 +660,8 @@
   // the app being in a visibility state that disables layout, then prepare a
   // pending resize event, so that the resize will occur once layouts are again
   // available.
-  if (html_element_context_->application_lifecycle_state()
+  if (html_element_context()
+          ->application_lifecycle_state()
           ->GetVisibilityState() != kVisibilityStateVisible) {
     is_resize_event_pending_ = true;
   }
@@ -728,7 +733,7 @@
   if (ui_nav_root_) {
     ui_nav_root_->SetEnabled(false);
   }
-  html_element_context_->application_lifecycle_state()->RemoveObserver(this);
+  html_element_context()->application_lifecycle_state()->RemoveObserver(this);
 }
 
 void Window::FireHashChangeEvent() {
diff --git a/src/cobalt/dom/window.h b/src/cobalt/dom/window.h
index 81467b4..2469cc3 100644
--- a/src/cobalt/dom/window.h
+++ b/src/cobalt/dom/window.h
@@ -322,7 +322,9 @@
 
   void Gc(script::EnvironmentSettings* settings);
 
-  HTMLElementContext* html_element_context() const;
+  HTMLElementContext* html_element_context() const {
+    return html_element_context_.get();
+  }
 
   // Will fire the animation frame callbacks and reset the animation frame
   // request callback list.
@@ -347,7 +349,7 @@
 
   void SetSize(cssom::ViewportSize size);
 
-  void SetCamera3D(const scoped_refptr<input::Camera3D>& camera_3d);
+  void UpdateCamera3D(const scoped_refptr<input::Camera3D>& camera_3d);
 
   void set_web_media_player_factory(
       media::WebMediaPlayerFactory* web_media_player_factory) {
diff --git a/src/cobalt/dom/window_event_handlers.idl b/src/cobalt/dom/window_event_handlers.idl
index 186e1ad..ba91797 100644
--- a/src/cobalt/dom/window_event_handlers.idl
+++ b/src/cobalt/dom/window_event_handlers.idl
@@ -18,4 +18,6 @@
 interface WindowEventHandlers {
   attribute EventHandler onunload;
   attribute EventHandler onbeforeunload;
+  attribute EventHandler onoffline;
+  attribute EventHandler ononline;
 };
diff --git a/src/cobalt/dom/window_timers.cc b/src/cobalt/dom/window_timers.cc
index 3b5c079..ef73f89 100644
--- a/src/cobalt/dom/window_timers.cc
+++ b/src/cobalt/dom/window_timers.cc
@@ -40,16 +40,12 @@
   }
 
   if (callbacks_active_) {
-    auto* timer = new Timer(type, owner_, handler, timeout, handle, this);
+    auto* timer = new Timer(type, owner_, dom_stat_tracker_, debugger_hooks_,
+                            handler, timeout, handle, this);
     if (application_state_ != base::kApplicationStateFrozen) {
       timer->StartOrResume();
     }
     timers_[handle] = timer;
-    debugger_hooks_.AsyncTaskScheduled(
-        timers_[handle], type == Timer::kOneShot ? "SetTimeout" : "SetInterval",
-        type == Timer::kOneShot
-            ? base::DebuggerHooks::AsyncTaskFrequency::kOneshot
-            : base::DebuggerHooks::AsyncTaskFrequency::kRecurring);
   } else {
     timers_[handle] = nullptr;
   }
@@ -69,26 +65,12 @@
   return TryAddNewTimer(Timer::kRepeating, handler, timeout);
 }
 
-void WindowTimers::ClearInterval(int handle) {
-  Timers::iterator timer = timers_.find(handle);
-  if (timer != timers_.end()) {
-    debugger_hooks_.AsyncTaskCanceled(timer->second);
-    timers_.erase(timer);
-  }
-}
-
-void WindowTimers::ClearAllIntervalsAndTimeouts() {
-  for (auto& timer_entry : timers_) {
-    debugger_hooks_.AsyncTaskCanceled(timer_entry.second);
-  }
-  timers_.clear();
-}
+void WindowTimers::ClearInterval(int handle) { timers_.erase(handle); }
 
 void WindowTimers::DisableCallbacks() {
   callbacks_active_ = false;
   // Immediately cancel any pending timers.
   for (auto& timer_entry : timers_) {
-    debugger_hooks_.AsyncTaskCanceled(timer_entry.second);
     timer_entry.second = nullptr;
   }
 }
@@ -126,9 +108,8 @@
   {
     // Keep a |TimerInfo| reference, so it won't be released when running the
     // callback.
-    scoped_refptr<Timer> timer_info = timer->second;
-    base::ScopedAsyncTask async_task(debugger_hooks_, timer_info);
-    timer_info->callback_reference().value().Run();
+    scoped_refptr<Timer> timer_info(timer->second);
+    timer_info->Run();
   }
 
   // After running the callback, double check whether the timer is still there
@@ -137,7 +118,6 @@
   // If the timer is not deleted and is not running, it means it is an oneshot
   // timer and has just fired the shot, and it should be deleted now.
   if (timer != timers_.end() && !timer->second->timer()->IsRunning()) {
-    debugger_hooks_.AsyncTaskCanceled(timer->second);
     timers_.erase(timer);
   }
 
@@ -169,13 +149,48 @@
 }
 
 WindowTimers::Timer::Timer(TimerType type, script::Wrappable* const owner,
+                           DomStatTracker* dom_stat_tracker,
+                           const base::DebuggerHooks& debugger_hooks,
                            const TimerCallbackArg& callback, int timeout,
                            int handle, WindowTimers* window_timers)
     : type_(type),
       callback_(owner, callback),
+      dom_stat_tracker_(dom_stat_tracker),
+      debugger_hooks_(debugger_hooks),
       timeout_(timeout),
       handle_(handle),
-      window_timers_(window_timers) {}
+      window_timers_(window_timers) {
+  debugger_hooks_.AsyncTaskScheduled(
+      this, type == Timer::kOneShot ? "SetTimeout" : "SetInterval",
+      type == Timer::kOneShot
+          ? base::DebuggerHooks::AsyncTaskFrequency::kOneshot
+          : base::DebuggerHooks::AsyncTaskFrequency::kRecurring);
+  switch (type) {
+    case Timer::kOneShot:
+      dom_stat_tracker_->OnWindowTimersTimeoutCreated();
+      break;
+    case Timer::kRepeating:
+      dom_stat_tracker_->OnWindowTimersIntervalCreated();
+      break;
+  }
+}
+
+WindowTimers::Timer::~Timer() {
+  switch (type_) {
+    case Timer::kOneShot:
+      dom_stat_tracker_->OnWindowTimersTimeoutDestroyed();
+      break;
+    case Timer::kRepeating:
+      dom_stat_tracker_->OnWindowTimersIntervalDestroyed();
+      break;
+  }
+  debugger_hooks_.AsyncTaskCanceled(this);
+}
+
+void WindowTimers::Timer::Run() {
+  base::ScopedAsyncTask async_task(debugger_hooks_, this);
+  callback_.value().Run();
+}
 
 void WindowTimers::Timer::Pause() {
   if (timer_) {
diff --git a/src/cobalt/dom/window_timers.h b/src/cobalt/dom/window_timers.h
index 42dcf56..6d3db4a 100644
--- a/src/cobalt/dom/window_timers.h
+++ b/src/cobalt/dom/window_timers.h
@@ -26,6 +26,7 @@
 #include "base/timer/timer.h"
 #include "cobalt/base/application_state.h"
 #include "cobalt/base/debugger_hooks.h"
+#include "cobalt/dom/dom_stat_tracker.h"
 #include "cobalt/script/callback_function.h"
 #include "cobalt/script/script_value.h"
 #include "cobalt/script/wrappable.h"
@@ -38,12 +39,14 @@
   typedef script::CallbackFunction<void()> TimerCallback;
   typedef script::ScriptValue<TimerCallback> TimerCallbackArg;
   explicit WindowTimers(script::Wrappable* const owner,
+                        DomStatTracker* dom_stat_tracker,
                         const base::DebuggerHooks& debugger_hooks,
                         base::ApplicationState application_state)
       : owner_(owner),
+        dom_stat_tracker_(dom_stat_tracker),
         debugger_hooks_(debugger_hooks),
         application_state_(application_state) {}
-  ~WindowTimers() {}
+  ~WindowTimers() { DisableCallbacks(); }
 
   int SetTimeout(const TimerCallbackArg& handler, int timeout);
 
@@ -53,8 +56,6 @@
 
   void ClearInterval(int handle);
 
-  void ClearAllIntervalsAndTimeouts();
-
   // When called, it will irreversibly put the WindowTimers object in an
   // inactive state where timer callbacks are ignored.  This is useful when
   // we're in the process of shutting down and wish to drain the JavaScript
@@ -69,11 +70,13 @@
     enum TimerType { kOneShot, kRepeating };
 
     Timer(TimerType type, script::Wrappable* const owner,
+          DomStatTracker* dom_stat_tracker,
+          const base::DebuggerHooks& debugger_hooks,
           const TimerCallbackArg& callback, int timeout, int handle,
           WindowTimers* window_timers);
 
     base::internal::TimerBase* timer() { return timer_.get(); }
-    TimerCallbackArg::Reference& callback_reference() { return callback_; }
+    void Run();
 
     // Pause this timer. The timer will not fire when paused.
     void Pause();
@@ -82,7 +85,7 @@
     void StartOrResume();
 
    private:
-    ~Timer() {}
+    ~Timer();
 
     // Create and start a timer of the specified TimerClass type.
     template <class TimerClass>
@@ -91,6 +94,8 @@
     TimerType type_;
     std::unique_ptr<base::internal::TimerBase> timer_;
     TimerCallbackArg::Reference callback_;
+    DomStatTracker* const dom_stat_tracker_;
+    const base::DebuggerHooks& debugger_hooks_;
     int timeout_;
     int handle_;
     WindowTimers* window_timers_;
@@ -118,6 +123,7 @@
   Timers timers_;
   int current_timer_index_ = 0;
   script::Wrappable* const owner_;
+  DomStatTracker* const dom_stat_tracker_;
   const base::DebuggerHooks& debugger_hooks_;
 
   // Set to false when we're about to shutdown, to ensure that no new JavaScript
diff --git a/src/cobalt/dom/window_timers_test.cc b/src/cobalt/dom/window_timers_test.cc
new file mode 100644
index 0000000..57b233e
--- /dev/null
+++ b/src/cobalt/dom/window_timers_test.cc
@@ -0,0 +1,468 @@
+// Copyright 2021 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cobalt/dom/window_timers.h"
+
+#include <memory>
+#include <string>
+
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/platform_thread.h"
+#include "base/time/time.h"
+#include "cobalt/dom/dom_stat_tracker.h"
+#include "cobalt/script/callback_function.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/javascript_engine.h"
+#include "cobalt/script/testing/fake_script_value.h"
+#include "net/test/test_with_scoped_task_environment.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cobalt {
+namespace dom {
+
+namespace testing {
+
+using ::testing::_;
+using ::testing::Return;
+
+class MockTimerCallback : public WindowTimers::TimerCallback {
+ public:
+  MOCK_CONST_METHOD0(Run, script::CallbackResult<void>());
+  void ExpectRunCall(int times) {
+    EXPECT_CALL(*this, Run())
+        .Times(times)
+        .WillRepeatedly(Return(script::CallbackResult<void>()));
+  }
+};
+
+class MockDebuggerHooks : public base::DebuggerHooks {
+ public:
+  MOCK_CONST_METHOD2(ConsoleLog, void(::logging::LogSeverity, std::string));
+  MOCK_CONST_METHOD3(AsyncTaskScheduled,
+                     void(const void*, const std::string&, AsyncTaskFrequency));
+  MOCK_CONST_METHOD1(AsyncTaskStarted, void(const void*));
+  MOCK_CONST_METHOD1(AsyncTaskFinished, void(const void*));
+  MOCK_CONST_METHOD1(AsyncTaskCanceled, void(const void*));
+
+  void ExpectAsyncTaskScheduled(int times) {
+    EXPECT_CALL(*this, AsyncTaskScheduled(_, _, _)).Times(times);
+  }
+  void ExpectAsyncTaskStarted(int times) {
+    EXPECT_CALL(*this, AsyncTaskStarted(_)).Times(times);
+  }
+  void ExpectAsyncTaskFinished(int times) {
+    EXPECT_CALL(*this, AsyncTaskFinished(_)).Times(times);
+  }
+  void ExpectAsyncTaskCanceled(int times) {
+    EXPECT_CALL(*this, AsyncTaskCanceled(_)).Times(times);
+  }
+};
+
+}  // namespace testing
+
+namespace {
+const int kTimerDelayInMilliseconds = 100;
+}  // namespace
+
+using ::cobalt::script::testing::FakeScriptValue;
+
+class WindowTimersTest : public ::testing::Test,
+                         public net::WithScopedTaskEnvironment {
+ protected:
+  WindowTimersTest()
+      : WithScopedTaskEnvironment(
+            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+        dom_stat_tracker_("WindowTimersTest"),
+        callback_(&mock_timer_callback_) {
+    script::Wrappable* foo = nullptr;
+    timers_.reset(
+        new WindowTimers(foo, &dom_stat_tracker_, hooks_,
+                         base::ApplicationState::kApplicationStateStarted));
+  }
+
+  ~WindowTimersTest() override {}
+
+  testing::MockDebuggerHooks hooks_;
+  DomStatTracker dom_stat_tracker_;
+  std::unique_ptr<WindowTimers> timers_;
+  testing::MockTimerCallback mock_timer_callback_;
+  FakeScriptValue<WindowTimers::TimerCallback> callback_;
+};
+
+TEST_F(WindowTimersTest, TimeoutIsNotCalledDirectly) {
+  hooks_.ExpectAsyncTaskScheduled(1);
+  hooks_.ExpectAsyncTaskCanceled(1);
+
+  mock_timer_callback_.ExpectRunCall(0);
+  timers_->SetTimeout(callback_, 0);
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(0));
+}
+
+TEST_F(WindowTimersTest, TimeoutZeroIsCalledImmediatelyFromTask) {
+  hooks_.ExpectAsyncTaskScheduled(1);
+  hooks_.ExpectAsyncTaskCanceled(1);
+  hooks_.ExpectAsyncTaskStarted(1);
+  hooks_.ExpectAsyncTaskFinished(1);
+
+  mock_timer_callback_.ExpectRunCall(1);
+  timers_->SetTimeout(callback_, 0);
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(0));
+
+  RunUntilIdle();
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 0);
+}
+
+TEST_F(WindowTimersTest, TimeoutIsNotCalledBeforeDelay) {
+  hooks_.ExpectAsyncTaskScheduled(1);
+  hooks_.ExpectAsyncTaskCanceled(1);
+
+  hooks_.ExpectAsyncTaskStarted(0);
+  hooks_.ExpectAsyncTaskFinished(0);
+  mock_timer_callback_.ExpectRunCall(0);
+  timers_->SetTimeout(callback_, kTimerDelayInMilliseconds);
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+
+  FastForwardBy(
+      base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds - 1));
+  RunUntilIdle();
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+}
+
+TEST_F(WindowTimersTest, TimeoutIsCalledAfterDelay) {
+  hooks_.ExpectAsyncTaskScheduled(1);
+  hooks_.ExpectAsyncTaskCanceled(1);
+  hooks_.ExpectAsyncTaskStarted(1);
+  hooks_.ExpectAsyncTaskFinished(1);
+
+  mock_timer_callback_.ExpectRunCall(1);
+  timers_->SetTimeout(callback_, kTimerDelayInMilliseconds);
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+
+  FastForwardBy(base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+  RunUntilIdle();
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 0);
+}
+
+TEST_F(WindowTimersTest, TimeoutIsNotCalledRepeatedly) {
+  hooks_.ExpectAsyncTaskScheduled(1);
+  hooks_.ExpectAsyncTaskCanceled(1);
+  hooks_.ExpectAsyncTaskStarted(1);
+  hooks_.ExpectAsyncTaskFinished(1);
+
+  mock_timer_callback_.ExpectRunCall(1);
+  timers_->SetTimeout(callback_, kTimerDelayInMilliseconds);
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+
+  FastForwardBy(
+      base::TimeDelta::FromMilliseconds(10 * kTimerDelayInMilliseconds));
+  FastForwardUntilNoTasksRemain();
+  RunUntilIdle();
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 0);
+}
+
+TEST_F(WindowTimersTest, TimeoutIsCalledWhenDelayed) {
+  hooks_.ExpectAsyncTaskScheduled(1);
+  hooks_.ExpectAsyncTaskCanceled(1);
+  hooks_.ExpectAsyncTaskStarted(1);
+  hooks_.ExpectAsyncTaskFinished(1);
+
+  mock_timer_callback_.ExpectRunCall(1);
+  timers_->SetTimeout(callback_, kTimerDelayInMilliseconds);
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+
+  AdvanceMockTickClock(
+      base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds + 1000));
+  RunUntilIdle();
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 0);
+}
+
+TEST_F(WindowTimersTest, MultipleTimeouts) {
+  hooks_.ExpectAsyncTaskScheduled(2);
+  hooks_.ExpectAsyncTaskCanceled(2);
+  hooks_.ExpectAsyncTaskStarted(2);
+  hooks_.ExpectAsyncTaskFinished(2);
+
+  mock_timer_callback_.ExpectRunCall(2);
+  timers_->SetTimeout(callback_, kTimerDelayInMilliseconds);
+  timers_->SetTimeout(callback_, kTimerDelayInMilliseconds * 3);
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 2);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+
+  FastForwardBy(
+      base::TimeDelta::FromMilliseconds(3 * kTimerDelayInMilliseconds));
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 0);
+}
+
+TEST_F(WindowTimersTest, ActiveTimeoutsAreCounted) {
+  hooks_.ExpectAsyncTaskScheduled(2);
+  hooks_.ExpectAsyncTaskCanceled(2);
+  hooks_.ExpectAsyncTaskStarted(2);
+  hooks_.ExpectAsyncTaskFinished(2);
+
+  mock_timer_callback_.ExpectRunCall(2);
+  timers_->SetTimeout(callback_, kTimerDelayInMilliseconds);
+  timers_->SetTimeout(callback_, kTimerDelayInMilliseconds * 3);
+
+  dom_stat_tracker_.FlushPeriodicTracking();
+  EXPECT_EQ("0", base::CValManager::GetInstance()
+                     ->GetValueAsString(
+                         "Count.WindowTimersTest.DOM.WindowTimers.Interval")
+                     .value_or("Foo"));
+  EXPECT_EQ("2", base::CValManager::GetInstance()
+                     ->GetValueAsString(
+                         "Count.WindowTimersTest.DOM.WindowTimers.Timeout")
+                     .value_or("Foo"));
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 2);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+
+  FastForwardBy(
+      base::TimeDelta::FromMilliseconds(3 * kTimerDelayInMilliseconds));
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 0);
+
+  dom_stat_tracker_.FlushPeriodicTracking();
+  EXPECT_EQ("0", base::CValManager::GetInstance()
+                     ->GetValueAsString(
+                         "Count.WindowTimersTest.DOM.WindowTimers.Interval")
+                     .value_or("Foo"));
+  EXPECT_EQ("0", base::CValManager::GetInstance()
+                     ->GetValueAsString(
+                         "Count.WindowTimersTest.DOM.WindowTimers.Timeout")
+                     .value_or("Foo"));
+}
+
+TEST_F(WindowTimersTest, IntervalZeroTaskIsScheduledImmediately) {
+  hooks_.ExpectAsyncTaskScheduled(1);
+  hooks_.ExpectAsyncTaskCanceled(1);
+
+  timers_->SetInterval(callback_, 0);
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(0));
+
+  // Note: We can't use RunUntilIdle() or FastForwardBy() in this case,
+  // because the task queue never gets idle.
+}
+
+TEST_F(WindowTimersTest, IntervalIsNotCalledBeforeDelay) {
+  hooks_.ExpectAsyncTaskScheduled(1);
+  hooks_.ExpectAsyncTaskCanceled(1);
+
+  hooks_.ExpectAsyncTaskStarted(0);
+  hooks_.ExpectAsyncTaskFinished(0);
+  mock_timer_callback_.ExpectRunCall(0);
+  timers_->SetInterval(callback_, kTimerDelayInMilliseconds);
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+
+  FastForwardBy(
+      base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds - 1));
+  RunUntilIdle();
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+}
+
+TEST_F(WindowTimersTest, IntervalIsCalledAfterDelay) {
+  hooks_.ExpectAsyncTaskScheduled(1);
+  hooks_.ExpectAsyncTaskCanceled(1);
+  hooks_.ExpectAsyncTaskStarted(1);
+  hooks_.ExpectAsyncTaskFinished(1);
+
+  mock_timer_callback_.ExpectRunCall(1);
+  timers_->SetInterval(callback_, kTimerDelayInMilliseconds);
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+
+  FastForwardBy(base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+  RunUntilIdle();
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+}
+
+TEST_F(WindowTimersTest, IntervalIsCalledRepeatedly) {
+  int interval_count = 10;
+
+  hooks_.ExpectAsyncTaskScheduled(1);
+  hooks_.ExpectAsyncTaskCanceled(1);
+  hooks_.ExpectAsyncTaskStarted(interval_count);
+  hooks_.ExpectAsyncTaskFinished(interval_count);
+
+  mock_timer_callback_.ExpectRunCall(interval_count);
+  timers_->SetInterval(callback_, kTimerDelayInMilliseconds);
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+
+  FastForwardBy(base::TimeDelta::FromMilliseconds(interval_count *
+                                                  kTimerDelayInMilliseconds));
+  RunUntilIdle();
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+}
+
+TEST_F(WindowTimersTest, IntervalDrifts) {
+  int interval_count = 10;
+
+  hooks_.ExpectAsyncTaskScheduled(1);
+  hooks_.ExpectAsyncTaskCanceled(1);
+  hooks_.ExpectAsyncTaskStarted(interval_count);
+  hooks_.ExpectAsyncTaskFinished(interval_count);
+
+  mock_timer_callback_.ExpectRunCall(interval_count);
+  timers_->SetInterval(callback_, kTimerDelayInMilliseconds);
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+
+  while (interval_count--) {
+    AdvanceMockTickClock(
+        base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds + 1000));
+    RunUntilIdle();
+  }
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 1);
+}
+
+TEST_F(WindowTimersTest, MultipleIntervals) {
+  hooks_.ExpectAsyncTaskScheduled(2);
+  hooks_.ExpectAsyncTaskCanceled(2);
+  hooks_.ExpectAsyncTaskStarted(4);
+  hooks_.ExpectAsyncTaskFinished(4);
+
+  mock_timer_callback_.ExpectRunCall(4);
+  timers_->SetInterval(callback_, kTimerDelayInMilliseconds);
+  timers_->SetInterval(callback_, kTimerDelayInMilliseconds * 3);
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 2);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+
+  FastForwardBy(
+      base::TimeDelta::FromMilliseconds(3 * kTimerDelayInMilliseconds));
+  RunUntilIdle();
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 2);
+}
+
+TEST_F(WindowTimersTest, ActiveIntervalsAreCounted) {
+  hooks_.ExpectAsyncTaskScheduled(2);
+  hooks_.ExpectAsyncTaskCanceled(2);
+  hooks_.ExpectAsyncTaskStarted(4);
+  hooks_.ExpectAsyncTaskFinished(4);
+
+  mock_timer_callback_.ExpectRunCall(4);
+  timers_->SetInterval(callback_, kTimerDelayInMilliseconds);
+  timers_->SetInterval(callback_, kTimerDelayInMilliseconds * 3);
+
+  dom_stat_tracker_.FlushPeriodicTracking();
+  EXPECT_EQ("2", base::CValManager::GetInstance()
+                     ->GetValueAsString(
+                         "Count.WindowTimersTest.DOM.WindowTimers.Interval")
+                     .value_or("Foo"));
+  EXPECT_EQ("0", base::CValManager::GetInstance()
+                     ->GetValueAsString(
+                         "Count.WindowTimersTest.DOM.WindowTimers.Timeout")
+                     .value_or("Foo"));
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 2);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+
+  FastForwardBy(
+      base::TimeDelta::FromMilliseconds(3 * kTimerDelayInMilliseconds));
+  RunUntilIdle();
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 2);
+
+  dom_stat_tracker_.FlushPeriodicTracking();
+  EXPECT_EQ("2", base::CValManager::GetInstance()
+                     ->GetValueAsString(
+                         "Count.WindowTimersTest.DOM.WindowTimers.Interval")
+                     .value_or("Foo"));
+  EXPECT_EQ("0", base::CValManager::GetInstance()
+                     ->GetValueAsString(
+                         "Count.WindowTimersTest.DOM.WindowTimers.Timeout")
+                     .value_or("Foo"));
+}
+
+TEST_F(WindowTimersTest, ActiveIntervalsAndTimeoutsAreCounted) {
+  hooks_.ExpectAsyncTaskScheduled(4);
+  hooks_.ExpectAsyncTaskCanceled(4);
+  hooks_.ExpectAsyncTaskStarted(6);
+  hooks_.ExpectAsyncTaskFinished(6);
+
+  mock_timer_callback_.ExpectRunCall(6);
+  timers_->SetInterval(callback_, kTimerDelayInMilliseconds);
+  timers_->SetInterval(callback_, kTimerDelayInMilliseconds * 3);
+  timers_->SetTimeout(callback_, kTimerDelayInMilliseconds);
+  timers_->SetTimeout(callback_, kTimerDelayInMilliseconds * 3);
+
+  dom_stat_tracker_.FlushPeriodicTracking();
+  EXPECT_EQ("2", base::CValManager::GetInstance()
+                     ->GetValueAsString(
+                         "Count.WindowTimersTest.DOM.WindowTimers.Interval")
+                     .value_or("Foo"));
+  EXPECT_EQ("2", base::CValManager::GetInstance()
+                     ->GetValueAsString(
+                         "Count.WindowTimersTest.DOM.WindowTimers.Timeout")
+                     .value_or("Foo"));
+
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 4);
+  EXPECT_EQ(NextMainThreadPendingTaskDelay(),
+            base::TimeDelta::FromMilliseconds(kTimerDelayInMilliseconds));
+
+  FastForwardBy(
+      base::TimeDelta::FromMilliseconds(3 * kTimerDelayInMilliseconds));
+  RunUntilIdle();
+  EXPECT_EQ(GetPendingMainThreadTaskCount(), 2);
+
+  dom_stat_tracker_.FlushPeriodicTracking();
+  EXPECT_EQ("2", base::CValManager::GetInstance()
+                     ->GetValueAsString(
+                         "Count.WindowTimersTest.DOM.WindowTimers.Interval")
+                     .value_or("Foo"));
+  EXPECT_EQ("0", base::CValManager::GetInstance()
+                     ->GetValueAsString(
+                         "Count.WindowTimersTest.DOM.WindowTimers.Timeout")
+                     .value_or("Foo"));
+}
+
+
+}  // namespace dom
+}  // namespace cobalt
diff --git a/src/cobalt/h5vcc/dial/dial_http_response.cc b/src/cobalt/h5vcc/dial/dial_http_response.cc
index 6531a3e..3fcd329 100644
--- a/src/cobalt/h5vcc/dial/dial_http_response.cc
+++ b/src/cobalt/h5vcc/dial/dial_http_response.cc
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include <memory>
+#include <utility>
 
 #include "cobalt/h5vcc/dial/dial_http_response.h"
 
@@ -24,7 +25,7 @@
 namespace dial {
 DialHttpResponse::DialHttpResponse(const std::string& path,
                                    const std::string& method)
-    : path_(path), method_(method), response_code_(0) {}
+    : path_(path), method_(method), response_code_(500) {}
 
 void DialHttpResponse::AddHeader(const std::string& header,
                                  const std::string& value) {
diff --git a/src/cobalt/input/camera_3d.h b/src/cobalt/input/camera_3d.h
index d282e4d..3fa1fb2 100644
--- a/src/cobalt/input/camera_3d.h
+++ b/src/cobalt/input/camera_3d.h
@@ -70,6 +70,9 @@
   // Resets camera to default orientation.
   virtual void Reset() {}
 
+  // Adopt input object from the given Camera3D.
+  virtual void SetInput(const scoped_refptr<Camera3D>& other) {}
+
   virtual ~Camera3D() {}
 
   template <typename FloatType>
diff --git a/src/cobalt/input/camera_3d_input_poller.cc b/src/cobalt/input/camera_3d_input_poller.cc
index 2101015..5b7a53c 100644
--- a/src/cobalt/input/camera_3d_input_poller.cc
+++ b/src/cobalt/input/camera_3d_input_poller.cc
@@ -19,6 +19,7 @@
 #include <algorithm>
 #include <cmath>
 
+#include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/input/create_default_camera_3d.h"
 #include "third_party/glm/glm/gtc/matrix_transform.hpp"
 #include "third_party/glm/glm/gtc/quaternion.hpp"
@@ -91,6 +92,13 @@
   yaw_in_radians_ = 0.0f;
 }
 
+void Camera3DInputPoller::SetInput(const scoped_refptr<Camera3D>& other) {
+  base::AutoLock lock(mutex_);
+  Camera3DInputPoller* other_camera =
+      base::polymorphic_downcast<Camera3DInputPoller*>(other.get());
+  input_poller_ = other_camera ? other_camera->input_poller_ : nullptr;
+}
+
 void Camera3DInputPoller::AccumulateOrientation() {
   if (!input_poller_) {
     // Nothing to do if no input poller was provided.
diff --git a/src/cobalt/input/camera_3d_input_poller.h b/src/cobalt/input/camera_3d_input_poller.h
index ceff058..c6050ab 100644
--- a/src/cobalt/input/camera_3d_input_poller.h
+++ b/src/cobalt/input/camera_3d_input_poller.h
@@ -52,6 +52,8 @@
 
   void Reset() override;
 
+  void SetInput(const scoped_refptr<Camera3D>& other) override;
+
  private:
   struct KeycodeMappingInfo {
     KeycodeMappingInfo() : axis(0), degrees_per_second(0.0f) {}
diff --git a/src/cobalt/layout_tests/testdata/css3-fonts/4-5-prefer-later-face-with-close-style-over-earlier-face-with-unicode-range.html b/src/cobalt/layout_tests/testdata/css3-fonts/4-5-prefer-later-face-with-close-style-over-earlier-face-with-unicode-range.html
index c257b7e..dfb03e2 100644
--- a/src/cobalt/layout_tests/testdata/css3-fonts/4-5-prefer-later-face-with-close-style-over-earlier-face-with-unicode-range.html
+++ b/src/cobalt/layout_tests/testdata/css3-fonts/4-5-prefer-later-face-with-close-style-over-earlier-face-with-unicode-range.html
@@ -34,4 +34,4 @@
 <body>
     <div>Hello</div>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/src/cobalt/layout_tests/testdata/css3-fonts/4-5-use-correct-font-with-unicode-range.html b/src/cobalt/layout_tests/testdata/css3-fonts/4-5-use-correct-font-with-unicode-range.html
index f4f2cbd..854e6b7 100644
--- a/src/cobalt/layout_tests/testdata/css3-fonts/4-5-use-correct-font-with-unicode-range.html
+++ b/src/cobalt/layout_tests/testdata/css3-fonts/4-5-use-correct-font-with-unicode-range.html
@@ -34,4 +34,4 @@
 <body>
     <div>Me & You = Us</div>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/src/cobalt/layout_tests/web_platform_tests.cc b/src/cobalt/layout_tests/web_platform_tests.cc
index 5edd114..be7348d 100644
--- a/src/cobalt/layout_tests/web_platform_tests.cc
+++ b/src/cobalt/layout_tests/web_platform_tests.cc
@@ -79,6 +79,15 @@
   }
 };
 
+// FakeResourceProviderStub has the identical behavior as ResourceProviderStub,
+// except the GetTypeId, which makes the ImageDecode not to create the
+// FailureImageDecoder based on the TypeId Check.
+class FakeResourceProviderStub : public render_tree::ResourceProviderStub {
+  base::TypeId GetTypeId() const override {
+    return base::GetTypeId<FakeResourceProviderStub>();
+  }
+};
+
 // Match the enums from testharness.js.
 enum TestStatus {
   kPass = 0,
@@ -190,7 +199,7 @@
   network::NetworkModule network_module(net_options);
 
   // Media module
-  render_tree::ResourceProviderStub resource_provider;
+  FakeResourceProviderStub resource_provider;
   std::unique_ptr<media::MediaModule> media_module(
       new media::MediaModule(NULL, &resource_provider));
   std::unique_ptr<media::CanPlayTypeHandler> can_play_type_handler(
diff --git a/src/cobalt/loader/image/image_decoder.cc b/src/cobalt/loader/image/image_decoder.cc
index 68782a3..be9856e 100644
--- a/src/cobalt/loader/image/image_decoder.cc
+++ b/src/cobalt/loader/image/image_decoder.cc
@@ -56,6 +56,9 @@
 
 // Returns true if the ResourceProvider is ResourceProviderStub.
 bool IsResourceProviderStub(render_tree::ResourceProvider* resource_provider) {
+  if (resource_provider == nullptr) {
+    return true;
+  }
   return resource_provider->GetTypeId() ==
          base::GetTypeId<render_tree::ResourceProviderStub>();
 }
@@ -108,6 +111,7 @@
       state_(resource_provider_ ? kWaitingForHeader : kSuspended),
       is_deletion_pending_(false) {
   signature_cache_.position = 0;
+  use_failure_image_decoder_ = IsResourceProviderStub(resource_provider);
 }
 
 ImageDecoder::ImageDecoder(
@@ -124,6 +128,7 @@
       state_(resource_provider_ ? kWaitingForHeader : kSuspended),
       is_deletion_pending_(false) {
   signature_cache_.position = 0;
+  use_failure_image_decoder_ = IsResourceProviderStub(resource_provider);
 }
 
 LoadResponseType ImageDecoder::OnResponseStarted(
@@ -241,11 +246,7 @@
   DCHECK_EQ(state_, kSuspended);
   DCHECK(!resource_provider_);
   DCHECK(resource_provider);
-  if (IsResourceProviderStub(resource_provider)) {
-    use_failure_image_decoder_ = true;
-  } else {
-    use_failure_image_decoder_ = false;
-  }
+  use_failure_image_decoder_ = IsResourceProviderStub(resource_provider);
   state_ = kWaitingForHeader;
   resource_provider_ = resource_provider;
 }
diff --git a/src/cobalt/loader/image/image_decoder_test.cc b/src/cobalt/loader/image/image_decoder_test.cc
index 6ccf613..b893b23 100644
--- a/src/cobalt/loader/image/image_decoder_test.cc
+++ b/src/cobalt/loader/image/image_decoder_test.cc
@@ -149,13 +149,25 @@
 
   return CheckSameColor(pixels, size.width(), size.height(), test_color);
 }
+
+// FakeResourceProviderStub has the identical behavior as ResourceProviderStub,
+// except the GetTypeId, which makes the ImageDecode not to create the
+// FailureImageDecoder based on the TypeId Check.
+class FakeResourceProviderStub : public render_tree::ResourceProviderStub {
+  base::TypeId GetTypeId() const override {
+    return base::GetTypeId<FakeResourceProviderStub>();
+  }
+};
+
 }  // namespace
 
 // TODO: Test special images like the image has gAMA chunk information,
 // pngs with 16 bit depth, and large pngs.
 
 TEST(ImageDecoderTest, DecodeImageWithContentLength0) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(
       std::string("No content returned, but expected some."));
 
@@ -179,7 +191,9 @@
 }
 
 TEST(ImageDecoderTest, DecodeNonImageTypeWithContentLength0) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(std::string(
       "No content returned, but expected some. Not an image mime type."));
 
@@ -203,7 +217,9 @@
 }
 
 TEST(ImageDecoderTest, DecodeNonImageType) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(std::string("Not an image mime type."));
 
   const char kHTMLHeaders[] = {
@@ -228,7 +244,9 @@
 }
 
 TEST(ImageDecoderTest, DecodeNoContentType) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(std::string("Not an image mime type."));
 
   const char kHTMLHeaders[] = {
@@ -252,7 +270,9 @@
 }
 
 TEST(ImageDecoderTest, DecodeImageWithNoContent) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(
       std::string("No content returned. Not an image mime type."));
 
@@ -276,7 +296,9 @@
 }
 
 TEST(ImageDecoderTest, DecodeImageWithLessThanHeaderBytes) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(
       std::string("No enough image data for header."));
 
@@ -288,7 +310,9 @@
 }
 
 TEST(ImageDecoderTest, FailedToDecodeImage) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(
       std::string("PNGImageDecoder failed to decode image."));
 
@@ -302,7 +326,9 @@
 }
 
 TEST(ImageDecoderTest, UnsupportedImageFormat) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(std::string("Unsupported image format."));
 
   const char kPartialICOImage[] = {
@@ -315,7 +341,9 @@
 
 // Test that we can properly decode the PNG image.
 TEST(ImageDecoderTest, DecodePNGImage) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(base::nullopt);
 
   std::vector<uint8> image_data =
@@ -349,7 +377,9 @@
 
 // Test that we can properly decode the PNG image with multiple chunks.
 TEST(ImageDecoderTest, DecodePNGImageWithMultipleChunks) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(base::nullopt);
 
   std::vector<uint8> image_data =
@@ -387,7 +417,9 @@
 
 // Test that we can properly decode the the interlaced PNG.
 TEST(ImageDecoderTest, DecodeInterlacedPNGImage) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(base::nullopt);
 
   std::vector<uint8> image_data =
@@ -421,7 +453,9 @@
 
 // Test that we can properly decode the interlaced PNG with multiple chunks.
 TEST(ImageDecoderTest, DecodeInterlacedPNGImageWithMultipleChunks) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(base::nullopt);
 
   std::vector<uint8> image_data =
@@ -459,7 +493,9 @@
 
 // Test that we can properly decode the JPEG image.
 TEST(ImageDecoderTest, DecodeJPEGImage) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(base::nullopt);
 
   std::vector<uint8> image_data =
@@ -485,7 +521,9 @@
 
 // Test that we can properly decode the JPEG image with multiple chunks.
 TEST(ImageDecoderTest, DecodeJPEGImageWithMultipleChunks) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(base::nullopt);
 
   std::vector<uint8> image_data =
@@ -515,7 +553,9 @@
 
 // Test that we can properly decode the progressive JPEG image.
 TEST(ImageDecoderTest, DecodeProgressiveJPEGImage) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(base::nullopt);
 
   std::vector<uint8> image_data =
@@ -542,7 +582,9 @@
 
 // Test that we can properly decode the progressive JPEG with multiple chunks.
 TEST(ImageDecoderTest, DecodeProgressiveJPEGImageWithMultipleChunks) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(base::nullopt);
 
   std::vector<uint8> image_data =
@@ -573,7 +615,7 @@
 // Test that we can properly decode the progressive JPEG image while forcing the
 // output to be single plane.
 TEST(ImageDecoderTest, DecodeProgressiveJPEGImageToSinglePlane) {
-  render_tree::ResourceProviderStub resource_provider;
+  FakeResourceProviderStub resource_provider;
   base::NullDebuggerHooks debugger_hooks;
   const bool kAllowImageDecodingToMultiPlane = false;
   JPEGImageDecoder jpeg_image_decoder(&resource_provider, debugger_hooks,
@@ -606,7 +648,7 @@
 // while forcing the output to be single plane.
 TEST(ImageDecoderTest,
      DecodeProgressiveJPEGImageWithMultipleChunksToSinglePlane) {
-  render_tree::ResourceProviderStub resource_provider;
+  FakeResourceProviderStub resource_provider;
   base::NullDebuggerHooks debugger_hooks;
   const bool kAllowImageDecodingToMultiPlane = false;
   JPEGImageDecoder jpeg_image_decoder(&resource_provider, debugger_hooks,
@@ -641,7 +683,9 @@
 
 // Test that we can properly decode the WEBP image.
 TEST(ImageDecoderTest, DecodeWEBPImage) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(base::nullopt);
 
   std::vector<uint8> image_data =
@@ -674,7 +718,9 @@
 
 // Test that we can properly decode the WEBP image with multiple chunks.
 TEST(ImageDecoderTest, DecodeWEBPImageWithMultipleChunks) {
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(base::nullopt);
 
   std::vector<uint8> image_data =
@@ -713,7 +759,9 @@
   base::Thread thread("AnimatedWebP");
   thread.Start();
 
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(base::nullopt);
 
   std::vector<uint8> image_data =
@@ -742,7 +790,9 @@
   base::Thread thread("AnimatedWebP");
   thread.Start();
 
-  MockImageDecoder image_decoder;
+  std::unique_ptr<FakeResourceProviderStub> resource_provider(
+      new FakeResourceProviderStub());
+  MockImageDecoder image_decoder(resource_provider.get());
   image_decoder.ExpectCallWithError(base::nullopt);
 
   std::vector<uint8> image_data =
diff --git a/src/cobalt/media/base/sbplayer_pipeline.cc b/src/cobalt/media/base/sbplayer_pipeline.cc
index 5a9b541..7e5bb2b 100644
--- a/src/cobalt/media/base/sbplayer_pipeline.cc
+++ b/src/cobalt/media/base/sbplayer_pipeline.cc
@@ -544,6 +544,11 @@
   error_cb_.Reset();
   if (demuxer_) {
     stop_cb_ = stop_cb;
+    {
+      base::AutoLock auto_lock(lock_);
+      audio_stream_ = nullptr;
+      video_stream_ = nullptr;
+    }
     demuxer_->Stop();
     OnDemuxerStopped();
   } else {
diff --git a/src/cobalt/media_session/media_session_client.cc b/src/cobalt/media_session/media_session_client.cc
index 7dd8853..a5a2c3c 100644
--- a/src/cobalt/media_session/media_session_client.cc
+++ b/src/cobalt/media_session/media_session_client.cc
@@ -34,7 +34,8 @@
 const base::TimeDelta kUpdateDelay = base::TimeDelta::FromMilliseconds(250);
 
 // Delay to check if the media session state is not active.
-const base::TimeDelta kMaybeFreezeDelay = base::TimeDelta::FromMilliseconds(1500);
+const base::TimeDelta kMaybeFreezeDelay =
+    base::TimeDelta::FromMilliseconds(1500);
 
 // Guess the media position state for the media session.
 void GuessMediaPositionState(MediaSessionState* session_state,
@@ -75,8 +76,7 @@
   extension_ = static_cast<const CobaltExtensionMediaSessionApi*>(
       SbSystemGetExtension(kCobaltExtensionMediaSessionName));
   if (extension_) {
-    if (strcmp(extension_->name,
-                           kCobaltExtensionMediaSessionName) != 0 ||
+    if (strcmp(extension_->name, kCobaltExtensionMediaSessionName) != 0 ||
         extension_->version < 1) {
       LOG(WARNING) << "Wrong MediaSession extension supplied";
       extension_ = nullptr;
@@ -176,12 +176,11 @@
 }
 
 void MediaSessionClient::PostDelayedTaskForMaybeFreezeCallback() {
-  if (is_active()) return;
-
   media_session_->task_runner_->PostDelayedTask(
-      FROM_HERE, base::Bind(&MediaSessionClient::RunMaybeFreezeCallback,
-                            base::Unretained(this), ++sequence_number_),
-                            kMaybeFreezeDelay);
+      FROM_HERE,
+      base::Bind(&MediaSessionClient::RunMaybeFreezeCallback,
+                 base::Unretained(this), ++sequence_number_),
+      kMaybeFreezeDelay);
 }
 
 void MediaSessionClient::UpdatePlatformPlaybackState(
diff --git a/src/cobalt/renderer/pipeline.cc b/src/cobalt/renderer/pipeline.cc
index bb9954c..c49e72d 100644
--- a/src/cobalt/renderer/pipeline.cc
+++ b/src/cobalt/renderer/pipeline.cc
@@ -26,10 +26,9 @@
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/extension/graphics.h"
 #include "cobalt/math/rect_f.h"
-#include "cobalt/render_tree/brush.h"
+#include "cobalt/render_tree/clear_rect_node.h"
 #include "cobalt/render_tree/composition_node.h"
 #include "cobalt/render_tree/dump_render_tree_to_string.h"
-#include "cobalt/render_tree/rect_node.h"
 #include "nb/memory_scope.h"
 #include "starboard/system.h"
 
@@ -66,7 +65,7 @@
 // How many entries the rasterize periodic timer will contain before updating.
 const size_t kRasterizePeriodicTimerEntriesPerUpdate = 60;
 
-// The maximum numer of entries that the rasterize animations timer can contain
+// The maximum number of entries that the rasterize animations timer can contain
 // before automatically updating. In the typical use case, the update will
 // occur manually when the animations expire.
 const size_t kRasterizeAnimationsTimerMaxEntries = 60;
@@ -658,11 +657,10 @@
   render_tree::ColorRGBA clear_color;
   if (render_target_ && clear_on_shutdown_mode_ == kClearAccordingToPlatform &&
       ShouldClearFrameOnShutdown(&clear_color)) {
-    rasterizer_->Submit(new render_tree::RectNode(
-                            math::RectF(render_target_->GetSize()),
-                            std::unique_ptr<render_tree::Brush>(
-                                new render_tree::SolidColorBrush(clear_color))),
-                        render_target_);
+    rasterizer_->Submit(
+        new render_tree::ClearRectNode(math::RectF(render_target_->GetSize()),
+                                       clear_color),
+        render_target_);
   }
 
   // This potential reference to a render tree whose animations may have ended
diff --git a/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
index 5fbc26e..8f4ee7d 100644
--- a/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
@@ -602,6 +602,11 @@
     }
   } else {
     texcoord_transform = data.local_transform.Inverse();
+
+    if (texcoord_transform.IsZeros()) {
+      DLOG(ERROR) << "data.local_transform is a non invertible matrix.";
+      return;
+    }
   }
 
   // Different shaders are used depending on whether the image has a single
diff --git a/src/cobalt/renderer/rasterizer/testdata/lottie_coverage/.gitignore b/src/cobalt/renderer/rasterizer/testdata/lottie_coverage/.gitignore
new file mode 100644
index 0000000..1b5748c
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/lottie_coverage/.gitignore
@@ -0,0 +1,2 @@
+*.json
+*.png
diff --git a/src/cobalt/site/docs/codelabs/cobalt_extensions/codelab.md b/src/cobalt/site/docs/codelabs/cobalt_extensions/codelab.md
new file mode 100644
index 0000000..8fc180c
--- /dev/null
+++ b/src/cobalt/site/docs/codelabs/cobalt_extensions/codelab.md
@@ -0,0 +1,793 @@
+---
+layout: doc
+title: "Cobalt Extensions codelab"
+---
+
+The Cobalt Extension framework provides a way to add optional, platform-specific
+features to the Cobalt application. A Cobalt Extension is an optional interface
+that porters can implement for their platforms if, and as, they wish.
+
+This tutorial uses coding exercises to guide you through the process of creating
+a simple example of a Cobalt Extension. By the end you should have a firm
+understanding of what Cobalt Extensions are, when to use them instead of
+alternatives, how to write them, and how to work with the Cobalt team to
+contribute them to the repository.
+
+## Prerequisites
+
+Because it's helpful to build and run Cobalt during the exercises, you'll first
+want to set up your environment and make sure you can build Cobalt. You can
+follow <a href="/development/setup-linux.html">Set up your environment -
+Linux</a> to do this if you're a Linux user. Please note that the exercise
+solutions assume you're using Linux but should be comparable to implementations
+for other platforms.
+
+Also note that while this codelab doesn't require it, you'll need to
+<a href="/starboard/porting.html">Port Cobalt to your platform</a> before you
+can actually use a Cobalt Extension to customize it for your platform.
+
+Finally, the exercises assume the ability to program in C and C++.
+
+### Exercise 0: Run Cobalt and inspect logs
+
+Assuming you've already built Cobalt, please now run Cobalt and pay special
+attention to a message it logs when it starts up. This message will be the focus
+of subsequent exercises.
+
+```
+$ out/linux-x64x11_debug/cobalt 2>/dev/null | grep "Starting application"
+```
+
+## Background
+
+Situated below Cobalt is Starboard. Starboard, which is a porting layer and OS
+abstraction, contains a minimal set of APIs to encapsulate the platform-specific
+functionalities that Cobalt uses. Each Starboard module (memory, socket, thread,
+etc.) defines functions that must be implemented on a porter's platform,
+imposing an implementation and maintenance cost on all porters. With this cost
+in mind the Cobalt team tries to keep the Starboard APIs stable and only adds a
+new API **when some functionality is required by Cobalt but the implementation
+depends on the platform**.
+
+A Starboard API can be made optional, though, by the introduction of an
+accompanying API that asks platforms whether they support the underlying feature
+and enables Cobalt to check for the answer at runtime. For example,
+`SbWindowOnScreenKeyboardIsSupported` is used so that only platforms that
+support an on screen keyboard need implement the related functions in
+`starboard/window.h`. To spare porters uninterested in the functionality, the
+Cobalt team chooses to make a Starboard API optional **when some Cobalt
+functionality is optional and the implementation is platform-dependent**.
+
+Finally, a nonobvious point explains why even an optional Starboard API may
+sometimes be too cumbersome: other applications beyond Cobalt are able to be run
+on top of Starboard. If a feature is needed by Cobalt but not by all Starboard-
+based applications or by Starboard itself, adding a Starboard API for it may add
+unnecessary size and complexity to the porting layer. **And here we arrive at
+the sweet spot for Cobalt Extensions: when the desired functionality is
+Cobalt-specific, optional in Cobalt, and has platform-dependent
+implementation.** Also, because Cobalt Extensions are lightweight and, as you'll
+see below, added without any changes to the Starboard layer, they're the
+preferred way for porters to add new, custom features to Cobalt.
+
+To summarize:
+
+<table>
+  <tr>
+    <th colspan="1">Tool</th>
+    <th colspan="1">Use case</th>
+    <th colspan="1">Ecosystem cost</th>
+  </tr>
+  <tr>
+    <td>Starboard API</td>
+    <td>Feature is <strong>required</strong> but implementation is
+    platform-dependent</td>
+    <td>High</td>
+  </tr>
+  <tr>
+    <td>Optional Starboard API</td>
+    <td>Feature is <strong>optional</strong> and implementation is
+    platform-dependent</td>
+    <td>Medium</td>
+  </tr>
+  <tr>
+    <td>Cobalt Extension</td>
+    <td>Feature is <strong>optional and specific to Cobalt</strong> and
+    implementation is platform-dependent</td>
+    <td>Low</td>
+  </tr>
+</table>
+
+As a caveat, please note that for all three of these abstractions the interface
+is in Cobalt's open-source repository and therefore visible to other porters.
+The implementation, on the other hand, is written and built by porters and so
+may be kept private.
+
+Finally, in addition to the alternatives mentioned, porters have in some cases
+made local changes to Cobalt, above the Starboard layer, to achieve some
+customization or optimization. This has been discouraged by the Cobalt team
+because it makes rebasing to future versions of Cobalt more difficult but has
+been possible because porters have historically built **both** Cobalt and
+Starboard. However, Cobalt is moving toward Evergreen
+(<a href="https://cobalt.googlesource.com/cobalt/+/refs/heads/master/src/starboard/doc/evergreen/cobalt_evergreen_overview.md">overview</a>),
+an architecture that enables automatic Cobalt updates on devices by separating a
+Google-built, Cobalt core shared library from the partner-built Starboard layer
+and Cobalt loader app. Because Cobalt core code is built by Google, custom
+changes to it are no longer possible for partners using Evergreen.
+
+## Anatomy of a Cobalt Extension
+
+### Extension structures
+
+Cobalt uses a structure to describe the interface for an extension and organizes
+the structures in headers under `cobalt/extension/`. The header for a "foo"
+extension should be named `foo.h` and the first version of it should contain the
+following content, as well as any additional members that provide the "foo"
+functionality.
+
+```
+#ifndef COBALT_EXTENSION_FOO_H_
+#define COBALT_EXTENSION_FOO_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define kCobaltExtensionFooName "dev.cobalt.extension.Foo"
+
+typedef struct CobaltExtensionFooApi {
+  // Name should be the string |kCobaltExtensionFooName|.
+  // This helps to validate that the extension API is correct.
+  const char* name;
+
+  // This specifies the version of the API that is implemented.
+  uint32_t version;
+
+  // The fields below this point were added in version 1 or later.
+
+} CobaltExtensionFooApi;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // COBALT_EXTENSION_FOO_H_
+```
+
+Please note a few important points about this structure:
+
+*   The first two members must be, in order:
+    *   A `const char* |name|`, storing the extension's name.
+    *   A `uint32_t |version|`, storing the version number of the extension.
+        Extension versioning is discussed later on in this codelab.
+*   The following members can be any C types (including custom structures) that
+    are useful. Often, these are function pointers.
+
+### Extension access in Cobalt
+
+The `SbSystemGetExtension` function from Starboard's `system` module allows
+Cobalt to query for an extension by name. It returns a pointer to the constant,
+global instance of the structure implementing the extension with the given name
+if it exists, otherwise `NULL`. This function is the only mechanism Cobalt has
+to get an extension; the Starboard interface intentionally doesn't have any
+functions related to the specific extensions.
+
+The caller in Cobalt must static cast the `const void*` returned by
+`SbSystemGetExtension` to a `const CobaltExtensionFooApi*`, or pointer of
+whatever type the extension structure type happens to be, before using it. Since
+the caller can't be sure whether a platform implements the extension or, if it
+does, implements it correctly, it's good defensive programming to check that the
+resulting pointer is not `NULL` and that the `name` member in the pointed-to
+structure has the same value as `kCobaltExtensionFooName`.
+
+### Extension implementation
+
+Because Cobalt Extensions are platform-dependent, the implementations of an
+extension belong in Starboard ports. A Starboard port implements an extension by
+defining a constant, global instance of the structure and implementing the
+`SbSystemGetExtension` function to return a pointer to it. For our "foo"
+extension, an implementation for `custom_platform`'s Starboard port could look
+as follows.
+
+`starboard/custom_platform/foo.h` declares a `GetFooApi` accessor for the
+structure instance.
+
+```
+#ifndef STARBOARD_CUSTOM_PLATFORM_FOO_H_
+#define STARBOARD_CUSTOM_PLATFORM_FOO_H_
+
+namespace starboard {
+namespace custom_platform {
+
+const void* GetFooApi();
+
+}  // namespace custom_platform
+}  // namespace starboard
+
+#endif  // STARBOARD_CUSTOM_PLATFORM_FOO_H_
+```
+
+`starboard/custom_platform/foo.cc`, then, defines `GetFooApi`.
+
+```
+#include "starboard/custom_platform/foo.h"
+
+#include "cobalt/extension/foo.h"
+
+namespace starboard {
+namespace custom_platform {
+
+namespace {
+
+// Definitions of any functions included as components in the extension
+// are added here.
+
+const CobaltExtensionFooApi kFooApi = {
+    kCobaltExtensionFooName,
+    1,  // API version that's implemented.
+    // Any additional members are initialized here.
+};
+
+}  // namespace
+
+const void* GetFooApi() {
+  return &kFooApi;
+}
+
+}  // namespace custom_platform
+}  // namespace starboard
+```
+
+Finally, `starboard/custom_platform/system_get_extension.cc` defines
+`SbSystemGetExtension` to wire up the extensions for the platform.
+
+```
+#include "starboard/system.h"
+
+#include "cobalt/extension/foo.h"
+#include "starboard/common/string.h"
+#include "starboard/custom_platform/foo.h"
+
+const void* SbSystemGetExtension(const char* name) {
+  if (strcmp(name, kCobaltExtensionFooName) == 0) {
+    return starboard::custom_platform::GetFooApi();
+  }
+  // Other conditions here should handle other implemented extensions.
+
+  return NULL;
+}
+```
+
+Please feel free to browse existing extension implementations in the repository.
+For example, the reference Raspberry Pi port implements the `Graphics` extension
+across the following files.
+
+*   `starboard/raspi/shared/graphics.h`
+*   `starboard/raspi/shared/graphics.cc`
+*   `starboard/raspi/shared/system_get_extensions.cc`
+
+### Exercise 1: Write and use your first extension
+
+Now that you've seen the anatomy of a Cobalt Extension it's your turn to write
+one of your own. In Exercise 0 we saw that Cobalt logs "Starting application"
+when it's started. Please write a `Pleasantry` Cobalt Extension that has a
+member of type `const char*` and name `greeting` and make any necessary changes
+in `cobalt/browser/main.cc` so that the extension can be used to log a custom
+greeting directly after the plain "Starting application." Implement the
+extension for Linux, or whichever other platform you'd like, and confirm that
+the greeting is logged.
+
+#### Solution to Exercise 1
+
+Click the items below to expand parts of a solution. The `git diff`s are between
+the solution and the `master` branch.
+
+<details>
+    <summary style="display:list-item">Contents of new
+    `cobalt/extension/pleasantry.h` file.</summary>
+
+```
+#ifndef COBALT_EXTENSION_PLEASANTRY_H_
+#define COBALT_EXTENSION_PLEASANTRY_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define kCobaltExtensionPleasantryName "dev.cobalt.extension.Pleasantry"
+
+typedef struct CobaltExtensionPleasantryApi {
+  // Name should be the string |kCobaltExtensionPleasantryName|.
+  // This helps to validate that the extension API is correct.
+  const char* name;
+
+  // This specifies the version of the API that is implemented.
+  uint32_t version;
+
+  // The fields below this point were added in version 1 or later.
+  const char* greeting;
+
+} CobaltExtensionPleasantryApi;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // COBALT_EXTENSION_PLEASANTRY_H_
+```
+
+</details>
+
+<details>
+    <summary style="display:list-item">Contents of new
+    `starboard/linux/shared/pleasantry.h` file.</summary>
+
+```
+#ifndef STARBOARD_LINUX_SHARED_PLEASANTRY_H_
+#define STARBOARD_LINUX_SHARED_PLEASANTRY_H_
+
+namespace starboard {
+namespace shared {
+
+const void* GetPleasantryApi();
+
+}  // namespace shared
+}  // namespace starboard
+
+#endif  // STARBOARD_LINUX_SHARED_PLEASANTRY_H_
+```
+
+</details>
+
+<details>
+    <summary style="display:list-item">Contents of new
+    `starboard/linux/shared/pleasantry.cc` file.</summary>
+
+```
+#include "starboard/linux/shared/pleasantry.h"
+
+#include "cobalt/extension/pleasantry.h"
+
+namespace starboard {
+namespace shared {
+
+namespace {
+
+const char *kGreeting = "Happy debugging!";
+
+const CobaltExtensionPleasantryApi kPleasantryApi = {
+    kCobaltExtensionPleasantryName,
+    1,
+    kGreeting,
+};
+
+}  // namespace
+
+const void* GetPleasantryApi() {
+  return &kPleasantryApi;
+}
+
+}  // namespace shared
+}  // namespace starboard
+```
+
+</details>
+
+<details>
+    <summary style="display:list-item">`git diff
+    starboard/linux/shared/starboard_platform.gypi`</summary>
+
+```
+@@ -38,6 +38,8 @@
+       '<(DEPTH)/starboard/linux/shared/netlink.cc',
+       '<(DEPTH)/starboard/linux/shared/netlink.h',
+       '<(DEPTH)/starboard/linux/shared/player_components_factory.cc',
++      '<(DEPTH)/starboard/linux/shared/pleasantry.cc',
++      '<(DEPTH)/starboard/linux/shared/pleasantry.h',
+       '<(DEPTH)/starboard/linux/shared/routes.cc',
+       '<(DEPTH)/starboard/linux/shared/routes.h',
+       '<(DEPTH)/starboard/linux/shared/system_get_connection_type.cc',
+```
+
+</details>
+
+<details>
+    <summary style="display:list-item">`git diff
+    starboard/linux/shared/system_get_extensions.cc`</summary>
+
+```
+@@ -16,12 +16,14 @@
+
+ #include "cobalt/extension/configuration.h"
+ #include "cobalt/extension/crash_handler.h"
++#include "cobalt/extension/pleasantry.h"
+ #include "starboard/common/string.h"
+ #include "starboard/shared/starboard/crash_handler.h"
+ #if SB_IS(EVERGREEN_COMPATIBLE)
+ #include "starboard/elf_loader/evergreen_config.h"
+ #endif
+ #include "starboard/linux/shared/configuration.h"
++#include "starboard/linux/shared/pleasantry.h"
+
+ const void* SbSystemGetExtension(const char* name) {
+ #if SB_IS(EVERGREEN_COMPATIBLE)
+@@ -41,5 +43,8 @@ const void* SbSystemGetExtension(const char* name) {
+   if (strcmp(name, kCobaltExtensionCrashHandlerName) == 0) {
+     return starboard::common::GetCrashHandlerApi();
+   }
++  if (strcmp(name, kCobaltExtensionPleasantryName) == 0) {
++    return starboard::shared::GetPleasantryApi();
++  }
+   return NULL;
+ }
+```
+
+</details>
+
+<details>
+    <summary style="display:list-item">`git diff cobalt/browser/main.cc`
+    </summary>
+
+```
+@@ -18,7 +18,9 @@
+ #include "cobalt/base/wrap_main.h"
+ #include "cobalt/browser/application.h"
+ #include "cobalt/browser/switches.h"
++#include "cobalt/extension/pleasantry.h"
+ #include "cobalt/version.h"
++#include "starboard/system.h"
+
+ namespace {
+
+@@ -77,6 +79,14 @@ void StartApplication(int argc, char** argv, const char* link,
+     return;
+   }
+   LOG(INFO) << "Starting application.";
++  const CobaltExtensionPleasantryApi* pleasantry_extension =
++      static_cast<const CobaltExtensionPleasantryApi*>(
++          SbSystemGetExtension(kCobaltExtensionPleasantryName));
++  if (pleasantry_extension &&
++      strcmp(pleasantry_extension->name, kCobaltExtensionPleasantryName) == 0 &&
++      pleasantry_extension->version >= 1) {
++    LOG(INFO) << pleasantry_extension->greeting;
++  }
+ #if SB_API_VERSION >= 13
+   DCHECK(!g_application);
+   g_application = new cobalt::browser::Application(quit_closure,
+```
+
+</details>
+
+## Extension versioning
+
+Cobalt Extensions are themselves extensible, but care must be taken to ensure
+that the extension interface in Cobalt and implementation in a platform's port,
+which may be built separately, are consistent.
+
+The `version` member, which is always the second member in an extension
+structure, indicates which version of the interface the structure describes. In
+other words, a `version` of the extension structure corresponds to a specific,
+invariant list of members. By convention, the first version of a Cobalt
+Extension is version `1` (i.e., one-based indexing, not zero-based).
+
+A new version of the extension can be introduced in the structure declaration by
+adding additional members to the end of the declaration and adding a comment to
+delineate, e.g., "The fields below this point were added in version 2 or later."
+To maintain compatibility and enable Cobalt to correctly index into instances of
+the structure, it's important that members are always added at the end of the
+structure declaration and that members are never removed. If a member is
+deprecated in a later version, this fact should simply be noted with a comment
+in the structure declaration.
+
+To implement a new version of the extension, a platform's port should then set
+the `version` member to the appropriate value when creating the instance of the
+structure, and also initialize all members required for the version.
+
+Finally, any code in Cobalt that uses the extension should guard references to
+members with version checks.
+
+### Exercise 2: Version your extension
+
+Add a second version of the `Pleasantry` extension that enables porters to also
+log a polite farewell message when the Cobalt application is stopped. To allow
+platforms more flexibility, add the new `farewell` member as a pointer to a
+function that takes no parameters and returns a `const char*`. Update
+`cobalt/browser/main.cc` so that Cobalt, if the platform implements version 2 of
+this extension, replaces the "Stopping application." message with a polite
+farewell provided by the platform.
+
+To keep things interesting, have the platform's implementation pseudo-randomly
+return one of several messages. And, once you've made the changes, build Cobalt
+and run it a few times to confirm that the feature behaves as expected.
+
+#### Solution to Exercise 2
+
+Click the items below to expand parts of a solution. The `git diff` is between
+the solution and the `master` branch.
+
+<details>
+    <summary style="display:list-item">Updated contents of
+    `cobalt/extension/pleasantry.h`.</summary>
+
+```
+#ifndef COBALT_EXTENSION_PLEASANTRY_H_
+#define COBALT_EXTENSION_PLEASANTRY_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define kCobaltExtensionPleasantryName "dev.cobalt.extension.Pleasantry"
+
+typedef struct CobaltExtensionPleasantryApi {
+  // Name should be the string |kCobaltExtensionPleasantryName|.
+  // This helps to validate that the extension API is correct.
+  const char* name;
+
+  // This specifies the version of the API that is implemented.
+  uint32_t version;
+
+  // The fields below this point were added in version 1 or later.
+  const char* greeting;
+
+  // The fields below this point were added in version 2 or later.
+  const char* (*GetFarewell)();
+
+} CobaltExtensionPleasantryApi;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // COBALT_EXTENSION_PLEASANTRY_H_
+```
+
+</details>
+
+<details>
+    <summary style="display:list-item">Updated contents of
+    `starboard/linux/shared/pleasantry.cc`.</summary>
+
+```
+#include "starboard/linux/shared/pleasantry.h"
+
+#include <stdlib.h>
+
+#include "cobalt/extension/pleasantry.h"
+#include "starboard/system.h"
+#include "starboard/time.h"
+
+namespace starboard {
+namespace shared {
+
+namespace {
+
+const char* kGreeting = "Happy debugging!";
+
+const char* kFarewells[] = {
+  "Farewell",
+  "Take care",
+  "Thanks for running Cobalt",
+};
+
+const char* GetFarewell() {
+  srand (SbTimeGetNow());
+  int pseudo_random_index = rand() % SB_ARRAY_SIZE_INT(kFarewells);
+  return kFarewells[pseudo_random_index];
+}
+
+const CobaltExtensionPleasantryApi kPleasantryApi = {
+  kCobaltExtensionPleasantryName,
+  2,
+  kGreeting,
+  &GetFarewell,
+};
+
+}  // namespace
+
+const void* GetPleasantryApi() {
+  return &kPleasantryApi;
+}
+
+}  // namespace shared
+}  // namespace starboard
+```
+
+</details>
+
+<details>
+    <summary style="display:list-item">`git diff cobalt/browser/main.cc`
+    </summary>
+
+```
+@@ -18,7 +18,9 @@
+ #include "cobalt/base/wrap_main.h"
+ #include "cobalt/browser/application.h"
+ #include "cobalt/browser/switches.h"
++#include "cobalt/extension/pleasantry.h"
+ #include "cobalt/version.h"
++#include "starboard/system.h"
+
+ namespace {
+
+@@ -54,6 +56,14 @@ bool CheckForAndExecuteStartupSwitches() {
+   return g_is_startup_switch_set;
+ }
+
++// Get the Pleasantry extension if it's implemented.
++const CobaltExtensionPleasantryApi* GetPleasantryApi() {
++  static const CobaltExtensionPleasantryApi* pleasantry_extension =
++      static_cast<const CobaltExtensionPleasantryApi*>(
++          SbSystemGetExtension(kCobaltExtensionPleasantryName));
++  return pleasantry_extension;
++}
++
+ void PreloadApplication(int argc, char** argv, const char* link,
+                         const base::Closure& quit_closure,
+                         SbTimeMonotonic timestamp) {
+@@ -77,6 +87,12 @@ void StartApplication(int argc, char** argv, const char* link,
+     return;
+   }
+   LOG(INFO) << "Starting application.";
++  const CobaltExtensionPleasantryApi* pleasantry_extension = GetPleasantryApi();
++  if (pleasantry_extension &&
++      strcmp(pleasantry_extension->name, kCobaltExtensionPleasantryName) == 0 &&
++      pleasantry_extension->version >= 1) {
++    LOG(INFO) << pleasantry_extension->greeting;
++  }
+ #if SB_API_VERSION >= 13
+   DCHECK(!g_application);
+   g_application = new cobalt::browser::Application(quit_closure,
+@@ -96,7 +112,14 @@ void StartApplication(int argc, char** argv, const char* link,
+ }
+
+ void StopApplication() {
+-  LOG(INFO) << "Stopping application.";
++  const CobaltExtensionPleasantryApi* pleasantry_extension = GetPleasantryApi();
++  if (pleasantry_extension &&
++      strcmp(pleasantry_extension->name, kCobaltExtensionPleasantryName) == 0 &&
++      pleasantry_extension->version >= 2) {
++    LOG(INFO) << pleasantry_extension->GetFarewell();
++  } else {
++    LOG(INFO) << "Stopping application.";
++  }
+   delete g_application;
+   g_application = NULL;
+ }
+```
+
+</details>
+
+`starboard/linux/shared/pleasantry.h`,
+`starboard/linux/shared/starboard_platform.gypi`, and
+`starboard/linux/shared/system_get_extensions.cc` should be unchanged from the
+Exercise 1 solution.
+
+## Extension testing
+
+Each Cobalt Extension has a test in `cobalt/extension/extension_test.cc` that
+tests whether the extension is wired up correctly for the platform Cobalt
+happens to be built for.
+
+Since some platforms may not implement a particular extension, these tests begin
+by checking whether `SbSystemGetExtension` simply returns `NULL` for the
+extension's name. For our `foo` extension, the first few lines may contain the
+following.
+
+```
+TEST(ExtensionTest, Foo) {
+  typedef CobaltExtensionFooApi ExtensionApi;
+  const char* kExtensionName = kCobaltExtensionFooName;
+
+  const ExtensionApi* extension_api =
+      static_cast<const ExtensionApi*>(SbSystemGetExtension(kExtensionName));
+  if (!extension_api) {
+    return;
+  }
+
+  // Verifications about the global structure instance, if implemented.
+}
+```
+
+If `SbSystemGetExtension` does not return `NULL`, meaning the platform does
+implement the extension, the tests generally verify a few details about the
+structure:
+
+*   It has the expected name.
+*   Its version is in the range of possible versions for the extension.
+*   For whichever version is implemented, any members required for that version
+    are present.
+*   It's a singleton.
+
+### Exercise 3: Test your extension
+
+You guessed it! Add a test for your new extension to
+`cobalt/extension/extension_test.cc`.
+
+Once you've written your test you can execute it to confirm that it passes.
+`cobalt/extension/extension.gyp` configures an `extension_test` target to be
+built from our `extension_test.cc` source file. We can build that target for our
+platform and then run the executable to run the tests.
+
+```
+$ cobalt/build/gyp_cobalt linux-x64x11
+```
+
+```
+$ ninja -C out/linux-x64x11_devel all
+```
+
+```
+$ out/linux-x64x11_devel/extension_test
+```
+
+Tip: because the `extension_test` has type `<(gtest_target_type)`, we can use
+`--gtest_filter` to filter the tests that are run. For example, you can run just
+your newly added test with `--gtest_filter=ExtensionTest.Pleasantry`.
+
+#### Solution to Exercise 3
+
+<details>
+    <summary style="display:list-item">Click here to see a solution for the new
+    test.</summary>
+
+```
+TEST(ExtensionTest, Pleasantry) {
+  typedef CobaltExtensionPleasantryApi ExtensionApi;
+  const char* kExtensionName = kCobaltExtensionPleasantryName;
+
+  const ExtensionApi* extension_api =
+      static_cast<const ExtensionApi*>(SbSystemGetExtension(kExtensionName));
+  if (!extension_api) {
+    return;
+  }
+
+  EXPECT_STREQ(extension_api->name, kExtensionName);
+  EXPECT_GE(extension_api->version, 1u);
+  EXPECT_LE(extension_api->version, 2u);
+
+  EXPECT_NE(extension_api->greeting, nullptr);
+
+  if (extension_api->version >= 2) {
+    EXPECT_NE(extension_api->GetFarewell, nullptr);
+  }
+
+  const ExtensionApi* second_extension_api =
+      static_cast<const ExtensionApi*>(SbSystemGetExtension(kExtensionName));
+  EXPECT_EQ(second_extension_api, extension_api)
+      << "Extension struct should be a singleton";
+}
+```
+
+</details>
+
+You'll also want to include the header for the extension, i.e., `#include
+"cobalt/extension/pleasantry.h"`.
+
+## Contributing a Cobalt Extension
+
+Thanks for taking the time to complete the codelab!
+
+**If you'd like to contribute an actual Cobalt Extension to Cobalt in order to
+add some useful functionality for your platform, we encourage you to start a
+discussion with the Cobalt team before you begin coding.** To do so, please
+[file a feature request](https://issuetracker.google.com/issues/new?component=181120)
+for the extension and include the following information:
+
+*   The name of the Cobalt Extension.
+*   A description of the extension.
+*   Why a Cobalt Extension is the right tool, instead of some alternative.
+*   The fact that you'd like to contribute the extension (i.e., write the code)
+    rather than rely on the Cobalt team to prioritize, plan, and implement it.
+
+Please file this feature request with the appropriate priority and the Cobalt
+team will review the proposal accordingly. If the Cobalt team approves of the
+use case and design then a member of the team will assign the feature request
+back to you for implementation. At this point, please follow the
+<a href="/contributors/index.html">Contributing to Cobalt</a> guide to ensure
+your code is compliant and can be reviewed and submitted.
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/branching.md b/src/cobalt/site/docs/gen/cobalt/doc/branching.md
new file mode 100644
index 0000000..c3b9cd9
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/branching.md
@@ -0,0 +1,98 @@
+---
+layout: doc
+title: "Cobalt Branching"
+---
+# Cobalt Branching
+
+*(This document assumes you are already familiar
+with [Cobalt Versioning][versioning] practices.)*
+
+The Cobalt project uses git branches for two main purposes:
+
+  1. To solidify a release as it is hardened for production.
+  2. To isolate `master` branch developers from risky or disruptive work.
+
+
+## Release Branches
+
+A "Cobalt release" is an official, tested version of Cobalt that is intended to
+be deployable to production. We branch for releases to allow development to
+continue on the `master` branch while stabilizing and finalizing a set of sources
+for release.
+
+
+### Release Timeline
+
+  1. Feature work is done in the `master` branch.
+
+  2. Once all feature work is completed, a release branch is created. The branch
+     will be named "[[Feature Year](versioning.md#Feature-Year)].[[Purpose](versioning.md#Purpose)].[[Update Number](versioning.md#Update-Number)]+".
+     Note that while very similar to the structure of the Cobalt
+     [version](versioning.md), it features a `+` symbol at the end, indicating
+     that the branch may eventually contain multiple release updates,
+     all greater than or equal to the specified update number.  In particular, a
+     single branch may host multiple releases/updates. Should another release
+     branch be cut from master with a pre-existing (feature year, purpose)
+     pair, the new branch will have an update number equivalent to the most
+     recently released update number, plus one.  Note that we expect it to be
+     rare that we will need a branch other than the `1+` branch.
+
+     An example release branch name is `19.lts.1+`.
+
+     An RC announcement will be made to
+     [cobalt-dev@googlegroups.com][cobalt-dev].
+
+     Note that a release branch implies that code on that branch is being
+     stabilized, not that it is ready for release.  Versions of Cobalt that
+     are ready for release will have a dedicated `*.stable` branch pointing to
+     them, and will be discussed later.
+
+  3. As bugs are discovered and feedback received from partners, fixes will be
+     cherry-picked into the release candidate branch. These cherry-picks should
+     not be considered stable again until the `*.stable` branch is updated.
+
+  4. As time goes on, the number of cherry-picks will decrease in number and
+     scope.
+
+  5. Once a commit on the branch is deemed to be feature-complete and stable, it
+     will be tagged with the current [version](versioning.md) for that branch,
+     and the version will be incremented for all subsequent commits.  A special
+     branch that acts more like a "moving tag" named "[[Feature Year](versioning.md#Feature-Year)].[[Purpose](versioning.md#Purpose)].stable"
+     will be created to point to the newly released version.  Should a
+     subsequent update be made for the given feature year and purpose, the
+     `*.stable` branch will be updated to point to the newest update.
+
+     An example stable branch name is `19.lts.stable`.
+
+     Some example release tags are:
+      - `19.lts.1`
+      - `19.lts.2`
+      - `20.lts.1`
+
+     A release announcement will be made
+     to [cobalt-dev@googlegroups.com][cobalt-dev].
+
+
+## Work Branches
+
+If a set of work is deemed to be particularly risky or disruptive, or if a
+serious contributor wants a sandbox to prepare an extensive patch, a work branch
+may be created to facilitate such development.
+
+Work branch names are of the form `work_<topic>`, where `<topic>` is the purpose
+for which the branch was created. Work branches are generally in use by a
+specific and limited set of people, and may disappear at any time.
+
+
+## Older branching schemes
+
+Older branches have been following different branch naming schemes, and for
+a description of those schemes, the version of this branching.md file within
+those branches should be consulted.
+
+## Other Reading
+
+  * [Cobalt Versioning][versioning]
+
+[cobalt-dev]: https://groups.google.com/forum/#!forum/cobalt-dev "cobalt-dev@googlegroups.com"
+[versioning]: versioning.md "Cobalt Versioning"
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/clients_performance_guide.md b/src/cobalt/site/docs/gen/cobalt/doc/clients_performance_guide.md
new file mode 100644
index 0000000..bfed2e7
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/clients_performance_guide.md
@@ -0,0 +1,172 @@
+---
+layout: doc
+title: "Cobalt Clients Performance Guide"
+---
+# Cobalt Clients Performance Guide
+
+This document contains a list of hints and tricks for using web technologies
+that when employed will result in improved performance of Cobalt client apps.
+
+[TOC]
+
+## Avoid large opacity animations of DOM subtrees.
+
+Be careful when applying the CSS opacity property to DOM subtrees.  When
+applying opacity to a DOM leaf node, the renderer can usually easily render the
+single element the way it normally would, except with an opacity parameter set.
+When rendering a non-trivial multi-subnode DOM subtree though, in order for
+the results to appear correct, the renderer has no choice but to create an
+offscreen surface, render to that surface *without* opacity, and then finally
+render the offscreen surface onto the onscreen surface *with* the set opacity
+applied.
+
+For some examples, suppose we have the following CSS:
+
+```
+<head>
+  <style>
+    .rectangle {
+      position: absolute;
+      width: 100px;
+      height: 100px;
+    }
+    .red {
+      background-color: red;
+    }
+    .green {
+      background-color: green;
+      transform: translate(25px, 25px);
+    }
+    .blue {
+      background-color: blue;
+      transform: translate(50px, 50px);
+    }
+    .half-opacity {
+      opacity: 0.5;
+    }
+  </style>
+</head>
+```
+
+Then when applying opacity to a subtree of 3 cascading rectangles,
+```
+<body>
+  <div class="half-opacity">
+    <div class="rectangle red"></div>
+    <div class="rectangle green"></div>
+    <div class="rectangle blue"></div>
+  </div>
+</body>
+```
+the results will look like this:
+
+![Opacity applied to subtree](resources/clients_performance_guide/opacity_on_subtree.png)
+
+which requires the browser to produce an offscreen surface the size of all three
+rectangles, which can be expensive for performance and memory.
+
+For comparison, when opacity is applied to leaf nodes individually,
+```
+<body>
+  <div>
+    <div class="rectangle red half-opacity"></div>
+    <div class="rectangle green half-opacity"></div>
+    <div class="rectangle blue half-opacity"></div>
+  </div>
+</body>
+```
+the results will look like this:
+
+![Opacity to each element of subtree](resources/clients_performance_guide/opacity_on_individuals.png)
+
+which is less expensive because each rectangle can be rendered directly with
+the specified opacity value.
+
+The problem in the first case where opacity is applied to the subtree is that
+switching render targets to and from an offscreen surface is time consuming
+for both the CPU and GPU, and can on some platforms noticeably slow down
+performance, likely manifesting as a lower framerate in animations.  While it is
+possible that Cobalt may cache the result, it is not guaranteed, and may not be
+possible if the subtree is being animated.  Additionally, the offscreen surface
+will of course consume memory that wouldn't have been required otherwise.
+
+### Similar situations
+
+While opacity tends to be the most common instigator of the behavior described
+above, there are other situations that can trigger offscreen surface usage.
+They are:
+
+ - Setting `overflow: hidden` on a rotated subtree parent element (e.g. via
+   `transform: rotate(...)`)
+ - Setting `overflow: hidden` on a subtree parent element with rounded corners.
+
+## Explicitly set Image src attributes to '' when finished with them.
+
+Cobalt maintains an image cache with a preset capacity (e.g. default of 32MB on
+platforms with 1080p UIs, but it can be customized).  When an image goes out
+of scope and is no longer needed, instead of leaving it up to the garbage
+collector to decide when an image should be destroyed and its resources
+released, it is recommended that Image objects have their `src` attribute
+explicitly cleared (i.e. set to `''`) when they are no longer needed, so
+that Cobalt can reclaim the image resources as soon as possible.
+
+## Be conservative with usage of the border-radius CSS property.
+
+While Cobalt has significant optimizations in place for handling the rendering
+of rounded corners, it still requires significantly more sophistication and
+processing than rendering a normal rectangle.  This applies to a number of
+different scenarios, such as using rounded corners on elements with either
+background-color or background-image.  Particularly expensive however would
+be to apply rounded corners on a parent node which has `overflow: hidden` set
+(as mentioned above), since this requires the creation of an offscreen surface.
+
+## Avoid large (e.g. fullscreen) divs
+
+The more screen area that is covered by DOM elements, the more work the GPU has
+to do, and so the lower the framerate will be.  For example, if a background
+is desired, instead of creating a new fullscreen `<div>`, set the
+desired background color or image on the `<body>` element which will cover the
+display anyway.  Otherwise, the `<body>` element will render its background, and
+then the `<div>` element will render over top of it (Cobalt is not smart enough
+to know if an element completely covers another element), resulting in more
+pixels being touched than is necessary.
+
+This type of optimization is related to the concept of "overdraw" from computer
+graphics.  A good definition for overdraw can be found at
+[https://developer.android.com/topic/performance/rendering/overdraw](https://developer.android.com/topic/performance/rendering/overdraw):
+
+> "Overdraw refers to the system's drawing a pixel on the screen multiple times
+>  in a single frame of rendering. For example, if we have a bunch of stacked
+>  UI cards, each card hides a portion of the one below it... It manifests
+>  itself as a performance problem by wasting GPU time to render pixels that
+>  don't contribute to what the user sees on the screen."
+
+The `<body>` element will always result in the display being filled with a
+color, which is `rgba(0, 0, 0, 0)` by default.  Since `<body>` already
+guarantees a full screen draw, the most optimal way of specifying a
+background is to modify `<body>`'s background properties instead of adding
+a layer on top of it.
+
+## Blitter optimizations
+
+If the platform's user agent string contains "blitter", then the platform uses
+the Blitter API for rendering. This device is much more limited in what it can
+render natively, and many complex geometry will require software rendering.
+This means the CPU creates a texture and calculates the color of each pixel in
+that texture. The following things trigger the software rendering path (i.e.
+uses extra memory and is slow) on platforms using the Blitter API:
+
+ - Text.
+ - Rounded corners.
+ - Borders of different sizes. If borders are to be used, then all borders
+   should have the same properties. (And avoid rounded corners.)
+ - Linear gradients which are not exactly vertical or horizontal (i.e. gradients
+   at an angle).
+ - Radial gradients.
+ - Shadows.
+ - Multi-plane images. JPEG images tend to decode into multi-plane images.
+   Prefer using PNG images instead -- these tend to be decoded into RGBA which
+   blitter can handle natively.
+ - Using part of a background image. For example, using background-position may
+   result in extra memory usage, or using a background image inside an
+   `overflow: hidden` element that is shifted or has rounded corners.
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/device_authentication.md b/src/cobalt/site/docs/gen/cobalt/doc/device_authentication.md
new file mode 100644
index 0000000..f1513a9
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/device_authentication.md
@@ -0,0 +1,51 @@
+---
+layout: doc
+title: "Device Authentication"
+---
+# Device Authentication
+
+Starting in Cobalt 20, initial URL requests will now have query parameters
+appended to them signed by the platform's secret key.  The key is provided during
+the certification process.  The key must be stored in secure storage on the
+device.
+
+## Message
+
+When constructing the URL for the initial browse request, according to the
+logic in
+[cobalt/browser/device_authentication.cc](../browser/device_authentication.cc),
+it will fetch from the platform a "certification scope" string provided to
+the device during certification.  The certification scope will be queried
+by a call to `SbSystemGetProperty(kSbSystemPropertyCertificationScope, ...)`,
+which the platform is expected to implement.  Along with the current system
+time, this forms the message that must be signed by the device's secret key.
+
+## Signing
+
+The message defined above must be signed with the HMAC-SHA256 algorithm. The
+resulting digest (encoded as base64), alongside the unencrypted message
+contents, will be appended to the initial URL.
+
+Two choices exists for how platforms can expose the secret key to Cobalt.
+Cobalt will first attempt to have the platform sign the message, and if that
+functionality is not implemented Cobalt will query the platform for the secret
+key and sign the message itself.  If neither choice is implemented, then Cobalt
+will log a warning and not append anything to the URL.
+
+### Platform signing
+
+Cobalt will first attempt to use the `SbSystemSignWithCertificationSecretKey()`
+function to sign the message using the secret key.  This method is preferred
+since it enables implementations where the key exists only in secure hardware
+and never enters the system's main memory.  A reference implementation, which
+depends on BoringSSL exists at
+[starboard/linux/x64x11/internal/system_sign_with_certification_secret_key.cc](../../starboard/linux/x64x11/internal/system_sign_with_certification_secret_key.cc).
+
+### Cobalt signing
+
+If the function `SbSystemSignWithCertificationSecretKey()` is unimplemented (e.g. it returns `false`, as is done in
+[starboard/shared/stub/system_sign_with_certification_secret_key.cc](../../starboard/shared/stub/system_sign_with_certification_secret_key.cc)),
+then Cobalt will instead attempt to retrieve the secret key from the system by
+a call to
+`SbSystemGetProperty(kSbSystemPropertyBase64EncodedCertificationSecret, ...)`,
+and use it to produce the HMAC-SHA256 digest of the message itself.
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/docker_build.md b/src/cobalt/site/docs/gen/cobalt/doc/docker_build.md
new file mode 100644
index 0000000..450693f
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/docker_build.md
@@ -0,0 +1,70 @@
+---
+layout: doc
+title: "Cobalt Docker builds"
+---
+# Cobalt Docker builds
+
+Cobalt includes [Docker image][docker.com](https://www.docker.com/)
+definitions for simplifying managing build environments.
+
+The instructions below assume Docker is installed and is able to run basic
+[`hello-world` verification](https://docs.docker.com/get-started/#test-docker-installation).
+`docker-compose` command is expected to be available as well.
+
+## Usage
+
+The simplest usage is:
+
+  `docker-compose run <platform>`
+
+By default, a debug build will be built, with `cobalt` as a target.
+You can override this with an environment variable, e.g.
+
+  `docker-compose run -e CONFIG=devel -e TARGET=nplb <platform>`
+
+where config is one of the four optimization levels, debug, devel, qa and gold,
+and target is the build target passed to `ninja`
+
+See [Cobalt README](../../README.md#build-types)
+for full details.
+
+Builds will be available in your `${COBALT_SRC}/out` directory.
+
+NB! Note that Docker runs processes as root user by default, hence output
+files in `src/out/<platform>` directory have `root` as file owner.
+
+## Customization
+
+To parametrize base operating system images used for the build, pass BASE_OS
+as an argument to docker-compose as follows:
+
+  `docker-compose build --build-arg BASE_OS="ubuntu:bionic" base`
+
+This parameter is defined in `docker/linux/base/Dockerfile` and is passed to
+Docker `FROM ...` statement.
+
+Available parameters for customizing container execution are:
+
+ - **BASE_OS**: passed to `base` image at build time to select a Debian-based
+    base os image and version. Defaults to Debian 9. `ubuntu:bionic` and
+    `ubuntu:xenial` are other tested examples.
+ - **PLATFORM**: Cobalt build platform, passed to GYP
+ - **CONFIG**: Cobalt build config, passed to GYP. Defaults to `debug`
+ - **TARGET**: Build target, passed to `ninja`
+
+The `docker-compose.yml` contains the currently defined experimental build
+configurations. Edit or add new `service` entries as needed, to build custom
+configurations.
+
+## Pre-built images
+
+Note: Pre-built images from a public container registry are not yet available.
+
+## Troubleshooting
+
+To debug build issues, enter the shell of the corresponding build container by
+launching the bash shell, i.e.
+
+  `docker-compose run linux-x64x11 /bin/bash`
+
+and try to build cobalt [with the usual `gyp / ninja` flow](../../README.md#building-and-running-the-code).
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/lifecycle.md b/src/cobalt/site/docs/gen/cobalt/doc/lifecycle.md
new file mode 100644
index 0000000..6b22ee0
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/lifecycle.md
@@ -0,0 +1,244 @@
+---
+layout: doc
+title: "Application Lifecycle"
+---
+# Application Lifecycle
+
+In order to meet common needs of applications running on CE devices, Cobalt
+implements a well-defined web application lifecycle, managing resources and
+notifying the application as appropriate.
+
+## Summary of changes in Cobalt 22
+
+The application lifecycle has some changes from Cobalt 22:
+
+### States:
+
+* The *Paused* state is renamed to *Blurred*.
+* The *Suspended* state is replaced by *Concealed* and *Frozen*.
+* The *Preloading* state is removed, and *Concealed* is used instead.
+  Note: The corresponding attribute value 'prerender' for
+  document.visibilityState is also removed.
+
+The new *Concealed* state is used for applications that are not visible but may
+use CPU or network resources. This state is used to both replace the
+*Preloading* state, and as an intermediate state between *Blurred* and
+*Frozen*.
+
+The *Frozen* state most closely resembles the previous *Suspended* state,
+during which applications do not have network access.
+
+### State Changes:
+
+* The *Pause* event is renamed to *Blur*.
+* The *Unpause* event is renamed to *Focus*.
+* The *Suspend* event is replaced by *Conceal* and *Freeze*.
+* The *Resume* event is replaced by *Unfreeze* and *Reveal*.
+
+Most platforms should only need to replace 'Pause' with 'Blur', 'Unpause' with
+'Focus', 'Suspend' with 'Freeze', and 'Resume' with 'Reveal'.
+
+Since there is no longer a special *Preloading* state, applications should no
+longer use the *Start* event when a preloaded application is brought to the
+foreground. Instead, the same event(s) used for backgrounded applications
+(*Concealed* or *Frozen*) should be used.
+
+### Application 'Backgrounding' and 'Foregrounding'.
+
+To signal that the application is being 'backgrounded', the use of *Suspend*
+should be replaced with *Freeze*.
+
+To signal that the application is being 'foregrounded', the use of *Unpause*
+should be replaced with *Focus*.
+
+Note: If a platform is using *Resume* (*Reveal*) to signal that an application
+is being 'foregrounded', then that may result in unexpected application
+behavior, unless a subsequent *Unpause* (*Focus*) is also used when the
+application receives input focus.
+
+More details about lifecycle states and state changes can be found in
+`src/starboard/event.h`.
+
+### Deprecated `SbEventType` values.
+
+The `SbEventType` enum is defined in `src/starboard/event.h`.
+
+* The `kSbEventTypePause` value is renamed to `kSbEventTypeBlur`.
+* The `kSbEventTypeUnpause` value is renamed to `kSbEventTypeFocus`.
+* The `kSbEventTypeSuspend` value is replaced by `kSbEventTypeConceal` and
+  `kSbEventTypeFreeze`.
+* The `kSbEventTypeResume` value is replaced by `kSbEventTypeUnfreeze` and
+  `kSbEventTypeReveal`.
+
+The corresponding helper functions in
+`starboard::shared::starboard::Application` (implemented in
+`starboard/shared/starboard/application.cc`) that inject events with these
+values have been updated correspondingly:
+
+* The `Pause()` method is renamed to `Blur()`.
+* The `Unpause()` method is renamed to `Focus()`.
+* The `Suspend()` method is replaced by `Conceal()` and
+  `Freeze()`.
+* The `Resume()` method is replaced by `Unfreeze()` and
+  `Reveal()`.
+
+Platforms that inject events themselves should be updated to use renamed event
+type values, and platforms that use the helper functions should be updated to
+call the corresponding renamed helper functions.
+
+### Deprecated `SbSystemRequest` functions.
+
+The `SbSytemRequest` functions are declared in `src/starboard/system.h`
+
+* The `SbSystemRequestPause` event is renamed to `SbSystemRequestBlur`
+* The `SbSystemRequestUnpause` event is renamed to `SbSystemRequestFocus`
+* The `SbSystemRequestSuspend` event is replaced by `SbSystemRequestConceal`
+  and `SbSystemRequestFreeze`
+* The `SbSystemRequestResume` event is replaced by `SbSystemRequestUnfreeze`
+  and `SbSystemRequestReveal`
+
+## Application States
+
+Starboard Application State | Page Visibility State | Window Focused
+:-------------------------- | :-------------------- | :-------------
+*Started*                   | visible               | true
+*Blurred*                   | visible               | false
+*Concealed*                 | hidden                | false
+*Frozen*                    | hidden                | false
+
+When transitioning between *Concealed* and *Frozen*, the document.onfreeze and
+document.onresume events from the Page LifeCycle Web API will be dispatched.
+
+### Started
+
+The application is running, visible, and interactive. The normal foreground
+application state. May be the start state, or can be entered from *Blurred*.
+
+May only transition to *Blurred*. In Linux desktop, this happens anytime the
+top-level Cobalt X11 window loses focus. Linux transition back to *Started*
+when the top-level Cobalt X11 window gains focus again.
+
+### Blurred
+
+The application may be fully visible, partially visible, or completely
+obscured, but it has lost input focus, so will receive no input events. It has
+been allowed to retain all its resources for a very quick return to *Started*,
+and the application is still running. May be entered from or transition to
+*Started* or *Concealed* at any time.
+
+### Concealed
+
+The application is not visible and will receive no input, but is running. Can
+be entered as the start state. May be entered from or transition to *Blurred*
+or *Frozen* at any time. The application may be terminated in this state
+without notification.
+
+Upon entering, all graphics resources will be revoked until revealed, so the
+application should expect all images to be lost, and all caches to be cleared.
+
+#### Expectations for the web application
+
+The application should **shut down** playback, releasing resources. On resume,
+all resources need to be reloaded, and playback should be reinitialized where
+it left off, or at the nearest key frame.
+
+### Frozen
+
+The application is not visible and will receive no input, and, once *Frozen*,
+will not run any code. May be entered from or transition to *Concealed* at any
+time. The application may be terminated in this state without notification.
+
+Upon entering, all graphics and media resources will be revoked until resumed,
+so the application should expect all images to be lost, all caches to be
+cleared, and all network requests to be aborted.
+
+#### Expectations for the porter
+
+Currently, Cobalt does not manually stop JavaScript execution when it goes into
+the *Frozen* state. In Linux desktop, it expects that a `SIGSTOP` will be
+raised, causing all the threads not to get any more CPU time until resumed.
+This will be fixed in a future version of Cobalt.
+
+### Application Startup Expectations for the porter
+
+The starboard application lifecycle, with descriptions of the states and the
+state changes can be found in `src/starboard/event.h`.
+
+For applications that can be preloaded, the platform should send
+`kSbEventTypePreload` as the first Starboard event instead of
+`kSbEventTypeStart`. Subclasses of
+`src/starboard/shared/starboard/application.cc` can opt-in to use the already
+implemented support for the `--preload` command-line switch.
+
+If started with `kSbEventTypePreload`, the platform can at any time send
+`kSbEventTypeFocus` when the application brought to the foreground.
+In Linux desktop (linux-x64x11), this can be done by sending a `SIGCONT` to the
+process that is in the *Preloading* state (see
+`starboard/shared/signal/suspend_signals.cc`)
+
+If the platform wants to only give applications a certain amount of time to
+preload, they can send `SbSystemRequestFreeze` to halt preloading and move to
+the *Frozen* state. In Linux desktop, this can be done by sending SIGUSR1 to
+the process that is in the *Preloading* state.
+
+## Implementing the Application Lifecycle (for the porter)
+
+The platform Starboard implementation **must always** send events in the
+prescribed order - meaning, for example, that it should never send a
+`kSbEventTypeConceal` event unless in the *Blurred* state.
+
+Most porters will want to subclass either `starboard::shared::Application` (in
+`src/starboard/shared/starboard/application.cc`) or
+`starboard::shared::QueueApplication` (in
+`src/starboard/shared/starboard/queue_application.cc`), as these are reference
+classes that rigorously implement the Starboard application lifecycle. They are
+optional, and platforms can directly dispatch events to SbEventHandle(), but it
+is then up to them to ensure that events are **always** sent in the correct
+state as specified in the Starboard documentation.
+
+`starboard::shared::Application` (in
+`starboard/shared/starboard/application.cc`) guarantees the correct ordering by
+implementing a small state machine that ignores invalid application state
+transitions, and inserts any necessary transitions to make them valid. For
+example, you can call `starboard::shared::Application::Conceal()`, and if you
+are in *Blurred*, it will just dispatch a `kSbEventTypeConceal` event. But if
+you call `Conceal()` in the *Started* state, it will first dispatch
+`kSbEventTypeBlur`, followed by a `kSbEventTypeConceal` event. If you call
+`Conceal()` in the *Concealed* state, it just does nothing.
+
+This behavior can be ensured by only dispatching events to SbEventHandle()
+using `Application::DispatchAndDelete()` either directly, or indirectly such
+as by using `Application::RunLoop()` with the default implementation of
+`Application::DispatchNextEvent()`.
+
+To control starting up in the *Concealed* state for preloading, `Application`
+subclasses must override two functions:
+
+``` c++
+class MyApplication : public shared::starboard::QueueApplication {
+  // [ ... ]
+  bool IsStartImmediate() override;
+  bool IsPreloadImmediate() override;
+  // [ ... ]
+}
+```
+
+To start up in the *Concealed* state, `IsStartImmediate()` should return
+`false` and `IsPreloadImmediate()` should return `true`.
+
+To start up in the *Starting* state (which is the default), `IsStartImmediate()`
+should return `true` and `IsPreloadImmediate()` will not be called.
+
+To delay starting up until some later event, `IsStartImmediate()` and
+`IsPreloadImmediate()` should both return `false`. No initial event will be
+automatically sent to the application, and it is then up to the porter to
+dispatch a `kSbEventTypeStart` or `kSbEventTypePreload` event as the first
+event. This is useful if you need to wait for an asynchronous system activity to
+complete before starting Cobalt.
+
+To support the `--preload` command-line argument:
+
+``` c++
+  bool IsStartImmediate() override { return !HasPreloadSwitch(); }
+  bool IsPreloadImmediate() override { return HasPreloadSwitch(); }
+```
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/memory_tuning.md b/src/cobalt/site/docs/gen/cobalt/doc/memory_tuning.md
new file mode 100644
index 0000000..44a94b6
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/memory_tuning.md
@@ -0,0 +1,277 @@
+---
+layout: doc
+title: ""
+---
+# Memory Tuning #
+
+Cobalt is designed to choose sensible parameters for memory-related options and
+parameters through a system called "AutoMem".
+
+On startup, AutoMem will print a memory table to the output console detailing
+the memory allocations that will be assigned to the various subsystems in
+cobalt.
+
+Some settings will be "fixed" while others will be "flexible" so that their
+memory consumption will scale down for memory constrained platforms.
+
+Read on for more information.
+
+**IMPORTANT**
+*Setting `--max_cobalt_cpu_usage` and `--max_cobalt_gpu_usage` on the
+command line is a beta feature.*
+
+### Memory Settings Table ###
+
+A table similar to the one below, will be printed on startup.
+
+~~~
+AutoMem:
+ _______________________________________________________________________________
+|SETTING NAME                          |VALUE        |         |TYPE  |SOURCE   |
+| encoded_image_cache_size_in_bytes    |     1048576 |  1.0 MB |  CPU |   Build |
+| image_cache_size_in_bytes            |    10485760 | 10.0 MB |  GPU | AutoSet |
+| offscreen_target_cache_size_in_bytes |     2097152 |  2.0 MB |  GPU | AutoSet |
+| remote_typeface_cache_size_in_bytes  |     4194304 |  4.0 MB |  CPU |   Build |
+| skia_atlas_texture_dimensions        | 2048x2048x2 |  8.0 MB |  GPU | AutoSet |
+| skia_cache_size_in_bytes             |     4194304 |  4.0 MB |  GPU |   Build |
+| software_surface_cache_size_in_bytes |         N/A |     N/A |  N/A |     N/A |
+|______________________________________|_____________|_________|______|_________|
+
+~~~
+This table shows the breakdown of how much memory is being allocated to each
+sub-system, the type, and where it came from.
+
+**SETTING NAME:** This is the name of the memory setting. If a setting can be
+manually set through the command line or the build system, then it will be
+accessible by using this name. For example adding the command line argument
+`--image_cache_size_in_bytes=25165824` will manually set the Image Cache Size to
+24 megabytes. Also note that this is also equivalent:
+`--image_cache_size_in_bytes=24MB`. Note that the numerical value can include
+the suffix kb/mb/gb to specify kilo/mega/giga-bytes. The numerical value can
+be a floating point value. For example `--image_cache_size_in_bytes=.1GB` is
+equivalent to `--image_cache_size_in_bytes=100MB`.
+
+**VALUE:** This two column value has a first setting that describes what the
+actual value is, and the second column is the amount of memory that the setting
+consumes. This first setting gives hints on what kind of values the
+setting can be set to via the command line. For example,
+`skia_atlas_texture_dimensions` accepts texture sizes on the command line, such
+as: `--skia_atlas_texture_dimensions=2048x4096x2`
+
+**TYPE:** This specifies whether the setting consumes GPU or CPU memory.
+For example, the Image Cache will decode images to buffers to the GPU memory
+and therefore it is the classified as the GPU memory type.
+
+**SOURCE:** This specifies where the memory setting came from. It will either
+be set from a specific place or automatically generated from Cobalt.
+  * Values for **SOURCE**:
+    * `Starboard API`
+      * The value used was reported by the result of a Starboard API function call.
+      * Example: `SbSystemGetUsedCPUMemory()`
+    * `Build`
+      * Specified by the platform specific `*.gyp(i)` build file.
+      * For example: see `image_cache_size_in_bytes` in [`build/config/base.gypi`](../build/config/base.gypi)
+    * `CmdLine`
+      * Read the memory setting value from the command line.
+      * For example: `cobalt --image_cache_size_in_bytes=24MB`.
+    * `AutoSet`
+      * No value was specified and therefore Cobalt calculated the default value
+	    automatically based on system parameters. For example many caches
+		will be chosen proportionally to the size of the UI resolution.
+    * `AutoSet (Constrained)`
+      * This value was AutoSet to a default value, but then was reduced in
+      response to `max_cobalt_cpu_usage` or `max_cobalt_gpu_usage being` set too low.
+
+### Maximum Memory Table ###
+
+This second table is also printed at startup and details the sum of memory and
+maximum memory limits as reported by cobalt.
+
+~~~
+ MEMORY                 SOURCE          TOTAL      SETTINGS CONSUME
+ ____________________________________________________________________
+|                      |               |          |                  |
+| max_cobalt_cpu_usage | Starboard API | 256.0 MB |         131.0 MB |
+|______________________|_______________|__________|__________________|
+|                      |               |          |                  |
+| max_cobalt_gpu_usage | Starboard API | 768.0 MB |         124.0 MB |
+|______________________|_______________|__________|__________________|
+~~~
+
+This table shows the limits for CPU and GPU memory consumption and also how
+much memory is being consumed for each memory type.
+
+**MEMORY**: This is the name of the memory limit. If you want to change this
+setting manually then use the name on the command line. For example
+`--max_cobalt_cpu_usage=150MB` will set Cobalt to 150MB limit for CPU
+memory. If the sum of CPU memory exceeds this limit then memory settings of the
+same type will reduce their memory usage.
+
+**SOURCE**: This value indicates where the value came from.
+ * `Starboard API`
+   * `max_cobalt_cpu_usage`: This value was found from SbSystemGetTotalCPUMemory().
+   * `max_cobalt_gpu_usage`: This value was found from SbSystemGetTotalGPUMemory().
+ * `CmdLine`
+   * `max_cobalt_cpu_usage`: --max_cobalt_cpu_usage was used as a command argument.
+   * `max_cobalt_gpu_usage`: --max_cobalt_gpu_usage was used as a command argument.
+ * `Build`
+   * `max_cobalt_cpu_usage`: max_cobalt_cpu_usage was specified in a platform gyp file.
+   * `max_cobalt_gpu_usage`: max_cobalt_gpu_usage was specified in a platform gyp file.
+
+**TOTAL**: Represents the maximum available memory for settings. This value
+came from **SOURCE**.
+
+**SETTINGS CONSUME**: This value indicates the consumption of memory for the
+current memory type.
+
+For `max_cobalt_cpu_usage`, `Starboard API` indicates that this value came from
+`SbSystemGetTotalCPUMemory()`  If this source value is `Starboard API` then this
+value came from `SbSystemGetTotalCPUMemory()` (for CPU) or
+`SbSystemGetTotalGPUMemory()` for GPU).
+
+If the available memory for the Cobalt is less than the amount of memory
+consumed by the settings, then any settings that are AutoSet AND adjustable
+will reduce their memory consumption. When this happens, look for the string
+*`AutoSet (Constrained)`* in the first table.
+
+## Setting Maximum Memory Values ##
+
+The max cpu and gpu memory of the system can be set either by command line or
+by modifying the gyp build file.
+
+Command Line:
+  * `--max_cobalt_cpu_usage=160MB`
+  * `--max_cobalt_gpu_usage=160MB`
+
+Build settings:
+  * `starboard/<PLATFORM>/gyp_configuration.gypi`
+    * `max_cobalt_cpu_usage`
+    * `max_cobalt_gpu_usage`
+
+Command Line settings will override build settings.
+
+### Memory Scaling ###
+
+There are two primary ways in which the memory consumption settings will scale down.
+One is by specifying `--max_cobalt_cpu_usage` (or `max_cobalt_gpu_usage`) to a
+particular value (e.g. `--max_cobalt_cpu_usage=160MB`).
+
+`--max_cobalt_cpu_usage` (and `--max_cobalt_gpu_usage`) will trigger the memory
+to scale down whenever the memory settings memory consumption exceed the maximum
+**TOTAL** value. The memory settings will be scaled down until their consumption is
+less than or equal the maximum allowed value **TOTAL**. See also **SETTINGS CONSUME**.
+
+*Forcing a Memory Setting to be flexible*
+
+If a memory setting is set via a build setting, then it's possible to make it
+flexible via the command line by setting the value to "autoset". For example,
+ `--image_cache_size_in_bytes=auto` will allow `image_cache_size_in_bytes` to be
+flexible by disabling the value being set by a build setting.
+
+### Memory Warnings ###
+
+Cobalt will periodically check to see if the memory consumed by the application
+is less than the `--max_cobalt_cpu_usage` and `--max_cobalt_gpu_usage` amount.
+If the cpu/gpu exceeds this maximum value then an error message will be logged
+once to stdout for cpu and/or gpu memory systems.
+
+
+### Example 1 - Configuring for a memory restricted platform ###
+
+Let's say that we are configuring platform called "XXX":
+
+We will configure XXX such that:
+  * `image_cache_size_in_bytes` will be set to 32MB in the build settings.
+  * `skia_atlas_texture_dimensions` will be set to `2048x2048x2` in the build settings.
+  * `max_cobalt_cpu_usage` will be set to 160MB on the command line.
+
+**Configuring `image_cache_size_in_bytes` to be 32MB:**
+  * in `starboard\<PLATFORM>\gyp_configuration.gypi`
+    * add `'image_cache_size_in_bytes': 32 * 1024 * 1024,`
+
+**Configuring `skia_atlas_texture_dimensions` to be 2048x2048x2:**
+
+  * in `src\starboard\XXX\gyp_configuration.gypi`
+    * add `'skia_glyph_atlas_width': '2048'`
+    * add `'skia_glyph_atlas_height': '2048'`
+    * (note that the third dimension is assumed)
+
+**Configuring `max_cobalt_cpu_usage` to be 160MB:**
+
+  * `cobalt --max_cobalt_cpu_usage=160MB`
+
+### Example 2 - Configuring for a memory-plentiful platform ###
+
+The following command line will give a lot of memory to image cache and give
+500MB to `max_cobalt_cpu_usage` and `max_cobalt_gpu_usage`.
+
+~~~
+cobalt --max_cobalt_cpu_usage=500MB --max_cobalt_gpu_usage=500MB
+--image_cache_size_in_bytes=80MB
+~~~
+
+## API Reference ##
+
+#### Memory System API ####
+
+  * `max_cobalt_cpu_usage`
+    * This setting will set the maximum cpu memory that the app will consume.
+      CPU Memory settings will scale down their consumption in order to stay under
+      the `max_cobalt_cpu_usage`. If memory consumption exceeds this value during
+      runtime then a memory warning will be printed to stdout.
+    * Set via command line or else build system or else starboard.
+      * starboard value will bind to `SbSystemGetTotalCPUMemory()`.
+  * `max_cobalt_gpu_usage`
+    * This setting will set the maximum gpu memory that the app will consume.
+      GPU Memory settings will scale down their consumption in order to stay under
+      the `max_cobalt_gpu_usage`. If memory consumption exceeds this value during
+      runtime then a memory warning will be printed to stdout.
+    * Set via command line or else build system or else starboard.
+      * starboard value will bind to `SbSystemGetTotalGPUMemory()`.
+    * Note that `SbSystemGetTotalGPUMemory()` is optional. If no value exists
+      for `max_cobalt_gpu_usage` in build/commandline/starboard settings then no
+      GPU memory checking is performed.
+
+#### Memory Setting API ####
+
+  * `image_cache_size_in_bytes`
+    * See documentation *Image cache capacity* in `performance_tuning.md` for what
+      this setting does.
+    * Set via command line, or else build system, or else automatically by Cobalt.
+  * `remote_typeface_cache_size_in_bytes`
+    * Determines the capacity of the remote typefaces cache which manages all typefaces
+      downloaded from a web page.
+    * Set via command line, or else build system, or else automatically by Cobalt.
+  * `skia_atlas_texture_dimensions`
+    * 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 Cobalt that these settings
+      should be automatically set.
+    * Set via command line, or else build system, or else automatically by Cobalt.
+    * Note that in the gyp build system, this setting is represented as two values:
+      * `skia_glyph_atlas_width` and
+      * `skia_glyph_atlas_height`
+  * `skia_cache_size_in_bytes`
+    * See documentation *Glyph atlas size* in `performance_tuning.md` for what this
+      setting does.
+    * Set via command line, or else build system or else automatically by Cobalt.
+  * `software_surface_cache_size_in_bytes`
+    * See documentation *Scratch Surface cache capacity* in `performance_tuning.md`
+      for what this setting does.
+    * Set via command line, or else build system, or else automatically by Cobalt.
+
+#### Units for Command Line Settings ####
+
+Memory values passed into Cobalt via command line arguments support units such
+kb, mb, and gb for kilo-byte, megabyte, gigabytes. These units are case insensitive.
+
+For example, these are all equivalent on the command line:
+
+`--image_cache_size_in_bytes=67108864`
+`--image_cache_size_in_bytes=65536kb`
+`--image_cache_size_in_bytes=64mb`
+`--image_cache_size_in_bytes=.0625gb`
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/net_log.md b/src/cobalt/site/docs/gen/cobalt/doc/net_log.md
new file mode 100644
index 0000000..0dbea4c
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/net_log.md
@@ -0,0 +1,34 @@
+---
+layout: doc
+title: "Cobalt NetLog"
+---
+# Cobalt NetLog
+
+Chromium has a very useful network diagnostic tool called the NetLog and Cobalt
+is hooked up to use it. It's the main tool to track network traffic and debug
+network code.
+
+### Activate the NetLog
+
+The following command line switch will activate the NetLog and store net log
+record to the specified location.
+`./cobalt --net_log=/PATH/TO/YOUR_NETLOG_NAME.json`
+The output json file will be stored at the file location you choose.
+
+
+### Read the NetLog records
+
+The produced json file is not human-friendly, use the
+[NetLog Viewer](https://netlog-viewer.appspot.com/#import)
+
+Cobalt's net_log can not enable some features in the web viewer, but all the
+network traffic is recorded in the event tab.
+
+
+### Add NetLog entries
+
+To Add NetLog entry, get the NetLog instance owned by NetworkModule to where you
+want to add entries and start/end your entry according to the NetLog interface.
+
+A NetLog object is created at each NetworkModule initialization and is passed
+into Chromium net through URLRequestContext.
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/performance_tuning.md b/src/cobalt/site/docs/gen/cobalt/doc/performance_tuning.md
new file mode 100644
index 0000000..bf3ea5d
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/performance_tuning.md
@@ -0,0 +1,393 @@
+---
+layout: doc
+title: "Performance Tuning"
+---
+# Performance Tuning
+
+Cobalt is designed to choose sensible parameters for all performance-related
+options and parameters, however sometimes these need to be explicitly set
+to allow Cobalt to run optimally for a specific platform.  This document
+discusses some of the tweakable parameters in Cobalt that can have an
+affect on performance.
+
+A number of tweaks are listed below in no particular order.  Each item
+has a set of tags keywords to make it easy to search for items related
+to a specific type of performance metric (e.g. "framerate").
+
+Many of the tweaks involve adding a new gyp variable to your platform's
+`gyp_configuration.gypi` file.  The default values for these variables are
+defined in either
+[`base_configuration.gypi`](../../starboard/build/base_configuration.gypi) or
+[`cobalt_configuration.gypi`](../build/cobalt_configuration.gypi).
+
+### Use a Release Build
+
+Cobalt has a number of different build configurations (e.g. "debug", "devel",
+"qa" and "gold" in slowest-to-fastest order), with varying degrees of
+optimizations enabled.  For example, while "devel" has compiler optimizations
+enabled, it does not disable DCHECKS (debug assertions) which can decrease
+Cobalt's performance.  The "qa" build is most similar to "gold", but it still
+has some debug features enabled (such as the debug console which can consume
+memory, and decrease performance while it is visible).  For the best
+performance, build Cobalt in the "gold" configuration.
+
+**Tags:** *framerate, startup, browse-to-watch, cpu memory, input latency.*
+
+
+### Framerate throttling
+
+If you're willing to accept a lower framerate, there is potential that
+JavaScript execution can be made to run faster (which can improve startup
+time, browse-to-watch time, and input latency).  Without any special
+settings in place, the renderer will attempt to render each frame as fast
+as it can, limited only by the display's refresh rate, which is usually 60Hz.
+By artificially throttling this rate to a lower value, like 30Hz, CPU
+resources can be freed to work on other tasks.  You can enable framerate
+throttling by setting a value for `cobalt_minimum_frame_time_in_milliseconds`
+in your platform's `gyp_configuration.gypi` file.  Setting it to 33, for
+example, will throttle Cobalt's renderer to 30 frames per second.
+
+**Tags:** *gyp_configuration.gypi, framerate, startup, browse-to-watch,
+           input latency.*
+
+
+### Image cache capacity
+
+Cobalt's image cache is used to cache decoded image data.  The image data
+in the image cache is stored as a texture, and so it will occupy GPU memory.
+The image cache capacity dictates how long images will be kept resident in
+memory even if they are not currently visible on the web page.  By reducing
+this value, you can lower GPU memory usage, at the cost of having Cobalt
+make more network requests and image decodes for previously seen images.
+Cobalt will automatically set the image cache capacity to a reasonable value,
+but if you wish to override this, you can do so by setting the
+`image_cache_size_in_bytes` variable in your `gyp_configuration.gypi` file.  For
+the YouTube web app, we have found that at 1080p, 32MB will allow around
+5 thumbnail shelves to stay resident at a time, with 720p and 4K resolutions
+using proportionally less and more memory, respectively.
+
+**Tags:** *gyp_configuration.gypi, cpu memory, gpu memory.*
+
+
+### Image cache capacity multiplier during video playback
+
+Cobalt provides a feature where the image cache capacity will be reduced
+as soon as video playback begins.  This can be useful for reducing peak
+GPU memory usage, which usually occurs during video playback.  The
+downside to lowering the image cache during video playback is that it
+may need to evict some images when the capacity changes, and so it is
+more likely that Cobalt will have to re-download and decode images after
+returning from video playback.  Note that this feature is not well tested.
+The feature can be activated by setting
+`image_cache_capacity_multiplier_when_playing_video` to a value between
+`0.0` and `1.0` in your `gyp_configuration.gypi` file.  The image cache
+capacity will be multiplied by this value during video playback.
+
+**Tags:** *gyp_configuration.gypi, gpu memory.*
+
+
+### Scratch Surface cache capacity
+
+This only affects GLES renderers.  While rasterizing a frame, it is
+occasionally necessary to render to a temporary offscreen surface and then
+apply that surface to the original render target.  Offscreen surface
+rendering may also need to be performed multiple times per frame.  The
+scratch surface cache will keep allocated a set of scratch textures that
+will be reused (within and across frames) for offscreen rendering.  Reusing
+offscreen surfaces allows render target allocations, which can be expensive
+on some platforms, to be minimized.  However, it has been found that some
+platforms (especially those with tiled renderers, like the Raspberry Pi's
+Broadcom VideoCore), reading and writing again and again to the same texture
+can result in performance degradation.  Memory may also be potentially saved
+by disabling this cache, since when it is enabled, if the cache is filled, it
+may be occupying memory that it is not currently using.  This setting can
+be adjusted by setting `surface_cache_size_in_bytes` in your
+`gyp_configuration.gypi` file.  A value of `0` will disable the surface cache.
+
+**Tags:** *gyp_configuration.gypi, gpu memory, framerate.*
+
+
+### Glyph atlas size
+
+This only affects GLES renderers.  Skia sets up glyph atlases to which
+it software rasterizes glyphs the first time they are encountered, and
+from which the glyphs are used as textures for hardware accelerated glyph
+rendering to the render target.  Adjusting this value will adjust
+GPU memory usage, but at the cost of performance as text glyphs will be
+less likely to be cached already.  Note that if experimenting with
+modifications to this setting, be sure to test many languages, as some
+are more demanding (e.g. Chinese and Japanese) on the glyph cache than
+others.  This value can be adjusted by changing the values of
+the `skia_glyph_atlas_width` and `skia_glyph_atlas_height` variables in your
+`gyp_configuration.gypi` file.  Note that by default, these will be
+automatically configured by Cobalt to values found to be optimal for
+the application's resolution.
+
+**Tags:** *gyp_configuration.gypi, gpu memory, input latency, framerate.*
+
+
+### Software surface cache capacity
+
+This only affects Starboard Blitter API renderers.  The Starboard Blitter API
+has only limited support for rendering special effects, so often Cobalt will
+have to fallback to a software rasterizer for rendering certain visual
+elements (most notably, text).  In order to avoid expensive software
+renders, the results are cached and re-used across frames.  The software
+surface cache is crucial to achieving an acceptable framerate on Blitter API
+platforms.  The size of this cache is specified by the
+`software_surface_cache_size_in_bytes` variable in `gyp_configuration.gypi`.
+
+**Tags:** *gyp_configuration.gypi, gpu memory, framerate.*
+
+
+### Toggle Just-In-Time JavaScript Compilation
+
+Just-in-time (JIT) compilation of JavaScript is well known to significantly
+improve the speed of JavaScript execution.  However, in the context of Cobalt
+and its web apps (like YouTube's HTML5 TV application), JITting may not be
+the best or fastest thing to do.  Enabling JIT can result in Cobalt using
+more memory (to store compiled code) and can also actually slow down
+JavaScript execution (e.g. time must now be spent compiling code).  It is
+recommended that JIT support be left disabled, but you can experiment with
+it by implementing the CobaltExtensionConfigurationApi method
+`CobaltEnableJit()` to return `true` to enable JIT, or `false` to disable it.
+
+**Tags:** *gyp_configuration.gypi, startup, browse-to-watch, input latency,
+           cpu memory.*
+
+
+### Ensure that you are not requesting Cobalt to render unchanging frames
+
+Some platforms require that the display buffer is swapped frequently, and
+so in these cases Cobalt will render the scene every frame, even if it is
+not changing, which consumes CPU resources.  If the platform needs a new frame
+submitted periodically implement the Cobalt Extension
+"dev.cobalt.extension.Graphics" and report the maximum frame interval via
+`GetMaximumFrameIntervalInMilliseconds`.
+
+See `SbSystemGetExtension` and
+[`CobaltExtensionGraphicsApi`](../extension/graphics.h).
+
+Every `cobalt_minimum_frame_time_in_milliseconds`, this function will be queried
+to determine if a new frame should be presented even if the scene has not
+changed.
+
+**Tags:** *configuration_public.h, startup, browse-to-watch, input latency,
+           framerate.*
+
+
+### Try enabling rendering only to regions that change
+
+If you set the
+[`CobaltConfigurationExtensionApi`](../extension/configuration.h) function
+`CobaltRenderDirtyRegionOnly` to return `true`, then Cobalt will invoke logic
+to detect which part of the frame has been affected by animations and can be
+configured to only render to that region.  However, this feature requires
+support from the driver for GLES platforms.  In particular, `eglChooseConfig()`
+will first be called with `EGL_SWAP_BEHAVIOR_PRESERVED_BIT` set in its
+attribute list.  If this fails, Cobalt will call eglChooseConfig() again
+without `EGL_SWAP_BEHAVIOR_PRESERVED_BIT` set and dirty region rendering will
+be disabled.  By having Cobalt render only small parts of the screen,
+CPU (and GPU) resources can be freed to work on other tasks.  This can
+especially affect startup time since usually only a small part of the
+screen is updating (e.g. displaying an animated spinner).  Thus, if
+possible, ensure that your EGL/GLES driver supports
+`EGL_SWAP_BEHAVIOR_PRESERVED_BIT`.  Note that it is possible (but not
+necessary) that GLES drivers will implement this feature by allocating a new
+offscreen buffer, which can significantly affect GPU memory usage.  If you are
+on a Blitter API platform, enabling this functionality will result in the
+allocation and blit of a fullscreen "intermediate" back buffer target.
+
+**Tags:** *startup, framerate, gpu memory.*
+
+
+### Ensure that thread priorities are respected
+
+Cobalt makes use of thread priorities to ensure that animations remain smooth
+even while JavaScript is being executed, and to ensure that JavaScript is
+processed (e.g. in response to a key press) before images are decoded.  Thus
+having support for priorities can improve the overall performance of the
+application.  To enable thread priority support, you should set the value
+of `kSbHasThreadPrioritySupport` to `true` in your `configuration_constants.h`
+file, and then also ensure that your platform's implementation of
+`SbThreadCreate()` properly forwards the priority parameter down to the
+platform.
+
+**Tags:** *configuration_public.h, framerate, startup, browse-to-watch,
+           input latency.*
+
+
+### Tweak compiler/linker optimization flags
+
+Huge performance improvements can be obtained by ensuring that the right
+optimizations are enabled by your compiler and linker flag settings.  You
+can set these up within `gyp_configuration.gypi` by adjusting the list
+variables `compiler_flags` and `linker_flags`.  See also
+`compiler_flags_gold` and `linker_flags_gold` which describe flags that
+apply only to gold builds where performance is critical.  Note that
+unless you explicitly set this up, it is unlikely that compiler/linker
+flags will carry over from external shell environment settings; they
+must be set explicitly in `gyp_configuration.gypi`.
+
+**Tags:** *framerate, startup, browse-to-watch, input latency*
+
+#### Optimize for size vs speed
+
+For qa and gold configs, different compiler flags can be used for gyp targets
+which should be optimized for size vs speed. This can be used to reduce the
+executable size with minimal impact on performance. On top of the base
+`compiler_flags_qa` and `compiler_flags_gold`, the gyp variables
+`compiler_flags_qa_size`, `compiler_flags_qa_speed`, `compiler_flags_gold_size`,
+and `compiler_flags_gold_speed` will be used. Performance-critical gyp targets
+specify `optimize_target_for_speed`: 1, and these will use compiler flags
+`compiler_flags_<config>` + `compiler_flags_<config>_speed`; other gyp targets
+will use `compiler_flags_<config>` + `compiler_flags_<config>_size`.
+
+**Tags:** *cpu memory, package size*
+
+#### Link Time Optimization (LTO)
+If your toolchain supports it, it is recommended that you enable the LTO
+optimization, as it has been reported to yield significant performance
+improvements in many high profile projects.
+
+**Tags:** *framerate, startup, browse-to-watch, input latency*
+
+
+### Close "Stats for Nerds" when measuring performance
+
+The YouTube web app offers a feature called "Stats for Nerds" that enables
+a stats overlay to appear on the screen during video playback.  Rendering
+this overlay requires a significant amount of processing, so it is
+recommended that all performance evaluation is done without the
+"Stats for Nerds" overlay active.  This can greatly affect browse-to-watch
+time and potentially affect the video frame drop rate.
+
+**Tags:** *browse-to-watch, framerate, youtube.*
+
+
+### Close the debug console when measuring performance
+
+Cobalt provides a debug console in non-gold builds to allow the display
+of variables overlaid on top of the application.  This can be helpful
+for debugging issues and keeping track of things like app lifetime, but
+the debug console consumes significant resources when it is visible in order
+to render it, so it should be hidden when performance is being evaluated.
+
+**Tags:** *framerate, startup, browse-to-watch, input latency.*
+
+
+### Toggle between dlmalloc and system allocator
+
+Cobalt includes dlmalloc and can be configured to use it to handle all
+memory allocations.  It should be carefully evaluated however whether
+dlmalloc performs better or worse than your system allocator, in terms
+of both memory fragmentation efficiency as well as runtime performance.
+To use dlmalloc, you should adjust your starboard_platform.gyp file to
+use the Starboard [`starboard/memory.h`](../../starboard/memory.h) function
+implementations defined in
+[`starboard/shared/dlmalloc/`](../../starboard/shared/dlmalloc).  To use
+your system allocator, you should adjust your starboard_platform.gyp file
+to use the Starboard [`starboard/memory.h`](../../starboard/memory.h) function
+implementations defined in
+[`starboard/shared/iso/`](../../starboard/shared/iso).
+
+**Tags:** *framerate, startup, browse-to-watch, input latency, cpu memory.*
+
+
+### Media buffer allocation strategy
+
+During video playback, memory is reserved by Cobalt to contain the encoded
+media data (separated into video and audio), and we refer to this memory
+as the media buffers.  By default, Cobalt pre-allocates the memory and
+wraps it with a custom allocator, in order to avoid fragmentation of main
+memory.  However, depending on your platform and your system allocator,
+overall memory usage may improve if media buffer allocations were made
+normally via the system allocator instead.  This can be achieved by setting
+`cobalt_media_buffer_initial_capacity` and `cobalt_media_buffer_allocation_unit`
+to 0 in gyp_configuration.gypi.  Note also that if you choose to pre-allocate
+memory, for 1080p video it has been found that 24MB is a good media buffer size.
+The pre-allocated media buffer capacity size can be adjusted by modifying the
+value of `cobalt_media_buffer_initial_capacity` mentioned above.
+
+**Tags:** *configuration_public.h, cpu memory.*
+
+
+### Adjust media buffer size settings
+
+Many of the parameters around media buffer allocation can be adjusted in your
+gyp_configuration.gypi file.  The variables in question are the family of
+`cobalt_media_*` variables, whose default values are specified in
+[`cobalt_configuration.gypi`](../build/cobalt_configuration.gypi).  In
+particular, if your maximum video output resolution is less than 1080, then you
+may lower the budgets for many of the categories according to your maximum
+resolution.
+
+**Tags:** *cpu memory*
+
+
+### Avoid using a the YouTube web app FPS counter (i.e. "?fps=1")
+
+The YouTube web app is able to display a Frames Per Second (FPS) counter in the
+corner when the URL parameter "fps=1" is set.  Unfortunately, activating this
+timer will cause Cobalt to re-layout and re-render the scene frequently in
+order to update the FPS counter.  Instead, we recommend instead to either
+measure the framerate in the GLES driver and periodically printing it, or
+hacking Cobalt to measure the framerate and periodically print it.  In order to
+hack in an FPS counter, you will want to look at the
+`HardwareRasterizer::Impl::Submit()` function in
+[`cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc`](../renderer/rasterizer/skia/hardware_rasterizer.cc).
+The work required to update the counter has the potential to affect many
+aspects of performance.  TODO: Cobalt should add a command line switch to
+enable printing of the framerate in gold builds.
+
+**Tags:** *framerate, startup, browse-to-watch, input latency,*
+
+
+### Implement hardware image decoding
+
+The Starboard header file [`starboard/image.h`](../../starboard/image.h) defines
+functions that allow platforms to implement hardware-accelerated image
+decoding, if available.  In particular, if `SbImageIsDecodeSupported()` returns
+true for the specified mime type and output format, then instead of using the
+software-based libpng or libjpeg libraries, Cobalt will instead call
+`SbImageDecode()`.  `SbImageDecode()` is expected to return a decoded image as
+a `SbDecodeTarget` option, from which Cobalt will extract a GL texture or
+Blitter API surface object when rendering.  If non-CPU hardware is used to
+decode images, it would alleviate the load on the CPU, and possibly also
+increase the speed at which images can be decoded.
+
+**Tags:** *startup, browse-to-watch, input latency.*
+
+
+### Use Chromium's about:tracing tool to debug Cobalt performance
+
+Cobalt has support for generating profiling data that is viewable through
+Chromium's about:tracing tool.  This feature is available in all Cobalt
+configurations except for "gold" ("qa" is the best build to use for performance
+investigations here). There are currently two ways to tell Cobalt
+to generate this data:
+
+1. The command line option, "--timed_trace=XX" will instruct Cobalt to trace
+   upon startup, for XX seconds (e.g. "--timed_trace=25").  When completed,
+   the output will be written to the file `timed_trace.json`.
+2. Using the debug console (hit CTRL+O on a keyboard once or twice), type in
+   the command "h5vcc.traceEvent.start()" and hit enter.  Cobalt will begin a
+   trace.  After some time has passed (and presumably you have performed some
+   actions), you can open the debug console again and type
+   "h5vcc.traceEvent.stop()" again to end the trace.
+   The trace output will be written to the file `h5vcc_trace_event.json`.
+
+The directory the output files will be placed within is the directory that the
+Starboard function `SbSystemGetPath()` returns with a `path_id` of
+`kSbSystemPathDebugOutputDirectory`, so you may need to check your
+implementation of `SbSystemGetPath()` to discover where this is.
+
+Once the trace file is created, it can be opened in Chrome by navigating to
+`about:tracing` or `chrome://tracing`, clicking the "Load" button near the top
+left, and then opening the JSON file created earlier.
+
+Of particular interest in the output view is the `MainWebModule` thread where
+JavaScript and layout are executed, and `Rasterizer` where per-frame rendering
+takes place.
+
+**Tags:** *framerate, startup, browse-to-watch, input latency.*
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/platform_services.md b/src/cobalt/site/docs/gen/cobalt/doc/platform_services.md
new file mode 100644
index 0000000..309b578
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/platform_services.md
@@ -0,0 +1,111 @@
+---
+layout: doc
+title: "Cobalt Platform Services"
+---
+# Cobalt Platform Services
+
+_NOTE: The Cobalt Platform Services API replaces the deprecated Cobalt Custom Web API Extensions_
+
+## Overview
+
+The Cobalt Platform Services API aims to provide Cobalt users the ability to
+extend the web application functionality of Cobalt. This is done using runtime
+extensions provided by the Starboard layer without having to make any
+modifications to the common Cobalt code.
+
+Web applications running on Cobalt may want to implement a feature to have
+direct access to platform-specific services, on platforms where they are
+available.
+
+For example, a Cobalt implementation may want to enable the web application to:
+
+*   Communicate directly with a service that is available on the platform
+*   Surface platform-level status messages
+
+The Cobalt Platform Services API is an RPC interface and makes assumptions that
+communication with the service is in-process and 100% reliable, unlike sockets
+or HTTP. Out-of-process communications can be implemented as a layer on top of
+the interface.
+
+## Interface Definition
+
+The Cobalt Platform Services API is an RPC interface allowing for bidirectional
+communication between the web application and platform service. The interface
+is intentionally minimal, to avoid as much as possible the need to make changes
+to common Cobalt code. There will be two parallel interfaces, one between the
+web app and Cobalt specified via IDL, and another between Cobalt and the
+Starboard implementation specified via a Starboard interface header file.
+
+The interface provides a method of querying for services by name, where a name
+is some arbitrary string (Java naming convention recommended). The platform
+should maintain a registry mapping names to services and return the appropriate
+service for the given name. Once the application has obtained a handle to a
+service, it can send messages to the service using a `send()` function, which
+optionally may return immediate results. In addition, it can receive
+asynchronous incoming messages from the service via a receive callback
+registered when the service is opened. The `send()` function may fail, either
+because the service has already been closed by the application, or because of
+some state of the service and platform. When `send()` fails, it will raise an
+`kInvalidStateErr` exception, which may be caught & handled by the application.
+
+Any functionality in addition to the necessities provided by the interface must
+be implemented within the service’s protocol.  For example, services may push a
+“version” message to the application immediately upon being opened in order to
+implement versioning.
+
+### IDL Interface
+
+The Platform Services extension is exposed to the web app via the following IDL:
+
+*   [src/cobalt/h5vcc/h5vcc\_platform\_service.idl](../h5vcc/h5vcc_platform_service.idl)
+
+The entrypoint for defined Platform Services extensions will be accessible in
+the `H5vccPlatformService` object. Note that ArrayBuffers are chosen to
+represent arbitrary message data in order to leave open the possibility of
+passing binary data.
+
+### Starboard Interface
+
+Implementing the Starboard layer of Platform Service extension support uses the
+following interface in parallel with the IDL interface:
+
+*   [src/cobalt/extension/platform\_service.h](../extension/platform_service.h)
+
+`CobaltExtensionPlatformServiceApi` is the main interface for the Starboard
+layer.
+
+### Naming Conventions for Service Names
+
+In order to guard against namespace pollution, the Java package naming
+convention is used for Platform Services.
+
+For example, some services names could be:
+
+*   `com.google.android.CobaltPlatformService`
+*   `com.<PARTNER>.<PLATFORM>.CobaltPlatformService`
+
+## Using a Cobalt Platforms Service Extension
+
+Assuming that the implementation work is completed for the IDL and
+complimentary Starboard interface, an example usage of an extension from the
+web application could look like the following:
+
+```
+var myCobaltPlatformService = "com.google.android.CobaltPlatformService";
+
+// checks if a platform has the specified service available
+H5vccPlatformService.has(myCobaltPlatformService);
+
+// attempting to open the specified service
+service = H5vccPlatformService.open(myCobaltPlatformService,
+                            (service, data) => { console.log("do something") };
+
+// send some data
+var data = new ArrayBuffer(16);
+var view = new DataView(data);
+view.setInt32(0, 0x01234567);
+service.send(data);
+
+// close the service when we are done
+service.close();
+```
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/resources/clients_performance_guide/opacity_on_individuals.png b/src/cobalt/site/docs/gen/cobalt/doc/resources/clients_performance_guide/opacity_on_individuals.png
new file mode 100644
index 0000000..17116be
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/resources/clients_performance_guide/opacity_on_individuals.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/resources/clients_performance_guide/opacity_on_subtree.png b/src/cobalt/site/docs/gen/cobalt/doc/resources/clients_performance_guide/opacity_on_subtree.png
new file mode 100644
index 0000000..b3b1656
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/resources/clients_performance_guide/opacity_on_subtree.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/resources/devtools-overlay-console-modes.png b/src/cobalt/site/docs/gen/cobalt/doc/resources/devtools-overlay-console-modes.png
new file mode 100644
index 0000000..5103358
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/resources/devtools-overlay-console-modes.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/resources/webapi_extension_example.jpg b/src/cobalt/site/docs/gen/cobalt/doc/resources/webapi_extension_example.jpg
new file mode 100644
index 0000000..e9b43d1
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/resources/webapi_extension_example.jpg
Binary files differ
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/spherical_video.md b/src/cobalt/site/docs/gen/cobalt/doc/spherical_video.md
new file mode 100644
index 0000000..b82de1e
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/spherical_video.md
@@ -0,0 +1,76 @@
+---
+layout: doc
+title: "Enabling Spherical Video in Cobalt"
+---
+# Enabling Spherical Video in Cobalt
+
+Cobalt supports playback of 360 spherical videos.  Cobalt does not expose
+this support to web applications through WebGL (which is currently
+unimplemented in Cobalt), but rather through a custom `map-to-mesh` CSS
+filter and custom [`window.camera3D` Web API](../dom/camera_3d.idl). Support
+for spherical video in Cobalt requires a GLES rasterizer (i.e. it is not
+supported for the Starboard Blitter API), and Starboard platform support for
+the player
+[decode-to-texture output mode](../../starboard/doc/howto_decode_to_texture.md).
+
+## Enabling spherical video support
+
+Spherical video support requires `map-to-mesh` support, which is enabled by
+default. You can explicitly disable it either through the command line switch
+`--disable_map_to_mesh` or by implementing the CobaltExtensionGraphicsApi
+function `IsMapToMeshEnabled()` to return `false`.
+
+When `map-to-mesh` is supported, Cobalt will make the `map-to-mesh` CSS filter
+parseable.  The web app can then detect whether the browser, Cobalt, supports
+spherical video by evaluating the following JavaScript:
+
+```
+function checkForMapToMeshSupport() {
+  return 'CSS' in window && 'supports' in window.CSS &&
+         CSS.supports(
+             'filter',
+             'map-to-mesh(url(p.msh), 100deg 60deg,' +
+                 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1),' +
+                 'monoscopic)');
+}
+```
+
+It is required that your platform provides
+[decode-to-texture support](../../starboard/doc/howto_decode_to_texture.md).
+
+## Input
+
+Cobalt currently supports input mappings from the following keys (defined in [starboard/key.h](../../starboard/key.h)):
+
+ - `kSbKeyLeft`
+ - `kSbKeyUp`
+ - `kSbKeyRight`
+ - `kSbKeyDown`
+ - `kSbKeyGamepadDPadUp`
+ - `kSbKeyGamepadDPadDown`
+ - `kSbKeyGamepadDPadLeft`
+ - `kSbKeyGamepadDPadRight`
+ - `kSbKeyGamepadLeftStickUp`
+ - `kSbKeyGamepadLeftStickDown`
+ - `kSbKeyGamepadLeftStickLeft`
+ - `kSbKeyGamepadLeftStickRight`
+ - `kSbKeyGamepadRightStickUp`
+ - `kSbKeyGamepadRightStickDown`
+ - `kSbKeyGamepadRightStickLeft`
+ - `kSbKeyGamepadRightStickRight`
+
+Additionally, if your platform generates `kSbInputEventTypeMove` (from
+[starboard/input.h](../../starboard/input.h)) events with
+`SbInputData::position` set to values in the range `[-1, 1]`, for the following
+keys,
+
+ - `kSbKeyGamepadLeftStickUp`
+ - `kSbKeyGamepadLeftStickDown`
+ - `kSbKeyGamepadLeftStickLeft`
+ - `kSbKeyGamepadLeftStickRight`
+ - `kSbKeyGamepadRightStickUp`
+ - `kSbKeyGamepadRightStickDown`
+ - `kSbKeyGamepadRightStickLeft`
+ - `kSbKeyGamepadRightStickRight`
+
+then they will be treated as analog inputs when controlling the camera.
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/splash_screen.md b/src/cobalt/site/docs/gen/cobalt/doc/splash_screen.md
new file mode 100644
index 0000000..16651c3
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/splash_screen.md
@@ -0,0 +1,144 @@
+---
+layout: doc
+title: "Cobalt Splash Screen"
+---
+# Cobalt Splash Screen
+
+## Startup splash screen sequence
+
+There can be up to three splash screens shown when launching web applications on
+Cobalt:
+
+  * one from the system
+  * one from Cobalt
+  * one from the web application itself
+
+The system splash screen is often a transition from the application icon
+on the home screen to a static asset dictated by the platform (which is outside
+of Cobalt's control). The Cobalt splash screen is shown as soon as Cobalt can
+render until the web application is loaded. The web application splash screen is
+the HTML content shown immediately upon loading the web application (this may
+resemble a typical splash screen, but it really can be whatever the application
+chooses to show on starting).
+
+## Cobalt splash screen priority order
+
+The Cobalt splash screen must be specified as a URL to a document. The document
+must be either self-contained or all of its references must be local. That means
+the document should not reference any external CSS, JavaScript, or image files,
+for example. This simplifies the caching process so that only a single document
+must be cached without tracing references. All fallback splash screens must
+refer to local documents. This is so the fallback splash screen can be shown
+without latency and even when there is no network available. Specifically, the
+fallback splash screen URL and its references should start with either
+`file:///` or `h5vcc-embedded://`. Additionally `none` can be used to specify
+that no Cobalt splash screen should be constructed; the system splash sequence
+transitions directly into the application splash sequence once the page is
+loaded.
+
+The Cobalt splash screen is one of the following, in order of precedence:
+
+  1. **Web cached splash screen:** If a splash screen specified by a web
+     application is cached from a previous instance of Cobalt, it will be loaded
+     at startup. The key for the cache splash screen is based on host & path of
+     the initial URL with no query or hash. If network connectivity is available
+     at startup, when the initial web application URL is processed, a custom
+     `rel="splashscreen"` attribute of the link element is used to specify and
+     cache the splashscreen URL for future runs.
+
+  2. **Command line fallback splash screen:** This is specified as a command
+     line argument `--fallback_splash_screen_url` via the system and used when
+     cache is unavailable.  This is the case when there is no local cache
+     storage, cache has been cleared, or the application is started for the
+     first time.
+
+  3. **Build-time fallback splash screen:** If a web cached splash screen is
+     unavailable and command line parameters are not passed by the system,
+     a CobaltExtensionConfigurationApi fallback splash screen may be used.
+     Porters should set the `CobaltFallbackSplashScreenUrl` value in
+     `configuration.cc` to the splash screen URL.
+
+  4. **Default splash screen:** If no web cached splash screen is available, and
+     command line and CobaltExtensionConfigurationApi fallbacks are not set, a
+     default splash screen will be used. This is set in
+     `configuration_defaults.cc` to refer to a black splash screen.
+
+## Web-updatability
+
+Since Cobalt parses the link element's `rel="splashscreen"` attribute for the
+splash screen URL in the content fetched from the initial URL, an application
+developer may update the splash screen by changing that attribute in the link
+element. On the next load of the application, the new splash screen will be
+cached, and on the subsequent load of the application, the new cached splash
+screen will be shown.
+
+For example, the document at the initial URL could contain
+```
+<link rel="splashscreen" href="https://www.example.com/self-contained.html">
+```
+where `"https://www.example.com/self-contained.html"` is the address of some
+self-contained splash screen document. The document must not violate the Content
+Security Policy. The splash screen is treated as a script resource by the CSP.
+
+### Caching implementation requirements
+
+In order to cache the application-provided splash screen, Cobalt will attempt
+to create directories and write files into the directory returned from a call to
+`SbSystemGetPath(kSbSystemPathCacheDirectory, ...)`.  Cobalt will expect the
+data that it writes into that directory to persist across process instances.
+Cobalt will also need to read the cached splash screen from the cache directory
+when starting up.
+
+## Topic-specific splash screens
+
+It is possible to specify multiple splash screens for a given Cobalt-based
+application, using a start-up 'topic' to select between the available splash
+screens. This can be useful when an application has multiple entry points that
+require different splash screens. The topic may be specified in the start-up url
+or deeplink as a query parameter. For example,
+`https://www.example.com/path?topic=foo`. If a splash-screen has been specified
+for topic 'foo', it will be used. Otherwise, the topic is ignored. Topic values
+should be URL encoded and limited to alphanumeric characters, hyphens,
+underscores, and percent signs.
+
+There are three ways to specify topic-specific splash screens. These methods mirror
+the types of splash screens listed above, and unless specified, the rules here
+are the same as for non-topic-based splash screens.
+
+  1. **Web cached splash screen:** A custom `rel="<topic>_splashscreen"`
+     attribute on a link element is used to specify a topic-specific splash
+     screen. There can be any number of these elements with different topics, in
+     addition to the topic-neutral `rel="splashscreen"`.
+
+  2. **Command line fallback splash screen:** The command line argument
+     `--fallback_splash_screen_topics` can be used if the cache is unavailable.
+     The argument accepts a list of topic/file parameters. If a file is not a
+     valid URL path, then it will be used as a filename at the path specified by
+     `--fallback_splash_screen_url`. For example,
+     `foo_topic=file:///foo.html&bar=bar.html`.
+
+  3. **Build-time fallback splash screen:** If a web cached splash screen is
+     unavailable and command line parameters are not passed by the system, a
+     CobaltExtensionConfigurationApi fallback splash screen may be used. Porters
+     should set the `CobaltFallbackSplashScreenTopics` value in
+     `configuration.cc` and this value should look like the command line option.
+
+## Application-specific splash screens
+
+On systems that plan to support multiple Cobalt-based applications, an
+application developer may wish to use the command line arguments for the
+fallback splash screen to display different Cobalt splash screens for different
+applications. The logic for passing in these different command line arguments to
+the Cobalt binary must be handled by the system.
+
+Alternatively, an application developer may use the default black splash screen
+whenever a cached splash screen is not available and rely on the web application
+to specify an application-specific cached splash screen otherwise.
+
+## Provided embedded resource splash screens
+For convenience, we currently provide the following splash screens as embedded
+resources:
+
+  * `h5vcc-embedded://black_splash_screen.html` - a black splash screen
+  * `h5vcc-embedded://cobalt_splash_screen.html` - a splash screen showing the
+    Cobalt logo
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/versioning.md b/src/cobalt/site/docs/gen/cobalt/doc/versioning.md
new file mode 100644
index 0000000..020d607
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/versioning.md
@@ -0,0 +1,82 @@
+---
+layout: doc
+title: "Cobalt Versioning"
+---
+# Cobalt Versioning
+
+Cobalt versions, as they appear in the user agent, have the following structure:
+
+**[Feature Year]**.**[Purpose]**.**[Update Number]**.**[Build ID]**
+
+The meansions of these components are described below.
+
+Example Cobalt versions would be:
+
+  * `19.lts.1.40455`
+  * `19.lts.2.53047`
+  * `20.lts.1.64553`
+
+## Feature Year
+
+Cobalt features are tied to a yearly release cycle and this number indicates
+the yearly feature set that this version of Cobalt supports.  It is the last
+two digits of the year of the target feature set.  For example for the 2019
+feature set, this value will be `19`.
+
+## Purpose
+
+The purpose of this build, usually named after the reason that a branch is cut.
+On the master branch it will be `master`, and on LTS branches for example it
+will be `lts`.
+
+## Update Number
+
+The current update revision number (e.g. release number) for a given pair of
+values above.  This will always be `0` on the master branch.  When a release
+branch is cut, will be modified to start at `1`, and be incremented each time a
+release or update is released.  It is possible that multiple updates are
+released off of the same release branch, if new bugs are discovered and fixed.
+
+## Build ID
+
+The Cobalt Build ID represents **fine-grained** information about the state of
+the source tree for a given build. An internal Cobalt build server generates a
+monotonically increasing number for each unique set of sources that it
+sees. When an open-source release is published,
+a [`src/cobalt/build/build.id`](../build/build.id) file is included that
+specifies the build ID of that source release. The Cobalt team can reproduce the
+exact sources for a given Build ID.
+
+Note that since the Build ID always increases with time, it means that the
+latest version of an older Cobalt release can have a higher Build ID than the
+latest version of a new Cobalt release. An example from above: Cobalt `4.16134`
+was produced earlier than Cobalt `3.16138`, thus has a lower Build ID.
+
+## Older Cobalt versioning scheme
+
+A Cobalt version consists of two components: The Release Number and the Build
+ID. Some real historical Cobalt version examples:
+
+  * `2.15147`
+  * `3.16138`
+  * `4.16134`
+  * `6.18971`
+
+You get the idea. The number before the dot is the "Release Number." The number
+after the dot is the "Build ID."
+
+### Release Number
+
+In older Cobalt versioning schemes, a "Cobalt release" is an official, tested
+version of Cobalt that is intended to be deployable to production. The
+"Release Number" is a single counting number, starting at "1" for our first
+release, and increasing by one for every release thereafter. This number is
+checked into [`src/cobalt/version.h`](../version.h), and represents **coarse**
+information about the state of the source tree when we decided to do a release.
+
+It is important to note that there are no point releases, or major or minor
+releases. Each release gets its own unique counting number.
+
+## Other Reading
+
+  * [Cobalt Branching](branching.md)
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/voice_search.md b/src/cobalt/site/docs/gen/cobalt/doc/voice_search.md
new file mode 100644
index 0000000..f5d54a2
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/voice_search.md
@@ -0,0 +1,69 @@
+---
+layout: doc
+title: "Enabling voice search in Cobalt"
+---
+# Enabling voice search in Cobalt
+
+Cobalt enables voice search through either:
+
+1. A subset of the [MediaRecorder Web API](https://www.w3.org/TR/mediastream-recording/#mediarecorder-api).
+2. A subset of the [Speech Recognition Web API](https://w3c.github.io/speech-api/#speechreco-section)
+
+Only one or the other can be used, and we recommend that the MediaRecorder API
+is followed, as we are considering deprecating the Speech Recognition API.
+
+**The Speech Recognition API is deprecated as of Starboard 13.**
+
+In both approaches, in order to check whether to enable voice control or not,
+web apps will call the [MediaDevices.enumerateDevices()](https://www.w3.org/TR/mediacapture-streams/#dom-mediadevices-enumeratedevices%28%29)
+Web API function within which Cobalt will in turn call a subset of the
+[Starboard SbMicrophone API](../../starboard/microphone.h).
+
+## MediaRecorder API
+
+To enable the MediaRecorder API in Cobalt, the complete
+[SbMicrophone API](../../starboard/microphone.h) must be implemented, and
+`SbSpeechRecognizerIsSupported()` must return `false`.
+
+## Speech Recognition API - Deprecated
+
+**The Speech Recognition API is deprecated as of Starboard 13.**
+
+In order to provide support for using this API, platforms must implement the
+[Starboard SbSpeechRecognizer API](../../starboard/speech_recognizer.h) as well
+as a subset of the [SbMicrophone API](../../starboard/microphone.h).
+
+### Specific instructions to enable voice search
+
+1. Implement `SbSpeechRecognizerIsSupported()` to return `true`, and implement
+   the [SbSpeechRecognizer API](../../starboard/speech_recognizer.h).
+2. Implement the following subset of the
+   [SbMicrophone API](../../starboard/microphone.h):
+    - `SbMicrophoneGetAvailable()`
+    - `SbMicrophoneCreate()`
+    - `SbMicrophoneDestroy()`
+
+   In particular, SbMicrophoneCreate() must return a valid microphone.  It is
+   okay to stub out the other functions, e.g. have `SbMicrophoneOpen()`
+   return `false`.
+3. The YouTube app will display the mic icon on the search page when it detects
+   valid microphone input devices using `MediaDevices.enumerateDevices()`.
+4. With `SbSpeechRecognizerIsSupported()` implemented to return `true`, Cobalt
+   will use the platform's
+   [Starboard SbSpeechRecognizer API](../../starboard/speech_recognizer.h)
+   implementation, and it will not actually read directly from the microphone
+   via the [Starboard SbMicrophone API](../../starboard/microphone.h).
+
+### Differences from versions of Cobalt <= 11
+
+In previous versions of Cobalt, there was no way to dynamically disable
+speech support besides modifying common Cobalt code to dynamically stub out the
+Speech Recognition API when the platform does not support microphone input.
+This is no longer necessary, web apps should now rely on
+`MediaDevices.enumerateDevices()` to determine whether voice support is enabled
+or not.
+
+### Speech Recognition API is deprecated in Starboard 13 ###
+
+Web applications are expected to use the MediaRecorder API. This in turn relies
+on the SbMicrophone API as detailed above.
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/web_debugging.md b/src/cobalt/site/docs/gen/cobalt/doc/web_debugging.md
new file mode 100644
index 0000000..63ff1af
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/web_debugging.md
@@ -0,0 +1,292 @@
+---
+layout: doc
+title: "Cobalt Web Debugging"
+---
+# Cobalt Web Debugging
+
+## Overview
+
+Cobalt includes the [Chrome
+DevTools](https://developers.google.com/web/tools/chrome-devtools/) frontend for
+debugging web apps. It's available in the **20.lts.1+** and newer branches of
+Cobalt.
+
+Cobalt only supports a subset of what DevTools can do, but we make a point of
+hiding UI elements that don't work so everything you see in the UI should work.
+As we get more implemented in the backend the respective UI will be enabled in
+the frontend.
+
+The following panels are supported:
+
+*   **Elements** - view the DOM tree and CSS styles
+*   **Console** - JavaScript "command line" and logging output
+*   **Sources** - interactive JavaScript debugging
+*   **Performance** - profile JavaScript execution
+
+## Using DevTools
+
+The DevTools frontend is loaded in Chrome from a small HTTP server built into
+**non-gold** Cobalt. Even though it looks mostly the same as Chrome's inspector
+(it's built from the same source code), Cobalt's DevTools is a separate app,
+and Cobalt is *not* a remote target that you can debug with Chrome's built-in
+debugger.
+
+After building and running Cobalt as usual, use Chrome on your desktop to load
+the start page from port 9222 on the target device where Cobalt is running.
+Click through to the only inspectable page shown on the start page.
+
+> If you have trouble connecting:
+> * Ensure you have an IP route from your desktop to the target device that
+>   allows traffic on the debugging port (default 9222).
+> * If you are running Cobalt locally on your desktop, then use
+>   http://localhost:9222 since the Linux build only listens to the loopback
+>   network interface by default.
+
+If you're not sure what IP address to use, look in the terminal log output for a
+message telling you the URL of Cobalt's DevTools (which you may be able to open
+with a ctrl-click in many terminal programs):
+
+```
+---------------------------------
+ Connect to the web debugger at:
+ http://192.168.1.1:9222
+---------------------------------
+```
+
+### Wait for web debugger
+
+If you're debugging the initial page as it's loading you need use the
+`--wait_for_web_debugger` switch to tell Cobalt to wait until you attach
+DevTools before actually loading the initial URL:
+
+```
+out/linux-x64x11_devel/cobalt --wait_for_web_debugger --url="http://test.example.com"
+```
+
+When this switch is specified, Cobalt will appear to hang with just a black
+window until you load DevTools. In the terminal log output you'll see that
+Cobalt is waiting with message like:
+
+```
+-------------------------------------
+ Waiting for web debugger to connect
+-------------------------------------
+```
+
+If you're debugging a page in a series of redirects, you can specify a number to
+make Cobalt wait before loading the Nth page. If no number is specified with the
+switch, the default value is 1 to wait before the initial page load. For
+example:
+
+```
+out/linux-x64x11_devel/cobalt --wait_for_web_debugger=2 --url="http://test.example.com"
+```
+
+## Panels
+
+### Elements
+
+The Elements panel displays the DOM as a tree with expandable nodes to dig into
+it. The right side bar shows the CSS styles affecting the selected node in the
+DOM. The *Styles* tab shows matching rules, inherited rules, and inline style.
+The *Computed* tab shows the computed style for the selected node. The box model
+properties are shown graphically in both the *Styles* and *Computed* tabs.
+
+> Cobalt currently only supports a read-only view of the DOM and CSS.
+
+Chrome docs:
+
+*   https://developers.google.com/web/tools/chrome-devtools/dom/
+*   https://developers.google.com/web/tools/chrome-devtools/css/
+
+### Console
+
+Cobalt has two types of consoles:
+
+*   Overlay Console: shown at runtime of Cobalt. It has multiple mode that it
+    can cycle between as well:
+    *   HUD
+    *   HUD & Debug Console
+    *   Media Console
+*   Remote Console: shown in a connected devtools session.
+
+Both console UIs show messages logged from JavaScript (with `console.log()`,
+etc.), and have a command line to evaluate arbitrary JavaScript in the context
+of the page being debugged.
+
+#### Overlay Console
+
+The overlay console also shows non-JavaScript logging from Cobalt itself, which
+is mostly interesting to Cobalt developers rather than web app developers.
+
+The various modes of the overlay console are accessed by repeatedly pressing
+"`F1`" or "`Ctrl+O`". They cycle in order between: none, HUD, HUD & Debug, and
+Media. Alternatively, initial console state can be set with the
+`--debug_console=off|hud|debug|media` command-line switch (`--debug_console=on`
+is accepted as a legacy option and maps to "debug" setting).
+
+![Overlay Console mode switching](resources/devtools-overlay-console-flow.png)
+
+##### HUD overlay
+
+This brings up an overlay panel which does not block sending input to the
+underlying Cobalt app. It serves to display real-time statistics (e.g. memory
+usage) and configuration values (e.g. disabled codecs) of the Cobalt app in a
+compact string.
+
+##### Debug Console overlay
+
+This overlay is interactive and it shows messages from Cobalt, along with logs
+from Javascript `console.log()`. While it is active, you cannot interact
+directly with the underlying page.
+
+Additionally, it can act as a JS interpreter that will evaluate arbitrary
+expressions on the page being debugged. The output from these JS commands will
+also be printed to the Debug console.
+
+Finally, it has some special debug commands which can be listed by calling
+`d.help()`. They are provided by a debug helper object and the list of functions
+are invoked by prepending either "`debug`" or "`d`". For example, you can
+disable the vp9 codec manually for all future played videos in this session of
+Cobalt by sending `debug.disable_media_codecs("vp9")` to the console.
+
+Note: you can clear the disabled media codecs by sending
+`debug.disable_media_codecs("")`. The command takes a semicolon separated list
+of codecs as the input list of codecs to disable.
+
+##### Media Console overlay
+
+The media console is a specialized console of the debug overlay system, for
+playback and media related tasks. The current list of implemented features are:
+
+*   Reading the play/pause state of the primary video
+*   Reading the current time and duration of the primary video
+*   Reading the playback rate of the primary video
+*   Reading the currently disabled codecs for the player
+*   Toggling between playing and pausing the primary video
+*   Setting the current playback rate between various presets for the primary
+    video
+*   Toggling the enabled/disabled state of the available codecs
+
+While the media console is shown, it is not possible to interact with the page
+below it directly.
+
+Additionally, the console does not show any meaningful information or
+interactions when no video is currently playing (all the readouts are blank or
+undefined). A status message of “No primary video.” indicates there is no valid
+player element on the current page.
+
+In the case of multiple videos playing (such as picture in picture), only the
+primary (fullscreen) video’s information is shown and the controls are only
+enabled for the primary video.
+
+The list of hotkeys and commands are dynamically generated as they are found to
+be available on app startup.
+
+Basic always-enabled commands are (case-sensitive):
+
+*   "`p`" Toggle the play/pause state
+*   "`]`" Increase the playback rate
+*   "`[`" Decrease the playback rate
+
+The above commands will take effect instantly for the currently playing video.
+They have no effect if there is no video playing.
+
+The following commands are dynamically loaded based on the capability of the
+system:
+
+*   "`CTRL+NUM`" Enable/disable specific video codec
+*   "`ALT+NUM`" Enable/disable specific audio codec
+
+**Important:** Media Console cannot be used to directly select a specific codec for
+playback. See the section below for rough outline of steps to work around this.
+
+The list of available codecs for any video is chosen based on the decoders on
+the platform, and what formats YouTube itself serves. As a result, the only way
+to get a particular codec to play is to disable all the options until the
+desired codec is the one that is picked. Simply do the following procedure:
+
+*   Pick the video you want to play.
+*   Enable “stats for nerds” (See [help page for
+    instructions](https://support.google.com/youtube/answer/7519898)).
+*   Write down the codecs that are chosen when playing the video, without any
+    codecs disabled (one for video, and one for audio).
+*   Disable the default codecs.
+*   Replay the same video from the browse screen.
+*   Repeat until you identify all codecs that are available for the video, until
+    the video is unable to be played.
+*   Use the above knowledge to disable the codecs to force the player into
+    choosing a particular codec, by process of elimination.
+
+**Important:** Disabled codecs only take effect when a video starts playing.
+When you play a video, the current list of disabled codecs is used to select an
+arbitrary enabled format. When you seek in the video, the disabled codecs list
+does not take effect. Only when you exit the player and re-enter by playing a
+video will any toggled codecs be affected.
+
+**Important:** Disabled codecs list is persistent for the app-run. If you
+disable “av01”, then until you re-enable it, “av01” formats will never be
+chosen.
+
+**Important:** If you disable all the available codecs, no video codec can be
+selected and an error dialog will be shown. This means that YouTube does not
+have the video in any other formats, outside of the codecs that are disabled.
+The player reports that it cannot play the video in any of the available formats
+so playback will fail here, which is intended.
+
+#### Remote Console
+
+The console in DevTools is a richer UI that can show evaluated objects with an
+expander so you can dig in to their properties. Logging from JavaScript with
+`console.log()` can show objects and exceptions as well, in contrast to the
+text-only messages shown in the console overlay.
+
+Chrome docs:
+
+*   https://developers.google.com/web/tools/chrome-devtools/console/
+
+### Sources
+
+Source-level JavaScript debugging can be done on the Sources panel. You can
+inspect sources, set breakpoints, see call stacks and scoped variables, add
+watch expressions, and all that good stuff.
+
+> Source debugging only works when Cobalt is built with V8.
+
+Chrome docs:
+
+*   https://developers.google.com/web/tools/chrome-devtools/javascript/
+
+### Performance
+
+The Performance panel allows you to record a profile of sampled call stacks
+while Cobalt is running your JavaScript code. The recorded profile is displayed
+in a flame chart showing the relationship and timing of function calls.
+
+> Performance profiling only works when Cobalt is built with V8, and the
+> platform implements the `SbThreadSampler` Starboard API.
+
+> The profiler can't currently identify which is the main thread, but you can
+> easily see it as the one with the most events.
+
+Chrome docs:
+
+*   https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/
+
+## Tips
+
+*   You can make Cobalt reload the current page by pressing F5 in the Cobalt
+    window, or ctrl-R in the remote DevTools. This may be useful for debugging
+    startup code in the web app. It may also help in case some source file is
+    not appearing in the DevTools Sources panel.
+
+*   The DevTools frontend remembers your breakpoints, so if you need to restart
+    Cobalt completely you can just kill it with ctrl-C in the terminal where you
+    launched it and re-run it. Then click the *Reconnect DevTools* button shown
+    in the DevTools UI or refresh the page to reload the DevTools UI.
+
+*   You can use the `--remote_debugging_port` command line switch to specify a
+    remote debugging port other than the default 9222.
+
+*   You can use the `--dev_servers_listen_ip` command line switch to change
+    which network interface the remote debugging server is listening to.
diff --git a/src/cobalt/site/docs/gen/cobalt/doc/webapi_extension.md b/src/cobalt/site/docs/gen/cobalt/doc/webapi_extension.md
new file mode 100644
index 0000000..f3c7b42
--- /dev/null
+++ b/src/cobalt/site/docs/gen/cobalt/doc/webapi_extension.md
@@ -0,0 +1,113 @@
+---
+layout: doc
+title: "Cobalt Web Extension Support"
+---
+# Cobalt Web Extension Support
+
+## Deprecation
+Please note that Web Extension support is deprecated. Please use Platform
+Services (cobalt/doc/platform_services.md) instead. This is an effort to move
+away from injecting compile-time modules into the Cobalt layer in favor of
+using runtime extensions provided by the Starboard layer.
+
+## Overview
+Cobalt provides a facility for extending the JavaScript Web API.  This allows
+custom web apps running on Cobalt to make calls through a custom API to
+C++ Cobalt code defined per Starboard platform.  This can allow for closer
+integration between the web app hosted by Cobalt and the system on which that
+web app is running.
+
+The Cobalt Web Extension support will allow you to attach an instance of a
+custom class to the JavaScript `window` global object so that it can be
+referenced from a web app in JavaScript as in the following example:
+
+```
+window.myInterface.RunMyFunction()
+```
+
+## Build-level modifications
+
+In order to extend the interface, one should add the following lines to the
+`variables` section of `<platform-directory>/cobalt/configuration.gypi` (see
+Starboard's
+[Application Customization](../../starboard/doc/building.md#application-customization)
+for more information):
+
+1. `cobalt_webapi_extension_source_idl_files`
+   This should be a list of [IDL files](https://en.wikipedia.org/wiki/Web_IDL)
+   that define the collection of new interfaces introduced by your extensions.
+   One of these new interfaces can be selected to be injected into the `window`
+   element (see 3. `cobalt_webapi_extension_gyp_target` for information on how
+   to do this).  Each IDL file listed here simultaneously defines a JavaScript
+   and a C++ interface.  For each IDL file, you will be expected to also provide
+   a header file in the same directory that re-declares (in C++) the interface
+   declared in the IDL file, as well as an implementation of all the methods
+   within it (either inline in the header file or in a corresponding source
+   file).
+2. `cobalt_webapi_extension_generated_header_idl_files`
+   This is a list of all files that may result in automatic header file
+   generation that might be referenced from other C++ code.  An example of
+   this is the definition of `enum`s that may then be referenced as types in
+   a file from 1. `cobalt_webapi_extension_source_idl_files`.
+3. `cobalt_webapi_extension_gyp_target`
+   This is the gyp target that will provide the IDL interface implementations,
+   as well as any necessary auxiliary code.  It will be added as a dependency of
+   [browser/cobalt.gyp:cobalt](../browser/cobalt.gyp).  It is expected that
+   this target will implement the interface defined in
+   [browser/webapi_extension.h](../browser/webapi_extension.h), which let you
+   name the injected window property, and provide a function to instantiate it
+   (i.e. to let you select which IDL object is the "entry point").
+
+The first two lists get included by
+[cobalt/browser/browser_bindings_gen.gyp](cobalt/browser/browser_bindings_gen.gyp),
+where you can look to see many examples of existing Cobalt IDL files that define
+the Web API available through Cobalt.  For each of these, you can also
+examine their corresponding `.h` files and in most cases their `.cc` files as
+well.
+
+An example configuration for these variables is available at
+[starboard/shared/test_webapi_extension/test_webapi_extension.gypi](../../starboard/shared/test_webapi_extension/test_webapi_extension.gypi), which
+contains the following variable definitions:
+
+```
+'cobalt_webapi_extension_source_idl_files': [
+  'my_new_interface.idl'
+],
+'cobalt_webapi_extension_generated_header_idl_files': [
+  'my_new_enum.idl'
+],
+'cobalt_webapi_extension_gyp_target':
+  '<(DEPTH)/starboard/shared/test_webapi_extension/webapi_extension.gyp:cobalt_test_webapi_extension',
+```
+
+## Implementing the [webapi_extension.h](../browser/webapi_extension.h) interface
+
+As discussed above in 3. `cobalt_webapi_extension_gyp_target`, you must provide
+an implementation of the two functions declared in
+[browser/webapi_extension.h](../browser/webapi_extension.h).
+
+### `GetWebAPIExtensionObjectPropertyName()`
+You should implement `GetWebAPIExtensionObjectPropertyName()` to return the name
+of the injected `window` property.  For example, in the example from the
+beginning of this document, `window.myInterface.RunMyFunction()`, we would have
+the function return `std::string("myInterface")`.  If you return `nullopt` from
+this function, it is assumed that you do not wish to extend the web interface.
+
+Note that you should NOT name your `window` property the same as your class name
+as described in the IDL file, it will result in a name collision in the
+JavaScript environment.
+
+### `CreateWebAPIExtensionObject()`
+This function should instantiate and return the object to be accessed from
+`window`.  The object must be defined by an IDL file.
+
+## Debugging
+You may find the Cobalt debug console to be particularly useful for debugging
+IDL additions and changes.  In it, you can enter arbitrary JavaScript and then
+hit enter to execute it.  You can toggle it open by hitting either CTRL+O or
+F1, and you may have to hit the key twice to skip past the HUD mode.
+
+Here is an example of an example interface being exercised through the
+debug console:
+
+![Debug console web extension example](resources/webapi_extension_example.jpg)
diff --git a/src/cobalt/site/docs/gen/starboard/build/doc/gn_migrate_stub_to_platform.md b/src/cobalt/site/docs/gen/starboard/build/doc/gn_migrate_stub_to_platform.md
new file mode 100644
index 0000000..f717d32
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/build/doc/gn_migrate_stub_to_platform.md
@@ -0,0 +1,132 @@
+---
+layout: doc
+title: "Stub to Platform GN Migration"
+---
+# Stub to Platform GN Migration
+
+This document outlines a step by step process for converting the stub platform's
+GN files to GN files that will be able to be built for your platform. It assumes
+you have an already working port of Starboard using GYP.
+
+## Steps to Migrate Stub Files to your platform's GN Files
+
+This is **one** way for migrating your platform from GYP to GN. The benefit of
+following this is that you can have regular checkpoints to see if your migration
+is going correctly, rather than trying to do the entire migration at once where
+it's uncertain how much progress is being made. \
+Here are the steps to do your migration:
+
+1.  [Copy stub files over to your platform and build them](#copy-stub-files-over-to-your-platform-and-build-them).
+2.  [Replace stub toolchain with your platform's toolchain](#replace-stub-toolchain-with-your-platforms-toolchain).
+3.  [Replace stub configuration with your platform's configuration](#replace-stub-configuration-with-your-platforms-configuration).
+4.  [Replace stubbed starboard_platform target sources with your platform's
+    sources](#replace-stubbed-starboardplatform-sources-with-your-platforms-sources).
+
+After each step, you should be able to build the starboard_platform target.
+For example, you would build raspi2 starboard_platform target with the following
+commands:
+```
+$gn gen out/raspi-2gn_devel --args='target_platform="raspi-2" build_type="devel"'
+$ninja -C out/raspi-2gn_devel/ starboard
+```
+
+### Copy Stub Files Over to Your Platform and Build Them
+
+Here is a list of steps outlining which files to copy over and how to build
+those files:
+
+1.  Copy over files from the stub implementation to the platform folder. This
+    list gives you an example of which files to copy over for your platform.
+    This is an example for files to be copied over for your platform's port at
+    starboard/YOUR_PLATFORM
+    *   starboard/stub/BUILD.gn > starboard/YOUR_PLATFORM/BUILD.gn
+    *   starboard/stub/platform_configuration/BUILD.gn >
+        starboard/YOUR_PLATFORM/platform_configuration/BUILD.gn
+    *   starboard/stub/platform_configuration/configuration.gni >
+        starboard/YOUR_PLATFORM/platform_configuration/configuration.gni
+    *   starboard/stub/toolchain/BUILD.gn >
+        starboard/YOUR_PLATFORM/toolchain/BUILD.gn
+2.  Add your platform path to starboard/build/platforms.gni as referenced
+    [here](../migrating_gyp_to_gn.md#adding-your-platform-to-starboard)
+3.  Resolve any errors which come up for missing/incorrect file paths. Then, you
+    should be able to build your platform target with the stubbed out files
+    suggested in the above section.
+
+### Replace Stub Toolchain with Your Platform's Toolchain
+
+Follow instructions [here](../migrating_gyp_to_gn.md#migrating-a-toolchain) for
+migrating the toolchain. Resolve errors and build the starboard_platform target
+with the stubbed files.
+
+### Replace Stub Configuration with Your Platform's Configuration
+
+This involves migrating the compiler flags and build variables as referenced
+[here](../migrating_gyp_to_gn.md#migrating-a-platform).
+
+> **Highly recommended** \
+> It’s good to turn off the `treat_warnings_as_errors flag` until you can compile
+> the starboard_platform target with the platform files.
+> If this flag is not disabled you might run into a lot of
+> warnings turned errors and it might take time to solve all those errors.
+> Meanwhile you won't be in a buildable state which might make it uncertain as to
+> how much progress you are actually making.
+> For disabling the flag you can pass that as an argument to gn.
+> Here's an example for disabling the flag for raspi2:
+> ```
+> $gn gen out/raspi-2gn_devel --args='target_platform="raspi-2" build_type="devel" treat_warnings_as_errors=false'
+> ```
+
+Resolve errors and build the starboard_platform target with the stubbed files.
+
+### Replace Stubbed starboard_platform Sources with Your Platform's Sources
+
+This involves adding files for the starboard_platform target as suggested
+[here](../migrating_gyp_to_gn.md#migrating-a-platform).
+
+While building any target, follow the recommendation above of building the
+target with `treat_warnings_as_errors=false`.
+
+Once you can build your platform files, you can remove the
+`treat_warnings_as_errors=false` flag and resolve the warning errors.
+
+## FAQ
+
+1.  **I’m getting a build error! What should I do?** \
+    Some common questions to ask yourself:
+
+    *   Is the same target building with GYP + ninja (as GN + Ninja)?
+
+        > For example if the `nplb` target is not being built by GN, check first
+        > if it can be built with GYP. If GYP cannot build it, this indicates
+        > that some flags are missing in GYP itself so it might be prudent to
+        > solve that first before migrating to GN.
+
+    *   Am I missing a config/dependency to include the missing file?
+
+        > [gn check](https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/reference.md#cmd_check)
+        > can help point out missing dependencies.
+
+    *   Is the same file being included in the build by GYP?
+
+        > Add a preprocessor directive like #error "This file is included" in
+        > that file and see if GYP + Ninja prints out that error message.
+
+    *   Is the same code path being followed by GYP + ninja ?
+
+        > Use the same method as above.
+
+    *   Are the compiler flags for this file the same as in GYP ?
+
+        > To compare flags for GYP vs GN refer
+        > [section](../migrating_gyp_to_gn.md#validating-a-target). To check if
+        > the variables/flags you are compiling have changed since GYP, refer
+        > [page](../migration_changes.md).
+
+    *   Have you passed in the default arguments for your platform correctly?
+
+        > Default variables such as `target_cpu`, `target_os` and others can be
+        > overridden by passing arguments to gn while building. Here's an
+        > example of passing the default argument `target_cpu` for raspi2:
+        > ```
+        > $gn gen out/raspi-2gn_devel --args='target_platform="raspi-2" build_type="devel" target_cpu="arm"'
+        > ```
diff --git a/src/cobalt/site/docs/gen/starboard/build/doc/migrating_gyp_to_gn.md b/src/cobalt/site/docs/gen/starboard/build/doc/migrating_gyp_to_gn.md
new file mode 100644
index 0000000..07b4968
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/build/doc/migrating_gyp_to_gn.md
@@ -0,0 +1,262 @@
+---
+layout: doc
+title: "Migrating GYP to GN"
+---
+# Migrating GYP to GN
+
+Cobalt is currently in the process of migrating from our current build system
+which uses [GYP][gyp_home] to an updated one with
+[Generate Ninja (GN)][gn_home]. This allows us to remove our dependencies on
+Python 2.
+
+## Getting Started with GN
+
+### Getting the Binary
+
+There are a few ways to get a binary. Follow the instructions for whichever way
+you prefer [here][gn_getting_a_binary].
+
+### Read the Docs
+
+Most of the documentation for GN is located [here][gn_doc_home].
+
+*   For a hands-on example with GN, check out the
+    [Quick Start Guide][gn_quick_start] and walk through the example.
+
+*   To learn more about the language and coding in it, read through the
+    [Language page][gn_language] and the [Style Guide][gn_style_guide].
+
+*   For a full reference of the language, run `gn help` or use the
+    [Reference page][gn_reference].
+
+If you're familiar with GYP but not with GN, it may be helpful to read
+Chromium's [GYP->GN Conversion Cookbook][gyp_to_gn_cookbook]. Keep in mind we
+don't want to follow everything that's recommended here—much of the advice is
+specific to Chromium. In particular:
+
+*   Whenever possible, avoid using a `source_set`. Instead, use a
+    `static_library`.
+*   Many of the flags under [Variable Mappings][gyp_to_gn_variable_mappings] do
+    not apply to Cobalt.
+*   Cobalt code is not Chromium code by default, so you can ignore
+    [that section][gyp_to_gn_chromium_code].
+
+### Know the Tools
+
+The flow of GN is fairly similar to that of GYP: you'll configure a build then
+actually build it (using ninja). Here's how to build `nplb` target for
+`stub_debug`:
+
+```
+$ gn gen out/stub_debug --args='target_platform="stub" build_type="debug"'
+$ ninja -C out/stub_debug nplb
+```
+
+You can change the directory argument to `gn gen` (`out/stub_debug`) if you'd
+like; unlike GYP, we can put the build root wherever we want.
+
+There are some additional important tools: `gn format`, which is a code
+formatter for GN, and `gn check`, which checks that build dependencies are
+correctly set. See the documentation for [gn format][gn_format_tool] and
+[gn check][gn_check_tool] for how to use both. The full list of commands GN
+supports can be found on the [reference page][gn_reference].
+
+## Migrating a Single Target
+
+GYP and GN are very similar within the scope of a single target. The GYP->GN
+Conversion Cookbook is a good reference for this, particularly
+[this section][gyp_to_gn_typical_modifications]. The GYP syntax stays very
+similar in general, though configuration will differ: in GN, you should create a
+`config` targets and have your target add that to their list of configs:
+
+```
+config("foo_config") {
+  cflags = ...
+}
+
+static_library("foo") {
+  sources = ...
+  deps = ...
+
+  configs += [ ":foo_config" ]
+}
+```
+
+You also may need to remove default configs. The default configs are listed in
+[BUILDCONFIG.gn](../config/BUILDCONFIG.gn). You remove a config like so:
+
+```
+static_library("foo") {
+  configs -= [ "//full/path/to/config:config_name" ]
+}
+```
+
+## Migrating a Platform
+
+When porting your platform with GYP following
+[the porting guide][cobalt_porting_guide], we expected a few build files to be
+present under your starboard path:
+
+*   `gyp_configuration.py`
+*   `gyp_configuration.gypi`
+*   `starboard_platform.gyp`
+
+These contain your toolchain, your compilation flags, your platform-specific
+build variables, and your definition of the `starboard_platform` target. This
+maps to the GN files needed to port your platform:
+
+*   Your toolchain: `toolchain/BUILD.gn`
+*   Your compilation flags: `platform_configuration/BUILD.gn`
+*   Your platform-specific build variables:
+    `platform_configuration/configuration.gni`
+*   Your definition of the `starboard_platform` target: `BUILD.gn`
+
+Some of these files need to define certain targets:
+
+*   `toolchain/BUILD.gn`
+
+    The toolchain implementation is discussed in more detail
+    [below](#migrating-a-toolchain).
+
+    ```
+    toolchain("host") {
+      ...
+    }
+
+    toolchain("target") {
+      ...
+    }
+    ```
+
+*   `platform_configuration/BUILD.gn`
+
+    ```
+    config("platform_configuration") {
+      # Set the flags that were in gyp_configuration.gypi.
+    }
+    ```
+
+*   `BUILD.gn`
+
+    ```
+    static_library("starboard_platform") {
+      # Largely the same as the current starboard_platform.gyp.
+    }
+    ```
+
+### Adding Your Platform to Starboard
+
+Instead of implicitly searching directories for certain files like GYP did, we
+explicitly enumerate our ports and their locations.
+[platforms.gni](../platforms.gni) contains all of this information, and you'll
+need to add your platform to that list following the same format.
+
+### Migrating a Family of Platforms
+
+Cobalt's reference platforms when implemented in GYP mainly used variables to
+share sources and dependencies. In GN, we prefer putting shared sources and
+dependencies in a static_library that we depend on in the final
+`starboard_platform` `static_library` target. This means that configurations to
+particular files should be in the same `static_library` that files are in.
+
+### Migrating a Toolchain
+
+Cobalt expects you to set a target and a host toolchain for your build like so:
+
+```
+toolchain("host") {
+  ...
+}
+
+toolchain("target") {
+  ...
+}
+```
+
+You may define a toolchain from scratch following the [reference][gn_toolchain],
+or you can use the
+[gcc/clang templates](../../../build/toolchain/gcc_toolchain.gni) provided.
+Almost all of the reference platforms use these templates, so look to those as
+examples for how to use it correctly. Here's the linux-x64x11
+[toolchain/BUILD.gn file](../../linux/x64x11/toolchain/BUILD.gn).
+
+## Checking Your Migration
+
+There are a few different ways to ensure you've migrated a target successfully.
+You'll of course want to make sure you can build things after you've migrated
+them.
+
+### Validating a Target
+
+If you're migrating a single target, it's simple to check: just configure the
+build using the the necessary arguments then build that target with `ninja`,
+i.e.:
+
+```
+static_library("new_target") { ... }
+```
+
+```
+$ gn gen out/stub_debug --args='target_platform="stub" build_type="debug"'
+$ gn check out/stub_debug
+$ ninja -C out/stub_debug new_target
+```
+
+If this was equivalent to a GYP target, you can compare the ninja compilation
+databases by using [format_ninja.py](../../../tools/format_ninja.py) and a
+comparison tool, i.e. [meld](https://meldmerge.org/). This will allow you to see
+any changes in commands, i.e. with flags or otherwise.
+
+The following differences for ninja flags between GYP and GN don't cause any
+issues:
+
+1. The name of the intermediate .o, .d files is different in both cases: Here is
+   an example while compiling the same source file
+   ```
+   starboard/common/new.cc
+   ```
+   GYP generates:
+   ```
+   obj/starboard/common/common.new.cc.o
+   ```
+   GN generates:
+   ```
+   obj/starboard/common/common/new.o
+   ```
+2. The `-x` flag for specifying language is not present in GN migration.
+   For example GYP specifies `-x c` flag while building c language files for
+   certain targets. This flag is not specified while building any GN targets.
+
+### Validating a Platform
+
+Checking that an entire platform has been migrated successfully is slightly more
+involved. It can be easiest to start by copying provided stub implementation and
+continuously migrating it over, checking that it builds as you go along. If you
+don't go this route, you can instead start by building a small target (with few
+dependencies) then work your way up to building the `all` target.
+
+You can use the same comparison method of using `format_ninja.py` as discussed
+[in the section above](#validating-a-target).
+
+### Step by Step Stub to Your Platform Migration Guide
+
+This [document](../gn_migrate_stub_to_platform.md) outlines a step by step
+process for converting the stub platform's GN files to GN files that will be
+able to be built for your platform.
+
+[cobalt_porting_guide]: https://cobalt.dev/starboard/porting.html
+[gn_check_tool]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/reference.md#cmd_check
+[gn_doc_home]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs
+[gn_format_tool]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/reference.md#cmd_format
+[gn_getting_a_binary]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/#getting-a-binary
+[gn_home]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/
+[gn_language]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/language.md
+[gn_reference]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/reference.md
+[gn_style_guide]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/style_guide.md
+[gn_toolchain]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/reference.md#func_toolchain
+[gn_quick_start]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/quick_start.md
+[gyp_home]: https://gyp.gsrc.io/index.md
+[gyp_to_gn_chromium_code]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/cookbook.md#chromium-code
+[gyp_to_gn_cookbook]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/cookbook.md
+[gyp_to_gn_typical_modifications]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/cookbook.md#typical-sources-and-deps-modifications
+[gyp_to_gn_variable_mappings]: https://cobalt.googlesource.com/third_party/gn/+/refs/heads/main/docs/cookbook.md#variable-mappings
diff --git a/src/cobalt/site/docs/gen/starboard/build/doc/migration_changes.md b/src/cobalt/site/docs/gen/starboard/build/doc/migration_changes.md
new file mode 100644
index 0000000..38d8477
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/build/doc/migration_changes.md
@@ -0,0 +1,72 @@
+---
+layout: doc
+title: "GYP to GN Migration Changes"
+---
+# GYP to GN Migration Changes
+
+This file tracks changes to configuration meta build configuration variables in
+the GYP to GN migration. Reference the table below to find the correct GN
+equivalent to a changed variable, deprecated GYP variables not in GN, and added
+variables.
+
+## Variable Changes
+
+*GYP*                                     | *GN*                                                 | *GN import*
+:---------------------------------------- | :--------------------------------------------------- | :----------
+`OS` ("starboard"/other)                  | `is_starboard` (true/false)                          | (global)
+`clang` (0/1)                             | `is_clang` (true/false)                              | (global)
+`has_input_events_filter`                 | `is_internal_build` (true/false)                     | (global)
+`has_drm_system_extension`                | `is_internal_build` (true/false)                     | (global)
+`has_cdm`                                 | `is_internal_build` (true/false)                     | (global)
+`has_private_system_properties`           | `is_internal_build` (true/false)                     | (global)
+`sb_deploy_output_dir`                    | `sb_install_output_dir`                              | `//starboard/build/config/base_configuration.gni`
+`sb_evergreen` (0/1)                      | `sb_is_evergreen` (true/false)                       | `//starboard/build/config/base_configuration.gni`
+`sb_evergreen_compatible` (0/1)           | `sb_is_evergreen_compatible` (true/false)            | `//starboard/build/config/base_configuration.gni`
+`sb_evergreen_compatible_libunwind` (0/1) | `sb_evergreen_compatible_use_libunwind` (true/false) | `//starboard/build/config/base_configuration.gni`
+`sb_evergreen_compatible_lite` (0/1)      | `sb_evergreen_compatible_enable_lite` (true/false)   | `//starboard/build/config/base_configuration.gni`
+`sb_disable_cpp14_audit`                  | (none)                                               |
+`sb_disable_microphone_idl`               | (none)                                               |
+`starboard_path`                          | (none)                                               |
+`tizen_os`                                | (none)                                               |
+`includes_starboard`                      | (none)                                               |
+(none)                                    | `has_platform_tests` (true/false)                    | `//starboard/build/config/base_configuration.gni`
+(none)                                    | `has_platform_targets` (true/false)                  | `//starboard/build/config/base_configuration.gni`
+(none)                                    | `install_target_path` (true/false)                   | `//starboard/build/config/base_configuration.gni`
+
+## Other Changes
+
+*GYP*                           | *GN*                                                  | *Notes* (see below)
+:------------------------------ | :---------------------------------------------------- | :------------------
+`'STARBOARD_IMPLEMENTATION'`    | `"//starboard/build/config:starboard_implementation"` | Starboard Implementation
+`optimize_target_for_speed` (0) | `"//starboard/build/config:size"`                     | Optimizations
+`optimize_target_for_speed` (1) | `"//starboard/build/config:speed"`                    | Optimizations
+`compiler_flags_*_speed`        | `speed_config_path`                                   | Optimizations
+`compiler_flags_*_size`         | `size_config_path`                                    | Optimizations
+`sb_pedantic_warnings`          | `pedantic_warnings_config_path`                       | Compiler Options
+`sb_pedantic_warnings`          | `no_pedantic_warnings_config_path`                    | Compiler Options
+
+Notes:
+
+*   *Starboard Implementation:* If your platform defined
+    `STARBOARD_IMPLENTATION` in its implementation, you would now add the above
+    config with `configs +=
+    ["//starboard/build/config:starboard_implementation"]`.
+
+*   *Optimizations:* Cobalt defaults to building targets to optimize for size.
+    If you need to optimize a target for speed, remove the size config and add
+    the speed config with `configs -= [ "//starboard/build/config:size" ]` and
+    `configs += [ "//starboard/build/config:speed" ]`. You can define these
+    configurations for your platform by creating `config`s and pointing to the
+    correct ones for `speed_config_path` and `size_config_path` in your
+    platform's `platform_configuration/configuration.gni` file.
+
+*   *Compiler Options:* Cobalt compiles some targets with stricter settings
+    than others, depending on the platform. Before these targets would opt into
+    the stricter settings by settings `sb_pedantic_warnings: 1` in their
+    `variables` section. Now they will add the appropriate config like so:
+    `configs += [ "//starboard/build/config:pedantic_warnings" ]` and remove
+    the default: `configs -= [ "//starboard/build/config:no_pedantic_warnings"
+    ]`. The additional config that is used to compile these targets is
+    specified with the `pedantic_warnings_config_path` and
+    `no_pedantic_warnings_config_path` variables in your platform's
+    `platform_configuration/configuration.gni` file.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/abstract-toolchain.md b/src/cobalt/site/docs/gen/starboard/doc/abstract-toolchain.md
new file mode 100644
index 0000000..caaba83
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/abstract-toolchain.md
@@ -0,0 +1,57 @@
+---
+layout: doc
+title: "Abstract Toolchain"
+---
+# Abstract Toolchain
+
+## Motivation
+
+The aim of implementing an Abstract Toolchain is to allow porters to add
+new toolchains or customize existing ones without the need of modifying
+common code.
+
+Initially all targets were defined in one common shared file,
+`src/tools/gyp/pylib/gyp/generator/ninja.py`.
+Modifications to this file were required for replacing any of the toolchain
+components, adding platform-specific tooling, adding new toolchains, or
+accommodating platform-specific flavor of reference tool. Doing this in a
+shared file does not scale with the number of ports.
+
+## Overview
+
+The solution implemented to solve toolchain abstraction consists of adding two
+new functions to the platform specific `gyp_configuration.py` file found under:
+
+`starboard/<PLATFORM>/gyp_configuration.py`
+
+The functions to implement are:
+
+`GetHostToolchain` and `GetTargetToolchain`
+
+## Example
+
+The simplest complete GCC based toolchain, where a target and host are the same,
+and all tools are in the PATH:
+
+  class ExamplePlatformConfig(starboard.PlatformConfig)
+    # ...
+
+    def GetTargetToolchain(self):
+      return [
+        starboard.toolchains.gnu.CCompiler(),
+        starboard.toolchains.gnu.CPlusPlusCompiler(),
+        starboard.toolchains.gnu.Assembler(),
+        starboard.toolchains.gnu.StaticLinker(),
+        starboard.toolchains.gnu.DynamicLinker(),
+        starboard.toolchains.gnu.Bison(),
+        starboard.toolchains.gnu.Stamp(),
+        starboard.toolchains.gnu.Copy(),
+      ]
+
+    def GetHostToolchain(self):
+      return self.GetTargetToolchain()
+
+You can find real examples of this in the Open Source repo:
+[Linux x8611](https://cobalt.googlesource.com/cobalt/+/refs/heads/21.lts.1+/src/starboard/linux/x64x11/gyp_configuration.py)
+
+[Raspberry Pi 2](https://cobalt.googlesource.com/cobalt/+/refs/heads/21.lts.1+/src/starboard/raspi/shared/gyp_configuration.py)
diff --git a/src/cobalt/site/docs/gen/starboard/doc/api_process.md b/src/cobalt/site/docs/gen/starboard/doc/api_process.md
new file mode 100644
index 0000000..0d699d2
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/api_process.md
@@ -0,0 +1,72 @@
+---
+layout: doc
+title: "Starboard API Review Process"
+---
+# Starboard API Review Process
+
+## Why do we need a process?
+The Starboard API is the contract between Starboard applications and
+implementors of the Starboard API. Changing existing APIs and adding new
+required APIs breaks that contract and increases the cost of implementors
+keeping their Starboard port up-to-date. Pushing a release to the Open Source
+repository signals to Starboard implementors that any non-experimental APIs in
+that version will not change for as long as that version of Starboard is
+supported by the Starboard applications. We cannot change those newly frozen
+APIs without causing a potentially significant disruption to any partners who
+have already implemented them, or are in the process of implementing them.
+
+While having a process may make it harder to add new things to Starboard, it is
+much harder to remove or change things that are already there.
+
+Thus we need to give special focus to changes to the Starboard API to ensure its
+consistency with existing APIs design principles. Unnecessary churn on the
+Starboard API creates more work for Starboard application developers and may
+discourage porters from keeping Starboard applications up-to-date on their
+platforms. This process is intended to save time and effort for both Starboard
+application developers and Starboard implementors in the long run, and
+illustrates the complexity of dealing with a wide variety of platforms
+simultaneously.
+
+## So you want to add a new API?
+Historically, we have done API review as a part of the Code Review process using
+Gerrit. This works well for small-ish changes. For larger changes, consider
+writing a design document up front before defining the new API.
+
+### Who does the review?
+Send a message to the public cobalt-dev group to request a review.
+
+### What is the process?
+Developers are strongly encouraged to create the interface and upload that to
+Gerrit for review before spending time on stubs and tests. Iteration on the
+interface will necessarily result in changes to the stubs and tests, which can
+result in more work for the implementer of a new API.
+
+1. Upload a .h file with Module Overview and (optionally) initial function
+   prototypes
+    * New APIs should be declared in the experimental version, as described in the
+      starboard versioning doc.
+2. Discuss the new API with whoever is performing the review, and address
+   comments.
+3. Iterate.
+    * As a part of the review process, the reviewer will work with you to ensure
+      that the new API adheres to the starboard principles.
+4. Finalize function declarations.
+5. Implement tests and stubs.
+    * Existing platforms on trunk should not break as a result of this change.
+    * At this point, you may submit the interface, tests, and stubs with your
+      reviewer’s +2.
+6. Implement the interface for at least one platform.
+7. Iterate
+8. It may be that implementation of the API reveals things that were overlooked
+   during the earlier stages of the review.
+
+Ideally most major points of feedback will be caught early in the review process
+before much time has been spent on implementation.
+In the case that the platform in (6) is an internal platform, provide a
+reference implementation for at least one external reference platform. This can
+be in a follow-up CL, but must be implemented before the new API is frozen
+(see [versioning.md](versioning.md)).
+
+## How to design a new API
+See [principles.md](principles.md) for a guide on how to design a good Starboard
+API.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/building.md b/src/cobalt/site/docs/gen/starboard/doc/building.md
new file mode 100644
index 0000000..0281e71
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/building.md
@@ -0,0 +1,99 @@
+---
+layout: doc
+title: "Building Starboard"
+---
+# Building Starboard
+
+Starboard currently uses GYP as the basis of its build system, though there is
+already some movement towards GN as a replacement.
+
+While you can integrate Starboard into any build system, there are enough knobs
+and dials that it would be a daunting effort. Instead, Starboard tries to provide a
+functional build framework that an application developer can easily integrate with.
+
+
+## The Flow
+
+The basic flow of how Starboard builds is:
+
+1. `starboard/build/gyp` - Parse command line parameters and pass them into
+   `GypRunner`.
+2. `starboard/build/gyp_runner.py`
+   1. Load the `PlatformConfiguration`.
+   2. Load the `ApplicationConfiguration`.
+   3. Calculate and merge the GYP includes, GYP variables, environment
+      variables, and generator variables, and pass them into GYP.
+3. tools/gyp - Parse all the .gyp and included .gypi files, generate ninja.
+4. ninja - Build all the source files.
+
+
+## The Platform vs. the Application
+
+In this documentation, you will see a lot of discussion about things being
+Platform or Application concerns.
+
+The Platform is more-or-less what you think it is -- Everything you might need
+to build any Starboard Application on a given platform.
+
+It helps to think about an Application as a broader concept than a single
+program. From Starboard's build system's perspective, an Application is a
+*single configuration of build variables per platform*, which may produce many
+build targets beyond a single executable - shared libraries, tests, and so on.
+
+
+## Application Customization
+
+Each Application will probably want to define its own knobs, dials, and defaults
+to be able to be customized per platform, and so Starboard provides a space for
+the Application to do that.
+
+Each Application can provide a platform-specific ApplicationConfiguration
+instance by creating a python module in
+`<platform-directory>/<application-name>/configuration.py`. This module must
+contain a class definition that extends from
+`starboard.build.application_configuration.ApplicationConfiguration`. If the
+class is not found in the platform-specific location, a generic configuration
+will be loaded, as dictated by the `APPLICATIONS` registry in
+`starboard_configuration.py`.
+
+Additionally, the Application can provide a GYPI file to be included at
+`<platform-directory>/<application-name>/configuration.gypi`. This will, by
+default, be included at the end of all other configuration GYPI files, but this
+behavior can be arbitrarily customized by the loaded `ApplicationConfiguration`
+class.
+
+
+## HOWTO: Create a new Application
+
+1. Create your Application's root `.gyp` file. Often called `all.gyp` or
+   something similar.
+
+2. Create a cross-platform `ApplicationConfiguration` python class for your
+   application. Take a look at
+   [`cobalt_configuration.py`](../../cobalt/build/cobalt_configuration.py) as an
+   example.
+
+   Define a subclass of
+   `starboard.build.application_configuration.ApplicationConfiguration` and
+   override any desired methods. In particular, you probably at least want to
+   override the `GetDefaultTargetBuildFile()` method to point at your root
+   `.gyp` file from step 1.
+
+3. Register your Application in your `starboard_configuration.py` file in your
+   source tree root.
+
+   To do this, just add an entry to the `APPLICATIONS` Mapping that maps your
+   canonical Application name to the cross-platform `ApplicationConfiguration`
+   subclass constructor for your application.
+
+       APPLICATIONS = {
+           # ...
+
+           'example_app': example_app.ExampleAppConfiguration
+
+           # ...
+       }
+
+At this point, you should be able to build your application with:
+
+    starboard/build/gyp -a <application-name>
diff --git a/src/cobalt/site/docs/gen/starboard/doc/c99.md b/src/cobalt/site/docs/gen/starboard/doc/c99.md
new file mode 100644
index 0000000..ad2f0c7
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/c99.md
@@ -0,0 +1,84 @@
+---
+layout: doc
+title: "Starboard and C99"
+---
+# Starboard and C99
+
+## Background
+
+Historically Starboard did not allow usage of standard C symbols in order to
+isolate Cobalt from non-compliant libc implementations and to provide a single,
+consistent behavior at the Starboard API layer.
+
+## C99 Usage Rationale
+1. Inconsistencies in the libc libraries are rare and all third party libraries
+need to be ported to the Starboard API. This can be a significant maintenance
+cost as the dependencies need to be periodically rebased.
+
+2. Even with all the efforts to use POEM headers from the
+[starboard/client_porting](../../starboard/client_porting) directory many
+non-Evergreen platforms still have a lot of direct system dependencies. These
+dependencies do not exist for Evergreen platforms as Cobalt is statically
+linked with the [musl](../../third_party/musl/musl.gyp) libc library.
+
+3. Starting with Starboard 13 a limited set of C99 symbols will be allowed.
+This set will expand gradually while the corresponding Starboard APIs will be
+deprecated and eventually removed.
+
+## List of Allowed C99 Symbols
+### <ctype.h>
+* isalnum
+* isdigit
+* isspace
+* isupper
+* isxdigit
+* tolower
+* toupper
+### <math.h>
+* fabs
+* floor
+* isfinite
+* isnan
+* pow
+* sqrt
+* sqrtf
+### <stdlib.h>
+* abs
+* atoi
+* atol
+* bsearch
+* strtof
+* strtod
+* strtol
+* strtoll
+* strtoul
+* strtoull
+* qsort
+### <string.h>
+* memchr
+* memcmp
+* memcpy
+* memmove
+* memset
+* strcat
+* strchr
+* strcmp
+* strcpy
+* strcspn
+* strlen
+* strncmp
+* strncat
+* strncpy
+* strrchr
+* strstr
+* strspn
+### <wchar.h>
+* wcscat
+* wcschr
+* wcslen
+* wmemchr
+* wmemcmp
+* wmemcpy
+* wmemmove
+* wmemset
+* wcsncmp
diff --git a/src/cobalt/site/docs/gen/starboard/doc/crash_handlers.md b/src/cobalt/site/docs/gen/starboard/doc/crash_handlers.md
new file mode 100644
index 0000000..2f30683
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/crash_handlers.md
@@ -0,0 +1,56 @@
+---
+layout: doc
+title: "Installing Crash Handlers in Cobalt"
+---
+# Installing Crash Handlers in Cobalt
+
+Partners can install Crashpad's crash handlers to create crash reports in the
+cache directory. This is done by:
+
+1. Adding the following files to the `starboard_platform` target's sources:
+
+```
+'<(DEPTH)/starboard/shared/starboard/crash_handler.cc',
+'<(DEPTH)/starboard/shared/starboard/crash_handler.h',
+```
+
+2. Handling `kCobaltExtensionCrashHandlerName` in the implementation of
+`SbSystemGetExtension`:
+
+```
+#include "starboard/system.h"
+
+#include "cobalt/extension/crash_handler.h"
+#include "starboard/shared/starboard/crash_handler.h"
+
+...
+
+const void* SbSystemGetExtension(const char* name) {
+
+  ...
+
+  if (SbStringCompareAll(name, kCobaltExtensionCrashHandlerName) == 0) {
+    return starboard::common::GetCrashHandlerApi();
+  }
+  return NULL;
+}
+```
+
+3. Calling the `third_party::crashpad::wrapper::InstallCrashpadHandler()` hook
+directly after installing system crash handlers. On linux, for example, this
+could look like:
+
+```
+#include "third_party/crashpad/wrapper/wrapper.h"
+
+int main(int argc, char** argv) {
+  ...
+  starboard::shared::signal::InstallCrashSignalHandlers();
+  starboard::shared::signal::InstallSuspendSignalHandlers();
+
+  third_party::crashpad::wrapper::InstallCrashpadHandler();
+
+  int result = application.Run(argc, argv);
+  ...
+}
+```
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_lite.md b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_lite.md
new file mode 100644
index 0000000..93ff983
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_lite.md
@@ -0,0 +1,182 @@
+---
+layout: doc
+title: "Evergreen Lite Partner Doc"
+---
+Evergreen Lite Partner Doc
+
+
+## What is Cobalt Evergreen Lite?
+
+Evergreen Lite is a Cobalt configuration similar to Evergreen Full. Evergreen
+Lite takes advantage of the same Evergreen software architecture, but removes
+the need for additional storage and is missing the defining cloud-based Cobalt
+Updater feature used in Evergreen Full.
+
+Evergreen Lite relies on separating the Starboard (platform) and Cobalt (core)
+components of a Cobalt implementation into the following discrete components:
+
+![Evergreen Lite Overvew](resources/evergreen_lite_overview.png)
+
+## Components
+
+Google-built (on Google toolchain)
+
+
+*   Cobalt Core
+    *   Pre-built shared library available for all supported architectures
+*   Cobalt Updater - disabled
+
+Partner-built (on Partner toolchain)
+
+
+
+*   Starboard
+    *   Platform-specific implementation
+    *   Contains system dependencies (e.g. libpthread.so, libEGL.so)
+*   Cobalt Loader (Loader App)
+    *   Loads the Cobalt core shared library
+    *   An ELF loader is used to load the Cobalt core and resolves symbols with
+        Starboard APIs when Cobalt starts up in Evergreen mode
+*   Crash handler
+    *   Uploads crash reports to Google server when crash happens
+
+With this new Cobalt Evergreen platform architecture, less engineering effort is
+ necessary for a full Cobalt integration/deployment.
+
+**The idea here is you should only need to implement Starboard one time (as
+long as the Starboard API version is supported by Cobalt), and any Cobalt
+Core-level binary updates are provided by Google with pre-built
+configurations/symbols via our open-source releases
+([GitHub](https://github.com/youtube/cobalt/releases))**. These pre-built
+Cobalt Core Evergreen binaries should be a direct replacement to update Cobalt
+without any engineering work required. As Cobalt Core binaries are pre-built,
+they should only require platform testing. NOTE that certain new Cobalt
+features may require Starboard changes, so if you want to take advantage of
+some of these new features, Starboard changes may be necessary.
+
+### Benefits compared to non-Evergreen
+
+*   Less engineering work/accelerated timeline for Cobalt
+integration/deployment as Google builds Cobalt core code and partners only need
+to build and maintain the Starboard layer
+*   Performance enhancements as the Cobalt core is built with modern toolchain
+*   Crash reports are uploaded to Google backend and monitored by Google, so
+they can be acted on and addressed more quickly
+
+### New in Evergreen Lite compared to non-Evergreen
+
+*   New `loader_app` and `crashpad_handler` components required to be built
+on platform toolchains
+*   No Cobalt Core customization is allowed because the vanilla Cobalt Core
+binary is provided by Google.
+
+### Differences compared to Evergreen Full
+
+*   The Google-control cloud-based automatic updates are disabled. Instead,
+Cobalt provides the update binary to partners, and partners control the release
+process
+*   No extra storage required comparing to the existing software requirements
+
+## How is Evergreen different from porting Cobalt previously?
+
+Same as the [Evergreen full doc](cobalt_evergreen_overview.md).
+
+## Building Cobalt Evergreen Components
+
+`kSbSystemPathStorageDirectory` is not required to implement. Set both
+`sb_evergreen_compatible` and `sb_evergreen_compatible_lite` to `1`s in the `gyp`
+platform config. The remaining is the same as the Evergreen full doc.
+
+## How does the update work with Evergreen Lite?
+
+Cobalt will release the Cobalt Core binary to partners for each Cobalt LTS
+major and minor release, and partners decide whether to update their devices
+with the latest Cobalt Core code via firmware OTA update. To update, partners
+only need to put the new Cobalt Core binary at the system image location under
+`<kSbSystemPathContentDirectory>/app/cobalt`. More about the system image slot
+is explained below.
+
+## Platform Requirements
+
+Cobalt Evergreen currently supports the following
+
+Target Architectures:
+
+*   `x86_32`
+*   `x86_64`
+*   `armv7 32`
+*   `armv8 64`
+
+Supported Javascript Engines
+
+*   V8
+
+## Building and Running Tests
+
+Same as the Evergreen Full doc -
+[cobalt_evergreen_overview.md](cobalt_evergreen_overview.md).
+
+## System Design
+
+### Cobalt Evergreen Components
+
+Cobalt updater is disabled. The binary will not check for updates by sending
+requests to the Google update server, nor download updates from the Google
+Download server.
+
+### Cobalt Evergreen Interfaces
+
+Same as the Evergreen Full doc -
+[cobalt_evergreen_overview.md](cobalt_evergreen_overview.md).
+
+### System Image Slot
+
+Evergreen Lite will have only one system image slot.  This is stored in the
+directory specified by `kSbSystemPathContentDirectory` under the
+`app/cobalt` subdirectory.
+
+```
+.
+├── content <--(kSbSystemPathContentDirectory)
+│   └── fonts <--(kSbSystemPathFontDirectory, `standard` or `limit` configuration)
+│   └── app
+│       └── cobalt <--(System image, provided by Google)
+│           ├── content <--(relative path defined in kSystemImageContentPath)
+│           │   ├── fonts <--(`empty` configuration)
+│           │   ├── icu
+│           │   ├── licenses
+│           │   ├── ssl
+│           ├── lib
+│           │   └── libcobalt.so
+│           └── manifest.json
+└── loader_app <--(Cobalt loader binary)
+└── crashpad_handler <--(Cobalt crash handler binary)
+```
+
+### Fonts
+
+Same as the Evergreen Full doc -
+[cobalt_evergreen_overview.md](cobalt_evergreen_overview.md).
+
+## How to run Evergreen Lite
+
+Launch Cobalt with the loader app binary with the `evergreen_lite` flag
+
+```
+$ ./loader_app --evergreen_lite
+```
+## FAQ
+
+### What’s the path from Evergreen Lite to Evergreen Full?
+
+*   Provision storage for the installation slots to contain downloaded update
+binaries - `kSbSystemPathStorageDirectory `and configure the slots as instructed
+in the Evergreen full doc
+*   Configure icu table under `kSbSystemPathStorageDirectory` to be shared
+    among slots
+*   Set `sb_evergreen_compatible_lite` to 0
+*   Implement the handling of pending updates
+*   Rebuild and rerun `nplb_evergreen_compat_tests`
+*   Launch Cobalt with loader app without the `evergreen_lite` flag
+
+More details can be found in the Evergreen Full doc.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_overview.md b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_overview.md
new file mode 100644
index 0000000..4e07d8e
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_overview.md
@@ -0,0 +1,728 @@
+---
+layout: doc
+title: "Cobalt Evergreen Overview"
+---
+# Cobalt Evergreen Overview
+
+![Cobalt non-Evergreen vs
+Evergreen](resources/cobalt_evergreen_overview_flow.png)
+
+## What is Cobalt Evergreen?
+
+Cobalt Evergreen is an end-to-end framework for cloud-based deployment of Cobalt
+updates without the need for supplemental Cobalt integration work on device
+platforms.
+
+There are two configurations available:
+*   Evergreen-Lite
+    *   Please read this document for general Evergreen details then see
+        Evergreen-Lite specific configuration details in
+        [cobalt_evergreen_lite.md](cobalt_evergreen_lite.md)
+*   Evergreen Full
+    *   Please continue reading below documentation for configuration details
+
+![Cobalt Evergreen Configurations](resources/cobalt_evergreen_configurations.png)
+
+For a bit of background context, as the number of Cobalt devices in the field
+increases there is a growing proliferation of version fragmentation. Many of
+these devices are unable to take advantage of the benefits of Cobalt
+performance, security, and functional improvements as it is costly to integrate
+and port new versions of Cobalt. We recognized this issue, listened to feedback
+from the Cobalt community and as a result developed Cobalt Evergreen as a way to
+make updating Cobalt a much simpler process for everyone involved.
+
+This relies on separating the Starboard(platform) and Cobalt(core) components of
+a Cobalt implementation into the following discrete components:
+
+**Google-built** (on Google toolchain)
+
+*   Cobalt Core
+    *   Pre-built shared library available for all supported architectures
+*   Cobalt Updater
+    *   Part of Cobalt Core and used to query servers to check for and download
+        updated Cobalt Core
+
+**Partner-built** (on Partner toolchain)
+
+*   Starboard
+    *   Platform-specific implementation
+    *   Contains system dependencies (e.g. `libpthread.so`, `libEGL.so`)
+*   Cobalt Loader (Loader App)
+    *   Selects the appropriate Cobalt core for usage
+    *   An ELF loader is used to load the Cobalt core and resolves symbols with
+        Starboard APIs when Cobalt starts up in Evergreen mode
+
+With this new Cobalt platform architecture, less engineering effort is necessary
+for a full Cobalt integration/deployment. The idea here is you should only need
+to implement Starboard one time and any Cobalt-level updates should only require
+platform testing. NOTE that certain new Cobalt features may require Starboard
+changes, so if you want to take advantage of some of these new features,
+Starboard changes may be necessary.
+
+### Main Benefits
+
+*   More stable platform as there is less Cobalt version fragmentation
+*   Little-to-no engineering effort necessary for Cobalt updates
+*   Longer device lifetime due to more Cobalt updates
+*   Less engineering work/accelerated timeline for Cobalt integration/deployment
+    as Google builds the Cobalt components and partners are only responsible for
+    the Starboard, `loader_app`, and `crashpad_handler` portion
+
+### New in Evergreen
+
+*   Larger storage and system permissions requirements in order to update and
+    store multiple Cobalt binaries
+*   Access permissions to download binaries onto a device platform from Google
+    servers
+*   New `loader_app` and `crashpad_handler` components required to be built on
+    platform toolchains
+*   Additional testing/verification required to ensure new Cobalt releases work
+    properly
+
+## How is Evergreen different from porting Cobalt previously?
+
+There are minimal differences in switching to Evergreen as the Cobalt team has
+already done a majority of the work building the necessary components to support
+the Evergreen architecture. You will still be responsible for building the
+Starboard and platform-specific components as usual. Thereafter, switching to
+Evergreen is as simple as building a different configuration. Please see the
+Raspberry Pi 2 Evergreen reference port
+([Instructions](cobalt_evergreen_reference_port_raspi2.md)) for an example.
+
+![Cobalt non-Evergreen vs
+Evergreen](resources/cobalt_evergreen_overview_vs_non_evergreen.png)
+
+### Building Cobalt Evergreen Components
+
+Cobalt Evergreen requires that there are two separate build(`gyp`)
+configurations used due to the separation of the Cobalt core(`libcobalt.so`) and
+the platform-specific Starboard layer(`loader_app`). As a result, you will have
+to initiate a separate gyp process for each. This is required since the Cobalt
+core binary is built with the Google toolchain settings and the
+platform-specific Starboard layer is built with partner toolchain
+configurations.
+
+Cobalt Evergreen is built by a separate gyp platform using the Google toolchain:
+
+```
+$ cobalt/build/gyp_cobalt evergreen-arm-softfp-sbversion-12
+$ ninja -C out/evergreen-arm-softfp-sbversion-12_qa cobalt
+```
+
+Which produces a shared library `libcobalt.so` targeted for specific
+architecture, ABI and Starboard version.
+
+The gyp variable `sb_evergreen` is set to 1 when building `libcobalt.so`.
+
+The partner port of Starboard is built with the partner’s toolchain and is
+linked into the `loader_app` which knows how to dynamically load
+`libcobalt.so`, and the `crashpad_handler` which handles crashes.
+
+```
+$ cobalt/build/gyp_cobalt <partner_port_name>
+$ ninja -C out/<partner_port_name>_qa loader_app crashpad_handler
+```
+
+Partners should set `sb_evergreen_compatible` to 1 in their gyp platform config.
+DO NOT set the `sb_evergreen` to 1 in your platform-specific configuration as it
+is used only by Cobalt when building with the Google toolchain.
+
+Additionally, partners should install crash handlers as instructed in the
+[Installing Crash Handlers for Cobalt guide](../crash_handlers.md).
+
+The following additional Starboard interfaces are necessary to implement for
+Evergreen:
+
+*   `kSbSystemPathStorageDirectory`
+    *   Dedicated location for storing Cobalt Evergreen-related binaries
+    *   This path must be writable and have at least 96MB of reserved space for
+        Evergreen updates. Please see the “Platforms Requirements” section below
+        for more details.
+*   `kSbMemoryMapProtectExec`
+    *   Ensures mapped memory can be executed
+*   `#define SB_CAN_MAP_EXECUTABLE_MEMORY 1`
+    *   Specifies that the platform can map executable memory
+    *   Defined in `configuration_public.h`
+
+Only if necessary, create a customized SABI configuration for your architecture.
+Note, we do not anticipate that you will need to make a new configuration for
+your platform unless it is not one of our supported architectures:
+
+*   x86\_32
+*   x86\_64
+*   arm32
+*   arm64
+
+If your target architecture falls outside the support list above, please reach
+out to us for guidance.
+
+#### Adding Crash Handlers to Evergreen
+
+### What is an example for how this would help me?
+
+Some common versions of Cobalt in the field may show a bug in the implementation
+of the CSS which can cause layout behavior to cause components to overlap and
+give users a poor user experience. A fix for this is identified and pushed to
+Cobalt open source ready for integration and deployment on devices.
+
+#### Without Cobalt Evergreen:
+
+Though a fix for this was made available in the latest Cobalt open source,
+affected devices in the field are not getting updated (e.g. due to engineering
+resources, timing, device end-of-life), users continue to have a poor experience
+and have negative sentiment against a device. In parallel, the web app team
+determines a workaround for this particular situation, but the workaround is
+obtuse and causes app bloat and technical debt from on-going maintenance of
+workarounds for various Cobalt versions.
+
+#### With Cobalt Evergreen:
+
+The Cobalt team can work with you to guide validation and deployment of a shared
+Cobalt library to all affected devices much more quickly without all the
+engineering effort required to deploy a new Cobalt build. With this simpler
+updating capability, device behavior will be more consistent and there is less
+technical debt from workarounds on the web application side. Additionally, users
+can benefit from the latest performance, security, and functional fixes.
+
+## Platform Requirements
+
+Cobalt Evergreen currently supports the following
+
+Target Architectures:
+
+*   x86\_32
+*   x86\_64
+*   armv7 32
+*   armv8 64
+
+Supported Javascript Engines
+
+*   V8
+
+Additional reserved storage (96MB) is required for Evergreen binaries. We expect
+Evergreen implementations to have an initial Cobalt preloaded on the device and
+an additional reserved space for additional Cobalt update storage.
+
+*   Initial Cobalt binary deployment - 64MB
+*   Additional Cobalt update storage - 96MB
+    *   Required for 2 update slots under `kSbSystemPathStorageDirectory`
+
+As Cobalt Evergreen is intended to be updated from Google Cloud architecture
+without the need for device FW updates, it is important that this can be done
+easily and securely on the target platform. There are a set of general minimum
+requirements to do so:
+
+*   Writable access to the file system of a device platform to download Cobalt
+    Evergreen binaries
+*   Enough reserved storage for Cobalt updates
+*   Platform supporting mmap API with writable memory (`PROT_WRITE`,
+    `PROT_EXEC`) for loading in-memory and performing relocations for Cobalt
+    Evergreen binaries
+
+## Building and Running Tests
+
+The `elf_loader_sandbox` binary can be used to run tests in Evergreen mode. This
+is much more lightweight than the `loader_app`, and does not have any knowledge
+about installations or downloading updates.
+
+The `elf_loader_sandbox` is run using two command line switches:
+`--evergreen_library` and `--evergreen_content`. These switches are the path to
+the shared library to be run and the path to that shared library's content.
+These paths should be *relative to the content of the elf_loader_sandbox*.
+
+For example, if we wanted to run the NPLB set of tests and had the following
+directory tree,
+
+```
+.../elf_loader_sandbox
+.../content/app/nplb/lib/libnplb.so
+.../content/app/nplb/content
+```
+
+we would use the following command to run NPLB:
+
+```
+.../elf_loader_sandbox --evergreen_library=app/nplb/lib/libnplb.so
+                       --evergreen_content=app/nplb/content
+```
+
+Building tests is identical to how they are already built except that a
+different platform configuration must be used. The platform configuration should
+be an Evergreen platform configuration, and have a Starboard ABI file that
+matches the file used by the platform configuration used to build the
+`elf_loader_sandbox`.
+
+For example, building these targets for the Raspberry Pi 2 would use the
+`raspi-2` and `evergreen-arm-hardfp` platform configurations.
+
+## Verifying Platform Requirements
+
+In order to verify the platform requirements you should run the
+`nplb_evergreen_compat_tests`. These tests ensure that the platform is
+configured appropriately for Evergreen.
+
+To enable the test, set the `sb_evergreen_compatible gyp` variable to 1 in the
+`gyp_configuration.gypi`. For more details please take a look at the Raspberry
+Pi 2 gyp files.
+
+There is a reference implementation available for Raspberry Pi 2 with
+instructions available [here](cobalt_evergreen_reference_port_raspi2.md).
+
+### Verifying Crashpad Uploads
+
+1. Build the `crashpad_database_util` target and deploy it onto the device.
+```
+$ cobalt/build/gyp_cobalt <partner_port_name>
+$ ninja -C out/<partner_port_name>_qa crashpad_database_util
+```
+2. Remove the existing state for crashpad as it throttles uploads to 1 per hour:
+```
+$ rm -rf <kSbSystemPathCacheDirectory>/crashpad_database/
+
+```
+3. Launch Cobalt.
+4. Trigger crash by sending `abort` signal to the `loader_app` process:
+```
+$ kill -6 <pid>
+```
+5. Verify the crash was uploaded through running `crashpad_database_util` on the device
+pointing it to the cache directory, where the crash data is stored.
+
+```
+$ crashpad_database_util -d <kSbSystemPathCacheDirectory>/crashpad_database/ --show-completed-reports --show-all-report-info
+```
+
+```
+8c3af145-30a0-43c7-a3a5-0952dea230e4:
+  Path: cobalt/cache/crashpad_database/completed/8c3af145-30a0-43c7-a3a5-0952dea230e4.dmp
+  Remote ID: c9b14b489a895093
+  Creation time: 2021-06-01 17:01:19 HDT
+  Uploaded: true
+  Last upload attempt time: 2021-06-01 17:01:19 HDT
+  Upload attempts: 1
+```
+
+In this example the minidump was successfully uploaded because we see `Uploaded: true`.
+
+Reference for [crashpad_database_util](https://chromium.googlesource.com/crashpad/crashpad/+/refs/heads/main/tools/crashpad_database_util.md)
+
+## System Design
+
+![Cobalt Evergreen
+Components](resources/cobalt_evergreen_overview_components.png)
+
+The above diagram is a high-level overview of the components in the Cobalt
+Evergreen architecture.
+
+* **Partner-built** represents components the Partner is responsible for
+  implementing and building.
+
+* **Cobalt-built** represents components the Cobalt team is responsible for
+  implementing and building.
+
+### Cobalt Evergreen Components
+
+#### Cobalt Updater
+
+This is a new component in the Cobalt Shared Library component that is built on
+top of the Starboard API. The purpose of this module is to check the update
+servers if there is a new version of the Cobalt Shared Library available for the
+target device. If a new version is available, the Cobalt updater will download,
+verify, and install the new package on the target platform. The new package can
+be used the next time Cobalt is started or it can be forced to update
+immediately and restart Cobalt as soon as the new package is available and
+verified on the platform. This behavior will take into account the
+suspend/resume logic on the target platform.
+
+Functionally, the Cobalt Updater itself runs as a separate thread within the
+Cobalt process when Cobalt is running. This behavior depends on what the target
+platform allows.
+
+For more detailed information on Cobalt Updater, please take a look
+[here](cobalt_update_framework.md).
+
+#### Google Update (Update Server)
+
+We use Google Update as the infrastructure to manage the Cobalt Evergreen
+package install and update process. This has been heavily used across Google for
+quite some time and has the level of reliability required for Cobalt Evergreen.
+There are also other important features such as:
+
+*   Fine grained device targeting
+*   Rollout and rollback
+*   Multiple update channels (e.g. production, testing, development)
+*   Staged rollouts
+
+For more detailed information on Google Update for Cobalt Evergreen, please take
+a look [here](cobalt_update_framework.md).
+
+#### Google Downloads (Download Server)
+
+We use Google Downloads to manage the downloads available for Cobalt Evergreen.
+The Cobalt Updater will use Google Downloads in order to download available
+packages onto the target platform. We selected Google Downloads for this purpose
+due to its ability to scale across billions of devices as well as the
+flexibility to control download behavior for reliability.
+
+For more detailed information on Google Downloads (Download Server) for Cobalt
+Evergreen, please take a look [here](cobalt_update_framework.md).
+
+### Cobalt Evergreen Interfaces
+
+#### Starboard ABI
+
+The Starboard ABI was introduced to provide a single, consistent method for
+specifying the Starboard API version and the ABI. This specification ensures
+that any two binaries, built with the same Starboard ABI and with arbitrary
+toolchains, are compatible.
+
+Note that Cobalt already provides default SABI files for the following
+architectures:
+
+*   x86\_32
+*   x86\_64
+*   arm v7 (32-bit)
+*   arm v8 (64-bit)
+
+You should not need to make a new SABI file for your target platform unless it
+is not a currently supported architecture. We recommend that you do not make any
+SABI file changes. If you believe it is necessary to create a new SABI file for
+your target platform, please reach out to the Cobalt team to advise.
+
+For more detailed information on the Starboard ABI for Cobalt Evergreen, please
+take a look here.
+
+### Installation Slots
+
+Cobalt Evergreen provides support for maintaining multiple, separate versions of
+the Cobalt binary on a platform. These versions are stored in installation
+slots(i.e. known locations on disk), and are used to significantly improve the
+resilience and reliability of Cobalt updates.
+
+All slot configurations assume the following:
+* 1 System Image Installation Slot (read-only)
+* 2+ Additional Installation Slot(s) (writable)
+
+The number of installation slots available will be determined by the platform
+owner. **3 slots is the default configuration for Evergreen**. There can be `N`
+installation slots configured with the only limitation being available storage.
+
+#### Slot Configuration
+NOTE: 3-slots is the DEFAULT configuration.
+
+The number of installation slots is directly controlled using
+`kMaxNumInstallations`, defined in
+[loader\_app.cc](../../loader_app/loader_app.cc).
+
+It is worth noting that all slot configurations specify that the first
+installation slot (`SLOT_0`) will always be the read-only factory system image.
+This is permanently installed on the platform and is used as a fail-safe option.
+This is stored in the directory specified by `kSbSystemPathContentDirectory`
+under the `app/cobalt` subdirectory.
+
+All of the other installation slots are located within the storage directory
+specified by `kSbSystemPathStorageDirectory`. This will vary depending on the
+platform.
+
+For example, on the Raspberry Pi the `kSbSystemPathStorageDirectory` directory
+is `/home/pi/.cobalt_storage`, and the paths to all existing installation slots
+will be as follows:
+
+```
+/home/pi/<kSbSystemPathContentDirectory>/app/cobalt (system image installation SLOT_0) (read-only)
+/home/pi/.cobalt_storage/installation_1 (SLOT_1)
+/home/pi/.cobalt_storage/installation_2 (SLOT_2)
+...
+/home/pi/.cobalt_storage/installation_N (SLOT_N)
+```
+
+Where the most recent update is stored will alternate between the available
+writable slots. In the above example, this would be `SLOT_1`...`SLOT_N`.
+
+#### Understanding Slot Structure
+Slots are used to manage Cobalt Evergreen binaries with associated app metadata
+to select the appropriate Cobalt Evergreen binaries.
+
+See the below structures for an example 3-slot configuration.
+
+Structure for `kSbSystemPathContentDirectory` used for the read-only System
+Image required for all slot configurations:
+
+```
+.
+├── content <--(kSbSystemPathContentDirectory)
+│   └── fonts <--(kSbSystemPathFontDirectory, `standard` or `limit` configuration, to be explained below)
+│   └── app
+│       └── cobalt <--(SLOT_0)
+│           ├── content <--(relative path defined in kSystemImageContentPath)
+│           │   ├── fonts <--(`empty` configuration)
+│           │   ├── (icu) <--(only present when it needs to be updated by Cobalt Update)
+│           │   ├── licenses
+│           │   ├── ssl
+│           ├── lib
+│           │   └── libcobalt.so <--(System image version of libcobalt.so)
+│           └── manifest.json
+└── loader_app <--(Cobalt launcher binary)
+└── crashpad_handler <--(Cobalt crash handler)
+```
+
+Structure for `kSbSystemPathStorageDirectory` used for future Cobalt Evergreen
+updates in an example 3-slot configuration:
+
+```
+├── .cobalt_storage <--(kSbSystemPathStorageDirectory)
+    ├── cobalt_updater
+    │   └── prefs_<APP_KEY>.json
+    ├── installation_1 <--(SLOT_1 - currently unused)
+    ├── installation_2 <--(SLOT_2 - contains new Cobalt version)
+    │   ├── content
+    │   │   ├── fonts <--(`empty` configuration)
+    │   │   ├── (icu) <--(only present when it needs to be updated by Cobalt Update)
+    │   │   ├── licenses
+    │   │   ├── ssl
+    │   ├── lib
+    │   │   └── libcobalt.so <--(SLOT_2 version of libcobalt.so)
+    │   ├── manifest.fingerprint
+    │   └── manifest.json <-- (Evergreen version information of libcobalt.so under SLOT_2)
+    ├── installation_store_<APP_KEY>.pb
+    └── icu (default location shared by installation slots, to be explained below)
+```
+Note that after the Cobalt binary is loaded by the loader_app, `kSbSystemPathContentDirectory` points to the
+content directory of the running binary, as stated in Starboard Module Reference of system.h.
+
+#### App metadata
+Each Cobalt Evergreen application has a set of unique metadata to track slot
+selection. The following set of files are unique per application via a
+differentiating <APP_KEY> identifier, which is a Base64 hash appended to the
+filename.
+
+```
+<SLOT_#>/installation_store_<APP_KEY>.pb
+<SLOT_#>/cobalt_updater/prefs_<APP_KEY>.json
+```
+
+You should NOT change any of these files and they are highlighted here just for
+reference.
+
+
+### Fonts
+The system font directory `kSbSystemPathFontDirectory` should be configured to
+point to the `standard` (23MB) or the `limited` (3.1MB) cobalt font packages. An
+easy way to do that is to use the `kSbSystemPathContentDirectory` to contain
+the system font directory and setting the `cobalt_font_package` to `standard` or
+`limited` in your port.
+
+Cobalt Evergreen (built by Google), will by default use the `empty` font
+package to minimize storage requirements. A separate
+`cobalt_font_package` variable is set to `empty` in the Evergreen platform.
+
+On Raspberry Pi this is:
+
+`empty` set of fonts under:
+```
+<kSbSystemPathContentDirectory>/app/cobalt/content/fonts
+```
+
+`standard` or `limited` set of fonts under:
+```
+<kSbSystemPathContentDirectory>/fonts
+```
+
+### ICU Tables
+The ICU table should be deployed under the `kSbSystemPathStorageDirectory`. This
+way all Cobalt Evergreen installations would be able to share the same tables.
+The current storage size for the ICU tables is 7MB.
+
+On Raspberry Pi this is:
+
+```
+/home/pi/.cobalt_storage/icu
+```
+The Cobalt Evergreen package will not carry ICU tables by default but may add
+them in the future if needed. When the package has ICU tables they would be
+stored under the content location for the installation:
+
+```
+<SLOT_#>/content/icu
+```
+
+### Handling Pending Updates
+Pending updates will be picked up on the next application start, which means
+that on platforms that support suspending the platform should check
+`loader_app::IsPendingRestart` and call `SbSystemRequestStop` instead of
+ suspending if there is a pending restart.
+
+Please see
+[`suspend_signals.cc`](../../shared/signal/suspend_signals.cc)
+for an example.
+
+### Multi-App Support
+Evergreen can support multiple apps that share a Cobalt binary. This is a very
+common way to save space and keep all your Cobalt apps using the latest version
+of Cobalt. We understand that there are situations where updates are only needed
+for certain apps, so we have provided a way where Cobalt Updater and loader_app
+behavior can be easily configured on a per-app basis with simple command-line flags.
+
+The configurable options for Cobalt Updater configuration are:
+* `--evergreen_lite` *Use the System Image version of Cobalt under Slot_0 and turn
+  off the updater for the specified application.*
+* `--disable_updater_module` *Stay on the current version of Cobalt that might be the
+  system image or an installed update, and turn off the updater for the
+  specified application.*
+
+Each app’s Cobalt Updater will perform an independent, regular check for new
+Cobalt Evergreen updates. Note that all apps will share the same set of slots,
+but each app will maintain metadata about which slots are “good” (working) or
+“bad” (error detected) and use the appropriate slot. Sharing slots allows
+Evergreen to download Cobalt updates a single time and be able to use it across
+all Evergreen-enabled apps.
+
+To illustrate, a simple example:
+
+* Cobalt v5 - latest Cobalt Evergreen version
+
+#### BEFORE COBALT UPDATE
+```
+[APP_1] (currently using SLOT_1, using Cobalt v4)
+[APP_2] (currently using SLOT_0, using Cobalt v3)
+[APP_3] (currently using SLOT_0, using Cobalt v3)
+```
+
+Now remember, apps could share the same Cobalt binary. Let’s say `APP_1` has
+detected an update available and downloads the latest update (Cobalt v5) into
+SLOT_2. The next time `APP_2` runs, it may detect Cobalt v5 as well. It would
+then simply do a `request_roll_forward` operation to switch to SLOT_2 and does
+not have to download a new update since the latest is already available in an
+existing slot. In this case, `APP_1` and `APP_2` are now using the same Cobalt
+binaries in SLOT_2.
+
+If `APP_3` has not been launched, not run through a regular Cobalt Updater
+check, or launched with the `--evergreen_lite`/`--disable_updater_module` flag,
+it stays with its current configuration.
+
+#### AFTER COBALT UPDATE
+```
+[APP_1] (currently using SLOT_2, using Cobalt v5)
+[APP_2] (currently using SLOT_2, using Cobalt v5)
+[APP_3] (currently using SLOT_0, using Cobalt v3)
+```
+
+Now that we have gone through an example scenario, we can cover some examples of
+how to configure Cobalt Updater behavior and `loader_app` configuration.
+
+
+Some example configurations include:
+```
+
+# All Cobalt-based apps get Evergreen Updates
+[APP_1] (Cobalt Updater ENABLED)
+[APP_2] (Cobalt Updater ENABLED)
+[APP_3] (Cobalt Updater ENABLED)
+
+loader_app --url="<YOUR_APP_1_URL>"
+loader_app --url="<YOUR_APP_2_URL>"
+loader_app --url="<YOUR_APP_3_URL>"
+
+
+# Only APP_1 gets Evergreen Updates, APP_2 disables the updater and uses an alternate splash screen, APP_3 uses
+# the system image and disables the updater
+[APP_1] (Cobalt Updater ENABLED)
+[APP_2] (Cobalt Updater DISABLED)
+[APP_3] (System Image loaded, Cobalt Updater DISABLED)
+
+loader_app --url="<YOUR_APP_1_URL>"
+loader_app --url="<YOUR_APP_2_URL>" --disable_updater_module \
+--fallback_splash_screen_url="/<PATH_TO_APP_2>/app_2_splash_screen.html"
+loader_app --url="<YOUR_APP_3_URL>" --evergreen_lite
+
+
+# APP_3 is a local app, wants Cobalt Updater disabled and stays on the system image, and uses an alternate content
+# directory (This configuration is common for System UI apps. APP_3 in this example.)
+[APP_1] (Cobalt Updater ENABLED)
+[APP_2] (Cobalt Updater ENABLED)
+[APP_3] (System Image loaded, Cobalt Updater DISABLED)
+
+loader_app --url="<YOUR_APP_1_URL>"
+loader_app --url="<YOUR_APP_2_URL>"
+loader_app --csp_mode=disable --allow_http --url="file:///<PATH_TO_APP_3>/index.html" --content="/<PATH_TO_APP_3>/content" --evergreen_lite
+```
+
+Please see
+[`loader_app_switches.cc`](../../loader_app/loader_app.cc)
+for full list of available command-line flags.
+
+### Platform Security
+
+As Cobalt binary packages ([CRX
+format](https://docs.google.com/document/d/1pAVB4y5EBhqufLshWMcvbQ5velk0yMGl5ynqiorTCG4/edit#heading=h.ke61kmpkapku))
+are downloaded from the Google Downloads server, the verification of the Cobalt
+update package is critical to the reliability of Cobalt Evergreen. There are
+mechanisms in place to ensure that the binary is verified and a chain of trust
+is formed. The Cobalt Updater is responsible for downloading the available
+Cobalt update package and verifies that the package is authored by Cobalt(and
+not an imposter), before trying to install the downloaded package.
+
+#### Understanding Verification
+
+![Cobalt Evergreen CRX
+Verification](resources/cobalt_evergreen_overview_crx_verification.png)
+
+In the above diagram, the Cobalt Updater downloads the update package if
+available, and parses the CRX header of the package for verification, before
+unpacking the whole package. A copy of the Cobalt public key is contained in the
+CRX header, so the updater retrieves the key and generates the hash of the key
+coming from the header of the package, say _Key_ _hash1_.
+
+At the same time, the updater has the hash of the Cobalt public key hard-coded
+locally, say _Key hash2_.
+
+The updater compares _Key hash1_ with _Key hash2._ If they match, verification
+succeeds.
+
+## **FAQ**
+
+### Can I host the binaries for Cobalt core myself to deploy on my devices?
+
+Not at this time. All Cobalt updates will be deployed through Google
+infrastructure. We believe Google hosting the Cobalt core binaries allows us to
+ensure a high-level of reliability and monitoring in case issues arise.
+
+### What is the performance impact of switching to Cobalt Evergreen?
+
+We expect performance to be similar to a standard non-Evergreen Cobalt port.
+
+### How can I ensure that Cobalt updates work well on our platform?
+
+Google will work closely with device partners to ensure that the appropriate
+testing is in place to prevent regressions.
+
+### Will there be tests provided to verify functionality and detect regression?
+
+Yes, there are tests available to help validate the implementation:
+
+*   NPLB tests to ensure all necessary APIs are implemented
+*   Cobalt Evergreen Test Plan to verify the functionality of all components and
+    use cases
+
+### How can I be sure that Cobalt space requirements will not grow too large for my system resources?
+
+The Cobalt team is focusing a large amount of effort to identify and integrate
+various methods to reduce the size of the Cobalt binary such as compression and
+using less fonts.
+
+### What if something goes wrong in the field? Can we rollback?
+
+Yes, this is one of the benefits of Evergreen. We can initiate an update from
+the server side that addresses problems that were undetected during full
+testing. There are a formal set of guidelines to verify an updated binary
+deployed to the device to ensure that it will work properly with no regressions
+that partners should follow to ensure that there are no regressions. In
+addition, it is also critical to do your own testing to exercise
+platform-specific behavior.
+
+### How can I be sure that Cobalt Evergreen will be optimized for my platform?
+
+Much of the optimization work remains in the Starboard layer and configuration
+so you should still expect good performance using Cobalt Evergreen. That being
+said, the Cobalt Evergreen configuration allows you to customize Cobalt features
+and settings as before.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_reference_port_raspi2.md b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_reference_port_raspi2.md
new file mode 100644
index 0000000..7763cc2
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_evergreen_reference_port_raspi2.md
@@ -0,0 +1,124 @@
+---
+layout: doc
+title: "Cobalt Evergreen Raspi-2 Reference Port"
+---
+# Cobalt Evergreen Raspi-2 Reference Port
+
+## Requirements
+
+*   Raspberry Pi 2 (image configured per
+    [instructions](https://cobalt.dev/development/setup-raspi.html) on
+    cobalt.dev)
+
+## Build instructions
+
+```
+## Clone the repository
+$ git clone https://cobalt.googlesource.com/cobalt
+
+## Build the loader app (new entry point)
+$ cd cobalt/src
+$ cobalt/build/gyp_cobalt -v raspi-2-sbversion-12 -C qa
+$ ninja -C out/raspi-2-sbversion-12_qa loader_app crashpad_handler
+
+## Create package directory for Cobalt Evergreen
+$ export COEG_PATH=coeg
+$ cp out/raspi-2-sbversion-12_qa/loader_app $COEG_PATH
+
+## Create directory structure for the initial installation
+[2-slot configuration]
+$ mkdir -p  ~/.cobalt_storage/installation_0/
+$ cd  ~/.cobalt_storage/installation_0/
+
+[3-slot configuration]
+$ mkdir -p $COEG_PATH/content/app/cobalt
+$ cd $COEG_PATH/content/app/cobalt
+
+## Download package
+$ curl -L https://dl.google.com/cobalt/evergreen/latest/cobalt_arm-hardfp_qa.crx  -o cobalt.zip
+
+## Unpack content package
+$ unzip cobalt.zip
+$ rm cobalt.zip
+$ cd -
+```
+
+The following are the steps to build the Cobalt content that’s contained in the
+crx package. Note you only need to do this if you want to build the Cobalt
+shared library and supplementary components.
+
+```
+## Build Cobalt core locally
+$ cd cobalt/src
+$ cobalt/build/gyp_cobalt -v evergreen-arm-hardfp-sbversion-12 -C qa
+$ ninja -C out/evergreen-arm-hardfp-sbversion-12_qa cobalt
+
+## Copy the generated files to the package directory for Cobalt Evergreen
+$ cp -r out/evergreen-arm-hardfp-sbversion-12_qa/lib   $COEG_PATH/content/app/cobalt/
+$ cp -r out/evergreen-arm-hardfp-sbversion-12_qa/content   $COEG_PATH/content/app/cobalt/
+
+## Create a file named manifest.json with the following content, and put it under $COEG_PATH/content/app/cobalt/
+$ cat > $COEG_PATH/content/app/cobalt/manifest.json <<EOF
+{
+        "manifest_version": 2,
+        "name": "Cobalt",
+        "description": "Cobalt",
+        "version": "1.0.0"
+}
+EOF
+```
+
+## Deployment instructions
+
+Configure your Raspberry Pi 2 with the following steps from your Linux machine.
+
+```
+## Save the address of the device
+$ export RASPI_ADDR=<YOUR_RASPI_ID_ADDR>
+
+## Remove old storage directory
+$ rm -rf /home/pi/.cobalt_storage
+
+## Copy the Evergreen contents to the device
+$ rsync -arvp $COEG_PATH pi@$RASPI_ADDR:/home/pi
+
+## Launch
+$ ssh pi@$RASPI_ADDR  /home/pi/$COEG_PATH/loader_app
+```
+
+## Run instructions
+
+```
+$ ssh pi@$RASPI_ADDR
+$ cd coeg
+$ ./loader_app
+```
+
+Cobalt should load and work as usual, but leveraging Evergreen. That’s it!
+
+## Troubleshooting
+
+### Certificate errors on execution of loader\_app
+
+Certificate issues may occur on certain network environments when launching
+`loader_app` via SSH. In this case, try launching with a keyboard directly
+connected to the device.
+
+### “Failed to load library at <path>” thrown on startup
+
+The loader can’t find the `libcobalt.so` file. Check that the path to
+`libcobalt.so` completely matches the one in Deployment instructions.
+
+### “fatal error: “assert(sk\_file)”” thrown on startup
+
+The loader can’t find the content/data folder or it is malformed. Check that the
+path to this folder completely matches the one in Deployment instructions.
+
+### “Check failed: address. Failed to retrieve the address” thrown on startup
+
+Ensure that `libcobalt.so` being used is the correct version. For a rebuild, you
+may need to remove the old .cobalt\_storage directory on your device.
+
+```
+## Remove old storage directory
+$ rm -rf /home/pi/.cobalt_storage
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_update_framework.md b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_update_framework.md
new file mode 100644
index 0000000..f1b1cf8
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/cobalt_update_framework.md
@@ -0,0 +1,104 @@
+---
+layout: doc
+title: "Cobalt Update Framework"
+---
+# Cobalt Update Framework
+
+## Background
+
+The updatability of Cobalt on the field devices enables the deployment of new
+features and crucial bug fixes in a timely manner. It significantly reduces the
+amount of work on partners’ shoulders to update to a newer version of Cobalt.
+This document introduces how Cobalt updates itself and what the system is like
+that supports the update of Cobalt. Note that the Cobalt Update Framework is
+currently used only for Evergreen configurations.
+
+## Goal
+
+*   Enable Cobalt to automatically update itself periodically
+*   Build a framework that hosts and serves the updates reliably
+
+## Overview
+
+![Cobalt Update Overview](resources/cobalt_update_overview.png)
+
+The Cobalt Updater is a module of Cobalt. It is initiated as Cobalt starts. It
+periodically sends requests to Google Update server to check for updates. If an
+update is available, the Update server responds with a downloadable link of the
+update package to the Updater. Then the Updater connects to the link, which is
+hosted on Google Downloads server, to download the update package. If an update
+is not available, the Updater server responds to indicate no update. Then the
+Updater waits until the next scheduled time to check for updates again.
+
+## Implementation
+
+### Google Update
+
+![Cobalt Update Interaction](resources/cobalt_update_interaction.png)
+
+Google Update is an update service that manages updates for Google products
+serving billions of users worldwide. We set up Cobalt updates on Google Update
+in a way that each type of device gets a unique update link (URL). The device
+type is identified by [Starboard
+ABI](../starboard_abi.md)
+(SABI) string. For instance, Raspberry Pi 2 and Linux desktop are two different
+types of devices. They are identified by two different SABI strings, and get two
+different update URLs on Google Update. The request sent by the Cobalt updater
+to Google Update  contains a SABI string. Google Update finds the suitable
+update link that matches the SABI string from the request, and responds to the
+Cobalt updater.
+
+Google Update allows the setup of multiple channels. We set up different
+channels for internal testing, partner testing, production and developers.
+
+Google Update also allows staged rollout and rollback when things go wrong. In
+the case where a problem is detected that requires rollback or fixes, Google
+will work with the partner to find a path to resolution.
+
+### Google Downloads
+
+Google Downloads is a download hosting service for official Google content. We
+generate Cobalt update packages for various types of devices, and upload the
+packages to Google Downloads. Then the links to the packages on Google Downloads
+are served on Google Update.
+
+### Cobalt Updater
+
+The updater checks for updates on Google Downloads, then downloads the update
+package if available. After the download is complete, the updater verifies the
+downloaded package, then unpack the package to a designated installation
+location. The updater runs update checks following a predefined schedule: the
+first check happens after Cobalt starts; the second check runs in a randomized
+number of hours between 1 and 24 hours; the following checks run every 24 hours.
+
+### Update flow
+
+![Cobalt Update Flow](resources/cobalt_update_flow.png)
+
+Above is a chart of the workflow of a complete update cycle. It shows how the
+Updater operates step by step and how it interacts with the Installation Manager
+and the Elf Loader[^1].
+
+The Installation Manager maintains the installation slots and provides a proper
+slot to the Updater. During the update and installation process, the
+Installation Manager keeps track of the status and collects any installation
+error. After the installation is completed, the Installation Manager marks the
+installation as pending, so that next time Cobalt starts, the Elf Loader loads
+the new installation and the update is complete. If the target platform supports
+app exits/suspends on user exiting, Cobalt will exit when an installation is
+pending, so that the new update will be picked up on the next start; otherwise,
+Cobalt is not able to exit by itself, then a manual termination of the app is
+required to pick up the update on restart.
+
+## FAQ
+
+### What happens if an urgent problem is found that requires a rollback or update?
+
+In the case where a problem is detected that requires rollback or fixes, Google
+will work with the partner to find a path to resolution.
+
+<!-- Footnotes themselves at the bottom. -->
+## Footnotes
+
+[^1]: Elf loader - A portable loader that loads the Cobalt binary and resolves
+     symbols with Starboard API when Cobalt starts up in Evergreen mode.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_configurations.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_configurations.png
new file mode 100644
index 0000000..8b3721c
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_configurations.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_components.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_components.png
new file mode 100644
index 0000000..073ce92
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_components.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_crx_verification.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_crx_verification.png
new file mode 100644
index 0000000..16ec0d9
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_crx_verification.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_flow.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_flow.png
new file mode 100644
index 0000000..df0284b
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_flow.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_vs_non_evergreen.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_vs_non_evergreen.png
new file mode 100644
index 0000000..cd9cb9f
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_evergreen_overview_vs_non_evergreen.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_flow.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_flow.png
new file mode 100644
index 0000000..eebe1d3
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_flow.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_interaction.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_interaction.png
new file mode 100644
index 0000000..07b710a
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_interaction.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_overview.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_overview.png
new file mode 100644
index 0000000..3c8328e
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/cobalt_update_overview.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/evergreen_lite_overview.png b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/evergreen_lite_overview.png
new file mode 100644
index 0000000..fa338d9
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/resources/evergreen_lite_overview.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/evergreen/symbolizing_minidumps.md b/src/cobalt/site/docs/gen/starboard/doc/evergreen/symbolizing_minidumps.md
new file mode 100644
index 0000000..df7a502
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/evergreen/symbolizing_minidumps.md
@@ -0,0 +1,133 @@
+---
+layout: doc
+title: "How to Symbolize Dumps"
+---
+# How to Symbolize Dumps
+
+Evergreen will store the minidumps (`.dmp` files) from the 2 most recent
+crashes on the disk. They are stored under `kSbSystemPathCacheDirectory` in the
+subdirectory `crashpad_database/`. These files can be used along with
+Breakpad's tools to get a full stacktrace of the past crashes. This can help in
+debugging, as these minidumps have the information for the dynamic
+`libcobalt.so` module correctly mapped, which a out-of-the-box dumper could not
+manage.
+
+## Obtaining the Tools to Symbolize Minidumps
+
+Tools for symbolizing these dumps are available through
+[Breakpad](https://chromium.googlesource.com/breakpad/breakpad/). Breakpad is
+an open source crash reporting library that we use to obtain symbol files
+(`.sym`) from unstripped binaries, and to process the symbol files with the
+minidumps to produce human-readable stacktraces.
+
+
+### Building Breakpad
+
+[Breakpad](https://chromium.googlesource.com/breakpad/breakpad/) provides
+instructions for building these tools yourself. The
+[Getting Started with Breakpad](https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/getting_started_with_breakpad.md)
+guide is a good place to start if you want to go through the docs yourself, but
+below is a brief overview of how to get and build the tools.
+
+Download depot_tools:
+```
+$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
+$ export PATH=/path/to/depot_tools:$PATH
+```
+
+Get breakpad:
+```
+$ mkdir breakpad && cd breakpad
+$ fetch breakpad
+$ cd src
+```
+
+Build breakpad:
+```
+$ ./configure && make
+```
+
+This will build the processor (`src/processor/minidump_stackwalk`), and when
+building on Linux it will also build the `dump_syms` tool
+(`src/tools/linux/dump_syms/dump_syms`).
+
+**IMPORTANT:** Once you have fetched Breakpad, you should remove the path to
+depot_tools from your `$PATH` environment variable, as it can conflict with
+Cobalt's depot_tools.
+
+## Symbolizing Minidumps
+
+Now that you have all the tools you need, we can symbolize the dumps. To be
+able to symbolize Cobalt using Evergreen, you need to be get the unstripped
+`libcobalt.so` binary. These will be available as assets in GitHub releases
+[on Cobalt's public GitHub repo](https://github.com/youtube/cobalt/releases).
+
+libcobalt releases will be labeled by the Evergreen version, the architecture,
+the config, and the ELF build id, for example
+"libcobalt_1.0.10_unstripped_armeabi_softfp_qa_ac3132014007df0e.tgz". Here, we
+have:
+* Evergreen Version: 1.0.10
+* Architecture: armeabi_softfp
+* Config: qa
+* ELF Build Id: ac3132014007df0e
+
+Knowing the architecture and config you want, you'll just have to know which
+version of Evergreen you're on or obtain the build id of the library. If you
+need to obtain the ELF build id, you can do so easily by running
+`readelf -n /path/to/libcobalt.so` and look at the hash displayed after "Build
+ID:".
+
+Now you can get the debug symbols from the library using the tools we
+downloaded previously. Unpack libcobalt and dump its symbols into a file:
+
+```
+$ tar xzf /path/to/libcobalt.tgz
+$ /path/to/dump_syms /path/to/unzipped/libcobalt > libcobalt.so.sym
+$ head -n1 libcobalt.so.sym
+MODULE Linux x86_64 6462A5D44C0843D100000000000000000 libcobalt.so
+```
+
+We run `head` on the symbol file to get the debug identifier, the hash
+displayed above (in this case, it's `6462A5D44C0843D100000000000000000`). Now
+we can create the file structure that `minidump_stackwalker` expects and run
+the stackwalker against the minidump:
+
+```
+$ mkdir -p symbols/libcobalt.so/<debug identifier>/
+$ mv libcobalt.so.sym symbols/libcobalt.so/<debug identifier>/
+$ /path/to/minidump_stackwalk /path/to/your/minidump.dmp symbols/
+```
+
+`minidump_stackwalk` produces verbose output on stderr, and the stacktrace on
+stdout, so you may want to redirect stderr.
+
+### Addendum: Adding Other Symbols
+
+We can use the process above to add symbols for any library or executable you
+use, not just `libcobalt.so`. To do this, all you have to do is run the
+`dump_syms` tools on the binary you want symbolized and put that in the
+"symbols/" folder.
+
+```
+$ /path/to/dump_syms /path/to/<your-binary> > <your-binary>.sym
+$ head -n1 <your-binary.sym>
+MODULE Linux x86_64 <debug-identifier> <your-binary>
+$ mkdir -p symbols/<your-binary>/<debug-identifier>
+$ mv <your-binary>.sym symbols/<your-binary>/<debug-identifier>/
+```
+
+Now, `minidump_stackwalk` should symbolize sections within `<your-binary>`. For
+example, if you decided to symbolize the `loader_app`, it would transform the
+stacktrace output from `minidump_stackwalk` from:
+
+```
+9  loader_app + 0x3a31130
+```
+
+to:
+
+```
+9  loader_app!SbEventHandle [sandbox.cc : 44 + 0x8]
+```
+
+Note that the addresses will vary.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/howto_decode_to_texture.md b/src/cobalt/site/docs/gen/starboard/doc/howto_decode_to_texture.md
new file mode 100644
index 0000000..8f22450
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/howto_decode_to_texture.md
@@ -0,0 +1,140 @@
+---
+layout: doc
+title: "**HOWTO:** Decode to Texture"
+---
+# **HOWTO:** Decode to Texture
+
+Starboard declares the interfaces necessary to allow applications to query for
+video frames from the media player, and have them returned as texture objects
+(e.g. GLES textures).  This is useful if the application would like to apply
+a geometrical transformation to the rendered video, in order to support 360
+spherical video playback for example.  Additionally, if a Starboard platform
+implementation does not support punch-through video playback, then
+applications can choose to use decode-to-texture instead.
+
+## API Overview
+
+Decode-to-texture support involves multiple Starboard API functions spanning
+both the [`starboard/player.h`](../player.h) and
+[`starboard/decode_target.h`](../decode_target.h) Starboard interface header
+files.  Support for decode-to-texture began in version 4 of the Starboard
+API.
+
+In particular, the following function implementations require consideration
+for decode-to-texture support:
+
+From [`starboard/player.h`](../player.h),
+
+* `SbPlayerCreate()`
+* `SbPlayerOutputModeSupported()`
+* `SbPlayerGetCurrentFrame()`
+
+From [`starboard/decode_target.h`](../decode_target.h),
+
+* `SbDecodeTargetRelease()`
+* `SbDecodeTargetGetInfo()`
+
+Note that it is possible that you may not need to use the
+`SbDecodeTargetGraphicsContextProvider` parameter of SbPlayerCreate().  More on
+this later.
+
+## Example Application Usage Pattern
+
+We now describe an example, and typical, sequence of steps that an
+application will take when it wishes to make use of decode-to-texture
+support.
+
+![Decode-to-texture sequence diagram](resources/decode_to_texture_sequence.png)
+
+1. An application with the desire to make use of decode-to-texture will first
+   call `SbPlayerOutputModeSupported()`, passing in
+   `kSbPlayerOutputModeDecodeToTexture` for its `output_mode` parameter.  If
+   the function returns false, the application learns that decode-to-texture
+   is not supported by the platform and it will not continue with a
+   decode-to-texture flow.
+
+2. If `SbPlayerOutputModeSupported()` returns true, the application will call
+   `SbPlayerCreate()`, passing in `kSbPlayerOutputModeDecodeToTexture` for
+   the `output_mode` parameter, and also providing a valid `provider`
+   parameter (more on this later).  At this point, the Starboard platform is
+   expected to have created a player with the decode-to-texture output mode.
+
+3. Once the player is started and playback has begun, the application's
+   renderer thread (this may be a different thread than the one that called
+   `SbPlayerCreate()`) will repeatedly and frequently call
+   `SbPlayerGetCurrentFrame()`.  Since this function will be called from the
+   application's renderer thread, it should be thread-safe.  If the platform
+   uses a GLES renderer, it is guaranteed that this function will be called
+   with the GLES renderer context set as current.  This function is expected
+   to return the video frame that is to be displayed at the time the function
+   is called as a `SbDecodeTarget` object.  The `SbPlayerGetCurrentFrame()`
+   will be called at the renderer's frequency, i.e. the application render
+   loop's frame rate.  If the application's frame rate is higher than the
+   video's frame rate, then the same video frame will sometimes be returned
+   in consecutive calls to `SbPlayerGetCurrentFrame()`.  If the video's frame
+   rate is higher than the application's (this should be rare), then some
+   video frames will never be returned by calls to
+   `SbPlayerGetCurrentFrame()`; in other words, video frames will be
+   dropped.
+
+4. Once the application has acquired a valid SbDecodeTarget object through a
+   call to `SbPlayerGetCurrentFrame()`, it will call
+   `SbDecodeTargetGetInfo()` on it to extract information about the opaque
+   `SbDecodeTarget` object.  The `SbDecodeTargetGetInfo()` function fills
+   out a `SbDecodeTargetInfo` structure which contains information about the
+   decoded frame and, most importantly, a reference to a GLES texture ID on
+   GLES platforms, or a reference to a `SbBlitterSurface` object on
+   Starboard Blitter API platforms.  The application can then use this
+   texture/surface handle to render the video frame as it wishes.
+
+5. When the application is finished using the `SbDecodeTarget` that it has
+   acquired through the `SbPlayerGetCurrentFrame()` function, it will call
+   `SbDecodeTargetRelease()` on it.  The Starboard platform implementation
+   should ensure that the `SbDecodeTarget` object returned by
+   `SbPlayerGetCurrentFrame()` remains valid until the corresponding call to
+   `SbDecodeTargetRelease()` is made.  A call to `SbDecodeTargetRelease()`
+   will be made to match each call to `SbPlayerGetCurrentFrame()`.
+
+## The `SbDecodeTargetGraphicsContextProvider` object
+
+It is completely possible that a platform's Starboard implementation can
+properly implement decode-to-texture support without dealing with the
+`SbDecodeTargetGraphicsContextProvider` object (passed in to
+`SbPlayerCreate()`).  The `SbDecodeTargetGraphicsContextProvider` reference
+gives platforms references to the graphics objects that will later be used to
+render the decoded frames.  For example, on Blitter API platforms, a reference
+to the `SbBlitterDevice` object will be a mamber of
+`SbDecodeTargetGraphicsContextProvider`.  For EGL platforms, a `EGLDisplay` and
+`EGLContext` will be available, but additionally a
+`SbDecodeTargetGlesContextRunner` function pointer will be provided that will
+allow you to run arbitrary code on the renderer thread with the `EGLContext`
+held current.  This may be useful if your `SbDecodeTarget` creation code will
+required making GLES calls (e.g. `glGenTextures()`) in which a `EGLContext` must
+be held current.
+
+## Performance Considerations
+
+The decode-to-texture Starboard API is specifically designed to allow
+Starboard implementations to have the player decode directly to a texture,
+so that the application can then reference and render with that texture
+without at any point performing a pixel copy.  The
+decode-to-texture path can therefore be highly performant.
+
+It is still recommended however that platforms support the punch-through
+player mode if possible.  When using the decode-to-texture player output
+mode, the video may be rendered within the application's render loop, which
+means that non-video-related time complexity in the application's render
+loop can affect video playback's apparent frame rate, potentially resulting in
+dropped frames.  The platform can likely configure punch-through video to
+refresh on its own loop, decoupling it from the application render loop.
+
+## Implementation Strategies
+
+### Working with "push" players
+
+If your player implementation is setup with a "push" framework where
+frames are pushed out as soon as they are decoded, then you will need
+to cache those frames (along with their timestamps) so that they can be
+passed on to the application when `SbPlayerGetCurrentFrame()` is called.
+This same strategy applies if the player pushes frames only when they are meant
+to be rendered.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/principles.md b/src/cobalt/site/docs/gen/starboard/doc/principles.md
new file mode 100644
index 0000000..04e039c
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/principles.md
@@ -0,0 +1,156 @@
+---
+layout: doc
+title: "Starboard Design Principles"
+---
+# Starboard Design Principles
+
+An overview of the goals and design principles of Starboard with the perspective
+of hindsight.
+
+**Status:** REVIEWED\
+**Created:** 2016-11-12
+
+Starboard is a porting abstraction and a collection of implementation fragments
+used to abstract operating system facilities and platform quirks from C or C++
+applications. It occupies a similar space to SDL, DirectFB, Marmalade, and
+various others.
+
+## Background
+
+Starboard was created as a response to the significant effort it has
+historically taken to port desktop-oriented web browsers to non-traditional
+device platforms like game consoles. Chromium in particular mixes
+platform-specific code with common code throughout the technology stack, making
+it very difficult to know what has to be done for a new platform or how much
+work it is going to be.
+
+## Goals
+
+Here are the main goals of Starboard, stack-ranked from most-to-least important.
+
+  * **G1** Minimize the total time and effort required to port Starboard Client
+    Applications to new platforms.
+  * **G2** Minimize the incremental time and effort required to rebase Starboard
+    Client Applications across platforms.
+  * **G3** Enable third parties to port Starboard to their platform without
+    significant engineering support from the Starboard team.
+  * **G4** Ensure support for low-profile platforms that are not geared towards
+    broad native C/C++ development access.
+  * **G5** Provide an organization framework for platform-specific code, clearly
+    delineating what is common and what is platform-specific, consolidating
+    platform-specific code into a single location, and enumerating all the APIs
+    needed to provide full functionality.
+  * **G6** Encapsulate all platform-provided services needed to build graphical
+    media applications into a single API.
+  * **G7** Reduce the total surface area needed to port to new platforms.
+  * **G8** Improve and encourage sharing of platform-specific implementation
+    components between platforms.
+  * **G9** Maximize the amount of common (platform-independent) code, to avoid
+    variances between platforms, and to increase the leverage of testing,
+    including fuzz testing which must often be done on particular platforms.
+  * **G10** Maintain a loose binding between a Starboard Platform Implementation
+    and a Starboard Client Application, such that they can be updated
+    independently at a source level.
+  * **G11** Avoid the pitfalls of trying to emulate POSIX, including, but not
+    limited to: auto-included headers, global defines of short and common
+    symbols, wrapping misbehaving or misprototyped system APIs, using custom
+    toolchain facilities, and conflicts with platform headers.
+
+## Principles
+
+### Make APIs sufficient for their purpose, but minimally so.
+
+APIs can generally be augmented without serious backwards-compatibility
+consequences, but they can not be changed or pruned so easily, so it is better
+to **err on the side of providing less**.
+
+#### Corollary: Implementation details should be as hidden as possible.
+
+#### Corollary: Anything that could be implemented purely on top of Starboard APIs should be implemented purely on top of Starboard APIs.
+
+#### Exception: If there are good reasons why an API may need to be implemented in a platform-specific manner on one or more platforms, but can be commonly implemented on other platforms, it should be part of the API, with a shared Starboard-based implementation.
+
+#### Exception: For the select few cases where Starboard implementations also need to use it, it should be included in the Starboard API so that can happen without creating circular dependencies.
+
+### Specify public APIs concretely and narrowly.
+
+A broader specification of the behavior of an API function makes life easier for
+the implementor, but more difficult for anyone attempting to use the API. An API
+can be so weakly specified that it is not usable across platforms. It can also
+be so strictly specified that it is not implementable across platforms. **Err on
+the side of narrower specifications**, requiring generality only when
+necessitated by one or more platforms.
+
+#### Corollary: Documentation should be exhaustive and clear.
+
+#### Corollary: Avoid overly-flexible convention-based interfaces.
+
+For example, passing in a set of string-string name-value pairs. This takes the
+compiler out of any kind of validation, and can encourage mismatches of
+understanding between Clients and Platforms.
+
+### Minimize the burden on the porter.
+
+Whenever adding or changing an API, or specifying a contract, consider whether
+this places a large burden on some platform implementers. This burden could be
+because of a wide porting surface, or complex requirements that are difficult to
+implement. It could be caused by a fundamental piece of infrastructure that
+isn't provided by a particular platform.
+
+We can always make APIs that are burdensome to use easier with more common code.
+
+### Be consistent and predictable.
+
+Consistency, not just in formatting, but in semantics, leads to
+predictability. Some people just won't read the documentation, even if it's
+thorough. Perhaps especially if it's thorough. The names of API entities should
+convey the intention as completely as possible.
+
+Yet, overly-verbose naming will make the API difficult to remember, read, and
+use.
+
+### Assume the porter knows nothing.
+
+Engineers from a broad set of backgrounds and environments will end up being
+dropped into porting Starboard. They may not have knowledge of any particular
+technologies, best practices, or design patterns. They may be under an
+aggressive deadline.
+
+### Always consider threading (and document it).
+
+Each function and module should have a strategy for dealing with multiple
+threads. It should make sense for the expected use cases of the interface
+entities in question. As the interface designer, it is most clear to you how the
+API should be used with respect to threads.
+
+Some may be "thread-safe," such that any functions can be called from any thread
+without much concern. Note that this places the burden on the implementer to
+ensure that an implementation meets that specification, and they MAY not know
+how to do that. This can also be more complex than just acquiring a mutex inside
+every function implementation, as there may be inherent race conditions between
+function calls even when using a synchronization mechanism.
+
+The path of least burden to the porter is to say that an interface is not
+thread-safe at all, which means applications will have to take care how the API
+is used. But, sometimes even this requires clarification as to what modes of
+access are dangerous and how to use the API safely.
+
+### Don't expose Informational-Only result codes, but do DLOG them.
+
+"Informational-Only" is defined by a result code that doesn't change the
+behavior of the caller. Many times, why something failed does not matter when
+the product is already in the hands of the user. We often want diagnostic
+logging during development
+
+### Trust but Verify. Whenever possible, write NPLB tests for all contracts declared by the interface.
+
+#### Corollary: For hard-to-test features (like Input) add an example sandbox app for testing.
+
+### We will get it wrong the first time, so plan for some kind of change mechanism.
+
+Starboard has a [versioning mechanism](versioning.md) to manage change.
+
+## References
+  * [Joshua Bloch's presentation about API design](https://www.youtube.com/watch?v=aAb7hSCtvGw)
+  * [Joshua Bloch's bumper sticker API design rules](http://www.infoq.com/articles/API-Design-Joshua-Bloch)
+  * [digithead's collection of API design links (I didn't read them all)](http://digitheadslabnotebook.blogspot.com/2010/07/how-to-design-good-apis.html)
diff --git a/src/cobalt/site/docs/gen/starboard/doc/resources/decode_to_texture_sequence.png b/src/cobalt/site/docs/gen/starboard/doc/resources/decode_to_texture_sequence.png
new file mode 100644
index 0000000..b2b4cb4
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/resources/decode_to_texture_sequence.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/resources/decode_to_texture_sequence.txt b/src/cobalt/site/docs/gen/starboard/doc/resources/decode_to_texture_sequence.txt
new file mode 100644
index 0000000..ac5127b
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/resources/decode_to_texture_sequence.txt
@@ -0,0 +1,13 @@
+participant Application (e.g. Cobalt) as a [fillcolor="#ffd0d0"]
+participant Starboard as s [fillcolor="#d0d0ff"]
+
+a->s: SbPlayerOutputModeSupported(kSbPlayerOutputModeDecodeToTexture, ...)
+s-->a: returns bool
+Note over a: If SbPlayerOutputModeSupported()\nreturns true... [fillcolor="white"]
+a->s: SbPlayerCreate(..., kSbPlayerOutputModeDecodeToTexture, ...)
+Note over a: Start of render loop [fillcolor="#ffffd0"]
+a->s: SbPlayerGetCurrentFrame()
+s-->a: returns SbDecodeTarget
+Note over a: Extracts GLES texture(s) from the\nSbDecodeTarget object and\nrenders a scene with them. [fillcolor="white"]
+a->s: SbDecodeTargetRelease()
+Note over a: Goto: Start of render loop [fillcolor="#ffffd0"]
diff --git a/src/cobalt/site/docs/gen/starboard/doc/resources/starboard_abi_overview.png b/src/cobalt/site/docs/gen/starboard/doc/resources/starboard_abi_overview.png
new file mode 100644
index 0000000..8a15c74
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/resources/starboard_abi_overview.png
Binary files differ
diff --git a/src/cobalt/site/docs/gen/starboard/doc/starboard_abi.md b/src/cobalt/site/docs/gen/starboard/doc/starboard_abi.md
new file mode 100644
index 0000000..619703c
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/starboard_abi.md
@@ -0,0 +1,123 @@
+---
+layout: doc
+title: "Starboard ABI"
+---
+# Starboard ABI
+
+The Starboard ABI was introduced to provide a single, consistent method for
+specifying the Starboard API version and the ABI. This specification ensures
+that any two binaries, built with the same Starboard ABI and with arbitrary
+toolchains, are compatible.
+
+## Background
+
+The Starboard ABI is the set of features, such as the Starboard API version or
+the sizes of data types, that collectively describes the relationship between
+the Starboard API and ABI of a binary. In the past, each of these features were
+inconsistently and ambiguously defined in a variety of files. This led to
+confusion, and made it difficult to track down the feature values for a
+platform. To simplify how Starboard is configured for a target platform, all of
+these features, and their concrete values, are now listed for each distinct
+target architecture in Starboard ABI files. These files provide a consistent,
+consolidated view of the values for each of these features, decoupling
+platform-specific details from architecture.
+
+## Goals
+
+The overall goal of the Starboard ABI is to provide a way to implement and
+verify binary compatibility on a target platform, and this goal can be broken
+down into the following more concise motivations:
+
+*   Separate platform and architecture into distinct concepts.
+*   Establish a consistent set of values for the various features of each target
+    architecture.
+*   Consolidate this set of features and their values in a consistent,
+    predictable location.
+*   Provide the ability to validate the values of each feature in produced
+    binaries.
+
+## Using Starboard ABI Files
+
+With the Starboard ABI being the source of truth for all things architecture
+related, each platform must now include a Starboard ABI file in its build (see
+[//starboard/sabi](../sabi)
+for examples). Starboard ABI files are JSON, and should all contain identical
+keys with the values being appropriate for the architecture. Each platform must
+override the new
+[GetPathToSabiJsonFile](../build/platform_configuration.py##339)
+method in its platform configuration to return the path to the desired Starboard
+ABI file (e.g.
+[//starboard/linux/shared/gyp\_configuration.py](../linux/shared/gyp_configuration.py)).
+By default, an empty and invalid Starboard ABI file is provided.
+
+Additionally, all platforms must include the
+[sabi.gypi](../sabi/sabi.gypi)
+in their build configuration. This file will consume the specified Starboard ABI
+file, resulting in the creation of a set of GYP variables and preprocessor
+macros. The preprocessor macros are passed directly to the compiler and replace
+the macros you might be familiar with, such as `SB_HAS_32_BIT_LONG`.
+
+The newly defined GYP variables need to be transformed into toolchain specific
+flags; these flags are what actually makes the build result in a binary for the
+desired architecture. These flags will, in most cases, be identical to the flags
+already being used for building.
+
+The process outlined above is shown in the diagram below.
+
+![Starboard ABI Overview](resources/starboard_abi_overview.png)
+
+### Post-Starboard ABI File Cleanup
+
+A number of GYP variables and preprocessor macros should no longer be defined
+directly, and instead the Starboard ABI file will be used to define them. These
+definitions need to be removed.
+
+From `configuration_public.h`:
+
+*   `SB_IS_ARCH_*`
+*   `SB_IS_BIG_ENDIAN`
+*   `SB_IS_32_BIT`
+*   `SB_IS_64_BIT`
+*   `SB_HAS_32_BIT_LONG`
+*   `SB_HAS_64_BIT_LONG`
+*   `SB_HAS_32_BIT_POINTERS`
+*   `SB_HAS_64_BIT_POINTERS`
+
+From `gyp_configuration.gypi`:
+
+*   `target_arch`
+
+## FAQ
+
+### What Starboard ABI files are provided?
+
+The Cobalt team provides, and maintains, Starboard ABI files for the following
+architectures:
+
+*   x86\_32
+*   x86\_64
+*   ARM v7 (32-bit)
+*   ARM v8 (64-bit)
+
+If you find that no valid Starboard ABI file exists for your architecture, or
+that you need to change any values of a provided Starboard ABI file, please
+reach out to the Cobalt team to advise.
+
+### How can I verify that my build is configured correctly?
+
+Similar to the process prior to Starboard ABI files, there are multiple levels
+of verification that occur:
+
+1.  When configuring your build, the Starboard ABI file that was specified will
+    have its values sanity checked against a provided
+    [schema](../sabi/sabi.schema.json).
+1.  When building, a number of static assertions will assert correctness of a
+    number of features generated from the Starboard ABI file against the
+    features of the binary.
+1.  The NPLB test suite has been expanded to include [additional
+    tests](../nplb/sabi/)
+    capable of verifying the remaining features of the binary.
+
+Finally, binaries produced by the Cobalt team for your architecture, including
+NPLB, will be made available to ensure end-to-end correctness of the produced
+binaries.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/starboard_split.md b/src/cobalt/site/docs/gen/starboard/doc/starboard_split.md
new file mode 100644
index 0000000..6eeaf95
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/starboard_split.md
@@ -0,0 +1,62 @@
+---
+layout: doc
+title: "Separation of Starboard from Cobalt"
+---
+# Separation of Starboard from Cobalt
+
+### Background
+
+In creating Cobalt Evergreen, we needed to have as few differences in the code
+as we could from one platform to another. Simply put, that means we want to get
+rid of as many platform specific compile time macros as possible. Because of
+the large amount of platform differences we had previously, there were macros
+defined in a variety places, all of which require different cases to convert.
+The below sections go into the differences regarding changes to these macros
+from Cobalt 20 to 21 and from Starboard 11 to 12.
+
+## Optional APIs
+
+In previous versions, there were a few APIs that could optionally defined and
+would only be enabled if certain macros were set. The platform would only have
+to implement the API if it set the macros accordingly. Now, those differences
+have been removed, and all platforms are required to implement these APIs. For
+convenience, we have provided stub functions for all implementations, which a
+platform can use without differences in Cobalt if they did not enable the API
+beforehand.
+
+## Migration from Configuration Macros to External Constants
+
+Starboard configurations have moved from
+[configuration.h](../configuration.h) and platform specific
+`configuration_public.h` files to `configuration_constants.cc` files. They
+have also been changes from macros to `extern const`s. This means that Cobalt
+will be able to evaluate these variables at runtime instead of compile time.
+The declarations for all of these variables are located in
+[configuration_constants.h](../configuration_constants.h), but each platform
+must define each variable individually, i.e. as
+```
+// configuration_constants.cc
+#include "starboard/configuration_constants.h"
+
+const int32_t kSbFileMaxName = 64;
+```
+There are two changes that are a result of this migration:
+
+1. There is no longer any form of inheritance. This means that if there are any
+configuration differences between two platforms, they must have separate
+`configuration_constants.cc` files.
+2. There are no longer default values for any variable. Because we cannot
+inherit values, we would not be able to receive a default value for any one, so
+each platform must have a definition for every configuration variable.
+
+## Migration from GYP Variables to Cobalt Extensions
+
+Cobalt configurations have moved from [cobalt_configuration.gypi](../../cobalt/build/cobalt_configuration.gypi) and platform specific `gyp_configuration.gypi` files to Cobalt extensions, primarily [CobaltExtensionConfigurationApi](../../cobalt/extension/configuration.h), but including the [CobaltExtensionGraphicsApi](../../cobalt/extension/graphics.h).
+
+Some variables were already in the process of being deprecated, sometimes with a replacement. In those cases, that path was followed.
+
+Implementing the Cobalt extension is completely optional, and when calling the functions corresponding to the old GYP variable, there will be a default value that the function will be able to fall back onto if the extension has not been implemented. That being said, if there is a single function the platform needs a custom implementation for, it must completely implement the CobaltExtensionConfigurationApi. For convenience, we have provided default functions to use to define the API if desired.
+
+##### Notes
+
+For migrating from macros, partners will have to treat their use differently! I.e. string literal vs const char* in their implementations. Add an overview of all of the cases of this migration in runtime code.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/style.md b/src/cobalt/site/docs/gen/starboard/doc/style.md
new file mode 100644
index 0000000..c837ed1
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/style.md
@@ -0,0 +1,280 @@
+---
+layout: doc
+title: "Starboard C and C++ Style Guide"
+---
+# Starboard C and C++ Style Guide
+
+A description of the coding conventions for Starboard code and API headers.
+
+**Status:** REVIEWED\
+**Created:** 2016-11-08
+
+Starboard generally tries to follow the coding conventions of Cobalt, which
+itself mostly follows the conventions of Chromium, which mostly follows the
+externally-published Google C++ coding conventions. But, Starboard has some
+special requirements due to its unusual constraints, so it must add a few new
+conventions and loosen some of the existing style prescriptions.
+
+## Background
+
+Before looking at this document, bear in mind that it is not intending to
+completely describe all conventions that apply to Starboard. You probably want
+to take some time to familiarize yourself with these documents first, probably
+in this order:
+
+  * [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html)
+  * [Chromium C++ Style Guide](https://chromium.googlesource.com/chromium/src/+/master/styleguide/c++/c++.md)
+  * [Cobalt Style Guide](http://cobalt.foo/broken)
+
+The main additional constraints that Starboard has to deal with are:
+
+  * The Starboard API is defined in straight-C. It must be able to interface
+    with all possible third-party components, many of which are in C and not
+    C++.
+  * Starboard is a public API. Starboard platform implementations and
+    applications written on top of Starboard will change independently. This
+    means there are intense requirements for API stability, usage
+    predictability, searchability, and documentation.
+  * Note that even though it is presented as a "style guide," the conventions
+    presented here are required to be approved for check-in unless otherwise
+    noted.
+
+
+## Definitions
+
+### snake-case
+
+Words separated with underscores.
+
+    lower_snake_case
+    ALL_CAPS_SNAKE_CASE
+
+### camel-case
+
+Words separated by letter capitalization.
+
+    camelCase
+    CapitalizedCamelCase
+
+## C++ Guidelines
+
+What follows are hereby the guidelines for Starboard C and C++ code. Heretofore
+the guidelines follow thusly as follows.
+
+### API Definitions
+
+  * Starboard API definitions must always be compatible with straight-C99 compilers.
+  * All public API declarations must be specified in headers in
+    `src/starboard/*.h`, not in any subdirectories.
+  * Non-public declarations must NOT be specified in headers in
+    `src/starboard/*.h`.
+  * C++ inline helper definitions may be included inside an `#if
+    defined(__cplusplus)` preprocessor block. They must only provide
+    convenience, and must NOT be required for any API functionality.
+  * All public API functions should be exported symbols with the SB_EXPORT
+    attribute.
+  * No non-const variables shall be exposed as part of the public API.
+  * All APIs should be implemented in C++ source files, not straight-C source files.
+
+### Modules
+
+  * Each module header must be contained with a single header file.
+
+  * The name of the module must be the singular form of the noun being
+    interfaced with by the module, without any "sb" or "starboard".
+      * `file.h`
+      * `directory.h`
+      * `window.h`
+  * Module interfaces should not have circular dependencies.
+
+### File Names
+
+  * Like in the other conventions (e.g. Google, Chromium), file names must be in
+    `lower_snake_case`.
+  * File names must not contain `sb_` or `starboard_`.
+  * The name of a module header file must be the `lower_snake_case` form of the
+    module name.
+      * `SbConditionVariable` ➡ `starboard/condition_variable.h`
+  * A header that is intended to be an internal implementation detail of one or
+    more platform implementations should have the suffix `_internal.h`, and
+    include the header `starboard/shared/internal_only.h`.
+  * See "Implementations" for conventions about where to place implementation files.
+
+### Types
+
+  * Like in the other conventions, types should be `CapitalizedCamelCase`.
+  * Every public Starboard type must start with `Sb`. There are no namespaces in
+    C, so `Sb` is the Starboard namespace.
+  * Every public Starboard type must be declared by a module, and must have the
+    name of the module following the `Sb`.
+      * `file.h` contains `SbFile`, `SbFileInfo`, `SbFileWhence`, etc...
+  * Every seemingly-allocatable, platform-specific Starboard type should be
+    defined as an opaque handle to a publicly undefined struct with the
+    `Private` suffix. Follow this pattern for all such type declarations.
+      * `struct SbFilePrivate` is declared, but not defined in the public header.
+      * `SbFilePrivate` is `typedef`'d to `struct SbFilePrivate`. This is a C
+        thing where types are defined as names with the "`struct`" keyword
+        prepended unless `typedef`'d.
+      * `SbFile` is defined as a `typedef` of `struct SbFilePrivate*`.
+  * C structs may be defined internally to have functions and visibility. It is
+    allowed for such structs to have constructors, destructors, methods,
+    members, and public members.
+  * It is also considered idiomatic to never define the private struct but to
+    just treat it like a handle into some other method of object tracking,
+    casting the handle back and forth to the pointer type.
+  * If a word in the name of a type is redundant with the module name, it is
+    omitted.
+        * A monotonic time type in the Time module is `SbTimeMonotonic`, not
+          ~~`SbMonotonicTime`, `SbTimeMonotonicTime`, or
+          `SbTimeMonotonicSbTime`~~.
+
+### Functions
+
+  * Like in the other conventions, functions should be `CapitalizedCamelCase`.
+  * Every public Starboard function must start with `Sb`. There are no namespaces
+    in C, so `Sb` is the Starboard namespace.
+  * Every public Starboard function must be declared by a module, and must have
+    the name of the module following the `Sb`.
+      * `system.h` contains `SbSystemGetPath()`
+      * `file.h` contains `SbFileOpen()`
+  * After the Starboard and Module prefix, functions should start with an
+    imperative verb indicating what the function does.
+      * The Thread module defines `SbThreadCreateLocalKey()` to create a key for
+        thread local storage.
+  * If a word in the name of a function is redundant with the module name, it is
+    omitted.
+      * The `File` module as the function `SbFileOpen`, not ~~`SbOpenFile`,
+        `SbFileOpenFile` or `SbFileOpenSbFile`~~.
+      * If this gets awkward, it may indicate a need to split into a different
+        module.
+
+### Variables, Parameters, Fields
+
+  * Like in the other conventions, variable, function parameter, and field names
+    must be in `lower_snake_case`.
+  * Private member fields end in an underscore.
+  * Public member fields do not end in an underscore.
+
+### Namespaces
+
+Most Starboard API headers are straight-C compatible, so cannot live inside a
+namespace. Implementations, since they implement straight-C interface functions,
+also cannot live inside a namespace.
+
+But, in all other cases, Starboard C++ code should follow the inherited
+conventions and use a namespace for each directory starting with a "starboard"
+namespace at the starboard repository root.
+
+### Preprocessor Macros
+
+  * Like in the other conventions, variable, function parameter, and field names
+    must be in `ALL_CAPS_SNAKE_CASE`.
+  * Macros may be used as compile-time constants because straight-C does not
+    have a proper facility for typed constants. This is as opposed to macros
+    used primarily at preprocessor-time to filter or modify what gets sent to
+    the compiler. Macros used as compile-time constants and that are not
+    configuration parameters should be explicitly-typed with a c-style cast, and
+    should follow the Constants naming conventions.
+  * Macros must start with `SB_`, and then must further be namespaced with the
+    module name, with the exception of configuration definitions.
+  * Configuration definitions should be namespaced with the module name that
+    they primarily affect, if applicable, or a scope that generally indicates
+    its domain.
+      * `SB_FILE_MAX_NAME`
+      * `SB_MEMORY_PAGE_SIZE`
+  * Always use `#if defined(MACRO)` over `#ifdef MACRO`.
+
+### Constants
+
+  * Constants (including enum entries) are named using the Google constant
+    naming convention, `CapitalizedCamelCase`d, but starting with a lower-case
+    `k`.
+  * After the `k`, all constants have `Sb`, the Starboard namespace.
+      * `kSb`
+  * After `kSb`, all constants then have the module name.
+      * `kSbTime`
+      * `kSbFile`
+  * After `kSb<module>` comes the rest of the name of the constant.
+      * `kSbTimeMillisecond`
+      * `kSbFileInvalid`
+  * Enum entries are prefixed with the full name of the enum.
+      * The enum `SbSystemDeviceType` contains entries like
+        `kSbSystemDeviceTypeBlueRayDiskPlayer`.
+
+### Comments
+
+  * All files must have a license and copyright comment.
+  * It is expected that the straight-C compiler supports C99 single-line
+    comments. Block comments should be avoided whenever possible, even in
+    license and copyright headers.
+  * Each public API module file should have a Module Overview documentation
+    comment below the license explaining what the module is for, and how to use
+    it effectively.
+  * The Module Overview must be separated by a completely blank line from the
+    license comment.
+  * The first line of the Module Overview documentation comment must say
+    "`Module Overview: Starboard <module-name> module`", followed by a blank
+    comment line (i.e. a line that contains a `//`, but nothing else).
+  * The first sentence of a documentation comment describing any entity (module,
+    type, function, variable, etc...) should assume "This module," "This type,"
+    "This function," or "This variable" at the beginning of the sentence, and
+    not include it.
+  * The first sentence of a documentation comment describing any entity should
+    be a single-sentence summary description of the entire entity.
+  * The first paragraph of a documentation comment should describe the overall
+    behavior of the entity.
+  * Paragraphs in comments should be separated by a blank comment line.
+  * All public entities must have documentation comments, including enum
+    entries.
+  * Documentation comments should be formatted with Markdown.
+  * Variables, constants, literals, and expressions should be referenced in
+    comments with pipes around them.
+  * All comments must be full grammatically-correct English sentences with
+    proper punctuation.
+  * Comments in Starboard headers must be written as requirements for the
+    porter, for example: "must not return NULL" or "should not return
+    NULL" rather than "will not return NULL". The choice of "must" vs "should"
+    must follow the guidelines of IETF RFC,
+    https://www.ietf.org/rfc/rfc2119.txt .
+
+### Implementations
+
+  * Each API implementation should attempt to minimize other platform
+    assumptions, and should therefore use Starboard APIs to accomplish
+    platform-specific work unless directly related to the platform functionality
+    being implemented.
+        * For example, `SbFile` can use POSIX file I/O, because that what it is
+          abstracting, but it should use `SbMemoryAllocate` for any memory
+          allocations, because it might be used with a variety of `SbMemory`
+          implementations.
+  * Whenever possible, each shared function implementation should be implemented
+    in an individual file so as to maximize the chances of reuse between
+    implementations.
+  * This does not apply to platform-specific functions that have no chance of
+    being reusable on other platforms.
+  * Implementation files that can conceivably be shared between one or more
+    implementations should be placed in a `starboard/shared/<dependency>/`
+    directory, where `<dependency>` is the primary platform dependency of that
+    implementation. (e.g. `libevent`, `posix`, `c++11`, etc.)
+  * Implementation files that don't have a specific platform dependency, but
+    whether to use them should be a platform decision should be placed in
+    `starboard/shared/starboard/`, and must only have dependencies on other
+    Starboard APIs.
+  * Implementation files that definitely can be common to ALL implementations
+    should be placed in `starboard/common/`.
+
+### Language Features
+
+  * In public headers, particularly in inline functions and macros, only C-Style
+    casts may be used, though they are forbidden everywhere else.
+  * It is expected that the C compiler supports inline functions. They must be
+    declared `static`, and they must use the `SB_C_INLINE` or
+    `SB_C_FORCE_INLINE` attribute. In straight-C code, there is no anonymous
+    namespace, so `static` is allowed and required for inline functions.
+  * No straight-C ISO or POSIX headers should be assumed to exist. Basic C++03
+    headers may be assumed to exist in C++ code. The ISO C standards have grown
+    up over a long period of time and have historically been implemented with
+    quirks, missing pieces, and so on. Support for the core C++ standard library
+    is much more consistent on those platforms that do support it.
+  * It is idiomatic to include thin C++ inline wrappers inside public API
+    headers, gated by an `#if defined(cplusplus__)` check.
diff --git a/src/cobalt/site/docs/gen/starboard/doc/versioning.md b/src/cobalt/site/docs/gen/starboard/doc/versioning.md
new file mode 100644
index 0000000..c3e07f1
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/doc/versioning.md
@@ -0,0 +1,245 @@
+---
+layout: doc
+title: "Starboard Versioning"
+---
+# Starboard Versioning
+
+## Motivation
+
+When a porter implements Starboard for a platform, it is more precise to say
+that they have implemented support for a certain version of Starboard.
+Changes to the Starboard API are associated with Starboard versions. Any usage
+of new Starboard APIs must also be protected by a compile-time check for the
+Starboard version it belongs to. This decoupling of Cobalt and Starboard
+versions ensures that a porter can update to a newer version of Cobalt, but not
+be required to implement new Starboard APIs, if the version of Starboard they
+have implemented is still supported.
+
+## Starboard API version vs. Starboard application version
+
+The Starboard version describes the set of Starboard APIs available to Starboard
+applications. It will be incremented with every open-source release that
+includes changes to the Starboard API. Reasons to increment the Starboard API
+version include:
+
+* New Starboard APIs
+* Removed Starboard APIs
+* Modified semantics to existing APIs
+
+Some notable cases that do not justify incrementing the Starboard version
+include:
+
+* More descriptive or clearer comments for existing APIs that do not change the
+  semantics
+* New utility classes that are built on top of Starboard APIs, such as
+  `starboard::ScopedFile`
+* Changes that affect the upward API to Starboard applications, but not the
+  downward API to porters. For example, defining new upward APIs in terms of
+  existing Starboard APIs.
+
+A particular Starboard application may be versioned independently of the
+Starboard API. A given version of a Starboard application may support a range of
+Starboard versions. It may be the case that some new functionality in a
+Starboard application requires Starboard APIs that were added to a particular
+API version. If a porter wants to use such a feature, they must therefore also
+implement the required version of the Starboard API. For example, Voice Search
+was added to Cobalt version 5 and requires the SbMicrophone APIs which were
+added to Starboard version 2. Platforms that implemented Starboard version 1
+continued to build and run Cobalt 5 correctly, but the Voice Search feature
+would be unavailable.
+
+## Range of supported Starboard versions
+
+The minimum supported API version is defined by the `SB_MINIMUM_API_VERSION`
+macro, which is defined in starboard/configuration.h. Likewise, the
+`SB_MAXIMUM_API_VERSION` macro defines the maximum supported API version. All
+platforms must declare a `SB_API_VERSION` macro in the platform’s
+configuration.h to declare the starboard version the platform has implemented.
+Declaring implementation for an API version outside this range will result in an
+error at compilation time.
+Generally Starboard applications will not support all versions of the Starboard
+API indefinitely. Starboard application owners may increment the minimum
+required Starboard version at their discretion.
+TBD: Timelines and communication around when an upcoming Cobalt release will
+require porters to implement a newer version of Starboard.
+
+## Using new Starboard APIs from Starboard Applications
+
+Usage of a Starboard API that is not available in all supported Starboard API
+versions must be guarded with a check for `SB_API_VERSION`. Starboard
+applications must continue to function correctly and must not disable existing
+functionality if this check evaluates to false, but it’s acceptable to disable
+new functionality in Starboard applications if this evaluates to false.
+
+## Adding and using new Starboard APIs
+
+### The "Experimental" Starboard Version
+
+At any given time, exactly one version of Starboard will be denoted as the
+"experimental" version, as defined by the `SB_EXPERIMENTAL_API_VERSION` macro in
+`starboard/configuration.h`. It is generally not recommended to declare support
+for this version. Any Starboard APIs defined in the experimental version are
+subject to change and API requirements could be added, removed, or changed at
+any time.
+
+### The "Release Candidate" Starboard Version
+
+At any given time, zero or more versions of Starboard will be denoted as the
+"release candidate" version, as defined by the
+`SB_RELEASE_CANDIDATE_API_VERSION` macro in `starboard/configuration.h`. The
+"release candidate" version is a set of API changes that have been considered
+and tested together. It is reasonable to port against this version, it has gone
+through some stabilization and may become frozen as it currently is. But, be
+aware that it is possible that minor incompatible changes may be made to this
+version if an unexpected situation arises. `SB_RELEASE_CANDIDATE_API_VERSION` is
+not defined if there is no "release candidate" version. Every API version
+greater than `SB_RELEASE_CANDIDATE_API_VERSION` but less than `SB_EXPERIMENTAL_API_VERSION` is also considered a release candidate.
+
+### "Frozen" Starboard versions
+
+All Starboard versions that are less than the experimental and release candidate
+versions are considered frozen. Any Starboard APIs in a frozen version MUST not
+change.
+
+### Version Numbers, and how They Interrelate Numerically
+
+```
+frozen < release-candidate < experimental < future
+```
+
+As mentioned previously, a release candidate version may or may not exist at any
+given time.  When there is a release candate version, it follows the invariant
+above.
+
+### Life of a Starboard API
+
+New Starboard APIs should be defined in the experimental version.
+
+When introducing a new Starboard API (or modifying an existing one), a new
+feature version define should be created within the "Experimental Feature
+Defines" section of `starboard/configuration.h`, and set to
+`SB_EXPERIMENTAL_API_VERSION`. A well written comment should be added in front
+of the feature define that describes exactly what is introduced by the feature.
+In the comment, all new/modified/removed symbols should be identified, and all
+modified header files should be named.
+
+For example,
+
+```
+// in starboard/configuration.h
+
+#define SB_EXPERIMENTAL_API_VERSION 7
+
+#undef SB_RELEASE_CANDIDATE_API_VERSION
+
+// --- Experimental Feature Defines ------------------------------------------
+
+...
+
+// Introduce a new API in starboard/screensaver.h, which declares the following
+// functions for managing the platform's screensaver settings:
+//   SbScreensaverDisableScreensaver()
+//   SbScreensaverEnableScreensaver()
+// Additionally, a new event, kSbEventTypeScreensaverStarted, is introduced in
+// starboard/event.h.
+#define SB_SCREENSAVER_FEATURE_API_VERSION SB_EXPERIMENTAL_API_VERSION
+
+// Introduce a new API in starboard/new_functionality.h which declares the
+// function SbNewFunctionality().
+#define SB_MY_NEW_FEATURE_API_VERSION SB_EXPERIMENTAL_API_VERSION
+
+// Introduce another new API in starboard/still_in_development.h which
+// declares the function SbStillInDevelopment().
+#define SB_MY_OTHER_NEW_FEATURE_API_VERSION SB_EXPERIMENTAL_API_VERSION
+```
+
+When declaring the new interface, the following syntax should be used:
+
+```
+// starboard/new_functionality.h
+#if SB_API_VERSION >= SB_MY_NEW_FEATURE_API_VERSION
+void SbNewFunctionality();
+#endif
+```
+
+Starboard application features that use a new API must have a similar check:
+
+```
+// cobalt/new_feature.cc
+#if SB_API_VERSION >= SB_MY_NEW_FEATURE_API_VERSION
+void DoSomethingCool() {
+  SbNewFunctionality();
+}
+#endif
+```
+
+When promoting the experimental API version to be the release candidate API
+version, the previously undefined `SB_RELEASE_CANDIDATE_API_VERSION` is set to
+the current value of `SB_EXPERIMENTAL_API_VERSION`, and
+`SB_EXPERIMENTAL_API_VERSION` is then incremented by one. As a result,
+`SB_RELEASE_CANDIDATE_API_VERSION` on the master branch should always either be
+undefined, or `SB_EXPERIMENTAL_API_VERSION - 1`.
+
+One or more features are then moved from `SB_EXPERIMENTAL_API_VERSION` to
+`SB_RELEASE_CANDIDATE_API_VERSION`, and into the "Release Candidate Feature
+Defines" section of `starboard/configuration.h`. Some features may be left in
+experimental if they are not ready for release. The documentation comments of
+these features should be moved into the (newly created) section for the
+corresponding version in [starboard/CHANGELOG.md](../CHANGELOG.md).
+
+```
+// in starboard/configuration.h
+
+#define SB_EXPERIMENTAL_API_VERSION 8
+
+#define SB_RELEASE_CANDIDATE_API_VERSION 7
+
+// --- Experimental Feature Defines ------------------------------------------
+
+// Introduce another new API in starboard/still_in_development.h which
+// declares the function SbStillInDevelopment().
+#define SB_MY_OTHER_NEW_FEATURE_API_VERSION SB_EXPERIMENTAL_API_VERSION
+
+// --- Release Candidate Features Defines ------------------------------------
+
+#define SB_MY_NEW_FEATURE_API_VERSION SB_RELEASE_CANDIDATE_API_VERSION
+
+```
+
+When a release candidate branch is promoted to a full release, these new
+Starboard APIs will be irrevocably frozen to the value of
+`SB_RELEASE_CANDIDATE_API_VERSION`, and the release candidate version will be
+undefined. Additionally, the feature defines should be removed.
+
+```
+// starboard/new_functionality.h
+#if SB_API_VERSION >= 7
+void SbNewFunctionality();
+#endif
+
+// starboard/other_new_functionality.h
+#if SB_API_VERSION >= SB_MY_OTHER_NEW_FEATURE_API_VERSION
+void SbStillInDevelopment();
+#endif
+
+// starboard/configuration.h
+#define SB_EXPERIMENTAL_API_VERSION 8
+#undef SB_RELEASE_CANDIDATE_API_VERSION
+
+// cobalt/new_feature.cc
+#if SB_API_VERSION >= 7
+void DoSomethingCool() {
+  SbNewFunctionality();
+}
+#endif
+```
+
+Whoever increments the experimental version must ensure that stubs and reference
+platforms declare support for the new experimental version through their
+respective `SB_API_VERSION` macros.
+
+### Communicating Starboard API changes to porters
+
+When a new version of Starboard is released, [starboard/CHANGELOG.md](../CHANGELOG.md) should be
+updated with the feature define comments for all features enabled in that
+version.
diff --git a/src/cobalt/site/docs/gen/starboard/tools/doc/abstract_launcher.md b/src/cobalt/site/docs/gen/starboard/tools/doc/abstract_launcher.md
new file mode 100644
index 0000000..d75ba45
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/tools/doc/abstract_launcher.md
@@ -0,0 +1,41 @@
+---
+layout: doc
+title: "App Launchers"
+---
+# App Launchers
+
+The app launcher framework is used to run an executable on a given platform,
+allowing its output/results to be used by other scripts or tools.
+
+## Making an App Launcher
+
+In order to use this framework for your platform, there must be a method called
+"GetLauncher()" in the PlatformConfig class that your platform's
+"gyp_configuration.py" file refers to.  It should load and return a module
+containing a class called "Launcher."  This class must inherit from the
+AbstractLauncher class in [abstract_launcher.py](../../abstract_launcher.py),
+and must implement at minimum the following abstract methods:
+
+- Run(): Runs the executable, logs its output, and returns its return code.
+         Generally, any app installation work is also done in this method.
+- Kill(): Kills the currently running executable and cleans up any leftover
+          resources such as threads, processes, etc.
+
+Once the above steps are implemented, tools that use this framework, such as
+[Starboard's unit test runner](../../testing/test_runner.py), should work
+properly for your platform.  For an example of a Launcher class, see
+[this Linux implementation](../../../linux/shared/launcher.py).  For an example
+of the corresponding "GetLauncher()" method, see
+[this gyp_configuration.py file](../../../linux/shared/gyp_configuration.py).
+
+## Using an App Launcher
+
+In order to use this framework in a Python tool, it must import
+abstract_launcher.py and call "abstract_launcher.LauncherFactory()."  This
+method returns a Launcher object from the platform specified by its "platform"
+argument.  To run the launcher, call its "Run()" method, and to stop it, call
+its "Kill()" method.  If your tools need to access the Launcher's output while
+the executable is still running, have it start "Run()" in a separate thread;
+this will allow the main thread to easily read from the Launcher's output file.
+For an example of creating and using a Launcher, see
+[this example](../../example/app_launcher_client.py).
diff --git a/src/cobalt/site/docs/gen/starboard/tools/doc/testing.md b/src/cobalt/site/docs/gen/starboard/tools/doc/testing.md
new file mode 100644
index 0000000..fa54425
--- /dev/null
+++ b/src/cobalt/site/docs/gen/starboard/tools/doc/testing.md
@@ -0,0 +1,111 @@
+---
+layout: doc
+title: "Test Runner Documentation"
+---
+# Test Runner Documentation
+
+The scripts in this folder comprise a cross-platform unit test runner. The
+components of this runner are as follows:
+
+## Components
+
+### 1.) test_runner.py
+
+This script is used to run unit test binaries on multiple platforms. To see a
+full list of parameters that can be supplied to the script, run:
+
+    python test_runner.py --help
+
+#### Running Tests:
+
+To run all tests for a given platform, execute the `test_runner.py` script and
+provide at minimum the `--platform` and `--config` arguments.
+
+Example:
+
+	python test_runner.py --platform=android-x86 --config=devel
+
+Running this command will run all unit tests for the `devel` build of the
+`android-x86` platform. To specify a device to run the tests on, provide the
+`--device_id` argument, as shown below:
+
+    python test_runner.py --platform=android-x86 --config=devel \
+      --device_id=emulator-4
+
+#### Running a Single Test:
+
+If you would like to run a single unit test binary and view its output, you can
+do so by using the `--target_name` parameter and providing a test binary name,
+as shown below:
+
+    python test_runner.py --platform=android-x86 --config=devel \
+      --device_id=emulator-4 --target_name=audio_test
+
+#### Building Tests:
+
+You can also use this script to build your unit test binaries before running
+them. To do this, provide the `-b` command line flag. If you would like to
+build the tests and then run them, provide the flags `-br`.
+
+### 2.) Master list of test binaries
+
+In your application's `starboard_configuration.py` file, define a variable
+called TEST_TARGETS. It should be a list containing the names of all of the
+test binaries that you want the test runner to run. An example is shown below:
+
+    TEST_TARGETS =[
+        'audio_test',
+        'bindings_test',
+    ]
+
+If your 'starboard_configuration.py' file contains this list, then every
+platform you support in Starboard will try to run these test binaries unless
+they are filtered out as described below.
+
+## Filtering Tests
+
+To filter out tests that you do not want to run for a specific platform,
+implement a method within the platform's `PlatformConfiguration` subclass called
+`GetTestFilters()`. The `PlatformConfiguration` subclass lives in the
+`gyp_configuration.py` file for each platform. If the tests are
+application-specific, you may define `GetTestFilters()` on an optional
+`ApplicationConfiguration` subclass, which will be found in the
+`<platform-directory>/<application-name>/configuration.py` subdirectory. See
+[this Linux implementation](../../linux/x64x11/cobalt/configuration.py) for an
+example.
+
+The `GetTestFilters()` function should return a list of `TestFilter` objects,
+which can be constructed by importing `starboard.tools.testing.test_filter`. To
+make a `TestFilter` object, provide the constructor with the test target name,
+the name of the actual unit test that the target runs, and optionally, the build
+configuration from which the test should be excluded. An example is shown below:
+
+    test_filter.TestFilter('math_test', 'Vector3dTest.IsZero', 'debug')
+
+If a configuration is not provided, then the test will be excluded from all
+configurations.
+
+To filter out all tests for a particular target, provide
+`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`.
+
+## Environment Variables
+
+If a platform requires extra environment variables in order to run tests
+properly, implement a method called `GetTestEnvVariables()` in the same
+`PlatformConfiguration` or `ApplicationConfiguration` mentioned above. The
+application-level variables will be merged on top of the platform-level
+variables. There is an example of this method in the provided Linux
+implementation. The method should return a dictionary that maps test binary
+names to dictionaries of environment variables that they need.
+
+Example:
+
+    def GetTestEnvVariables(self):
+      return {
+          'base_unittests': {'ASAN_OPTIONS': 'detect_leaks=0'},
+          'crypto_unittests': {'ASAN_OPTIONS': 'detect_leaks=0'},
+          'net_unittests': {'ASAN_OPTIONS': 'detect_leaks=0'}
+      }
diff --git a/src/docker/docsite/Dockerfile-gke b/src/docker/docsite/Dockerfile-gke
new file mode 100644
index 0000000..c199810
--- /dev/null
+++ b/src/docker/docsite/Dockerfile-gke
@@ -0,0 +1,29 @@
+# Copyright 2021 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+FROM ruby:2.7-buster
+
+RUN apt update -qqy \
+    && apt install -qqy --no-install-recommends bundler doxygen git nodejs \
+        python python-pip python-setuptools python-wheel \
+    && apt-get clean autoclean \
+    && apt-get autoremove -y --purge \
+    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
+    && rm -rf /var/lib/{apt,dpkg,cache,log}
+
+COPY Gemfile /app/Gemfile
+
+RUN bundle install --gemfile=/app/Gemfile
+
+CMD ruby -v
diff --git a/src/docker/docsite/README.md b/src/docker/docsite/README.md
index 06ea6fc..d2e3701 100644
--- a/src/docker/docsite/README.md
+++ b/src/docker/docsite/README.md
@@ -26,3 +26,14 @@
 `preview-site.sh`, which normally installs gems, run with elevated permissions
 the resulting files added or modified would not be accessible to the user who
 ran the Docker container.
+
+# GKE version
+For Buildbot on GKE, we use base images then layer the Buildbot worker image
+atop. This currently requires root to work, so we have a separate simplified
+Dockerfile which only has the necessary ruby and gems installed, plus the
+additional libs required for Buildbot.
+To build and push a new version run:
+
+docker build -t gcr.io/cobalt-buildbot-gcr/docsite-builder -f Dockerfile-gke .
+
+docker push gcr.io/cobalt-buildbot-gcr/docsite-builder
diff --git a/src/docker/linux/linux-x64x11/Dockerfile b/src/docker/linux/linux-x64x11/Dockerfile
index 816203b..d58b8d9 100644
--- a/src/docker/linux/linux-x64x11/Dockerfile
+++ b/src/docker/linux/linux-x64x11/Dockerfile
@@ -21,8 +21,6 @@
         libgles2-mesa-dev \
         mesa-common-dev \
         libpulse-dev \
-        libavformat-dev \
-        libavresample-dev \
         libasound2-dev \
         libxrender-dev \
         libxcomposite-dev \
diff --git a/src/docker/linux/raspi/gn/Dockerfile b/src/docker/linux/raspi/gn/Dockerfile
index 2952fef..3339455 100644
--- a/src/docker/linux/raspi/gn/Dockerfile
+++ b/src/docker/linux/raspi/gn/Dockerfile
@@ -14,5 +14,5 @@
 
 FROM cobalt-build-raspi
 
-CMD gn gen ${OUTDIR}/${PLATFORM}_${CONFIG} --args="target_platform=\"${PLATFORM}\" build_type=\"${CONFIG}\" target_cpu=\"arm\" treat_warnings_as_errors=false" && \
+CMD gn gen ${OUTDIR}/${PLATFORM}_${CONFIG} --args="target_platform=\"${PLATFORM}\" build_type=\"${CONFIG}\" target_cpu=\"arm\" is_clang=false can_build_evergreen_loader_apps=false " && \
     ninja -j ${NINJA_PARALLEL} -C ${OUTDIR}/${PLATFORM}_${CONFIG}
diff --git a/src/docker/linux/unittest/Dockerfile b/src/docker/linux/unittest/Dockerfile
index 45b65f1..d3bff35 100644
--- a/src/docker/linux/unittest/Dockerfile
+++ b/src/docker/linux/unittest/Dockerfile
@@ -17,10 +17,6 @@
 RUN apt update -qqy \
     && apt install -qqy --no-install-recommends \
         libasound2 \
-        libavcodec-dev \
-        libavformat-dev \
-        libavresample-dev \
-        libavutil-dev \
         libegl1-mesa \
         libgl1-mesa-dri \
         libgles2-mesa \
diff --git a/src/docker/precommit_hooks/Dockerfile b/src/docker/precommit_hooks/Dockerfile
index eff79a4..19630fb 100644
--- a/src/docker/precommit_hooks/Dockerfile
+++ b/src/docker/precommit_hooks/Dockerfile
@@ -17,17 +17,29 @@
 RUN apt update -qqy \
     && apt install -qqy --no-install-recommends \
         git python2 python3 python3-pip \
+        python3-setuptools python3-wheel \
+        libncurses5 curl unzip \
     && apt-get clean autoclean \
     && apt-get autoremove -y --purge \
     && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
     && rm -rf /var/lib/{apt,dpkg,cache,log}
 
-RUN pip3 install pre-commit
+RUN pip3 install "pre-commit<3" "cpplint<2" "yapf<1" "pylint<3"
+
+# === Get GN via CIPD
+ARG GN_SHA256SUM="1291d4cf9729b6615c621139be4e9c8bb49b5cc80330e7a9e3e83c583d683f71  /usr/local/bin/gn"
+ARG GN_HASH=vC0rxqiqGTD3ls9KJHrgJoWP2OBiPk_QEO_xbDItKYoC
+
+RUN curl --location --silent --output /tmp/gn.zip \
+    "https://chrome-infra-packages.appspot.com/dl/gn/gn/linux-amd64/+/${GN_HASH}" \
+    && unzip /tmp/gn.zip -d /usr/local/bin \
+    && rm /tmp/gn.zip \
+    && echo ${GN_SHA256SUM} | sha256sum --check
 
 WORKDIR /code
 
 ENV PRE_COMMIT_COLOR=always
-ENV SKIP=test-download-from-gcs-helper,check-bug-in-commit-message,run-py2-tests
+ENV SKIP=test-download-from-gcs-helper,check-bug-in-commit-message,run-py2-tests,check-if-starboard-interface-changed
 
 CMD pre-commit install -t pre-push -t pre-commit && \
     (pre-commit run --from-ref ${FROM_REF} --to-ref ${TO_REF} --hook-stage commit; \
diff --git a/src/glimp/.gitignore b/src/glimp/.gitignore
new file mode 100644
index 0000000..5b69378
--- /dev/null
+++ b/src/glimp/.gitignore
@@ -0,0 +1,5 @@
+*.pyc
+*.sublime-workspace
+*.swp
+*.tmp
+.DS_Store
diff --git a/src/nb/.gitignore b/src/nb/.gitignore
new file mode 100644
index 0000000..e43b0f9
--- /dev/null
+++ b/src/nb/.gitignore
@@ -0,0 +1 @@
+.DS_Store
diff --git a/src/third_party/v8/__init__.py b/src/net/.gitignore
similarity index 100%
rename from src/third_party/v8/__init__.py
rename to src/net/.gitignore
diff --git a/src/net/test/test_with_scoped_task_environment.h b/src/net/test/test_with_scoped_task_environment.h
index 4ec5586..7abb7ea 100644
--- a/src/net/test/test_with_scoped_task_environment.h
+++ b/src/net/test/test_with_scoped_task_environment.h
@@ -18,7 +18,7 @@
 namespace net {
 
 // Inherit from this class if a ScopedTaskEnvironment is needed in a test.
-// Use in class hierachies where inheritance from ::testing::Test at the same
+// Use in class hierarchies where inheritance from ::testing::Test at the same
 // time is not desirable or possible (for example, when inheriting from
 // PlatformTest at the same time).
 class WithScopedTaskEnvironment {
@@ -34,16 +34,30 @@
     return scoped_task_environment_.MainThreadHasPendingTask();
   }
 
+  // Executes all tasks that have no remaining delay. Tasks with a remaining
+  // delay greater than zero will remain enqueued, and no virtual time will
+  // elapse.
   void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
 
+  // Fast-forwards virtual time by |delta|, causing all tasks with a remaining
+  // delay less than or equal to |delta| to be executed. |delta| must be
+  // non-negative.
   void FastForwardBy(base::TimeDelta delta) {
     scoped_task_environment_.FastForwardBy(delta);
   }
 
+  // Fast-forwards virtual time by |delta| but not causing any task execution.
+  void AdvanceMockTickClock(base::TimeDelta delta) {
+    scoped_task_environment_.AdvanceMockTickClock(delta);
+  }
+
+  // Fast-forwards virtual time just until all tasks are executed.
   void FastForwardUntilNoTasksRemain() {
     scoped_task_environment_.FastForwardUntilNoTasksRemain();
   }
 
+  // Returns a TickClock that uses the virtual time ticks of |this| as its tick
+  // source. The returned TickClock will hold a reference to |this|.
   const base::TickClock* GetMockTickClock() WARN_UNUSED_RESULT {
     return scoped_task_environment_.GetMockTickClock();
   }
diff --git a/src/precommit_hooks/google_java_format_wrapper.py b/src/precommit_hooks/google_java_format_wrapper.py
index ad3448c..2b5e6fd 100755
--- a/src/precommit_hooks/google_java_format_wrapper.py
+++ b/src/precommit_hooks/google_java_format_wrapper.py
@@ -24,4 +24,8 @@
     sys.exit(0)
 
   google_java_format_args = sys.argv[1:]
-  sys.exit(subprocess.call(['google-java-format'] + google_java_format_args))
+  try:
+    sys.exit(subprocess.call(['google-java-format'] + google_java_format_args))
+  except FileNotFoundError:
+    print('google-java-format not found, skipping.')
+    sys.exit(0)
diff --git a/src/requirements.txt b/src/requirements.txt
index b666306..ecfd514 100644
--- a/src/requirements.txt
+++ b/src/requirements.txt
@@ -1,5 +1,5 @@
-cpplint==1.5.4
-pre-commit==2.6.0
-pylint==2.6.0
-yapf==0.30.0
+cpplint<2
+pre-commit<3
+pylint<3
+yapf<1
 requests==2.25.1
diff --git a/src/starboard/.gitignore b/src/starboard/.gitignore
new file mode 100644
index 0000000..69fbb00
--- /dev/null
+++ b/src/starboard/.gitignore
@@ -0,0 +1,7 @@
+*.pyc
+*.sublime-workspace
+*.swp
+xcuserdata
+.DS_Store
+keyboxes
+keyboxes-dev
diff --git a/src/starboard/BUILD.gn b/src/starboard/BUILD.gn
index b421b3e..0902779 100644
--- a/src/starboard/BUILD.gn
+++ b/src/starboard/BUILD.gn
@@ -37,10 +37,10 @@
     deps += [ "//$starboard_path/platform_targets" ]
   }
 
-  if (has_platform_tests) {
-    deps += [ "//$starboard_path/starboard_platform_tests" ]
-  } else {
+  if (platform_tests_path == "") {
     deps += [ ":starboard_platform_tests" ]
+  } else {
+    deps += [ platform_tests_path ]
   }
 
   if (sb_filter_based_player) {
@@ -147,7 +147,7 @@
   ]
 }
 
-if (!has_platform_tests) {
+if (platform_tests_path == "") {
   # If 'starboard_platform_tests' is not defined by the platform, then an
   # empty 'starboard_platform_tests' target is defined.
   target(gtest_target_type, "starboard_platform_tests") {
diff --git a/src/starboard/_env.py b/src/starboard/_env.py
index f091f9e..332eabc 100644
--- a/src/starboard/_env.py
+++ b/src/starboard/_env.py
@@ -15,7 +15,7 @@
 #
 """Ask the parent directory to load the project environment."""
 
-from imp import load_source
+from imp import load_source  # pylint: disable=deprecated-module
 from os import path
 import sys
 
diff --git a/src/starboard/android/apk/.gitignore b/src/starboard/android/apk/.gitignore
new file mode 100644
index 0000000..a521b8d
--- /dev/null
+++ b/src/starboard/android/apk/.gitignore
@@ -0,0 +1,8 @@
+*.iml
+.gradle
+/local.properties
+/.idea
+.DS_Store
+/build
+/captures
+build.id
diff --git a/src/starboard/android/apk/app/.gitignore b/src/starboard/android/apk/app/.gitignore
new file mode 100644
index 0000000..bda32a5
--- /dev/null
+++ b/src/starboard/android/apk/app/.gitignore
@@ -0,0 +1,2 @@
+/.cobaltrc
+/build
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltSystemConfigChangeReceiver.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltSystemConfigChangeReceiver.java
index 5207655..9f2c5d9 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltSystemConfigChangeReceiver.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltSystemConfigChangeReceiver.java
@@ -31,18 +31,39 @@
   CobaltSystemConfigChangeReceiver(Context appContext, Runnable stopRequester) {
     this.isForeground = true;
     this.stopRequester = stopRequester;
-    appContext.registerReceiver(this, new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
+    IntentFilter filter = new IntentFilter();
+    filter.addAction(Intent.ACTION_LOCALE_CHANGED);
+    filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+    filter.addAction(Intent.ACTION_TIME_CHANGED);
+    filter.addAction(Intent.ACTION_DATE_CHANGED);
+    appContext.registerReceiver(this, filter);
   }
 
   @Override
   public void onReceive(Context context, Intent intent) {
-    if ((!Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) || isForeground) return;
+    if (isForeground) {
+      return;
+    }
 
-    Log.w(TAG, "System locale settings have changed.");
-    stopRequester.run();
+    switch (intent.getAction()) {
+      case Intent.ACTION_TIMEZONE_CHANGED:
+      case Intent.ACTION_TIME_CHANGED:
+      case Intent.ACTION_DATE_CHANGED:
+        Log.w(TAG, "System Date or Time have changed.");
+        nativeDateTimeConfigurationChanged();
+        break;
+      case Intent.ACTION_LOCALE_CHANGED:
+        Log.w(TAG, "System locale settings have changed.");
+        stopRequester.run();
+        break;
+      default:
+        Log.w(TAG, "Unknown intent.");
+    }
   }
 
   public void setForeground(final boolean isForeground) {
     this.isForeground = isForeground;
   }
+
+  private native void nativeDateTimeConfigurationChanged();
 }
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java
index c31e017..ba0329d 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java
@@ -521,6 +521,10 @@
   }
 
   private void updateMetadata(boolean resetMetadataWithEmptyBuilder) {
+    if (mediaSession == null) {
+      return;
+    }
+
     MediaMetadataCompat.Builder metadataBuilder = new MediaMetadataCompat.Builder();
     // Reset the metadata to make sure the artwork update correctly.
     if (resetMetadataWithEmptyBuilder) mediaSession.setMetadata(metadataBuilder.build());
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java
index 2473e28..fc7752e 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java
@@ -365,7 +365,7 @@
       }
 
       // This logic is inspired by
-      // https://github.com/google/ExoPlayer/blob/deb9b301b2c7ef66fdd7d8a3e58298a79ba9c619/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java#L1803.
+      // https://cs.android.com/android/_/android/platform/external/exoplayer/+/3423b4bbfffbb62b5f2d8f16cfdc984dc107cd02:tree/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java;l=2200-2215;drc=9af07bc62f8115cbaa6f1178ce8aa3533d2b9e29.
       ByteBuffer hdrStaticInfo = ByteBuffer.allocateDirect(25);
       // Force big endian in case the HDR metadata causes problems in production.
       if (forceBigEndianHdrMetadata) {
diff --git a/src/starboard/android/shared/BUILD.gn b/src/starboard/android/shared/BUILD.gn
index a84353e..a56739f 100644
--- a/src/starboard/android/shared/BUILD.gn
+++ b/src/starboard/android/shared/BUILD.gn
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("//starboard/shared/starboard/media/media_tests.gni")
 import("//starboard/shared/starboard/player/buildfiles.gni")
 
 config("starboard_platform_config") {
@@ -179,7 +180,6 @@
     "//starboard/shared/signal/crash_signals_sigaction.cc",
     "//starboard/shared/signal/suspend_signals.cc",
     "//starboard/shared/signal/suspend_signals.h",
-    "//starboard/shared/signal/system_request_conceal.cc",
     "//starboard/shared/starboard/application.cc",
     "//starboard/shared/starboard/application.h",
     "//starboard/shared/starboard/audio_sink/audio_sink_create.cc",
@@ -284,6 +284,9 @@
     "atomic_public.h",
     "audio_decoder.cc",
     "audio_decoder.h",
+    "audio_decoder_passthrough.h",
+    "audio_renderer_passthrough.cc",
+    "audio_renderer_passthrough.h",
     "audio_sink_get_max_channels.cc",
     "audio_sink_get_min_buffer_size_in_frames.cc",
     "audio_sink_get_nearest_supported_sample_frequency.cc",
@@ -293,6 +296,8 @@
     "audio_sink_min_required_frames_tester.h",
     "audio_track_audio_sink_type.cc",
     "audio_track_audio_sink_type.h",
+    "audio_track_bridge.cc",
+    "audio_track_bridge.h",
     "bionic/bionic_netlink.cpp",
     "bionic/bionic_netlink.h",
     "bionic/ifaddrs.cpp",
@@ -380,6 +385,7 @@
     "system_has_capability.cc",
     "system_network_is_disconnected.cc",
     "system_platform_error.cc",
+    "system_request_conceal.cc",
     "system_request_freeze_no_freezedone_callback.cc",
     "system_request_stop.cc",
     "system_request_suspend.cc",
@@ -468,6 +474,25 @@
   public_deps = [ "//starboard/elf_loader:evergreen_info" ]
 }
 
+target(gtest_target_type, "starboard_platform_tests") {
+  testonly = true
+
+  sources = media_tests_sources + [
+              "//starboard/common/test_main.cc",
+              "jni_env_ext_test.cc",
+              "model_year_test.cc",
+            ]
+
+  configs += [ "//starboard/build/config:starboard_implementation" ]
+
+  deps = [
+    "//starboard",
+    "//starboard/shared/starboard/player/filter/testing:test_util",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
+
 copy("ndk_sources") {
   sources = [ "$android_ndk_path/sources/android/cpufeatures/cpu-features.c" ]
   outputs = [ "$target_gen_dir/ndk-sources/{{source_file_part}}" ]
diff --git a/src/starboard/android/shared/application_android.cc b/src/starboard/android/shared/application_android.cc
index 598bed7..9d52d26 100644
--- a/src/starboard/android/shared/application_android.cc
+++ b/src/starboard/android/shared/application_android.cc
@@ -261,14 +261,14 @@
         env->CallStarboardVoidMethodOrAbort("beforeStartOrResume", "()V");
 #if SB_API_VERSION >= 13
         DispatchStart(GetAppStartTimestamp());
-#else  // SB_API_VERSION >= 13
+#else   // SB_API_VERSION >= 13
         DispatchStart();
 #endif  // SB_API_VERSION >= 13
       } else if (state() == kStateConcealed || state() == kStateFrozen) {
 #if SB_API_VERSION >= 13
-        DispatchAndDelete(new Event(kSbEventTypeReveal, SbTimeGetMonotonicNow(),
-                                    NULL, NULL));
-#else  // SB_API_VERSION >= 13
+        DispatchAndDelete(
+            new Event(kSbEventTypeReveal, SbTimeGetMonotonicNow(), NULL, NULL));
+#else   // SB_API_VERSION >= 13
         DispatchAndDelete(new Event(kSbEventTypeReveal, NULL, NULL));
 #endif  // SB_API_VERSION >= 13
       } else {
@@ -286,13 +286,13 @@
         // (rather than to the Activity lifecycle). The service should be
         // started after window being destroyed.
         StartMediaPlaybackService();
-        // Cobalt can't keep running without a window, even if the Activity
-        // hasn't stopped yet. DispatchAndDelete() will inject events as needed
-        // if we're not already paused.
+// Cobalt can't keep running without a window, even if the Activity
+// hasn't stopped yet. DispatchAndDelete() will inject events as needed
+// if we're not already paused.
 #if SB_API_VERSION >= 13
-        DispatchAndDelete(new Event(kSbEventTypeConceal, SbTimeGetMonotonicNow(),
-                                    NULL, NULL));
-#else  // SB_API_VERSION >= 13
+        DispatchAndDelete(new Event(kSbEventTypeConceal,
+                                    SbTimeGetMonotonicNow(), NULL, NULL));
+#else   // SB_API_VERSION >= 13
         DispatchAndDelete(new Event(kSbEventTypeConceal, NULL, NULL));
 #endif  // SB_API_VERSION >= 13
         if (window_) {
@@ -349,9 +349,9 @@
         } else {
           SB_LOG(INFO) << "ApplicationAndroid Inject: kSbEventTypeLink";
 #if SB_API_VERSION >= 13
-          Inject(new Event(kSbEventTypeLink, SbTimeGetMonotonicNow(),
-              deep_link, SbMemoryDeallocate));
-#else  // SB_API_VERSION >= 13
+          Inject(new Event(kSbEventTypeLink, SbTimeGetMonotonicNow(), deep_link,
+                           SbMemoryDeallocate));
+#else   // SB_API_VERSION >= 13
           Inject(new Event(kSbEventTypeLink, deep_link, SbMemoryDeallocate));
 #endif  // SB_API_VERSION >= 13
         }
@@ -359,37 +359,37 @@
       break;
   }
 
-  // If there's a window, sync the app state to the Activity lifecycle, letting
-  // DispatchAndDelete() inject events as needed if we missed a state.
+// If there's a window, sync the app state to the Activity lifecycle, letting
+// DispatchAndDelete() inject events as needed if we missed a state.
 #if SB_API_VERSION >= 13
-if (native_window_) {
+  if (native_window_) {
     switch (sync_state) {
       case AndroidCommand::kStart:
-        DispatchAndDelete(new Event(kSbEventTypeReveal, SbTimeGetMonotonicNow(),
-                                    NULL, NULL));
+        DispatchAndDelete(
+            new Event(kSbEventTypeReveal, SbTimeGetMonotonicNow(), NULL, NULL));
         break;
       case AndroidCommand::kResume:
-        DispatchAndDelete(new Event(kSbEventTypeFocus, SbTimeGetMonotonicNow(),
-                                    NULL, NULL));
+        DispatchAndDelete(
+            new Event(kSbEventTypeFocus, SbTimeGetMonotonicNow(), NULL, NULL));
         break;
       case AndroidCommand::kPause:
-        DispatchAndDelete(new Event(kSbEventTypeBlur, SbTimeGetMonotonicNow(),
-                                    NULL, NULL));
+        DispatchAndDelete(
+            new Event(kSbEventTypeBlur, SbTimeGetMonotonicNow(), NULL, NULL));
         break;
       case AndroidCommand::kStop:
         if (state() != kStateConcealed && state() != kStateFrozen) {
           // We usually conceal when losing the window above, but if the window
           // wasn't destroyed (e.g. when Daydream starts) then we still have to
           // conceal when the Activity is stopped.
-          DispatchAndDelete(new Event(kSbEventTypeConceal, SbTimeGetMonotonicNow(),
-                                      NULL, NULL));
+          DispatchAndDelete(new Event(kSbEventTypeConceal,
+                                      SbTimeGetMonotonicNow(), NULL, NULL));
         }
         break;
       default:
         break;
     }
   }
-#else  // SB_API_VERSION >= 13
+#else   // SB_API_VERSION >= 13
   if (native_window_) {
     switch (sync_state) {
       case AndroidCommand::kStart:
@@ -671,8 +671,7 @@
 SbTimeMonotonic ApplicationAndroid::GetAppStartTimestamp() {
   JniEnvExt* env = JniEnvExt::Get();
   jlong app_start_timestamp =
-      env->CallStarboardLongMethodOrAbort("getAppStartTimestamp",
-                                          "()J");
+      env->CallStarboardLongMethodOrAbort("getAppStartTimestamp", "()J");
   return app_start_timestamp;
 }
 
@@ -684,6 +683,19 @@
   return SbTimeGetMonotonicNow();
 }
 
+void ApplicationAndroid::SendDateTimeConfigurationChangedEvent() {
+  // Set the timezone to allow SbTimeZoneGetName() to return updated timezone.
+  tzset();
+  Inject(new Event(kSbEventDateTimeConfigurationChanged, NULL, NULL));
+}
+
+extern "C" SB_EXPORT_PLATFORM void
+Java_dev_cobalt_coat_CobaltSystemConfigChangeReceiver_nativeDateTimeConfigurationChanged(
+    JNIEnv* env,
+    jobject jcaller) {
+  ApplicationAndroid::Get()->SendDateTimeConfigurationChangedEvent();
+}
+
 }  // namespace shared
 }  // namespace android
 }  // namespace starboard
diff --git a/src/starboard/android/shared/application_android.h b/src/starboard/android/shared/application_android.h
index 1c8dde4..6e5a458 100644
--- a/src/starboard/android/shared/application_android.h
+++ b/src/starboard/android/shared/application_android.h
@@ -94,6 +94,8 @@
   void OsNetworkStatusChange(bool became_online);
   SbTimeMonotonic GetAppStartTimestamp();
 
+  void SendDateTimeConfigurationChangedEvent();
+
  protected:
   // --- Application overrides ---
   void Initialize() override;
diff --git a/src/starboard/android/shared/gyp_configuration.py b/src/starboard/android/shared/gyp_configuration.py
index 69a6787..83e55d2 100644
--- a/src/starboard/android/shared/gyp_configuration.py
+++ b/src/starboard/android/shared/gyp_configuration.py
@@ -15,7 +15,7 @@
 
 from __future__ import print_function
 
-import imp
+import imp  # pylint: disable=deprecated-module
 import os
 import subprocess
 
@@ -113,8 +113,8 @@
     # example src/out/android-arm64/devel/cobalt.apk
     return ['*.apk']
 
-  def GetGeneratorVariables(self, configuration):
-    _ = configuration
+  def GetGeneratorVariables(self, config_name):
+    _ = config_name
     generator_variables = {
         'qtcreator_session_name_prefix': 'cobalt',
     }
diff --git a/src/starboard/android/shared/install_target.gni b/src/starboard/android/shared/install_target.gni
index 4111a06..1442c9f 100644
--- a/src/starboard/android/shared/install_target.gni
+++ b/src/starboard/android/shared/install_target.gni
@@ -89,6 +89,8 @@
       "-P",
       "cobaltProductDir=$root_out_dir",
       "-P",
+      "cobaltLibraryDir=$root_out_dir",
+      "-P",
       "cobaltTarget=$installable_target_name",
       "-P",
       "enableVulkan=$enable_vulkan",
diff --git a/src/starboard/android/shared/media_is_video_supported.cc b/src/starboard/android/shared/media_is_video_supported.cc
index 095a698..01c23d2 100644
--- a/src/starboard/android/shared/media_is_video_supported.cc
+++ b/src/starboard/android/shared/media_is_video_supported.cc
@@ -98,14 +98,16 @@
   // Check extended parameters for correctness and return false if any invalid
   // invalid params are found.
   MimeType mime_type(content_type);
-  // Allows for enabling tunneled playback. Disabled by default.
-  // https://source.android.com/devices/tv/multimedia-tunneling
-  mime_type.RegisterBoolParameter("tunnelmode");
-  // Override endianness on HDR Info header. Defaults to little.
-  mime_type.RegisterStringParameter("hdrinfoendianness", "big|little");
+  if (strlen(content_type) > 0) {
+    // Allows for enabling tunneled playback. Disabled by default.
+    // https://source.android.com/devices/tv/multimedia-tunneling
+    mime_type.RegisterBoolParameter("tunnelmode");
+    // Override endianness on HDR Info header. Defaults to little.
+    mime_type.RegisterStringParameter("hdrinfoendianness", "big|little");
 
-  if (!mime_type.is_valid()) {
-    return false;
+    if (!mime_type.is_valid()) {
+      return false;
+    }
   }
 
   bool must_support_tunnel_mode =
diff --git a/src/starboard/android/shared/platform_configuration/configuration.gni b/src/starboard/android/shared/platform_configuration/configuration.gni
index f1c28dd..1b25e6b 100644
--- a/src/starboard/android/shared/platform_configuration/configuration.gni
+++ b/src/starboard/android/shared/platform_configuration/configuration.gni
@@ -52,3 +52,4 @@
 install_target_path = "//starboard/android/shared/install_target.gni"
 
 sb_widevine_platform = "android"
+platform_tests_path = "//starboard/android/shared:starboard_platform_tests"
diff --git a/src/starboard/android/shared/starboard_platform.gypi b/src/starboard/android/shared/starboard_platform.gypi
index 6e61339..e8579cb 100644
--- a/src/starboard/android/shared/starboard_platform.gypi
+++ b/src/starboard/android/shared/starboard_platform.gypi
@@ -164,6 +164,7 @@
         'system_has_capability.cc',
         'system_network_is_disconnected.cc',
         'system_platform_error.cc',
+        'system_request_conceal.cc',
         'system_request_freeze_no_freezedone_callback.cc',
         'system_request_stop.cc',
         'system_request_suspend.cc',
@@ -357,7 +358,6 @@
         '<(DEPTH)/starboard/shared/signal/crash_signals_sigaction.cc',
         '<(DEPTH)/starboard/shared/signal/suspend_signals.cc',
         '<(DEPTH)/starboard/shared/signal/suspend_signals.h',
-        '<(DEPTH)/starboard/shared/signal/system_request_conceal.cc',
         '<(DEPTH)/starboard/shared/starboard/application.cc',
         '<(DEPTH)/starboard/shared/starboard/application.h',
         '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc',
diff --git a/src/starboard/android/shared/system_request_conceal.cc b/src/starboard/android/shared/system_request_conceal.cc
new file mode 100644
index 0000000..ebfeb4a
--- /dev/null
+++ b/src/starboard/android/shared/system_request_conceal.cc
@@ -0,0 +1,24 @@
+// Copyright 2021 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "starboard/android/shared/jni_env_ext.h"
+
+using starboard::android::shared::JniEnvExt;
+
+void SbSystemRequestConceal() {
+  JniEnvExt* env = JniEnvExt::Get();
+  env->CallStarboardVoidMethodOrAbort("requestSuspend", "()V");
+}
diff --git a/src/starboard/android/shared/system_request_freeze_no_freezedone_callback.cc b/src/starboard/android/shared/system_request_freeze_no_freezedone_callback.cc
index d245e9e..1231877 100644
--- a/src/starboard/android/shared/system_request_freeze_no_freezedone_callback.cc
+++ b/src/starboard/android/shared/system_request_freeze_no_freezedone_callback.cc
@@ -14,12 +14,9 @@
 
 #include "starboard/system.h"
 
-#include "starboard/android/shared/jni_env_ext.h"
 #include "starboard/shared/signal/signal_internal.h"
 #include "starboard/shared/starboard/application.h"
 
-using starboard::android::shared::JniEnvExt;
-
 #if SB_IS(EVERGREEN_COMPATIBLE) && !SB_IS(EVERGREEN_COMPATIBLE_LITE)
 #include "starboard/loader_app/pending_restart.h"
 #endif  // SB_IS(EVERGREEN_COMPATIBLE) && !SB_IS(EVERGREEN_COMPATIBLE_LITE)
@@ -35,19 +32,11 @@
     // There is no FreezeDone callback for stopping all thread execution
     // after fully transitioning into Frozen.
     starboard::shared::starboard::Application::Get()->Freeze(NULL, NULL);
-
-    // Let Android platform directly transit into Frozen.
-    JniEnvExt* env = JniEnvExt::Get();
-    env->CallStarboardVoidMethodOrAbort("requestSuspend", "()V");
   }
 #else
   // There is no FreezeDone callback for stopping all thread execution
   // after fully transitioning into Frozen.
   starboard::shared::starboard::Application::Get()->Freeze(NULL, NULL);
-
-  // Let Android platform directly transit into Frozen.
-  JniEnvExt* env = JniEnvExt::Get();
-  env->CallStarboardVoidMethodOrAbort("requestSuspend", "()V");
 #endif  // SB_IS(EVERGREEN_COMPATIBLE) && !SB_IS(EVERGREEN_COMPATIBLE_LITE)
 }
 #endif  // SB_API_VERSION >= 13
diff --git a/src/starboard/build/config/BUILDCONFIG.gn b/src/starboard/build/config/BUILDCONFIG.gn
index 38169b8..b3356ca 100644
--- a/src/starboard/build/config/BUILDCONFIG.gn
+++ b/src/starboard/build/config/BUILDCONFIG.gn
@@ -26,6 +26,9 @@
   cobalt_fastbuild = getenv("IS_CI") == 1
 
   is_internal_build = false
+
+  # TODO: Remove this flag when the affected targets can be built.
+  can_build_evergreen_loader_apps = true
 }
 
 is_debug = build_type == "debug"
diff --git a/src/starboard/build/config/base_configuration.gni b/src/starboard/build/config/base_configuration.gni
index 6523033..ed0dc54 100644
--- a/src/starboard/build/config/base_configuration.gni
+++ b/src/starboard/build/config/base_configuration.gni
@@ -82,8 +82,8 @@
   # Where the Starboard ABI file for this platform can be found.
   sabi_path = "starboard/sabi/default/sabi.json"
 
-  # Whether the platform implements platforms tests.
-  has_platform_tests = false
+  # Set to the starboard_platform_tests target if the platform implements them.
+  platform_tests_path = ""
 
   # Whether the platform has platform-specific targets to depend on.
   has_platform_targets = false
@@ -98,4 +98,7 @@
   static_library_configs = []
   source_set_configs = []
   loadable_module_configs = []
+
+  # Whether or not to build drm test suites.
+  has_drm_support = true
 }
diff --git a/src/starboard/build/config/sabi/BUILD.gn b/src/starboard/build/config/sabi/BUILD.gn
index 081e595..96b4185 100644
--- a/src/starboard/build/config/sabi/BUILD.gn
+++ b/src/starboard/build/config/sabi/BUILD.gn
@@ -49,6 +49,9 @@
     "SB_SABI_JSON_ID=R\"($sabi_id)\"",
     "SB_API_VERSION=$sb_api_version",
 
+    "SB_SABI_TARGET_ARCH=\"${target_cpu}\"",
+    "SB_SABI_WORD_SIZE=\"${word_size}\"",
+
     "SB_IS_ARCH_${arch_uppercase}=1",
     "SB_HAS_${calling_convention_uppercase}_CALLING=1",
     "SB_HAS_${floating_point_abi_uppercase}_FLOATS=1",
diff --git a/src/starboard/build/doc/migrating_gyp_to_gn.md b/src/starboard/build/doc/migrating_gyp_to_gn.md
index 1a3d4bb..c6d06b6 100644
--- a/src/starboard/build/doc/migrating_gyp_to_gn.md
+++ b/src/starboard/build/doc/migrating_gyp_to_gn.md
@@ -203,20 +203,25 @@
 comparison tool, i.e. [meld](https://meldmerge.org/). This will allow you to see
 any changes in commands, i.e. with flags or otherwise.
 
-The name of the intermediate .o, .d files is different in both cases: this
-doesn't cause any issues. Keep this in mind while comparing the ninja flags for
-GYP vs GN. Here is an example for raspi2 while compiling the same source file
-```
-starboard/common/new.cc
-```
-GYP generates:
-```
-obj/starboard/common/common.new.cc.o
-```
-GN generates:
-```
-obj/starboard/common/common/new.o
-```
+The following differences for ninja flags between GYP and GN don't cause any
+issues:
+
+1. The name of the intermediate .o, .d files is different in both cases: Here is
+   an example while compiling the same source file
+   ```
+   starboard/common/new.cc
+   ```
+   GYP generates:
+   ```
+   obj/starboard/common/common.new.cc.o
+   ```
+   GN generates:
+   ```
+   obj/starboard/common/common/new.o
+   ```
+2. The `-x` flag for specifying language is not present in GN migration.
+   For example GYP specifies `-x c` flag while building c language files for
+   certain targets. This flag is not specified while building any GN targets.
 
 ### Validating a Platform
 
diff --git a/src/starboard/build/nasm_assemble.gni b/src/starboard/build/nasm_assemble.gni
new file mode 100644
index 0000000..eb1989c
--- /dev/null
+++ b/src/starboard/build/nasm_assemble.gni
@@ -0,0 +1,135 @@
+# Copyright 2021 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# This provides the nasm_assemble() template which uses NASM to
+# assemble assembly files.
+#
+# Files to be assembled with NASM should have an extension of .asm
+#
+# Example:
+#
+#   nasm_assemble("my_nasm_target") {
+#     source = [
+#       "example.asm",
+#     ]
+#     include_dirs = [ "assembly_include" ]
+#   }
+
+if (is_mac || is_ios) {
+  if (current_cpu == "x86") {
+    _nasm_flags = [ "-fmacho32" ]
+  } else if (current_cpu == "x64") {
+    _nasm_flags = [ "-fmacho64" ]
+  }
+} else if (is_posix || is_fuchsia) {
+  if (current_cpu == "x86") {
+    _nasm_flags = [ "-felf32" ]
+  } else if (current_cpu == "x64") {
+    _nasm_flags = [ "-felf64" ]
+  }
+} else if (is_win) {
+  if (current_cpu == "x86") {
+    _nasm_flags = [
+      "-DPREFIX",
+      "-fwin32",
+    ]
+  } else if (current_cpu == "x64") {
+    _nasm_flags = [ "-fwin64" ]
+  }
+}
+
+template("nasm_assemble") {
+  assert(defined(invoker.sources), "Need sources defined for $target_name")
+  assert(current_cpu == "x86" || current_cpu == "x64")
+
+  action_name = "${target_name}_action"
+  source_set_name = target_name
+
+  action_foreach(action_name) {
+    # Only the source set can depend on this.
+    visibility = [ ":$source_set_name" ]
+
+    script = "//starboard/build/run_bash.py"
+    forward_variables_from(invoker,
+                           [
+                             "sources",
+                             "inputs",
+                             "deps",
+                           ])
+
+    # Flags.
+    args = [ "$path_to_yasm" ]
+    args += _nasm_flags
+    if (defined(invoker.nasm_flags)) {
+      args += invoker.nasm_flags
+    }
+
+    # User defined include dirs go first.
+    if (defined(invoker.include_dirs)) {
+      foreach(include, invoker.include_dirs) {
+        # NASM does not append path separators when processing the -I flags,
+        # so -Ifoo means includes of bar look up "foobar" rather than "foo/bar".
+        # Add the trailing slash for it.
+        args += [ "-I" + rebase_path(include, root_build_dir) + "/" ]
+      }
+    }
+
+    # Default nasm include dirs. Make it match the native build (source root
+    # and root generated code directory).
+    # This goes to the end of include list. Note that, as above, we must
+    # append path separators because NASM does not do it itself.
+    args += [
+      "-I./",
+
+      # rebase_path("//") already includes a trailing slash.
+      "-I" + rebase_path("//", root_build_dir),
+      "-I" + rebase_path(root_gen_dir, root_build_dir) + "/",
+    ]
+
+    # Extra defines.
+    if (defined(invoker.defines)) {
+      foreach(def, invoker.defines) {
+        args += [ "-D$def" ]
+      }
+    }
+
+    # Output file.
+    outputs = [
+      "$root_out_dir/obj/third_party/libjpeg-turbo/{{source_name_part}}.asm.o",
+    ]
+    args += [
+      "-o",
+      rebase_path(outputs[0], root_build_dir),
+      "{{source}}",
+    ]
+
+    depfile = outputs[0] + ".d"
+  }
+
+  # Gather the .o files into a linkable thing. This doesn't actually link
+  # anything (a source set just compiles files to link later), but will pass
+  # the object files generated by the action up the dependency chain.
+  static_library(source_set_name) {
+    if (defined(invoker.visibility)) {
+      visibility = invoker.visibility
+    }
+
+    sources = get_target_outputs(":$action_name")
+
+    # Do not publicize any header to remove build dependency
+    public = []
+
+    deps = [ ":$action_name" ]
+  }
+}
diff --git a/src/starboard/build/platform_configuration.py b/src/starboard/build/platform_configuration.py
index f04b9e7..2cf158c 100644
--- a/src/starboard/build/platform_configuration.py
+++ b/src/starboard/build/platform_configuration.py
@@ -13,7 +13,7 @@
 # limitations under the License.
 """Base platform build configuration."""
 
-import imp
+import imp  # pylint: disable=deprecated-module
 import inspect
 import logging
 import os
diff --git a/src/starboard/contrib/linux/README.md b/src/starboard/contrib/linux/README.md
index 8c3fd94..12b5b66 100644
--- a/src/starboard/contrib/linux/README.md
+++ b/src/starboard/contrib/linux/README.md
@@ -5,7 +5,7 @@
   Sample commands:
 
 ```bash
-$ cp starboard/contrib/linux/stadia starboard/linux/
+$ cp -r starboard/contrib/linux/stadia starboard/linux/
 $ ./cobalt/build/gyp_cobalt linux-stadia
 $ ninja -C out/linux-stadia_devel cobalt
 ```
diff --git a/src/starboard/contrib/linux/stadia/atomic_public.h b/src/starboard/contrib/linux/stadia/atomic_public.h
index 6c07e70..f714dec 100644
--- a/src/starboard/contrib/linux/stadia/atomic_public.h
+++ b/src/starboard/contrib/linux/stadia/atomic_public.h
@@ -12,6 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// This file is meant to live under starboard/linux/stadia/ (see ../README.md),
+// so we disable the header guard check.
+// NOLINT(build/header_guard)
+
 #ifndef STARBOARD_LINUX_STADIA_ATOMIC_PUBLIC_H_
 #define STARBOARD_LINUX_STADIA_ATOMIC_PUBLIC_H_
 
diff --git a/src/starboard/contrib/linux/stadia/configuration_public.h b/src/starboard/contrib/linux/stadia/configuration_public.h
index 8fb5278..6c54147 100644
--- a/src/starboard/contrib/linux/stadia/configuration_public.h
+++ b/src/starboard/contrib/linux/stadia/configuration_public.h
@@ -19,6 +19,10 @@
 // Other source files should never include this header directly, but should
 // include the generic "starboard/configuration.h" instead.
 
+// This file is meant to live under starboard/linux/stadia/ (see ../README.md),
+// so we disable the header guard check.
+// NOLINT(build/header_guard)
+
 #ifndef STARBOARD_LINUX_STADIA_CONFIGURATION_PUBLIC_H_
 #define STARBOARD_LINUX_STADIA_CONFIGURATION_PUBLIC_H_
 
diff --git a/src/starboard/contrib/linux/stadia/thread_types_public.h b/src/starboard/contrib/linux/stadia/thread_types_public.h
index 96dc485..44599a0 100644
--- a/src/starboard/contrib/linux/stadia/thread_types_public.h
+++ b/src/starboard/contrib/linux/stadia/thread_types_public.h
@@ -12,6 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// This file is meant to live under starboard/linux/stadia/ (see ../README.md),
+// so we disable the header guard check.
+// NOLINT(build/header_guard)
+
 #ifndef STARBOARD_LINUX_STADIA_THREAD_TYPES_PUBLIC_H_
 #define STARBOARD_LINUX_STADIA_THREAD_TYPES_PUBLIC_H_
 
diff --git a/src/starboard/contrib/stadia/clients/vendor/public/stadia_plugin.h b/src/starboard/contrib/stadia/clients/vendor/public/stadia_plugin.h
index 4b5e699..e35c408 100644
--- a/src/starboard/contrib/stadia/clients/vendor/public/stadia_plugin.h
+++ b/src/starboard/contrib/stadia/clients/vendor/public/stadia_plugin.h
@@ -39,6 +39,7 @@
                         StadiaPluginReceiveFromCallback callback,
                         void* user_data));
 
+// clang-format off
 STADIA_EXPORT_FUNCTION(void,
                        StadiaPluginSendTo,
                        (StadiaPlugin* plugin,
@@ -46,5 +47,6 @@
                         size_t length));
 
 STADIA_EXPORT_FUNCTION(void, StadiaPluginClose, (StadiaPlugin* plugin));
+// clang-format on
 }
 #endif  // STARBOARD_CONTRIB_STADIA_CLIENTS_VENDOR_PUBLIC_STADIA_PLUGIN_H_
diff --git a/src/starboard/contrib/stadia/x11/application_stadia_x11.cc b/src/starboard/contrib/stadia/x11/application_stadia_x11.cc
index fb2fc76..dde9300 100644
--- a/src/starboard/contrib/stadia/x11/application_stadia_x11.cc
+++ b/src/starboard/contrib/stadia/x11/application_stadia_x11.cc
@@ -15,7 +15,6 @@
 #include "starboard/contrib/stadia/x11/application_stadia_x11.h"
 
 #include "starboard/contrib/stadia/services/vendor/linux/public/stadia_lifecycle.h"
-#include "starboard/shared/x11/application_x11.cc"
 #include "starboard/shared/x11/window_internal.h"
 
 namespace starboard {
diff --git a/src/starboard/contrib/stadia/x11/application_stadia_x11.h b/src/starboard/contrib/stadia/x11/application_stadia_x11.h
index 3d40274..c682cab 100644
--- a/src/starboard/contrib/stadia/x11/application_stadia_x11.h
+++ b/src/starboard/contrib/stadia/x11/application_stadia_x11.h
@@ -37,4 +37,4 @@
 }  // namespace contrib
 }  // namespace starboard
 
-#endif  // STARBOARD_CONRTIB_STADIA_X11_APPLICATION_STADIA_X11_H_
+#endif  // STARBOARD_CONTRIB_STADIA_X11_APPLICATION_STADIA_X11_H_
diff --git a/src/starboard/doc/abstract-toolchain.md b/src/starboard/doc/abstract-toolchain.md
index 8c5d8e1..0a7e5bd 100644
--- a/src/starboard/doc/abstract-toolchain.md
+++ b/src/starboard/doc/abstract-toolchain.md
@@ -10,7 +10,7 @@
 `src/tools/gyp/pylib/gyp/generator/ninja.py`.
 Modifications to this file were required for replacing any of the toolchain
 components, adding platform-specific tooling, adding new toolchains, or
-accomodating platform-specific flavor of reference tool. Doing this in a
+accommodating platform-specific flavor of reference tool. Doing this in a
 shared file does not scale with the number of ports.
 
 ## Overview
diff --git a/src/starboard/doc/c99.md b/src/starboard/doc/c99.md
index 0030329..b23ef3b 100644
--- a/src/starboard/doc/c99.md
+++ b/src/starboard/doc/c99.md
@@ -59,10 +59,12 @@
 * strcat
 * strchr
 * strcmp
+* strcpy
 * strcspn
 * strlen
 * strncmp
 * strncat
+* strncpy
 * strrchr
 * strstr
 * strspn
diff --git a/src/starboard/doc/evergreen/cobalt_evergreen_overview.md b/src/starboard/doc/evergreen/cobalt_evergreen_overview.md
index 51130f1..001f324 100644
--- a/src/starboard/doc/evergreen/cobalt_evergreen_overview.md
+++ b/src/starboard/doc/evergreen/cobalt_evergreen_overview.md
@@ -503,16 +503,17 @@
 
 ### Fonts
 The system font directory `kSbSystemPathFontDirectory` should be configured to
-point to the `standard` (23MB) or the `limited` (3.1MB) cobalt font packages. An
-easy way to do that is to use the `kSbSystemPathContentDirectory` to contain
-the system font directory and setting the `cobalt_font_package` to `standard` or
-`limited` in your port.
+point to either the system fonts on the device or the Cobalt `standard` (23MB)
+or the Cobalt `limited` (3.1MB) font packages. An easy way to use the Cobalt
+fonts is to set `kSbSystemPathFontDirectory` to point to
+`kSbSystemPathContentDirectory/fonts` and configure `cobalt_font_package` to
+`standard` or `limited` in your port.
 
 Cobalt Evergreen (built by Google), will by default use the `empty` font
 package to minimize storage requirements. A separate
 `cobalt_font_package` variable is set to `empty` in the Evergreen platform.
 
-On Raspberry Pi this is:
+On Raspberry Pi the Cobalt fonts are configured the following way:
 
 `empty` set of fonts under:
 ```
diff --git a/src/starboard/doc/howto_decode_to_texture.md b/src/starboard/doc/howto_decode_to_texture.md
index 3bb46bc..993d50a 100644
--- a/src/starboard/doc/howto_decode_to_texture.md
+++ b/src/starboard/doc/howto_decode_to_texture.md
@@ -84,7 +84,7 @@
    texture/surface handle to render the video frame as it wishes.
 
 5. When the application is finished using the `SbDecodeTarget` that it has
-   aquired through the `SbPlayerGetCurrentFrame()` function, it will call
+   acquired through the `SbPlayerGetCurrentFrame()` function, it will call
    `SbDecodeTargetRelease()` on it.  The Starboard platform implementation
    should ensure that the `SbDecodeTarget` object returned by
    `SbPlayerGetCurrentFrame()` remains valid until the corresponding call to
@@ -133,4 +133,4 @@
 to cache those frames (along with their timestamps) so that they can be
 passed on to the application when `SbPlayerGetCurrentFrame()` is called.
 This same strategy applies if the player pushes frames only when they are meant
-to be rendered.
\ No newline at end of file
+to be rendered.
diff --git a/src/starboard/doc/principles.md b/src/starboard/doc/principles.md
index a58fba7..d24877d 100644
--- a/src/starboard/doc/principles.md
+++ b/src/starboard/doc/principles.md
@@ -150,4 +150,3 @@
   * [Joshua Bloch's presentation about API design](https://www.youtube.com/watch?v=aAb7hSCtvGw)
   * [Joshua Bloch's bumper sticker API design rules](http://www.infoq.com/articles/API-Design-Joshua-Bloch)
   * [digithead's collection of API design links (I didn't read them all)](http://digitheadslabnotebook.blogspot.com/2010/07/how-to-design-good-apis.html)
-
diff --git a/src/starboard/doc/resources/decode_to_texture_sequence.txt b/src/starboard/doc/resources/decode_to_texture_sequence.txt
index 5118f0b..ac5127b 100644
--- a/src/starboard/doc/resources/decode_to_texture_sequence.txt
+++ b/src/starboard/doc/resources/decode_to_texture_sequence.txt
@@ -11,4 +11,3 @@
 Note over a: Extracts GLES texture(s) from the\nSbDecodeTarget object and\nrenders a scene with them. [fillcolor="white"]
 a->s: SbDecodeTargetRelease()
 Note over a: Goto: Start of render loop [fillcolor="#ffffd0"]
-
diff --git a/src/starboard/doc/starboard_split.md b/src/starboard/doc/starboard_split.md
index cab325c..a222d83 100644
--- a/src/starboard/doc/starboard_split.md
+++ b/src/starboard/doc/starboard_split.md
@@ -55,4 +55,4 @@
 
 ##### Notes
 
-For migrating from macros, partners will have to treat their use differently! I.e. string literal vs const char* in their implementations. Add an overview of all of the cases of this migration in runtime code.
\ No newline at end of file
+For migrating from macros, partners will have to treat their use differently! I.e. string literal vs const char* in their implementations. Add an overview of all of the cases of this migration in runtime code.
diff --git a/src/starboard/doc/style.md b/src/starboard/doc/style.md
index f14aa33..546618e 100644
--- a/src/starboard/doc/style.md
+++ b/src/starboard/doc/style.md
@@ -105,7 +105,7 @@
     name of the module following the `Sb`.
       * `file.h` contains `SbFile`, `SbFileInfo`, `SbFileWhence`, etc...
   * Every seemingly-allocatable, platform-specific Starboard type should be
-    defined as an opaque handle to a publically undefined struct with the
+    defined as an opaque handle to a publicly undefined struct with the
     `Private` suffix. Follow this pattern for all such type declarations.
       * `struct SbFilePrivate` is declared, but not defined in the public header.
       * `SbFilePrivate` is `typedef`'d to `struct SbFilePrivate`. This is a C
diff --git a/src/starboard/elf_loader/BUILD.gn b/src/starboard/elf_loader/BUILD.gn
index 9ce393b..eff2b9e 100644
--- a/src/starboard/elf_loader/BUILD.gn
+++ b/src/starboard/elf_loader/BUILD.gn
@@ -97,31 +97,33 @@
   ]
 }
 
-target(final_executable_type, "elf_loader_sys_sandbox") {
-  # To properly function the system loader requires the starboard
-  # symbols to be exported from the binary.
-  # To allow symbols to be exported remove the '-fvisibility=hidden' flag
-  # from your compiler_flags.gypi. For Linux this would be:
-  #   starboard/linux/shared/compiler_flags.gypi
-  # Example run:
-  # export LD_LIBRARY_PATH=.
-  # ./elf_loader_sys_sandbox --evergreen_library=app/cobalt/lib/libcobalt.so --evergreen_content=app/cobalt/content
-  sources = [ "sandbox.cc" ]
-  configs += [ ":elf_loader_config" ]
+if (can_build_evergreen_loader_apps) {
+  target(final_executable_type, "elf_loader_sys_sandbox") {
+    # To properly function the system loader requires the starboard
+    # symbols to be exported from the binary.
+    # To allow symbols to be exported remove the '-fvisibility=hidden' flag
+    # from your compiler_flags.gypi. For Linux this would be:
+    #   starboard/linux/shared/compiler_flags.gypi
+    # Example run:
+    # export LD_LIBRARY_PATH=.
+    # ./elf_loader_sys_sandbox --evergreen_library=app/cobalt/lib/libcobalt.so --evergreen_content=app/cobalt/content
+    sources = [ "sandbox.cc" ]
+    configs += [ ":elf_loader_config" ]
 
-  starboard_syms_path =
-      rebase_path("//starboard/starboard.syms", root_build_dir)
-  ldflags = [
-    "-Wl,--dynamic-list=$starboard_syms_path",
-    "-ldl",
-  ]
+    starboard_syms_path =
+        rebase_path("//starboard/starboard.syms", root_build_dir)
+    ldflags = [
+      "-Wl,--dynamic-list=$starboard_syms_path",
+      "-ldl",
+    ]
 
-  deps = [
-    ":elf_loader_sys",
-    ":evergreen_info",
-    ":sabi_string",
-    "//starboard",
-  ]
+    deps = [
+      ":elf_loader_sys",
+      ":evergreen_info",
+      ":sabi_string",
+      "//starboard",
+    ]
+  }
 }
 
 target(gtest_target_type, "elf_loader_test") {
diff --git a/src/starboard/evergreen/testing/linux/stop_process.sh b/src/starboard/evergreen/testing/linux/stop_process.sh
new file mode 100644
index 0000000..ace0eca
--- /dev/null
+++ b/src/starboard/evergreen/testing/linux/stop_process.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# Copyright 2021 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+function stop_process() {
+  if [[ $# -ne 1 ]]; then
+    log "error" " stop_process only accepts a single argument"
+    return 1
+  fi
+
+  kill -9 "${1}" 1> /dev/null
+}
diff --git a/src/starboard/evergreen/testing/raspi/clean_up.sh b/src/starboard/evergreen/testing/raspi/clean_up.sh
index 50d3792..6c2d9ad 100755
--- a/src/starboard/evergreen/testing/raspi/clean_up.sh
+++ b/src/starboard/evergreen/testing/raspi/clean_up.sh
@@ -14,5 +14,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-source $1/../linux/clean_up.sh
+function clean_up() {
+  echo " Clearing loader app process id storage"
+  eval "${SSH}\"rm -rf ${PID_STORAGE_DIR}\"" 1> /dev/null
 
+  clear_storage
+}
diff --git a/src/starboard/evergreen/testing/raspi/setup.sh b/src/starboard/evergreen/testing/raspi/setup.sh
index 3292873..65c263a 100755
--- a/src/starboard/evergreen/testing/raspi/setup.sh
+++ b/src/starboard/evergreen/testing/raspi/setup.sh
@@ -21,6 +21,7 @@
 CONTENT="/home/pi/coeg/content/app/cobalt/content"
 STORAGE_DIR="/home/pi/.cobalt_storage"
 STORAGE_DIR_TMPFS="${STORAGE_DIR}.tmpfs"
+PID_STORAGE_DIR="/tmp/cobalt_loader_pids"
 
 ID="id"
 TAIL="tail"
@@ -69,3 +70,12 @@
     fi
   fi
 fi
+
+eval "${SSH}\"test -d /tmp\"" 1> /dev/null
+if [[ $? -ne 0 ]]; then
+  echo " The '/tmp' directory is required on the Raspberry Pi 2 to persist data"
+  exit 1
+fi
+
+echo " Making a directory on the Raspberry Pi 2 to store loader app process ids"
+run_command "mkdir -p ${PID_STORAGE_DIR}"
diff --git a/src/starboard/evergreen/testing/raspi/start_cobalt.sh b/src/starboard/evergreen/testing/raspi/start_cobalt.sh
index a1ea738..f64e0da 100755
--- a/src/starboard/evergreen/testing/raspi/start_cobalt.sh
+++ b/src/starboard/evergreen/testing/raspi/start_cobalt.sh
@@ -44,9 +44,26 @@
 
   log "info" " Logs will be output to '${LOG_PATH}/${LOG}'"
 
-  eval "${SSH}\"/home/pi/coeg/loader_app --url=\"\"${URL}\"\" ${ARGS} \" 2>&1 | tee \"${LOG_PATH}/${LOG}\"" &
+  # A file name unique to the process, provided by the current time in
+  # milliseconds, isn't strictly needed but is used out of caution.
+  declare pid_storage_path="${PID_STORAGE_DIR}/$(date +%s%3N)"
 
-  loader_pid_ref=$!
+  # The stored process ID initially points to a remote shell process but that
+  # process image is quickly replaced, via exec, with a new one executing the
+  # loader app. This approach enables the local machine to obtain the loader
+  # app's process ID without interfering with its stdout/stderr, which must be
+  # piped to tee.
+  declare store_pid_cmd="echo \\$\\$ > ${pid_storage_path}"
+  declare replace_with_loader_cmd="exec /home/pi/coeg/loader_app --url=\"\"${URL}\"\" ${ARGS}"
+  eval "${SSH}\"${store_pid_cmd};${replace_with_loader_cmd}\" 2>&1 | tee \"${LOG_PATH}/${LOG}\"" &
+
+  # The device's filesystem is polled to avoid a race condition since the
+  # previous eval command is necessarily run in the background.
+  eval "${SSH}\"while [[ ! -f ${pid_storage_path} ]] ; do sleep 1 ; done\""
+
+  loader_pid_ref=$(eval "${SSH}\"cat ${pid_storage_path}\"")
+
+  delete_file "${pid_storage_path}"
 
   log "info" " Cobalt process ID is ${loader_pid_ref}"
 }
diff --git a/src/starboard/evergreen/testing/raspi/stop_process.sh b/src/starboard/evergreen/testing/raspi/stop_process.sh
new file mode 100644
index 0000000..aee05a3
--- /dev/null
+++ b/src/starboard/evergreen/testing/raspi/stop_process.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# Copyright 2021 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+function stop_process() {
+  if [[ $# -ne 1 ]]; then
+    log "error" " stop_process only accepts a single argument"
+    return 1
+  fi
+
+  eval "${SSH}\"kill -9 ${1}\"" 1> /dev/null
+}
diff --git a/src/starboard/evergreen/testing/setup.sh b/src/starboard/evergreen/testing/setup.sh
index 7820281..0cf60da 100755
--- a/src/starboard/evergreen/testing/setup.sh
+++ b/src/starboard/evergreen/testing/setup.sh
@@ -57,7 +57,8 @@
          "${DIR}/${1}/deploy_cobalt.sh"       \
          "${DIR}/${1}/run_command.sh"         \
          "${DIR}/${1}/start_cobalt.sh"        \
-         "${DIR}/${1}/stop_cobalt.sh")
+         "${DIR}/${1}/stop_cobalt.sh"         \
+         "${DIR}/${1}/stop_process.sh")
 
 for script in "${SCRIPTS[@]}"; do
   if [[ ! -f "${script}" ]]; then
diff --git a/src/starboard/evergreen/testing/shared/cycle_cobalt.sh b/src/starboard/evergreen/testing/shared/cycle_cobalt.sh
index 9b26cf7..276b321 100755
--- a/src/starboard/evergreen/testing/shared/cycle_cobalt.sh
+++ b/src/starboard/evergreen/testing/shared/cycle_cobalt.sh
@@ -85,9 +85,9 @@
   watch_cobalt "${LOG}" "${PAT}"
   RES=$?
 
-  log "info" " Stopping with 'kill -9 ${LOADER}'"
+  log "info" " Stopping ${LOADER}"
 
-  kill -9 "${LOADER}" 1> /dev/null
+  stop_process "${LOADER}"
 
   sleep 1
 
diff --git a/src/starboard/linux/shared/BUILD.gn b/src/starboard/linux/shared/BUILD.gn
index 9ef03b9..07cc2eb 100644
--- a/src/starboard/linux/shared/BUILD.gn
+++ b/src/starboard/linux/shared/BUILD.gn
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("//starboard/shared/starboard/media/media_tests.gni")
 import("//starboard/shared/starboard/player/buildfiles.gni")
 
 group("starboard_platform") {
@@ -366,7 +367,6 @@
     "//starboard/shared/stub/system_get_total_gpu_memory.cc",
     "//starboard/shared/stub/system_get_used_gpu_memory.cc",
     "//starboard/shared/stub/system_hide_splash_screen.cc",
-    "//starboard/shared/stub/system_network_is_disconnected.cc",
     "//starboard/shared/stub/system_raise_platform_error.cc",
     "//starboard/shared/stub/system_sign_with_certification_secret_key.cc",
     "//starboard/shared/stub/thread_create_priority.cc",
@@ -447,3 +447,18 @@
     ]
   }
 }
+
+target(gtest_target_type, "starboard_platform_tests") {
+  testonly = true
+
+  sources = media_tests_sources + [ "//starboard/common/test_main.cc" ]
+
+  configs += [ "//starboard/build/config:starboard_implementation" ]
+
+  deps = [
+    "//starboard",
+    "//starboard/shared/starboard/player/filter/testing:test_util",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
diff --git a/src/starboard/linux/shared/gyp_configuration.py b/src/starboard/linux/shared/gyp_configuration.py
index b408b63..319cdc2 100644
--- a/src/starboard/linux/shared/gyp_configuration.py
+++ b/src/starboard/linux/shared/gyp_configuration.py
@@ -113,6 +113,7 @@
       ],
   }
 
+  # pylint: disable=line-too-long
   __FILTERED_TESTS = {  # pylint: disable=invalid-name
       'player_filter_tests': [
           # libdav1d crashes when fed invalid data
@@ -120,9 +121,11 @@
       ],
   }
   # Conditionally disables tests that require ipv6
-  if os.getenv('IPV6_AVAILABLE', 1) == '0':
+  if os.getenv('IPV6_AVAILABLE', '1') == '0':
     __FILTERED_TESTS['nplb'] = [
         'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.SunnyDayDestination/1',
         'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.SunnyDaySourceForDestination/1',
         'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.SunnyDaySourceNotLoopback/1',
     ]
+
+  # pylint: enable=line-too-long
diff --git a/src/starboard/linux/shared/platform_configuration/configuration.gni b/src/starboard/linux/shared/platform_configuration/configuration.gni
index eda9b87..5d6af1b 100644
--- a/src/starboard/linux/shared/platform_configuration/configuration.gni
+++ b/src/starboard/linux/shared/platform_configuration/configuration.gni
@@ -33,3 +33,6 @@
     "//starboard/linux/shared/platform_configuration:no_pedantic_warnings"
 
 sb_widevine_platform = "linux"
+
+has_drm_support = is_internal_build
+platform_tests_path = "//starboard/linux/shared:starboard_platform_tests"
diff --git a/src/starboard/linux/x64x11/shared/BUILD.gn b/src/starboard/linux/x64x11/shared/BUILD.gn
index 3238904a..8407ab2 100644
--- a/src/starboard/linux/x64x11/shared/BUILD.gn
+++ b/src/starboard/linux/x64x11/shared/BUILD.gn
@@ -19,7 +19,7 @@
     "//starboard/linux/shared:starboard_platform",
   ]
 
-  deps = [ "//third_party/libjpeg" ]
+  deps = [ "//third_party/libjpeg-turbo:libjpeg" ]
 }
 
 static_library("starboard_platform_sources") {
diff --git a/src/starboard/loader_app/BUILD.gn b/src/starboard/loader_app/BUILD.gn
index 481ccc8..cc35c66 100644
--- a/src/starboard/loader_app/BUILD.gn
+++ b/src/starboard/loader_app/BUILD.gn
@@ -42,22 +42,24 @@
   }
 }
 
-target(final_executable_type, "loader_app_sys") {
-  if (target_cpu == "x86" || target_cpu == "x64" || target_cpu == "arm" ||
-      target_cpu == "arm64") {
-    sources = _common_loader_app_sources
+if (can_build_evergreen_loader_apps) {
+  target(final_executable_type, "loader_app_sys") {
+    if (target_cpu == "x86" || target_cpu == "x64" || target_cpu == "arm" ||
+        target_cpu == "arm64") {
+      sources = _common_loader_app_sources
 
-    starboard_syms_path =
-        rebase_path("//starboard/starboard.syms", root_build_dir)
-    ldflags = [
-      "-Wl,--dynamic-list=$starboard_syms_path",
-      "-ldl",
-    ]
-    deps = [
-      ":common_loader_app_dependencies",
-      "//cobalt/content/fonts:copy_font_data",
-      "//starboard/elf_loader:elf_loader_sys",
-    ]
+      starboard_syms_path =
+          rebase_path("//starboard/starboard.syms", root_build_dir)
+      ldflags = [
+        "-Wl,--dynamic-list=$starboard_syms_path",
+        "-ldl",
+      ]
+      deps = [
+        ":common_loader_app_dependencies",
+        "//cobalt/content/fonts:copy_font_data",
+        "//starboard/elf_loader:elf_loader_sys",
+      ]
+    }
   }
 }
 
diff --git a/src/starboard/nplb/BUILD.gn b/src/starboard/nplb/BUILD.gn
index a53df6a..20e502d 100644
--- a/src/starboard/nplb/BUILD.gn
+++ b/src/starboard/nplb/BUILD.gn
@@ -107,6 +107,7 @@
     "drm_helpers.cc",
     "drm_helpers.h",
     "drm_is_server_certificate_updatable_test.cc",
+    "drm_session_test.cc",
     "drm_update_server_certificate_test.cc",
     "egl_test.cc",
     "extern_c_test.cc",
@@ -294,7 +295,7 @@
     "window_get_size_test.cc",
   ]
 
-  if (is_internal_build) {
+  if (has_drm_support) {
     sources += [
       "drm_create_system_test.cc",
       "media_can_play_mime_and_key_system_test.cc",
@@ -303,6 +304,10 @@
 
   deps = [ "//starboard/nplb/testdata/file_tests:nplb_file_tests_data" ]
 
+  if (is_internal_build) {
+    deps += [ "//starboard/private/nplb:nplb_private" ]
+  }
+
   public_deps = [
     "//starboard",
     "//starboard/common",
diff --git a/src/starboard/raspi/2/gyp_configuration.py b/src/starboard/raspi/2/gyp_configuration.py
index 7cf32e4..5f5b245 100644
--- a/src/starboard/raspi/2/gyp_configuration.py
+++ b/src/starboard/raspi/2/gyp_configuration.py
@@ -17,6 +17,7 @@
 
 
 class Raspi2PlatformConfig(shared_configuration.RaspiPlatformConfig):
+  """Starboard raspi-2 platform configuration."""
 
   def __init__(self,
                platform,
@@ -24,8 +25,8 @@
     super(Raspi2PlatformConfig, self).__init__(
         platform, sabi_json_path=sabi_json_path)
 
-  def GetVariables(self, config_name):
-    variables = super(Raspi2PlatformConfig, self).GetVariables(config_name)
+  def GetVariables(self, configuration):
+    variables = super(Raspi2PlatformConfig, self).GetVariables(configuration)
     return variables
 
 
diff --git a/src/starboard/raspi/shared/BUILD.gn b/src/starboard/raspi/shared/BUILD.gn
index 3828973..2cc3d1c 100644
--- a/src/starboard/raspi/shared/BUILD.gn
+++ b/src/starboard/raspi/shared/BUILD.gn
@@ -375,6 +375,17 @@
 
   sources += common_player_sources
 
+  if (sb_api_version == 12) {
+    sources += [
+      "//starboard/shared/stub/speech_recognizer_cancel.cc",
+      "//starboard/shared/stub/speech_recognizer_create.cc",
+      "//starboard/shared/stub/speech_recognizer_destroy.cc",
+      "//starboard/shared/stub/speech_recognizer_is_supported.cc",
+      "//starboard/shared/stub/speech_recognizer_start.cc",
+      "//starboard/shared/stub/speech_recognizer_stop.cc",
+    ]
+  }
+
   configs += [
     "//starboard/build/config:pedantic_warnings",
     "//starboard/build/config:starboard_implementation",
diff --git a/src/starboard/raspi/shared/platform_configuration/BUILD.gn b/src/starboard/raspi/shared/platform_configuration/BUILD.gn
index 98d7b28..fe181d1 100644
--- a/src/starboard/raspi/shared/platform_configuration/BUILD.gn
+++ b/src/starboard/raspi/shared/platform_configuration/BUILD.gn
@@ -182,8 +182,7 @@
     # This decision should be revisited after raspi toolchain is upgraded.
     "-Wno-maybe-uninitialized",
 
-    #TODO: Renable -Werror after fixing all warnings.
-    #"-Werror",
+    "-Werror",
     "-Wno-expansion-to-defined",
     "-Wno-implicit-fallthrough",
   ]
diff --git a/src/starboard/raspi/shared/platform_configuration/configuration.gni b/src/starboard/raspi/shared/platform_configuration/configuration.gni
index fd4a3ce..4ceaa77 100644
--- a/src/starboard/raspi/shared/platform_configuration/configuration.gni
+++ b/src/starboard/raspi/shared/platform_configuration/configuration.gni
@@ -15,12 +15,12 @@
 import("//starboard/build/config/base_configuration.gni")
 
 arm_float_abi = "hard"
+has_drm_support = false
 sb_pedantic_warnings = true
 sb_static_contents_output_data_dir = "$root_out_dir/content"
 
-pedantic_warnings_config_path =
-    "//starboard/raspi/shared/platform_configuration:pedantic_warnings"
 no_pedantic_warnings_config_path =
     "//starboard/raspi/shared/platform_configuration:no_pedantic_warnings"
-
+pedantic_warnings_config_path =
+    "//starboard/raspi/shared/platform_configuration:pedantic_warnings"
 sabi_path = "//starboard/sabi/arm/hardfp/sabi-v$sb_api_version.json"
diff --git a/src/starboard/sabi/_env.py b/src/starboard/sabi/_env.py
index f091f9e..332eabc 100644
--- a/src/starboard/sabi/_env.py
+++ b/src/starboard/sabi/_env.py
@@ -15,7 +15,7 @@
 #
 """Ask the parent directory to load the project environment."""
 
-from imp import load_source
+from imp import load_source  # pylint: disable=deprecated-module
 from os import path
 import sys
 
diff --git a/src/starboard/shared/starboard/media/media_tests.gni b/src/starboard/shared/starboard/media/media_tests.gni
new file mode 100644
index 0000000..38c8042
--- /dev/null
+++ b/src/starboard/shared/starboard/media/media_tests.gni
@@ -0,0 +1,21 @@
+# Copyright 2021 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+media_tests_sources = [
+  "//starboard/shared/starboard/media/avc_util_test.cc",
+  "//starboard/shared/starboard/media/codec_util_test.cc",
+  "//starboard/shared/starboard/media/mime_type_test.cc",
+  "//starboard/shared/starboard/media/video_capabilities_test.cc",
+  "//starboard/shared/starboard/media/vp9_util_test.cc",
+]
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
index 64f94ab..6a4b15e 100644
--- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
+++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
@@ -161,7 +161,7 @@
     player_components_ =
         factory->CreateComponents(creation_parameters, error_message);
     if (!player_components_) {
-      SB_LOG(ERROR) << "Failed to create renderer with error: "
+      SB_LOG(ERROR) << "Failed to create player components with error: "
                     << *error_message;
       return false;
     }
@@ -399,8 +399,7 @@
     // only log when the other members of |bounds| have been changed to avoid
     // spamming the log.
     bounds_.z_index = bounds.z_index;
-    bool bounds_changed =
-        memcmp(&bounds_, &bounds, sizeof(bounds_)) != 0;
+    bool bounds_changed = memcmp(&bounds_, &bounds, sizeof(bounds_)) != 0;
     SB_LOG_IF(INFO, bounds_changed)
         << "Set bounds to "
         << "x: " << bounds.x << ", y: " << bounds.y
diff --git a/src/starboard/shared/starboard/player/testdata/.gitignore b/src/starboard/shared/starboard/player/testdata/.gitignore
new file mode 100644
index 0000000..f1136ab
--- /dev/null
+++ b/src/starboard/shared/starboard/player/testdata/.gitignore
@@ -0,0 +1,2 @@
+*.dmp
+
diff --git a/src/starboard/stub/gyp_configuration.py b/src/starboard/stub/gyp_configuration.py
index 6329189..dc2a4b2 100644
--- a/src/starboard/stub/gyp_configuration.py
+++ b/src/starboard/stub/gyp_configuration.py
@@ -39,9 +39,6 @@
 class StubConfiguration(config.base.PlatformConfigBase):
   """Starboard stub platform configuration."""
 
-  def __init__(self, platform):
-    super(StubConfiguration, self).__init__(platform)
-
   def GetVariables(self, configuration):
     variables = super(StubConfiguration, self).GetVariables(
         configuration, use_clang=1)
@@ -59,7 +56,7 @@
     })
     return env_variables
 
-  def GetTargetToolchain(self, **kwargs):
+  def GetTargetToolchain(self, **kwargs):  # pylint: disable=unused-argument
     environment_variables = self.GetEnvironmentVariables()
     cc_path = environment_variables['CC']
     cxx_path = environment_variables['CXX']
@@ -77,7 +74,7 @@
         bash.Shell(),
     ]
 
-  def GetHostToolchain(self, **kwargs):
+  def GetHostToolchain(self, **kwargs):  # pylint: disable=unused-argument
     environment_variables = self.GetEnvironmentVariables()
     cc_path = environment_variables['CC_host']
     cxx_path = environment_variables['CXX_host']
diff --git a/src/starboard/tools/doc/abstract_launcher.md b/src/starboard/tools/doc/abstract_launcher.md
index 062ade4..c612081 100644
--- a/src/starboard/tools/doc/abstract_launcher.md
+++ b/src/starboard/tools/doc/abstract_launcher.md
@@ -34,4 +34,4 @@
 the executable is still running, have it start "Run()" in a separate thread;
 this will allow the main thread to easily read from the Launcher's output file.
 For an example of creating and using a Launcher, see
-[this example](../../example/app_launcher_client.py).
\ No newline at end of file
+[this example](../../example/app_launcher_client.py).
diff --git a/src/starboard/tools/doc/testing.md b/src/starboard/tools/doc/testing.md
index d675e09..e26e6fb 100644
--- a/src/starboard/tools/doc/testing.md
+++ b/src/starboard/tools/doc/testing.md
@@ -78,7 +78,7 @@
 
     test_filter.TestFilter('math_test', 'Vector3dTest.IsZero', 'debug')
 
-If a configuration is not provided, then the test will be exluded from all
+If a configuration is not provided, then the test will be excluded from all
 configurations.
 
 To filter out all tests for a particular target, provide
diff --git a/src/starboard/tools/testing/test_runner.py b/src/starboard/tools/testing/test_runner.py
index 1ae0133..a4db330 100755
--- a/src/starboard/tools/testing/test_runner.py
+++ b/src/starboard/tools/testing/test_runner.py
@@ -402,8 +402,9 @@
       test_params.append("--gtest_filter=" + gtest_filter_value)
 
     if self.log_xml_results:
-      # Log the xml results
-      test_params.append("--gtest_output=xml:log")
+      # Log the xml results in the current working directory.
+      xml_filename = "{}_testoutput.xml".format(target_name)
+      test_params.append("--gtest_output=xml:{}".format(xml_filename))
       logging.info("Xml results for this test will be logged.")
     elif self.xml_output_dir:
       # Have gtest create and save a test result xml
diff --git a/src/testing/gmock/.gitignore b/src/testing/gmock/.gitignore
new file mode 100644
index 0000000..e43b0f9
--- /dev/null
+++ b/src/testing/gmock/.gitignore
@@ -0,0 +1 @@
+.DS_Store
diff --git a/src/testing/gmock/src/gmock-internal-utils.cc b/src/testing/gmock/src/gmock-internal-utils.cc
index 4e9381d..0065286 100644
--- a/src/testing/gmock/src/gmock-internal-utils.cc
+++ b/src/testing/gmock/src/gmock-internal-utils.cc
@@ -64,8 +64,8 @@
     // We don't care about the current locale as the input is
     // guaranteed to be a valid C++ identifier name.
     const bool starts_new_word = IsUpper(*p) ||
-        (!IsAlpha(prev_char) && IsLower(*p)) ||
-        (!IsDigit(prev_char) && IsDigit(*p));
+                                 (!IsAlpha(prev_char) && IsLower(*p)) ||
+                                 (!IsDigit(prev_char) && IsDigit(*p));
 
     if (IsAlNum(*p)) {
       if (starts_new_word && result != "")
@@ -81,14 +81,13 @@
 // use Google Mock with a testing framework other than Google Test.
 class GoogleTestFailureReporter : public FailureReporterInterface {
  public:
-  virtual void ReportFailure(FailureType type, const char* file, int line,
+  virtual void ReportFailure(FailureType type,
+                             const char* file,
+                             int line,
                              const string& message) {
-    AssertHelper(type == kFatal ?
-                 TestPartResult::kFatalFailure :
-                 TestPartResult::kNonFatalFailure,
-                 file,
-                 line,
-                 message.c_str()) = Message();
+    AssertHelper(type == kFatal ? TestPartResult::kFatalFailure
+                                : TestPartResult::kNonFatalFailure,
+                 file, line, message.c_str()) = Message();
     if (type == kFatal) {
       posix::Abort();
     }
@@ -147,24 +146,21 @@
   // macro.
 
   if (severity == kWarning) {
-    // Prints a GMOCK WARNING marker to make the warnings easily searchable.
-#if GTEST_OS_STARBOARD
-    SB_LOG(INFO) << "\nGMOCK WARNING:";
-#else
+// Prints a GMOCK WARNING marker to make the warnings easily searchable.
+#if !GTEST_OS_STARBOARD
     std::cout << "\nGMOCK WARNING:";
 #endif
   }
   // Pre-pends a new-line to message if it doesn't start with one.
   if (message.empty() || message[0] != '\n') {
-#if GTEST_OS_STARBOARD
-    SB_LOG(INFO) << "\nGMOCK WARNING:";
-#else
+#if !GTEST_OS_STARBOARD
     std::cout << "\n";
 #endif
   }
 
 #if GTEST_OS_STARBOARD
-  SB_LOG(INFO) << "\nGMOCK WARNING:";
+  SB_LOG(INFO) << "\nGMOCK" << ((severity == kWarning) ? " WARNING" : "")
+               << ": " << message;
 #else
   std::cout << message;
 #endif
@@ -189,14 +185,14 @@
 
 #if GTEST_OS_STARBOARD
     SB_LOG(INFO) << "Stack trace:\n"
-         << ::testing::internal::GetCurrentOsStackTraceExceptTop(
-             ::testing::UnitTest::GetInstance(), actual_to_skip);
+                 << ::testing::internal::GetCurrentOsStackTraceExceptTop(
+                        ::testing::UnitTest::GetInstance(), actual_to_skip);
   }
   SB_LOG(INFO) << ::std::flush;
 #else
     std::cout << "Stack trace:\n"
-         << ::testing::internal::GetCurrentOsStackTraceExceptTop(
-             ::testing::UnitTest::GetInstance(), actual_to_skip);
+              << ::testing::internal::GetCurrentOsStackTraceExceptTop(
+                     ::testing::UnitTest::GetInstance(), actual_to_skip);
   }
   std::cout << ::std::flush;
 #endif
diff --git a/src/testing/gtest-parallel/.gitignore b/src/testing/gtest-parallel/.gitignore
new file mode 100644
index 0000000..2f5184c
--- /dev/null
+++ b/src/testing/gtest-parallel/.gitignore
@@ -0,0 +1,2 @@
+.*.swp
+.DS_Store
diff --git a/src/testing/gtest/.gitignore b/src/testing/gtest/.gitignore
new file mode 100644
index 0000000..e43b0f9
--- /dev/null
+++ b/src/testing/gtest/.gitignore
@@ -0,0 +1 @@
+.DS_Store
diff --git a/src/third_party/angle/.gitignore b/src/third_party/angle/.gitignore
new file mode 100644
index 0000000..6723e41
--- /dev/null
+++ b/src/third_party/angle/.gitignore
@@ -0,0 +1,87 @@
+.vs
+*.Makefile
+*.ncb
+*.nvuser
+*.opensdf
+*.orig
+*.psess
+*.pyc
+*.rej
+*.sdf
+*.sln
+*.suo
+*.target.mk
+*.TMP
+*.VC.db
+*.VC.opendb
+*.vcproj
+*.vcxproj
+*.vcxproj.filters
+*.vcxproj.user
+*.vsp
+*~
+.DS_Store
+.*.sw*
+.cipd
+.gclient
+.gclient_entries
+.git_cl_description_backup
+/src/tests/third_party/gles_conformance_tests
+/testing
+/third_party/android_ndk
+/third_party/catapult
+/third_party/cherry
+/third_party/fuchsia-sdk
+/third_party/gles1_conform
+/third_party/glmark2/src
+/third_party/glslang/src
+/third_party/googletest
+/third_party/jsoncpp
+/third_party/libjpeg_turbo
+/third_party/libpng/src
+/third_party/llvm-build
+/third_party/Python-Markdown
+/third_party/qemu-linux-x64
+/third_party/qemu-mac-x64
+/third_party/rapidjson/src
+/third_party/spirv-cross/src
+/third_party/spirv-headers/src
+/third_party/spirv-tools/src
+/third_party/SwiftShader
+/third_party/VK-GL-CTS/src
+/third_party/vulkan-headers/src
+/third_party/vulkan-loader/src
+/third_party/vulkan-tools/src
+/third_party/vulkan-validation-layers/src
+/third_party/yasm
+/third_party/zlib
+/tools/clang
+/tools/flex-bison/linux/bison
+/tools/flex-bison/linux/flex
+/tools/flex-bison/windows/bison.exe
+/tools/flex-bison/windows/flex.exe
+/tools/flex-bison/windows/m4.exe
+/tools/flex-bison/windows/msys*.dll
+/tools/glslang/glslang_validator
+/tools/glslang/glslang_validator.exe
+/tools/md_browser
+/tools/memory
+angle_debug.txt
+build
+buildtools/
+debug.txt
+Debug/
+Debug_ARM/
+Debug_Win32/
+Debug_x64/
+diag.txt
+ipch
+lib/*
+out
+patches-*
+Release/
+Release_ARM/
+Release_Win32/
+Release_x64/
+TestResults.qpa
+.idea/
diff --git a/src/third_party/angle/samples/capture_replay/.gitignore b/src/third_party/angle/samples/capture_replay/.gitignore
new file mode 100644
index 0000000..b149c68
--- /dev/null
+++ b/src/third_party/angle/samples/capture_replay/.gitignore
@@ -0,0 +1 @@
+angle_capture_context*
\ No newline at end of file
diff --git a/src/third_party/blink/Tools/Scripts/webkitpy/thirdparty/wpt/wpt/.gitignore b/src/third_party/blink/Tools/Scripts/webkitpy/thirdparty/wpt/wpt/.gitignore
new file mode 100644
index 0000000..162fd51
--- /dev/null
+++ b/src/third_party/blink/Tools/Scripts/webkitpy/thirdparty/wpt/wpt/.gitignore
@@ -0,0 +1,15 @@
+*#
+*.py[co]
+*.sw[po]
+*~
+MANIFEST.json
+\#*
+_certs
+.virtualenv
+config.json
+node_modules
+scratch
+testharness_runner.html
+webdriver/.idea
+.vscode/
+.DS_Store
diff --git a/src/third_party/blink/Tools/Scripts/webkitpy/thirdparty/wpt/wpt/tools/wptserve/.gitignore b/src/third_party/blink/Tools/Scripts/webkitpy/thirdparty/wpt/wpt/tools/wptserve/.gitignore
new file mode 100644
index 0000000..8e87d38
--- /dev/null
+++ b/src/third_party/blink/Tools/Scripts/webkitpy/thirdparty/wpt/wpt/tools/wptserve/.gitignore
@@ -0,0 +1,40 @@
+*.py[cod]
+*~
+\#*
+
+docs/_build/
+
+# C extensions
+*.so
+
+# Packages
+*.egg
+*.egg-info
+dist
+build
+eggs
+parts
+bin
+var
+sdist
+develop-eggs
+.installed.cfg
+lib
+lib64
+
+# Installer logs
+pip-log.txt
+
+# Unit test / coverage reports
+.coverage
+.tox
+nosetests.xml
+tests/functional/html/*
+
+# Translations
+*.mo
+
+# Mr Developer
+.mr.developer.cfg
+.project
+.pydevproject
diff --git a/src/third_party/boringssl/src/.gitignore b/src/third_party/boringssl/src/.gitignore
new file mode 100644
index 0000000..db50b0b
--- /dev/null
+++ b/src/third_party/boringssl/src/.gitignore
@@ -0,0 +1,28 @@
+build/
+ssl/test/runner/runner
+*.swp
+*.swo
+doc/*.html
+doc/doc.css
+
+util/bot/android_ndk
+util/bot/android_tools
+util/bot/cmake-linux64
+util/bot/cmake-linux64.tar.gz
+util/bot/cmake-mac
+util/bot/cmake-mac.tar.gz
+util/bot/cmake-win32
+util/bot/cmake-win32.zip
+util/bot/golang
+util/bot/gyp
+util/bot/libcxx
+util/bot/libcxxabi
+util/bot/libFuzzer
+util/bot/llvm-build
+util/bot/nasm-win32.exe
+util/bot/perl-win32
+util/bot/perl-win32.zip
+util/bot/sde-linux64
+util/bot/sde-linux64.tar.bz2
+util/bot/win_toolchain.json
+util/bot/yasm-win32.exe
diff --git a/src/third_party/brotli/.gitignore b/src/third_party/brotli/.gitignore
new file mode 100644
index 0000000..a6d1d90
--- /dev/null
+++ b/src/third_party/brotli/.gitignore
@@ -0,0 +1,17 @@
+# C
+*.o
+bin/
+buildfiles/
+**/obj/
+dist/
+
+# Python
+__pycache__/
+*.py[cod]
+*.so
+*.egg-info/
+
+# Tests
+*.txt.uncompressed
+*.br
+*.unbr
diff --git a/src/third_party/crashpad/.gitignore b/src/third_party/crashpad/.gitignore
new file mode 100644
index 0000000..fe8a94c
--- /dev/null
+++ b/src/third_party/crashpad/.gitignore
@@ -0,0 +1,42 @@
+# Copyright 2014 The Crashpad Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+*.Makefile
+*.ninja
+*.pyc
+*.target.mk
+*.xcodeproj
+*~
+.*.sw?
+.DS_Store
+.gdb_history
+.gdbinit
+/Makefile
+/out
+/third_party/edo/edo
+/third_party/fuchsia/.cipd
+/third_party/fuchsia/clang
+/third_party/fuchsia/qemu
+/third_party/fuchsia/sdk
+/third_party/gtest/gtest
+/third_party/libfuzzer
+/third_party/linux/.cipd
+/third_party/linux/clang
+/third_party/linux/sysroot
+/third_party/lss/lss
+/third_party/gyp/gyp
+/third_party/mini_chromium/mini_chromium
+/third_party/zlib/zlib
+/xcodebuild
+tags
diff --git a/src/third_party/crashpad/doc/.gitignore b/src/third_party/crashpad/doc/.gitignore
new file mode 100644
index 0000000..e324eac
--- /dev/null
+++ b/src/third_party/crashpad/doc/.gitignore
@@ -0,0 +1 @@
+/generated
diff --git a/src/third_party/crashpad/handler/BUILD.gn b/src/third_party/crashpad/handler/BUILD.gn
index 8823beb..91a0f06 100644
--- a/src/third_party/crashpad/handler/BUILD.gn
+++ b/src/third_party/crashpad/handler/BUILD.gn
@@ -152,6 +152,20 @@
 }
 
 if (!crashpad_is_ios) {
+  if (crashpad_is_in_starboard) {
+    config("crashpad_handler_starboard_config") {
+      cflags = [
+        "-ffunction-sections",
+        "-fdata-sections",
+      ]
+      ldflags = [
+        "-Wl,--as-needed",
+        "-Wl,-gc-sections",
+        "-Wl,-z,noexecstack",
+      ]
+    }
+  }
+
   crashpad_executable("crashpad_handler") {
     if (crashpad_is_in_starboard) {
       check_includes = false
@@ -166,17 +180,22 @@
       "../third_party/mini_chromium:base",
     ]
 
+    configs = []
     if (crashpad_is_win) {
       if (crashpad_is_in_chromium || crashpad_is_in_dart) {
         remove_configs = [ "//build/config/win:console" ]
-        configs = [ "//build/config/win:windowed" ]
+        configs += [ "//build/config/win:windowed" ]
       } else {
         remove_configs =
             [ "//third_party/mini_chromium/mini_chromium/build:win_console" ]
-        configs =
+        configs +=
             [ "//third_party/mini_chromium/mini_chromium/build:win_windowed" ]
       }
     }
+
+    if (crashpad_is_in_starboard) {
+      configs += [ ":crashpad_handler_starboard_config" ]
+    }
   }
 }
 
diff --git a/src/third_party/devtools/.gitignore b/src/third_party/devtools/.gitignore
new file mode 100644
index 0000000..c5f7022
--- /dev/null
+++ b/src/third_party/devtools/.gitignore
@@ -0,0 +1,34 @@
+.DS_Store
+.git_cl_description_backup
+.vscode
+*.Makefile
+*.mk
+*.pyc
+*.rsp
+*.rules
+*.sln
+*.stamp
+*.tmp
+*.vcproj*
+*.vcxproj*
+*.xcodeproj*
+/.dev_profile
+/.test_cache
+/front_end/*/jsconfig.json
+/front_end/protocol_externs.js
+/release
+/scripts/visualize_deps/out
+config.gypi
+karma-coverage
+npm-debug.log
+
+# These are generated for build and would be put in the symlinked folder (thus this folder)
+/front_end/InspectorBackendCommands.js
+/front_end/SupportedCSSProperties.js
+/front_end/accessibility/ARIAProperties.js
+/front_end/formatter_worker.js
+/front_end/heap_snapshot_worker.js
+
+/build
+/buildtools
+/out
diff --git a/src/third_party/devtools/front_end/sdk/wasm_source_map/.gitignore b/src/third_party/devtools/front_end/sdk/wasm_source_map/.gitignore
new file mode 100644
index 0000000..53eaa21
--- /dev/null
+++ b/src/third_party/devtools/front_end/sdk/wasm_source_map/.gitignore
@@ -0,0 +1,2 @@
+/target
+**/*.rs.bk
diff --git a/src/third_party/devtools/scripts/migration/.gitignore b/src/third_party/devtools/scripts/migration/.gitignore
new file mode 100644
index 0000000..0fb3f3a
--- /dev/null
+++ b/src/third_party/devtools/scripts/migration/.gitignore
@@ -0,0 +1,6 @@
+refactor-to-es-module.js
+remove-unused-global-exports.js
+move-side-effects-to-legacy.js
+get-mappings.js
+replace-internal-references.js
+node_modules
diff --git a/src/third_party/devtools/scripts/run_old_devtools/.gitignore b/src/third_party/devtools/scripts/run_old_devtools/.gitignore
new file mode 100644
index 0000000..231fb44
--- /dev/null
+++ b/src/third_party/devtools/scripts/run_old_devtools/.gitignore
@@ -0,0 +1,2 @@
+debugging-user-data-dir
+user-data-dir
diff --git a/src/third_party/flac/.gitignore b/src/third_party/flac/.gitignore
new file mode 100644
index 0000000..e43b0f9
--- /dev/null
+++ b/src/third_party/flac/.gitignore
@@ -0,0 +1 @@
+.DS_Store
diff --git a/src/third_party/freetype2/.gitignore b/src/third_party/freetype2/.gitignore
new file mode 100644
index 0000000..a47f568
--- /dev/null
+++ b/src/third_party/freetype2/.gitignore
@@ -0,0 +1,3 @@
+config.mk
+objs/vc2010/
+build
diff --git a/src/third_party/freetype2/builds/unix/.gitignore b/src/third_party/freetype2/builds/unix/.gitignore
new file mode 100644
index 0000000..f89b226
--- /dev/null
+++ b/src/third_party/freetype2/builds/unix/.gitignore
@@ -0,0 +1,18 @@
+aclocal.m4
+autom4te.cache
+config.cache
+config.guess
+config.log
+config.status
+config.sub
+configure
+configure.ac
+freetype2.pc
+freetype-config
+ftconfig.h
+ftoption.h
+install-sh
+libtool
+ltmain.sh
+unix-cc.mk
+unix-def.mk
diff --git a/src/third_party/freetype2/builds/windows/.gitignore b/src/third_party/freetype2/builds/windows/.gitignore
new file mode 100644
index 0000000..41456a4
--- /dev/null
+++ b/src/third_party/freetype2/builds/windows/.gitignore
@@ -0,0 +1,5 @@
+# user-specific cache/settings files
+*.opensdf
+*.sdf
+*.suo
+*.user
diff --git a/src/third_party/freetype2/docs/.gitignore b/src/third_party/freetype2/docs/.gitignore
new file mode 100644
index 0000000..b8d05d1
--- /dev/null
+++ b/src/third_party/freetype2/docs/.gitignore
@@ -0,0 +1,12 @@
+# Static site folder
+reference/
+
+# HTML and Markdown files
+*.html
+*.md
+
+# MkDocs Config file
+mkdocs.yml
+
+# Python virtualenv
+env/
diff --git a/src/third_party/freetype2/objs/.gitignore b/src/third_party/freetype2/objs/.gitignore
new file mode 100644
index 0000000..f847620
--- /dev/null
+++ b/src/third_party/freetype2/objs/.gitignore
@@ -0,0 +1,3 @@
+*
+!README
+!.gitignore
diff --git a/src/third_party/glm/.gitignore b/src/third_party/glm/.gitignore
new file mode 100644
index 0000000..e699e5e
--- /dev/null
+++ b/src/third_party/glm/.gitignore
@@ -0,0 +1,54 @@
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
+
+# CMake
+CMakeCache.txt
+CMakeFiles
+cmake_install.cmake
+install_manifest.txt
+*.cmake
+# ^ May need to add future .cmake files as exceptions
+
+# Test logs
+Testing/*
+
+# Test input
+test/gtc/*.dds
+
+# Project Files
+Makefile
+*.cbp
+*.user
+
+# Misc.
+*.log
+.DS_Store
+
+# local build(s)
+build*
diff --git a/src/third_party/google_benchmark/.gitignore b/src/third_party/google_benchmark/.gitignore
new file mode 100644
index 0000000..a7716e3
--- /dev/null
+++ b/src/third_party/google_benchmark/.gitignore
@@ -0,0 +1,62 @@
+*.a
+*.so
+*.so.?*
+*.dll
+*.exe
+*.dylib
+*.cmake
+!/cmake/*.cmake
+!/test/AssemblyTests.cmake
+*~
+*.swp
+*.pyc
+__pycache__
+
+# lcov
+*.lcov
+/lcov
+
+# cmake files.
+/Testing
+CMakeCache.txt
+CMakeFiles/
+cmake_install.cmake
+
+# makefiles.
+Makefile
+
+# in-source build.
+bin/
+lib/
+/test/*_test
+
+# exuberant ctags.
+tags
+
+# YouCompleteMe configuration.
+.ycm_extra_conf.pyc
+
+# ninja generated files.
+.ninja_deps
+.ninja_log
+build.ninja
+install_manifest.txt
+rules.ninja
+
+# bazel output symlinks.
+bazel-*
+
+# out-of-source build top-level folders.
+build/
+_build/
+build*/
+
+# in-source dependencies
+/googletest/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+CMakeSettings.json
+
+# Visual Studio Code cache/options directory
+.vscode/
diff --git a/src/third_party/icu/.gitignore b/src/third_party/icu/.gitignore
new file mode 100644
index 0000000..e43b0f9
--- /dev/null
+++ b/src/third_party/icu/.gitignore
@@ -0,0 +1 @@
+.DS_Store
diff --git a/src/third_party/inspector_protocol/.gitignore b/src/third_party/inspector_protocol/.gitignore
new file mode 100644
index 0000000..069df0d
--- /dev/null
+++ b/src/third_party/inspector_protocol/.gitignore
@@ -0,0 +1,9 @@
+*.pyc
+*~
+
+# Generated files.
+out*/
+
+# Third party files which are pulled with gclient (see DEPS).
+third_party/gtest/gtest
+third_party/mini_chromium/mini_chromium
diff --git a/src/third_party/libdav1d/.gitignore b/src/third_party/libdav1d/.gitignore
new file mode 100644
index 0000000..2bbd7c4
--- /dev/null
+++ b/src/third_party/libdav1d/.gitignore
@@ -0,0 +1,8 @@
+/build*
+/Session.vim
+[._]*.swp
+*~
+tags
+.DS_Store
+/tests/dav1d-test-data
+*.snap
diff --git a/src/third_party/libjpeg-turbo/BUILD.gn b/src/third_party/libjpeg-turbo/BUILD.gn
index 39a4f7a..ab09f6e 100644
--- a/src/third_party/libjpeg-turbo/BUILD.gn
+++ b/src/third_party/libjpeg-turbo/BUILD.gn
@@ -23,11 +23,20 @@
   ]
   if (!is_starboard) {
     defines = [ "MANGLE_JPEG_NAMES" ]
+  } else {
+    public_deps = [
+      "//starboard:starboard_headers_only",
+      "//starboard/common",
+    ]
   }
 }
 
 if (current_cpu == "x86" || current_cpu == "x64") {
-  import("//third_party/nasm/nasm_assemble.gni")
+  if (is_starboard) {
+    import("//starboard/build/nasm_assemble.gni")
+  } else {
+    import("//third_party/nasm/nasm_assemble.gni")
+  }
 
   nasm_assemble("simd_asm") {
     defines = []
@@ -252,6 +261,22 @@
     "NO_GETENV",
   ]
 
+  if (is_starboard) {
+    sources += [
+      "jaricom.c",
+      "jcarith.c",
+      "jdarith.c",
+    ]
+    # These dependencies are needed for file io
+    # and are not currently used by Cobalt
+    sources -= [
+      "jdatadst.c",
+      "jdatasrc.c",
+    ]
+    # This is defined in code.
+    defines -= [ "NO_GETENV" ]
+  }
+
   configs += [ ":libjpeg_config" ]
 
   public_configs = [ ":libjpeg_config" ]
@@ -282,6 +307,15 @@
     "wrppm.c",
   ]
 
+  if (is_starboard) {
+    sources -= [
+      "rdbmp.c",
+      "rdppm.c",
+      "wrbmp.c",
+      "wrppm.c",
+    ]
+  }
+
   defines = [
     "WITH_SIMD",
     "BMP_SUPPORTED",
diff --git a/src/third_party/libjpeg-turbo/libjpeg.gyp b/src/third_party/libjpeg-turbo/libjpeg.gyp
index 01af1bd..3448a91 100644
--- a/src/third_party/libjpeg-turbo/libjpeg.gyp
+++ b/src/third_party/libjpeg-turbo/libjpeg.gyp
@@ -5,6 +5,7 @@
 {
   'variables': {
     'optimize_target_for_speed': 1,
+    'is_starboard': 1,
   },
   'targets': [
     {
@@ -49,7 +50,9 @@
         'jdapimin.c',
         'jdapistd.c',
         'jdarith.c',
+        'jdatadst.c',
         'jdatadst-tj.c',
+        'jdatasrc.c',
         'jdatasrc-tj.c',
         'jdcoefct.c',
         'jdcolor.c',
@@ -88,21 +91,29 @@
         'jquant2.c',
         'jutils.c',
         'jversion.h',
+        'rdbmp.c',
+        'rdppm.c',
         'transupp.h',
         'transupp.c',
         'turbojpeg.h',
         'turbojpeg.c',
+        'wrbmp.c',
+        'wrppm.c',
         '<@(no_simd_files)',
-        # These dependecies are needed for file io
-        # and are not currently used by Cobalt.
-        #'rdbmp.c',
-        #'rdppm.c',
-        #'wrbmp.c',
-        #'wrppm.c',
-        #'jdatasrc.c',
-        #'jdatadst.c',
       ],
       'conditions': [
+        ['is_starboard', {
+          # These dependecies are needed for file io
+          # and are not currently used by Cobalt.
+          'sources!': [
+            'jdatadst.c',
+            'jdatasrc.c',
+            'rdbmp.c',
+            'rdppm.c',
+            'wrbmp.c',
+            'wrppm.c',
+          ],
+        }],
         # arm processor specific optimizations.
         ['target_arch == "arm" and arm_neon == 1 or target_arch == "arm64" and arm_neon == 1', {
           'include_dirs': [
diff --git a/src/third_party/libvpx/.gitignore b/src/third_party/libvpx/.gitignore
new file mode 100644
index 0000000..5f26835
--- /dev/null
+++ b/src/third_party/libvpx/.gitignore
@@ -0,0 +1,69 @@
+*.S
+*.a
+*.asm.s
+*.d
+*.gcda
+*.gcno
+*.o
+*~
+.cproject
+.project
+.settings
+/*-*.mk
+/*.asm
+/*.doxy
+/*.ivf
+/*.ivf.md5
+/.bins
+/.deps
+/.docs
+/.install-*
+/.libs
+/Makefile
+/arm_neon.h
+/config.log
+/config.mk
+/docs/
+/doxyfile
+/examples/*.dox
+/examples/decode_to_md5
+/examples/decode_with_drops
+/examples/decode_with_partial_drops
+/examples/example_xma
+/examples/postproc
+/examples/resize_util
+/examples/set_maps
+/examples/simple_decoder
+/examples/simple_encoder
+/examples/twopass_encoder
+/examples/vp8_multi_resolution_encoder
+/examples/vp8cx_set_ref