Import Cobalt 4.11565
diff --git a/src/cobalt/audio/audio_node_input.cc b/src/cobalt/audio/audio_node_input.cc
index 2f42724..9be0c32 100644
--- a/src/cobalt/audio/audio_node_input.cc
+++ b/src/cobalt/audio/audio_node_input.cc
@@ -232,7 +232,12 @@
   // TODO: Consider computing computedNumberOfChannels and do up-mix or
   // down-mix base on computedNumberOfChannels. The current implementation
   // is based on the fact that the channelCountMode is max.
-  DCHECK_EQ(owner_node_->channel_count_mode(), AudioNode::kMax);
+  if (owner_node_->channel_count_mode() != AudioNode::kMax) {
+    DLOG(ERROR) << "Unsupported channel count mode: "
+                << owner_node_->channel_count_mode();
+    return;
+  }
+
   // Pull audio buffer from connected audio input. When an input is connected
   // from one or more AudioNode outputs. Fan-in is supported.
   for (std::set<AudioNodeOutput*>::iterator iter = outputs_.begin();
diff --git a/src/cobalt/base/base.gyp b/src/cobalt/base/base.gyp
index a2822ab..19652ec 100644
--- a/src/cobalt/base/base.gyp
+++ b/src/cobalt/base/base.gyp
@@ -45,6 +45,7 @@
         'log_message_handler.h',
         'math.cc',
         'math.h',
+        'message_queue.h',
         'poller.h',
         'polymorphic_downcast.h',
         'polymorphic_equatable.h',
diff --git a/src/cobalt/base/message_queue.h b/src/cobalt/base/message_queue.h
new file mode 100644
index 0000000..3c7ad78
--- /dev/null
+++ b/src/cobalt/base/message_queue.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_BASE_MESSAGE_QUEUE_H_
+#define COBALT_BASE_MESSAGE_QUEUE_H_
+
+#include <queue>
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/synchronization/lock.h"
+
+namespace base {
+
+// A thread safe in-order message queue.  In some situations this can be
+// preferred versus PostTask()ing directly to a MessageLoop since the data
+// stored within the queued Closures can be destroyed on demand, and also the
+// queue messages can be processed at a time of the user's choosing.
+class MessageQueue {
+ public:
+  ~MessageQueue() {
+    // Leave no message behind!
+    ProcessAll();
+  }
+
+  // Add a message to the end of the queue.
+  void AddMessage(const base::Closure& message) {
+    base::AutoLock lock(mutex_);
+    DCHECK(!message.is_null());
+    queue_.push(message);
+  }
+
+  // Execute all messages in the MessageQueue until the queue is empty and then
+  // return.
+  void ProcessAll() {
+    base::AutoLock lock(mutex_);
+
+    while (!queue_.empty()) {
+      queue_.front().Run();
+      queue_.pop();
+    }
+  }
+
+ private:
+  base::Lock mutex_;
+  std::queue<base::Closure> queue_;
+};
+
+}  // namespace base
+
+#endif  // COBALT_BASE_MESSAGE_QUEUE_H_
diff --git a/src/cobalt/bindings/testing/bindings_test_base.h b/src/cobalt/bindings/testing/bindings_test_base.h
index 25e9ea2..f634699 100644
--- a/src/cobalt/bindings/testing/bindings_test_base.h
+++ b/src/cobalt/bindings/testing/bindings_test_base.h
@@ -25,6 +25,7 @@
 #include "cobalt/script/global_environment.h"
 #include "cobalt/script/javascript_engine.h"
 #include "cobalt/script/source_code.h"
+#include "cobalt/script/wrappable.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -71,6 +72,17 @@
     return global_environment_->EvaluateScript(source, out_result);
   }
 
+  bool EvaluateScript(const std::string& script,
+                      const scoped_refptr<script::Wrappable>& owning_object,
+                      base::optional<script::OpaqueHandleHolder::Reference>*
+                          out_opaque_handle = NULL) {
+    scoped_refptr<script::SourceCode> source =
+        script::SourceCode::CreateSourceCode(
+            script, base::SourceLocation("[object BindingsTestBase]", 1, 1));
+    return global_environment_->EvaluateScript(source, owning_object,
+                                               out_opaque_handle);
+  }
+
   void CollectGarbage() { engine_->CollectGarbage(); }
 
  protected:
diff --git a/src/cobalt/bindings/testing/evaluate_script_test.cc b/src/cobalt/bindings/testing/evaluate_script_test.cc
new file mode 100644
index 0000000..61d74fa
--- /dev/null
+++ b/src/cobalt/bindings/testing/evaluate_script_test.cc
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/bindings/testing/arbitrary_interface.h"
+#include "cobalt/bindings/testing/bindings_test_base.h"
+#include "cobalt/bindings/testing/object_type_bindings_interface.h"
+#include "cobalt/bindings/testing/script_object_owner.h"
+
+using cobalt::script::OpaqueHandleHolder;
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::StrictMock;
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+namespace {
+class EvaluateScriptTest
+    : public InterfaceBindingsTest<ObjectTypeBindingsInterface> {};
+}  // namespace
+
+TEST_F(EvaluateScriptTest, TwoArguments) {
+  std::string result;
+
+  std::string script =
+      "function fib(n) {\n"
+      "  if (n <= 0) {\n"
+      "    return 0;\n"
+      "  } else if (n == 1) {\n"
+      "    return 1;\n"
+      "  } else {\n"
+      "    return fib(n - 1) + fib(n - 2);\n"
+      "  }\n"
+      "}\n"
+      "fib(8)";
+  EXPECT_TRUE(EvaluateScript(script, &result));
+  EXPECT_STREQ("21", result.c_str());
+}
+
+TEST_F(EvaluateScriptTest, ThreeArguments) {
+  std::string script =
+      "function fib(n) {\n"
+      "  if (n <= 0) {\n"
+      "    return 0;\n"
+      "  } else if (n == 1) {\n"
+      "    return 1;\n"
+      "  } else {\n"
+      "    return fib(n - 1) + fib(n - 2);\n"
+      "  }\n"
+      "}\n"
+      "fib(8)";
+
+  // Call with null out handle.
+  scoped_refptr<StrictMock<ArbitraryInterface> > arbitrary_interface_mock(
+      new StrictMock<ArbitraryInterface>());
+  EXPECT_TRUE(EvaluateScript(script, arbitrary_interface_mock, NULL));
+
+  // Call with non-null, but unset optional handle.
+  base::optional<OpaqueHandleHolder::Reference> opaque_handle;
+  EXPECT_TRUE(EvaluateScript(script, arbitrary_interface_mock, &opaque_handle));
+  ASSERT_FALSE(opaque_handle->referenced_object().IsNull());
+
+  EXPECT_CALL(test_mock(), object_property())
+      .WillOnce(Return(&opaque_handle->referenced_object()));
+  std::string result;
+  EXPECT_TRUE(EvaluateScript("test.objectProperty == 21;", &result));
+  EXPECT_STREQ("true", result.c_str());
+}
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
diff --git a/src/cobalt/bindings/testing/global_constructors_idls_idl_files_list.tmp b/src/cobalt/bindings/testing/global_constructors_idls_idl_files_list.tmp
deleted file mode 100644
index 1f9a3fc..0000000
--- a/src/cobalt/bindings/testing/global_constructors_idls_idl_files_list.tmp
+++ /dev/null
@@ -1,45 +0,0 @@
-AnonymousIndexedGetterInterface.idl
-AnonymousNamedGetterInterface.idl
-AnonymousNamedIndexedGetterInterface.idl
-ArbitraryInterface.idl
-BaseInterface.idl
-BooleanTypeTestInterface.idl
-CallbackFunctionInterface.idl
-CallbackInterfaceInterface.idl
-ConditionalInterface.idl
-ConstantsInterface.idl
-ConstructorInterface.idl
-ConstructorWithArgumentsInterface.idl
-DerivedGetterSetterInterface.idl
-DerivedInterface.idl
-DisabledInterface.idl
-DOMStringTestInterface.idl
-EnumerationInterface.idl
-ExceptionObjectInterface.idl
-ExceptionsInterface.idl
-ExtendedIDLAttributesInterface.idl
-GarbageCollectionTestInterface.idl
-GetOpaqueRootInterface.idl
-GlobalInterfaceParent.idl
-IndexedGetterInterface.idl
-InterfaceWithUnsupportedProperties.idl
-NamedConstructorInterface.idl
-NamedGetterInterface.idl
-NamedIndexedGetterInterface.idl
-NestedPutForwardsInterface.idl
-NoConstructorInterface.idl
-NoInterfaceObjectInterface.idl
-NullableTypesTestInterface.idl
-NumericTypesTestInterface.idl
-ObjectTypeBindingsInterface.idl
-OperationsTestInterface.idl
-PutForwardsInterface.idl
-SingleOperationInterface.idl
-StringifierAnonymousOperationInterface.idl
-StringifierAttributeInterface.idl
-StringifierOperationInterface.idl
-StaticPropertiesInterface.idl
-TargetInterface.idl
-UnionTypesInterface.idl
-Window.idl
-UnsupportedInterface.idl
diff --git a/src/cobalt/bindings/testing/global_objects_idl_files_list.tmp b/src/cobalt/bindings/testing/global_objects_idl_files_list.tmp
deleted file mode 100644
index c1c7594..0000000
--- a/src/cobalt/bindings/testing/global_objects_idl_files_list.tmp
+++ /dev/null
@@ -1,44 +0,0 @@
-AnonymousIndexedGetterInterface.idl
-AnonymousNamedGetterInterface.idl
-AnonymousNamedIndexedGetterInterface.idl
-ArbitraryInterface.idl
-BaseInterface.idl
-BooleanTypeTestInterface.idl
-CallbackFunctionInterface.idl
-CallbackInterfaceInterface.idl
-ConditionalInterface.idl
-ConstantsInterface.idl
-ConstructorInterface.idl
-ConstructorWithArgumentsInterface.idl
-DerivedGetterSetterInterface.idl
-DerivedInterface.idl
-DisabledInterface.idl
-DOMStringTestInterface.idl
-EnumerationInterface.idl
-ExceptionObjectInterface.idl
-ExceptionsInterface.idl
-ExtendedIDLAttributesInterface.idl
-GarbageCollectionTestInterface.idl
-GetOpaqueRootInterface.idl
-GlobalInterfaceParent.idl
-IndexedGetterInterface.idl
-InterfaceWithUnsupportedProperties.idl
-NamedConstructorInterface.idl
-NamedGetterInterface.idl
-NamedIndexedGetterInterface.idl
-NestedPutForwardsInterface.idl
-NoConstructorInterface.idl
-NoInterfaceObjectInterface.idl
-NullableTypesTestInterface.idl
-NumericTypesTestInterface.idl
-ObjectTypeBindingsInterface.idl
-OperationsTestInterface.idl
-PutForwardsInterface.idl
-SingleOperationInterface.idl
-StringifierAnonymousOperationInterface.idl
-StringifierAttributeInterface.idl
-StringifierOperationInterface.idl
-StaticPropertiesInterface.idl
-TargetInterface.idl
-UnionTypesInterface.idl
-Window.idl
diff --git a/src/cobalt/bindings/testing/interfaces_info_individual_static_idl_files_list.tmp b/src/cobalt/bindings/testing/interfaces_info_individual_static_idl_files_list.tmp
deleted file mode 100644
index ff5e547..0000000
--- a/src/cobalt/bindings/testing/interfaces_info_individual_static_idl_files_list.tmp
+++ /dev/null
@@ -1,48 +0,0 @@
-AnonymousIndexedGetterInterface.idl
-AnonymousNamedGetterInterface.idl
-AnonymousNamedIndexedGetterInterface.idl
-ArbitraryInterface.idl
-BaseInterface.idl
-BooleanTypeTestInterface.idl
-CallbackFunctionInterface.idl
-CallbackInterfaceInterface.idl
-ConditionalInterface.idl
-ConstantsInterface.idl
-ConstructorInterface.idl
-ConstructorWithArgumentsInterface.idl
-DerivedGetterSetterInterface.idl
-DerivedInterface.idl
-DisabledInterface.idl
-DOMStringTestInterface.idl
-EnumerationInterface.idl
-ExceptionObjectInterface.idl
-ExceptionsInterface.idl
-ExtendedIDLAttributesInterface.idl
-GarbageCollectionTestInterface.idl
-GetOpaqueRootInterface.idl
-GlobalInterfaceParent.idl
-IndexedGetterInterface.idl
-InterfaceWithUnsupportedProperties.idl
-NamedConstructorInterface.idl
-NamedGetterInterface.idl
-NamedIndexedGetterInterface.idl
-NestedPutForwardsInterface.idl
-NoConstructorInterface.idl
-NoInterfaceObjectInterface.idl
-NullableTypesTestInterface.idl
-NumericTypesTestInterface.idl
-ObjectTypeBindingsInterface.idl
-OperationsTestInterface.idl
-PutForwardsInterface.idl
-SingleOperationInterface.idl
-StringifierAnonymousOperationInterface.idl
-StringifierAttributeInterface.idl
-StringifierOperationInterface.idl
-StaticPropertiesInterface.idl
-TargetInterface.idl
-UnionTypesInterface.idl
-Window.idl
-ImplementedInterface.idl
-PartialInterface.idl
-InterfaceWithUnsupportedProperties_partial.idl
-UnsupportedInterface.idl
diff --git a/src/cobalt/bindings/testing/testing.gyp b/src/cobalt/bindings/testing/testing.gyp
index 0286dcd..e9f6492 100644
--- a/src/cobalt/bindings/testing/testing.gyp
+++ b/src/cobalt/bindings/testing/testing.gyp
@@ -129,6 +129,7 @@
         'dependent_interface_test.cc',
         'dom_string_bindings_test.cc',
         'enumeration_bindings_test.cc',
+        'evaluate_script_test.cc',
         'exceptions_bindings_test.cc',
         'extended_attributes_test.cc',
         'garbage_collection_test.cc',
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc
index 27c9f1a..7559d56 100644
--- a/src/cobalt/browser/application.cc
+++ b/src/cobalt/browser/application.cc
@@ -104,7 +104,6 @@
 #endif  // ENABLE_WEBDRIVER
 
 GURL GetInitialURL() {
-#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
   // Allow the user to override the default URL via a command line parameter.
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kInitialURL)) {
@@ -115,7 +114,6 @@
       DLOG(INFO) << "URL from parameter is not valid, using default URL.";
     }
   }
-#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
 
   return GURL(kDefaultURL);
 }
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc
index 692ee5d..73de733 100644
--- a/src/cobalt/browser/browser_module.cc
+++ b/src/cobalt/browser/browser_module.cc
@@ -139,6 +139,9 @@
                       options.network_module_options),
       render_tree_combiner_(renderer_module_.pipeline(),
                             renderer_module_.render_target()->GetSize()),
+#if defined(ENABLE_SCREENSHOT)
+      screen_shot_writer_(new ScreenShotWriter(renderer_module_.pipeline())),
+#endif  // defined(ENABLE_SCREENSHOT)
       web_module_loaded_(true /* manually_reset */,
                          false /* initially_signalled */),
       web_module_recreated_callback_(options.web_module_recreated_callback),
@@ -158,9 +161,6 @@
           kScreenshotCommandShortHelp, kScreenshotCommandLongHelp)),
 #endif  // defined(ENABLE_SCREENSHOT)
 #endif  // defined(ENABLE_DEBUG_CONSOLE)
-#if defined(ENABLE_SCREENSHOT)
-      screen_shot_writer_(new ScreenShotWriter(renderer_module_.pipeline())),
-#endif  // defined(ENABLE_SCREENSHOT)
       ALLOW_THIS_IN_INITIALIZER_LIST(
           h5vcc_url_handler_(this, system_window, account_manager)),
       web_module_options_(options.web_module_options),
@@ -190,7 +190,7 @@
 
 #if defined(ENABLE_DEBUG_CONSOLE)
   debug_console_.reset(new DebugConsole(
-      base::Bind(&BrowserModule::OnDebugConsoleRenderTreeProduced,
+      base::Bind(&BrowserModule::QueueOnDebugConsoleRenderTreeProduced,
                  base::Unretained(this)),
       media_module_.get(), &network_module_,
       renderer_module_.render_target()->GetSize(),
@@ -239,18 +239,19 @@
   }
 
   // Destroy old WebModule first, so we don't get a memory high-watermark after
-  // the second WebModule's construtor runs, but before scoped_ptr::reset() is
+  // the second WebModule's constructor runs, but before scoped_ptr::reset() is
   // run.
   web_module_.reset(NULL);
 
   // Show a splash screen while we're waiting for the web page to load.
   const math::Size& viewport_size = renderer_module_.render_target()->GetSize();
   DestroySplashScreen();
-  splash_screen_.reset(new SplashScreen(
-      base::Bind(&BrowserModule::OnRenderTreeProduced, base::Unretained(this)),
-      &network_module_, viewport_size,
-      renderer_module_.pipeline()->GetResourceProvider(),
-      kLayoutMaxRefreshFrequencyInHz));
+  splash_screen_.reset(
+      new SplashScreen(base::Bind(&BrowserModule::QueueOnRenderTreeProduced,
+                                  base::Unretained(this)),
+                       &network_module_, viewport_size,
+                       renderer_module_.pipeline()->GetResourceProvider(),
+                       kLayoutMaxRefreshFrequencyInHz));
 
   // Create new WebModule.
 #if !defined(COBALT_FORCE_CSP)
@@ -270,9 +271,10 @@
   options.image_cache_capacity_multiplier_when_playing_video =
       COBALT_IMAGE_CACHE_CAPACITY_MULTIPLIER_WHEN_PLAYING_VIDEO;
   web_module_.reset(new WebModule(
-      url,
-      base::Bind(&BrowserModule::OnRenderTreeProduced, base::Unretained(this)),
+      url, base::Bind(&BrowserModule::QueueOnRenderTreeProduced,
+                      base::Unretained(this)),
       base::Bind(&BrowserModule::OnError, base::Unretained(this)),
+      base::Bind(&BrowserModule::OnWindowClose, base::Unretained(this)),
       media_module_.get(), &network_module_, viewport_size,
       renderer_module_.pipeline()->GetResourceProvider(),
       kLayoutMaxRefreshFrequencyInHz, options));
@@ -282,6 +284,14 @@
 }
 
 void BrowserModule::OnLoad() {
+  // Repost to our own message loop if necessary. This also prevents
+  // asynchonrous access to this object by |web_module_| during destruction.
+  if (MessageLoop::current() != self_message_loop_) {
+    self_message_loop_->PostTask(
+        FROM_HERE, base::Bind(&BrowserModule::OnLoad, weak_this_));
+    return;
+  }
+
   DestroySplashScreen();
   web_module_loaded_.Signal();
 }
@@ -303,16 +313,28 @@
 }
 #endif
 
+void BrowserModule::ProcessRenderTreeSubmissionQueue() {
+  TRACE_EVENT0("cobalt::browser",
+               "BrowserModule::ProcessRenderTreeSubmissionQueue()");
+  DCHECK_EQ(MessageLoop::current(), self_message_loop_);
+  render_tree_submission_queue_.ProcessAll();
+}
+
+void BrowserModule::QueueOnRenderTreeProduced(
+    const browser::WebModule::LayoutResults& layout_results) {
+  TRACE_EVENT0("cobalt::browser", "BrowserModule::QueueOnRenderTreeProduced()");
+  render_tree_submission_queue_.AddMessage(
+      base::Bind(&BrowserModule::OnRenderTreeProduced, base::Unretained(this),
+                 layout_results));
+  self_message_loop_->PostTask(
+      FROM_HERE,
+      base::Bind(&BrowserModule::ProcessRenderTreeSubmissionQueue, weak_this_));
+}
+
 void BrowserModule::OnRenderTreeProduced(
     const browser::WebModule::LayoutResults& layout_results) {
   TRACE_EVENT0("cobalt::browser", "BrowserModule::OnRenderTreeProduced()");
-  if (MessageLoop::current() != self_message_loop_) {
-    self_message_loop_->PostTask(
-        FROM_HERE,
-        base::Bind(&BrowserModule::OnRenderTreeProduced, weak_this_,
-                   layout_results));
-    return;
-  }
+  DCHECK_EQ(MessageLoop::current(), self_message_loop_);
 
   renderer::Submission renderer_submission(layout_results.render_tree,
                                            layout_results.layout_time);
@@ -328,6 +350,20 @@
 #endif
 }
 
+void BrowserModule::OnWindowClose() {
+#if defined(ENABLE_DEBUG_CONSOLE)
+  if (input_device_manager_fuzzer_) {
+    return;
+  }
+#endif
+
+#if defined(OS_STARBOARD)
+  SbSystemRequestStop(0);
+#else
+  LOG(WARNING) << "window.close is not supported on this platform.";
+#endif
+}
+
 #if defined(ENABLE_DEBUG_CONSOLE)
 void BrowserModule::OnFuzzerToggle(const std::string& message) {
   if (MessageLoop::current() != self_message_loop_) {
@@ -372,17 +408,23 @@
   }
 }
 
+void BrowserModule::QueueOnDebugConsoleRenderTreeProduced(
+    const browser::WebModule::LayoutResults& layout_results) {
+  TRACE_EVENT0("cobalt::browser",
+               "BrowserModule::QueueOnDebugConsoleRenderTreeProduced()");
+  render_tree_submission_queue_.AddMessage(
+      base::Bind(&BrowserModule::OnDebugConsoleRenderTreeProduced,
+                 base::Unretained(this), layout_results));
+  self_message_loop_->PostTask(
+      FROM_HERE,
+      base::Bind(&BrowserModule::ProcessRenderTreeSubmissionQueue, weak_this_));
+}
+
 void BrowserModule::OnDebugConsoleRenderTreeProduced(
     const browser::WebModule::LayoutResults& layout_results) {
   TRACE_EVENT0("cobalt::browser",
                "BrowserModule::OnDebugConsoleRenderTreeProduced()");
-  if (MessageLoop::current() != self_message_loop_) {
-    self_message_loop_->PostTask(
-        FROM_HERE,
-        base::Bind(&BrowserModule::OnDebugConsoleRenderTreeProduced, weak_this_,
-                   layout_results));
-    return;
-  }
+  DCHECK_EQ(MessageLoop::current(), self_message_loop_);
 
   render_tree_combiner_.UpdateDebugConsoleRenderTree(renderer::Submission(
       layout_results.render_tree, layout_results.layout_time));
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h
index df6da73..d589084 100644
--- a/src/cobalt/browser/browser_module.h
+++ b/src/cobalt/browser/browser_module.h
@@ -17,13 +17,14 @@
 #ifndef COBALT_BROWSER_BROWSER_MODULE_H_
 #define COBALT_BROWSER_BROWSER_MODULE_H_
 
-#include <list>
 #include <string>
+#include <vector>
 
 #include "base/memory/scoped_ptr.h"
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
 #include "cobalt/account/account_manager.h"
+#include "cobalt/base/message_queue.h"
 #include "cobalt/browser/h5vcc_url_handler.h"
 #include "cobalt/browser/render_tree_combiner.h"
 #include "cobalt/browser/screen_shot_writer.h"
@@ -70,7 +71,7 @@
 
   // Type for a collection of URL handler callbacks that can potentially handle
   // a URL before using it to initialize a new WebModule.
-  typedef std::list<URLHandler::URLHandlerCallback> URLHandlerCollection;
+  typedef std::vector<URLHandler::URLHandlerCallback> URLHandlerCollection;
 
   BrowserModule(const GURL& url, system_window::SystemWindow* system_window,
                 account::AccountManager* account_manager,
@@ -126,6 +127,8 @@
 
   // Glue function to deal with the production of the main render tree,
   // and will manage handing it off to the renderer.
+  void QueueOnRenderTreeProduced(
+      const browser::WebModule::LayoutResults& layout_results);
   void OnRenderTreeProduced(
       const browser::WebModule::LayoutResults& layout_results);
 
@@ -163,6 +166,9 @@
   // Destroys the splash screen, if currently displayed.
   void DestroySplashScreen();
 
+  // Called when web module has received window.close.
+  void OnWindowClose();
+
 #if defined(ENABLE_DEBUG_CONSOLE)
   // Toggles the input fuzzer on/off.  Ignores the parameter.
   void OnFuzzerToggle(const std::string&);
@@ -173,6 +179,8 @@
 
   // Glue function to deal with the production of the debug console render tree,
   // and will manage handing it off to the renderer.
+  void QueueOnDebugConsoleRenderTreeProduced(
+      const browser::WebModule::LayoutResults& layout_results);
   void OnDebugConsoleRenderTreeProduced(
       const browser::WebModule::LayoutResults& layout_results);
 #endif  // defined(ENABLE_DEBUG_CONSOLE)
@@ -192,6 +200,9 @@
   void OnRendererSubmissionRasterized();
 #endif  // OS_STARBOARD
 
+  // Process all messages queued into the |render_tree_submission_queue_|.
+  void ProcessRenderTreeSubmissionQueue();
+
   // TODO:
   //     WeakPtr usage here can be avoided if BrowserModule has a thread to
   //     own where it can ensure that its tasks are all resolved when it is
@@ -244,6 +255,18 @@
   // Manages the two render trees, combines and renders them.
   RenderTreeCombiner render_tree_combiner_;
 
+#if defined(ENABLE_SCREENSHOT)
+  // Helper object to create screen shots of the last layout tree.
+  scoped_ptr<ScreenShotWriter> screen_shot_writer_;
+#endif  // defined(ENABLE_SCREENSHOT)
+
+  // Keeps track of all messages containing render tree submissions that will
+  // ultimately reference the |render_tree_combiner_| and the
+  // |renderer_module_|.  It is important that this is destroyed before the
+  // above mentioned references are.  It must however outlive all WebModules
+  // that may be producing render trees.
+  base::MessageQueue render_tree_submission_queue_;
+
   // Sets up everything to do with web page management, from loading and
   // parsing the web page and all referenced files to laying it out.  The
   // web module will ultimately produce a render tree that can be passed
@@ -283,11 +306,6 @@
 #endif  // defined(ENABLE_SCREENSHOT)
 #endif  // defined(ENABLE_DEBUG_CONSOLE)
 
-#if defined(ENABLE_SCREENSHOT)
-  // Helper object to create screen shots of the last layout tree.
-  scoped_ptr<ScreenShotWriter> screen_shot_writer_;
-#endif  // defined(ENABLE_SCREENSHOT)
-
   // Handler object for h5vcc URLs.
   H5vccURLHandler h5vcc_url_handler_;
 
diff --git a/src/cobalt/browser/debug_console.cc b/src/cobalt/browser/debug_console.cc
index a293be3..b02557d 100644
--- a/src/cobalt/browser/debug_console.cc
+++ b/src/cobalt/browser/debug_console.cc
@@ -181,9 +181,10 @@
                  get_debug_server_callback);
   web_module_.reset(new WebModule(
       GURL(kInitialDebugConsoleUrl), render_tree_produced_callback,
-      base::Bind(&DebugConsole::OnError, base::Unretained(this)), media_module,
-      network_module, window_dimensions, resource_provider, layout_refresh_rate,
-      web_module_options));
+      base::Bind(&DebugConsole::OnError, base::Unretained(this)),
+      base::Closure(), /* window_close_callback */
+      media_module, network_module, window_dimensions, resource_provider,
+      layout_refresh_rate, web_module_options));
 }
 
 DebugConsole::~DebugConsole() {}
diff --git a/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp b/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp
deleted file mode 100644
index 7c539ab..0000000
--- a/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp
+++ /dev/null
@@ -1,144 +0,0 @@
-../audio/AudioBuffer.idl
-../audio/AudioBufferSourceNode.idl
-../audio/AudioContext.idl
-../audio/AudioDestinationNode.idl
-../audio/AudioNode.idl
-../cssom/CSSConditionRule.idl
-../cssom/CSSGroupingRule.idl
-../cssom/CSSFontFaceRule.idl
-../cssom/CSSMediaRule.idl
-../cssom/CSSKeyframeRule.idl
-../cssom/CSSKeyframesRule.idl
-../cssom/CSSRule.idl
-../cssom/CSSRuleList.idl
-../cssom/CSSStyleDeclaration.idl
-../cssom/CSSStyleRule.idl
-../cssom/CSSStyleSheet.idl
-../cssom/MediaList.idl
-../cssom/StyleSheet.idl
-../cssom/StyleSheetList.idl
-../debug/DebugHub.idl
-../debug/Debugger.idl
-../debug/DebuggerEventTarget.idl
-../debug/DebugScriptRunner.idl
-../dom/AnimationEvent.idl
-../dom/ArrayBuffer.idl
-../dom/ArrayBufferView.idl
-../dom/Attr.idl
-../dom/Blob.idl
-../dom/CDATASection.idl
-../dom/CharacterData.idl
-../dom/Comment.idl
-../dom/Console.idl
-../dom/Crypto.idl
-../dom/DataView.idl
-../dom/Document.idl
-../dom/DocumentTimeline.idl
-../dom/DocumentType.idl
-../dom/DOMException.idl
-../dom/DOMImplementation.idl
-../dom/DOMParser.idl
-../dom/DOMRect.idl
-../dom/DOMRectList.idl
-../dom/DOMRectReadOnly.idl
-../dom/DOMStringMap.idl
-../dom/DOMTokenList.idl
-../dom/Element.idl
-../dom/Event.idl
-../dom/EventListener.idl
-../dom/EventTarget.idl
-../dom/Float32Array.idl
-../dom/Float64Array.idl
-../dom/FocusEvent.idl
-../dom/History.idl
-../dom/HTMLAnchorElement.idl
-../dom/HTMLBodyElement.idl
-../dom/HTMLBRElement.idl
-../dom/HTMLCollection.idl
-../dom/HTMLDivElement.idl
-../dom/HTMLElement.idl
-../dom/HTMLHeadElement.idl
-../dom/HTMLHeadingElement.idl
-../dom/HTMLHtmlElement.idl
-../dom/HTMLImageElement.idl
-../dom/HTMLLinkElement.idl
-../dom/HTMLMediaElement.idl
-../dom/HTMLMetaElement.idl
-../dom/HTMLParagraphElement.idl
-../dom/HTMLScriptElement.idl
-../dom/HTMLSpanElement.idl
-../dom/HTMLStyleElement.idl
-../dom/HTMLTitleElement.idl
-../dom/HTMLUnknownElement.idl
-../dom/HTMLVideoElement.idl
-../dom/KeyboardEvent.idl
-../dom/Location.idl
-../dom/MediaError.idl
-../dom/MediaKeyCompleteEvent.idl
-../dom/MediaKeyError.idl
-../dom/MediaKeyErrorEvent.idl
-../dom/MediaKeyMessageEvent.idl
-../dom/MediaKeyNeededEvent.idl
-../dom/MediaQueryList.idl
-../dom/MediaSource.idl
-../dom/MimeTypeArray.idl
-../dom/NamedNodeMap.idl
-../dom/Navigator.idl
-../dom/Node.idl
-../dom/NodeList.idl
-../dom/Performance.idl
-../dom/PerformanceTiming.idl
-../dom/PluginArray.idl
-../dom/ProgressEvent.idl
-../dom/Screen.idl
-../dom/SecurityPolicyViolationEvent.idl
-../dom/SourceBuffer.idl
-../dom/SourceBufferList.idl
-../dom/Storage.idl
-../dom/StorageEvent.idl
-../dom/TestRunner.idl
-../dom/Text.idl
-../dom/TimeRanges.idl
-../dom/TransitionEvent.idl
-../dom/UIEvent.idl
-../dom/Uint16Array.idl
-../dom/Uint32Array.idl
-../dom/Uint8Array.idl
-../dom/URL.idl
-../dom/VideoPlaybackQuality.idl
-../dom/Window.idl
-../dom/XMLDocument.idl
-../dom/XMLSerializer.idl
-../h5vcc/dial/DialHttpRequest.idl
-../h5vcc/dial/DialHttpResponse.idl
-../h5vcc/dial/DialServer.idl
-../h5vcc/H5vcc.idl
-../h5vcc/H5vccAccountInfo.idl
-../h5vcc/H5vccAccountManager.idl
-../h5vcc/H5vccAudioConfig.idl
-../h5vcc/H5vccAudioConfigArray.idl
-../h5vcc/H5vccCVal.idl
-../h5vcc/H5vccCValKeyList.idl
-../h5vcc/H5vccDeepLinkEventTarget.idl
-../h5vcc/H5vccRuntime.idl
-../h5vcc/H5vccRuntimeEventTarget.idl
-../h5vcc/H5vccSettings.idl
-../h5vcc/H5vccStorage.idl
-../h5vcc/H5vccSystem.idl
-../speech/SpeechRecognition.idl
-../speech/SpeechRecognitionAlternative.idl
-../speech/SpeechRecognitionError.idl
-../speech/SpeechRecognitionEvent.idl
-../speech/SpeechRecognitionResult.idl
-../speech/SpeechRecognitionResultList.idl
-../web_animations/Animatable.idl
-../web_animations/Animation.idl
-../web_animations/AnimationEffectReadOnly.idl
-../web_animations/AnimationEffectTimingReadOnly.idl
-../web_animations/AnimationTimeline.idl
-../web_animations/Keyframe.idl
-../web_animations/KeyframeEffectReadOnly.idl
-../webdriver/ScriptExecutor.idl
-../xhr/XMLHttpRequest.idl
-../xhr/XMLHttpRequestEventTarget.idl
-../xhr/XMLHttpRequestUpload.idl
diff --git a/src/cobalt/browser/global_objects_idl_files_list.tmp b/src/cobalt/browser/global_objects_idl_files_list.tmp
deleted file mode 100644
index 7c539ab..0000000
--- a/src/cobalt/browser/global_objects_idl_files_list.tmp
+++ /dev/null
@@ -1,144 +0,0 @@
-../audio/AudioBuffer.idl
-../audio/AudioBufferSourceNode.idl
-../audio/AudioContext.idl
-../audio/AudioDestinationNode.idl
-../audio/AudioNode.idl
-../cssom/CSSConditionRule.idl
-../cssom/CSSGroupingRule.idl
-../cssom/CSSFontFaceRule.idl
-../cssom/CSSMediaRule.idl
-../cssom/CSSKeyframeRule.idl
-../cssom/CSSKeyframesRule.idl
-../cssom/CSSRule.idl
-../cssom/CSSRuleList.idl
-../cssom/CSSStyleDeclaration.idl
-../cssom/CSSStyleRule.idl
-../cssom/CSSStyleSheet.idl
-../cssom/MediaList.idl
-../cssom/StyleSheet.idl
-../cssom/StyleSheetList.idl
-../debug/DebugHub.idl
-../debug/Debugger.idl
-../debug/DebuggerEventTarget.idl
-../debug/DebugScriptRunner.idl
-../dom/AnimationEvent.idl
-../dom/ArrayBuffer.idl
-../dom/ArrayBufferView.idl
-../dom/Attr.idl
-../dom/Blob.idl
-../dom/CDATASection.idl
-../dom/CharacterData.idl
-../dom/Comment.idl
-../dom/Console.idl
-../dom/Crypto.idl
-../dom/DataView.idl
-../dom/Document.idl
-../dom/DocumentTimeline.idl
-../dom/DocumentType.idl
-../dom/DOMException.idl
-../dom/DOMImplementation.idl
-../dom/DOMParser.idl
-../dom/DOMRect.idl
-../dom/DOMRectList.idl
-../dom/DOMRectReadOnly.idl
-../dom/DOMStringMap.idl
-../dom/DOMTokenList.idl
-../dom/Element.idl
-../dom/Event.idl
-../dom/EventListener.idl
-../dom/EventTarget.idl
-../dom/Float32Array.idl
-../dom/Float64Array.idl
-../dom/FocusEvent.idl
-../dom/History.idl
-../dom/HTMLAnchorElement.idl
-../dom/HTMLBodyElement.idl
-../dom/HTMLBRElement.idl
-../dom/HTMLCollection.idl
-../dom/HTMLDivElement.idl
-../dom/HTMLElement.idl
-../dom/HTMLHeadElement.idl
-../dom/HTMLHeadingElement.idl
-../dom/HTMLHtmlElement.idl
-../dom/HTMLImageElement.idl
-../dom/HTMLLinkElement.idl
-../dom/HTMLMediaElement.idl
-../dom/HTMLMetaElement.idl
-../dom/HTMLParagraphElement.idl
-../dom/HTMLScriptElement.idl
-../dom/HTMLSpanElement.idl
-../dom/HTMLStyleElement.idl
-../dom/HTMLTitleElement.idl
-../dom/HTMLUnknownElement.idl
-../dom/HTMLVideoElement.idl
-../dom/KeyboardEvent.idl
-../dom/Location.idl
-../dom/MediaError.idl
-../dom/MediaKeyCompleteEvent.idl
-../dom/MediaKeyError.idl
-../dom/MediaKeyErrorEvent.idl
-../dom/MediaKeyMessageEvent.idl
-../dom/MediaKeyNeededEvent.idl
-../dom/MediaQueryList.idl
-../dom/MediaSource.idl
-../dom/MimeTypeArray.idl
-../dom/NamedNodeMap.idl
-../dom/Navigator.idl
-../dom/Node.idl
-../dom/NodeList.idl
-../dom/Performance.idl
-../dom/PerformanceTiming.idl
-../dom/PluginArray.idl
-../dom/ProgressEvent.idl
-../dom/Screen.idl
-../dom/SecurityPolicyViolationEvent.idl
-../dom/SourceBuffer.idl
-../dom/SourceBufferList.idl
-../dom/Storage.idl
-../dom/StorageEvent.idl
-../dom/TestRunner.idl
-../dom/Text.idl
-../dom/TimeRanges.idl
-../dom/TransitionEvent.idl
-../dom/UIEvent.idl
-../dom/Uint16Array.idl
-../dom/Uint32Array.idl
-../dom/Uint8Array.idl
-../dom/URL.idl
-../dom/VideoPlaybackQuality.idl
-../dom/Window.idl
-../dom/XMLDocument.idl
-../dom/XMLSerializer.idl
-../h5vcc/dial/DialHttpRequest.idl
-../h5vcc/dial/DialHttpResponse.idl
-../h5vcc/dial/DialServer.idl
-../h5vcc/H5vcc.idl
-../h5vcc/H5vccAccountInfo.idl
-../h5vcc/H5vccAccountManager.idl
-../h5vcc/H5vccAudioConfig.idl
-../h5vcc/H5vccAudioConfigArray.idl
-../h5vcc/H5vccCVal.idl
-../h5vcc/H5vccCValKeyList.idl
-../h5vcc/H5vccDeepLinkEventTarget.idl
-../h5vcc/H5vccRuntime.idl
-../h5vcc/H5vccRuntimeEventTarget.idl
-../h5vcc/H5vccSettings.idl
-../h5vcc/H5vccStorage.idl
-../h5vcc/H5vccSystem.idl
-../speech/SpeechRecognition.idl
-../speech/SpeechRecognitionAlternative.idl
-../speech/SpeechRecognitionError.idl
-../speech/SpeechRecognitionEvent.idl
-../speech/SpeechRecognitionResult.idl
-../speech/SpeechRecognitionResultList.idl
-../web_animations/Animatable.idl
-../web_animations/Animation.idl
-../web_animations/AnimationEffectReadOnly.idl
-../web_animations/AnimationEffectTimingReadOnly.idl
-../web_animations/AnimationTimeline.idl
-../web_animations/Keyframe.idl
-../web_animations/KeyframeEffectReadOnly.idl
-../webdriver/ScriptExecutor.idl
-../xhr/XMLHttpRequest.idl
-../xhr/XMLHttpRequestEventTarget.idl
-../xhr/XMLHttpRequestUpload.idl
diff --git a/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp b/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp
deleted file mode 100644
index 216f4b4..0000000
--- a/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp
+++ /dev/null
@@ -1,171 +0,0 @@
-../audio/AudioBuffer.idl
-../audio/AudioBufferSourceNode.idl
-../audio/AudioContext.idl
-../audio/AudioDestinationNode.idl
-../audio/AudioNode.idl
-../cssom/CSSConditionRule.idl
-../cssom/CSSGroupingRule.idl
-../cssom/CSSFontFaceRule.idl
-../cssom/CSSMediaRule.idl
-../cssom/CSSKeyframeRule.idl
-../cssom/CSSKeyframesRule.idl
-../cssom/CSSRule.idl
-../cssom/CSSRuleList.idl
-../cssom/CSSStyleDeclaration.idl
-../cssom/CSSStyleRule.idl
-../cssom/CSSStyleSheet.idl
-../cssom/MediaList.idl
-../cssom/StyleSheet.idl
-../cssom/StyleSheetList.idl
-../debug/DebugHub.idl
-../debug/Debugger.idl
-../debug/DebuggerEventTarget.idl
-../debug/DebugScriptRunner.idl
-../dom/AnimationEvent.idl
-../dom/ArrayBuffer.idl
-../dom/ArrayBufferView.idl
-../dom/Attr.idl
-../dom/Blob.idl
-../dom/CDATASection.idl
-../dom/CharacterData.idl
-../dom/Comment.idl
-../dom/Console.idl
-../dom/Crypto.idl
-../dom/DataView.idl
-../dom/Document.idl
-../dom/DocumentTimeline.idl
-../dom/DocumentType.idl
-../dom/DOMException.idl
-../dom/DOMImplementation.idl
-../dom/DOMParser.idl
-../dom/DOMRect.idl
-../dom/DOMRectList.idl
-../dom/DOMRectReadOnly.idl
-../dom/DOMStringMap.idl
-../dom/DOMTokenList.idl
-../dom/Element.idl
-../dom/Event.idl
-../dom/EventListener.idl
-../dom/EventTarget.idl
-../dom/Float32Array.idl
-../dom/Float64Array.idl
-../dom/FocusEvent.idl
-../dom/History.idl
-../dom/HTMLAnchorElement.idl
-../dom/HTMLBodyElement.idl
-../dom/HTMLBRElement.idl
-../dom/HTMLCollection.idl
-../dom/HTMLDivElement.idl
-../dom/HTMLElement.idl
-../dom/HTMLHeadElement.idl
-../dom/HTMLHeadingElement.idl
-../dom/HTMLHtmlElement.idl
-../dom/HTMLImageElement.idl
-../dom/HTMLLinkElement.idl
-../dom/HTMLMediaElement.idl
-../dom/HTMLMetaElement.idl
-../dom/HTMLParagraphElement.idl
-../dom/HTMLScriptElement.idl
-../dom/HTMLSpanElement.idl
-../dom/HTMLStyleElement.idl
-../dom/HTMLTitleElement.idl
-../dom/HTMLUnknownElement.idl
-../dom/HTMLVideoElement.idl
-../dom/KeyboardEvent.idl
-../dom/Location.idl
-../dom/MediaError.idl
-../dom/MediaKeyCompleteEvent.idl
-../dom/MediaKeyError.idl
-../dom/MediaKeyErrorEvent.idl
-../dom/MediaKeyMessageEvent.idl
-../dom/MediaKeyNeededEvent.idl
-../dom/MediaQueryList.idl
-../dom/MediaSource.idl
-../dom/MimeTypeArray.idl
-../dom/NamedNodeMap.idl
-../dom/Navigator.idl
-../dom/Node.idl
-../dom/NodeList.idl
-../dom/Performance.idl
-../dom/PerformanceTiming.idl
-../dom/PluginArray.idl
-../dom/ProgressEvent.idl
-../dom/Screen.idl
-../dom/SecurityPolicyViolationEvent.idl
-../dom/SourceBuffer.idl
-../dom/SourceBufferList.idl
-../dom/Storage.idl
-../dom/StorageEvent.idl
-../dom/TestRunner.idl
-../dom/Text.idl
-../dom/TimeRanges.idl
-../dom/TransitionEvent.idl
-../dom/UIEvent.idl
-../dom/Uint16Array.idl
-../dom/Uint32Array.idl
-../dom/Uint8Array.idl
-../dom/URL.idl
-../dom/VideoPlaybackQuality.idl
-../dom/Window.idl
-../dom/XMLDocument.idl
-../dom/XMLSerializer.idl
-../h5vcc/dial/DialHttpRequest.idl
-../h5vcc/dial/DialHttpResponse.idl
-../h5vcc/dial/DialServer.idl
-../h5vcc/H5vcc.idl
-../h5vcc/H5vccAccountInfo.idl
-../h5vcc/H5vccAccountManager.idl
-../h5vcc/H5vccAudioConfig.idl
-../h5vcc/H5vccAudioConfigArray.idl
-../h5vcc/H5vccCVal.idl
-../h5vcc/H5vccCValKeyList.idl
-../h5vcc/H5vccDeepLinkEventTarget.idl
-../h5vcc/H5vccRuntime.idl
-../h5vcc/H5vccRuntimeEventTarget.idl
-../h5vcc/H5vccSettings.idl
-../h5vcc/H5vccStorage.idl
-../h5vcc/H5vccSystem.idl
-../speech/SpeechRecognition.idl
-../speech/SpeechRecognitionAlternative.idl
-../speech/SpeechRecognitionError.idl
-../speech/SpeechRecognitionEvent.idl
-../speech/SpeechRecognitionResult.idl
-../speech/SpeechRecognitionResultList.idl
-../web_animations/Animatable.idl
-../web_animations/Animation.idl
-../web_animations/AnimationEffectReadOnly.idl
-../web_animations/AnimationEffectTimingReadOnly.idl
-../web_animations/AnimationTimeline.idl
-../web_animations/Keyframe.idl
-../web_animations/KeyframeEffectReadOnly.idl
-../webdriver/ScriptExecutor.idl
-../xhr/XMLHttpRequest.idl
-../xhr/XMLHttpRequestEventTarget.idl
-../xhr/XMLHttpRequestUpload.idl
-../cssom/LinkStyle.idl
-../dom/Document_CSSOM.idl
-../dom/Document_HTML5.idl
-../dom/Document_WebAnimationsAPI.idl
-../dom/Element_CSSOMView.idl
-../dom/Element_DOMParsingAndSerialization.idl
-../dom/ElementCSSInlineStyle.idl
-../dom/GlobalCrypto.idl
-../dom/GlobalEventHandlers.idl
-../dom/HTMLElement_CSSOMView.idl
-../dom/NavigatorID.idl
-../dom/NavigatorLanguage.idl
-../dom/NavigatorPlugins.idl
-../dom/NavigatorStorageUtils.idl
-../dom/NonDocumentTypeChildNode.idl
-../dom/NonElementParentNode.idl
-../dom/ParentNode.idl
-../dom/Performance_HighResolutionTime.idl
-../dom/URLUtils.idl
-../dom/Window_AnimationTiming.idl
-../dom/Window_CSSOM.idl
-../dom/Window_CSSOMView.idl
-../dom/Window_Performance.idl
-../dom/WindowEventHandlers.idl
-../dom/WindowLocalStorage.idl
-../dom/WindowSessionStorage.idl
-../dom/WindowTimers.idl
diff --git a/src/cobalt/browser/splash_screen.cc b/src/cobalt/browser/splash_screen.cc
index 85e55bd..804b92d 100644
--- a/src/cobalt/browser/splash_screen.cc
+++ b/src/cobalt/browser/splash_screen.cc
@@ -37,6 +37,7 @@
   web_module_.reset(new WebModule(
       options.url, render_tree_produced_callback,
       base::Bind(&SplashScreen::OnError, base::Unretained(this)),
+      base::Closure(), /* window_close_callback */
       &stub_media_module_, network_module, window_dimensions, resource_provider,
       layout_refresh_rate, web_module_options));
 }
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc
index b6a41c1..a402253 100644
--- a/src/cobalt/browser/switches.cc
+++ b/src/cobalt/browser/switches.cc
@@ -48,10 +48,6 @@
 // Setting this switch causes all certificate errors to be ignored.
 const char kIgnoreCertificateErrors[] = "ignore_certificate_errors";
 
-// Setting this switch defines the startup URL that Cobalt will use.  If no
-// value is set, a default URL will be used.
-const char kInitialURL[] = "url";
-
 // If this flag is set, input will be continuously generated randomly instead of
 // taken from an external input device (like a controller).
 const char kInputFuzzer[] = "input_fuzzer";
@@ -105,6 +101,10 @@
 // ideally) these images are cached within GPU memory.
 const char kImageCacheSizeInBytes[] = "image_cache_size_in_bytes";
 
+// Setting this switch defines the startup URL that Cobalt will use.  If no
+// value is set, a default URL will be used.
+const char kInitialURL[] = "url";
+
 // Determines the capacity of the remote typefaces cache which manages all
 // typefaces downloaded from a web page.
 const char kRemoteTypefaceCacheSizeInBytes[] =
diff --git a/src/cobalt/browser/switches.h b/src/cobalt/browser/switches.h
index 3531931..7d463d0 100644
--- a/src/cobalt/browser/switches.h
+++ b/src/cobalt/browser/switches.h
@@ -30,7 +30,6 @@
 extern const char kEnableWebDriver[];
 extern const char kExtraWebFileDir[];
 extern const char kIgnoreCertificateErrors[];
-extern const char kInitialURL[];
 extern const char kInputFuzzer[];
 extern const char kNullAudioStreamer[];
 extern const char kNullSavegame[];
@@ -46,6 +45,7 @@
 #endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
 
 extern const char kImageCacheSizeInBytes[];
+extern const char kInitialURL[];
 extern const char kRemoteTypefaceCacheSizeInBytes[];
 extern const char kScratchSurfaceCacheSizeInBytes[];
 extern const char kSkiaCacheSizeInBytes[];
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc
index b80a9bd..7932196 100644
--- a/src/cobalt/browser/web_module.cc
+++ b/src/cobalt/browser/web_module.cc
@@ -23,7 +23,6 @@
 #include "base/message_loop_proxy.h"
 #include "base/optional.h"
 #include "base/stringprintf.h"
-#include "cobalt/base/address_sanitizer.h"
 #include "cobalt/base/tokens.h"
 #include "cobalt/browser/switches.h"
 #include "cobalt/browser/web_module_stat_tracker.h"
@@ -321,7 +320,7 @@
       data.network_module->cookie_jar(), data.network_module->GetPostSender(),
       data.options.location_policy, data.options.csp_enforcement_mode,
       base::Bind(&WebModule::Impl::OnCspPolicyChanged, base::Unretained(this)),
-      data.options.csp_insecure_allowed_token);
+      data.window_close_callback, data.options.csp_insecure_allowed_token);
   DCHECK(window_);
 
   window_weak_ = base::AsWeakPtr(window_.get());
@@ -556,28 +555,22 @@
 WebModule::WebModule(
     const GURL& initial_url,
     const OnRenderTreeProducedCallback& render_tree_produced_callback,
-    const OnErrorCallback& error_callback, media::MediaModule* media_module,
-    network::NetworkModule* network_module, const math::Size& window_dimensions,
+    const OnErrorCallback& error_callback,
+    const base::Closure& window_close_callback,
+    media::MediaModule* media_module, network::NetworkModule* network_module,
+    const math::Size& window_dimensions,
     render_tree::ResourceProvider* resource_provider, float layout_refresh_rate,
     const Options& options)
     : thread_(options.name.c_str()) {
   ConstructionData construction_data(
-      initial_url, render_tree_produced_callback, error_callback, media_module,
-      network_module, window_dimensions, resource_provider, kDOMMaxElementDepth,
-      layout_refresh_rate, options);
-
-#if defined(COBALT_BUILD_TYPE_DEBUG)
-  // Non-optimized builds require a bigger stack size.
-  const size_t kBaseStackSize = 2 * 1024 * 1024;
-#else
-  const size_t kBaseStackSize = 256 * 1024;
-#endif
+      initial_url, render_tree_produced_callback, error_callback,
+      window_close_callback, media_module, network_module, window_dimensions,
+      resource_provider, kDOMMaxElementDepth, layout_refresh_rate, options);
 
   // Start the dedicated thread and create the internal implementation
   // object on that thread.
-  size_t stack_size = kBaseStackSize + base::kAsanAdditionalStackSize;
   thread_.StartWithOptions(
-      base::Thread::Options(MessageLoop::TYPE_DEFAULT, stack_size));
+      base::Thread::Options(MessageLoop::TYPE_DEFAULT, kWebModuleStackSize));
   DCHECK(message_loop());
 
   message_loop()->PostTask(
diff --git a/src/cobalt/browser/web_module.h b/src/cobalt/browser/web_module.h
index a4742cb..55706e7 100644
--- a/src/cobalt/browser/web_module.h
+++ b/src/cobalt/browser/web_module.h
@@ -27,6 +27,7 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_checker.h"
+#include "cobalt/base/address_sanitizer.h"
 #include "cobalt/base/console_commands.h"
 #include "cobalt/base/source_location.h"
 #include "cobalt/css_parser/parser.h"
@@ -150,6 +151,7 @@
   WebModule(const GURL& initial_url,
             const OnRenderTreeProducedCallback& render_tree_produced_callback,
             const OnErrorCallback& error_callback,
+            const base::Closure& window_close_callback,
             media::MediaModule* media_module,
             network::NetworkModule* network_module,
             const math::Size& window_dimensions,
@@ -180,6 +182,15 @@
   debug::DebugServer* GetDebugServer();
 #endif  // ENABLE_DEBUG_CONSOLE
 
+#if defined(COBALT_BUILD_TYPE_DEBUG)
+  // Non-optimized builds require a bigger stack size.
+  static const size_t kBaseStackSize = 2 * 1024 * 1024;
+#else
+  static const size_t kBaseStackSize = 256 * 1024;
+#endif
+  static const size_t kWebModuleStackSize =
+      kBaseStackSize + base::kAsanAdditionalStackSize;
+
  private:
   // Data required to construct a WebModule, initialized in the constructor and
   // passed to |Initialize|.
@@ -187,7 +198,9 @@
     ConstructionData(
         const GURL& initial_url,
         const OnRenderTreeProducedCallback& render_tree_produced_callback,
-        const OnErrorCallback& error_callback, media::MediaModule* media_module,
+        const OnErrorCallback& error_callback,
+        const base::Closure& window_close_callback,
+        media::MediaModule* media_module,
         network::NetworkModule* network_module,
         const math::Size& window_dimensions,
         render_tree::ResourceProvider* resource_provider,
@@ -196,6 +209,7 @@
         : initial_url(initial_url),
           render_tree_produced_callback(render_tree_produced_callback),
           error_callback(error_callback),
+          window_close_callback(window_close_callback),
           media_module(media_module),
           network_module(network_module),
           window_dimensions(window_dimensions),
@@ -207,6 +221,7 @@
     GURL initial_url;
     OnRenderTreeProducedCallback render_tree_produced_callback;
     OnErrorCallback error_callback;
+    const base::Closure& window_close_callback;
     media::MediaModule* media_module;
     network::NetworkModule* network_module;
     math::Size window_dimensions;
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index f895aef..deb3c7d 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-11333
\ No newline at end of file
+11565
\ No newline at end of file
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi
index 3e07aab..7170bcb 100644
--- a/src/cobalt/build/config/base.gypi
+++ b/src/cobalt/build/config/base.gypi
@@ -28,6 +28,12 @@
     # Contains the current build configuration.
     'cobalt_config%': 'gold',
     'cobalt_fastbuild%': 0,
+
+    # Contains the current font package selection.  This can be used to trade
+    # font quality, coverage, and latency with smaller font package size.
+    # See content/fonts/README.md for more details.
+    'cobalt_font_package%': 'unlimited',
+
     # Build version number.
     'cobalt_version%': 0,
     # Contains the name of the hosting OS. The value is defined by gyp_cobalt.
diff --git a/src/cobalt/content/fonts/10megabytes/fonts.xml b/src/cobalt/content/fonts/10megabytes/fonts.xml
new file mode 100644
index 0000000..c0ffb0a
--- /dev/null
+++ b/src/cobalt/content/fonts/10megabytes/fonts.xml
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    NOTE: Families with a "fallback" value of "true" are added to the fallback
+    list, regardless of whether or not they are named. Fallback fonts are chosen
+    based on a match: full BCP-47 language tag including script, then just
+    language, and finally order (the first font containing the glyph). Order of
+    appearance is also the tiebreaker for weight matching.
+
+    The pages attribute indicates which character pages are contained within
+    the font. It is used with character fallback to allow the system to quickly
+    determine that a character cannot appear in a font without requiring the
+    full character map to be loaded into memory. Character pages are zero
+    indexed, and each page contains 256 characters, so character 1000 would be
+    contained within page 3.
+-->
+<familyset version="1">
+    <!-- first font is default -->
+    <family name="sans-serif">
+        <font weight="400" style="normal">Roboto-Regular.ttf</font>
+    </family>
+    <!-- Note that aliases must come after the fonts they reference. -->
+    <alias name="arial" to="sans-serif" />
+    <alias name="helvetica" to="sans-serif" />
+    <alias name="roboto" to="sans-serif" />
+    <alias name="tahoma" to="sans-serif" />
+    <alias name="verdana" to="sans-serif" />
+    <alias name="courier" to="serif-monospace" />
+    <alias name="courier new" to="serif-monospace" />
+    <family name="sans-serif-smallcaps">
+        <font weight="400" style="normal">CarroisGothicSC-Regular.ttf</font>
+    </family>
+    <!-- fallback fonts -->
+    <family name="Noto Naskh Arabic UI" fallback="true" pages="0,6-8,32,37,46,251-254">
+        <font weight="400" style="normal">NotoNaskhArabicUI-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,18-19,45,171,254">
+        <font weight="400" style="normal">NotoSansEthiopic-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,5,32,37,251,254">
+        <font weight="400" style="normal">NotoSansHebrew-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,2-3,14,32,37,254">
+        <font weight="400" style="normal">NotoSansThaiUI-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,5,251,254">
+        <font weight="400" style="normal">NotoSansArmenian-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,5,16,45,254">
+        <font weight="400" style="normal">NotoSansGeorgian-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,2,9,28,32,34,37,168,254">
+        <font weight="400" style="normal">NotoSansDevanagariUI-Regular.ttf</font>
+    </family>
+    <!-- Gujarati should come after Devanagari -->
+    <family fallback="true" pages="0,9-10,32,34,37,168,254">
+        <font weight="400" style="normal">NotoSansGujaratiUI-Regular.ttf</font>
+    </family>
+    <!-- Gurmukhi should come after Devanagari -->
+    <family fallback="true" pages="0,9-10,32,34,37-38,168,254">
+        <font weight="400" style="normal">NotoSansGurmukhiUI-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,9,11,32,34,37,254">
+        <font weight="400" style="normal">NotoSansTamilUI-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,3,9,13,32,34,37,254">
+        <font weight="400" style="normal">NotoSansMalayalamUI-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,9,32,34,37,254">
+        <font weight="400" style="normal">NotoSansBengaliUI-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,9,12,32,34,37,254">
+        <font weight="400" style="normal">NotoSansTeluguUI-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,9,12,32,34,37,254">
+        <font weight="400" style="normal">NotoSansKannadaUI-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,9,11,32,34,37,254">
+        <font weight="400" style="normal">NotoSansOriyaUI-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,9,13,32,34,37,254">
+        <font weight="400" style="normal">NotoSansSinhala-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,23,25,32,37">
+        <font weight="400" style="normal">NotoSansKhmerUI-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,3,14,32,37">
+        <font weight="400" style="normal">NotoSansLaoUI-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,6-7,32,37,253-254">
+        <font weight="400" style="normal">NotoSansThaana-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,3,170">
+        <font weight="400" style="normal">NotoSansCham-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,27,32,37,254">
+        <font weight="400" style="normal">NotoSansBalinese-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,166,254,360-362">
+        <font weight="400" style="normal">NotoSansBamum-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,27,254">
+        <font weight="400" style="normal">NotoSansBatak-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,26,32,169,254">
+        <font weight="400" style="normal">NotoSansBuginese-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,23,254">
+        <font weight="400" style="normal">NotoSansBuhid-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0-3,20-22,24,254">
+        <font weight="400" style="normal">NotoSansCanadianAboriginal-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,19,254">
+        <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0-3,29,44,254">
+        <font weight="400" style="normal">NotoSansCoptic-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,44,254">
+        <font weight="400" style="normal">NotoSansGlagolitic-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,23,254">
+        <font weight="400" style="normal">NotoSansHanunoo-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,32,37,169,254">
+        <font weight="400" style="normal">NotoSansJavanese-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,169,254">
+        <font weight="400" style="normal">NotoSansKayahLi-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,28,37,254">
+        <font weight="400" style="normal">NotoSansLepcha-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,9,25,254">
+        <font weight="400" style="normal">NotoSansLimbu-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,2,164,254">
+        <font weight="400" style="normal">NotoSansLisu-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,6,8,254">
+        <font weight="400" style="normal">NotoSansMandaic-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,170-171,254">
+        <font weight="400" style="normal">NotoSansMeeteiMayek-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,25,254">
+        <font weight="400" style="normal">NotoSansNewTaiLue-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,6-7,32,46,253-254">
+        <font weight="400" style="normal">NotoSansNKo-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,28,254">
+        <font weight="400" style="normal">NotoSansOlChiki-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,169,254">
+        <font weight="400" style="normal">NotoSansRejang-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,32,37,168,254">
+        <font weight="400" style="normal">NotoSansSaurashtra-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,27-28,254">
+        <font weight="400" style="normal">NotoSansSundanese-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,9,32,37,168,254">
+        <font weight="400" style="normal">NotoSansSylotiNagri-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,3,6-7,32,34,37-38,254">
+        <font weight="400" style="normal">NotoSansSyriacEstrangela-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,23,254">
+        <font weight="400" style="normal">NotoSansTagbanwa-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,26,32,34,37,254">
+        <font weight="400" style="normal">NotoSansTaiTham-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,32,37,167,170,254">
+        <font weight="400" style="normal">NotoSansTaiViet-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,15,32,37,254">
+        <font weight="400" style="normal">NotoSansTibetan-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,3,32,45,254">
+        <font weight="400" style="normal">NotoSansTifinagh-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,165-166,254">
+        <font weight="400" style="normal">NotoSansVai-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,160-164,254">
+        <font weight="400" style="normal">NotoSansYi-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="32-43">
+        <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
+    </family>
+    <family fallback="true" lang="ja" pages="0,32,34-35,46-159,249-250,254-255,498,512-523,525-527,530-538,540-543,545-547,550,552,554-559,561,563-568,570,572-573,575-579,582-584,586-594,596-608,610-612,614-618,620,622-625,627-628,630-631,633-638,640,642-646,649-655,658,660-664,666,669-678,681,695-696,760-761">
+        <font weight="400" style="normal">NotoSansJP-Regular.otf</font>
+    </family>
+    <family fallback="true" pages="0,32-33,35-39,41,43,48,50,224,254-255,496-502,4068">
+        <font weight="400" style="normal">NotoEmoji-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,14,17,32,48-51,77-159,172-215,249-250,254-255,260">
+        <font weight="400" style="normal">DroidSansFallback.ttf</font>
+    </family>
+    <!--
+        Tai Le and Mongolian are intentionally kept last, to make sure they don't override
+        the East Asian punctuation for Chinese.
+    -->
+    <family fallback="true" pages="0,16,25,48,254">
+        <font weight="400" style="normal">NotoSansTaiLe-Regular.ttf</font>
+    </family>
+    <family fallback="true" pages="0,24,32,36-37,48,254">
+        <font weight="400" style="normal">NotoSansMongolian-Regular.ttf</font>
+    </family>
+</familyset>
diff --git a/src/cobalt/content/fonts/README.md b/src/cobalt/content/fonts/README.md
index acee96c..5305139 100644
--- a/src/cobalt/content/fonts/README.md
+++ b/src/cobalt/content/fonts/README.md
@@ -1,29 +1,32 @@
-# Generating a minimal font for devices with small space requirements
+## Description
 
-[GlyphIGo](https://github.com/pettarin/glyphIgo) was used to generate a subset
-of the Roboto font
+This directory contains a few different set of font packages one can select
+to be packaged with cobalt.
 
-`cobalt/content/fonts` contains a script called `create_minimized_roboto.sh`
-that can help recreate minimized font if needed
+## How to use
 
-Steps:
+To use this:
 
-1.  `cd src/cobalt/content/fonts`
-1.  `./create_minimized_roboto.sh`
-1.  Download `fontforge` using apt.  `sudo apt install fontforge`
-1.  In `fontforge`, navigate the menu: `Encoding`->`Reencode`->`Glyph Order`.
-Scroll to the top, find the first glyph.  By spec, this glyph is called
-`.notdef`, and is used when this font is the default font and there glyph for a
-character we're looking for is missing in the file.  Often this will be blank
-after the last step, which can be undesired.
-1.  Copy `.notdef` glyph from a different font.
-    1.  Open a different font.
-    1.  Find the `.notdef` glyph.
-    1.  Select the glyph without opening it.
-    1.  Navigate the menu: `Edit`->`Copy` from the font you want to copy from.
-    1.  Switch focus to the minimized font.
-    1.  Select `.notdef` glyph.
-    1.  Navigate the menu: `Edit`->`Paste`.
-1.  Export the font using the menu: `File`->`Generate Fonts...`, make sure that
-the file name is correct.
-1.  Fix any errors if found, or if you can.
+1.  Select one of the profiles below.
+2.  Add a variable named `cobalt_font_package` in your platform's
+`gyp_configuration.gypi` file.
+
+Example:
+
+    'variables': {
+        'cobalt_font_package': '10megabytes',
+    }
+
+
+
+## Profiles
+
+1.  `10megabytes`: Use this set of fonts if the target space allocated for fonts
+is approximately 10 megabytes.  This directory contains DroidSansFallback, which
+will render many Chinese, and Korean characters at lower quality.  The benefit
+of using this font is space savings at the cost of reduced quality.
+1.  `minimal`: Use this if minimizing space is a goal, and Cobalt should rely
+on web fonts.
+1.  `unlimited`: This font set is preferred, and default.  This will enable the
+use the fonts with highest quality and coverage, without the network latency of
+fetching fonts from the server.
diff --git a/src/cobalt/content/fonts/CarroisGothicSC-Regular.ttf b/src/cobalt/content/fonts/all_fonts/CarroisGothicSC-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/CarroisGothicSC-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/CarroisGothicSC-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/ComingSoon.ttf b/src/cobalt/content/fonts/all_fonts/ComingSoon.ttf
similarity index 100%
rename from src/cobalt/content/fonts/ComingSoon.ttf
rename to src/cobalt/content/fonts/all_fonts/ComingSoon.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/CutiveMono.ttf b/src/cobalt/content/fonts/all_fonts/CutiveMono.ttf
similarity index 100%
rename from src/cobalt/content/fonts/CutiveMono.ttf
rename to src/cobalt/content/fonts/all_fonts/CutiveMono.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/DancingScript-Bold.ttf b/src/cobalt/content/fonts/all_fonts/DancingScript-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/DancingScript-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/DancingScript-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/DancingScript-Regular.ttf b/src/cobalt/content/fonts/all_fonts/DancingScript-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/DancingScript-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/DancingScript-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/DroidSansFallback.ttf b/src/cobalt/content/fonts/all_fonts/DroidSansFallback.ttf
similarity index 100%
rename from src/cobalt/content/fonts/DroidSansFallback.ttf
rename to src/cobalt/content/fonts/all_fonts/DroidSansFallback.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/DroidSansMono.ttf b/src/cobalt/content/fonts/all_fonts/DroidSansMono.ttf
similarity index 100%
rename from src/cobalt/content/fonts/DroidSansMono.ttf
rename to src/cobalt/content/fonts/all_fonts/DroidSansMono.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/MTLmr3m.ttf b/src/cobalt/content/fonts/all_fonts/MTLmr3m.ttf
similarity index 100%
rename from src/cobalt/content/fonts/MTLmr3m.ttf
rename to src/cobalt/content/fonts/all_fonts/MTLmr3m.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/MinimalRoboto.ttf b/src/cobalt/content/fonts/all_fonts/MinimalRoboto.ttf
similarity index 100%
rename from src/cobalt/content/fonts/MinimalRoboto.ttf
rename to src/cobalt/content/fonts/all_fonts/MinimalRoboto.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NanumGothic.ttf b/src/cobalt/content/fonts/all_fonts/NanumGothic.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NanumGothic.ttf
rename to src/cobalt/content/fonts/all_fonts/NanumGothic.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoEmoji-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoEmoji-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoEmoji-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoEmoji-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoNaskhArabicUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoNaskhArabicUI-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoNaskhArabicUI-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoNaskhArabicUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoNaskhArabicUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoNaskhArabicUI-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoNaskhArabicUI-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoNaskhArabicUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansArmenian-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansArmenian-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansArmenian-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansArmenian-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansArmenian-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansArmenian-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansArmenian-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansArmenian-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansBalinese-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansBalinese-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansBalinese-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansBalinese-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansBamum-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansBamum-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansBamum-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansBamum-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansBatak-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansBatak-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansBatak-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansBatak-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansBengaliUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansBengaliUI-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansBengaliUI-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansBengaliUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansBengaliUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansBengaliUI-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansBengaliUI-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansBengaliUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansBuginese-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansBuginese-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansBuginese-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansBuginese-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansBuhid-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansBuhid-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansBuhid-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansBuhid-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansCanadianAboriginal-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansCanadianAboriginal-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansCanadianAboriginal-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansCanadianAboriginal-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansCham-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansCham-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansCham-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansCham-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansCham-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansCham-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansCham-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansCham-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansCherokee-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansCherokee-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansCherokee-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansCherokee-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansCoptic-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansCoptic-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansCoptic-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansCoptic-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansDevanagariUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansDevanagariUI-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansDevanagariUI-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansDevanagariUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansDevanagariUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansDevanagariUI-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansDevanagariUI-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansDevanagariUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansEthiopic-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansEthiopic-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansEthiopic-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansEthiopic-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansEthiopic-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansEthiopic-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansEthiopic-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansEthiopic-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansGeorgian-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansGeorgian-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansGeorgian-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansGeorgian-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansGeorgian-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansGeorgian-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansGeorgian-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansGeorgian-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansGlagolitic-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansGlagolitic-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansGlagolitic-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansGlagolitic-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansGujaratiUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansGujaratiUI-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansGujaratiUI-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansGujaratiUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansGujaratiUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansGujaratiUI-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansGujaratiUI-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansGujaratiUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansGurmukhiUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansGurmukhiUI-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansGurmukhiUI-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansGurmukhiUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansGurmukhiUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansGurmukhiUI-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansGurmukhiUI-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansGurmukhiUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansHanunoo-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansHanunoo-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansHanunoo-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansHanunoo-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansHebrew-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansHebrew-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansHebrew-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansHebrew-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansHebrew-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansHebrew-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansHebrew-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansHebrew-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansJP-Regular.otf b/src/cobalt/content/fonts/all_fonts/NotoSansJP-Regular.otf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansJP-Regular.otf
rename to src/cobalt/content/fonts/all_fonts/NotoSansJP-Regular.otf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansJavanese-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansJavanese-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansJavanese-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansJavanese-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansKR-Regular.otf b/src/cobalt/content/fonts/all_fonts/NotoSansKR-Regular.otf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansKR-Regular.otf
rename to src/cobalt/content/fonts/all_fonts/NotoSansKR-Regular.otf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansKannadaUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansKannadaUI-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansKannadaUI-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansKannadaUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansKannadaUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansKannadaUI-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansKannadaUI-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansKannadaUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansKayahLi-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansKayahLi-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansKayahLi-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansKayahLi-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansKhmerUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansKhmerUI-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansKhmerUI-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansKhmerUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansKhmerUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansKhmerUI-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansKhmerUI-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansKhmerUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansLaoUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansLaoUI-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansLaoUI-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansLaoUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansLaoUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansLaoUI-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansLaoUI-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansLaoUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansLepcha-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansLepcha-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansLepcha-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansLepcha-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansLimbu-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansLimbu-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansLimbu-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansLimbu-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansLisu-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansLisu-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansLisu-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansLisu-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansMalayalamUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansMalayalamUI-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansMalayalamUI-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansMalayalamUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansMalayalamUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansMalayalamUI-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansMalayalamUI-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansMalayalamUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansMandaic-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansMandaic-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansMandaic-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansMandaic-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansMeeteiMayek-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansMeeteiMayek-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansMeeteiMayek-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansMeeteiMayek-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansMongolian-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansMongolian-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansMongolian-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansMongolian-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansMyanmarUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansMyanmarUI-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansMyanmarUI-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansMyanmarUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansMyanmarUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansMyanmarUI-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansMyanmarUI-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansMyanmarUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansNKo-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansNKo-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansNKo-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansNKo-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansNewTaiLue-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansNewTaiLue-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansNewTaiLue-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansNewTaiLue-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansOlChiki-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansOlChiki-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansOlChiki-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansOlChiki-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansOriyaUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansOriyaUI-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansOriyaUI-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansOriyaUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansOriyaUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansOriyaUI-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansOriyaUI-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansOriyaUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansRejang-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansRejang-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansRejang-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansRejang-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSC-Regular.otf b/src/cobalt/content/fonts/all_fonts/NotoSansSC-Regular.otf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansSC-Regular.otf
rename to src/cobalt/content/fonts/all_fonts/NotoSansSC-Regular.otf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSaurashtra-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansSaurashtra-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansSaurashtra-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansSaurashtra-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSinhala-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansSinhala-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansSinhala-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansSinhala-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSinhala-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansSinhala-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansSinhala-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansSinhala-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSundanese-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansSundanese-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansSundanese-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansSundanese-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSylotiNagri-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansSylotiNagri-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansSylotiNagri-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansSylotiNagri-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSymbols-Regular-Subsetted.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansSymbols-Regular-Subsetted.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansSymbols-Regular-Subsetted.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansSymbols-Regular-Subsetted.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSyriacEstrangela-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansSyriacEstrangela-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansSyriacEstrangela-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansSyriacEstrangela-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTC-Regular.otf b/src/cobalt/content/fonts/all_fonts/NotoSansTC-Regular.otf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansTC-Regular.otf
rename to src/cobalt/content/fonts/all_fonts/NotoSansTC-Regular.otf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTagbanwa-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTagbanwa-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansTagbanwa-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansTagbanwa-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTaiLe-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTaiLe-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansTaiLe-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansTaiLe-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTaiTham-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTaiTham-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansTaiTham-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansTaiTham-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTaiViet-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTaiViet-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansTaiViet-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansTaiViet-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTamilUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTamilUI-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansTamilUI-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansTamilUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTamilUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTamilUI-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansTamilUI-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansTamilUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTeluguUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTeluguUI-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansTeluguUI-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansTeluguUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTeluguUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTeluguUI-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansTeluguUI-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansTeluguUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansThaana-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansThaana-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansThaana-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansThaana-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansThaana-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansThaana-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansThaana-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansThaana-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansThaiUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansThaiUI-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansThaiUI-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansThaiUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansThaiUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansThaiUI-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansThaiUI-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansThaiUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTibetan-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTibetan-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansTibetan-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansTibetan-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTifinagh-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTifinagh-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansTifinagh-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansTifinagh-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansVai-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansVai-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansVai-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansVai-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansYi-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansYi-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSansYi-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSansYi-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSerif-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSerif-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSerif-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSerif-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSerif-BoldItalic.ttf b/src/cobalt/content/fonts/all_fonts/NotoSerif-BoldItalic.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSerif-BoldItalic.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSerif-BoldItalic.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSerif-Italic.ttf b/src/cobalt/content/fonts/all_fonts/NotoSerif-Italic.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSerif-Italic.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSerif-Italic.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSerif-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSerif-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/NotoSerif-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/NotoSerif-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/Roboto-Bold.ttf b/src/cobalt/content/fonts/all_fonts/Roboto-Bold.ttf
similarity index 100%
rename from src/cobalt/content/fonts/Roboto-Bold.ttf
rename to src/cobalt/content/fonts/all_fonts/Roboto-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/Roboto-BoldItalic.ttf b/src/cobalt/content/fonts/all_fonts/Roboto-BoldItalic.ttf
similarity index 100%
rename from src/cobalt/content/fonts/Roboto-BoldItalic.ttf
rename to src/cobalt/content/fonts/all_fonts/Roboto-BoldItalic.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/Roboto-Italic.ttf b/src/cobalt/content/fonts/all_fonts/Roboto-Italic.ttf
similarity index 100%
rename from src/cobalt/content/fonts/Roboto-Italic.ttf
rename to src/cobalt/content/fonts/all_fonts/Roboto-Italic.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/Roboto-Regular.ttf b/src/cobalt/content/fonts/all_fonts/Roboto-Regular.ttf
similarity index 100%
rename from src/cobalt/content/fonts/Roboto-Regular.ttf
rename to src/cobalt/content/fonts/all_fonts/Roboto-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/minimal/fonts.xml b/src/cobalt/content/fonts/minimal/fonts.xml
new file mode 100644
index 0000000..1381b81
--- /dev/null
+++ b/src/cobalt/content/fonts/minimal/fonts.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<familyset version="1">
+    <!-- Ideally, this font should only be used if there are no other fonts in
+         our final image. -->
+    <family name="Minimal Roboto">
+        <font weight="400" style="normal">MinimalRoboto.ttf</font>
+    </family>
+    <family name="sans-serif-smallcaps">
+        <font weight="400" style="normal">CarroisGothicSC-Regular.ttf</font>
+    </family>
+</familyset>
diff --git a/src/cobalt/content/fonts/scripts/README.md b/src/cobalt/content/fonts/scripts/README.md
new file mode 100644
index 0000000..acee96c
--- /dev/null
+++ b/src/cobalt/content/fonts/scripts/README.md
@@ -0,0 +1,29 @@
+# Generating a minimal font for devices with small space requirements
+
+[GlyphIGo](https://github.com/pettarin/glyphIgo) was used to generate a subset
+of the Roboto font
+
+`cobalt/content/fonts` contains a script called `create_minimized_roboto.sh`
+that can help recreate minimized font if needed
+
+Steps:
+
+1.  `cd src/cobalt/content/fonts`
+1.  `./create_minimized_roboto.sh`
+1.  Download `fontforge` using apt.  `sudo apt install fontforge`
+1.  In `fontforge`, navigate the menu: `Encoding`->`Reencode`->`Glyph Order`.
+Scroll to the top, find the first glyph.  By spec, this glyph is called
+`.notdef`, and is used when this font is the default font and there glyph for a
+character we're looking for is missing in the file.  Often this will be blank
+after the last step, which can be undesired.
+1.  Copy `.notdef` glyph from a different font.
+    1.  Open a different font.
+    1.  Find the `.notdef` glyph.
+    1.  Select the glyph without opening it.
+    1.  Navigate the menu: `Edit`->`Copy` from the font you want to copy from.
+    1.  Switch focus to the minimized font.
+    1.  Select `.notdef` glyph.
+    1.  Navigate the menu: `Edit`->`Paste`.
+1.  Export the font using the menu: `File`->`Generate Fonts...`, make sure that
+the file name is correct.
+1.  Fix any errors if found, or if you can.
diff --git a/src/cobalt/content/fonts/scripts/Roboto-Regular.ttf b/src/cobalt/content/fonts/scripts/Roboto-Regular.ttf
new file mode 100644
index 0000000..251d6a7
--- /dev/null
+++ b/src/cobalt/content/fonts/scripts/Roboto-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/create_minimized_roboto.sh b/src/cobalt/content/fonts/scripts/create_minimized_roboto.sh
similarity index 100%
rename from src/cobalt/content/fonts/create_minimized_roboto.sh
rename to src/cobalt/content/fonts/scripts/create_minimized_roboto.sh
diff --git a/src/cobalt/content/fonts/minimized_roboto_subset_chars.txt b/src/cobalt/content/fonts/scripts/minimized_roboto_subset_chars.txt
similarity index 78%
rename from src/cobalt/content/fonts/minimized_roboto_subset_chars.txt
rename to src/cobalt/content/fonts/scripts/minimized_roboto_subset_chars.txt
index 75498f5..54fdd68 100644
--- a/src/cobalt/content/fonts/minimized_roboto_subset_chars.txt
+++ b/src/cobalt/content/fonts/scripts/minimized_roboto_subset_chars.txt
@@ -1 +1 @@
-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 (),.-/!
\ No newline at end of file
+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ()[]{},.-/!#'"<>:
diff --git a/src/cobalt/content/fonts/fonts.xml b/src/cobalt/content/fonts/unlimited/fonts.xml
similarity index 100%
rename from src/cobalt/content/fonts/fonts.xml
rename to src/cobalt/content/fonts/unlimited/fonts.xml
diff --git a/src/cobalt/debug/debug_web_server.cc b/src/cobalt/debug/debug_web_server.cc
index 0bc80b7..5ec3d06 100644
--- a/src/cobalt/debug/debug_web_server.cc
+++ b/src/cobalt/debug/debug_web_server.cc
@@ -137,10 +137,10 @@
 }
 
 DebugWebServer::~DebugWebServer() {
-  net::HttpServer* server = server_.get();
-  server_->AddRef();
-  server_ = NULL;
-  http_server_thread_.message_loop()->ReleaseSoon(FROM_HERE, server);
+  // Destroy the server on its own thread then stop the thread.
+  http_server_thread_.message_loop()->PostTask(
+      FROM_HERE,
+      base::Bind(&DebugWebServer::StopServer, base::Unretained(this)));
   http_server_thread_.Stop();
 }
 
@@ -320,5 +320,10 @@
   }
 }
 
+void DebugWebServer::StopServer() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  server_ = NULL;
+}
+
 }  // namespace debug
 }  // namespace cobalt
diff --git a/src/cobalt/debug/debug_web_server.h b/src/cobalt/debug/debug_web_server.h
index ac2a593..9f55c16 100644
--- a/src/cobalt/debug/debug_web_server.h
+++ b/src/cobalt/debug/debug_web_server.h
@@ -79,11 +79,14 @@
 
   void StartServer(int port);
 
+  void StopServer();
+
   void SendErrorResponseOverWebSocket(int id, const std::string& message);
 
   base::ThreadChecker thread_checker_;
   base::Thread http_server_thread_;
   scoped_ptr<net::StreamListenSocketFactory> factory_;
+  // net::HttpServer is a ref-counted object, so we have to use scoped_refptr.
   scoped_refptr<net::HttpServer> server_;
   GetDebugServerCallback get_debug_server_callback_;
 
diff --git a/src/cobalt/dom/font_cache.h b/src/cobalt/dom/font_cache.h
index 469d8e0..dd74c4e 100644
--- a/src/cobalt/dom/font_cache.h
+++ b/src/cobalt/dom/font_cache.h
@@ -39,20 +39,21 @@
 namespace dom {
 
 // The font cache is typically owned by dom::Document and handles the following:
+//   - Tracking of font faces, which it uses to determine if a specified
+//     font family is local or remote, and for url determination in requesting
+//     remote typefaces.
 //   - Creation and caching of font lists, which it provides to the used
 //     style provider as requested. Font lists handle most layout-related font
 //     cache interactions. Layout objects only interact with the font cache
 //     through their font lists.
-//   - Tracking of font faces, which it uses to determine if a specified
-//     font family is local or remote, and for url determination in requesting
-//     remote typefaces.
 //   - Retrieval of typefaces, either locally from the resource provider or
-//     remotely from the remote typeface cache.
-//   - Caching the indices of the glyphs that the typeface provides for specific
-//     characters, so that only the first query of a specific font character
-//     necessitates the glyph lookup.
-//   - Determination of the fallback typeface for a specific character, and
-//     caching of that information for subsequent lookups.
+//     remotely from the remote typeface cache, and caching of both typefaces
+//     and fonts to facilitate sharing of them across font lists.
+//   - Determination of the fallback typeface for a specific character using a
+//     specific font style, and caching of that information for subsequent
+//     lookups.
+//   - Creation of glyph buffers, which is accomplished by passing the request
+//    to the resource provider.
 // NOTE: The font cache is not thread-safe and must only used within a single
 // thread.
 class FontCache {
diff --git a/src/cobalt/dom/window.cc b/src/cobalt/dom/window.cc
index 3e23ed9..054f995 100644
--- a/src/cobalt/dom/window.cc
+++ b/src/cobalt/dom/window.cc
@@ -39,9 +39,6 @@
 #include "cobalt/dom/storage.h"
 #include "cobalt/dom/window_timers.h"
 #include "cobalt/script/javascript_engine.h"
-#if defined(OS_STARBOARD)
-#include "starboard/system.h"
-#endif
 
 namespace cobalt {
 namespace dom {
@@ -85,6 +82,7 @@
                const std::string& default_security_policy,
                CspEnforcementType csp_enforcement_mode,
                const base::Closure& csp_policy_changed_callback,
+               const base::Closure& window_close_callback,
                int csp_insecure_allowed_token)
     : width_(width),
       height_(height),
@@ -123,7 +121,8 @@
           new Storage(this, Storage::kLocalStorage, local_storage_database))),
       ALLOW_THIS_IN_INITIALIZER_LIST(
           session_storage_(new Storage(this, Storage::kSessionStorage, NULL))),
-      screen_(new Screen(width, height)) {
+      screen_(new Screen(width, height)),
+      window_close_callback_(window_close_callback) {
 #if defined(ENABLE_TEST_RUNNER)
   test_runner_ = new TestRunner();
 #endif  // ENABLE_TEST_RUNNER
@@ -140,11 +139,9 @@
 
 // https://www.w3.org/TR/html5/browsers.html#dom-window-close
 void Window::Close() {
-#if defined(OS_STARBOARD)
-  SbSystemRequestStop(0);
-#else
-  LOG(WARNING) << "window.close is not supported on this platform.";
-#endif
+  if (!window_close_callback_.is_null()) {
+    window_close_callback_.Run();
+  }
 }
 
 const scoped_refptr<Navigator>& Window::navigator() const { return navigator_; }
diff --git a/src/cobalt/dom/window.h b/src/cobalt/dom/window.h
index 8240112..7853ada 100644
--- a/src/cobalt/dom/window.h
+++ b/src/cobalt/dom/window.h
@@ -107,6 +107,7 @@
          const std::string& default_security_policy,
          dom::CspEnforcementType csp_enforcement_mode,
          const base::Closure& csp_policy_changed_callback,
+         const base::Closure& window_close_callback,
          int csp_insecure_allowed_token = 0);
 
   // Web API: Window
@@ -277,6 +278,8 @@
 
   scoped_refptr<Screen> screen_;
 
+  base::Closure window_close_callback_;
+
 #if defined(ENABLE_TEST_RUNNER)
   scoped_refptr<TestRunner> test_runner_;
 #endif  // ENABLE_TEST_RUNNER
diff --git a/src/cobalt/dom/window_test.cc b/src/cobalt/dom/window_test.cc
index 43650c0..8879146 100644
--- a/src/cobalt/dom/window_test.cc
+++ b/src/cobalt/dom/window_test.cc
@@ -61,7 +61,8 @@
                        base::Unretained(&mock_error_callback_)),
             NULL, network_bridge::PostSender(),
             std::string() /* default security policy */, kCspEnforcementEnable,
-            base::Closure() /* csp_policy_changed */)) {}
+            base::Closure() /* csp_policy_changed */,
+            base::Closure() /* window_close */)) {}
 
   ~WindowTest() OVERRIDE {}
 
diff --git a/src/cobalt/layout/layout.cc b/src/cobalt/layout/layout.cc
index 46ca1c1..bd61bde 100644
--- a/src/cobalt/layout/layout.cc
+++ b/src/cobalt/layout/layout.cc
@@ -78,7 +78,7 @@
   *initial_containing_block = initial_containing_block_creation_results.box;
 
   // Generate boxes.
-  {
+  if (document->html()) {
     TRACE_EVENT0("cobalt::layout", kBenchmarkStatBoxGeneration);
     base::StopWatch stop_watch_box_generation(
         LayoutStatTracker::kStopWatchTypeBoxGeneration,
diff --git a/src/cobalt/layout_tests/layout_snapshot.cc b/src/cobalt/layout_tests/layout_snapshot.cc
index 97b7689..5fb8bce 100644
--- a/src/cobalt/layout_tests/layout_snapshot.cc
+++ b/src/cobalt/layout_tests/layout_snapshot.cc
@@ -85,8 +85,9 @@
       url, base::Bind(&WebModuleOnRenderTreeProducedCallback, &results,
                       &run_loop, MessageLoop::current()),
       base::Bind(&WebModuleErrorCallback, &run_loop, MessageLoop::current()),
-      stub_media_module.get(), &network_module, viewport_size,
-      resource_provider, 60.0f, web_module_options);
+      base::Closure() /* window_close_callback */, stub_media_module.get(),
+      &network_module, viewport_size, resource_provider, 60.0f,
+      web_module_options);
 
   run_loop.Run();
 
diff --git a/src/cobalt/layout_tests/web_platform_tests.cc b/src/cobalt/layout_tests/web_platform_tests.cc
index 14e32ae..d984a55 100644
--- a/src/cobalt/layout_tests/web_platform_tests.cc
+++ b/src/cobalt/layout_tests/web_platform_tests.cc
@@ -176,8 +176,9 @@
       url, base::Bind(&WebModuleOnRenderTreeProducedCallback, &results,
                       &run_loop, MessageLoop::current()),
       base::Bind(&WebModuleErrorCallback, &run_loop, MessageLoop::current()),
-      media_module.get(), &network_module, kDefaultViewportSize,
-      &resource_provider, 60.0f, web_module_options);
+      base::Closure() /* window_close_callback */, media_module.get(),
+      &network_module, kDefaultViewportSize, &resource_provider, 60.0f,
+      web_module_options);
   run_loop.Run();
   const std::string extract_results =
       "document.getElementById(\"__testharness__results__\").textContent;";
diff --git a/src/cobalt/loader/embedded_resources/splash_screen.css b/src/cobalt/loader/embedded_resources/splash_screen.css
index 0af40bf..7602576 100644
--- a/src/cobalt/loader/embedded_resources/splash_screen.css
+++ b/src/cobalt/loader/embedded_resources/splash_screen.css
@@ -4,11 +4,11 @@
 }
 
 #splash {
-  background-color: #e62d27;
+  background-color: #e62117;
   background-image: url("h5vcc-embedded://you_tube_logo.png");
   background-position: center center;
   background-repeat: no-repeat;
-  background-size: 60%;
+  background-size: 100%;
   height: 100%;
   left: 0;
   position: absolute;
diff --git a/src/cobalt/loader/embedded_resources/you_tube_logo.png b/src/cobalt/loader/embedded_resources/you_tube_logo.png
index 0d2082d..a964097 100644
--- a/src/cobalt/loader/embedded_resources/you_tube_logo.png
+++ b/src/cobalt/loader/embedded_resources/you_tube_logo.png
Binary files differ
diff --git a/src/cobalt/media/media_module_starboard.cc b/src/cobalt/media/media_module_starboard.cc
index 4c54544..f4cf154 100644
--- a/src/cobalt/media/media_module_starboard.cc
+++ b/src/cobalt/media/media_module_starboard.cc
@@ -16,21 +16,14 @@
 
 #include "cobalt/media/media_module.h"
 
-#include "base/bind.h"
 #include "base/compiler_specific.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/math/size.h"
 #include "cobalt/media/shell_media_platform_starboard.h"
 #include "cobalt/system_window/starboard/system_window.h"
-#include "media/audio/null_audio_streamer.h"
-#include "media/audio/shell_audio_sink.h"
 #include "media/base/filter_collection.h"
 #include "media/base/media_log.h"
 #include "media/base/message_loop_factory.h"
-#include "media/filters/shell_audio_decoder_impl.h"
-#include "media/filters/shell_raw_audio_decoder_stub.h"
-#include "media/filters/shell_raw_video_decoder_stub.h"
-#include "media/filters/shell_video_decoder_impl.h"
 #include "media/player/web_media_player_impl.h"
 #include "starboard/media.h"
 #include "starboard/window.h"
@@ -76,14 +69,6 @@
         message_loop_factory->GetMessageLoop(MessageLoopFactory::kPipeline);
     scoped_ptr<FilterCollection> filter_collection(new FilterCollection);
 
-    ::media::ShellAudioStreamer* streamer = NULL;
-    if (options_.use_null_audio_streamer) {
-      DLOG(INFO) << "Use Null audio";
-      streamer = ::media::NullAudioStreamer::GetInstance();
-    } else {
-      DLOG(INFO) << "Use Pulse audio";
-      streamer = ::media::ShellAudioStreamer::Instance();
-    }
     SbWindow window = kSbWindowInvalid;
     if (system_window_) {
       window = polymorphic_downcast<SystemWindowStarboard*>(system_window_)
@@ -91,8 +76,8 @@
     }
     return make_scoped_ptr<WebMediaPlayer>(new ::media::WebMediaPlayerImpl(
         window, client, this, media_platform_.GetVideoFrameProvider(),
-        filter_collection.Pass(), new ::media::ShellAudioSink(streamer),
-        message_loop_factory.Pass(), new ::media::MediaLog));
+        filter_collection.Pass(), NULL, message_loop_factory.Pass(),
+        new ::media::MediaLog));
   }
 
  private:
diff --git a/src/cobalt/render_tree/node_visitor_test.cc b/src/cobalt/render_tree/node_visitor_test.cc
index ad7c3b2..cc6a84f 100644
--- a/src/cobalt/render_tree/node_visitor_test.cc
+++ b/src/cobalt/render_tree/node_visitor_test.cc
@@ -101,7 +101,7 @@
   }
 };
 
-void SetBounds(const cobalt::math::Rect&) {}
+bool SetBounds(const cobalt::math::Rect&) { return false; }
 
 }  // namespace
 
diff --git a/src/cobalt/render_tree/punch_through_video_node.h b/src/cobalt/render_tree/punch_through_video_node.h
index 7261ab7..22dd0f9 100644
--- a/src/cobalt/render_tree/punch_through_video_node.h
+++ b/src/cobalt/render_tree/punch_through_video_node.h
@@ -41,7 +41,7 @@
 //          support punch out video rendering.
 class PunchThroughVideoNode : public Node {
  public:
-  typedef base::Callback<void(const math::Rect&)> SetBoundsCB;
+  typedef base::Callback<bool(const math::Rect&)> SetBoundsCB;
 
   struct Builder {
     Builder(const math::RectF& rect, const SetBoundsCB& set_bounds_cb)
diff --git a/src/cobalt/renderer/copy_font_data.gypi b/src/cobalt/renderer/copy_font_data.gypi
index 2ce0512..405ad41 100644
--- a/src/cobalt/renderer/copy_font_data.gypi
+++ b/src/cobalt/renderer/copy_font_data.gypi
@@ -17,15 +17,192 @@
 
 {
   'includes': [ '../build/contents_dir.gypi' ],
-
   'variables': {
-    'fonts_dir': '<(static_contents_source_dir)/fonts',
+    'source_all_fonts_dir': '<(static_contents_source_dir)/fonts/all_fonts',
   },
 
   'copies': [
     {
-      'destination': '<(static_contents_output_data_dir)',
-      'files': [ '<@(fonts_dir)' ],
+      'destination': '<(static_contents_output_data_dir)/fonts/',
+      'files': [
+        '<(static_contents_source_dir)/fonts/<(cobalt_font_package)/fonts.xml',
+      ],
+      'conditions': [
+        [ 'cobalt_font_package == "minimal"', {
+          'files+': [
+            '<(source_all_fonts_dir)/MinimalRoboto.ttf',
+            '<(source_all_fonts_dir)/CarroisGothicSC-Regular.ttf',
+          ],
+        }], # minimal
+        [ 'cobalt_font_package == "10megabytes"', {
+          'files+': [
+            '<(source_all_fonts_dir)/NotoSansTagbanwa-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansSinhala-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansNewTaiLue-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansSundanese-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansMandaic-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansGurmukhiUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansDevanagariUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansMongolian-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansBamum-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansBuhid-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansCherokee-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansArmenian-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansJP-Regular.otf',
+            '<(source_all_fonts_dir)/NotoSansEthiopic-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansGlagolitic-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansBatak-Regular.ttf',
+            '<(source_all_fonts_dir)/Roboto-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoNaskhArabicUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansBuginese-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansVai-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTifinagh-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansCham-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansJavanese-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTeluguUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTaiLe-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansMeeteiMayek-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansKannadaUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansSyriacEstrangela-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansBengaliUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansThaiUI-Regular.ttf',
+            '<(source_all_fonts_dir)/CarroisGothicSC-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansNKo-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansGeorgian-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansSymbols-Regular-Subsetted.ttf',
+            '<(source_all_fonts_dir)/NotoSansCoptic-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansYi-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTaiTham-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansOlChiki-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansOriyaUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansSylotiNagri-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansRejang-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansCanadianAboriginal-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansLisu-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTibetan-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansKayahLi-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansLaoUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansHanunoo-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTaiViet-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansHebrew-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansBalinese-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTamilUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansGujaratiUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansMalayalamUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansLepcha-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoEmoji-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansThaana-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansKhmerUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansSaurashtra-Regular.ttf',
+            '<(source_all_fonts_dir)/DroidSansFallback.ttf',
+            '<(source_all_fonts_dir)/NotoSansLimbu-Regular.ttf',
+          ],
+        }], # 10megabytes
+        [ 'cobalt_font_package == "unlimited"', {
+          'files+': [
+            '<(source_all_fonts_dir)/NotoSansTagbanwa-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansSinhala-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansNewTaiLue-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansSundanese-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansMandaic-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSerif-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansTeluguUI-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansMyanmarUI-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansGurmukhiUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansDevanagariUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansMongolian-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansArmenian-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansBamum-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansBuhid-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansEthiopic-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansDevanagariUI-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansCherokee-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansArmenian-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansJP-Regular.otf',
+            '<(source_all_fonts_dir)/NotoSansOriyaUI-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansEthiopic-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansGlagolitic-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansBatak-Regular.ttf',
+            '<(source_all_fonts_dir)/Roboto-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTC-Regular.otf',
+            '<(source_all_fonts_dir)/NotoSerif-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoNaskhArabicUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansBuginese-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansVai-Regular.ttf',
+            '<(source_all_fonts_dir)/MTLmr3m.ttf',
+            '<(source_all_fonts_dir)/NanumGothic.ttf',
+            '<(source_all_fonts_dir)/ComingSoon.ttf',
+            '<(source_all_fonts_dir)/NotoSansTifinagh-Regular.ttf',
+            '<(source_all_fonts_dir)/DancingScript-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansCham-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansSC-Regular.otf',
+            '<(source_all_fonts_dir)/NotoSansHebrew-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansJavanese-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTeluguUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTaiLe-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansMeeteiMayek-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansKannadaUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansKhmerUI-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansSyriacEstrangela-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSerif-BoldItalic.ttf',
+            '<(source_all_fonts_dir)/NotoSansBengaliUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansThaiUI-Regular.ttf',
+            '<(source_all_fonts_dir)/CutiveMono.ttf',
+            '<(source_all_fonts_dir)/DroidSansMono.ttf',
+            '<(source_all_fonts_dir)/CarroisGothicSC-Regular.ttf',
+            '<(source_all_fonts_dir)/Roboto-Italic.ttf',
+            '<(source_all_fonts_dir)/NotoSansNKo-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansGeorgian-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansSymbols-Regular-Subsetted.ttf',
+            '<(source_all_fonts_dir)/NotoSansCoptic-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansYi-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTaiTham-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansMyanmarUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansMalayalamUI-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansGujaratiUI-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansLaoUI-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansOlChiki-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansOriyaUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansSylotiNagri-Regular.ttf',
+            '<(source_all_fonts_dir)/Roboto-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansRejang-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansThaiUI-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansCanadianAboriginal-Regular.ttf',
+            '<(source_all_fonts_dir)/Roboto-BoldItalic.ttf',
+            '<(source_all_fonts_dir)/NotoSansLisu-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTibetan-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansKayahLi-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansLaoUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansHanunoo-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTaiViet-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansKannadaUI-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansSinhala-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSerif-Italic.ttf',
+            '<(source_all_fonts_dir)/NotoSansGurmukhiUI-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansHebrew-Regular.ttf',
+            '<(source_all_fonts_dir)/DancingScript-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansBalinese-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTamilUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansGujaratiUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansGeorgian-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansMalayalamUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansLepcha-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoEmoji-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansTamilUI-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansThaana-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansKhmerUI-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansSaurashtra-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoSansKR-Regular.otf',
+            '<(source_all_fonts_dir)/NotoSansCham-Bold.ttf',
+            '<(source_all_fonts_dir)/DroidSansFallback.ttf',
+            '<(source_all_fonts_dir)/NotoSansBengaliUI-Bold.ttf',
+            '<(source_all_fonts_dir)/MinimalRoboto.ttf',
+            '<(source_all_fonts_dir)/NotoSansLimbu-Regular.ttf',
+            '<(source_all_fonts_dir)/NotoNaskhArabicUI-Bold.ttf',
+            '<(source_all_fonts_dir)/NotoSansThaana-Bold.ttf',
+          ],
+        }], # unlimited
+      ],
     },
   ],
 }
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_nv12.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_nv12.glsl
index 6fcae22..0a0d63b 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_nv12.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_nv12.glsl
@@ -11,7 +11,7 @@
     // Stage 0: YUV to RGB
     output_Stage0 = vec4(
         texture2D(uSampler0_Stage0, vMatrixCoord_Stage0).aaaa.r,
-        texture2D(uSampler1_Stage0, vMatrixCoord_Stage0).ba,
+        texture2D(uSampler1_Stage0, vMatrixCoord_Stage0).ra,
         1.0) * uYUVMatrix_Stage0;
   }
   gl_FragColor = output_Stage0;
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
index 12475b8..d0f5377 100644
--- a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
@@ -240,18 +240,23 @@
 
 void RenderTreeNodeVisitor::Visit(
     render_tree::PunchThroughVideoNode* punch_through_video_node) {
-  SbBlitterSetColor(context_, SbBlitterColorFromRGBA(0, 0, 0, 0));
-  SbBlitterSetBlending(context_, false);
   SbBlitterRect blitter_rect =
       RectFToBlitterRect(render_state_.transform.TransformRect(
           punch_through_video_node->data().rect));
-  SbBlitterFillRect(context_, blitter_rect);
 
-  if (!punch_through_video_node->data().set_bounds_cb.is_null()) {
-    punch_through_video_node->data().set_bounds_cb.Run(
-        math::Rect(blitter_rect.x, blitter_rect.y, blitter_rect.width,
-                   blitter_rect.height));
+  if (punch_through_video_node->data().set_bounds_cb.is_null()) {
+    return;
   }
+  bool render_punch_through =
+      punch_through_video_node->data().set_bounds_cb.Run(
+          math::Rect(blitter_rect.x, blitter_rect.y, blitter_rect.width,
+                     blitter_rect.height));
+  if (!render_punch_through) {
+    return;
+  }
+  SbBlitterSetColor(context_, SbBlitterColorFromRGBA(0, 0, 0, 0));
+  SbBlitterSetBlending(context_, false);
+  SbBlitterFillRect(context_, blitter_rect);
 }
 
 namespace {
diff --git a/src/cobalt/renderer/rasterizer/pixel_test.cc b/src/cobalt/renderer/rasterizer/pixel_test.cc
index 6dc87b7..6f821ed 100644
--- a/src/cobalt/renderer/rasterizer/pixel_test.cc
+++ b/src/cobalt/renderer/rasterizer/pixel_test.cc
@@ -113,7 +113,7 @@
 
 namespace {
 
-void SetBounds(const math::Rect&) {}
+bool SetBounds(bool result, const math::Rect&) { return result; }
 
 }  // namespace
 
@@ -2749,14 +2749,30 @@
       RoundedCorners(50, 50)));
 }
 
-TEST_F(PixelTest, PunchThroughVideoNodePunchesThrough) {
+// If SetBoundsCB() returns false, the PunchThroughVideoNode should have no
+// effect.
+TEST_F(PixelTest, PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsFalse) {
   CompositionNode::Builder builder;
   builder.AddChild(new RectNode(RectF(25, 25, 150, 150),
                                 scoped_ptr<Brush>(new SolidColorBrush(
                                     ColorRGBA(0.5f, 0.5f, 1.0f, 1.0f)))));
 
   builder.AddChild(new PunchThroughVideoNode(PunchThroughVideoNode::Builder(
-      RectF(50, 50, 100, 100), base::Bind(SetBounds))));
+      RectF(50, 50, 100, 100), base::Bind(SetBounds, false))));
+
+  TestTree(new CompositionNode(builder.Pass()));
+}
+
+// If SetBoundsCB() returns true, the PunchThroughVideoNode should trigger the
+// painting of a solid rectangle with RGBA(0, 0, 0, 0).
+TEST_F(PixelTest, PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsTrue) {
+  CompositionNode::Builder builder;
+  builder.AddChild(new RectNode(RectF(25, 25, 150, 150),
+                                scoped_ptr<Brush>(new SolidColorBrush(
+                                    ColorRGBA(0.5f, 0.5f, 1.0f, 1.0f)))));
+
+  builder.AddChild(new PunchThroughVideoNode(PunchThroughVideoNode::Builder(
+      RectF(50, 50, 100, 100), base::Bind(SetBounds, true))));
 
   TestTree(new CompositionNode(builder.Pass()));
 }
diff --git a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
index b0b493f..ab9fc7d 100644
--- a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
@@ -697,9 +697,6 @@
 
   const math::RectF& math_rect = punch_through_video_node->data().rect;
 
-  SkPaint paint;
-  paint.setXfermodeMode(SkXfermode::kSrc_Mode);
-  paint.setARGB(0, 0, 0, 0);
   SkRect sk_rect = SkRect::MakeXYWH(math_rect.x(), math_rect.y(),
                                     math_rect.width(), math_rect.height());
   SkMatrix total_matrix = draw_state_.render_target->getTotalMatrix();
@@ -707,13 +704,22 @@
   SkRect sk_rect_transformed;
   total_matrix.mapRect(&sk_rect_transformed, sk_rect);
 
-  if (!punch_through_video_node->data().set_bounds_cb.is_null()) {
-    punch_through_video_node->data().set_bounds_cb.Run(
-        math::Rect(static_cast<int>(sk_rect_transformed.x()),
-                   static_cast<int>(sk_rect_transformed.y()),
-                   static_cast<int>(sk_rect_transformed.width()),
-                   static_cast<int>(sk_rect_transformed.height())));
+  if (punch_through_video_node->data().set_bounds_cb.is_null()) {
+    return;
   }
+  bool render_punch_through =
+      punch_through_video_node->data().set_bounds_cb.Run(
+          math::Rect(static_cast<int>(sk_rect_transformed.x()),
+                     static_cast<int>(sk_rect_transformed.y()),
+                     static_cast<int>(sk_rect_transformed.width()),
+                     static_cast<int>(sk_rect_transformed.height())));
+  if (!render_punch_through) {
+    return;
+  }
+
+  SkPaint paint;
+  paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+  paint.setARGB(0, 0, 0, 0);
 
   draw_state_.render_target->drawRect(sk_rect, paint);
 
diff --git a/src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsFalse-expected.png b/src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsFalse-expected.png
new file mode 100644
index 0000000..d26f087
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsFalse-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThrough-expected.png b/src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsTrue-expected.png
similarity index 100%
rename from src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThrough-expected.png
rename to src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsTrue-expected.png
Binary files differ
diff --git a/src/cobalt/script/mozjs/conversion_helpers.h b/src/cobalt/script/mozjs/conversion_helpers.h
index 3d54ec6..19a8ec8 100644
--- a/src/cobalt/script/mozjs/conversion_helpers.h
+++ b/src/cobalt/script/mozjs/conversion_helpers.h
@@ -71,7 +71,6 @@
   size_t length = in_string.length();
   jschar* inflated_buffer =
       js::InflateUTF8String(context, in_string.c_str(), &length);
-  DCHECK(inflated_buffer);
 
   if (!inflated_buffer) {
     LOG(ERROR) << "Failed to inflate UTF8 string.";
diff --git a/src/cobalt/script/mozjs/mozjs.gyp b/src/cobalt/script/mozjs/mozjs.gyp
index b29d99b..6e856f5 100644
--- a/src/cobalt/script/mozjs/mozjs.gyp
+++ b/src/cobalt/script/mozjs/mozjs.gyp
@@ -73,5 +73,30 @@
         '<(DEPTH)/third_party/mozjs/mozjs.gyp:mozjs_lib',
       ],
     },
+
+    {
+      'target_name': 'mozjs_engine_test',
+      'type': '<(gtest_target_type)',
+      'sources': [
+        '<(DEPTH)/third_party/mozjs/test/jscustomallocator_test.cc',
+      ],
+      'dependencies': [
+        '<(DEPTH)/base/base.gyp:run_all_unittests',
+        '<(DEPTH)/testing/gtest.gyp:gtest',
+        '<(DEPTH)/third_party/mozjs/mozjs.gyp:mozjs_lib',
+      ],
+    },
+
+    {
+      'target_name': 'mozjs_engine_test_deploy',
+      'type': 'none',
+      'dependencies': [
+        'mozjs_engine_test',
+      ],
+      'variables': {
+        'executable_name': 'mozjs_engine_test',
+      },
+      'includes': [ '../../../starboard/build/deploy.gypi' ],
+    },
   ],
 }
diff --git a/src/cobalt/script/mozjs/mozjs_engine.cc b/src/cobalt/script/mozjs/mozjs_engine.cc
index 1b79cf7..39f47bb 100644
--- a/src/cobalt/script/mozjs/mozjs_engine.cc
+++ b/src/cobalt/script/mozjs/mozjs_engine.cc
@@ -19,7 +19,11 @@
 #include <algorithm>
 
 #include "base/logging.h"
+#include "cobalt/base/c_val.h"
+#include "cobalt/base/poller.h"
+#include "cobalt/browser/web_module.h"
 #include "cobalt/script/mozjs/mozjs_global_environment.h"
+#include "third_party/mozjs/cobalt_config/include/jscustomallocator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 
 namespace cobalt {
@@ -38,6 +42,64 @@
   CheckAccessStub,
   MozjsGlobalEnvironment::CheckEval
 };
+
+#if defined(__LB_SHELL__FOR_RELEASE__)
+const int kPollerPeriodMs = 2000;
+#else  // #if defined(__LB_SHELL__FOR_RELEASE__)
+const int kPollerPeriodMs = 20;
+#endif  // #if defined(__LB_SHELL__FOR_RELEASE__)
+
+class EngineStats {
+ public:
+  EngineStats();
+
+  static EngineStats* GetInstance() {
+    return Singleton<EngineStats,
+                     StaticMemorySingletonTraits<EngineStats> >::get();
+  }
+
+  void EngineCreated() {
+    base::AutoLock auto_lock(lock_);
+    ++engine_count_;
+  }
+
+  void EngineDestroyed() {
+    base::AutoLock auto_lock(lock_);
+    --engine_count_;
+  }
+
+  void Update() {
+    base::AutoLock auto_lock(lock_);
+    allocated_memory_ =
+        MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+    mapped_memory_ = MemoryAllocatorReporter::Get()->GetCurrentBytesMapped();
+    memory_sum_ = allocated_memory_ + mapped_memory_;
+  }
+
+ private:
+  base::Lock lock_;
+  base::CVal<size_t, base::CValPublic> allocated_memory_;
+  base::CVal<size_t, base::CValPublic> mapped_memory_;
+  base::CVal<size_t, base::CValPublic> memory_sum_;
+  base::CVal<size_t> engine_count_;
+
+  // Repeating timer to query the used bytes.
+  scoped_ptr<base::PollerWithThread> poller_;
+};
+
+EngineStats::EngineStats()
+    : allocated_memory_("Memory.JS.AllocatedMemory", 0,
+                        "JS memory occupied by the Mozjs allocator."),
+      mapped_memory_("Memory.JS.MappedMemory", 0, "JS mapped memory."),
+      memory_sum_("Memory.JS", 0,
+                  "Total memory occupied by the Mozjs allocator and heap."),
+      engine_count_("Count.JS.Engine", 0,
+                    "Total JavaScript engine registered.") {
+  poller_.reset(new base::PollerWithThread(
+      base::Bind(&EngineStats::Update, base::Unretained(this)),
+      base::TimeDelta::FromMilliseconds(kPollerPeriodMs)));
+}
+
 }  // namespace
 
 MozjsEngine::MozjsEngine() {
@@ -47,6 +109,12 @@
       JS_NewRuntime(kGarbageCollectionThresholdBytes, JS_NO_HELPER_THREADS);
   CHECK(runtime_);
 
+  // Sets the size of the native stack that should not be exceeded.
+  // Setting three quarters of the web module stack size to ensure that native
+  // stack won't exceed the stack size.
+  JS_SetNativeStackQuota(runtime_,
+                         browser::WebModule::kWebModuleStackSize / 4 * 3);
+
   JS_SetRuntimePrivate(runtime_, this);
 
   JS_SetSecurityCallbacks(runtime_, &security_callbacks);
@@ -68,10 +136,13 @@
 
   // Callback to be called during garbage collection during the sweep phase.
   JS_SetFinalizeCallback(runtime_, &MozjsEngine::FinalizeCallback);
+
+  EngineStats::GetInstance()->EngineCreated();
 }
 
 MozjsEngine::~MozjsEngine() {
   DCHECK(thread_checker_.CalledOnValidThread());
+  EngineStats::GetInstance()->EngineDestroyed();
   JS_DestroyRuntime(runtime_);
 }
 
diff --git a/src/cobalt/script/mozjs/mozjs_global_environment.cc b/src/cobalt/script/mozjs/mozjs_global_environment.cc
index 25fa34b..9a79991 100644
--- a/src/cobalt/script/mozjs/mozjs_global_environment.cc
+++ b/src/cobalt/script/mozjs/mozjs_global_environment.cc
@@ -195,33 +195,16 @@
     const scoped_refptr<SourceCode>& source_code,
     std::string* out_result_utf8) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  MozjsSourceCode* mozjs_source_code =
-      base::polymorphic_downcast<MozjsSourceCode*>(source_code.get());
-
-  const std::string& script = mozjs_source_code->source_utf8();
-  const base::SourceLocation location = mozjs_source_code->location();
 
   JSAutoRequest auto_request(context_);
   JSAutoCompartment auto_compartment(context_, global_object_proxy_);
   JSExceptionState* previous_exception_state = JS_SaveExceptionState(context_);
   JS::RootedValue result_value(context_);
+
   std::string error_message;
   last_error_message_ = &error_message;
-  JS::RootedObject global_object(
-      context_, js::GetProxyTargetObject(global_object_proxy_));
 
-  size_t length = script.size();
-  jschar* inflated_buffer =
-      js::InflateUTF8String(context_, script.c_str(), &length);
-  DCHECK(inflated_buffer);
-  bool success = false;
-  if (inflated_buffer) {
-    success = JS_EvaluateUCScript(context_, global_object, inflated_buffer,
-                                  length, location.file_path.c_str(),
-                                  location.line_number, result_value.address());
-    js_free(inflated_buffer);
-  }
-
+  bool success = EvaluateScriptInternal(source_code, &result_value);
   if (out_result_utf8) {
     if (success) {
       MozjsExceptionState exception_state(context_);
@@ -233,8 +216,61 @@
       DLOG(ERROR) << "Script execution failed.";
     }
   }
-  JS_RestoreExceptionState(context_, previous_exception_state);
   last_error_message_ = NULL;
+  JS_RestoreExceptionState(context_, previous_exception_state);
+  return success;
+}
+
+bool MozjsGlobalEnvironment::EvaluateScript(
+    const scoped_refptr<SourceCode>& source_code,
+    const scoped_refptr<Wrappable>& owning_object,
+    base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  JSAutoRequest auto_request(context_);
+  JSAutoCompartment auto_compartment(context_, global_object_proxy_);
+  JSExceptionState* previous_exception_state = JS_SaveExceptionState(context_);
+  JS::RootedValue result_value(context_);
+  if (!EvaluateScriptInternal(source_code, &result_value)) {
+    return false;
+  }
+  if (out_opaque_handle) {
+    JS::RootedObject js_object(context_);
+    JS_ValueToObject(context_, result_value, js_object.address());
+    MozjsObjectHandleHolder mozjs_object_holder(js_object, context_,
+                                                wrapper_factory());
+    out_opaque_handle->emplace(owning_object.get(), mozjs_object_holder);
+  }
+  JS_RestoreExceptionState(context_, previous_exception_state);
+  return true;
+}
+
+bool MozjsGlobalEnvironment::EvaluateScriptInternal(
+    const scoped_refptr<SourceCode>& source_code,
+    JS::MutableHandleValue out_result) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(global_object_proxy_);
+  MozjsSourceCode* mozjs_source_code =
+      base::polymorphic_downcast<MozjsSourceCode*>(source_code.get());
+
+  const std::string& script = mozjs_source_code->source_utf8();
+  const base::SourceLocation location = mozjs_source_code->location();
+
+  JS::RootedObject global_object(
+      context_, js::GetProxyTargetObject(global_object_proxy_));
+
+  size_t length = script.size();
+  jschar* inflated_buffer =
+      js::InflateUTF8String(context_, script.c_str(), &length);
+  bool success = false;
+  if (inflated_buffer) {
+    success = JS_EvaluateUCScript(context_, global_object, inflated_buffer,
+                                  length, location.file_path.c_str(),
+                                  location.line_number, out_result.address());
+    js_free(inflated_buffer);
+  } else {
+    DLOG(ERROR) << "Malformed UTF-8 script.";
+  }
+
   return success;
 }
 
@@ -321,7 +357,7 @@
   if (global_object_proxy_ && garbage_collection_count_ == 1) {
     DCHECK(!opaque_root_state_);
     JSAutoRequest auto_request(context_);
-    JSAutoCompartment auto_comparment(context_, global_object_proxy_);
+    JSAutoCompartment auto_compartment(context_, global_object_proxy_);
     // Get the current state of opaque root relationships. Keep this object
     // alive for the duration of the GC phase to ensure that reachability
     // between roots and reachable objects is maintained.
diff --git a/src/cobalt/script/mozjs/mozjs_global_environment.h b/src/cobalt/script/mozjs/mozjs_global_environment.h
index 54f75de..d13d7f0 100644
--- a/src/cobalt/script/mozjs/mozjs_global_environment.h
+++ b/src/cobalt/script/mozjs/mozjs_global_environment.h
@@ -56,10 +56,7 @@
   bool EvaluateScript(const scoped_refptr<SourceCode>& script_utf8,
                       const scoped_refptr<Wrappable>& owning_object,
                       base::optional<OpaqueHandleHolder::Reference>*
-                          out_opaque_handle) OVERRIDE {
-    NOTIMPLEMENTED();
-    return false;
-  }
+                          out_opaque_handle) OVERRIDE;
 
   std::vector<StackFrame> GetStackTrace(int max_frames = 0) OVERRIDE;
 
@@ -133,7 +130,10 @@
   // with an error that eval() is disabled.
   static JSBool CheckEval(JSContext* context);
 
- protected:
+ private:
+  bool EvaluateScriptInternal(const scoped_refptr<SourceCode>& source_code,
+                              JS::MutableHandleValue out_result);
+
   static void ReportErrorHandler(JSContext* context, const char* message,
                                  JSErrorReport* report);
 
diff --git a/src/glimp/entry_points/gles_2_0.cc b/src/glimp/entry_points/gles_2_0.cc
index 10391ca..884318a 100644
--- a/src/glimp/entry_points/gles_2_0.cc
+++ b/src/glimp/entry_points/gles_2_0.cc
@@ -281,7 +281,12 @@
 }
 
 void GL_APIENTRY glCullFace(GLenum mode) {
-  SB_NOTIMPLEMENTED();
+  gles::Context* context = GetCurrentContext();
+  if (!context) {
+    return;
+  }
+
+  return context->CullFace(mode);
 }
 
 void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers) {
diff --git a/src/glimp/gles/context.cc b/src/glimp/gles/context.cc
index a104230..2057fcb 100644
--- a/src/glimp/gles/context.cc
+++ b/src/glimp/gles/context.cc
@@ -21,6 +21,7 @@
 #include "glimp/egl/error.h"
 #include "glimp/egl/surface.h"
 #include "glimp/gles/blend_state.h"
+#include "glimp/gles/cull_face_state.h"
 #include "glimp/gles/draw_mode.h"
 #include "glimp/gles/index_data_type.h"
 #include "glimp/gles/pixel_format.h"
@@ -299,9 +300,13 @@
       draw_state_.scissor.enabled = true;
       draw_state_dirty_flags_.scissor_dirty = true;
       break;
+    case GL_CULL_FACE:
+      draw_state_.cull_face_state.enabled = true;
+      draw_state_.cull_face_state.mode = CullFaceState::kBack;
+      draw_state_dirty_flags_.cull_face_dirty = true;
+      break;
     case GL_DEPTH_TEST:
     case GL_DITHER:
-    case GL_CULL_FACE:
     case GL_STENCIL_TEST:
     case GL_POLYGON_OFFSET_FILL:
     case GL_SAMPLE_ALPHA_TO_COVERAGE:
@@ -323,9 +328,12 @@
       draw_state_.scissor.enabled = false;
       draw_state_dirty_flags_.scissor_dirty = true;
       break;
+    case GL_CULL_FACE:
+      draw_state_.cull_face_state.enabled = false;
+      draw_state_dirty_flags_.cull_face_dirty = true;
+      break;
     case GL_DEPTH_TEST:
     case GL_DITHER:
-    case GL_CULL_FACE:
     case GL_STENCIL_TEST:
     case GL_POLYGON_OFFSET_FILL:
     case GL_SAMPLE_ALPHA_TO_COVERAGE:
@@ -426,6 +434,31 @@
   draw_state_dirty_flags_.blend_state_dirty = true;
 }
 
+namespace {
+CullFaceState::Mode CullFaceModeFromEnum(GLenum mode) {
+  switch (mode) {
+    case GL_FRONT:
+      return CullFaceState::kFront;
+    case GL_BACK:
+      return CullFaceState::kBack;
+    case GL_FRONT_AND_BACK:
+      return CullFaceState::kFrontAndBack;
+    default:
+      return CullFaceState::kModeInvalid;
+  }
+}
+}  // namespace
+
+void Context::CullFace(GLenum mode) {
+  CullFaceState::Mode cull_face_mode = CullFaceModeFromEnum(mode);
+  if (cull_face_mode == CullFaceState::kModeInvalid) {
+    SetError(GL_INVALID_ENUM);
+    return;
+  }
+  draw_state_.cull_face_state.mode = cull_face_mode;
+  draw_state_dirty_flags_.cull_face_dirty = true;
+}
+
 GLuint Context::CreateProgram() {
   GLIMP_TRACE_EVENT0(__FUNCTION__);
   nb::scoped_ptr<ProgramImpl> program_impl = impl_->CreateProgram();
diff --git a/src/glimp/gles/context.h b/src/glimp/gles/context.h
index e028ed5..7d2d919 100644
--- a/src/glimp/gles/context.h
+++ b/src/glimp/gles/context.h
@@ -95,6 +95,8 @@
 
   void BlendFunc(GLenum sfactor, GLenum dfactor);
 
+  void CullFace(GLenum mode);
+
   GLuint CreateProgram();
   void DeleteProgram(GLuint program);
   void AttachShader(GLuint program, GLuint shader);
diff --git a/src/glimp/gles/cull_face_state.h b/src/glimp/gles/cull_face_state.h
new file mode 100644
index 0000000..b68d6b0
--- /dev/null
+++ b/src/glimp/gles/cull_face_state.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GLIMP_GLES_CULL_FACE_STATE_H_
+#define GLIMP_GLES_CULL_FACE_STATE_H_
+
+namespace glimp {
+namespace gles {
+
+// Describes GL cull face state, which can be modified via commands like
+// glCullFace().
+//   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCullFace.xml
+struct CullFaceState {
+  // When enabled, the initial face culling value should be kBack.
+  enum Mode {
+    kFront,
+    kBack,
+    kFrontAndBack,
+    kModeInvalid,
+  };
+
+  // Default state is face culling off.
+  CullFaceState() : enabled(false), mode(kBack) {}
+
+  Mode mode;
+  bool enabled;
+};
+
+}  // namespace gles
+}  // namespace glimp
+
+#endif  // GLIMP_GLES_CULL_FACE_STATE_H_
diff --git a/src/glimp/gles/draw_state.h b/src/glimp/gles/draw_state.h
index 96f5ec1..db9c2d9 100644
--- a/src/glimp/gles/draw_state.h
+++ b/src/glimp/gles/draw_state.h
@@ -24,6 +24,7 @@
 #include "glimp/egl/surface.h"
 #include "glimp/gles/blend_state.h"
 #include "glimp/gles/buffer.h"
+#include "glimp/gles/cull_face_state.h"
 #include "glimp/gles/framebuffer.h"
 #include "glimp/gles/program.h"
 #include "glimp/gles/sampler.h"
@@ -156,6 +157,9 @@
   // existing pixels in the output framebuffer.
   BlendState blend_state;
 
+  // Defines whether face culling is enabled, and upon which face if so.
+  CullFaceState cull_face_state;
+
   // The currently bound array buffer, set by calling
   // glBindBuffer(GL_ARRAY_BUFFER).
   nb::scoped_refptr<Buffer> array_buffer;
@@ -190,6 +194,7 @@
     scissor_dirty = true;
     viewport_dirty = true;
     blend_state_dirty = true;
+    cull_face_dirty = true;
     array_buffer_dirty = true;
     element_array_buffer_dirty = true;
     used_program_dirty = true;
@@ -205,6 +210,7 @@
   bool scissor_dirty;
   bool viewport_dirty;
   bool blend_state_dirty;
+  bool cull_face_dirty;
   bool array_buffer_dirty;
   bool element_array_buffer_dirty;
   bool used_program_dirty;
diff --git a/src/glimp/glimp_common.gypi b/src/glimp/glimp_common.gypi
index 4f00bfe..ef1a68c 100644
--- a/src/glimp/glimp_common.gypi
+++ b/src/glimp/glimp_common.gypi
@@ -45,6 +45,7 @@
     'gles/context_impl.h',
     'gles/convert_pixel_data.cc',
     'gles/convert_pixel_data.h',
+    'gles/cull_face_state.h',
     'gles/draw_mode.h',
     'gles/draw_state.cc',
     'gles/draw_state.h',
diff --git a/src/media/base/pipeline.h b/src/media/base/pipeline.h
index 3f5aaf6..0912c6b 100644
--- a/src/media/base/pipeline.h
+++ b/src/media/base/pipeline.h
@@ -51,7 +51,9 @@
 // playing.
 class MEDIA_EXPORT Pipeline : public base::RefCountedThreadSafe<Pipeline> {
  public:
-  typedef base::Callback<void(const gfx::Rect&)> SetBoundsCB;
+  // Return true if the punch through box should be rendered.  Return false if
+  // no punch through box should be rendered.
+  typedef base::Callback<bool(const gfx::Rect&)> SetBoundsCB;
 
   // Buffering states the pipeline transitions between during playback.
   // kHaveMetadata:
diff --git a/src/media/base/sbplayer_pipeline.cc b/src/media/base/sbplayer_pipeline.cc
index ead7b85..971f574 100644
--- a/src/media/base/sbplayer_pipeline.cc
+++ b/src/media/base/sbplayer_pipeline.cc
@@ -118,12 +118,13 @@
     base::Lock lock_;
     player_ = player;
   }
-  void SetBounds(const gfx::Rect& rect) {
+  bool SetBounds(const gfx::Rect& rect) {
     base::AutoLock auto_lock(lock_);
-    if (SbPlayerIsValid(player_)) {
-      SbPlayerSetBounds(player_, rect.x(), rect.y(), rect.width(),
-                        rect.height());
+    if (!SbPlayerIsValid(player_)) {
+      return false;
     }
+    SbPlayerSetBounds(player_, rect.x(), rect.y(), rect.width(), rect.height());
+    return true;
   }
 
  private:
@@ -725,7 +726,7 @@
 
   video_read_in_progress_ = false;
   if (buffer->IsEndOfStream()) {
-    SbPlayerWriteEndOfStream(player_, kSbMediaTypeAudio);
+    SbPlayerWriteEndOfStream(player_, kSbMediaTypeVideo);
     return;
   }
   SbMediaVideoSampleInfo video_info;
diff --git a/src/media/player/web_media_player.h b/src/media/player/web_media_player.h
index 77a9c0c..ef6b89a 100644
--- a/src/media/player/web_media_player.h
+++ b/src/media/player/web_media_player.h
@@ -32,7 +32,9 @@
 
 class WebMediaPlayer {
  public:
-  typedef base::Callback<void(const gfx::Rect&)> SetBoundsCB;
+  // Return true if the punch through box should be rendered.  Return false if
+  // no punch through box should be rendered.
+  typedef base::Callback<bool(const gfx::Rect&)> SetBoundsCB;
 
   enum NetworkState {
     kNetworkStateEmpty,
diff --git a/src/nb/allocator.h b/src/nb/allocator.h
index c5ddf7c..75ac4ed 100644
--- a/src/nb/allocator.h
+++ b/src/nb/allocator.h
@@ -42,14 +42,21 @@
   // Will return NULL if the allocation fails.
   virtual void* Allocate(std::size_t size, std::size_t alignment) = 0;
 
-  // Allocates a range of memory of the given size for the given alignment.
-  // Returns a pointer that may not be aligned but points to a memory area that
-  // is still large enough when the pointer is subsequently aligned to the given
-  // alignment. It can allocate up to size + alignment - 1 bytes. This allows a
-  // reuse allocator to use the padding area as a free block. Will return NULL
-  // if the allocation fails.
-  virtual void* AllocateForAlignment(std::size_t size,
-                                     std::size_t alignment) = 0;
+  // When supported, allocates a range of memory of the given size for the given
+  // alignment. Returns a pointer that may not be aligned but points to a memory
+  // area that is still large enough when the pointer is subsequently aligned to
+  // the given alignment. This allows a reuse allocator to use the padding area
+  // as a free block. |size| will be set to the actual size allocated on
+  // successful allocations. Will return NULL if the allocation fails. In the
+  // case that the underlying block size is inconvenient or impossible to be
+  // retreived, the |size| can remain unchanged for a successful allocation. The
+  // user may lose the ability to combine two adjacent allocations in this case.
+  // Note that the coding style recommends that in/out parameters to be placed
+  // after input parameters but |size| is kept in the left for consistency.
+  virtual void* AllocateForAlignment(std::size_t* /*size*/,
+                                     std::size_t /*alignment*/) {
+    return 0;
+  }
 
   // Frees memory previously allocated via any call to Allocate().
   virtual void Free(void* memory) = 0;
diff --git a/src/nb/allocator_decorator.cc b/src/nb/allocator_decorator.cc
index daa5320..18578b1 100644
--- a/src/nb/allocator_decorator.cc
+++ b/src/nb/allocator_decorator.cc
@@ -68,7 +68,7 @@
   return impl_->Allocate(size, alignment);
 }
 
-void* AllocatorDecorator::AllocateForAlignment(std::size_t size,
+void* AllocatorDecorator::AllocateForAlignment(std::size_t* size,
                                                std::size_t alignment) {
   ScopedLock scoped_lock(lock_);
   return impl_->AllocateForAlignment(size, alignment);
diff --git a/src/nb/allocator_decorator.h b/src/nb/allocator_decorator.h
index 13969ad..78a8407 100644
--- a/src/nb/allocator_decorator.h
+++ b/src/nb/allocator_decorator.h
@@ -34,7 +34,7 @@
 
   void* Allocate(std::size_t size);
   void* Allocate(std::size_t size, std::size_t alignment);
-  void* AllocateForAlignment(std::size_t size, std::size_t alignment);
+  void* AllocateForAlignment(std::size_t* size, std::size_t alignment);
   void Free(void* memory);
   std::size_t GetCapacity() const;
   std::size_t GetAllocated() const;
diff --git a/src/nb/fixed_no_free_allocator.cc b/src/nb/fixed_no_free_allocator.cc
index 3722da6..53a615f 100644
--- a/src/nb/fixed_no_free_allocator.cc
+++ b/src/nb/fixed_no_free_allocator.cc
@@ -27,28 +27,6 @@
   next_memory_ = memory_start_;
 }
 
-void* FixedNoFreeAllocator::Allocate(std::size_t size,
-                                     std::size_t alignment,
-                                     bool align_pointer) {
-  // Find the next aligned memory available.
-  uint8_t* aligned_next_memory =
-      AsPointer(AlignUp(AsInteger(next_memory_), alignment));
-
-  if (aligned_next_memory + size < aligned_next_memory) {
-    // "aligned_next_memory + size" overflows.
-    return NULL;
-  }
-
-  if (aligned_next_memory + size > memory_end_) {
-    // We don't have enough memory available to make this allocation.
-    return NULL;
-  }
-
-  void* memory_pointer = align_pointer ? aligned_next_memory : next_memory_;
-  next_memory_ = aligned_next_memory + size;
-  return memory_pointer;
-}
-
 void FixedNoFreeAllocator::Free(void* memory) {
   // Nothing to do here besides ensure that the freed memory belongs to us.
   SB_DCHECK(memory >= memory_start_);
@@ -67,4 +45,30 @@
   SB_NOTIMPLEMENTED();
 }
 
+void* FixedNoFreeAllocator::Allocate(std::size_t* size,
+                                     std::size_t alignment,
+                                     bool align_pointer) {
+  // Find the next aligned memory available.
+  uint8_t* aligned_next_memory =
+      AsPointer(AlignUp(AsInteger(next_memory_), alignment));
+
+  if (aligned_next_memory + *size < aligned_next_memory) {
+    // "aligned_next_memory + size" overflows.
+    return NULL;
+  }
+
+  if (aligned_next_memory + *size > memory_end_) {
+    // We don't have enough memory available to make this allocation.
+    return NULL;
+  }
+
+  if (!align_pointer) {
+    *size += AsInteger(aligned_next_memory) - AsInteger(next_memory_);
+  }
+
+  void* memory_pointer = align_pointer ? aligned_next_memory : next_memory_;
+  next_memory_ = aligned_next_memory + *size;
+  return memory_pointer;
+}
+
 }  // namespace nb
diff --git a/src/nb/fixed_no_free_allocator.h b/src/nb/fixed_no_free_allocator.h
index 696a7c0..31bfc60 100644
--- a/src/nb/fixed_no_free_allocator.h
+++ b/src/nb/fixed_no_free_allocator.h
@@ -37,22 +37,23 @@
 class FixedNoFreeAllocator : public Allocator {
  public:
   FixedNoFreeAllocator(void* memory_start, std::size_t memory_size);
-  void* Allocate(std::size_t size) { return Allocate(size, 1, true); }
+  void* Allocate(std::size_t size) { return Allocate(&size, 1, true); }
 
   void* Allocate(std::size_t size, std::size_t alignment) {
-    return Allocate(size, alignment, true);
+    return Allocate(&size, alignment, true);
   }
 
-  void* AllocateForAlignment(std::size_t size, std::size_t alignment) {
+  void* AllocateForAlignment(std::size_t* size, std::size_t alignment) {
     return Allocate(size, alignment, false);
   }
-  void* Allocate(std::size_t size, std::size_t alignment, bool align_pointer);
   void Free(void* memory);
   std::size_t GetCapacity() const;
   std::size_t GetAllocated() const;
   void PrintAllocations() const;
 
  private:
+  void* Allocate(std::size_t* size, std::size_t alignment, bool align_pointer);
+
   // The start of our memory range, as passed in to the constructor.
   void* const memory_start_;
 
diff --git a/src/nb/memory_pool.cc b/src/nb/memory_pool.cc
index 840042c..4ae9a7e 100644
--- a/src/nb/memory_pool.cc
+++ b/src/nb/memory_pool.cc
@@ -23,15 +23,21 @@
 MemoryPool::MemoryPool(void* buffer,
                        std::size_t size,
                        bool thread_safe,
-                       bool verify_full_capacity)
+                       bool verify_full_capacity,
+                       std::size_t small_allocation_threshold)
     : no_free_allocator_(buffer, size),
       reuse_allocator_(
-          scoped_ptr<Allocator>(new ReuseAllocator(&no_free_allocator_)),
+          scoped_ptr<Allocator>(new ReuseAllocator(&no_free_allocator_,
+                                                   size,
+                                                   small_allocation_threshold)),
           thread_safe) {
   SB_DCHECK(buffer);
   SB_DCHECK(size != 0U);
 
-  if (verify_full_capacity) {
+  // This is redundant if ReuseAllocator::Allcator() can allocate the difference
+  // between the requested size and the last free block from the fallback
+  // allocator and combine the blocks.
+  if (verify_full_capacity && small_allocation_threshold == 0) {
     void* p = Allocate(size);
     SB_DCHECK(p);
     Free(p);
diff --git a/src/nb/memory_pool.h b/src/nb/memory_pool.h
index cef03db..b81e893 100644
--- a/src/nb/memory_pool.h
+++ b/src/nb/memory_pool.h
@@ -29,30 +29,16 @@
 // as necessary.
 class MemoryPool : public Allocator {
  public:
-  // When |verify_full_capacity| is true, the ctor tries to allocate the whole
-  // budget and free it immediately.  This can:
-  // 1. Ensure the |size| is accurate after accounting for all implicit
-  //    alignment enforced by the underlying allocators.
-  // 2. The |reuse_allocator_| contains a free block of the whole budget.  As
-  //    the |reuse_allocator_| doesn't support extending of free block, an
-  //    allocation that is larger than the both biggest free block in the
-  //    |reuse_allocator_| and the remaining memory inside the
-  //    |no_free_allocator_| will fail even if the combination of both can
-  //    fulfill the allocation.
-  // Note that when |verify_full_capacity| is true, GetHighWaterMark() always
-  // return the budget, which makes memory usage tracking useless.
   MemoryPool(void* buffer,
              std::size_t size,
              bool thread_safe,
-             bool verify_full_capacity = false);
+             bool verify_full_capacity = false,
+             std::size_t small_allocation_threshold = 0);
 
   void* Allocate(std::size_t size) { return reuse_allocator_.Allocate(size); }
   void* Allocate(std::size_t size, std::size_t alignment) {
     return reuse_allocator_.Allocate(size, alignment);
   }
-  void* AllocateForAlignment(std::size_t size, std::size_t alignment) {
-    return reuse_allocator_.AllocateForAlignment(size, alignment);
-  }
   void Free(void* memory) { reuse_allocator_.Free(memory); }
   std::size_t GetCapacity() const { return reuse_allocator_.GetCapacity(); }
   std::size_t GetAllocated() const { return reuse_allocator_.GetAllocated(); }
diff --git a/src/nb/pointer_arithmetic.h b/src/nb/pointer_arithmetic.h
index 411308c..cb1539a 100644
--- a/src/nb/pointer_arithmetic.h
+++ b/src/nb/pointer_arithmetic.h
@@ -31,7 +31,7 @@
   return reinterpret_cast<uint8_t*>(integer_value);
 }
 
-// Helper method for subclasses to align addresses up to a specified value.
+// Helper method to align addresses up to a specified value.
 // Returns the the smallest value that is greater than or equal to value, but
 // aligned to alignment.
 template <typename T>
@@ -42,9 +42,20 @@
 
 template <typename T>
 T* AlignUp(T* value, uintptr_t alignment) {
-  uintptr_t decremented_value = AsInteger(value) - 1;
-  return reinterpret_cast<T*>(decremented_value + alignment -
-                              (decremented_value % alignment));
+  return reinterpret_cast<T*>(AlignUp(AsInteger(value), alignment));
+}
+
+// Helper method to align addresses down to a specified value.
+// Returns the the largest value that is less than or equal to value, but
+// aligned to alignment.
+template <typename T>
+T AlignDown(T value, T alignment) {
+  return value / alignment * alignment;
+}
+
+template <typename T>
+T* AlignDown(T* value, uintptr_t alignment) {
+  return reinterpret_cast<T*>(AlignDown(AsInteger(value), alignment));
 }
 
 // Helper method for subclasses to determine if a given address or value
diff --git a/src/nb/reuse_allocator.cc b/src/nb/reuse_allocator.cc
index 61a40a6..70898ae 100644
--- a/src/nb/reuse_allocator.cc
+++ b/src/nb/reuse_allocator.cc
@@ -24,10 +24,104 @@
 
 namespace nb {
 
-ReuseAllocator::ReuseAllocator(Allocator* fallback_allocator) {
-  fallback_allocator_ = fallback_allocator;
-  capacity_ = 0;
-  total_allocated_ = 0;
+// Minimum block size to avoid extremely small blocks inside the block list and
+// to ensure that a zero sized allocation will return a non-zero sized block.
+const std::size_t kMinBlockSizeBytes = 16;
+
+bool ReuseAllocator::MemoryBlock::Merge(const MemoryBlock& other) {
+  if (AsInteger(address_) + size_ == AsInteger(other.address_)) {
+    size_ += other.size_;
+    return true;
+  }
+  if (AsInteger(other.address_) + other.size_ == AsInteger(address_)) {
+    address_ = other.address_;
+    size_ += other.size_;
+    return true;
+  }
+  return false;
+}
+
+bool ReuseAllocator::MemoryBlock::CanFullfill(std::size_t request_size,
+                                              std::size_t alignment) const {
+  const std::size_t extra_bytes_for_alignment =
+      AlignUp(AsInteger(address_), alignment) - AsInteger(address_);
+  const std::size_t aligned_size = request_size + extra_bytes_for_alignment;
+  return size_ >= aligned_size;
+}
+
+void ReuseAllocator::MemoryBlock::Allocate(std::size_t request_size,
+                                           std::size_t alignment,
+                                           bool allocate_from_front,
+                                           MemoryBlock* allocated,
+                                           MemoryBlock* free) const {
+  SB_DCHECK(allocated);
+  SB_DCHECK(free);
+  SB_DCHECK(CanFullfill(request_size, alignment));
+
+  // First we assume that the block is just enough to fulfill the allocation and
+  // leaves no free block.
+  allocated->address_ = address_;
+  allocated->size_ = size_;
+  free->address_ = NULL;
+  free->size_ = 0;
+
+  if (allocate_from_front) {
+    // |address_|
+    //     |     <- allocated_size ->     | <- remaining_size -> |
+    //     -------------------------------------------------------
+    //          |   <-  request_size ->   |                      |
+    //  |aligned_address|       |end_of_allocation|      |address_ + size_|
+    std::size_t aligned_address = AlignUp(AsInteger(address_), alignment);
+    std::size_t end_of_allocation = aligned_address + request_size;
+    std::size_t allocated_size = end_of_allocation - AsInteger(address_);
+    std::size_t remaining_size = size_ - allocated_size;
+    if (remaining_size < kMinBlockSizeBytes) {
+      return;
+    }
+    allocated->size_ = allocated_size;
+    free->address_ = AsPointer(end_of_allocation);
+    free->size_ = remaining_size;
+  } else {
+    // |address_|
+    //     |   <- remaining_size ->  |   <- allocated_size ->    |
+    //     -------------------------------------------------------
+    //                               |  <-  request_size -> |    |
+    //                       |aligned_address|           |address_ + size_|
+    std::size_t aligned_address =
+        AlignDown(AsInteger(address_) + size_ - request_size, alignment);
+    std::size_t allocated_size = AsInteger(address_) + size_ - aligned_address;
+    std::size_t remaining_size = size_ - allocated_size;
+    if (remaining_size < kMinBlockSizeBytes) {
+      return;
+    }
+    allocated->address_ = AsPointer(aligned_address);
+    allocated->size_ = allocated_size;
+    free->address_ = address_;
+    free->size_ = remaining_size;
+  }
+}
+
+ReuseAllocator::ReuseAllocator(Allocator* fallback_allocator)
+    : fallback_allocator_(fallback_allocator),
+      small_allocation_threshold_(0),
+      capacity_(0),
+      total_allocated_(0) {}
+
+ReuseAllocator::ReuseAllocator(Allocator* fallback_allocator,
+                               std::size_t capacity,
+                               std::size_t small_allocation_threshold)
+    : fallback_allocator_(fallback_allocator),
+      small_allocation_threshold_(small_allocation_threshold),
+      capacity_(0),
+      total_allocated_(0) {
+  // If |small_allocation_threshold_| is non-zero, this class will use last-fit
+  // strategy to fulfill small allocations.  Pre-allocator full capacity so
+  // last-fit makes sense.
+  if (small_allocation_threshold_ > 0) {
+    void* p = Allocate(capacity, 1);
+    SB_DCHECK(p);
+    Free(p);
+  }
 }
 
 ReuseAllocator::~ReuseAllocator() {
@@ -44,18 +138,14 @@
   }
 }
 
-void ReuseAllocator::AddFreeBlock(void* address, std::size_t size) {
-  MemoryBlock new_block;
-  new_block.address = address;
-  new_block.size = size;
-
+ReuseAllocator::FreeBlockSet::iterator ReuseAllocator::AddFreeBlock(
+    MemoryBlock block_to_add) {
   if (free_blocks_.size() == 0) {
-    free_blocks_.insert(new_block);
-    return;
+    return free_blocks_.insert(block_to_add).first;
   }
 
   // See if we can merge this block with one on the right or left.
-  FreeBlockSet::iterator it = free_blocks_.lower_bound(new_block);
+  FreeBlockSet::iterator it = free_blocks_.lower_bound(block_to_add);
   // lower_bound will return an iterator to our neighbor on the right,
   // if one exists.
   FreeBlockSet::iterator right_to_erase = free_blocks_.end();
@@ -63,9 +153,7 @@
 
   if (it != free_blocks_.end()) {
     MemoryBlock right_block = *it;
-    if (AsInteger(new_block.address) + new_block.size ==
-        AsInteger(right_block.address)) {
-      new_block.size += right_block.size;
+    if (block_to_add.Merge(right_block)) {
       right_to_erase = it;
     }
   }
@@ -75,10 +163,7 @@
     it--;
     MemoryBlock left_block = *it;
     // Are we contiguous with the block to our left?
-    if (AsInteger(left_block.address) + left_block.size ==
-        AsInteger(new_block.address)) {
-      new_block.address = left_block.address;
-      new_block.size += left_block.size;
+    if (block_to_add.Merge(left_block)) {
       left_to_erase = it;
     }
   }
@@ -90,7 +175,7 @@
     free_blocks_.erase(left_to_erase);
   }
 
-  free_blocks_.insert(new_block);
+  return free_blocks_.insert(block_to_add).first;
 }
 
 void ReuseAllocator::RemoveFreeBlock(FreeBlockSet::iterator it) {
@@ -101,11 +186,6 @@
   return Allocate(size, 1);
 }
 
-void* ReuseAllocator::AllocateForAlignment(std::size_t size,
-                                           std::size_t alignment) {
-  return Allocate(size, alignment);
-}
-
 void* ReuseAllocator::Allocate(std::size_t size, std::size_t alignment) {
   if (alignment == 0) {
     alignment = 1;
@@ -113,15 +193,14 @@
 
   // Try to satisfy request from free list.
   // First look for a block that is appropriately aligned.
-  // If we can't, look for a block that is big enough that we can
-  // carve out an aligned block.
+  // If we can't, look for a block that is big enough that we can carve out an
+  // aligned block.
   // If there is no such block, allocate more from our fallback allocator.
   void* user_address = 0;
 
-  // Keeping things rounded and aligned will help us
-  // avoid creating tiny and/or badly misaligned free blocks.
-  // Also ensure even for a 0-byte request we return a unique block.
-  const std::size_t kMinBlockSizeBytes = 16;
+  // Keeping things rounded and aligned will help us avoid creating tiny and/or
+  // badly misaligned free blocks.  Also ensure even for a 0-byte request we
+  // return a unique block.
   const std::size_t kMinAlignment = 16;
   size = std::max(size, kMinBlockSizeBytes);
   size = AlignUp(size, kMinBlockSizeBytes);
@@ -130,68 +209,59 @@
   // Worst case how much memory we need.
   MemoryBlock allocated_block;
 
-  // Start looking through the free list.
-  // If this is slow, we can store another map sorted by size.
-  for (FreeBlockSet::iterator it = free_blocks_.begin();
-       it != free_blocks_.end(); ++it) {
-    MemoryBlock block = *it;
-    const std::size_t extra_bytes_for_alignment =
-        (alignment - AsInteger(block.address) % alignment) % alignment;
-    const std::size_t aligned_size = size + extra_bytes_for_alignment;
-    if (block.size >= aligned_size) {
-      // The block is big enough.  We may waste some space due to alignment.
-      RemoveFreeBlock(it);
-      const std::size_t remaining_bytes = block.size - aligned_size;
-      if (remaining_bytes >= kMinBlockSizeBytes) {
-        AddFreeBlock(AsPointer(AsInteger(block.address) + aligned_size),
-                     remaining_bytes);
-        allocated_block.size = aligned_size;
-      } else {
-        allocated_block.size = block.size;
+  bool scan_from_front = size > small_allocation_threshold_;
+  FreeBlockSet::iterator free_block_iter = free_blocks_.end();
+
+  if (scan_from_front) {
+    // Start looking through the free list from the front.
+    for (FreeBlockSet::iterator it = free_blocks_.begin();
+         it != free_blocks_.end(); ++it) {
+      if (it->CanFullfill(size, alignment)) {
+        free_block_iter = it;
+        break;
       }
-      user_address = AlignUp(block.address, alignment);
-      allocated_block.address = block.address;
-      SB_DCHECK(allocated_block.size <= block.size);
-      break;
+    }
+  } else {
+    // Start looking through the free list from the back.
+    for (FreeBlockSet::reverse_iterator it = free_blocks_.rbegin();
+         it != free_blocks_.rend(); ++it) {
+      if (it->CanFullfill(size, alignment)) {
+        free_block_iter = it.base();
+        --free_block_iter;
+        break;
+      }
     }
   }
 
-  if (user_address == 0) {
-    // No free blocks found.
-    // Allocate one from the fallback allocator.
-    size = AlignUp(size, alignment);
-    void* ptr = fallback_allocator_->AllocateForAlignment(size, alignment);
+  if (free_block_iter == free_blocks_.end()) {
+    // No free blocks found, allocate one from the fallback allocator.
+    std::size_t block_size = size;
+    void* ptr =
+        fallback_allocator_->AllocateForAlignment(&block_size, alignment);
     if (ptr == NULL) {
       return NULL;
     }
-    uint8_t* memory_address = reinterpret_cast<uint8_t*>(ptr);
-    user_address = AlignUp(memory_address, alignment);
-    allocated_block.size = size;
-    allocated_block.address = user_address;
-
-    if (memory_address != user_address) {
-      std::size_t alignment_padding_size =
-          AsInteger(user_address) - AsInteger(memory_address);
-      if (alignment_padding_size >= kMinBlockSizeBytes) {
-        // Register the memory range skipped for alignment as a free block for
-        // later use.
-        AddFreeBlock(memory_address, alignment_padding_size);
-        capacity_ += alignment_padding_size;
-      } else {
-        // The memory range skipped for alignment is too small for a free block.
-        // Adjust the allocated block to include the alignment padding.
-        allocated_block.size += alignment_padding_size;
-        allocated_block.address = AsPointer(AsInteger(allocated_block.address) -
-                                            alignment_padding_size);
-      }
-    }
-
-    capacity_ += allocated_block.size;
+    free_block_iter = AddFreeBlock(MemoryBlock(ptr, block_size));
+    capacity_ += block_size;
     fallback_allocations_.push_back(ptr);
   }
+
+  MemoryBlock block = *free_block_iter;
+  // The block is big enough.  We may waste some space due to alignment.
+  RemoveFreeBlock(free_block_iter);
+
+  MemoryBlock free_block;
+  block.Allocate(size, alignment, scan_from_front, &allocated_block,
+                 &free_block);
+  if (free_block.size() > 0) {
+    SB_DCHECK(free_block.address());
+    AddFreeBlock(free_block);
+  }
+  user_address = AlignUp(allocated_block.address(), alignment);
+
   SB_DCHECK(allocated_blocks_.find(user_address) == allocated_blocks_.end());
   allocated_blocks_[user_address] = allocated_block;
-  total_allocated_ += allocated_block.size;
+  total_allocated_ += allocated_block.size();
   return user_address;
 }
 
@@ -205,10 +275,10 @@
 
   // Mark this block as free and remove it from the allocated set.
   const MemoryBlock& block = (*it).second;
-  AddFreeBlock(block.address, block.size);
+  AddFreeBlock(block);
 
-  SB_DCHECK(block.size <= total_allocated_);
-  total_allocated_ -= block.size;
+  SB_DCHECK(block.size() <= total_allocated_);
+  total_allocated_ -= block.size();
 
   allocated_blocks_.erase(it);
 }
@@ -218,7 +288,7 @@
   SizesHistogram sizes_histogram;
   for (AllocatedBlockMap::const_iterator iter = allocated_blocks_.begin();
        iter != allocated_blocks_.end(); ++iter) {
-    std::size_t block_size = iter->second.size;
+    std::size_t block_size = iter->second.size();
     if (sizes_histogram.find(block_size) == sizes_histogram.end()) {
       sizes_histogram[block_size] = 0;
     }
diff --git a/src/nb/reuse_allocator.h b/src/nb/reuse_allocator.h
index 6f4f16a..7686930 100644
--- a/src/nb/reuse_allocator.h
+++ b/src/nb/reuse_allocator.h
@@ -30,16 +30,32 @@
 // maintaining all allocation meta data is outside of the allocated memory.
 // It is passed a fallback allocator that it can request additional memory
 // from as needed.
+// The default allocation strategy for the allocator is first-fit, i.e. it will
+// scan for free blocks sorted by addresses and allocate from the first free
+// block that can fulfill the allocation.  However, in some situations the
+// majority of the allocations can be small ones with some large allocations.
+// This may cause serious fragmentations and the failure of large allocations.
+// If |small_allocation_threshold| in the ctor is set to a non-zero value, the
+// class will allocate small allocations whose sizes are less than or equal to
+// the threshold using last-fit, i.e. it will scan from the back to the front
+// for free blocks.  This way the allocation for large blocks and small blocks
+// are separated thus cause much less fragmentations.
 class ReuseAllocator : public Allocator {
  public:
   explicit ReuseAllocator(Allocator* fallback_allocator);
+  // When |small_allocation_threshold| is non-zero, this class will allocate
+  // its full capacity from the |fallback_allocator| in the ctor so it is
+  // possible for the class to use the last-fit allocation strategy.  See the
+  // class comment above for more details.
+  ReuseAllocator(Allocator* fallback_allocator,
+                 std::size_t capacity,
+                 std::size_t small_allocation_threshold);
   virtual ~ReuseAllocator();
 
   // Search free memory blocks for an existing one, and if none are large
   // enough, allocate a new one from no-free memory and return that.
   void* Allocate(std::size_t size);
   void* Allocate(std::size_t size, std::size_t alignment);
-  void* AllocateForAlignment(std::size_t size, std::size_t alignment);
 
   // Marks the memory block as being free and it will then become recyclable
   void Free(void* memory);
@@ -50,29 +66,67 @@
   void PrintAllocations() const;
 
  private:
-  // We will allocate from the given allocator whenever we can't find
-  // pre-used memory to allocate.
-  Allocator* fallback_allocator_;
+  class MemoryBlock {
+   public:
+    MemoryBlock() : address_(0), size_(0) {}
+    MemoryBlock(void* address, std::size_t size)
+        : address_(address), size_(size) {}
 
-  struct MemoryBlock {
-    void* address;
-    std::size_t size;
+    void* address() const { return address_; }
+    std::size_t size() const { return size_; }
+
+    void set_address(void* address) { address_ = address; }
+    void set_size(std::size_t size) { size_ = size; }
+
     bool operator<(const MemoryBlock& other) const {
-      return address < other.address;
+      return address_ < other.address_;
     }
+    // If the current block and |other| can be combined into a continuous memory
+    // block, store the conmbined block in the current block and return true.
+    // Otherwise return false.
+    bool Merge(const MemoryBlock& other);
+    // Return true if the current block can be used to fulfill an allocation
+    // with the given size and alignment.
+    bool CanFullfill(std::size_t request_size, std::size_t alignment) const;
+    // Allocate a block from this block with the given size and alignment.
+    // Store the allocated block in |allocated|.  If the rest space is large
+    // enough to form a block, it will be stored into |free|.  Otherwise the
+    // whole block is stored into |allocated|.
+    // Note that the call of this function has to ensure that CanFulfill() is
+    // already called on this block and returns true.
+    void Allocate(std::size_t request_size,
+                  std::size_t alignment,
+                  bool allocate_from_front,
+                  MemoryBlock* allocated,
+                  MemoryBlock* free) const;
+
+   private:
+    void* address_;
+    std::size_t size_;
   };
+
   // Freelist sorted by address.
   typedef std::set<MemoryBlock> FreeBlockSet;
   // Map from pointers we returned to the user, back to memory blocks.
   typedef std::map<void*, MemoryBlock> AllocatedBlockMap;
-  void AddFreeBlock(void* address, std::size_t size);
-  void RemoveFreeBlock(FreeBlockSet::iterator);
+
+  FreeBlockSet::iterator AddFreeBlock(MemoryBlock block_to_add);
+  void RemoveFreeBlock(FreeBlockSet::iterator it);
 
   FreeBlockSet free_blocks_;
   AllocatedBlockMap allocated_blocks_;
 
-  // A list of allocations made from the fallback allocator.  We keep track
-  // of this so that we can free them all upon our destruction.
+  // We will allocate from the given allocator whenever we can't find pre-used
+  // memory to allocate.
+  Allocator* fallback_allocator_;
+
+  // Any allocations with size less than or equal to the following threshold
+  // will be allocated from the back of the pool.  See the comment of the class
+  // for more details.
+  std::size_t small_allocation_threshold_;
+
+  // A list of allocations made from the fallback allocator.  We keep track of
+  // this so that we can free them all upon our destruction.
   std::vector<void*> fallback_allocations_;
 
   // How much we have allocated from the fallback allocator.
diff --git a/src/nb/reuse_allocator_benchmark.cc b/src/nb/reuse_allocator_benchmark.cc
index 4117d5c..5e48ba7 100644
--- a/src/nb/reuse_allocator_benchmark.cc
+++ b/src/nb/reuse_allocator_benchmark.cc
@@ -177,17 +177,14 @@
 
 class DefaultAllocator : public nb::Allocator {
  public:
-  void* Allocate(std::size_t size) { return Allocate(size, 0); }
-  void* Allocate(std::size_t size, std::size_t alignment) {
+  void* Allocate(std::size_t size) SB_OVERRIDE { return Allocate(size, 0); }
+  void* Allocate(std::size_t size, std::size_t alignment) SB_OVERRIDE {
     return SbMemoryAllocateAligned(alignment, size);
   }
-  void* AllocateForAlignment(std::size_t size, std::size_t alignment) {
-    return SbMemoryAllocateAligned(alignment, size);
-  }
-  void Free(void* memory) { SbMemoryFree(memory); }
-  std::size_t GetCapacity() const { return 0; }
-  std::size_t GetAllocated() const { return 0; }
-  void PrintAllocations() const {}
+  void Free(void* memory) SB_OVERRIDE { SbMemoryFree(memory); }
+  std::size_t GetCapacity() const SB_OVERRIDE { return 0; }
+  std::size_t GetAllocated() const SB_OVERRIDE { return 0; }
+  void PrintAllocations() const SB_OVERRIDE {}
 };
 
 void MemoryPlaybackTest(const std::string& filename) {
diff --git a/src/nb/reuse_allocator_test.cc b/src/nb/reuse_allocator_test.cc
index 658c81a..4d42361 100644
--- a/src/nb/reuse_allocator_test.cc
+++ b/src/nb/reuse_allocator_test.cc
@@ -18,6 +18,7 @@
 
 #include "nb/fixed_no_free_allocator.h"
 #include "nb/scoped_ptr.h"
+#include "starboard/configuration.h"
 #include "starboard/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -32,14 +33,21 @@
  public:
   static const int kBufferSize = 1 * 1024 * 1024;
 
-  ReuseAllocatorTest() {
+  ReuseAllocatorTest() { ResetAllocator(0); }
+
+ protected:
+  void ResetAllocator(size_t small_allocation_threshold) {
     buffer_.reset(new uint8_t[kBufferSize]);
     fallback_allocator_.reset(
         new nb::FixedNoFreeAllocator(buffer_.get(), kBufferSize));
-    allocator_.reset(new nb::ReuseAllocator(fallback_allocator_.get()));
+    if (small_allocation_threshold == 0) {
+      allocator_.reset(new nb::ReuseAllocator(fallback_allocator_.get()));
+    } else {
+      allocator_.reset(new nb::ReuseAllocator(
+          fallback_allocator_.get(), kBufferSize, small_allocation_threshold));
+    }
   }
 
- protected:
   nb::scoped_array<uint8_t> buffer_;
   nb::scoped_ptr<nb::FixedNoFreeAllocator> fallback_allocator_;
   nb::scoped_ptr<nb::ReuseAllocator> allocator_;
@@ -99,3 +107,32 @@
   allocator_->Free(test_p);
   allocator_->Free(blocks[0]);
 }
+
+TEST_F(ReuseAllocatorTest, SmallAlloc) {
+  // Recreate allocator with small allocation threshold to 256.
+  ResetAllocator(256);
+
+  const std::size_t kBlockSizes[] = {117, 193, 509, 1111};
+  const std::size_t kAlignment = 16;
+  void* blocks[] = {NULL, NULL, NULL, NULL};
+  for (int i = 0; i < SB_ARRAY_SIZE(kBlockSizes); ++i) {
+    blocks[i] = allocator_->Allocate(kBlockSizes[i], kAlignment);
+  }
+  // The two small allocs should be in the back in reverse order.
+  EXPECT_GT(reinterpret_cast<uintptr_t>(blocks[0]),
+            reinterpret_cast<uintptr_t>(blocks[1]));
+  // Small allocs should has higher address than other allocs.
+  EXPECT_GT(reinterpret_cast<uintptr_t>(blocks[1]),
+            reinterpret_cast<uintptr_t>(blocks[3]));
+  // Non-small allocs are allocated from the front and the first one has the
+  // lowest address.
+  EXPECT_LT(reinterpret_cast<uintptr_t>(blocks[2]),
+            reinterpret_cast<uintptr_t>(blocks[3]));
+  for (int i = 0; i < SB_ARRAY_SIZE(kBlockSizes); ++i) {
+    allocator_->Free(blocks[i]);
+  }
+  // Should have one single free block equals to the capacity.
+  void* test_p = allocator_->Allocate(allocator_->GetCapacity());
+  EXPECT_TRUE(test_p != NULL);
+  allocator_->Free(test_p);
+}
diff --git a/src/starboard/event.h b/src/starboard/event.h
index c602259..cec1884 100644
--- a/src/starboard/event.h
+++ b/src/starboard/event.h
@@ -26,6 +26,43 @@
 extern "C" {
 #endif
 
+// The Starboard Application life cycle
+// ------------------------------------
+//
+//           *
+//           |                      _________________________
+//         Start                   |                         |
+//           |                     |                       Resume
+//           V                     V                         |
+//      [ STARTED ] --Pause--> [ PAUSED ] --Suspend--> [ SUSPENDED ]
+//           ^                     |                         |
+//           |                  Unpause                     Stop
+//           |_____________________|                         |
+//                                                           V
+//                                                      [ STOPPED ]
+//
+// The first event that a Starboard application will receive is Start
+// (kSbEventTypeStart). This puts the application in the STARTED state; it is in
+// the foreground and can expect to do all the normal things it might want to
+// do. Once in the STARTED state, it may receive a Pause event, putting the
+// application into the PAUSED state.
+//
+// In the PAUSED state, the application is still visible, but has lost focus, or
+// it is partially obscured by a modal dialog, or it is on its way to being shut
+// down. The application should pause activity in this state. In this state, it
+// can receive Unpause to be brought back to the foreground state, STARTED, or
+// Suspend to be pushed further in the background to the SUSPENDED state.
+//
+// In the SUSPENDED state, the application is generally not visible. It should
+// immediately release all graphics and video resources, and shut down all
+// background activity (timers, rendering, etc). Additionally, the application
+// should flush storage to ensure that if the application is killed, the storage
+// will be up-to-date. The application may be killed at this point, but will
+// ideally receive a Stop event for a more graceful shutdown.
+//
+// Note that the application is always expected to transition through PAUSED to
+// SUSPENDED before receiving Stop or being killed.
+
 // An enumeration of all possible event types dispatched directly by the
 // system. Each event is accompanied by a void* data argument, and each event
 // must define the type of the value pointed to by that data argument, if any.
@@ -33,28 +70,43 @@
   // The first event that an application receives on startup. Applications
   // should perform initialization and prepare to react to subsequent events.
   // Applications that wish to run and then exit must call SbSystemRequestStop()
-  // to terminate. SbEventStartData is passed as the data argument.
+  // to terminate. This event will only be sent once for a given process launch.
+  // SbEventStartData is passed as the data argument.
   kSbEventTypeStart,
 
-  // The operating system will put the application into a suspended state after
-  // this event is handled. This is an opportunity for the application to
-  // partially tear down and release some resources. Some platforms will
-  // terminate the application if work is done while suspended. Can only be
+  // A dialog will be raised or the application will otherwise be put into a
+  // background-but-visible or partially-obscured state (PAUSED). Graphics and
+  // video resources will still be available, but the application should pause
+  // foreground activity like animations and video playback. Can only be
   // received after a Start event. The only events that should be dispatched
-  // after a Suspend event are Resume or Stop. No data argument.
+  // after a Pause event are Unpause or Suspend. No data argument.
+  kSbEventTypePause,
+
+  // The application is returning to the foreground (STARTED) after having been
+  // put in the PAUSED (e.g. partially-obscured) state. The application should
+  // unpause foreground activity like animations and video playback. Can only be
+  // received after a Pause or Resume event. No data argument.
+  kSbEventTypeUnpause,
+
+  // The operating system will put the application into a Suspended state after
+  // this event is handled. The application is expected to stop periodic
+  // background work, release ALL graphics and video resources, and flush any
+  // pending SbStorage writes. Some platforms will terminate the application if
+  // work is done or resources are retained after suspension. Can only be
+  // received after a Pause event. The only events that should be dispatched
+  // after a Suspend event are Resume or Stop. On some platforms, the process
+  // may also be killed after Suspend without a Stop event. No data argument.
   kSbEventTypeSuspend,
 
-  // The operating system has restored the application to normal execution after
-  // a Pause event. This is the first even the application will receive coming
-  // out of Pause, and it will only be received immediately after a Pause event.
-  // No data argument.
+  // The operating system has restored the application to the PAUSED state from
+  // the SUSPENDED state. This is the first event the application will receive
+  // coming out of SUSPENDED, and it will only be received after a Suspend
+  // event. The application will now be in the PAUSED state. No data argument.
   kSbEventTypeResume,
 
   // The operating system will shut the application down entirely after this
-  // event is handled. This is an opportunity for the application to save any
-  // state that it wishes to before its process space is revoked. Can only be
-  // recieved after a Start event. May be received after a Pause event. No data
-  // argument.
+  // event is handled. Can only be recieved after a Suspend event, in the
+  // SUSPENDED state. No data argument.
   kSbEventTypeStop,
 
   // A user input event, including keyboard, mouse, gesture, or something else.
diff --git a/src/starboard/linux/x64directfb/main.cc b/src/starboard/linux/x64directfb/main.cc
index f6d023a..2a7616c 100644
--- a/src/starboard/linux/x64directfb/main.cc
+++ b/src/starboard/linux/x64directfb/main.cc
@@ -17,11 +17,15 @@
 #include "starboard/configuration.h"
 #include "starboard/shared/directfb/application_directfb.h"
 #include "starboard/shared/signal/crash_signals.h"
+#include "starboard/shared/signal/suspend_signals.h"
 
 int main(int argc, char** argv) {
   tzset();
   starboard::shared::signal::InstallCrashSignalHandlers();
+  starboard::shared::signal::InstallSuspendSignalHandlers();
   starboard::ApplicationDirectFB application;
   int result = application.Run(argc, argv);
+  starboard::shared::signal::UninstallSuspendSignalHandlers();
+  starboard::shared::signal::UninstallCrashSignalHandlers();
   return result;
 }
diff --git a/src/starboard/linux/x64directfb/starboard_platform.gyp b/src/starboard/linux/x64directfb/starboard_platform.gyp
index 25c0476..cca05bb 100644
--- a/src/starboard/linux/x64directfb/starboard_platform.gyp
+++ b/src/starboard/linux/x64directfb/starboard_platform.gyp
@@ -236,6 +236,8 @@
         '<(DEPTH)/starboard/shared/pthread/thread_yield.cc',
         '<(DEPTH)/starboard/shared/signal/crash_signals_sigaction.cc',
         '<(DEPTH)/starboard/shared/signal/crash_signals.h',
+        '<(DEPTH)/starboard/shared/signal/suspend_signals.cc',
+        '<(DEPTH)/starboard/shared/signal/suspend_signals.h',
         '<(DEPTH)/starboard/shared/starboard/application.cc',
         '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc',
         '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_destroy.cc',
diff --git a/src/starboard/linux/x64x11/main.cc b/src/starboard/linux/x64x11/main.cc
index 1331c05..7feb245 100644
--- a/src/starboard/linux/x64x11/main.cc
+++ b/src/starboard/linux/x64x11/main.cc
@@ -16,12 +16,16 @@
 
 #include "starboard/configuration.h"
 #include "starboard/shared/signal/crash_signals.h"
+#include "starboard/shared/signal/suspend_signals.h"
 #include "starboard/shared/x11/application_x11.h"
 
 int main(int argc, char** argv) {
   tzset();
   starboard::shared::signal::InstallCrashSignalHandlers();
+  starboard::shared::signal::InstallSuspendSignalHandlers();
   starboard::shared::x11::ApplicationX11 application;
   int result = application.Run(argc, argv);
+  starboard::shared::signal::UninstallSuspendSignalHandlers();
+  starboard::shared::signal::UninstallCrashSignalHandlers();
   return result;
 }
diff --git a/src/starboard/linux/x64x11/starboard_platform.gyp b/src/starboard/linux/x64x11/starboard_platform.gyp
index 65712a4..6276a96 100644
--- a/src/starboard/linux/x64x11/starboard_platform.gyp
+++ b/src/starboard/linux/x64x11/starboard_platform.gyp
@@ -199,6 +199,8 @@
         '<(DEPTH)/starboard/shared/pthread/thread_yield.cc',
         '<(DEPTH)/starboard/shared/signal/crash_signals.h',
         '<(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/starboard/application.cc',
         '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc',
         '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_destroy.cc',
diff --git a/src/starboard/nplb/memory_set_test.cc b/src/starboard/nplb/memory_set_test.cc
index 2a647b4..0874104 100644
--- a/src/starboard/nplb/memory_set_test.cc
+++ b/src/starboard/nplb/memory_set_test.cc
@@ -31,7 +31,7 @@
   void* result = SbMemorySet(memory, 0xCD, kSize);
   EXPECT_EQ(memory, result);
   for (int i = 0; i < kSize; ++i) {
-    EXPECT_EQ(data[i], '\xCD');
+    ASSERT_EQ('\xCD', data[i]);
   }
 
   SbMemoryFree(memory);
@@ -47,7 +47,7 @@
   void* result = SbMemorySet(memory, 0xCD, 0);
   EXPECT_EQ(memory, result);
   for (int i = 0; i < kSize; ++i) {
-    EXPECT_EQ(data[i], static_cast<char>(i));
+    ASSERT_EQ(static_cast<char>(i), data[i]);
   }
 
   SbMemoryFree(memory);
@@ -63,7 +63,7 @@
   void* result = SbMemorySet(memory, 0x6789ABCD, kSize);
   EXPECT_EQ(memory, result);
   for (int i = 0; i < kSize; ++i) {
-    EXPECT_EQ(data[i], '\xCD');
+    ASSERT_EQ('\xCD', data[i]);
   }
 
   SbMemoryFree(memory);
diff --git a/src/starboard/nplb/system_get_property_test.cc b/src/starboard/nplb/system_get_property_test.cc
index 52c348b..de94895 100644
--- a/src/starboard/nplb/system_get_property_test.cc
+++ b/src/starboard/nplb/system_get_property_test.cc
@@ -74,7 +74,7 @@
   if (IsCEDevice(SbSystemGetDeviceType())) {
     BasicTest(kSbSystemPropertyBrandName, true, true, __LINE__);
     BasicTest(kSbSystemPropertyModelName, true, true, __LINE__);
-    BasicTest(kSbSystemPropertyModelYear, true, true, __LINE__);
+    BasicTest(kSbSystemPropertyModelYear, false, true, __LINE__);
   } else {
     BasicTest(kSbSystemPropertyBrandName, false, true, __LINE__);
     BasicTest(kSbSystemPropertyModelName, false, true, __LINE__);
diff --git a/src/starboard/nplb/thread_yield_test.cc b/src/starboard/nplb/thread_yield_test.cc
index c6a07d1..17a4ed5 100644
--- a/src/starboard/nplb/thread_yield_test.cc
+++ b/src/starboard/nplb/thread_yield_test.cc
@@ -65,11 +65,11 @@
 // thread gets started first, I hope to make this inherently flaky test not
 // flaky.
 //
-// Note: This test ended up EVER so slightly flaky, but within most
-// tolerances. If it fails on you randomly and inconsistently, it was probably
-// just a flake.
-TEST(SbThreadYieldTest, FLAKY_SunnyDayRace) {
-  const int kTrials = 30;
+// Note: This test may still be flaky, but it should be a lot less flaky than
+// before. If this test starts flaking again, tag it with FLAKY_ again.
+TEST(SbThreadYieldTest, SunnyDayRace) {
+  const int kTrials = 20;
+  int passes = 0;
   for (int trial = 0; trial < kTrials; ++trial) {
     // Pin to CPU 0 to make sure the threads don't get distributed onto other
     // cores.
@@ -106,8 +106,15 @@
       }
     }
 
-    EXPECT_LT(average_unyielder, average_yielder) << "Trial " << trial;
+    // If unyielders took less time then yielders, on average, then we consider
+    // the trial a pass.
+    if (average_unyielder < average_yielder) {
+      ++passes;
+    }
   }
+
+  // We expect at least 2/3 of the trials to pass.
+  EXPECT_LT(kTrials * 2 / 3, passes);
 }
 
 }  // namespace
diff --git a/src/starboard/raspi/1/starboard_platform.gyp b/src/starboard/raspi/1/starboard_platform.gyp
index d5b6b23..f22110b 100644
--- a/src/starboard/raspi/1/starboard_platform.gyp
+++ b/src/starboard/raspi/1/starboard_platform.gyp
@@ -206,6 +206,8 @@
         '<(DEPTH)/starboard/shared/pthread/thread_yield.cc',
         '<(DEPTH)/starboard/shared/signal/crash_signals.cc',
         '<(DEPTH)/starboard/shared/signal/crash_signals.h',
+        '<(DEPTH)/starboard/shared/signal/suspend_signals.cc',
+        '<(DEPTH)/starboard/shared/signal/suspend_signals.h',
         '<(DEPTH)/starboard/shared/starboard/application.cc',
         '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc',
         '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_destroy.cc',
diff --git a/src/starboard/raspi/shared/main.cc b/src/starboard/raspi/shared/main.cc
index 1745d23..737c678 100644
--- a/src/starboard/raspi/shared/main.cc
+++ b/src/starboard/raspi/shared/main.cc
@@ -17,11 +17,15 @@
 #include "starboard/configuration.h"
 #include "starboard/raspi/shared/application_dispmanx.h"
 #include "starboard/shared/signal/crash_signals.h"
+#include "starboard/shared/signal/suspend_signals.h"
 
 int main(int argc, char** argv) {
   tzset();
   starboard::shared::signal::InstallCrashSignalHandlers();
+  starboard::shared::signal::InstallSuspendSignalHandlers();
   starboard::raspi::shared::ApplicationDispmanx application;
   int result = application.Run(argc, argv);
+  starboard::shared::signal::UninstallSuspendSignalHandlers();
+  starboard::shared::signal::UninstallCrashSignalHandlers();
   return result;
 }
diff --git a/src/starboard/shared/signal/crash_signals.cc b/src/starboard/shared/signal/crash_signals.cc
index 5c20870..a3e9b2e 100644
--- a/src/starboard/shared/signal/crash_signals.cc
+++ b/src/starboard/shared/signal/crash_signals.cc
@@ -18,6 +18,7 @@
 
 #include "starboard/configuration.h"
 #include "starboard/log.h"
+#include "starboard/shared/signal/signal_internal.h"
 #include "starboard/system.h"
 
 namespace starboard {
@@ -26,48 +27,44 @@
 
 namespace {
 
-const int kSignalsToTrap[] = {
-    SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV,
+const int kCrashSignalsToTrap[] = {
+    SIGABRT, SIGFPE, SIGILL, SIGSEGV,
 };
 
-const char* GetSignalName(int signal_id) {
-  switch (signal_id) {
-    case SIGABRT:
-      return "SIGABRT";
-    case SIGFPE:
-      return "SIGFPE";
-    case SIGILL:
-      return "SIGILL";
-    case SIGINT:
-      return "SIGINT";
-    case SIGSEGV:
-      return "SIGSEGV";
-    default:
-      return "UNKNOWN SIGNAL";
-  }
-}
+const int kStopSignalsToTrap[] = {
+    SIGTERM, SIGINT,
+};
 
 void DumpStackSignalSafe(int signal_id) {
-  const char* signal_name = GetSignalName(signal_id);
-  SbLogRawFormatF("\nCaught signal: %s (%d)\n", signal_name, signal_id);
-  SbLogFlush();
+  LogSignalCaught(signal_id);
   SbLogRawDumpStack(1);
 
   UninstallCrashSignalHandlers();
   SbSystemBreakIntoDebugger();
 }
 
+void Stop(int signal_id) {
+  LogSignalCaught(signal_id);
+  SbSystemRequestStop(0);
+}
+
 }  // namespace
 
 void InstallCrashSignalHandlers() {
-  for (int i = 0; i < SB_ARRAY_SIZE_INT(kSignalsToTrap); ++i) {
-    ::signal(kSignalsToTrap[i], &DumpStackSignalSafe);
+  for (int i = 0; i < SB_ARRAY_SIZE_INT(kCrashSignalsToTrap); ++i) {
+    ::signal(kCrashSignalsToTrap[i], &DumpStackSignalSafe);
+  }
+  for (int i = 0; i < SB_ARRAY_SIZE_INT(kStopSignalsToTrap); ++i) {
+    ::signal(kStopSignalsToTrap[i], &Stop);
   }
 }
 
 void UninstallCrashSignalHandlers() {
-  for (int i = 0; i < SB_ARRAY_SIZE_INT(kSignalsToTrap); ++i) {
-    ::signal(kSignalsToTrap[i], SIG_DFL);
+  for (int i = 0; i < SB_ARRAY_SIZE_INT(kCrashSignalsToTrap); ++i) {
+    ::signal(kCrashSignalsToTrap[i], SIG_DFL);
+  }
+  for (int i = 0; i < SB_ARRAY_SIZE_INT(kStopSignalsToTrap); ++i) {
+    ::signal(kStopSignalsToTrap[i], SIG_DFL);
   }
 }
 
diff --git a/src/starboard/shared/signal/crash_signals_sigaction.cc b/src/starboard/shared/signal/crash_signals_sigaction.cc
index 735e506..4bf5b59 100644
--- a/src/starboard/shared/signal/crash_signals_sigaction.cc
+++ b/src/starboard/shared/signal/crash_signals_sigaction.cc
@@ -18,7 +18,7 @@
 
 #include "starboard/configuration.h"
 #include "starboard/log.h"
-#include "starboard/memory.h"
+#include "starboard/shared/signal/signal_internal.h"
 #include "starboard/system.h"
 
 namespace starboard {
@@ -27,42 +27,26 @@
 
 namespace {
 
-const int kSignalsToTrap[] = {
-    SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV,
+const int kCrashSignalsToTrap[] = {
+    SIGABRT, SIGFPE, SIGILL, SIGSEGV,
 };
 
-const char* GetSignalName(int signal_id) {
-  switch (signal_id) {
-    case SIGABRT:
-      return "SIGABRT";
-    case SIGFPE:
-      return "SIGFPE";
-    case SIGILL:
-      return "SIGILL";
-    case SIGINT:
-      return "SIGINT";
-    case SIGSEGV:
-      return "SIGSEGV";
-    default:
-      return "UNKNOWN SIGNAL";
-  }
-}
-
-typedef void (*SignalHandlerFunction)(int);
+const int kStopSignalsToTrap[] = {
+    SIGTERM, SIGINT,
+};
 
 void SetSignalHandler(int signal_id, SignalHandlerFunction handler) {
-    struct sigaction action = {0};
+  struct sigaction action = {0};
 
-    action.sa_handler = handler;
-    action.sa_flags = 0;
-    ::sigemptyset(&action.sa_mask);
+  action.sa_handler = handler;
+  action.sa_flags = 0;
+  ::sigemptyset(&action.sa_mask);
 
-    ::sigaction(signal_id, &action, NULL);
+  ::sigaction(signal_id, &action, NULL);
 }
 
 void DumpStackSignalSafe(int signal_id) {
-  const char* signal_name = GetSignalName(signal_id);
-  SbLogRawFormatF("\nCaught signal: %s (%d)\n", signal_name, signal_id);
+  LogSignalCaught(signal_id);
   SbLogFlush();
   SbLogRawDumpStack(1);
 
@@ -70,17 +54,28 @@
   SbSystemBreakIntoDebugger();
 }
 
+void Stop(int signal_id) {
+  LogSignalCaught(signal_id);
+  SbSystemRequestStop(0);
+}
+
 }  // namespace
 
 void InstallCrashSignalHandlers() {
-  for (int i = 0; i < SB_ARRAY_SIZE_INT(kSignalsToTrap); ++i) {
-    SetSignalHandler(kSignalsToTrap[i], &DumpStackSignalSafe);
+  for (int i = 0; i < SB_ARRAY_SIZE_INT(kCrashSignalsToTrap); ++i) {
+    SetSignalHandler(kCrashSignalsToTrap[i], &DumpStackSignalSafe);
+  }
+  for (int i = 0; i < SB_ARRAY_SIZE_INT(kStopSignalsToTrap); ++i) {
+    SetSignalHandler(kStopSignalsToTrap[i], &Stop);
   }
 }
 
 void UninstallCrashSignalHandlers() {
-  for (int i = 0; i < SB_ARRAY_SIZE_INT(kSignalsToTrap); ++i) {
-    SetSignalHandler(kSignalsToTrap[i], SIG_DFL);
+  for (int i = 0; i < SB_ARRAY_SIZE_INT(kCrashSignalsToTrap); ++i) {
+    SetSignalHandler(kCrashSignalsToTrap[i], SIG_DFL);
+  }
+  for (int i = 0; i < SB_ARRAY_SIZE_INT(kStopSignalsToTrap); ++i) {
+    SetSignalHandler(kStopSignalsToTrap[i], SIG_DFL);
   }
 }
 
diff --git a/src/starboard/shared/signal/signal_internal.h b/src/starboard/shared/signal/signal_internal.h
new file mode 100644
index 0000000..f511ab0
--- /dev/null
+++ b/src/starboard/shared/signal/signal_internal.h
@@ -0,0 +1,62 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_SIGNAL_SIGNAL_INTERNAL_H_
+#define STARBOARD_SHARED_SIGNAL_SIGNAL_INTERNAL_H_
+
+#include <signal.h>
+
+#include "starboard/log.h"
+#include "starboard/shared/internal_only.h"
+
+namespace starboard {
+namespace shared {
+namespace signal {
+
+inline const char* GetSignalName(int signal_id) {
+  switch (signal_id) {
+    case SIGABRT:
+      return "SIGABRT";
+    case SIGCONT:
+      return "SIGCONT";
+    case SIGFPE:
+      return "SIGFPE";
+    case SIGILL:
+      return "SIGILL";
+    case SIGINT:
+      return "SIGINT";
+    case SIGSEGV:
+      return "SIGSEGV";
+    case SIGTSTP:
+      return "SIGTSTP";
+    case SIGTERM:
+      return "SIGTERM";
+    default:
+      return "UNKNOWN SIGNAL";
+  }
+}
+
+inline void LogSignalCaught(int signal_id) {
+  const char* signal_name = GetSignalName(signal_id);
+  SbLogRawFormatF("\nCaught signal: %s (%d)\n", signal_name, signal_id);
+  SbLogFlush();
+}
+
+typedef void (*SignalHandlerFunction)(int);
+
+}  // namespace signal
+}  // namespace shared
+}  // namespace starboard
+
+#endif  // STARBOARD_SHARED_SIGNAL_SIGNAL_INTERNAL_H_
diff --git a/src/starboard/shared/signal/suspend_signals.cc b/src/starboard/shared/signal/suspend_signals.cc
new file mode 100644
index 0000000..0ea0f09
--- /dev/null
+++ b/src/starboard/shared/signal/suspend_signals.cc
@@ -0,0 +1,73 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/signal/suspend_signals.h"
+
+#include <signal.h>
+
+#include "starboard/configuration.h"
+#include "starboard/log.h"
+#include "starboard/memory.h"
+#include "starboard/shared/signal/signal_internal.h"
+#include "starboard/shared/starboard/application.h"
+#include "starboard/system.h"
+
+namespace starboard {
+namespace shared {
+namespace signal {
+
+namespace {
+
+void SetSignalHandler(int signal_id, SignalHandlerFunction handler) {
+  struct sigaction action = {0};
+
+  action.sa_handler = handler;
+  action.sa_flags = 0;
+  ::sigemptyset(&action.sa_mask);
+
+  ::sigaction(signal_id, &action, NULL);
+}
+
+void SuspendDone(void* /*context*/) {
+  SetSignalHandler(SIGTSTP, SIG_DFL);
+  raise(SIGTSTP);
+}
+
+void Suspend(int signal_id) {
+  LogSignalCaught(signal_id);
+  starboard::Application::Get()->Suspend(NULL, &SuspendDone);
+}
+
+void Resume(int signal_id) {
+  LogSignalCaught(signal_id);
+  SetSignalHandler(SIGTSTP, &Suspend);
+  // TODO: Resume or Unpause based on state.
+  starboard::Application::Get()->Unpause(NULL, NULL);
+}
+
+}  // namespace
+
+void InstallSuspendSignalHandlers() {
+  SetSignalHandler(SIGTSTP, &Suspend);
+  SetSignalHandler(SIGCONT, &Resume);
+}
+
+void UninstallSuspendSignalHandlers() {
+  SetSignalHandler(SIGTSTP, SIG_DFL);
+  SetSignalHandler(SIGCONT, SIG_DFL);
+}
+
+}  // namespace signal
+}  // namespace shared
+}  // namespace starboard
diff --git a/src/starboard/shared/signal/suspend_signals.h b/src/starboard/shared/signal/suspend_signals.h
new file mode 100644
index 0000000..730f8ad
--- /dev/null
+++ b/src/starboard/shared/signal/suspend_signals.h
@@ -0,0 +1,31 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_SIGNAL_SUSPEND_SIGNALS_H_
+#define STARBOARD_SHARED_SIGNAL_SUSPEND_SIGNALS_H_
+
+#include "starboard/shared/internal_only.h"
+
+namespace starboard {
+namespace shared {
+namespace signal {
+
+void InstallSuspendSignalHandlers();
+void UninstallSuspendSignalHandlers();
+
+}  // namespace signal
+}  // namespace shared
+}  // namespace starboard
+
+#endif  // STARBOARD_SHARED_SIGNAL_SUSPEND_SIGNALS_H_
diff --git a/src/starboard/shared/starboard/application.cc b/src/starboard/shared/starboard/application.cc
index b7ca314..26e08db 100644
--- a/src/starboard/shared/starboard/application.cc
+++ b/src/starboard/shared/starboard/application.cc
@@ -35,7 +35,7 @@
   event.type = type;
   event.data = data;
   SbEventHandle(&event);
-  if (destructor && event.data) {
+  if (destructor) {
     destructor(event.data);
   }
 }
@@ -57,7 +57,10 @@
 Application* Application::g_instance = NULL;
 
 Application::Application()
-    : error_level_(0), thread_(SbThreadGetCurrent()), start_link_(NULL) {
+    : error_level_(0),
+      thread_(SbThreadGetCurrent()),
+      start_link_(NULL),
+      state_(kStateUnstarted) {
   Application* old_instance =
       reinterpret_cast<Application*>(SbAtomicAcquire_CompareAndSwapPtr(
           reinterpret_cast<SbAtomicPtr*>(&g_instance),
@@ -80,6 +83,7 @@
 int Application::Run(int argc, char** argv) {
   Initialize();
   DispatchStart(argc, argv, start_link_);
+  state_ = kStateStarted;
 
   for (;;) {
     if (!DispatchAndDelete(GetNextEvent())) {
@@ -91,6 +95,22 @@
   return error_level_;
 }
 
+void Application::Pause(void* context, EventHandledCallback callback) {
+  Inject(new Event(kSbEventTypePause, context, callback));
+}
+
+void Application::Unpause(void* context, EventHandledCallback callback) {
+  Inject(new Event(kSbEventTypeUnpause, context, callback));
+}
+
+void Application::Suspend(void* context, EventHandledCallback callback) {
+  Inject(new Event(kSbEventTypeSuspend, context, callback));
+}
+
+void Application::Resume(void* context, EventHandledCallback callback) {
+  Inject(new Event(kSbEventTypeResume, context, callback));
+}
+
 void Application::Stop(int error_level) {
   Event* event = new Event(kSbEventTypeStop, NULL, NULL);
   event->error_level = error_level;
@@ -134,18 +154,100 @@
     return true;
   }
 
-  bool should_continue = true;
-  if (event->event->type == kSbEventTypeStop) {
-    should_continue = false;
-    error_level_ = event->error_level;
+  // Ensure that we go through the the appropriate lifecycle events based on the
+  // current state.
+  switch (event->event->type) {
+    case kSbEventTypePause:
+      if (state() != kStateStarted) {
+        delete event;
+        return true;
+      }
+      break;
+    case kSbEventTypeUnpause:
+      if (state() == kStateStarted) {
+        delete event;
+        return true;
+      }
+
+      if (state() == kStateSuspended) {
+        Inject(new Event(kSbEventTypeResume, NULL, NULL));
+        Inject(event);
+        return true;
+      }
+      break;
+    case kSbEventTypeSuspend:
+      if (state() == kStateSuspended) {
+        delete event;
+        return true;
+      }
+
+      if (state() == kStateStarted) {
+        Inject(new Event(kSbEventTypePause, NULL, NULL));
+        Inject(event);
+        return true;
+      }
+      break;
+    case kSbEventTypeResume:
+      if (state() == kStateStarted || state() == kStatePaused) {
+        delete event;
+        return true;
+      }
+      break;
+    case kSbEventTypeStop:
+      if (state() == kStateStarted) {
+        Inject(new Event(kSbEventTypePause, NULL, NULL));
+        Inject(new Event(kSbEventTypeSuspend, NULL, NULL));
+        Inject(event);
+        return true;
+      }
+
+      if (state() == kStatePaused) {
+        Inject(new Event(kSbEventTypeSuspend, NULL, NULL));
+        Inject(event);
+        return true;
+      }
+      error_level_ = event->error_level;
+      break;
+    case kSbEventTypeScheduled: {
+      TimedEvent* timed_event =
+          reinterpret_cast<TimedEvent*>(event->event->data);
+      timed_event->callback(timed_event->context);
+      delete event;
+      return true;
+    }
+    default:
+      break;
   }
 
-  if (event->event->type == kSbEventTypeScheduled) {
-    TimedEvent* timed_event = reinterpret_cast<TimedEvent*>(event->event->data);
-    timed_event->callback(timed_event->context);
-  } else {
-    SbEventHandle(event->event);
+  SbEventHandle(event->event);
+
+  bool should_continue = true;
+  switch (event->event->type) {
+    case kSbEventTypePause:
+      SB_DCHECK(state() == kStateStarted);
+      state_ = kStatePaused;
+      break;
+    case kSbEventTypeUnpause:
+      SB_DCHECK(state() == kStatePaused);
+      state_ = kStateStarted;
+      break;
+    case kSbEventTypeSuspend:
+      SB_DCHECK(state() == kStatePaused);
+      state_ = kStateSuspended;
+      break;
+    case kSbEventTypeResume:
+      SB_DCHECK(state() == kStateSuspended);
+      state_ = kStatePaused;
+      break;
+    case kSbEventTypeStop:
+      SB_DCHECK(state() == kStateSuspended);
+      state_ = kStateStopped;
+      should_continue = false;
+      break;
+    default:
+      break;
   }
+
   delete event;
   return should_continue;
 }
diff --git a/src/starboard/shared/starboard/application.h b/src/starboard/shared/starboard/application.h
index 2c990a0..7328f2e 100644
--- a/src/starboard/shared/starboard/application.h
+++ b/src/starboard/shared/starboard/application.h
@@ -38,6 +38,32 @@
 // dispatching events to the Starboard event handler, SbEventHandle.
 class Application {
  public:
+  // You can use a void(void *) function to signal that a state-transition event
+  // has completed.
+  typedef SbEventDataDestructor EventHandledCallback;
+
+  // Enumeration of states that the application can be in.
+  enum State {
+    // The initial Unstarted state.
+    kStateUnstarted,
+
+    // The normal foreground, fully-visible state after receiving the initial
+    // START event or after UNPAUSE from Paused.
+    kStateStarted,
+
+    // The background-but-visible or partially-obscured state after receiving an
+    // PAUSE event from Started or RESUME event from Suspended.
+    kStatePaused,
+
+    // The fully-obscured or about-to-be-terminated state after receiving a
+    // SUSPEND event in Paused.
+    kStateSuspended,
+
+    // The completely terminated state after receiving the STOP event in the
+    // Suspended state.
+    kStateStopped,
+  };
+
   // Structure to keep track of scheduled events, also used as the data argument
   // for kSbEventTypeScheduled Events.
   struct TimedEvent {
@@ -75,8 +101,6 @@
   // deleting the event and calling the destructor on its data when it is
   // deleted.
   struct Event {
-    Event(SbEvent* event, SbEventDataDestructor destructor)
-        : event(event), destructor(destructor), error_level(0) {}
     Event(SbEventType type, void* data, SbEventDataDestructor destructor)
         : event(new SbEvent()), destructor(destructor), error_level(0) {
       event->type = type;
@@ -90,7 +114,7 @@
       event->data = data;
     }
     ~Event() {
-      if (destructor && event->data) {
+      if (destructor) {
         destructor(event->data);
       }
       if (event) {
@@ -120,8 +144,45 @@
   // initialization and teardown events. Returns the resulting error level.
   int Run(int argc, char** argv);
 
+  // Signals that the application should transition from STARTED to PAUSED as
+  // soon as possible. Does nothing if already PAUSED or SUSPENDED. May be
+  // called from an external thread.
+  //
+  // |context|: A context value to pass to |callback| on event completion. Must
+  // not be NULL if callback is not NULL.
+  // |callback|: A function to call on event completion, from the main thread.
+  void Pause(void* context, EventHandledCallback callback);
+
+  // Signals that the application should transition to STARTED as soon as
+  // possible, moving through all required state transitions to get there. Does
+  // nothing if already STARTED. May be called from an external thread.
+  //
+  // |context|: A context value to pass to |callback| on event completion. Must
+  // not be NULL if callback is not NULL.
+  // |callback|: A function to call on event completion, from the main thread.
+  void Unpause(void* context, EventHandledCallback callback);
+
+  // Signals that the application should transition to SUSPENDED as soon as
+  // possible, moving through all required state transitions to get there. Does
+  // nothing if already SUSPENDED. May be called from an external thread.
+  //
+  // |context|: A context value to pass to |callback| on event completion. Must
+  // not be NULL if callback is not NULL.
+  // |callback|: A function to call on event completion, from the main thread.
+  void Suspend(void* context, EventHandledCallback callback);
+
+  // Signals that the application should transition to PAUSED from SUSPENDED as
+  // soon as possible. Does nothing if already PAUSED or STARTED. May be called
+  // from an external thread.
+  //
+  // |context|: A context value to pass to |callback| on event completion. Must
+  // not be NULL if callback is not NULL.
+  // |callback|: A function to call on event completion, from the main thread.
+  void Resume(void* context, EventHandledCallback callback);
+
   // Signals that the application should gracefully terminate as soon as
-  // possible. May be called from an external thread.
+  // possible. Will transition through PAUSED and SUSPENDED to STOPPED as
+  // appropriate for the current state. May be called from an external thread.
   void Stop(int error_level);
 
   // Schedules an event into the event queue.  May be called from an external
@@ -199,10 +260,14 @@
   // event that initializes and starts Cobalt.
   void SetStartLink(const char* start_link);
 
+  // Returns whether the current thread is the Application thread.
   bool IsCurrentThread() const {
     return SbThreadIsEqual(thread_, SbThreadGetCurrent());
   }
 
+  // Returns the current application state.
+  State state() const { return state_; }
+
  private:
   // Dispatches |event| to the system event handler, taking ownership of the
   // event. Returns whether to keep servicing the event queue, i.e. false means
@@ -222,6 +287,10 @@
   // The deep link included in the Start event sent to Cobalt. Initially NULL,
   // derived classes may set it during initialization using |SetStartLink|.
   char* start_link_;
+
+  // The current state that the application is in based on what events it has
+  // actually processed. Should only be accessed on the main thread.
+  State state_;
 };
 
 }  // namespace starboard
diff --git a/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc b/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc
index 09b2402..cd88dd8 100644
--- a/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc
+++ b/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc
@@ -106,7 +106,7 @@
                                &is_playing, &is_eos_reached, context_);
     if (is_playing) {
       int frames_to_consume =
-          std::min(kMaxFramesToConsumePerRequest, frames_in_buffer / 2);
+          std::min(kMaxFramesToConsumePerRequest, frames_in_buffer);
 
       SbThreadSleep(frames_to_consume * kSbTimeSecond / sampling_frequency_hz_);
       consume_frame_func_(frames_to_consume, context_);
diff --git a/src/starboard/shared/starboard/queue_application.h b/src/starboard/shared/starboard/queue_application.h
index fa5ac0e..b48d8a7 100644
--- a/src/starboard/shared/starboard/queue_application.h
+++ b/src/starboard/shared/starboard/queue_application.h
@@ -54,10 +54,13 @@
   virtual bool MayHaveSystemEvents() = 0;
 
   // Returns an event if one exists, otherwise returns NULL.
-  virtual Event* PollNextSystemEvent() = 0;
+  virtual Event* PollNextSystemEvent() {
+    return WaitForSystemEventWithTimeout(SbTime());
+  }
 
   // Waits for an event until the timeout |time| runs out.  If an event occurs
-  // in this time, it is returned, otherwise NULL is returned.
+  // in this time, it is returned, otherwise NULL is returned. If |time| is zero
+  // or negative, then this should function effectively like a no-wait poll.
   virtual Event* WaitForSystemEventWithTimeout(SbTime time) = 0;
 
   // Wakes up any thread waiting within a call to
@@ -65,6 +68,20 @@
   virtual void WakeSystemEventWait() = 0;
 
  private:
+  // Specialization of Queue for starboard events.  It differs in that it has
+  // the responsibility of deleting heap allocated starboard events in its
+  // destructor.  Note the non-virtual destructor, which is intentional and
+  // safe, as Queue has no virtual functions and EventQueue is never used
+  // polymorphically.
+  class EventQueue : public Queue<Event*> {
+   public:
+    ~EventQueue() {
+      while (Event* event = Poll()) {
+        delete event;
+      }
+    }
+  };
+
   class TimedEventQueue {
    public:
     TimedEventQueue();
@@ -99,7 +116,7 @@
   TimedEventQueue timed_event_queue_;
 
   // The queue of events that have not yet been dispatched.
-  Queue<Event*> event_queue_;
+  EventQueue event_queue_;
 };
 
 }  // namespace starboard
diff --git a/src/starboard/shared/stub/player_set_volume.cc b/src/starboard/shared/stub/player_set_volume.cc
new file mode 100644
index 0000000..5a45e91
--- /dev/null
+++ b/src/starboard/shared/stub/player_set_volume.cc
@@ -0,0 +1,17 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/player.h"
+
+void SbPlayerSetVolume(SbPlayer /*player*/, double /*volume*/) {}
diff --git a/src/starboard/shared/x11/application_x11.cc b/src/starboard/shared/x11/application_x11.cc
index bfde70b..1457e73 100644
--- a/src/starboard/shared/x11/application_x11.cc
+++ b/src/starboard/shared/x11/application_x11.cc
@@ -556,23 +556,18 @@
   return key_modifiers;
 }
 
-bool XNextEventPoll(Display* display, XEvent* out_event) {
-  if (XPending(display) == 0) {
-    return false;
-  }
-
-  XNextEvent(display, out_event);
-  return true;
-}
-
 bool XNextEventTimed(Display* display, XEvent* out_event, SbTime duration) {
   if (XPending(display) == 0) {
+    if (duration <= SbTime()) {
+      return false;
+    }
+
     int fd = ConnectionNumber(display);
     fd_set read_set;
     FD_ZERO(&read_set);
     FD_SET(fd, &read_set);
     struct timeval tv;
-    SbTime clamped_duration = std::max(duration, (SbTime)0);
+    SbTime clamped_duration = std::max(duration, SbTime());
     ToTimevalDuration(clamped_duration, &tv);
     if (select(fd + 1, &read_set, NULL, NULL, &tv) == 0) {
       return false;
@@ -762,20 +757,10 @@
   return display_;
 }
 
-shared::starboard::Application::Event* ApplicationX11::PollNextSystemEvent() {
-  SB_DCHECK(display_);
-
-  XEvent x_event;
-
-  if (XNextEventPoll(display_, &x_event)) {
-    return XEventToEvent(&x_event);
-  }
-
-  return NULL;
-}
-
 shared::starboard::Application::Event*
 ApplicationX11::WaitForSystemEventWithTimeout(SbTime time) {
+  SB_DCHECK(display_);
+
   XEvent x_event;
 
   if (XNextEventTimed(display_, &x_event, time)) {
@@ -878,6 +863,18 @@
     data->key_location = XKeyEventToSbKeyLocation(x_key_event);
     data->key_modifiers = XKeyEventToSbKeyModifiers(x_key_event);
     return new Event(kSbEventTypeInput, data, &DeleteDestructor<SbInputData>);
+  } else if (x_event->type == FocusIn) {
+    Unpause(NULL, NULL);
+    return NULL;
+  } else if (x_event->type == FocusOut) {
+    Pause(NULL, NULL);
+    return NULL;
+  } else if (x_event->type == MapNotify) {
+    Resume(NULL, NULL);
+    return NULL;
+  } else if (x_event->type == UnmapNotify) {
+    Suspend(NULL, NULL);
+    return NULL;
   }
 
   SB_DLOG(INFO) << "Unrecognized event type = " << x_event->type;
diff --git a/src/starboard/shared/x11/application_x11.h b/src/starboard/shared/x11/application_x11.h
index 11b4aca..8bd9940 100644
--- a/src/starboard/shared/x11/application_x11.h
+++ b/src/starboard/shared/x11/application_x11.h
@@ -63,7 +63,6 @@
 
   // --- QueueApplication overrides ---
   bool MayHaveSystemEvents() SB_OVERRIDE;
-  Event* PollNextSystemEvent() SB_OVERRIDE;
   Event* WaitForSystemEventWithTimeout(SbTime time) SB_OVERRIDE;
   void WakeSystemEventWait() SB_OVERRIDE;
 
diff --git a/src/starboard/shared/x11/window_internal.cc b/src/starboard/shared/x11/window_internal.cc
index 3885bf6..b17082a 100644
--- a/src/starboard/shared/x11/window_internal.cc
+++ b/src/starboard/shared/x11/window_internal.cc
@@ -78,7 +78,8 @@
   }
 
   XSetWindowAttributes swa = {0};
-  swa.event_mask = KeyPressMask | KeyReleaseMask | StructureNotifyMask;
+  swa.event_mask =
+      KeyPressMask | KeyReleaseMask | StructureNotifyMask | FocusChangeMask;
   swa.colormap =
       XCreateColormap(display, root_window, x_visual_info.visual, AllocNone);
   // Setting border_pixel to 0 is required if the requested window depth (e.g.
diff --git a/src/starboard/stub/starboard_platform.gyp b/src/starboard/stub/starboard_platform.gyp
index 1ac0c82..707fecd 100644
--- a/src/starboard/stub/starboard_platform.gyp
+++ b/src/starboard/stub/starboard_platform.gyp
@@ -109,6 +109,7 @@
         '<(DEPTH)/starboard/shared/stub/player_seek.cc',
         '<(DEPTH)/starboard/shared/stub/player_set_bounds.cc',
         '<(DEPTH)/starboard/shared/stub/player_set_pause.cc',
+        '<(DEPTH)/starboard/shared/stub/player_set_volume.cc',
         '<(DEPTH)/starboard/shared/stub/player_write_end_of_stream.cc',
         '<(DEPTH)/starboard/shared/stub/player_write_sample.cc',
         '<(DEPTH)/starboard/shared/stub/socket_accept.cc',
diff --git a/src/third_party/mozjs/cobalt_config/include/jscustomallocator.h b/src/third_party/mozjs/cobalt_config/include/jscustomallocator.h
index b8d70d1..4dcd88e 100644
--- a/src/third_party/mozjs/cobalt_config/include/jscustomallocator.h
+++ b/src/third_party/mozjs/cobalt_config/include/jscustomallocator.h
@@ -12,7 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#ifndef gc_JSCUSTOMALLOCATOR_H
+#define gc_JSCUSTOMALLOCATOR_H
+
+#include <algorithm>
+
 #include "jstypes.h"
+#include "memory_allocator_reporter.h"
 #include "starboard/memory.h"
 #include "starboard/string.h"
 
@@ -20,25 +26,58 @@
 #define JS_OOM_POSSIBLY_FAIL_REPORT(cx) do {} while(0)
 
 static JS_INLINE void* js_malloc(size_t bytes) {
-  return SbMemoryAllocate(bytes);
-}
-
-static JS_INLINE void* js_calloc(size_t bytes) {
-  return SbMemoryCalloc(bytes, 1);
+  size_t reservation_bytes = AllocationMetadata::GetReservationBytes(bytes);
+  MemoryAllocatorReporter::Get()->UpdateAllocatedBytes(reservation_bytes);
+  void* metadata = SbMemoryAllocate(reservation_bytes);
+  AllocationMetadata::SetSizeToBaseAddress(metadata, reservation_bytes);
+  return AllocationMetadata::GetUserAddressFromBaseAddress(metadata);
 }
 
 static JS_INLINE void* js_calloc(size_t nmemb, size_t size) {
-  return SbMemoryCalloc(nmemb, size);
+  size_t total_size = nmemb * size;
+  void* memory = js_malloc(total_size);
+  if (memory) {
+    SbMemorySet(memory, 0, total_size);
+  }
+  return memory;
 }
 
-static JS_INLINE void* js_realloc(void* p, size_t bytes) {
-  return SbMemoryReallocate(p, bytes);
+static JS_INLINE void* js_calloc(size_t bytes) {
+  return js_calloc(bytes, 1);
 }
 
 static JS_INLINE void js_free(void* p) {
-  SbMemoryFree(p);
+  if (p == NULL) {
+    return;
+  }
+
+  AllocationMetadata* metadata =
+      AllocationMetadata::GetMetadataFromUserAddress(p);
+  MemoryAllocatorReporter::Get()->UpdateAllocatedBytes(-static_cast<ssize_t>(
+      AllocationMetadata::GetSizeOfAllocationFromMetadata(metadata)));
+  SbMemoryFree(metadata);
+}
+
+static JS_INLINE void* js_realloc(void* p, size_t bytes) {
+  AllocationMetadata* metadata =
+      AllocationMetadata::GetMetadataFromUserAddress(p);
+  size_t current_size =
+      AllocationMetadata::GetSizeOfAllocationFromMetadata(metadata);
+  size_t adjusted_size = AllocationMetadata::GetReservationBytes(bytes);
+
+  MemoryAllocatorReporter::Get()->UpdateAllocatedBytes(
+      static_cast<ssize_t>(adjusted_size - current_size));
+  void* new_ptr = SbMemoryReallocate(metadata, adjusted_size);
+  AllocationMetadata::SetSizeToBaseAddress(new_ptr, adjusted_size);
+  return AllocationMetadata::GetUserAddressFromBaseAddress(new_ptr);
 }
 
 static JS_INLINE char* js_strdup(char* s) {
-  return SbStringDuplicate(s);
+  size_t length = SbStringGetLength(s) + 1;
+
+  char* new_ptr = reinterpret_cast<char*>(js_malloc(length));
+  SbStringCopy(new_ptr, s, length);
+  return new_ptr;
 }
+
+#endif /* gc_JSCUSTOMALLOCATOR_H */
diff --git a/src/third_party/mozjs/js/src/gc/Memory.cpp b/src/third_party/mozjs/js/src/gc/Memory.cpp
index b9e5199..9c55ba1 100644
--- a/src/third_party/mozjs/js/src/gc/Memory.cpp
+++ b/src/third_party/mozjs/js/src/gc/Memory.cpp
@@ -7,6 +7,7 @@
 #include "gc/Memory.h"
 
 #include "jscntxt.h"
+#include "memory_allocator_reporter.h"
 
 #include "js/HeapAPI.h"
 
@@ -324,13 +325,23 @@
     JS_ASSERT(flags == 0);
     JS_ASSERT(fd == -1);
     JS_ASSERT(offset == 0);
-    return SbMemoryMap(length, prot, "mozjs::gc::MapMemory");
+
+    void* result = SbMemoryMap(length, prot, "mozjs::gc::MapMemory");
+    if (result != SB_MEMORY_MAP_FAILED) {
+      MemoryAllocatorReporter::Get()->UpdateMappedBytes(length);
+    }
+    return result;
 }
 
 static inline bool
 UnmapMemory(void* region, size_t length)
 {
-    return SbMemoryUnmap(region, length);
+    bool success = SbMemoryUnmap(region, length);
+    if (success) {
+      MemoryAllocatorReporter::Get()->UpdateMappedBytes(
+          -static_cast<ssize_t>(length));
+    }
+    return success;
 }
 #else
 
diff --git a/src/third_party/mozjs/js/src/jsstarboard-time.cpp b/src/third_party/mozjs/js/src/jsstarboard-time.cpp
index d5049e2..92d309b 100644
--- a/src/third_party/mozjs/js/src/jsstarboard-time.cpp
+++ b/src/third_party/mozjs/js/src/jsstarboard-time.cpp
@@ -15,8 +15,11 @@
 #include "jsstarboard-time.h"
 
 #include "mozilla/Assertions.h"
+#include "starboard/configuration.h"
 #include "unicode/timezone.h"
 
+// If the Starboard platform has this quirk, do not use these functions.
+#if !SB_HAS_QUIRK(NO_TIMEZONE_NAME_SUPPORT)
 SbTime getDSTOffset(int64_t utc_time_us) {
   // UDate is in milliseconds from the epoch.
   UDate udate = utc_time_us / kSbTimeMillisecond;
@@ -41,4 +44,4 @@
   delete current_zone;
   return raw_offset_ms * kSbTimeMillisecond;
 }
-
+#endif
diff --git a/src/third_party/mozjs/js/src/jsutil.cpp b/src/third_party/mozjs/js/src/jsutil.cpp
index bd3e182..142f724 100644
--- a/src/third_party/mozjs/js/src/jsutil.cpp
+++ b/src/third_party/mozjs/js/src/jsutil.cpp
@@ -41,32 +41,6 @@
     js_free(addr);
 }
 
-class Compressor
-{
-    /* Number of bytes we should hand to zlib each compressMore() call. */
-    static const size_t CHUNKSIZE = 2048;
-    z_stream zs;
-    const unsigned char *inp;
-    size_t inplen;
-    size_t outbytes;
-
-  public:
-    enum Status {
-        MOREOUTPUT,
-        DONE,
-        CONTINUE,
-        OOM
-    };
-
-    Compressor(const unsigned char *inp, size_t inplen);
-    ~Compressor();
-    bool init();
-    void setOutput(unsigned char *out, size_t outlen);
-    size_t outWritten() const { return outbytes; }
-    /* Compress some of the input. Return true if it should be called again. */
-    Status compressMore();
-};
-
 Compressor::Compressor(const unsigned char *inp, size_t inplen)
     : inp(inp),
       inplen(inplen),
diff --git a/src/third_party/mozjs/js/src/jsutil.h b/src/third_party/mozjs/js/src/jsutil.h
index 9306a26..9dcfa8f 100644
--- a/src/third_party/mozjs/js/src/jsutil.h
+++ b/src/third_party/mozjs/js/src/jsutil.h
@@ -17,6 +17,10 @@
 
 #include "js/Utility.h"
 
+#ifdef USE_ZLIB
+#include "zlib.h"
+#endif
+
 /* Forward declarations. */
 struct JSContext;
 
@@ -262,6 +266,32 @@
 
 #ifdef USE_ZLIB
 
+class Compressor
+{
+    /* Number of bytes we should hand to zlib each compressMore() call. */
+    static const size_t CHUNKSIZE = 2048;
+    z_stream zs;
+    const unsigned char *inp;
+    size_t inplen;
+    size_t outbytes;
+
+  public:
+    enum Status {
+        MOREOUTPUT,
+        DONE,
+        CONTINUE,
+        OOM
+    };
+
+    Compressor(const unsigned char *inp, size_t inplen);
+    ~Compressor();
+    bool init();
+    void setOutput(unsigned char *out, size_t outlen);
+    size_t outWritten() const { return outbytes; }
+    /* Compress some of the input. Return true if it should be called again. */
+    Status compressMore();
+};
+
 /*
  * Decompress a string. The caller must know the length of the output and
  * allocate |out| to a string of that length.
diff --git a/src/third_party/mozjs/js/src/memory_allocator_reporter.cpp b/src/third_party/mozjs/js/src/memory_allocator_reporter.cpp
new file mode 100644
index 0000000..93d42df
--- /dev/null
+++ b/src/third_party/mozjs/js/src/memory_allocator_reporter.cpp
@@ -0,0 +1,83 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "memory_allocator_reporter.h"
+
+#include "starboard/once.h"
+
+namespace {
+// Control to initialize s_instance.
+SbOnceControl s_instance_control = SB_ONCE_INITIALIZER;
+MemoryAllocatorReporter* s_instance = NULL;
+
+void Initialize() {
+  s_instance = new MemoryAllocatorReporter();
+}
+
+void* OffsetPointer(void* base, ssize_t offset) {
+  uintptr_t base_as_int = reinterpret_cast<uintptr_t>(base);
+  return reinterpret_cast<void*>(base_as_int + offset);
+}
+}  // namespace
+
+AllocationMetadata* AllocationMetadata::GetMetadataFromUserAddress(void* ptr) {
+  if (ptr == NULL) {
+    return NULL;
+  }
+
+  // The metadata lives just in front of the data.
+  void* meta_addr =
+      OffsetPointer(ptr, -static_cast<ssize_t>(sizeof(AllocationMetadata)));
+  return reinterpret_cast<AllocationMetadata*>(meta_addr);
+}
+
+void* AllocationMetadata::GetUserAddressFromBaseAddress(void* base_ptr) {
+  void* adjusted_base =
+      OffsetPointer(base_ptr, static_cast<ssize_t>(sizeof(AllocationMetadata)));
+  return adjusted_base;
+}
+
+void AllocationMetadata::SetSizeToBaseAddress(void* base_ptr, size_t size) {
+  if (base_ptr) {
+    AllocationMetadata* metadata =
+        reinterpret_cast<AllocationMetadata*>(base_ptr);
+    metadata->set_size_requested(size);
+  }
+}
+
+void MemoryAllocatorReporter::UpdateAllocatedBytes(ssize_t bytes) {
+  starboard::ScopedLock lock(mutex_);
+  current_bytes_allocated_ += bytes;
+}
+
+ssize_t MemoryAllocatorReporter::GetCurrentBytesAllocated() {
+  starboard::ScopedLock lock(mutex_);
+  return current_bytes_allocated_;
+}
+
+void MemoryAllocatorReporter::UpdateMappedBytes(ssize_t bytes) {
+  starboard::ScopedLock lock(mutex_);
+  current_bytes_mapped_ += bytes;
+}
+
+ssize_t MemoryAllocatorReporter::GetCurrentBytesMapped() {
+  starboard::ScopedLock lock(mutex_);
+  return current_bytes_mapped_;
+}
+
+// static
+MemoryAllocatorReporter* MemoryAllocatorReporter::Get() {
+  SbOnce(&s_instance_control, &Initialize);
+  return s_instance;
+}
diff --git a/src/third_party/mozjs/js/src/memory_allocator_reporter.h b/src/third_party/mozjs/js/src/memory_allocator_reporter.h
new file mode 100644
index 0000000..e0d679f
--- /dev/null
+++ b/src/third_party/mozjs/js/src/memory_allocator_reporter.h
@@ -0,0 +1,62 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef MemoryAllocatorReporter_h
+#define MemoryAllocatorReporter_h
+
+#include <sys/types.h>
+
+#include "starboard/mutex.h"
+
+class AllocationMetadata {
+ public:
+  static AllocationMetadata* GetMetadataFromUserAddress(void* ptr);
+  static void* GetUserAddressFromBaseAddress(void* base_ptr);
+  static size_t GetReservationBytes(size_t bytes_requested) {
+    return sizeof(AllocationMetadata) + bytes_requested;
+  }
+  static size_t GetSizeOfAllocationFromMetadata(AllocationMetadata* metadata) {
+    return metadata ? metadata->size_requested() : 0;
+  }
+  static void SetSizeToBaseAddress(void* base_ptr, size_t size);
+
+  size_t size_requested() { return size_requested_; }
+  void set_size_requested(size_t size) { size_requested_ = size; }
+
+ private:
+  // Bytes requested by the underlying allocator.
+  size_t size_requested_;
+};
+
+// Reporter that is used to report memory allocation.
+class MemoryAllocatorReporter {
+ public:
+  static MemoryAllocatorReporter* Get();
+
+  MemoryAllocatorReporter()
+      : current_bytes_allocated_(0), current_bytes_mapped_(0) {}
+
+  void UpdateAllocatedBytes(ssize_t bytes);
+  ssize_t GetCurrentBytesAllocated();
+
+  void UpdateMappedBytes(ssize_t bytes);
+  ssize_t GetCurrentBytesMapped();
+
+ private:
+  starboard::Mutex mutex_;
+  ssize_t current_bytes_allocated_;
+  ssize_t current_bytes_mapped_;
+};
+
+#endif /* MemoryAllocatorReporter_h */
diff --git a/src/third_party/mozjs/js/src/vm/DateTime.cpp b/src/third_party/mozjs/js/src/vm/DateTime.cpp
index cfca247..a78a121 100644
--- a/src/third_party/mozjs/js/src/vm/DateTime.cpp
+++ b/src/third_party/mozjs/js/src/vm/DateTime.cpp
@@ -8,8 +8,16 @@
 
 #if defined(STARBOARD)
 #include "jsstarboard-time.h"
+#include "starboard/configuration.h"
 #include "starboard/time_zone.h"
-#else
+// For Starboard platforms that don't have support for getting the timezone
+// name, fall back to using localtime for conversion between UTC<->localtime.
+#if !SB_HAS_QUIRK(NO_TIMEZONE_NAME_SUPPORT)
+#define USE_STARBOARD_TIME
+#endif  // !SB_HAS_QUIRK(NO_TIMEZONE_NAME_SUPPORT)
+#endif  // defined(STARBOARD)
+
+#if !defined(USE_STARBOARD_TIME)
 #include <time.h>
 #endif
 
@@ -17,7 +25,7 @@
 
 using mozilla::UnspecifiedNaN;
 
-#if !defined(STARBOARD)
+#if !defined(USE_STARBOARD_TIME)
 static bool
 ComputeLocalTime(time_t local, struct tm *ptm)
 {
@@ -131,7 +139,7 @@
     // local seconds' frame of reference and then subtract.
     return local_secs - (utc_secs + SecondsPerDay);
 }
-#endif  // defined(STARBOARD)
+#endif  // defined(USE_STARBOARD_TIME)
 
 void
 js::DateTimeInfo::updateTimeZoneAdjustment()
@@ -140,7 +148,7 @@
      * The difference between local standard time and UTC will never change for
      * a given time zone.
      */
-#if defined(STARBOARD)
+#if defined(USE_STARBOARD_TIME)
     utcToLocalStandardOffsetSeconds = getTZOffset() / kSbTimeSecond;
 #else
     utcToLocalStandardOffsetSeconds = UTCToLocalStandardOffsetSeconds();
@@ -179,7 +187,7 @@
     updateTimeZoneAdjustment();
 }
 
-#if defined(STARBOARD)
+#if defined(USE_STARBOARD_TIME)
 int64_t
 js::DateTimeInfo::computeDSTOffsetMilliseconds(int64_t utcSeconds)
 {
@@ -219,7 +227,7 @@
 
     return diff * msPerSecond;
 }
-#endif  // defined(STARBOARD)
+#endif  // defined(USE_STARBOARD_TIME)
 
 int64_t
 js::DateTimeInfo::getDSTOffsetMilliseconds(int64_t utcMilliseconds)
diff --git a/src/third_party/mozjs/mozjs.gypi b/src/third_party/mozjs/mozjs.gypi
index 9fb9822..6b85ee0 100644
--- a/src/third_party/mozjs/mozjs.gypi
+++ b/src/third_party/mozjs/mozjs.gypi
@@ -82,6 +82,7 @@
       'js/src/jsweakmap.cpp',
       'js/src/jsworkers.cpp',
       'js/src/jswrapper.cpp',
+      'js/src/memory_allocator_reporter.cpp',
       'js/src/perf/jsperf.cpp',
       'js/src/perf/pm_stub.cpp',
       'js/src/prmjtime.cpp',
diff --git a/src/third_party/mozjs/test/jscustomallocator_test.cc b/src/third_party/mozjs/test/jscustomallocator_test.cc
new file mode 100644
index 0000000..e6702e1
--- /dev/null
+++ b/src/third_party/mozjs/test/jscustomallocator_test.cc
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jscustomallocator.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const size_t kSize = 1024 * 128;
+
+TEST(JSCustomallocator, JSMalloc) {
+  void* memory = js_malloc(kSize);
+  EXPECT_NE(static_cast<void*>(NULL), memory);
+  ssize_t current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated,
+            AllocationMetadata::GetReservationBytes(kSize));
+  js_free(memory);
+  current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated, 0);
+}
+
+TEST(JSCustomallocator, JSCallocWithNumber) {
+  void* memory = js_calloc(5, kSize);
+  EXPECT_NE(static_cast<void*>(NULL), memory);
+  ssize_t current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated,
+            AllocationMetadata::GetReservationBytes(5 * kSize));
+  js_free(memory);
+  current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated, 0);
+}
+
+TEST(JSCustomallocator, JSCalloc) {
+  void* memory = js_calloc(kSize);
+  EXPECT_NE(static_cast<void*>(NULL), memory);
+  ssize_t current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated,
+            AllocationMetadata::GetReservationBytes(kSize));
+  js_free(memory);
+  current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated, 0);
+}
+
+TEST(JSCustomallocator, JSReallocSmaller) {
+  void* memory = js_malloc(kSize);
+  ASSERT_NE(static_cast<void*>(NULL), memory);
+  char* data = static_cast<char*>(memory);
+  for (int i = 0; i < kSize; ++i) {
+    data[i] = i;
+  }
+
+  for (int i = 0; i < kSize; ++i) {
+    EXPECT_EQ(data[i], static_cast<char>(i));
+  }
+
+  ssize_t current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated,
+            AllocationMetadata::GetReservationBytes(kSize));
+
+  memory = js_realloc(memory, kSize / 2);
+  data = static_cast<char*>(memory);
+  ASSERT_NE(static_cast<void*>(NULL), memory);
+  for (int i = 0; i < kSize / 2; ++i) {
+    EXPECT_EQ(data[i], static_cast<char>(i));
+  }
+
+  current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated,
+            AllocationMetadata::GetReservationBytes(kSize / 2));
+
+  js_free(memory);
+
+  current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated, 0);
+}
+
+TEST(JSCustomallocator, JSReallocBigger) {
+  void* memory = js_malloc(kSize);
+  ASSERT_NE(static_cast<void*>(NULL), memory);
+  char* data = static_cast<char*>(memory);
+  for (int i = 0; i < kSize; ++i) {
+    data[i] = i;
+  }
+
+  for (int i = 0; i < kSize; ++i) {
+    EXPECT_EQ(data[i], static_cast<char>(i));
+  }
+
+  ssize_t current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated,
+            AllocationMetadata::GetReservationBytes(kSize));
+
+  memory = js_realloc(memory, kSize * 2);
+  ASSERT_NE(static_cast<void*>(NULL), memory);
+  data = static_cast<char*>(memory);
+  for (int i = 0; i < kSize; ++i) {
+    EXPECT_EQ(data[i], static_cast<char>(i));
+  }
+
+  for (int i = kSize; i < kSize * 2; ++i) {
+    data[i] = i;
+  }
+
+  for (int i = kSize; i < kSize * 2; ++i) {
+    EXPECT_EQ(data[i], static_cast<char>(i));
+  }
+
+  current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated,
+            AllocationMetadata::GetReservationBytes(kSize * 2));
+
+  js_free(memory);
+
+  current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated, 0);
+}
+
+TEST(JSCustomallocator, JSReallocNULL) {
+  void* memory = js_realloc(NULL, kSize);
+  EXPECT_NE(static_cast<void*>(NULL), memory);
+  ssize_t current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated,
+            AllocationMetadata::GetReservationBytes(kSize));
+
+  js_free(memory);
+
+  current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated, 0);
+}
+
+TEST(JSCustomallocator, JSStrdup) {
+  const char* input = "abcedfg123456";
+  char* dupe = js_strdup(const_cast<char*>(input));
+  const char* kNull = NULL;
+  EXPECT_NE(kNull, dupe);
+  EXPECT_EQ(0, SbStringCompareNoCase(input, dupe));
+  EXPECT_EQ(SbStringGetLength(input), SbStringGetLength(dupe));
+
+  ssize_t current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated, AllocationMetadata::GetReservationBytes(
+                                         SbStringGetLength(dupe) + 1));
+
+  js_free(dupe);
+
+  current_bytes_allocated =
+      MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated();
+  EXPECT_EQ(current_bytes_allocated, 0);
+}
+
+}  // namespace
diff --git a/src/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp b/src/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp
index 526e3be..77a5de6 100644
--- a/src/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp
+++ b/src/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp
@@ -88,7 +88,7 @@
             fsBuilder->codeAppend(".r,\n\t\t");
             fsBuilder->appendTextureLookup(samplers[1], coords[0].c_str(), coords[0].getType());
             if (yuvEffect.fNV12) {
-                fsBuilder->codeAppend(".ba,\n\t\t");
+                fsBuilder->codeAppend(".ra,\n\t\t");
             } else {
                 fsBuilder->codeAppend(".r,\n\t\t");
                 fsBuilder->appendTextureLookup(samplers[2], coords[0].c_str(), coords[0].getType());