diff --git a/BUILD.gn b/BUILD.gn
index b7d2cb1..6755a0c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -589,7 +589,7 @@
   if (is_win || is_linux) {
     deps += [
       "//components/resource_provider:resource_provider_unittests",
-      "//mash/wm:tests",
+      "//mash:mash_unittests",
       "//media/mojo/services:tests",
       "//ui/views/mus:tests",
     ]
diff --git a/DEPS b/DEPS
index 9d6e121..751fcfb 100644
--- a/DEPS
+++ b/DEPS
@@ -39,11 +39,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'ddf0713f0ba4ea75ca49a4ed6b4249eef72da1ce',
+  'skia_revision': '1cf632500a854d01b789ea22c1cf7967cfb6f570',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '718a6857086a6ce463f85a60ad5fbc07c6f8b335',
+  'v8_revision': 'f8acc0386662fbc50f374932f1152032414e4e0f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -267,7 +267,7 @@
 
   'src/third_party/catapult':
     Var('chromium_git') + '/external/github.com/catapult-project/catapult.git' + '@' +
-    'b729c79a9559c7fc5b211a2c7707f1302450adcc',
+    '25e660b72a41d00be8248a76e09ab3faab733f36',
 
   'src/third_party/openh264/src':
     Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + 'b37cda248234162033e3e11b0335f3131cdfe488',
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc
index 9cc3669..cf6b4b4 100644
--- a/android_webview/browser/browser_view_renderer.cc
+++ b/android_webview/browser/browser_view_renderer.cc
@@ -250,23 +250,24 @@
     viewport_rect_for_tile_priority = last_on_draw_global_visible_rect_;
   }
 
-  scoped_ptr<cc::CompositorFrame> frame =
+  content::SynchronousCompositor::Frame frame =
       compositor_->DemandDrawHw(surface_size,
                                 gfx::Transform(),
                                 viewport,
                                 clip,
                                 viewport_rect_for_tile_priority,
                                 transform_for_tile_priority);
-  if (!frame.get()) {
+  if (!frame.frame.get()) {
     TRACE_EVENT_INSTANT0("android_webview", "NoNewFrame",
                          TRACE_EVENT_SCOPE_THREAD);
     return shared_renderer_state_.HasFrameOnUI();
   }
 
   scoped_ptr<ChildFrame> child_frame = make_scoped_ptr(new ChildFrame(
-      std::move(frame), GetCompositorID(compositor_),
-      viewport_rect_for_tile_priority.IsEmpty(), transform_for_tile_priority,
-      offscreen_pre_raster_, parent_draw_constraints.is_layer));
+      frame.output_surface_id, std::move(frame.frame),
+      GetCompositorID(compositor_), viewport_rect_for_tile_priority.IsEmpty(),
+      transform_for_tile_priority, offscreen_pre_raster_,
+      parent_draw_constraints.is_layer));
 
   ReturnUnusedResource(shared_renderer_state_.PassUncommittedFrameOnUI());
   shared_renderer_state_.SetCompositorFrameOnUI(std::move(child_frame));
@@ -292,21 +293,23 @@
   content::SynchronousCompositor* compositor =
       compositor_map_[child_frame->compositor_id];
   if (compositor && !frame_ack.resources.empty())
-    compositor->ReturnResources(frame_ack);
+    compositor->ReturnResources(child_frame->output_surface_id, frame_ack);
 }
 
 void BrowserViewRenderer::ReturnResourceFromParent() {
-  std::map<uint32_t, cc::ReturnedResourceArray> returned_resource_map;
+  SharedRendererState::ReturnedResourcesMap returned_resource_map;
   shared_renderer_state_.SwapReturnedResourcesOnUI(&returned_resource_map);
   for (auto iterator = returned_resource_map.begin();
        iterator != returned_resource_map.end(); iterator++) {
     uint32_t compositor_id = iterator->first;
     content::SynchronousCompositor* compositor = compositor_map_[compositor_id];
     cc::CompositorFrameAck frame_ack;
-    frame_ack.resources.swap(iterator->second);
+    frame_ack.resources.swap(iterator->second.resources);
 
-    if (compositor && !frame_ack.resources.empty())
-      compositor->ReturnResources(frame_ack);
+    if (compositor && !frame_ack.resources.empty()) {
+      compositor->ReturnResources(iterator->second.output_surface_id,
+                                  frame_ack);
+    }
   }
 }
 
diff --git a/android_webview/browser/browser_view_renderer_unittest.cc b/android_webview/browser/browser_view_renderer_unittest.cc
index 5b2ec24..ffa5742 100644
--- a/android_webview/browser/browser_view_renderer_unittest.cc
+++ b/android_webview/browser/browser_view_renderer_unittest.cc
@@ -2,11 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <map>
+#include <queue>
+#include <utility>
+
 #include "android_webview/browser/browser_view_renderer.h"
 #include "android_webview/browser/child_frame.h"
 #include "android_webview/browser/test/rendering_test.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
+#include "cc/output/compositor_frame.h"
+#include "content/public/test/test_synchronous_compositor_android.h"
 
 namespace android_webview {
 
@@ -156,7 +162,7 @@
     if (0 == on_draw_count_) {
       // No frame from compositor.
     } else if (1 == on_draw_count_) {
-      SetCompositorFrame();
+      compositor_->SetHardwareFrame(0u, ConstructEmptyFrame());
     } else if (2 == on_draw_count_) {
       // No frame from compositor.
     }
@@ -186,4 +192,95 @@
 
 RENDERING_TEST_F(CompositorNoFrameTest);
 
+class SwitchOutputSurfaceIdTest : public RenderingTest {
+ public:
+  struct FrameInfo {
+    uint32_t output_surface_id;
+    cc::ResourceId resource_id;  // Each frame contains a single resource.
+  };
+
+  void StartTest() override {
+    last_output_surface_id_ = 0;
+    FrameInfo infos[] = {
+        // First output surface.
+        {0u, 1u}, {0u, 1u}, {0u, 2u}, {0u, 2u}, {0u, 3u}, {0u, 3u}, {0u, 4u},
+        // Second output surface.
+        {1u, 1u}, {1u, 1u}, {1u, 2u}, {1u, 2u}, {1u, 3u}, {1u, 3u}, {1u, 4u},
+    };
+    for (const auto& info : infos) {
+      content::SynchronousCompositor::Frame frame;
+      frame.output_surface_id = info.output_surface_id;
+      frame.frame = ConstructEmptyFrame();
+      cc::TransferableResource resource;
+      resource.id = info.resource_id;
+      frame.frame->delegated_frame_data->resource_list.push_back(resource);
+      frames_.push(std::move(frame));
+
+      // Keep a id -> count map for the last ouptut_surface_id.
+      if (last_output_surface_id_ != info.output_surface_id) {
+        expected_return_count_.clear();
+        last_output_surface_id_ = info.output_surface_id;
+      }
+      if (expected_return_count_.count(info.resource_id)) {
+        expected_return_count_[info.resource_id]++;
+      } else {
+        expected_return_count_[info.resource_id] = 1;
+      }
+    }
+
+    browser_view_renderer_->PostInvalidate();
+  }
+
+  void WillOnDraw() override {
+    if (!frames_.empty()) {
+      compositor_->SetHardwareFrame(frames_.front().output_surface_id,
+                                    std::move(frames_.front().frame));
+    }
+  }
+
+  void DidOnDraw(bool success) override {
+    EXPECT_TRUE(success);
+    if (frames_.empty()) {
+      ui_task_runner_->PostTask(
+          FROM_HERE, base::Bind(&SwitchOutputSurfaceIdTest::CheckResults,
+                                base::Unretained(this)));
+    } else {
+      frames_.pop();
+      browser_view_renderer_->PostInvalidate();
+    }
+  }
+
+  void CheckResults() {
+    window_->Detach();
+    window_.reset();
+
+    // Make sure resources for the last output surface are returned.
+    content::TestSynchronousCompositor::FrameAckArray returned_resources_array;
+    compositor_->SwapReturnedResources(&returned_resources_array);
+    for (const auto& resources : returned_resources_array) {
+      if (resources.output_surface_id != last_output_surface_id_)
+        continue;
+      for (const auto& returned_resource : resources.resources) {
+        EXPECT_TRUE(!!expected_return_count_.count(returned_resource.id));
+        EXPECT_GE(expected_return_count_[returned_resource.id],
+                  returned_resource.count);
+        expected_return_count_[returned_resource.id] -=
+            returned_resource.count;
+        if (!expected_return_count_[returned_resource.id])
+          expected_return_count_.erase(returned_resource.id);
+      }
+    }
+    EXPECT_TRUE(expected_return_count_.empty());
+
+    EndTest();
+  }
+
+ private:
+  std::queue<content::SynchronousCompositor::Frame> frames_;
+  uint32_t last_output_surface_id_;
+  std::map<cc::ResourceId, int> expected_return_count_;
+};
+
+RENDERING_TEST_F(SwitchOutputSurfaceIdTest);
+
 }  // namespace android_webview
diff --git a/android_webview/browser/child_frame.cc b/android_webview/browser/child_frame.cc
index aa6130f..f51b7455f 100644
--- a/android_webview/browser/child_frame.cc
+++ b/android_webview/browser/child_frame.cc
@@ -10,13 +10,15 @@
 
 namespace android_webview {
 
-ChildFrame::ChildFrame(scoped_ptr<cc::CompositorFrame> frame,
+ChildFrame::ChildFrame(uint32_t output_surface_id,
+                       scoped_ptr<cc::CompositorFrame> frame,
                        uint32_t compositor_id,
                        bool viewport_rect_for_tile_priority_empty,
                        const gfx::Transform& transform_for_tile_priority,
                        bool offscreen_pre_raster,
                        bool is_layer)
-    : frame(std::move(frame)),
+    : output_surface_id(output_surface_id),
+      frame(std::move(frame)),
       compositor_id(compositor_id),
       viewport_rect_for_tile_priority_empty(
           viewport_rect_for_tile_priority_empty),
diff --git a/android_webview/browser/child_frame.h b/android_webview/browser/child_frame.h
index b83e57e..ca42958 100644
--- a/android_webview/browser/child_frame.h
+++ b/android_webview/browser/child_frame.h
@@ -19,7 +19,8 @@
 
 class ChildFrame {
  public:
-  ChildFrame(scoped_ptr<cc::CompositorFrame> frame,
+  ChildFrame(uint32_t output_surface_id,
+             scoped_ptr<cc::CompositorFrame> frame,
              uint32_t compositor_id,
              bool viewport_rect_for_tile_priority_empty,
              const gfx::Transform& transform_for_tile_priority,
@@ -27,6 +28,7 @@
              bool is_layer);
   ~ChildFrame();
 
+  const uint32_t output_surface_id;
   scoped_ptr<cc::CompositorFrame> frame;
   // The id of the compositor this |frame| comes from.
   const uint32_t compositor_id;
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc
index aab7f168..f0a4f85 100644
--- a/android_webview/browser/hardware_renderer.cc
+++ b/android_webview/browser/hardware_renderer.cc
@@ -38,7 +38,9 @@
     : shared_renderer_state_(state),
       last_egl_context_(eglGetCurrentContext()),
       gl_surface_(new AwGLSurface),
-      compositor_id_(0),  // Valid compositor id starts at 1.
+      compositor_id_(0u),  // Valid compositor id starts at 1.
+      last_committed_output_surface_id_(0u),
+      last_submitted_output_surface_id_(0u),
       output_surface_(NULL) {
   DCHECK(last_egl_context_);
 
@@ -86,6 +88,7 @@
   if (!child_frame.get())
     return;
 
+  last_committed_output_surface_id_ = child_frame->output_surface_id;
   ReturnResourcesInChildFrame();
   child_frame_ = std::move(child_frame);
   DCHECK(child_frame_->frame.get());
@@ -110,7 +113,8 @@
   // kModeProcess. Instead, submit the frame in "kModeDraw" stage to avoid
   // unnecessary kModeProcess.
   if (child_frame_.get() && child_frame_->frame.get()) {
-    if (compositor_id_ != child_frame_->compositor_id) {
+    if (compositor_id_ != child_frame_->compositor_id ||
+        last_submitted_output_surface_id_ != child_frame_->output_surface_id) {
       if (!root_id_.is_null())
         surface_factory_->Destroy(root_id_);
       if (!child_id_.is_null())
@@ -122,6 +126,7 @@
       // This will return all the resources to the previous compositor.
       surface_factory_.reset();
       compositor_id_ = child_frame_->compositor_id;
+      last_submitted_output_surface_id_ = child_frame_->output_surface_id;
       surface_factory_.reset(
           new cc::SurfaceFactory(surface_manager_.get(), this));
     }
@@ -223,7 +228,8 @@
 
 void HardwareRenderer::ReturnResources(
     const cc::ReturnedResourceArray& resources) {
-  ReturnResourcesToCompositor(resources, compositor_id_);
+  ReturnResourcesToCompositor(resources, compositor_id_,
+                              last_submitted_output_surface_id_);
 }
 
 void HardwareRenderer::SetBeginFrameSource(
@@ -246,15 +252,20 @@
     // The child frame's compositor id is not necessarily same as
     // compositor_id_.
     ReturnResourcesToCompositor(resources_to_return,
-                                child_frame_->compositor_id);
+                                child_frame_->compositor_id,
+                                child_frame_->output_surface_id);
   }
   child_frame_.reset();
 }
 
 void HardwareRenderer::ReturnResourcesToCompositor(
     const cc::ReturnedResourceArray& resources,
-    uint32_t compositor_id) {
-  shared_renderer_state_->InsertReturnedResourcesOnRT(resources, compositor_id);
+    uint32_t compositor_id,
+    uint32_t output_surface_id) {
+  if (output_surface_id != last_committed_output_surface_id_)
+    return;
+  shared_renderer_state_->InsertReturnedResourcesOnRT(resources, compositor_id,
+                                                      output_surface_id);
 }
 
 }  // namespace android_webview
diff --git a/android_webview/browser/hardware_renderer.h b/android_webview/browser/hardware_renderer.h
index fe842f4..1b5127a 100644
--- a/android_webview/browser/hardware_renderer.h
+++ b/android_webview/browser/hardware_renderer.h
@@ -52,7 +52,8 @@
 
   void ReturnResourcesInChildFrame();
   void ReturnResourcesToCompositor(const cc::ReturnedResourceArray& resources,
-                                   uint32_t compositor_routing_id);
+                                   uint32_t compositor_routing_id,
+                                   uint32_t output_surface_id);
 
   SharedRendererState* shared_renderer_state_;
 
@@ -79,6 +80,10 @@
   cc::SurfaceId child_id_;
   cc::SurfaceId root_id_;
   uint32_t compositor_id_;
+  // HardwareRenderer guarantees resources are returned in the order of
+  // output_surface_id, and resources for old output surfaces are dropped.
+  uint32_t last_committed_output_surface_id_;
+  uint32_t last_submitted_output_surface_id_;
 
   // This is owned by |display_|.
   ParentOutputSurface* output_surface_;
diff --git a/android_webview/browser/net/android_stream_reader_url_request_job.cc b/android_webview/browser/net/android_stream_reader_url_request_job.cc
index 091c237a7..97ad3a8 100644
--- a/android_webview/browser/net/android_stream_reader_url_request_job.cc
+++ b/android_webview/browser/net/android_stream_reader_url_request_job.cc
@@ -230,7 +230,7 @@
   PostTaskAndReplyWithResult(
       GetWorkerThreadRunner(), FROM_HERE,
       base::Bind(&InputStreamReaderWrapper::ReadRawData,
-                 input_stream_reader_wrapper_, make_scoped_refptr(dest),
+                 input_stream_reader_wrapper_, base::RetainedRef(dest),
                  dest_size),
       base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted,
                  weak_factory_.GetWeakPtr()));
diff --git a/android_webview/browser/net/aw_cookie_store_wrapper.h b/android_webview/browser/net/aw_cookie_store_wrapper.h
index a5bbf1a..e3f3a5d 100644
--- a/android_webview/browser/net/aw_cookie_store_wrapper.h
+++ b/android_webview/browser/net/aw_cookie_store_wrapper.h
@@ -111,8 +111,8 @@
     if (callback.is_null())
       return callback;
     return base::Bind(&AwCookieStoreWrapper::RunCallbackOnClientThread<Type>,
-                      client_task_runner_, weak_factory_.GetWeakPtr(),
-                      callback);
+                      base::RetainedRef(client_task_runner_),
+                      weak_factory_.GetWeakPtr(), callback);
   }
 
   // Returns a base::Closure that posts a task to the |client_task_runner_| to
diff --git a/android_webview/browser/shared_renderer_state.cc b/android_webview/browser/shared_renderer_state.cc
index e81ab126..488f915b 100644
--- a/android_webview/browser/shared_renderer_state.cc
+++ b/android_webview/browser/shared_renderer_state.cc
@@ -213,18 +213,28 @@
   return inside_hardware_release_;
 }
 
+SharedRendererState::ReturnedResources::ReturnedResources()
+    : output_surface_id(0u) {}
+
+SharedRendererState::ReturnedResources::~ReturnedResources() {}
+
 void SharedRendererState::InsertReturnedResourcesOnRT(
     const cc::ReturnedResourceArray& resources,
-    uint32_t compositor_id) {
+    uint32_t compositor_id,
+    uint32_t output_surface_id) {
   base::AutoLock lock(lock_);
-  cc::ReturnedResourceArray& returned_resources =
+  ReturnedResources& returned_resources =
       returned_resources_map_[compositor_id];
-  returned_resources.insert(returned_resources.end(), resources.begin(),
-                            resources.end());
+  if (returned_resources.output_surface_id != output_surface_id) {
+    returned_resources.resources.clear();
+  }
+  returned_resources.resources.insert(returned_resources.resources.end(),
+                                      resources.begin(), resources.end());
+  returned_resources.output_surface_id = output_surface_id;
 }
 
 void SharedRendererState::SwapReturnedResourcesOnUI(
-    std::map<uint32_t, cc::ReturnedResourceArray>* returned_resource_map) {
+    ReturnedResourcesMap* returned_resource_map) {
   DCHECK(returned_resource_map->empty());
   base::AutoLock lock(lock_);
   returned_resource_map->swap(returned_resources_map_);
diff --git a/android_webview/browser/shared_renderer_state.h b/android_webview/browser/shared_renderer_state.h
index a6f3e0b..a2313a58 100644
--- a/android_webview/browser/shared_renderer_state.h
+++ b/android_webview/browser/shared_renderer_state.h
@@ -34,6 +34,15 @@
 // This class is used to pass data between UI thread and RenderThread.
 class SharedRendererState {
  public:
+  struct ReturnedResources {
+    ReturnedResources();
+    ~ReturnedResources();
+
+    uint32_t output_surface_id;
+    cc::ReturnedResourceArray resources;
+  };
+  using ReturnedResourcesMap = std::map<uint32_t, ReturnedResources>;
+
   SharedRendererState(
       const scoped_refptr<base::SingleThreadTaskRunner>& ui_loop,
       BrowserViewRenderer* browser_view_renderer);
@@ -48,8 +57,7 @@
   void InitializeHardwareDrawIfNeededOnUI();
   void ReleaseHardwareDrawIfNeededOnUI();
   ParentCompositorDrawConstraints GetParentDrawConstraintsOnUI() const;
-  void SwapReturnedResourcesOnUI(
-      std::map<uint32_t, cc::ReturnedResourceArray>* returned_resource_map);
+  void SwapReturnedResourcesOnUI(ReturnedResourcesMap* returned_resource_map);
   bool ReturnedResourcesEmptyOnUI() const;
   scoped_ptr<ChildFrame> PassUncommittedFrameOnUI();
   void DeleteHardwareRendererOnUI();
@@ -62,7 +70,8 @@
   void PostExternalDrawConstraintsToChildCompositorOnRT(
       const ParentCompositorDrawConstraints& parent_draw_constraints);
   void InsertReturnedResourcesOnRT(const cc::ReturnedResourceArray& resources,
-                                   uint32_t compositor_id);
+                                   uint32_t compositor_id,
+                                   uint32_t output_surface_id);
 
  private:
   friend class internal::RequestDrawGLTracker;
@@ -106,8 +115,7 @@
   scoped_ptr<ChildFrame> child_frame_;
   bool inside_hardware_release_;
   ParentCompositorDrawConstraints parent_draw_constraints_;
-  // A map from compositor's ID to the resources that belong to the compositor.
-  std::map<uint32_t, cc::ReturnedResourceArray> returned_resources_map_;
+  ReturnedResourcesMap returned_resources_map_;
   base::Closure request_draw_gl_closure_;
 
   base::WeakPtrFactory<SharedRendererState> weak_factory_on_ui_thread_;
diff --git a/android_webview/browser/test/rendering_test.cc b/android_webview/browser/test/rendering_test.cc
index 4f00a205..e51f3aa9 100644
--- a/android_webview/browser/test/rendering_test.cc
+++ b/android_webview/browser/test/rendering_test.cc
@@ -67,8 +67,7 @@
   message_loop_->QuitWhenIdle();
 }
 
-void RenderingTest::SetCompositorFrame() {
-  DCHECK(compositor_.get());
+scoped_ptr<cc::CompositorFrame> RenderingTest::ConstructEmptyFrame() {
   scoped_ptr<cc::CompositorFrame> compositor_frame(new cc::CompositorFrame);
   scoped_ptr<cc::DelegatedFrameData> frame(new cc::DelegatedFrameData);
   scoped_ptr<cc::RenderPass> root_pass(cc::RenderPass::Create());
@@ -77,11 +76,12 @@
                     gfx::Transform());
   frame->render_pass_list.push_back(std::move(root_pass));
   compositor_frame->delegated_frame_data = std::move(frame);
-  compositor_->SetHardwareFrame(std::move(compositor_frame));
+  return compositor_frame;
 }
 
 void RenderingTest::WillOnDraw() {
-  SetCompositorFrame();
+  DCHECK(compositor_);
+  compositor_->SetHardwareFrame(0u, ConstructEmptyFrame());
 }
 
 bool RenderingTest::RequestDrawGL(bool wait_for_completion) {
@@ -103,7 +103,8 @@
 }
 
 void RenderingTest::PostInvalidate() {
-  window_->PostInvalidate();
+  if (window_)
+    window_->PostInvalidate();
 }
 
 void RenderingTest::DetachFunctorFromView() {
diff --git a/android_webview/browser/test/rendering_test.h b/android_webview/browser/test/rendering_test.h
index 0e6fcf1..8dd6cae3 100644
--- a/android_webview/browser/test/rendering_test.h
+++ b/android_webview/browser/test/rendering_test.h
@@ -16,6 +16,10 @@
 class MessageLoop;
 }
 
+namespace cc {
+class CompositorFrame;
+}
+
 namespace content {
 class TestSynchronousCompositor;
 }
@@ -58,6 +62,7 @@
   void DidDrawOnRT(SharedRendererState* functor) override {}
 
  protected:
+
   RenderingTest();
   ~RenderingTest() override;
 
@@ -68,7 +73,7 @@
   void InitializeCompositor();
   void Attach();
   void EndTest();
-  void SetCompositorFrame();
+  scoped_ptr<cc::CompositorFrame> ConstructEmptyFrame();
 
   scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
   scoped_ptr<BrowserViewRenderer> browser_view_renderer_;
diff --git a/android_webview/native/aw_contents_client_bridge.cc b/android_webview/native/aw_contents_client_bridge.cc
index d5b3b44..8cd4cc9 100644
--- a/android_webview/native/aw_contents_client_bridge.cc
+++ b/android_webview/native/aw_contents_client_bridge.cc
@@ -263,7 +263,7 @@
       base::Bind(&RecordClientCertificateKey, client_cert,
                  base::Passed(&private_key)),
       base::Bind(&content::ClientCertificateDelegate::ContinueWithCertificate,
-                 base::Owned(delegate), client_cert));
+                 base::Owned(delegate), base::RetainedRef(client_cert)));
 }
 
 void AwContentsClientBridge::RunJavaScriptDialog(
diff --git a/ash/display/display_layout.cc b/ash/display/display_layout.cc
index 1897d76..1cc7b7f 100644
--- a/ash/display/display_layout.cc
+++ b/ash/display/display_layout.cc
@@ -48,12 +48,6 @@
       position(DisplayPlacement::RIGHT),
       offset(0) {}
 
-DisplayPlacement::DisplayPlacement(const DisplayPlacement& placement)
-    : display_id(placement.display_id),
-      parent_display_id(placement.parent_display_id),
-      position(placement.position),
-      offset(placement.offset) {}
-
 DisplayPlacement::DisplayPlacement(Position pos, int offset)
     : display_id(gfx::Display::kInvalidDisplayID),
       parent_display_id(gfx::Display::kInvalidDisplayID),
@@ -69,6 +63,12 @@
   DCHECK_GE(kMaxValidOffset, abs(offset));
 }
 
+DisplayPlacement::DisplayPlacement(const DisplayPlacement& placement)
+    : display_id(placement.display_id),
+      parent_display_id(placement.parent_display_id),
+      position(placement.position),
+      offset(placement.offset) {}
+
 DisplayPlacement& DisplayPlacement::Swap() {
   switch (position) {
     case TOP:
@@ -167,36 +167,35 @@
   bool has_primary_as_parent = false;
   int64_t id = 0;
 
-  for (const auto* placement : layout.placement_list) {
+  for (const auto& placement : layout.placement_list) {
     // Placements are sorted by display_id.
-    if (id >= placement->display_id) {
+    if (id >= placement.display_id) {
       LOG(ERROR) << "PlacementList must be sorted by display_id";
       return false;
     }
-    if (placement->display_id == gfx::Display::kInvalidDisplayID) {
+    if (placement.display_id == gfx::Display::kInvalidDisplayID) {
       LOG(ERROR) << "display_id is not initialized";
       return false;
     }
-    if (placement->parent_display_id == gfx::Display::kInvalidDisplayID) {
+    if (placement.parent_display_id == gfx::Display::kInvalidDisplayID) {
       LOG(ERROR) << "display_parent_id is not initialized";
       return false;
     }
-    if (placement->display_id == placement->parent_display_id) {
+    if (placement.display_id == placement.parent_display_id) {
       LOG(ERROR) << "display_id must not be same as parent_display_id";
       return false;
     }
-    if (!IsIdInList(placement->display_id, list)) {
-      LOG(ERROR) << "display_id is not in the id list:"
-                 << placement->ToString();
+    if (!IsIdInList(placement.display_id, list)) {
+      LOG(ERROR) << "display_id is not in the id list:" << placement.ToString();
       return false;
     }
 
-    if (!IsIdInList(placement->parent_display_id, list)) {
+    if (!IsIdInList(placement.parent_display_id, list)) {
       LOG(ERROR) << "parent_display_id is not in the id list:"
-                 << placement->ToString();
+                 << placement.ToString();
       return false;
     }
-    has_primary_as_parent |= layout.primary_id == placement->parent_display_id;
+    has_primary_as_parent |= layout.primary_id == placement.parent_display_id;
   }
   if (!has_primary_as_parent)
     LOG(ERROR) << "At least, one placement must have the primary as a parent.";
@@ -205,8 +204,8 @@
 
 scoped_ptr<DisplayLayout> DisplayLayout::Copy() const {
   scoped_ptr<DisplayLayout> copy(new DisplayLayout);
-  for (auto placement : placement_list)
-    copy->placement_list.push_back(new DisplayPlacement(*placement));
+  for (const auto& placement : placement_list)
+    copy->placement_list.push_back(placement);
   copy->mirrored = mirrored;
   copy->default_unified = default_unified;
   copy->primary_id = primary_id;
@@ -217,8 +216,8 @@
   if (placement_list.size() != layout.placement_list.size())
     return false;
   for (size_t index = 0; index < placement_list.size(); index++) {
-    const DisplayPlacement& placement1 = *placement_list[index];
-    const DisplayPlacement& placement2 = *layout.placement_list[index];
+    const DisplayPlacement& placement1 = placement_list[index];
+    const DisplayPlacement& placement2 = layout.placement_list[index];
     if (placement1.position != placement2.position ||
         placement1.offset != placement2.offset ||
         placement1.display_id != placement2.display_id ||
@@ -237,9 +236,9 @@
   if (default_unified)
     s << ", default_unified";
   bool added = false;
-  for (const auto* placement : placement_list) {
+  for (const auto& placement : placement_list) {
     s << (added ? "),(" : " [(");
-    s << placement->ToString();
+    s << placement.ToString();
     added = true;
   }
   if (added)
@@ -247,14 +246,14 @@
   return s.str();
 }
 
-const DisplayPlacement* DisplayLayout::FindPlacementById(
-    int64_t display_id) const {
+DisplayPlacement DisplayLayout::FindPlacementById(int64_t display_id) const {
   const auto iter =
       std::find_if(placement_list.begin(), placement_list.end(),
-                   [display_id](const DisplayPlacement* placement) {
-                     return placement->display_id == display_id;
+                   [display_id](const DisplayPlacement& placement) {
+                     return placement.display_id == display_id;
                    });
-  return (iter == placement_list.end()) ? nullptr : *iter;
+  return (iter == placement_list.end()) ? DisplayPlacement()
+                                        : DisplayPlacement(*iter);
 }
 
 }  // namespace ash
diff --git a/ash/display/display_layout.h b/ash/display/display_layout.h
index 136360b..fd056130 100644
--- a/ash/display/display_layout.h
+++ b/ash/display/display_layout.h
@@ -13,7 +13,6 @@
 #include "ash/ash_export.h"
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
 #include "base/strings/string_piece.h"
 
 namespace base {
@@ -61,9 +60,9 @@
   // based on the top/left edge of the primary display.
   int offset;
 
-  explicit DisplayPlacement(const DisplayPlacement& placement);
   DisplayPlacement(Position position, int offset);
   DisplayPlacement();
+  DisplayPlacement(const DisplayPlacement& placement);
 
   DisplayPlacement& Swap();
 
@@ -82,7 +81,7 @@
   // Validates the layout object.
   static bool Validate(const DisplayIdList& list, const DisplayLayout& layout);
 
-  ScopedVector<DisplayPlacement> placement_list;
+  std::vector<DisplayPlacement> placement_list;
 
   // True if displays are mirrored.
   bool mirrored;
@@ -102,9 +101,9 @@
   // Returns string representation of the layout for debugging/testing.
   std::string ToString() const;
 
-  // Returns the DisplayPlacement entry in |placement_list| matching
-  // |display_id| if it exists, otherwise returns nullptr.
-  const DisplayPlacement* FindPlacementById(int64_t display_id) const;
+  // Returns the DisplayPlacement entry matching |display_id| if it exists,
+  // otherwise returns a DisplayPlacement with an invalid display id.
+  DisplayPlacement FindPlacementById(int64_t display_id) const;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(DisplayLayout);
diff --git a/ash/display/display_layout_builder.cc b/ash/display/display_layout_builder.cc
index 6a1919d..579337f 100644
--- a/ash/display/display_layout_builder.cc
+++ b/ash/display/display_layout_builder.cc
@@ -4,6 +4,8 @@
 
 #include "ash/display/display_layout_builder.h"
 
+#include <algorithm>
+
 namespace ash {
 
 DisplayLayoutBuilder::DisplayLayoutBuilder(const DisplayLayout& layout)
@@ -37,12 +39,12 @@
     int64_t parent_display_id,
     DisplayPlacement::Position position,
     int offset) {
-  scoped_ptr<DisplayPlacement> placement(new DisplayPlacement);
-  placement->position = position;
-  placement->offset = offset;
-  placement->display_id = display_id;
-  placement->parent_display_id = parent_display_id;
-  layout_->placement_list.push_back(std::move(placement));
+  DisplayPlacement placement;
+  placement.position = position;
+  placement.offset = offset;
+  placement.display_id = display_id;
+  placement.parent_display_id = parent_display_id;
+  layout_->placement_list.push_back(placement);
   return *this;
 }
 
@@ -57,8 +59,8 @@
 
 scoped_ptr<DisplayLayout> DisplayLayoutBuilder::Build() {
   std::sort(layout_->placement_list.begin(), layout_->placement_list.end(),
-            [](const DisplayPlacement* a, const DisplayPlacement* b) {
-              return a->display_id < b->display_id;
+            [](const DisplayPlacement& a, const DisplayPlacement& b) {
+              return a.display_id < b.display_id;
             });
   return std::move(layout_);
 }
diff --git a/ash/display/display_layout_builder_unittest.cc b/ash/display/display_layout_builder_unittest.cc
index 91232052..159790cd 100644
--- a/ash/display/display_layout_builder_unittest.cc
+++ b/ash/display/display_layout_builder_unittest.cc
@@ -16,10 +16,10 @@
   scoped_ptr<DisplayLayout> layout(builder.Build());
   ASSERT_EQ(1u, layout->placement_list.size());
 
-  EXPECT_EQ(2, layout->placement_list[0]->display_id);
-  EXPECT_EQ(1, layout->placement_list[0]->parent_display_id);
-  EXPECT_EQ(30, layout->placement_list[0]->offset);
-  EXPECT_EQ(DisplayPlacement::LEFT, layout->placement_list[0]->position);
+  EXPECT_EQ(2, layout->placement_list[0].display_id);
+  EXPECT_EQ(1, layout->placement_list[0].parent_display_id);
+  EXPECT_EQ(30, layout->placement_list[0].offset);
+  EXPECT_EQ(DisplayPlacement::LEFT, layout->placement_list[0].position);
 }
 
 TEST_F(DisplayLayoutBuilderTest, MultiplePlacement) {
@@ -32,20 +32,20 @@
   ASSERT_EQ(3u, layout->placement_list.size());
 
   // placmenets are sorted by display_id.
-  EXPECT_EQ(3, layout->placement_list[0]->display_id);
-  EXPECT_EQ(5, layout->placement_list[0]->parent_display_id);
-  EXPECT_EQ(20, layout->placement_list[0]->offset);
-  EXPECT_EQ(DisplayPlacement::LEFT, layout->placement_list[0]->position);
+  EXPECT_EQ(3, layout->placement_list[0].display_id);
+  EXPECT_EQ(5, layout->placement_list[0].parent_display_id);
+  EXPECT_EQ(20, layout->placement_list[0].offset);
+  EXPECT_EQ(DisplayPlacement::LEFT, layout->placement_list[0].position);
 
-  EXPECT_EQ(4, layout->placement_list[1]->display_id);
-  EXPECT_EQ(5, layout->placement_list[1]->parent_display_id);
-  EXPECT_EQ(10, layout->placement_list[1]->offset);
-  EXPECT_EQ(DisplayPlacement::RIGHT, layout->placement_list[1]->position);
+  EXPECT_EQ(4, layout->placement_list[1].display_id);
+  EXPECT_EQ(5, layout->placement_list[1].parent_display_id);
+  EXPECT_EQ(10, layout->placement_list[1].offset);
+  EXPECT_EQ(DisplayPlacement::RIGHT, layout->placement_list[1].position);
 
-  EXPECT_EQ(5, layout->placement_list[2]->display_id);
-  EXPECT_EQ(1, layout->placement_list[2]->parent_display_id);
-  EXPECT_EQ(30, layout->placement_list[2]->offset);
-  EXPECT_EQ(DisplayPlacement::TOP, layout->placement_list[2]->position);
+  EXPECT_EQ(5, layout->placement_list[2].display_id);
+  EXPECT_EQ(1, layout->placement_list[2].parent_display_id);
+  EXPECT_EQ(30, layout->placement_list[2].offset);
+  EXPECT_EQ(DisplayPlacement::TOP, layout->placement_list[2].position);
 }
 
 }  // namespace ash
diff --git a/ash/display/display_layout_store.cc b/ash/display/display_layout_store.cc
index b78bf98..1deb3a4d 100644
--- a/ash/display/display_layout_store.cc
+++ b/ash/display/display_layout_store.cc
@@ -58,14 +58,13 @@
   // Old data may not have the display_id/parent_display_id.
   // Guess these values based on the saved primary_id.
   if (layout->placement_list.size() >= 1 &&
-      layout->placement_list[0]->display_id ==
-          gfx::Display::kInvalidDisplayID) {
+      layout->placement_list[0].display_id == gfx::Display::kInvalidDisplayID) {
     if (layout->primary_id == list[1]) {
-      layout->placement_list[0]->display_id = list[0];
-      layout->placement_list[0]->parent_display_id = list[1];
+      layout->placement_list[0].display_id = list[0];
+      layout->placement_list[0].parent_display_id = list[1];
     } else {
-      layout->placement_list[0]->display_id = list[1];
-      layout->placement_list[0]->parent_display_id = list[0];
+      layout->placement_list[0].display_id = list[1];
+      layout->placement_list[0].parent_display_id = list[0];
     }
   }
   DCHECK(DisplayLayout::Validate(list, *layout.get())) << layout->ToString();
@@ -102,11 +101,10 @@
   layout->primary_id = list[0];
   layout->placement_list.clear();
   for (size_t i = 0; i < list.size() - 1; i++) {
-    scoped_ptr<DisplayPlacement> placement(
-        new DisplayPlacement(default_display_placement_));
-    placement->display_id = list[i + 1];
-    placement->parent_display_id = list[i];
-    layout->placement_list.push_back(std::move(placement));
+    DisplayPlacement placement(default_display_placement_);
+    placement.display_id = list[i + 1];
+    placement.parent_display_id = list[i];
+    layout->placement_list.push_back(placement);
   }
   layouts_[list] = std::move(layout);
   auto iter = layouts_.find(list);
diff --git a/ash/display/display_manager.cc b/ash/display/display_manager.cc
index 25dfc06..06f956cf 100644
--- a/ash/display/display_manager.cc
+++ b/ash/display/display_manager.cc
@@ -1326,11 +1326,11 @@
   while (parents.size()) {
     int64_t parent_id = *parents.begin();
     parents.erase(parent_id);
-    for (const DisplayPlacement* placement : layout.placement_list) {
-      if (placement->parent_display_id == parent_id) {
-        if (ApplyDisplayPlacement(*placement, display_list) && updated_ids)
-          updated_ids->push_back(placement->display_id);
-        parents.insert(placement->display_id);
+    for (const DisplayPlacement& placement : layout.placement_list) {
+      if (placement.parent_display_id == parent_id) {
+        if (ApplyDisplayPlacement(placement, display_list) && updated_ids)
+          updated_ids->push_back(placement.display_id);
+        parents.insert(placement.display_id);
       }
     }
   }
diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc
index 3424058..9be39e9 100644
--- a/ash/display/display_manager_unittest.cc
+++ b/ash/display/display_manager_unittest.cc
@@ -2203,8 +2203,7 @@
   int64_t id2 = 10002;
 
   scoped_ptr<DisplayLayout> old_layout(new DisplayLayout);
-  old_layout->placement_list.push_back(
-      new DisplayPlacement(DisplayPlacement::BOTTOM, 0));
+  old_layout->placement_list.emplace_back(DisplayPlacement::BOTTOM, 0);
   old_layout->primary_id = id1;
 
   DisplayLayoutStore* layout_store = display_manager()->layout_store();
@@ -2212,8 +2211,8 @@
   layout_store->RegisterLayoutForDisplayIdList(list, std::move(old_layout));
   const DisplayLayout& stored = layout_store->GetRegisteredDisplayLayout(list);
 
-  EXPECT_EQ(id1, stored.placement_list[0]->parent_display_id);
-  EXPECT_EQ(id2, stored.placement_list[0]->display_id);
+  EXPECT_EQ(id1, stored.placement_list[0].parent_display_id);
+  EXPECT_EQ(id2, stored.placement_list[0].display_id);
 }
 
 #endif  // OS_CHROMEOS
diff --git a/ash/display/extended_mouse_warp_controller.cc b/ash/display/extended_mouse_warp_controller.cc
index 9fe1254..879b04b 100644
--- a/ash/display/extended_mouse_warp_controller.cc
+++ b/ash/display/extended_mouse_warp_controller.cc
@@ -80,13 +80,13 @@
       Shell::GetInstance()->display_manager();
 
   // TODO(oshima): Use ComputeBondary instead and try all combinations.
-  for (const auto* placement :
+  for (const auto& placement :
        display_manager->GetCurrentDisplayLayout().placement_list) {
-    DisplayPlacement::Position position = placement->position;
+    DisplayPlacement::Position position = placement.position;
     const gfx::Display& a =
-        display_manager->GetDisplayForId(placement->parent_display_id);
+        display_manager->GetDisplayForId(placement.parent_display_id);
     const gfx::Display& b =
-        display_manager->GetDisplayForId(placement->display_id);
+        display_manager->GetDisplayForId(placement.display_id);
 
     if (position == DisplayPlacement::TOP ||
         position == DisplayPlacement::BOTTOM) {
diff --git a/ash/display/extended_mouse_warp_controller_unittest.cc b/ash/display/extended_mouse_warp_controller_unittest.cc
index 8709620..13f5e02 100644
--- a/ash/display/extended_mouse_warp_controller_unittest.cc
+++ b/ash/display/extended_mouse_warp_controller_unittest.cc
@@ -61,7 +61,7 @@
             mouse_warp_controller()->warp_regions_[0]->b_indicator_bounds());
 
   // Move 2nd display downwards a bit.
-  layout->placement_list[0]->offset = 5;
+  layout->placement_list[0].offset = 5;
   display_manager->SetLayoutForCurrentDisplays(layout->Copy());
   event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
   // This is same as before because the 2nd display's y is above
@@ -79,7 +79,7 @@
 
   // Move it down further so that the shared edge is shorter than
   // minimum hole size (160).
-  layout->placement_list[0]->offset = 200;
+  layout->placement_list[0].offset = 200;
   display_manager->SetLayoutForCurrentDisplays(layout->Copy());
   event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
   ASSERT_EQ(1U, mouse_warp_controller()->warp_regions_.size());
@@ -95,7 +95,7 @@
             mouse_warp_controller()->warp_regions_[0]->b_indicator_bounds());
 
   // Now move 2nd display upwards
-  layout->placement_list[0]->offset = -5;
+  layout->placement_list[0].offset = -5;
   display_manager->SetLayoutForCurrentDisplays(layout->Copy());
   event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
   ASSERT_EQ(1U, mouse_warp_controller()->warp_regions_.size());
@@ -139,7 +139,7 @@
   EXPECT_EQ(gfx::Rect(0, 0, 1, 360),
             mouse_warp_controller()->warp_regions_[0]->b_indicator_bounds());
 
-  layout->placement_list[0]->offset = 250;
+  layout->placement_list[0].offset = 250;
   display_manager->SetLayoutForCurrentDisplays(layout->Copy());
   event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
   ASSERT_EQ(1U, mouse_warp_controller()->warp_regions_.size());
@@ -180,7 +180,7 @@
   EXPECT_EQ(gfx::Rect(0, 0, 360, 1),
             mouse_warp_controller()->warp_regions_[0]->b_indicator_bounds());
 
-  layout->placement_list[0]->offset = 250;
+  layout->placement_list[0].offset = 250;
   display_manager->SetLayoutForCurrentDisplays(layout->Copy());
   event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
   ASSERT_EQ(1U, mouse_warp_controller()->warp_regions_.size());
@@ -195,8 +195,8 @@
   EXPECT_EQ(gfx::Rect(250, 0, 110, 1),
             mouse_warp_controller()->warp_regions_[0]->b_indicator_bounds());
 
-  layout->placement_list[0]->position = DisplayPlacement::BOTTOM;
-  layout->placement_list[0]->offset = 0;
+  layout->placement_list[0].position = DisplayPlacement::BOTTOM;
+  layout->placement_list[0].offset = 0;
   display_manager->SetLayoutForCurrentDisplays(layout->Copy());
   event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
   ASSERT_EQ(1U, mouse_warp_controller()->warp_regions_.size());
diff --git a/ash/display/json_converter.cc b/ash/display/json_converter.cc
index 91017b6..63a7efe76 100644
--- a/ash/display/json_converter.cc
+++ b/ash/display/json_converter.cc
@@ -9,7 +9,6 @@
 #include "ash/display/display_layout.h"
 #include "ash/display/display_pref_util.h"
 #include "base/logging.h"
-#include "base/memory/scoped_vector.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
 
@@ -40,7 +39,7 @@
     if (!dict_value->GetString(kPositionKey, &position_str))
       return false;
     DisplayPlacement::StringToPosition(position_str, &position);
-    layout->placement_list.push_back(new DisplayPlacement(position, offset));
+    layout->placement_list.emplace_back(position, offset);
   }
   return true;
 }
@@ -112,7 +111,7 @@
 template <>
 bool UpdateFromDict(const base::DictionaryValue* dict_value,
                     const std::string& field_name,
-                    ScopedVector<DisplayPlacement>* output) {
+                    std::vector<DisplayPlacement>* output) {
   bool (base::Value::*getter)(const base::ListValue**) const =
       &base::Value::GetAsList;
   const base::ListValue* list = nullptr;
@@ -128,17 +127,17 @@
     if (!list_item->GetAsDictionary(&item_values))
       return false;
 
-    scoped_ptr<DisplayPlacement> item(new DisplayPlacement);
-    if (!UpdateFromDict(item_values, kOffsetKey, &item->offset) ||
-        !UpdateFromDict(item_values, kPositionKey, &item->position) ||
+    DisplayPlacement item;
+    if (!UpdateFromDict(item_values, kOffsetKey, &item.offset) ||
+        !UpdateFromDict(item_values, kPositionKey, &item.position) ||
         !UpdateFromDict(item_values, kDisplayPlacementDisplayIdKey,
-                        &item->display_id) ||
+                        &item.display_id) ||
         !UpdateFromDict(item_values, kDisplayPlacementParentDisplayIdKey,
-                        &item->parent_display_id)) {
+                        &item.parent_display_id)) {
       return false;
     }
 
-    output->push_back(std::move(item));
+    output->push_back(item);
   }
   return true;
 }
@@ -177,17 +176,17 @@
   dict_value->SetString(kPrimaryIdKey, base::Int64ToString(layout.primary_id));
 
   scoped_ptr<base::ListValue> placement_list(new base::ListValue);
-  for (const auto* placement : layout.placement_list) {
+  for (const auto& placement : layout.placement_list) {
     scoped_ptr<base::DictionaryValue> placement_value(
         new base::DictionaryValue);
     placement_value->SetString(
-        kPositionKey, DisplayPlacement::PositionToString(placement->position));
-    placement_value->SetInteger(kOffsetKey, placement->offset);
+        kPositionKey, DisplayPlacement::PositionToString(placement.position));
+    placement_value->SetInteger(kOffsetKey, placement.offset);
     placement_value->SetString(kDisplayPlacementDisplayIdKey,
-                               base::Int64ToString(placement->display_id));
+                               base::Int64ToString(placement.display_id));
     placement_value->SetString(
         kDisplayPlacementParentDisplayIdKey,
-        base::Int64ToString(placement->parent_display_id));
+        base::Int64ToString(placement.parent_display_id));
     placement_list->Append(std::move(placement_value));
   }
   dict_value->Set(kDisplayPlacementKey, std::move(placement_list));
diff --git a/ash/display/json_converter_unittest.cc b/ash/display/json_converter_unittest.cc
index 3c964d0..0ac13d8 100644
--- a/ash/display/json_converter_unittest.cc
+++ b/ash/display/json_converter_unittest.cc
@@ -16,16 +16,16 @@
   layout.primary_id = 1;
   layout.mirrored = true;
   layout.default_unified = false;
-  layout.placement_list.push_back(new DisplayPlacement);
-  layout.placement_list.push_back(new DisplayPlacement);
-  layout.placement_list[0]->display_id = 2;
-  layout.placement_list[0]->parent_display_id = 1;
-  layout.placement_list[0]->position = DisplayPlacement::BOTTOM;
+  layout.placement_list.push_back(DisplayPlacement());
+  layout.placement_list.push_back(DisplayPlacement());
+  layout.placement_list[0].display_id = 2;
+  layout.placement_list[0].parent_display_id = 1;
+  layout.placement_list[0].position = DisplayPlacement::BOTTOM;
 
-  layout.placement_list[1]->display_id = 3;
-  layout.placement_list[1]->parent_display_id = 2;
-  layout.placement_list[1]->position = DisplayPlacement::LEFT;
-  layout.placement_list[1]->offset = 30;
+  layout.placement_list[1].display_id = 3;
+  layout.placement_list[1].parent_display_id = 2;
+  layout.placement_list[1].position = DisplayPlacement::LEFT;
+  layout.placement_list[1].offset = 30;
 
   base::DictionaryValue value;
   DisplayLayoutToJson(layout, &value);
@@ -85,8 +85,8 @@
   EXPECT_EQ(1, read_layout.primary_id);
   EXPECT_EQ(false, read_layout.default_unified);
   ASSERT_EQ(1u, read_layout.placement_list.size());
-  EXPECT_EQ(DisplayPlacement::BOTTOM, read_layout.placement_list[0]->position);
-  EXPECT_EQ(20, read_layout.placement_list[0]->offset);
+  EXPECT_EQ(DisplayPlacement::BOTTOM, read_layout.placement_list[0].position);
+  EXPECT_EQ(20, read_layout.placement_list[0].offset);
 }
 
 }  // namespace ash
diff --git a/ash/display/mouse_cursor_event_filter_unittest.cc b/ash/display/mouse_cursor_event_filter_unittest.cc
index fb0e586a..0842c694 100644
--- a/ash/display/mouse_cursor_event_filter_unittest.cc
+++ b/ash/display/mouse_cursor_event_filter_unittest.cc
@@ -46,7 +46,7 @@
                                          ->display_manager()
                                          ->GetCurrentDisplayLayout()
                                          .placement_list[0]
-                                         ->position);
+                                         .position);
 
   EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(11, 11)));
 
@@ -86,7 +86,7 @@
                                          ->display_manager()
                                          ->GetCurrentDisplayLayout()
                                          .placement_list[0]
-                                         ->position);
+                                         .position);
 
   // Touch the left edge of the secondary root window. Pointer should NOT warp
   // because 1px left of (0, 500) is outside the primary root window.
@@ -114,7 +114,7 @@
                                          ->display_manager()
                                          ->GetCurrentDisplayLayout()
                                          .placement_list[0]
-                                         ->position);
+                                         .position);
 
   aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(900, 123));
 
diff --git a/ash/display/screen_position_controller_unittest.cc b/ash/display/screen_position_controller_unittest.cc
index 20120b53..333379c 100644
--- a/ash/display/screen_position_controller_unittest.cc
+++ b/ash/display/screen_position_controller_unittest.cc
@@ -46,7 +46,7 @@
                                        ->display_manager()
                                        ->GetCurrentDisplayLayout()
                                        .Copy());
-  layout->placement_list[0]->position = position;
+  layout->placement_list[0].position = position;
   Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays(
       std::move(layout));
 }
diff --git a/ash/display/window_tree_host_manager.cc b/ash/display/window_tree_host_manager.cc
index 4b59621..b24022e 100644
--- a/ash/display/window_tree_host_manager.cc
+++ b/ash/display/window_tree_host_manager.cc
@@ -445,7 +445,7 @@
   // Only update the layout if it is requested to swap primary display.
   if (layout.primary_id != new_primary_display.id()) {
     scoped_ptr<DisplayLayout> swapped_layout(layout.Copy());
-    swapped_layout->placement_list[0]->Swap();
+    swapped_layout->placement_list[0].Swap();
     swapped_layout->primary_id = new_primary_display.id();
     DisplayIdList list = display_manager->GetCurrentDisplayIdList();
     GetDisplayManager()->layout_store()->RegisterLayoutForDisplayIdList(
@@ -775,6 +775,16 @@
                               : layout.primary_id);
     }
   }
+
+  for (const gfx::Display& display : display_manager->active_display_list()) {
+    bool output_is_secure =
+        !display_manager->IsInMirrorMode() && display.IsInternal();
+    GetAshWindowTreeHostForDisplayId(display.id())
+        ->AsWindowTreeHost()
+        ->compositor()
+        ->SetOutputIsSecure(output_is_secure);
+  }
+
   FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged());
   UpdateMouseLocationAfterDisplayChange();
 }
diff --git a/ash/display/window_tree_host_manager_unittest.cc b/ash/display/window_tree_host_manager_unittest.cc
index eb01743..0fdcb58 100644
--- a/ash/display/window_tree_host_manager_unittest.cc
+++ b/ash/display/window_tree_host_manager_unittest.cc
@@ -807,7 +807,7 @@
   EXPECT_EQ("200,0 300x253", secondary_display.work_area().ToString());
   EXPECT_EQ(
       "id=2200000001, parent=2200000000, right, 50",
-      display_manager->GetCurrentDisplayLayout().placement_list[0]->ToString());
+      display_manager->GetCurrentDisplayLayout().placement_list[0].ToString());
 
   // Switch primary and secondary by display ID.
   TestObserver observer;
@@ -828,7 +828,7 @@
       display_manager->GetCurrentDisplayLayout();
 
   EXPECT_EQ("id=2200000000, parent=2200000001, left, -50",
-            inverted_layout.placement_list[0]->ToString());
+            inverted_layout.placement_list[0].ToString());
   // Test if the bounds are correctly swapped.
   gfx::Display swapped_primary = gfx::Screen::GetScreen()->GetPrimaryDisplay();
   gfx::Display swapped_secondary = ScreenUtil::GetSecondaryDisplay();
diff --git a/ash/extended_desktop_unittest.cc b/ash/extended_desktop_unittest.cc
index d4fc79b..035e925d 100644
--- a/ash/extended_desktop_unittest.cc
+++ b/ash/extended_desktop_unittest.cc
@@ -36,7 +36,7 @@
 void SetSecondaryDisplayLayout(DisplayPlacement::Position position) {
   scoped_ptr<DisplayLayout> layout =
       Shell::GetInstance()->display_manager()->GetCurrentDisplayLayout().Copy();
-  layout->placement_list[0]->position = position;
+  layout->placement_list[0].position = position;
   Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays(
       std::move(layout));
 }
diff --git a/ash/mus/sysui_application.cc b/ash/mus/sysui_application.cc
index 15a5186..16585a31 100644
--- a/ash/mus/sysui_application.cc
+++ b/ash/mus/sysui_application.cc
@@ -16,7 +16,6 @@
 #include "ash/shell_window_ids.h"
 #include "base/bind.h"
 #include "base/files/file_path.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "components/mus/public/cpp/property_type_converters.h"
@@ -289,9 +288,5 @@
   return true;
 }
 
-void SysUIApplication::ShellConnectionLost() {
-  base::MessageLoop::current()->QuitWhenIdle();
-}
-
 }  // namespace sysui
 }  // namespace ash
diff --git a/ash/mus/sysui_application.h b/ash/mus/sysui_application.h
index 2535c5e0..dba0f5e 100644
--- a/ash/mus/sysui_application.h
+++ b/ash/mus/sysui_application.h
@@ -26,7 +26,6 @@
                   const mojo::Identity& identity,
                   uint32_t id) override;
   bool AcceptConnection(mojo::Connection* connection) override;
-  void ShellConnectionLost() override;
 
   mojo::TracingImpl tracing_;
   scoped_ptr<AshInit> ash_init_;
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index e61e7aa7..b3ddf68 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -1906,7 +1906,7 @@
 
 bool ShelfView::ShouldShowTooltipForView(const views::View* view) const {
   if (view == GetAppListButtonView() &&
-      Shell::GetInstance()->GetAppListWindow())
+      Shell::GetInstance()->GetAppListTargetVisibility())
     return false;
   const ShelfItem* item = ShelfItemForView(view);
   if (!item)
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc
index 994e146..71e5e7f 100644
--- a/ash/shelf/shelf_view_unittest.cc
+++ b/ash/shelf/shelf_view_unittest.cc
@@ -1517,7 +1517,7 @@
 
 TEST_F(ShelfViewTest, ShouldHideTooltipWithAppListWindowTest) {
   Shell::GetInstance()->ShowAppList(NULL);
-  ASSERT_TRUE(Shell::GetInstance()->GetAppListWindow());
+  ASSERT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility());
 
   // The tooltip shouldn't hide if the mouse is on normal buttons.
   for (int i = 1; i < test_api_->GetButtonCount(); i++) {
diff --git a/ash/shell.h b/ash/shell.h
index fbd85b8..d929dba5 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -250,7 +250,7 @@
   // Returns app list window or NULL if it is not visible.
   aura::Window* GetAppListWindow();
 
-  // Returns app list view or NULL if it is not visible.
+  // Returns app list view if one exists, or NULL otherwise.
   app_list::AppListView* GetAppListView();
 
   // Returns true if a system-modal dialog window is currently open.
diff --git a/ash/wm/app_list_controller.h b/ash/wm/app_list_controller.h
index 3364b11..1f3114c 100644
--- a/ash/wm/app_list_controller.h
+++ b/ash/wm/app_list_controller.h
@@ -65,7 +65,7 @@
   // Returns app list window or NULL if it is not visible.
   aura::Window* GetWindow();
 
-  // Returns app list view or NULL if it is not visible.
+  // Returns app list view if one exists, or NULL otherwise.
   app_list::AppListView* GetView() { return view_; }
 
  private:
diff --git a/base/bind_helpers.h b/base/bind_helpers.h
index 81dba6d8..d19c749 100644
--- a/base/bind_helpers.h
+++ b/base/bind_helpers.h
@@ -431,11 +431,6 @@
 }
 
 template <typename T>
-T* Unwrap(const scoped_refptr<T>& o) {
-  return o.get();
-}
-
-template <typename T>
 T* Unwrap(const RetainedRefWrapper<T>& o) {
   return o.get();
 }
diff --git a/base/bind_internal.h b/base/bind_internal.h
index 199467c..de14bff 100644
--- a/base/bind_internal.h
+++ b/base/bind_internal.h
@@ -181,6 +181,11 @@
     return (object->*method_)(std::forward<RunArgs>(args)...);
   }
 
+  template <typename RefType, typename... RunArgs>
+  R Run(const scoped_refptr<RefType>& object, RunArgs&&... args) {
+    return (object.get()->*method_)(std::forward<RunArgs>(args)...);
+  }
+
  private:
   R (T::*method_)(Args...);
 };
@@ -201,6 +206,11 @@
     return (object->*method_)(std::forward<RunArgs>(args)...);
   }
 
+  template <typename RefType, typename... RunArgs>
+  R Run(const scoped_refptr<RefType>& object, RunArgs&&... args) {
+    return (object.get()->*method_)(std::forward<RunArgs>(args)...);
+  }
+
  private:
   R (T::*method_)(Args...) const;
 };
diff --git a/base/mac/sdk_forward_declarations.h b/base/mac/sdk_forward_declarations.h
index c9b7d64..d5b85ae 100644
--- a/base/mac/sdk_forward_declarations.h
+++ b/base/mac/sdk_forward_declarations.h
@@ -346,6 +346,10 @@
 @interface NSView (LionSDK)
 - (NSSize)convertSizeFromBacking:(NSSize)size;
 - (void)setWantsBestResolutionOpenGLSurface:(BOOL)flag;
+- (NSDraggingSession*)beginDraggingSessionWithItems:(NSArray*)items
+                                              event:(NSEvent*)event
+                                             source:
+                                                 (id<NSDraggingSource>)source;
 @end
 
 @interface NSObject (ICCameraDeviceDelegateLionSDK)
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc
index b0f5e4e9..35197e2 100644
--- a/base/metrics/histogram.cc
+++ b/base/metrics/histogram.cc
@@ -153,21 +153,10 @@
   PersistentHistogramAllocator::ImportGlobalHistograms();
 
   HistogramBase* histogram = StatisticsRecorder::FindHistogram(name_);
-
-  // crbug.com/588946 debugging. See comment at end of function.
-  const BucketRanges* created_ranges =
-      reinterpret_cast<const BucketRanges*>(0xDEADBEEF);
-  const BucketRanges* registered_ranges =
-      reinterpret_cast<const BucketRanges*>(0xDEADBEEF);
-  scoped_ptr<HistogramBase> tentative_histogram;
-  PersistentHistogramAllocator* allocator =
-      reinterpret_cast<PersistentHistogramAllocator*>(0xDEADBEEF);
-  PersistentHistogramAllocator::Reference histogram_ref = 0xDEADBEEF;
-
   if (!histogram) {
     // To avoid racy destruction at shutdown, the following will be leaked.
-    created_ranges = CreateRanges();
-    registered_ranges =
+    const BucketRanges* created_ranges = CreateRanges();
+    const BucketRanges* registered_ranges =
         StatisticsRecorder::RegisterOrDeleteDuplicateRanges(created_ranges);
 
     // In most cases, the bucket-count, minimum, and maximum values are known
@@ -180,15 +169,15 @@
       minimum_ = registered_ranges->range(1);
       maximum_ = registered_ranges->range(bucket_count_ - 1);
     }
-    CHECK_LT(0, minimum_);
-    CHECK_LT(0, maximum_);
 
     // Try to create the histogram using a "persistent" allocator. As of
     // 2016-02-25, the availability of such is controlled by a base::Feature
     // that is off by default. If the allocator doesn't exist or if
     // allocating from it fails, code below will allocate the histogram from
     // the process heap.
-    allocator =
+    PersistentHistogramAllocator::Reference histogram_ref = 0;
+    scoped_ptr<HistogramBase> tentative_histogram;
+    PersistentHistogramAllocator* allocator =
         PersistentHistogramAllocator::GetGlobalAllocator();
     if (allocator) {
       tentative_histogram = allocator->AllocateHistogram(
@@ -199,33 +188,16 @@
           registered_ranges,
           flags_,
           &histogram_ref);
-      CHECK_LT(0, minimum_);
-      CHECK_LT(0, maximum_);
-      CHECK_EQ(
-          minimum_,
-          static_cast<Histogram*>(tentative_histogram.get())->declared_min_);
-      CHECK_EQ(
-          maximum_,
-          static_cast<Histogram*>(tentative_histogram.get())->declared_max_);
     }
 
     // Handle the case where no persistent allocator is present or the
     // persistent allocation fails (perhaps because it is full).
     if (!tentative_histogram) {
-      // DCHECK(!histogram_ref);  // Should never have been set.
-      // DCHECK(!allocator);  // Shouldn't have failed.
+      DCHECK(!histogram_ref);  // Should never have been set.
+      DCHECK(!allocator);  // Shouldn't have failed.
       flags_ &= ~HistogramBase::kIsPersistent;
       tentative_histogram = HeapAlloc(registered_ranges);
       tentative_histogram->SetFlags(flags_);
-
-      CHECK_LT(0, minimum_);
-      CHECK_LT(0, maximum_);
-      CHECK_EQ(
-          minimum_,
-          static_cast<Histogram*>(tentative_histogram.get())->declared_min_);
-      CHECK_EQ(
-          maximum_,
-          static_cast<Histogram*>(tentative_histogram.get())->declared_max_);
     }
 
     FillHistogram(tentative_histogram.get());
@@ -239,7 +211,7 @@
         tentative_histogram.release());
 
     // Persistent histograms need some follow-up processing.
-    if (histogram_ref != 0xDEADBEEF) {
+    if (histogram_ref) {
       allocator->FinalizeHistogram(histogram_ref,
                                    histogram == tentative_histogram_ptr);
     }
@@ -252,15 +224,6 @@
   }
 
   DCHECK_EQ(histogram_type_, histogram->GetHistogramType()) << name_;
-  bool bad_args = false;
-  HistogramBase* existing_histogram = histogram;
-  HistogramType existing_type = histogram->GetHistogramType();
-  const char* existing_name = histogram->histogram_name().c_str();
-  Sample existing_minimum = static_cast<Histogram*>(histogram)->declared_min_;
-  Sample existing_maximum = static_cast<Histogram*>(histogram)->declared_max_;
-  uint32_t existing_bucket_count =
-    static_cast<Histogram*>(histogram)->bucket_count();
-
   if (bucket_count_ != 0 &&
       !histogram->HasConstructionArguments(minimum_, maximum_, bucket_count_)) {
     // The construction arguments do not match the existing histogram.  This can
@@ -270,45 +233,8 @@
     // on dereference, but extension/Pepper APIs will guard against NULL and not
     // crash.
     DLOG(ERROR) << "Histogram " << name_ << " has bad construction arguments";
-    bad_args = true;
-    histogram = nullptr;
+    return nullptr;
   }
-
-#if !DCHECK_IS_ON() && defined(OS_WIN)  // Affect only Windows release builds.
-  // For the moment, crash here so that collected crash reports have access
-  // to the construction values in order to figure out why this is failing.
-  // TODO(bcwhite): Remove this once crbug.com/588946 is resolved. Also remove
-  // from beta-branch because we don't want crashes due to misbehaving
-  // extensions (see comment above).
-  if (!histogram) {
-    HistogramType histogram_type = histogram_type_;
-    HistogramBase::Sample minimum = minimum_;
-    HistogramBase::Sample maximum = maximum_;
-    uint32_t bucket_count = bucket_count_;
-    int32_t flags = flags_;
-    CHECK(histogram) << name_ << ": bad-args=" << bad_args;
-    base::debug::Alias(&histogram_type);
-    base::debug::Alias(&minimum);
-    base::debug::Alias(&maximum);
-    base::debug::Alias(&bucket_count);
-    base::debug::Alias(&flags);
-    base::debug::Alias(&created_ranges);
-    base::debug::Alias(&registered_ranges);
-    base::debug::Alias(&histogram_ref);
-    base::debug::Alias(&tentative_histogram);
-    base::debug::Alias(&allocator);
-    base::debug::Alias(&tentative_histogram);
-  }
-#endif
-
-  // Down here so vars are always "used".
-  base::debug::Alias(&bad_args);
-  base::debug::Alias(&existing_histogram);
-  base::debug::Alias(&existing_type);
-  base::debug::Alias(&existing_name);
-  base::debug::Alias(&existing_minimum);
-  base::debug::Alias(&existing_maximum);
-  base::debug::Alias(&existing_bucket_count);
   return histogram;
 }
 
@@ -571,12 +497,8 @@
     bucket_ranges_(ranges),
     declared_min_(minimum),
     declared_max_(maximum) {
-  CHECK_LT(0, minimum);
-  CHECK_LT(0, maximum);
   if (ranges)
     samples_.reset(new SampleVector(HashMetricName(name), ranges));
-  CHECK_EQ(minimum, declared_min_);
-  CHECK_EQ(maximum, declared_max_);
 }
 
 Histogram::Histogram(const std::string& name,
@@ -592,16 +514,12 @@
     bucket_ranges_(ranges),
     declared_min_(minimum),
     declared_max_(maximum) {
-  CHECK_LT(0, minimum);
-  CHECK_LT(0, maximum);
   if (ranges) {
     samples_.reset(new SampleVector(HashMetricName(name),
                                     counts, counts_size, meta, ranges));
     logged_samples_.reset(new SampleVector(samples_->id(), logged_counts,
                                            counts_size, logged_meta, ranges));
   }
-  CHECK_EQ(minimum, declared_min_);
-  CHECK_EQ(maximum, declared_max_);
 }
 
 Histogram::~Histogram() {
diff --git a/base/metrics/histogram_unittest.cc b/base/metrics/histogram_unittest.cc
index 15109b1a..03dc7bd 100644
--- a/base/metrics/histogram_unittest.cc
+++ b/base/metrics/histogram_unittest.cc
@@ -574,7 +574,7 @@
   EXPECT_FALSE(iter.SkipBytes(1));
 }
 
-TEST_P(HistogramTest, DISABLED_BadConstruction) {
+TEST_P(HistogramTest, BadConstruction) {
   HistogramBase* histogram = Histogram::FactoryGet(
       "BadConstruction", 0, 100, 8, HistogramBase::kNoFlags);
   EXPECT_TRUE(histogram->HasConstructionArguments(1, 100, 8));
diff --git a/base/metrics/metrics_hashes.cc b/base/metrics/metrics_hashes.cc
index 9b60401..5672b06d 100644
--- a/base/metrics/metrics_hashes.cc
+++ b/base/metrics/metrics_hashes.cc
@@ -4,7 +4,6 @@
 
 #include "base/metrics/metrics_hashes.h"
 
-#include "base/debug/alias.h"
 #include "base/logging.h"
 #include "base/md5.h"
 #include "base/sys_byteorder.h"
@@ -16,42 +15,16 @@
 // Converts the 8-byte prefix of an MD5 hash into a uint64_t value.
 inline uint64_t DigestToUInt64(const base::MD5Digest& digest) {
   uint64_t value;
-  CHECK_GE(sizeof(digest.a), sizeof(value));
+  DCHECK_GE(sizeof(digest.a), sizeof(value));
   memcpy(&value, digest.a, sizeof(value));
-  uint64_t hash = base::NetToHost64(value);
-  CHECK_NE(0U, hash);
-  base::debug::Alias(&hash);
-  base::debug::Alias(&value);
-  base::debug::Alias(&digest);
-  return hash;
+  return base::NetToHost64(value);
 }
 
 }  // namespace
 
 uint64_t HashMetricName(base::StringPiece name) {
-  base::MD5Digest digest = {{
-    0x0F, 0x0E, 0x0D, 0x0C, 0x00, 0x0D, 0x0E, 0x02,
-    0x0D, 0x0E, 0x0A, 0x0D, 0x0B, 0x0E, 0x0E, 0x0F
-  }};
+  base::MD5Digest digest;
   base::MD5Sum(name.data(), name.size(), &digest);
-  CHECK(
-      digest.a[0] != 0x0F ||
-      digest.a[1] != 0x0E ||
-      digest.a[2] != 0x0D ||
-      digest.a[3] != 0x0C ||
-      digest.a[4] != 0x00 ||
-      digest.a[5] != 0x0D ||
-      digest.a[6] != 0x0E ||
-      digest.a[7] != 0x02 ||
-      digest.a[8] != 0x0D ||
-      digest.a[9] != 0x0E ||
-      digest.a[10] != 0x0A ||
-      digest.a[11] != 0x0D ||
-      digest.a[12] != 0x0B ||
-      digest.a[13] != 0x0E ||
-      digest.a[14] != 0x0E ||
-      digest.a[15] != 0x0F);
-  base::debug::Alias(&name);
   return DigestToUInt64(digest);
 }
 
diff --git a/base/metrics/persistent_histogram_allocator.cc b/base/metrics/persistent_histogram_allocator.cc
index 0eab0163..6006d31 100644
--- a/base/metrics/persistent_histogram_allocator.cc
+++ b/base/metrics/persistent_histogram_allocator.cc
@@ -295,12 +295,6 @@
   // validated below; the local copy is to ensure that the contents cannot
   // be externally changed between validation and use.
   PersistentHistogramData histogram_data = *histogram_data_ptr;
-  CHECK_EQ(histogram_data.histogram_type, histogram_data_ptr->histogram_type);
-  CHECK_EQ(histogram_data.flags, histogram_data_ptr->flags);
-  CHECK_EQ(histogram_data.minimum, histogram_data_ptr->minimum);
-  CHECK_EQ(histogram_data.maximum, histogram_data_ptr->maximum);
-  CHECK_EQ(histogram_data.bucket_count, histogram_data_ptr->bucket_count);
-  CHECK_EQ(histogram_data.ranges_checksum, histogram_data_ptr->ranges_checksum);
 
   HistogramBase::Sample* ranges_data =
       memory_allocator_->GetAsObject<HistogramBase::Sample>(
@@ -351,8 +345,6 @@
   HistogramBase::AtomicCount* logged_data =
       counts_data + histogram_data.bucket_count;
 
-  CHECK_LT(0, histogram_data.minimum);
-  CHECK_LT(0, histogram_data.maximum);
   std::string name(histogram_data_ptr->name);
   scoped_ptr<HistogramBase> histogram;
   switch (histogram_data.histogram_type) {
diff --git a/base/metrics/statistics_recorder.cc b/base/metrics/statistics_recorder.cc
index 50c4836c..2bb50ad 100644
--- a/base/metrics/statistics_recorder.cc
+++ b/base/metrics/statistics_recorder.cc
@@ -5,7 +5,6 @@
 #include "base/metrics/statistics_recorder.h"
 
 #include "base/at_exit.h"
-#include "base/debug/alias.h"
 #include "base/debug/leak_annotations.h"
 #include "base/json/string_escape.h"
 #include "base/logging.h"
@@ -133,17 +132,13 @@
         histogram_to_return = histogram;
       } else {
         // We already have one histogram with this name.
-        CHECK_EQ(histogram->histogram_name(),
-                 it->second->histogram_name()) << "hash collision";
+        DCHECK_EQ(histogram->histogram_name(),
+                  it->second->histogram_name()) << "hash collision";
         histogram_to_return = it->second;
         histogram_to_delete = histogram;
       }
-      base::debug::Alias(&it);
-      base::debug::Alias(&name);
-      base::debug::Alias(&name_hash);
     }
   }
-  base::debug::Alias(&histogram);
   delete histogram_to_delete;
   return histogram_to_return;
 }
@@ -293,22 +288,10 @@
   if (histograms_ == NULL)
     return NULL;
 
-  const uint64_t lookup_hash = HashMetricName(name);
-  HistogramMap::iterator it = histograms_->find(lookup_hash);
+  HistogramMap::iterator it = histograms_->find(HashMetricName(name));
   if (histograms_->end() == it)
     return NULL;
-
-  const uint64_t existing_hash = it->first;
-  const char* existing_name = it->second->histogram_name().c_str();
-  HistogramMap* histograms = histograms_;
-  CHECK_EQ(name, it->second->histogram_name()) << "hash collision";
-  base::debug::Alias(&lookup_hash);
-  base::debug::Alias(&existing_hash);
-  base::debug::Alias(&name);
-  base::debug::Alias(&existing_name);
-  base::debug::Alias(&it);
-  base::debug::Alias(&histograms);
-
+  DCHECK_EQ(name, it->second->histogram_name()) << "hash collision";
   return it->second;
 }
 
diff --git a/blimp/docs/running.md b/blimp/docs/running.md
index bb92199f..9d640e14 100644
--- a/blimp/docs/running.md
+++ b/blimp/docs/running.md
@@ -102,6 +102,8 @@
   destroyed before serialization.
 * `--android-fonts-path=$PATH`: Path to where the fonts are located.
   Typically this would be `out-linux/Debug/gen/third_party/blimp_fonts`.
+* `--disable-remote-fonts`: Disables downloading of custom web fonts in the
+  renderer.
 
 #### Typical invocation
 When the client connects to a manually specified engine instead of using the
diff --git a/blimp/engine/app/ui/blimp_ui_context_factory.cc b/blimp/engine/app/ui/blimp_ui_context_factory.cc
index d41150a2..b9246d0 100644
--- a/blimp/engine/app/ui/blimp_ui_context_factory.cc
+++ b/blimp/engine/app/ui/blimp_ui_context_factory.cc
@@ -20,7 +20,6 @@
 
 void BlimpUiContextFactory::CreateOutputSurface(
     base::WeakPtr<ui::Compositor> compositor) {
-  NOTIMPLEMENTED();
 }
 
 scoped_ptr<ui::Reflector> BlimpUiContextFactory::CreateReflector(
@@ -55,7 +54,6 @@
 }
 
 cc::SharedBitmapManager* BlimpUiContextFactory::GetSharedBitmapManager() {
-  NOTIMPLEMENTED();
   return nullptr;
 }
 
@@ -76,7 +74,6 @@
 
 void BlimpUiContextFactory::ResizeDisplay(ui::Compositor* compositor,
                                           const gfx::Size& size) {
-  NOTIMPLEMENTED();
 }
 
 }  // namespace engine
diff --git a/blimp/engine/session/blimp_engine_session.cc b/blimp/engine/session/blimp_engine_session.cc
index eb144b1..64d0e8f 100644
--- a/blimp/engine/session/blimp_engine_session.cc
+++ b/blimp/engine/session/blimp_engine_session.cc
@@ -468,8 +468,8 @@
     details->set_url(source->GetURL().spec());
 
   if (changed_flags & content::InvalidateTypes::INVALIDATE_TYPE_TAB) {
-    // TODO(dtrainor): Serialize the favicon?
-    NOTIMPLEMENTED();
+    // TODO(dtrainor): Serialize the favicon? crbug.com/597094.
+    DVLOG(3) << "Tab favicon changed";
   }
 
   if (changed_flags & content::InvalidateTypes::INVALIDATE_TYPE_TITLE)
diff --git a/blimp/engine/start_engine.sh b/blimp/engine/start_engine.sh
index a9cf193..519f317 100755
--- a/blimp/engine/start_engine.sh
+++ b/blimp/engine/start_engine.sh
@@ -14,6 +14,7 @@
   --disable-cached-picture-raster \
   --blimp-client-token-path=/engine/data/client_token \
   --android-fonts-path=/engine/fonts \
+  --disable-remote-fonts \
   $@ &
 
 # Stop execution if either stunnel or blimp_engine_app die.
diff --git a/build/android/BUILD.gn b/build/android/BUILD.gn
index 01deb142..73b25cd 100644
--- a/build/android/BUILD.gn
+++ b/build/android/BUILD.gn
@@ -10,37 +10,9 @@
 # Create or update the API versions cache if necessary by running a
 # functionally empty lint task. This prevents racy creation of the
 # cache while linting java targets in android_lint.
-action("prepare_android_lint_cache") {
-  _cache_dir = "${root_out_dir}/android_lint_cache"
-  depfile = "${_cache_dir}/prepare_android_lint_cache.d"
-  _manifest_file = "//build/android/AndroidManifest.xml"
-  _result_file = "${_cache_dir}/result.xml"
-  script = "//build/android/gyp/lint.py"
-
-  inputs = [
-    "${android_sdk_root}/platform-tools/api/api-versions.xml",
-  ]
-  outputs = [
-    depfile,
-  ]
-  args = [
-    "--build-tools-version",
-    android_sdk_build_tools_version,
-    "--cache-dir",
-    rebase_path(_cache_dir, root_build_dir),
-    "--depfile",
-    rebase_path(depfile, root_build_dir),
-    "--lint-path",
-    "$rebased_android_sdk_root/tools/lint",
-    "--manifest-path",
-    rebase_path(_manifest_file, root_build_dir),
-    "--product-dir",
-    ".",
-    "--result-path",
-    rebase_path(_result_file, root_build_dir),
-    "--silent",
-    "--enable",
-  ]
+android_lint("prepare_android_lint_cache") {
+  android_manifest = "//build/android/AndroidManifest.xml"
+  create_cache = true
 }
 
 action("find_sun_tools_jar") {
diff --git a/build/android/android_lint_cache.gyp b/build/android/android_lint_cache.gyp
index a8b514eca..20b5f77 100644
--- a/build/android/android_lint_cache.gyp
+++ b/build/android/android_lint_cache.gyp
@@ -37,6 +37,7 @@
             '--product-dir', '<(PRODUCT_DIR)',
             '--result-path', '<(result_path)',
             '--stamp', '<(android_lint_cache_stamp)',
+            '--create-cache',
             '--silent',
             '--enable'
           ],
diff --git a/build/android/gyp/lint.py b/build/android/gyp/lint.py
index 9814bf0a..0aad9c5 100755
--- a/build/android/gyp/lint.py
+++ b/build/android/gyp/lint.py
@@ -130,11 +130,16 @@
       os.remove(result_path)
 
     env = {}
+    stderr_filter = None
     if cache_dir:
+      # When _JAVA_OPTIONS is set, java prints to stderr:
+      # Picked up _JAVA_OPTIONS: ...
       env['_JAVA_OPTIONS'] = '-Duser.home=%s' % _RelativizePath(cache_dir)
+      stderr_filter = lambda l: '' if '_JAVA_OPTIONS' in l else l
 
     try:
-      build_utils.CheckOutput(cmd, cwd=_SRC_ROOT, env=env or None)
+      build_utils.CheckOutput(cmd, cwd=_SRC_ROOT, env=env or None,
+                              stderr_filter=stderr_filter)
     except build_utils.CalledProcessError:
       if can_fail_build:
         traceback.print_exc()
@@ -192,6 +197,9 @@
   parser.add_argument('--cache-dir',
                       help='Path to the directory in which the android cache '
                            'directory tree should be stored.')
+  parser.add_argument('--create-cache', action='store_true',
+                      help='Mark the lint cache file as an output rather than '
+                      'an input.')
   parser.add_argument('--can-fail-build', action='store_true',
                       help='If set, script will exit with nonzero exit status'
                            ' if lint errors are present')
@@ -257,9 +265,13 @@
     if args.cache_dir:
       if not args.build_tools_version:
         parser.error('--cache-dir specified without --build-tools-version')
-      output_paths.append(os.path.join(
-          args.cache_dir, '.android', 'cache',
-          'api-versions-6-%s.bin' % args.build_tools_version))
+      _cache_file = os.path.join(
+            args.cache_dir, '.android', 'cache',
+            'api-versions-6-%s.bin' % args.build_tools_version)
+      if args.create_cache:
+        output_paths.append(_cache_file)
+      else:
+        input_paths.append(_cache_file)
 
     build_utils.CallAndWriteDepfileIfStale(
         lambda changes: _OnStaleMd5(changes, args.lint_path,
diff --git a/build/common.gypi b/build/common.gypi
index 94b3b3a..aea53b9 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -3275,6 +3275,8 @@
               # which started happening more regularly after VS2013 Update 4.
               # Needs to be a bit lower for VS2015, or else errors out.
               '/maxilksize:0x7ff00000',
+              # Tell the linker to crash on failures.
+              '/fastfail',
             ],
           },
         },
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 79805d15a..72cf046 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -24,13 +24,6 @@
 }
 
 template("android_lint") {
-  set_sources_assignment_filter([])
-
-  jar_path = invoker.jar_path
-  android_manifest = invoker.android_manifest
-  java_files = invoker.java_files
-  base_path = "$target_gen_dir/$target_name"
-
   action(target_name) {
     deps = []
     forward_variables_from(invoker,
@@ -40,41 +33,65 @@
                              "public_deps",
                              "testonly",
                            ])
-    script = "//build/android/gyp/lint.py"
-    result_path = base_path + "/result.xml"
-    config_path = base_path + "/config.xml"
-    suppressions_file = "//build/android/lint/suppressions.xml"
-    inputs = [
-               suppressions_file,
-               android_manifest,
-               jar_path,
-             ] + java_files
+    _cache_dir = "$root_build_dir/android_lint_cache"
+    _result_path = "$target_gen_dir/$target_name/result.xml"
+    _config_path = "$target_gen_dir/$target_name/config.xml"
+    _suppressions_file = "//build/android/lint/suppressions.xml"
+    _cache_file = "$_cache_dir/.android/cache/api-versions-6-${android_sdk_build_tools_version}.bin"
 
-    outputs = [
-      config_path,
-      result_path,
+    script = "//build/android/gyp/lint.py"
+    depfile = "$target_gen_dir/$target_name.d"
+    inputs = [
+      "${android_sdk_root}/platform-tools/api/api-versions.xml",
+      _suppressions_file,
+      invoker.android_manifest,
     ]
 
-    deps += [ "//build/android:prepare_android_lint_cache" ]
-
-    rebased_java_files = rebase_path(java_files, root_build_dir)
+    outputs = [
+      depfile,
+      _config_path,
+      _result_path,
+    ]
 
     args = [
       "--lint-path=$rebased_android_sdk_root/tools/lint",
+      "--cache-dir",
+      rebase_path(_cache_dir, root_build_dir),
+      "--build-tools-version",
+      android_sdk_build_tools_version,
+      "--depfile",
+      rebase_path(depfile, root_build_dir),
       "--config-path",
-      rebase_path(suppressions_file, root_build_dir),
+      rebase_path(_suppressions_file, root_build_dir),
       "--manifest-path",
-      rebase_path(android_manifest, root_build_dir),
+      rebase_path(invoker.android_manifest, root_build_dir),
       "--product-dir=.",
-      "--jar-path",
-      rebase_path(jar_path, root_build_dir),
       "--processed-config-path",
-      rebase_path(config_path, root_build_dir),
+      rebase_path(_config_path, root_build_dir),
       "--result-path",
-      rebase_path(result_path, root_build_dir),
-      "--java-files=$rebased_java_files",
+      rebase_path(_result_path, root_build_dir),
       "--enable",
     ]
+
+    if (defined(invoker.create_cache) && invoker.create_cache) {
+      outputs += [ _cache_file ]
+      args += [
+        "--create-cache",
+        "--silent",
+      ]
+    } else {
+      inputs += [
+                  _cache_file,
+                  invoker.jar_path,
+                ] + invoker.java_files
+      deps += [ "//build/android:prepare_android_lint_cache" ]
+      _rebased_java_files = rebase_path(invoker.java_files, root_build_dir)
+      args += [
+        "--jar-path",
+        rebase_path(invoker.jar_path, root_build_dir),
+        "--java-files=$_rebased_java_files",
+      ]
+    }
   }
 }
 
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index b71d146..a096d56d 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -143,6 +143,19 @@
     ":compiler_codegen",
   ]
 
+  if (is_win) {
+    ldflags += [
+      # Suggested by Microsoft Devrel to avoid
+      #   LINK : fatal error LNK1248: image size (80000000) exceeds maximum allowable size (80000000)
+      # which started happening more regularly after VS2013 Update 4.
+      # Needs to be a bit lower for VS2015, or else errors out.
+      "/maxilksize:0x7ff00000",
+
+      # Tell the linker to crash on failures.
+      "/fastfail",
+    ]
+  }
+
   # In general, Windows is totally different, but all the other builds share
   # some common GCC configuration.
   if (!is_win) {
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py
index 2977159..4d0380e 100755
--- a/build/vs_toolchain.py
+++ b/build/vs_toolchain.py
@@ -331,6 +331,12 @@
   return 0
 
 
+def NormalizePath(path):
+  while path.endswith("\\"):
+    path = path[:-1]
+  return path
+
+
 def GetToolchainDir():
   """Gets location information about the current toolchain (must have been
   previously updated by 'update'). This is used for the GN build."""
@@ -348,10 +354,10 @@
 wdk_dir = "%s"
 runtime_dirs = "%s"
 ''' % (
-      os.environ['GYP_MSVS_OVERRIDE_PATH'],
-      os.environ['WINDOWSSDKDIR'],
+      NormalizePath(os.environ['GYP_MSVS_OVERRIDE_PATH']),
+      NormalizePath(os.environ['WINDOWSSDKDIR']),
       GetVisualStudioVersion(),
-      os.environ.get('WDK_DIR', ''),
+      NormalizePath(os.environ.get('WDK_DIR', '')),
       os.path.pathsep.join(runtime_dll_dirs or ['None']))
 
 
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 3ef1ab6..99b5fe5 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -466,10 +466,6 @@
                                      : user_scrollable_vertical_;
 }
 
-sk_sp<SkPicture> LayerImpl::GetPicture() {
-  return nullptr;
-}
-
 scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) {
   return LayerImpl::Create(tree_impl, layer_id_);
 }
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index 97ff96c..f0044f56 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -34,7 +34,6 @@
 #include "cc/tiles/tile_priority.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkImageFilter.h"
-#include "third_party/skia/include/core/SkPicture.h"
 #include "ui/gfx/geometry/point3_f.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/rect_f.h"
@@ -526,8 +525,6 @@
   // ReleaseResources call.
   virtual void RecreateResources();
 
-  virtual sk_sp<SkPicture> GetPicture();
-
   virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl);
   virtual void PushPropertiesTo(LayerImpl* layer);
 
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 6f5c125..cf2e36a 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -649,10 +649,6 @@
   layer_tree_impl()->set_needs_update_draw_properties();
 }
 
-sk_sp<SkPicture> PictureLayerImpl::GetPicture() {
-  return raster_source_->GetFlattenedPicture();
-}
-
 Region PictureLayerImpl::GetInvalidationRegionForDebugging() {
   // |invalidation_| gives the invalidation contained in the source frame, but
   // is not cleared after drawing from the layer. However, update_rect() is
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index c4f4257..6b10911 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -17,8 +17,6 @@
 #include "cc/tiles/picture_layer_tiling.h"
 #include "cc/tiles/picture_layer_tiling_set.h"
 #include "cc/tiles/tiling_set_eviction_queue.h"
-#include "skia/ext/refptr.h"
-#include "third_party/skia/include/core/SkPicture.h"
 
 namespace cc {
 
@@ -49,7 +47,6 @@
   void DidBeginTracing() override;
   void ReleaseResources() override;
   void RecreateResources() override;
-  sk_sp<SkPicture> GetPicture() override;
   Region GetInvalidationRegionForDebugging() override;
 
   // PictureLayerTilingClient overrides.
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc
index c1a688e..12efed0 100644
--- a/cc/layers/texture_layer_impl.cc
+++ b/cc/layers/texture_layer_impl.cc
@@ -166,8 +166,7 @@
     return;
 
   if (!texture_mailbox_.secure_output_only() ||
-      (layer_tree_impl()->output_surface()->is_secure() &&
-       !AnchestorHasCopyRequest())) {
+      (layer_tree_impl()->OutputIsSecure() && !AnchestorHasCopyRequest())) {
     TextureDrawQuad* quad =
         render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
     ResourceId id =
diff --git a/cc/layers/texture_layer_impl_unittest.cc b/cc/layers/texture_layer_impl_unittest.cc
index 5b3bac8..997a5c0 100644
--- a/cc/layers/texture_layer_impl_unittest.cc
+++ b/cc/layers/texture_layer_impl_unittest.cc
@@ -103,7 +103,7 @@
   }
 }
 
-TEST(TextureLayerImplTest, Protected) {
+TEST(TextureLayerImplTest, OutputIsSecure) {
   gfx::Size layer_size(1000, 1000);
   gfx::Size viewport_size(1000, 1000);
 
@@ -138,7 +138,7 @@
   }
 
   {
-    impl.SetSecureOutputSurface(true);
+    impl.SetOutputIsSecure(true);
     gfx::Rect occluded;
     impl.AppendQuadsWithOcclusion(texture_layer_impl, occluded);
 
@@ -148,7 +148,7 @@
   }
 
   {
-    impl.SetSecureOutputSurface(false);
+    impl.SetOutputIsSecure(false);
     impl.RequestCopyOfOutput();
     gfx::Rect occluded;
     impl.AppendQuadsWithOcclusion(texture_layer_impl, occluded);
diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h
index 64cb19e..43cacfee 100644
--- a/cc/output/output_surface.h
+++ b/cc/output/output_surface.h
@@ -167,10 +167,6 @@
   bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                     base::trace_event::ProcessMemoryDump* pmd) override;
 
-  // Is this output surface associated with a secure display.
-  bool is_secure() const { return is_secure_; }
-  void set_is_secure(bool is_secure) { is_secure_ = is_secure; }
-
  protected:
   OutputSurfaceClient* client_;
 
@@ -196,7 +192,6 @@
  private:
   bool external_stencil_test_enabled_;
 
-  bool is_secure_ = false;
   base::WeakPtrFactory<OutputSurface> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(OutputSurface);
diff --git a/cc/test/fake_proxy.h b/cc/test/fake_proxy.h
index 040c12b..cbb3ead 100644
--- a/cc/test/fake_proxy.h
+++ b/cc/test/fake_proxy.h
@@ -45,6 +45,7 @@
   void UpdateTopControlsState(TopControlsState constraints,
                               TopControlsState current,
                               bool animate) override {}
+  void SetOutputIsSecure(bool output_is_secure) override {}
 
   virtual RendererCapabilities& GetRendererCapabilities();
 
diff --git a/cc/test/layer_test_common.cc b/cc/test/layer_test_common.cc
index 2979d5e4..0e3020ec 100644
--- a/cc/test/layer_test_common.cc
+++ b/cc/test/layer_test_common.cc
@@ -123,10 +123,12 @@
     : client_(FakeLayerTreeHostClient::DIRECT_3D),
       output_surface_(FakeOutputSurface::Create3d()),
       host_(FakeLayerTreeHost::Create(&client_, &task_graph_runner_, settings)),
-      root_layer_impl_(LayerImpl::Create(host_->host_impl()->active_tree(), 1)),
       render_pass_(RenderPass::Create()),
       layer_impl_id_(2) {
-  root_layer_impl_->SetHasRenderSurface(true);
+  scoped_ptr<LayerImpl> root_layer_impl =
+      LayerImpl::Create(host_->host_impl()->active_tree(), 1);
+  root_layer_impl->SetHasRenderSurface(true);
+  host_->host_impl()->active_tree()->SetRootLayer(std::move(root_layer_impl));
   host_->host_impl()->SetVisible(true);
   host_->host_impl()->InitializeRenderer(output_surface_.get());
 
@@ -150,7 +152,8 @@
   LayerImplList layer_list;
   host_->host_impl()->active_tree()->IncrementRenderSurfaceListIdForTesting();
   LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-      root_layer_impl_.get(), viewport_size, &layer_list,
+      host_->host_impl()->active_tree()->root_layer(), viewport_size,
+      &layer_list,
       host_->host_impl()->active_tree()->current_render_surface_list_id());
   LayerTreeHostCommon::CalculateDrawProperties(&inputs);
 }
@@ -211,7 +214,8 @@
   std::vector<scoped_ptr<CopyOutputRequest>> copy_requests;
   copy_requests.push_back(
       CopyOutputRequest::CreateRequest(base::Bind(&EmptyCopyOutputCallback)));
-  root_layer_impl_->PassCopyRequests(&copy_requests);
+  host_->host_impl()->active_tree()->root_layer()->PassCopyRequests(
+      &copy_requests);
 }
 
 }  // namespace cc
diff --git a/cc/test/layer_test_common.h b/cc/test/layer_test_common.h
index 39d21685..a1904b9 100644
--- a/cc/test/layer_test_common.h
+++ b/cc/test/layer_test_common.h
@@ -61,7 +61,8 @@
       scoped_ptr<T> layer =
           T::Create(host_->host_impl()->active_tree(), layer_impl_id_++);
       T* ptr = layer.get();
-      root_layer_impl_->AddChild(std::move(layer));
+      LayerImpl* root_layer_impl = host_->active_tree()->root_layer();
+      root_layer_impl->AddChild(std::move(layer));
       return ptr;
     }
 
@@ -88,7 +89,8 @@
       scoped_ptr<T> layer =
           T::Create(host_->host_impl()->active_tree(), layer_impl_id_++, a);
       T* ptr = layer.get();
-      root_layer_impl_->AddChild(std::move(layer));
+      LayerImpl* root_layer_impl = host_->active_tree()->root_layer();
+      root_layer_impl->AddChild(std::move(layer));
       return ptr;
     }
 
@@ -97,7 +99,8 @@
       scoped_ptr<T> layer =
           T::Create(host_->host_impl()->active_tree(), layer_impl_id_++, a, b);
       T* ptr = layer.get();
-      root_layer_impl_->AddChild(std::move(layer));
+      LayerImpl* root_layer_impl = host_->active_tree()->root_layer();
+      root_layer_impl->AddChild(std::move(layer));
       return ptr;
     }
 
@@ -106,7 +109,8 @@
       scoped_ptr<T> layer = T::Create(host_->host_impl()->active_tree(),
                                       layer_impl_id_++, a, b, c, d);
       T* ptr = layer.get();
-      root_layer_impl_->AddChild(std::move(layer));
+      LayerImpl* root_layer_impl = host_->active_tree()->root_layer();
+      root_layer_impl->AddChild(std::move(layer));
       return ptr;
     }
 
@@ -124,7 +128,8 @@
       scoped_ptr<T> layer = T::Create(host_->host_impl()->active_tree(),
                                       layer_impl_id_++, a, b, c, d, e);
       T* ptr = layer.get();
-      root_layer_impl_->AddChild(std::move(layer));
+      LayerImpl* root_layer_impl = host_->active_tree()->root_layer();
+      root_layer_impl->AddChild(std::move(layer));
       return ptr;
     }
 
@@ -139,8 +144,8 @@
 
     void RequestCopyOfOutput();
 
-    void SetSecureOutputSurface(bool secure_output) {
-      host_->host_impl()->output_surface()->set_is_secure(secure_output);
+    void SetOutputIsSecure(bool output_is_secure) {
+      host_->host_impl()->set_output_is_secure(output_is_secure);
     }
 
     OutputSurface* output_surface() const {
@@ -149,7 +154,9 @@
     ResourceProvider* resource_provider() const {
       return host_->host_impl()->resource_provider();
     }
-    LayerImpl* root_layer() const { return root_layer_impl_.get(); }
+    LayerImpl* root_layer() const {
+      return host_->host_impl()->active_tree()->root_layer();
+    }
     FakeLayerTreeHost* host() { return host_.get(); }
     FakeLayerTreeHostImpl* host_impl() const { return host_->host_impl(); }
     TaskRunnerProvider* task_runner_provider() const {
@@ -164,7 +171,6 @@
     TestTaskGraphRunner task_graph_runner_;
     scoped_ptr<OutputSurface> output_surface_;
     scoped_ptr<FakeLayerTreeHost> host_;
-    scoped_ptr<LayerImpl> root_layer_impl_;
     scoped_ptr<RenderPass> render_pass_;
     scoped_refptr<AnimationTimeline> timeline_;
     scoped_refptr<AnimationTimeline> timeline_impl_;
diff --git a/cc/test/layer_tree_host_common_test.cc b/cc/test/layer_tree_host_common_test.cc
index d1a7dc25..c923e50 100644
--- a/cc/test/layer_tree_host_common_test.cc
+++ b/cc/test/layer_tree_host_common_test.cc
@@ -166,8 +166,12 @@
     LayerImpl* page_scale_layer,
     bool can_use_lcd_text,
     bool layers_always_allowed_lcd_text) {
-  host_impl()->active_tree()->SetDeviceScaleFactor(device_scale_factor);
-  host_impl()->active_tree()->SetPageScaleOnActiveTree(page_scale_factor);
+  root_layer->layer_tree_impl()->SetDeviceScaleFactor(device_scale_factor);
+  if (page_scale_layer)
+    root_layer->layer_tree_impl()->SetViewportLayersFromIds(
+        Layer::INVALID_ID, page_scale_layer->id(), Layer::INVALID_ID,
+        Layer::INVALID_ID);
+  root_layer->layer_tree_impl()->SetPageScaleOnActiveTree(page_scale_factor);
 
   gfx::Transform identity_matrix;
   gfx::Size device_viewport_size =
diff --git a/cc/trees/damage_tracker_unittest.cc b/cc/trees/damage_tracker_unittest.cc
index 4dd597d..743631f2 100644
--- a/cc/trees/damage_tracker_unittest.cc
+++ b/cc/trees/damage_tracker_unittest.cc
@@ -1465,12 +1465,14 @@
 
   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_.active_tree(), 1);
   root->SetForceRenderSurface(true);
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  EmulateDrawingOneFrame(root.get());
-  root->draw_properties().render_target = root.get();
+  host_impl_.active_tree()->SetRootLayer(std::move(root));
+  LayerImpl* root_ptr = host_impl_.active_tree()->root_layer();
+  root_ptr->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  EmulateDrawingOneFrame(root_ptr);
+  root_ptr->draw_properties().render_target = root_ptr;
 
-  ASSERT_EQ(root.get(), root->render_target());
-  RenderSurfaceImpl* target_surface = root->render_surface();
+  ASSERT_EQ(root_ptr, root_ptr->render_target());
+  RenderSurfaceImpl* target_surface = root_ptr->render_surface();
 
   LayerImplList empty_list;
   target_surface->damage_tracker()->UpdateDamageTrackingState(
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index d31fb067..ab28243a1 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -453,42 +453,30 @@
 }
 
 template <typename LayerType>
-void UpdateRenderSurfacesWithEffectTreeInternal(EffectTree* effect_tree,
-                                                LayerType* layer) {
+void UpdateRenderSurfaceForLayer(EffectTree* effect_tree,
+                                 bool non_root_surfaces_enabled,
+                                 LayerType* layer) {
+  if (!non_root_surfaces_enabled) {
+    layer->SetHasRenderSurface(!layer->parent());
+    return;
+  }
   EffectNode* node = effect_tree->Node(layer->effect_tree_index());
 
   if (node->owner_id == layer->id() && node->data.has_render_surface)
     layer->SetHasRenderSurface(true);
   else
     layer->SetHasRenderSurface(false);
+}
+
+void UpdateRenderSurfacesForLayersRecursive(EffectTree* effect_tree,
+                                            Layer* layer) {
+  UpdateRenderSurfaceForLayer(effect_tree, true, layer);
 
   for (size_t i = 0; i < layer->children().size(); ++i) {
-    UpdateRenderSurfacesWithEffectTreeInternal<LayerType>(effect_tree,
-                                                          layer->child_at(i));
+    UpdateRenderSurfacesForLayersRecursive(effect_tree, layer->child_at(i));
   }
 }
 
-void UpdateRenderSurfacesWithEffectTree(EffectTree* effect_tree, Layer* layer) {
-  UpdateRenderSurfacesWithEffectTreeInternal<Layer>(effect_tree, layer);
-}
-
-void UpdateRenderSurfacesNonRootSurfacesDisabled(LayerImpl* layer) {
-  // Only root layer has render surface, all other layers don't.
-  layer->SetHasRenderSurface(!layer->parent());
-
-  for (size_t i = 0; i < layer->children().size(); ++i)
-    UpdateRenderSurfacesNonRootSurfacesDisabled(layer->child_at(i));
-}
-
-void UpdateRenderSurfacesWithEffectTree(EffectTree* effect_tree,
-                                        bool non_root_surfaces_enabled,
-                                        LayerImpl* layer) {
-  if (!non_root_surfaces_enabled)
-    UpdateRenderSurfacesNonRootSurfacesDisabled(layer);
-  else
-    UpdateRenderSurfacesWithEffectTreeInternal<LayerImpl>(effect_tree, layer);
-}
-
 }  // namespace
 
 static void ResetIfHasNanCoordinate(gfx::RectF* rect) {
@@ -697,7 +685,8 @@
       outer_viewport_scroll_layer, overscroll_elasticity_layer,
       elastic_overscroll, page_scale_factor, device_scale_factor, viewport,
       device_transform, property_trees);
-  UpdateRenderSurfacesWithEffectTree(&property_trees->effect_tree, root_layer);
+  UpdateRenderSurfacesForLayersRecursive(&property_trees->effect_tree,
+                                         root_layer);
   ValidateRenderSurfaces(root_layer);
   ComputeVisibleRects(root_layer, property_trees,
                       can_render_to_separate_surface, update_layer_list);
@@ -740,8 +729,9 @@
                          PropertyTrees* property_trees,
                          bool can_render_to_separate_surface,
                          LayerImplList* visible_layer_list) {
-  UpdateRenderSurfacesWithEffectTree(
-      &property_trees->effect_tree, can_render_to_separate_surface, root_layer);
+  for (auto* layer : *root_layer->layer_tree_impl())
+    UpdateRenderSurfaceForLayer(&property_trees->effect_tree,
+                                can_render_to_separate_surface, layer);
   if (can_render_to_separate_surface)
     ValidateRenderSurfaces(root_layer);
   LayerImplList update_layer_list;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index ced57c21..16197c36cf 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -613,6 +613,10 @@
   }
 }
 
+void LayerTreeHost::SetOutputIsSecure(bool output_is_secure) {
+  proxy_->SetOutputIsSecure(output_is_secure);
+}
+
 const RendererCapabilities& LayerTreeHost::GetRendererCapabilities() const {
   return proxy_->GetRendererCapabilities();
 }
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index ffb597b1..8af3dcb 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -182,6 +182,8 @@
 
   void SetNeedsDisplayOnAllLayers();
 
+  void SetOutputIsSecure(bool output_is_secure);
+
   void CollectRenderingStats(RenderingStats* stats) const;
 
   RenderingStatsInstrumentation* rendering_stats_instrumentation() const {
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index 24352bc8..08e6113 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -359,9 +359,17 @@
                                false);
   root->AddChild(std::move(clip_layer_scoped_ptr));
   root->SetHasRenderSurface(true);
+  LayerImpl* root_layer = root.get();
+  host_impl.active_tree()->SetRootLayer(std::move(root));
 
-  ExecuteCalculateDrawProperties(
-      root.get(), kDeviceScale, kPageScale, scroll_layer->parent());
+  // We need property trees to exist when we try to update page scale factor on
+  // active tree. But we still need to rebuild property trees after that because
+  // BuildingPropertyTreesForTesting doesn't take into account the scale factors
+  // and the page scale layer.
+  root_layer->layer_tree_impl()->BuildPropertyTreesForTesting();
+  root_layer->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  ExecuteCalculateDrawProperties(root_layer, kDeviceScale, kPageScale,
+                                 scroll_layer->parent());
   gfx::Transform expected_transform = identity_matrix;
   gfx::PointF sub_layer_screen_position = kScrollLayerPosition - kScrollDelta;
   expected_transform.Translate(MathUtil::Round(sub_layer_screen_position.x() *
@@ -382,9 +390,9 @@
   SetLayerPropertiesForTesting(scroll_layer, arbitrary_translate,
                                gfx::Point3F(), gfx::PointF(), gfx::Size(10, 20),
                                true, false, false);
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(
-      root.get(), kDeviceScale, kPageScale, scroll_layer->parent());
+  root_layer->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  ExecuteCalculateDrawProperties(root_layer, kDeviceScale, kPageScale,
+                                 scroll_layer->parent());
   expected_transform.MakeIdentity();
   expected_transform.Translate(
       MathUtil::Round(kTranslateX * kPageScale * kDeviceScale +
@@ -4834,6 +4842,12 @@
 
   float device_scale_factor = 2.5f;
   float page_scale_factor = 3.f;
+  // We need property trees to exist when we try to update page scale factor on
+  // active tree. But we still need to rebuild property trees after that because
+  // BuildingPropertyTreesForTesting doesn't take into account the scale factors
+  // and the page scale layer.
+  root->layer_tree_impl()->BuildPropertyTreesForTesting();
+  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
   ExecuteCalculateDrawProperties(root, device_scale_factor, page_scale_factor,
                                  root);
 
@@ -4920,6 +4934,12 @@
   float page_scale_factor = 0.01f;
 
   {
+    // We need property trees to exist when we try to update page scale factor
+    // on active tree. But we still need to rebuild property trees after that
+    // because BuildingPropertyTreesForTesting doesn't take into account the
+    // scale factors and the page scale layer.
+    root->layer_tree_impl()->BuildPropertyTreesForTesting();
+    root->layer_tree_impl()->property_trees()->needs_rebuild = true;
     ExecuteCalculateDrawProperties(root, device_scale_factor, page_scale_factor,
                                    root);
 
@@ -5584,6 +5604,7 @@
                                gfx::PointF(), gfx::Size(50, 50), true, false,
                                true);
   root->SetDrawsContent(true);
+  LayerImpl* root_layer = root.get();
 
   scoped_ptr<LayerImpl> child = LayerImpl::Create(host_impl.pending_tree(), 2);
   SetLayerPropertiesForTesting(child.get(), identity_matrix, gfx::Point3F(),
@@ -5601,20 +5622,21 @@
 
   child->AddChild(std::move(grand_child));
   root->AddChild(std::move(child));
+  host_impl.pending_tree()->SetRootLayer(std::move(root));
 
   LayerImplList render_surface_layer_list;
-  root->layer_tree_impl()->IncrementRenderSurfaceListIdForTesting();
+  root_layer->layer_tree_impl()->IncrementRenderSurfaceListIdForTesting();
   LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-      root.get(), root->bounds(), &render_surface_layer_list,
-      root->layer_tree_impl()->current_render_surface_list_id());
+      root_layer, root_layer->bounds(), &render_surface_layer_list,
+      root_layer->layer_tree_impl()->current_render_surface_list_id());
   inputs.can_adjust_raster_scales = true;
   LayerTreeHostCommon::CalculateDrawProperties(&inputs);
 
   // We should have one render surface and one layers. The child has
   // hidden itself and the grand child.
   ASSERT_EQ(1u, render_surface_layer_list.size());
-  ASSERT_EQ(1u, root->render_surface()->layer_list().size());
-  EXPECT_EQ(1, root->render_surface()->layer_list().at(0)->id());
+  ASSERT_EQ(1u, root_layer->render_surface()->layer_list().size());
+  EXPECT_EQ(1, root_layer->render_surface()->layer_list().at(0)->id());
 }
 
 void EmptyCopyOutputCallback(scoped_ptr<CopyOutputResult> result) {}
@@ -5633,6 +5655,7 @@
                                gfx::PointF(), gfx::Size(50, 50), true, false,
                                true);
   root->SetDrawsContent(true);
+  LayerImpl* root_layer = root.get();
 
   scoped_ptr<LayerImpl> copy_grand_parent =
       LayerImpl::Create(host_impl.pending_tree(), 2);
@@ -5699,6 +5722,7 @@
   root->AddChild(std::move(copy_grand_parent_sibling_before));
   root->AddChild(std::move(copy_grand_parent));
   root->AddChild(std::move(copy_grand_parent_sibling_after));
+  host_impl.pending_tree()->SetRootLayer(std::move(root));
 
   // Hide the copy_grand_parent and its subtree. But make a copy request in that
   // hidden subtree on copy_layer. Also hide the copy grand child and its
@@ -5715,14 +5739,14 @@
   EXPECT_TRUE(copy_layer->HasCopyRequest());
 
   LayerImplList render_surface_layer_list;
-  root->layer_tree_impl()->IncrementRenderSurfaceListIdForTesting();
+  root_layer->layer_tree_impl()->IncrementRenderSurfaceListIdForTesting();
   LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-      root.get(), root->bounds(), &render_surface_layer_list,
-      root->layer_tree_impl()->current_render_surface_list_id());
+      root_layer, root_layer->bounds(), &render_surface_layer_list,
+      root_layer->layer_tree_impl()->current_render_surface_list_id());
   inputs.can_adjust_raster_scales = true;
   LayerTreeHostCommon::CalculateDrawProperties(&inputs);
 
-  EXPECT_GT(root->num_copy_requests_in_target_subtree(), 0);
+  EXPECT_GT(root_layer->num_copy_requests_in_target_subtree(), 0);
   EXPECT_GT(copy_grand_parent_layer->num_copy_requests_in_target_subtree(), 0);
   EXPECT_GT(copy_parent_layer->num_copy_requests_in_target_subtree(), 0);
   EXPECT_GT(copy_layer->num_copy_requests_in_target_subtree(), 0);
@@ -5731,17 +5755,18 @@
   // parent since it has opacity and two drawing descendants, one for the parent
   // since it owns a surface, and one for the copy_layer.
   ASSERT_EQ(4u, render_surface_layer_list.size());
-  EXPECT_EQ(root->id(), render_surface_layer_list.at(0)->id());
+  EXPECT_EQ(root_layer->id(), render_surface_layer_list.at(0)->id());
   EXPECT_EQ(copy_grand_parent_layer->id(),
             render_surface_layer_list.at(1)->id());
   EXPECT_EQ(copy_parent_layer->id(), render_surface_layer_list.at(2)->id());
   EXPECT_EQ(copy_layer->id(), render_surface_layer_list.at(3)->id());
 
   // The root render surface should have 2 contributing layers.
-  ASSERT_EQ(2u, root->render_surface()->layer_list().size());
-  EXPECT_EQ(root->id(), root->render_surface()->layer_list().at(0)->id());
+  ASSERT_EQ(2u, root_layer->render_surface()->layer_list().size());
+  EXPECT_EQ(root_layer->id(),
+            root_layer->render_surface()->layer_list().at(0)->id());
   EXPECT_EQ(copy_grand_parent_layer->id(),
-            root->render_surface()->layer_list().at(1)->id());
+            root_layer->render_surface()->layer_list().at(1)->id());
 
   // Nothing actually draws into the copy parent, so only the copy_layer will
   // appear in its list, since it needs to be drawn for the copy request.
@@ -5760,7 +5785,8 @@
   // but the copy_layer and copy_child should be drawn for the copy request.
   // copy grand child should not be drawn as its hidden even in the copy
   // request.
-  EffectTree tree = root->layer_tree_impl()->property_trees()->effect_tree;
+  EffectTree tree =
+      root_layer->layer_tree_impl()->property_trees()->effect_tree;
   EffectNode* node = tree.Node(copy_grand_parent_layer->effect_tree_index());
   EXPECT_FALSE(node->data.is_drawn);
   node = tree.Node(copy_parent_layer->effect_tree_index());
@@ -5823,23 +5849,26 @@
   copy_layer->AddChild(std::move(copy_child));
   copy_parent->AddChild(std::move(copy_layer));
   root->AddChild(std::move(copy_parent));
+  host_impl.pending_tree()->SetRootLayer(std::move(root));
+  LayerImpl* root_ptr = host_impl.pending_tree()->root_layer();
 
   LayerImplList render_surface_layer_list;
-  root->layer_tree_impl()->IncrementRenderSurfaceListIdForTesting();
+  root_ptr->layer_tree_impl()->IncrementRenderSurfaceListIdForTesting();
   LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-      root.get(), root->bounds(), &render_surface_layer_list,
-      root->layer_tree_impl()->current_render_surface_list_id());
+      root_ptr, root_ptr->bounds(), &render_surface_layer_list,
+      root_ptr->layer_tree_impl()->current_render_surface_list_id());
   inputs.can_adjust_raster_scales = true;
   LayerTreeHostCommon::CalculateDrawProperties(&inputs);
 
   // We should have two render surface, as the others are clipped out.
   ASSERT_EQ(2u, render_surface_layer_list.size());
-  EXPECT_EQ(root->id(), render_surface_layer_list.at(0)->id());
+  EXPECT_EQ(root_ptr->id(), render_surface_layer_list.at(0)->id());
 
   // The root render surface should only have 2 contributing layer, since the
   // other layers are empty/clipped away.
-  ASSERT_EQ(2u, root->render_surface()->layer_list().size());
-  EXPECT_EQ(root->id(), root->render_surface()->layer_list().at(0)->id());
+  ASSERT_EQ(2u, root_ptr->render_surface()->layer_list().size());
+  EXPECT_EQ(root_ptr->id(),
+            root_ptr->render_surface()->layer_list().at(0)->id());
 }
 
 TEST_F(LayerTreeHostCommonTest, VisibleContentRectInsideSurface) {
@@ -6386,14 +6415,16 @@
   child2->AddChild(std::move(child3));
   child1->AddChild(std::move(child2));
   root->AddChild(std::move(child1));
+  host_impl.active_tree()->SetRootLayer(std::move(root));
+  LayerImpl* root_ptr = host_impl.active_tree()->root_layer();
 
   {
     LayerImplList render_surface_layer_list;
-    FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(root.get());
-    root->layer_tree_impl()->IncrementRenderSurfaceListIdForTesting();
+    FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(root_ptr);
+    root_ptr->layer_tree_impl()->IncrementRenderSurfaceListIdForTesting();
     LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-        root.get(), root->bounds(), &render_surface_layer_list,
-        root->layer_tree_impl()->current_render_surface_list_id());
+        root_ptr, root_ptr->bounds(), &render_surface_layer_list,
+        root_ptr->layer_tree_impl()->current_render_surface_list_id());
     inputs.can_render_to_separate_surface = true;
     LayerTreeHostCommon::CalculateDrawProperties(&inputs);
 
@@ -6423,10 +6454,10 @@
 
   {
     LayerImplList render_surface_layer_list;
-    root->layer_tree_impl()->IncrementRenderSurfaceListIdForTesting();
+    root_ptr->layer_tree_impl()->IncrementRenderSurfaceListIdForTesting();
     LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-        root.get(), root->bounds(), &render_surface_layer_list,
-        root->layer_tree_impl()->current_render_surface_list_id());
+        root_ptr, root_ptr->bounds(), &render_surface_layer_list,
+        root_ptr->layer_tree_impl()->current_render_surface_list_id());
     inputs.can_render_to_separate_surface = false;
     LayerTreeHostCommon::CalculateDrawProperties(&inputs);
 
@@ -7315,12 +7346,14 @@
   AnimationScaleFactorTrackingLayerImpl* parent_raw = parent.get();
   AnimationScaleFactorTrackingLayerImpl* child_raw = child.get();
   AnimationScaleFactorTrackingLayerImpl* grand_child_raw = grand_child.get();
+  AnimationScaleFactorTrackingLayerImpl* grand_parent_raw = grand_parent.get();
 
   child->AddChild(std::move(grand_child));
   parent->AddChild(std::move(child));
   grand_parent->AddChild(std::move(parent));
+  host_impl.active_tree()->SetRootLayer(std::move(grand_parent));
 
-  SetLayerPropertiesForTesting(grand_parent.get(), identity_matrix,
+  SetLayerPropertiesForTesting(grand_parent_raw, identity_matrix,
                                gfx::Point3F(), gfx::PointF(), gfx::Size(1, 2),
                                true, false, true);
   SetLayerPropertiesForTesting(parent_raw, identity_matrix, gfx::Point3F(),
@@ -7334,19 +7367,21 @@
                                gfx::PointF(), gfx::Size(1, 2), true, false,
                                false);
 
-  ExecuteCalculateDrawProperties(grand_parent.get());
+  ExecuteCalculateDrawProperties(grand_parent_raw);
 
   // No layers have animations.
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().maximum_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(0.f,
             parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(0.f, child_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(
       0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
 
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().starting_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
             parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
@@ -7366,16 +7401,18 @@
                                         TransformOperations(), translation);
 
   // No layers have scale-affecting animations.
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().maximum_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(0.f,
             parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(0.f, child_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(
       0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
 
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().starting_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
             parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
@@ -7390,19 +7427,21 @@
   AddAnimatedTransformToLayerWithPlayer(child_raw->id(), timeline, 1.0,
                                         TransformOperations(), scale);
   child_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(grand_parent.get());
+  ExecuteCalculateDrawProperties(grand_parent_raw);
 
   // Only |child| has a scale-affecting animation.
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().maximum_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(0.f,
             parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(5.f, child_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(
       5.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
 
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().starting_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
             parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(1.f,
@@ -7411,14 +7450,15 @@
       1.f,
       grand_child_raw->draw_properties().starting_animation_contents_scale);
 
-  AddAnimatedTransformToLayerWithPlayer(grand_parent->id(), timeline, 1.0,
+  AddAnimatedTransformToLayerWithPlayer(grand_parent_raw->id(), timeline, 1.0,
                                         TransformOperations(), scale);
-  grand_parent->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(grand_parent.get());
+  grand_parent_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  ExecuteCalculateDrawProperties(grand_parent_raw);
 
   // |grand_parent| and |child| have scale-affecting animations.
-  EXPECT_EQ(5.f,
-            grand_parent->draw_properties().maximum_animation_contents_scale);
+  EXPECT_EQ(
+      5.f,
+      grand_parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(5.f,
             parent_raw->draw_properties().maximum_animation_contents_scale);
   // We don't support combining animated scales from two nodes; 0.f means
@@ -7427,8 +7467,9 @@
   EXPECT_EQ(
       0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
 
-  EXPECT_EQ(1.f,
-            grand_parent->draw_properties().starting_animation_contents_scale);
+  EXPECT_EQ(
+      1.f,
+      grand_parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(1.f,
             parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
@@ -7440,19 +7481,21 @@
   AddAnimatedTransformToLayerWithPlayer(parent_raw->id(), timeline, 1.0,
                                         TransformOperations(), scale);
   parent_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(grand_parent.get());
+  ExecuteCalculateDrawProperties(grand_parent_raw);
 
   // |grand_parent|, |parent|, and |child| have scale-affecting animations.
-  EXPECT_EQ(5.f,
-            grand_parent->draw_properties().maximum_animation_contents_scale);
+  EXPECT_EQ(
+      5.f,
+      grand_parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(0.f,
             parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(0.f, child_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(
       0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
 
-  EXPECT_EQ(1.f,
-            grand_parent->draw_properties().starting_animation_contents_scale);
+  EXPECT_EQ(
+      1.f,
+      grand_parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
             parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
@@ -7461,7 +7504,7 @@
       0.f,
       grand_child_raw->draw_properties().starting_animation_contents_scale);
 
-  AbortAnimationsOnLayerWithPlayer(grand_parent->id(), timeline,
+  AbortAnimationsOnLayerWithPlayer(grand_parent_raw->id(), timeline,
                                    TargetProperty::TRANSFORM);
   AbortAnimationsOnLayerWithPlayer(parent_raw->id(), timeline,
                                    TargetProperty::TRANSFORM);
@@ -7474,20 +7517,22 @@
   AddAnimatedTransformToLayerWithPlayer(child_raw->id(), timeline, 1.0,
                                         TransformOperations(), perspective);
   child_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(grand_parent.get());
+  ExecuteCalculateDrawProperties(grand_parent_raw);
 
   // |child| has a scale-affecting animation but computing the maximum of this
   // animation is not supported.
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().maximum_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(0.f,
             parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(0.f, child_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(
       0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
 
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().starting_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
             parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
@@ -7500,18 +7545,19 @@
                                    TargetProperty::TRANSFORM);
   gfx::Transform scale_matrix;
   scale_matrix.Scale(1.f, 2.f);
-  grand_parent->SetTransform(scale_matrix);
+  grand_parent_raw->SetTransform(scale_matrix);
   parent_raw->SetTransform(scale_matrix);
-  grand_parent->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  grand_parent_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
 
   AddAnimatedTransformToLayerWithPlayer(parent_raw->id(), timeline, 1.0,
                                         TransformOperations(), scale);
-  ExecuteCalculateDrawProperties(grand_parent.get());
+  ExecuteCalculateDrawProperties(grand_parent_raw);
 
   // |grand_parent| and |parent| each have scale 2.f. |parent| has a  scale
   // animation with maximum scale 5.f.
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().maximum_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(10.f,
             parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(10.f,
@@ -7520,8 +7566,9 @@
       10.f,
       grand_child_raw->draw_properties().maximum_animation_contents_scale);
 
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().starting_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(2.f,
             parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(2.f,
@@ -7533,20 +7580,22 @@
   gfx::Transform perspective_matrix;
   perspective_matrix.ApplyPerspectiveDepth(2.f);
   child_raw->SetTransform(perspective_matrix);
-  grand_parent->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(grand_parent.get());
+  grand_parent_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  ExecuteCalculateDrawProperties(grand_parent_raw);
 
   // |child| has a transform that's neither a translation nor a scale.
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().maximum_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(10.f,
             parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(0.f, child_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(
       0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
 
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().starting_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(2.f,
             parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
@@ -7556,21 +7605,23 @@
       grand_child_raw->draw_properties().starting_animation_contents_scale);
 
   parent_raw->SetTransform(perspective_matrix);
-  grand_parent->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(grand_parent.get());
+  grand_parent_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  ExecuteCalculateDrawProperties(grand_parent_raw);
 
   // |parent| and |child| have transforms that are neither translations nor
   // scales.
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().maximum_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(0.f,
             parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(0.f, child_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(
       0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
 
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().starting_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
             parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
@@ -7581,22 +7632,24 @@
 
   parent_raw->SetTransform(identity_matrix);
   child_raw->SetTransform(identity_matrix);
-  grand_parent->SetTransform(perspective_matrix);
-  grand_parent->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  grand_parent_raw->SetTransform(perspective_matrix);
+  grand_parent_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
 
-  ExecuteCalculateDrawProperties(grand_parent.get());
+  ExecuteCalculateDrawProperties(grand_parent_raw);
 
   // |grand_parent| has a transform that's neither a translation nor a scale.
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().maximum_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(0.f,
             parent_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(0.f, child_raw->draw_properties().maximum_animation_contents_scale);
   EXPECT_EQ(
       0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
 
-  EXPECT_EQ(0.f,
-            grand_parent->draw_properties().starting_animation_contents_scale);
+  EXPECT_EQ(
+      0.f,
+      grand_parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
             parent_raw->draw_properties().starting_animation_contents_scale);
   EXPECT_EQ(0.f,
@@ -7656,6 +7709,7 @@
   child->AddChild(std::move(grand_child2));
   parent->AddChild(std::move(child));
   grand_parent->AddChild(std::move(parent));
+  host_impl.active_tree()->SetRootLayer(std::move(grand_parent));
 
   SetLayerPropertiesForTesting(grand_parent_raw, identity_matrix,
                                gfx::Point3F(), gfx::PointF(), gfx::Size(1, 2),
@@ -7899,6 +7953,7 @@
   root->AddChild(std::move(child2));
   root->SetForceRenderSurface(true);
   root->SetDrawsContent(true);
+  host_impl.active_tree()->SetRootLayer(std::move(root));
 
   gfx::Transform identity_matrix, scale_transform_child1,
       scale_transform_child2;
@@ -7938,7 +7993,7 @@
                                true, false, false);
   child2_layer->SetDrawsContent(true);
 
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  root_layer->layer_tree_impl()->property_trees()->needs_rebuild = true;
   ExecuteCalculateDrawProperties(root_layer);
 
   EXPECT_FLOAT_EQ(1.f, root_layer->GetIdealContentsScale());
@@ -8011,7 +8066,7 @@
   device_scale_factor = 4.0f;
   inputs.device_scale_factor = device_scale_factor;
   inputs.can_adjust_raster_scales = true;
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  root_layer->layer_tree_impl()->property_trees()->needs_rebuild = true;
   LayerTreeHostCommon::CalculateDrawProperties(&inputs);
 
   EXPECT_FLOAT_EQ(12.f, root_layer->GetIdealContentsScale());
@@ -8860,14 +8915,16 @@
                                gfx::PointF(), gfx::Size(10, 10), true, false,
                                false);
 
+  LayerImpl* root_ptr = root.get();
   LayerImpl* child_ptr = child.get();
   LayerImpl* grandchild_ptr = grandchild.get();
 
   child->AddChild(std::move(grandchild));
   root->AddChild(std::move(child));
+  host_impl.active_tree()->SetRootLayer(std::move(root));
 
   // Check the non-skipped case.
-  ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
+  ExecuteCalculateDrawPropertiesWithPropertyTrees(root_ptr);
   EXPECT_EQ(gfx::Rect(10, 10), grandchild_ptr->visible_layer_rect());
 
   // Now we will reset the visible rect from property trees for the grandchild,
@@ -8879,17 +8936,17 @@
   singular.matrix().set(0, 0, 0);
 
   child_ptr->SetTransform(singular);
-  ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
+  ExecuteCalculateDrawPropertiesWithPropertyTrees(root_ptr);
   EXPECT_EQ(gfx::Rect(0, 0), grandchild_ptr->visible_layer_rect());
   child_ptr->SetTransform(identity);
 
   child_ptr->SetHideLayerAndSubtree(true);
-  ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
+  ExecuteCalculateDrawPropertiesWithPropertyTrees(root_ptr);
   EXPECT_EQ(gfx::Rect(0, 0), grandchild_ptr->visible_layer_rect());
   child_ptr->SetHideLayerAndSubtree(false);
 
   child_ptr->SetOpacity(0.f);
-  ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
+  ExecuteCalculateDrawPropertiesWithPropertyTrees(root_ptr);
   EXPECT_EQ(gfx::Rect(0, 0), grandchild_ptr->visible_layer_rect());
 
   // Now, even though child has zero opacity, we will configure |grandchild| and
@@ -8899,8 +8956,8 @@
   requests.push_back(CopyOutputRequest::CreateEmptyRequest());
 
   grandchild_ptr->PassCopyRequests(&requests);
-  root.get()->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
+  root_ptr->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  ExecuteCalculateDrawPropertiesWithPropertyTrees(root_ptr);
   EXPECT_EQ(gfx::Rect(10, 10), grandchild_ptr->visible_layer_rect());
 }
 
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 7e7adfe..efc8eb0 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -226,6 +226,7 @@
       texture_mailbox_deleter_(new TextureMailboxDeleter(GetTaskRunner())),
       max_memory_needed_bytes_(0),
       resourceless_software_draw_(false),
+      output_is_secure_(false),
       animation_host_(),
       rendering_stats_instrumentation_(rendering_stats_instrumentation),
       micro_benchmark_controller_(this),
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index f9ad198..a7d6b083 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -580,6 +580,12 @@
                                   bool is_direct_manipulation,
                                   ScrollTree* scroll_tree);
 
+  void set_output_is_secure(bool output_is_secure) {
+    output_is_secure_ = output_is_secure;
+  }
+
+  bool output_is_secure() const { return output_is_secure_; }
+
   // Record main frame timing information.
   // |start_of_main_frame_args| is the BeginFrameArgs of the beginning of the
   // main frame (ie the frame that kicked off the main frame).
@@ -809,6 +815,8 @@
   gfx::Rect viewport_rect_for_tile_priority_;
   bool resourceless_software_draw_;
 
+  bool output_is_secure_;
+
   gfx::Rect viewport_damage_rect_;
 
   scoped_ptr<AnimationHost> animation_host_;
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index a923346..5086f7f 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -876,12 +876,8 @@
   }
 
   void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
-    // Perform 2 commits.
-    if (!num_draws_) {
+    if (num_draws_ < 2)
       PostSetNeedsRedrawRectToMainThread(invalid_rect_);
-    } else {
-      EndTest();
-    }
     num_draws_++;
   }
 
@@ -904,6 +900,7 @@
       EXPECT_EQ(
           pending_tiling->TilingDataForTesting().max_texture_size().width(),
           active_tiling->TilingDataForTesting().max_texture_size().width());
+      EndTest();
     }
   }
 
@@ -924,7 +921,9 @@
   scoped_refptr<FakePictureLayer> root_layer_;
 };
 
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterDeviceSizeChanged);
+// As there's no pending tree in single-threaded case, this test should run
+// only for multi-threaded case.
+MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterDeviceSizeChanged);
 
 class LayerTreeHostTestNoExtraCommitFromInvalidate : public LayerTreeHostTest {
  public:
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 35406d4..e89c84d 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -1391,6 +1391,10 @@
   return layer_tree_host_impl_->IsUIResourceOpaque(uid);
 }
 
+bool LayerTreeImpl::OutputIsSecure() const {
+  return layer_tree_host_impl_->output_is_secure();
+}
+
 void LayerTreeImpl::ProcessUIResourceRequestQueue() {
   for (const auto& req : ui_resource_request_queue_) {
     switch (req.GetType()) {
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index ce68146..a137011 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -367,6 +367,8 @@
 
   bool IsUIResourceOpaque(UIResourceId uid) const;
 
+  bool OutputIsSecure() const;
+
   void RegisterPictureLayerImpl(PictureLayerImpl* layer);
   void UnregisterPictureLayerImpl(PictureLayerImpl* layer);
   const std::vector<PictureLayerImpl*>& picture_layers() const {
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc
index 4a5f480..8cf4f01 100644
--- a/cc/trees/layer_tree_impl_unittest.cc
+++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -648,6 +648,7 @@
   //
   scoped_ptr<LayerImpl> root =
       LayerImpl::Create(host_impl().active_tree(), 123);
+  LayerImpl* root_layer = root.get();
 
   gfx::Transform identity_matrix;
   gfx::Point3F transform_origin;
@@ -702,12 +703,12 @@
     grand_child->AddChild(std::move(rotated_leaf));
     child->AddChild(std::move(grand_child));
     root->AddChild(std::move(child));
+    host_impl().active_tree()->SetRootLayer(std::move(root));
 
-    ExecuteCalculateDrawProperties(root.get());
+    ExecuteCalculateDrawProperties(root_layer);
   }
 
-  host_impl().SetViewportSize(root->bounds());
-  host_impl().active_tree()->SetRootLayer(std::move(root));
+  host_impl().SetViewportSize(root_layer->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
   // (11, 89) is close to the the bottom left corner within the clip, but it is
   // not inside the layer.
@@ -830,6 +831,7 @@
 
 TEST_F(LayerTreeImplTest, HitTestingForMultipleLayers) {
   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
+  LayerImpl* root_layer = root.get();
 
   gfx::Transform identity_matrix;
   gfx::Point3F transform_origin;
@@ -879,16 +881,16 @@
     child1->AddChild(std::move(grand_child1));
     root->AddChild(std::move(child1));
     root->AddChild(std::move(child2));
+    host_impl().active_tree()->SetRootLayer(std::move(root));
 
-    ExecuteCalculateDrawProperties(root.get());
+    ExecuteCalculateDrawProperties(root_layer);
   }
 
-  LayerImpl* child1 = root->children()[0];
-  LayerImpl* child2 = root->children()[1];
+  LayerImpl* child1 = root_layer->children()[0];
+  LayerImpl* child2 = root_layer->children()[1];
   LayerImpl* grand_child1 = child1->children()[0];
 
-  host_impl().SetViewportSize(root->bounds());
-  host_impl().active_tree()->SetRootLayer(std::move(root));
+  host_impl().SetViewportSize(root_layer->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -897,7 +899,7 @@
   ASSERT_TRUE(grand_child1);
   ASSERT_EQ(1u, RenderSurfaceLayerList().size());
 
-  RenderSurfaceImpl* root_render_surface = root_layer()->render_surface();
+  RenderSurfaceImpl* root_render_surface = root_layer->render_surface();
   ASSERT_EQ(4u, root_render_surface->layer_list().size());
   ASSERT_EQ(1, root_render_surface->layer_list().at(0)->id());  // root layer
   ASSERT_EQ(2, root_render_surface->layer_list().at(1)->id());  // child1
@@ -1292,6 +1294,7 @@
   // all layers are forced to be render surfaces now.
   //
   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
+  LayerImpl* root_layer = root.get();
 
   gfx::Transform identity_matrix;
   gfx::Point3F transform_origin;
@@ -1344,16 +1347,16 @@
     child1->AddChild(std::move(grand_child1));
     root->AddChild(std::move(child1));
     root->AddChild(std::move(child2));
+    host_impl().active_tree()->SetRootLayer(std::move(root));
 
-    ExecuteCalculateDrawProperties(root.get());
+    ExecuteCalculateDrawProperties(root_layer);
   }
 
-  LayerImpl* child1 = root->children()[0];
-  LayerImpl* child2 = root->children()[1];
+  LayerImpl* child1 = root_layer->children()[0];
+  LayerImpl* child2 = root_layer->children()[1];
   LayerImpl* grand_child1 = child1->children()[0];
 
-  host_impl().SetViewportSize(root->bounds());
-  host_impl().active_tree()->SetRootLayer(std::move(root));
+  host_impl().SetViewportSize(root_layer->bounds());
   host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
 
   // Sanity check the scenario we just created.
@@ -1366,7 +1369,7 @@
   ASSERT_EQ(4u, RenderSurfaceLayerList().size());
   // The root surface has the root layer, and child1's and child2's render
   // surfaces.
-  ASSERT_EQ(3u, root_layer()->render_surface()->layer_list().size());
+  ASSERT_EQ(3u, root_layer->render_surface()->layer_list().size());
   // The child1 surface has the child1 layer and grand_child1's render surface.
   ASSERT_EQ(2u, child1->render_surface()->layer_list().size());
   ASSERT_EQ(1u, child2->render_surface()->layer_list().size());
diff --git a/cc/trees/occlusion_tracker_unittest.cc b/cc/trees/occlusion_tracker_unittest.cc
index 5bfd312..5aa72c3 100644
--- a/cc/trees/occlusion_tracker_unittest.cc
+++ b/cc/trees/occlusion_tracker_unittest.cc
@@ -105,8 +105,7 @@
     TestContentLayerImpl* layer_ptr = layer.get();
     SetProperties(layer_ptr, transform, position, bounds);
 
-    DCHECK(!root_.get());
-    root_ = std::move(layer);
+    host_->host_impl()->active_tree()->SetRootLayer(std::move(layer));
 
     layer_ptr->SetForceRenderSurface(true);
     SetRootLayerOnMainThread(layer_ptr);
@@ -196,7 +195,7 @@
   }
 
   void DestroyLayers() {
-    root_ = nullptr;
+    host_->host_impl()->active_tree()->SetRootLayer(nullptr);
     render_surface_layer_list_impl_.clear();
     replica_layers_.clear();
     mask_layers_.clear();
@@ -219,7 +218,7 @@
   }
 
   void CalcDrawEtc(TestContentLayerImpl* root) {
-    DCHECK(root == root_.get());
+    DCHECK(root == root->layer_tree_impl()->root_layer());
 
     // These occlusion tests attach and detach layers in multiple
     // iterations, so rebuild property trees every time.
@@ -311,7 +310,6 @@
   TestTaskGraphRunner task_graph_runner_;
   scoped_ptr<FakeLayerTreeHost> host_;
   // These hold ownership of the layers for the duration of the test.
-  scoped_ptr<LayerImpl> root_;
   LayerImplList render_surface_layer_list_impl_;
   LayerIterator layer_iterator_begin_;
   LayerIterator layer_iterator_;
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h
index cb7152de..27144aa 100644
--- a/cc/trees/proxy.h
+++ b/cc/trees/proxy.h
@@ -83,6 +83,8 @@
                                       TopControlsState current,
                                       bool animate) = 0;
 
+  virtual void SetOutputIsSecure(bool output_is_secure) = 0;
+
   // Testing hooks
   virtual bool MainFrameWillHappenForTesting() = 0;
 };
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc
index 63bac73..c5821f3 100644
--- a/cc/trees/proxy_main.cc
+++ b/cc/trees/proxy_main.cc
@@ -449,6 +449,10 @@
   channel_main_->UpdateTopControlsStateOnImpl(constraints, current, animate);
 }
 
+void ProxyMain::SetOutputIsSecure(bool output_is_secure) {
+  NOTREACHED() << "Only used by SingleProxyMain";
+}
+
 bool ProxyMain::SendCommitRequestToImplThreadIfNeeded(
     CommitPipelineStage required_stage) {
   DCHECK(IsMainThread());
diff --git a/cc/trees/proxy_main.h b/cc/trees/proxy_main.h
index 560d26bd..1b627dd 100644
--- a/cc/trees/proxy_main.h
+++ b/cc/trees/proxy_main.h
@@ -113,6 +113,7 @@
   void UpdateTopControlsState(TopControlsState constraints,
                               TopControlsState current,
                               bool animate) override;
+  void SetOutputIsSecure(bool output_is_secure) override;
 
   // This sets the channel used by ProxyMain to communicate with ProxyImpl.
   void SetChannel(scoped_ptr<ChannelMain> channel_main);
diff --git a/cc/trees/remote_channel_impl.cc b/cc/trees/remote_channel_impl.cc
index 4708c1e..5d98369 100644
--- a/cc/trees/remote_channel_impl.cc
+++ b/cc/trees/remote_channel_impl.cc
@@ -306,6 +306,10 @@
   NOTREACHED() << "Should not be called on the remote client LayerTreeHost";
 }
 
+void RemoteChannelImpl::SetOutputIsSecure(bool output_is_secure) {
+  NOTREACHED() << "Only used by SingleProxyMain";
+}
+
 bool RemoteChannelImpl::MainFrameWillHappenForTesting() {
   DCHECK(task_runner_provider_->IsMainThread());
   bool main_frame_will_happen;
diff --git a/cc/trees/remote_channel_impl.h b/cc/trees/remote_channel_impl.h
index 79e19ec8..8989776 100644
--- a/cc/trees/remote_channel_impl.h
+++ b/cc/trees/remote_channel_impl.h
@@ -162,6 +162,7 @@
   void UpdateTopControlsState(TopControlsState constraints,
                               TopControlsState current,
                               bool animate) override;
+  void SetOutputIsSecure(bool output_is_secure) override;
   bool MainFrameWillHappenForTesting() override;
 
   // Called on impl thread.
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 7c1d821e..fa193bf 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -886,6 +886,10 @@
   NOTREACHED() << "Top Controls are used only in threaded mode";
 }
 
+void SingleThreadProxy::SetOutputIsSecure(bool output_is_secure) {
+  layer_tree_host_impl_->set_output_is_secure(output_is_secure);
+}
+
 void SingleThreadProxy::DidFinishImplFrame() {
   layer_tree_host_impl_->DidFinishImplFrame();
 #if DCHECK_IS_ON()
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index 66e0075..b5477f2 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -61,6 +61,7 @@
   void UpdateTopControlsState(TopControlsState constraints,
                               TopControlsState current,
                               bool animate) override;
+  void SetOutputIsSecure(bool output_is_secure) override;
 
   // SchedulerClient implementation
   void WillBeginImplFrame(const BeginFrameArgs& args) override;
diff --git a/chrome/android/java/res/layout-sw600dp/empty_background_view.xml b/chrome/android/java/res/layout/empty_background_view_tablet.xml
similarity index 100%
rename from chrome/android/java/res/layout-sw600dp/empty_background_view.xml
rename to chrome/android/java/res/layout/empty_background_view_tablet.xml
diff --git a/chrome/android/java/res/layout/main.xml b/chrome/android/java/res/layout/main.xml
index f275e70..6cd6423 100644
--- a/chrome/android/java/res/layout/main.xml
+++ b/chrome/android/java/res/layout/main.xml
@@ -62,7 +62,7 @@
     <ViewStub
         android:id="@+id/empty_container_stub"
         android:inflatedId="@+id/empty_container"
-        android:layout="@layout/empty_background_view"
+        android:layout="@layout/empty_background_view_tablet"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
     <!-- This empty view is used as the anchor for custom menu -->
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index ca7e88e..3d64a3f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -551,10 +551,6 @@
 
             Intent intent = getIntent();
 
-            if (!CipherFactory.getInstance().restoreFromBundle(getSavedInstanceState())) {
-                mTabModelSelectorImpl.clearEncryptedState();
-            }
-
             boolean noRestoreState =
                     CommandLine.getInstance().hasSwitch(ChromeSwitches.NO_RESTORE_STATE);
             if (noRestoreState) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java
index 50daa6f..cf5d9e89 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java
@@ -312,10 +312,6 @@
         mTabSaver.clearState();
     }
 
-    public void clearEncryptedState() {
-        mTabSaver.clearEncryptedState();
-    }
-
     @Override
     public void destroy() {
         mTabSaver.destroy();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
index fa8a8119..e3a8cc45 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
@@ -516,14 +516,6 @@
     }
 
     /**
-     * Clears all the encrypted data from the disk.
-     * Most likely called when we lost the encryption key.
-     */
-    public void clearEncryptedState() {
-        cleanupAllEncryptedPersistentData();
-    }
-
-    /**
      * Cancels loading of {@link Tab}s from disk from saved state. This is useful if the user
      * does an action which impacts all {@link Tab}s, not just the ones currently loaded into
      * the model. For example, if the user tries to close all {@link Tab}s, we need don't want
@@ -959,26 +951,6 @@
         }
     }
 
-    private void cleanupAllEncryptedPersistentData() {
-        String[] files = null;
-        // Temporarily allowing disk access. TODO: Fix. See http://crbug.com/473357
-        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
-        try {
-            long time = SystemClock.elapsedRealtime();
-            files = getStateDirectory().list();
-            logExecutionTime("CleanupAllEncryptedTime", time);
-        } finally {
-            StrictMode.setThreadPolicy(oldPolicy);
-        }
-        if (files != null) {
-            for (String file : files) {
-                if (file.startsWith(TabState.SAVED_TAB_STATE_FILE_PREFIX_INCOGNITO)) {
-                    deleteFileAsync(file);
-                }
-            }
-        }
-    }
-
     private void deleteFileAsync(final String file) {
         new AsyncTask<Void, Void, Void>() {
             @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/AudioTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/AudioTest.java
index 79f5a41..cd55dd99 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/AudioTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/AudioTest.java
@@ -50,7 +50,7 @@
     public void testPlayMp3() throws InterruptedException, TimeoutException {
         Tab tab = getActivity().getActivityTab();
         TabTitleObserver titleObserver = new TabTitleObserver(tab, "ready_to_play");
-        loadUrl(mTestServer.getURL("/chrome/test/data/android/media/mp3-play.html"));
+        loadUrl(mTestServer.getURL("/chrome/test/data/android/media/audio-play.html"));
         titleObserver.waitForTitleUpdate(5);
         assertEquals("ready_to_play", tab.getTitle());
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/document/DocumentModeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/document/DocumentModeTest.java
index a158fe8a..4ad202f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/document/DocumentModeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/document/DocumentModeTest.java
@@ -672,6 +672,12 @@
         // Wait for the Activity to start up.
         final DocumentActivity newActivity = ActivityUtils.waitForActivity(
                 getInstrumentation(), DocumentActivity.class, viewIntentRunnable);
+        CriteriaHelper.pollUiThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                return newActivity.getActivityTab() != null;
+            }
+        });
         ChromeTabUtils.waitForTabPageLoaded(newActivity.getActivityTab(), (String) null);
 
         TabModelSelector selector = ChromeApplication.getDocumentTabModelSelector();
@@ -693,6 +699,12 @@
         // Wait for the Activity to start up.
         final DocumentActivity newActivity = ActivityUtils.waitForActivity(
                 getInstrumentation(), DocumentActivity.class, viewIntentRunnable);
+        CriteriaHelper.pollUiThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                return newActivity.getActivityTab() != null;
+            }
+        });
         ChromeTabUtils.waitForTabPageLoaded(newActivity.getActivityTab(), (String) null);
 
         TabModelSelector selector = ChromeApplication.getDocumentTabModelSelector();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastTestBase.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastTestBase.java
index f1f642a..305234a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastTestBase.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastTestBase.java
@@ -93,7 +93,7 @@
     // URLs of the default test page and video.
     protected static final String DEFAULT_VIDEO_PAGE =
             "/chrome/test/data/android/media/simple_video.html";
-    protected static final String DEFAULT_VIDEO = "/chrome/test/data/android/media/test.mp4";
+    protected static final String DEFAULT_VIDEO = "/chrome/test/data/android/media/test.webm";
 
     // Constants used to find the default video and maximise button on the page
     protected static final String VIDEO_ELEMENT = "video";
@@ -112,7 +112,7 @@
     protected static final String TEST_VIDEO_PAGE_2 =
             "/chrome/test/data/android/media/simple_video2.html";
 
-    protected static final String TEST_VIDEO_2 = "/chrome/test/data/android/media/test2.mp4";
+    protected static final String TEST_VIDEO_2 = "/chrome/test/data/android/media/test2.webm";
 
     protected static final String TWO_VIDEO_PAGE =
             "/chrome/test/data/android/media/two_videos.html";
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index 89f2b615..7f689ef 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -878,6 +878,14 @@
             Remove From Chromium...
           </message>
         </if>
+        <if expr="not chromeos">
+          <message name="IDS_APP_LIST_MESSAGE_TITLE" desc="Title given to the message displayed in the app launcher to say it is going away">
+            The Chromium App Launcher is going away.
+          </message>
+          <message name="IDS_APP_LIST_MESSAGE_TEXT" desc="The message body text displayed in the app launcher to say it is going away">
+            Use the <ph name="APPS_ICON_IMAGE">$1<ex>Apps</ex></ph> shortcut in the Chromium bookmarks bar to continue accessing your apps.
+          </message>
+        </if>
       </if>
 
       <!-- App shortcuts -->
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 05535350..185a619 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -13293,6 +13293,14 @@
         <message name="IDS_APP_LIST_SIGNIN_SETTINGS_TEXT" desc="App launcher sign-in settings link text.">
           App Launcher Settings
         </message>
+        <if expr="not chromeos">
+          <message name="IDS_APP_LIST_MESSAGE_LEARN_MORE_TEXT" desc="Link anchor text displayed at the end of a message in the app launcher linking to a site with additional information about the message.">
+            Learn more.
+          </message>
+          <message name="IDS_APP_LIST_MESSAGE_LEARN_MORE_LINK" desc="URL for the Learn More link displayed at the end of the app launcher message.">
+            https://support.google.com/chrome/answer/3060053?hl=[GRITLANGCODE]
+          </message>
+        </if>
       </if>
 
       <!-- iOS Chrome to Device strings-->
@@ -14564,6 +14572,13 @@
       </message>
     </if>
 
+    <message name="IDS_FLAGS_ENABLE_WEB_USB_NAME" desc="Title for the flag to enable WebUSB.">
+      WebUSB
+    </message>
+    <message name="IDS_FLAGS_ENABLE_WEB_USB_DESCRIPTION" desc="Description for the flag to enable WebUSB.">
+      Enable WebUSB support.
+    </message>
+
     </messages>
   </release>
 </grit>
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index 6698f055..fed9f4dd 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -879,6 +879,14 @@
             Remove From Chrome...
           </message>
         </if>
+        <if expr="not chromeos">
+          <message name="IDS_APP_LIST_MESSAGE_TITLE" desc="Title given to the message displayed in the app launcher to say it is going away">
+            The Chrome App Launcher is going away.
+          </message>
+          <message name="IDS_APP_LIST_MESSAGE_TEXT" desc="The message body text displayed in the app launcher to say it is going away">
+            Use the <ph name="APPS_ICON_IMAGE">$1<ex>Apps</ex></ph> shortcut in the Chrome bookmarks bar to continue accessing your apps.
+          </message>
+        </if>
       </if>
 
       <!-- App shortcuts -->
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 8cbc245..b93cb0b 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -115,6 +115,16 @@
   <message name="IDS_SETTINGS_SETTINGS" desc="The settings page title.">
     Settings
   </message>
+  <if expr="not chromeos">
+    <message name="IDS_SETTINGS_RESTART" desc="Text for a button that will restart Chrome.">
+      Relaunch
+    </message>
+  </if>
+  <if expr="chromeos">
+    <message name="IDS_SETTINGS_RESTART" desc="Text for a button that will restart ChromeOS.">
+      Restart
+    </message>
+  </if>
 
   <!-- Passwords and Autofill Page -->
   <message name="IDS_SETTINGS_PASSWORDS_AND_AUTOFILL_PAGE_TITLE" desc="Name of the settings page which allows managing passwords and autofill settings.">
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index d1a8ea4..df060fb3 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1720,6 +1720,9 @@
     {"enable-brotli", IDS_FLAGS_ENABLE_BROTLI_NAME,
      IDS_FLAGS_ENABLE_BROTLI_DESCRIPTION, kOsAll,
      FEATURE_VALUE_TYPE(features::kBrotliEncoding)},
+    {"enable-webusb", IDS_FLAGS_ENABLE_WEB_USB_NAME,
+     IDS_FLAGS_ENABLE_WEB_USB_DESCRIPTION, kOsAll,
+     FEATURE_VALUE_TYPE(features::kWebUsb)},
 #if defined(OS_ANDROID)
     {"enable-unified-media-pipeline",
      IDS_FLAGS_ENABLE_UNIFIED_MEDIA_PIPELINE_NAME,
diff --git a/chrome/browser/android/cookies/cookies_fetcher.cc b/chrome/browser/android/cookies/cookies_fetcher.cc
index 4a1455d1..947129f 100644
--- a/chrome/browser/android/cookies/cookies_fetcher.cc
+++ b/chrome/browser/android/cookies/cookies_fetcher.cc
@@ -44,9 +44,10 @@
   jobject_.Reset(env, obj);
 
   // The rest must be done from the IO thread.
-  content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO, FROM_HERE,
       base::Bind(&CookiesFetcher::PersistCookiesInternal,
-      base::Unretained(this), getter));
+                 base::Unretained(this), base::RetainedRef(getter)));
 }
 
 void CookiesFetcher::PersistCookiesInternal(
@@ -132,12 +133,9 @@
 
   // The rest must be done from the IO thread.
   content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
+      content::BrowserThread::IO, FROM_HERE,
       base::Bind(&CookiesFetcher::RestoreToCookieJarInternal,
-                 base::Unretained(this),
-                 getter,
-                 cookie));
+                 base::Unretained(this), base::RetainedRef(getter), cookie));
 }
 
 void CookiesFetcher::RestoreToCookieJarInternal(
diff --git a/chrome/browser/android/offline_pages/offline_page_tab_helper.cc b/chrome/browser/android/offline_pages/offline_page_tab_helper.cc
index 713d241..2abf13a 100644
--- a/chrome/browser/android/offline_pages/offline_page_tab_helper.cc
+++ b/chrome/browser/android/offline_pages/offline_page_tab_helper.cc
@@ -16,6 +16,7 @@
 #include "content/public/browser/web_contents.h"
 #include "net/base/net_errors.h"
 #include "net/base/network_change_notifier.h"
+#include "ui/base/page_transition_types.h"
 
 DEFINE_WEB_CONTENTS_USER_DATA_KEY(offline_pages::OfflinePageTabHelper);
 
@@ -43,6 +44,15 @@
   if (net::NetworkChangeNotifier::IsOffline())
     return;
 
+  // Ignore navigations that are forward or back transitions in the nav stack
+  // which are not at the head of the stack.
+  if (web_contents()->GetController().GetEntryCount() > 0 &&
+      web_contents()->GetController().GetCurrentEntryIndex() != -1 &&
+      (web_contents()->GetController().GetCurrentEntryIndex() <
+       web_contents()->GetController().GetEntryCount() - 1)) {
+    return;
+  }
+
   // Skips if not loading an offline copy of saved page.
   GURL online_url = offline_pages::OfflinePageUtils::GetOnlineURLForOfflineURL(
       web_contents()->GetBrowserContext(), navigation_handle->GetURL());
@@ -77,6 +87,12 @@
   if (!net::NetworkChangeNotifier::IsOffline())
     return;
 
+  // On a forward or back transition, don't affect the order of the nav stack.
+  if (navigation_handle->GetPageTransition() ==
+      ui::PAGE_TRANSITION_FORWARD_BACK) {
+    return;
+  }
+
   // Skips if not loading an online version of saved page.
   GURL offline_url = offline_pages::OfflinePageUtils::GetOfflineURLForOnlineURL(
       web_contents()->GetBrowserContext(), navigation_handle->GetURL());
@@ -99,6 +115,7 @@
   UMA_HISTOGRAM_COUNTS("OfflinePages.RedirectToOnlineCount", 1);
   content::NavigationController::LoadURLParams load_params(online_url);
   load_params.transition_type = ui::PAGE_TRANSITION_CLIENT_REDIRECT;
+  load_params.should_replace_current_entry = true;
   web_contents()->GetController().LoadURLWithParams(load_params);
 }
 
@@ -107,6 +124,7 @@
   UMA_HISTOGRAM_COUNTS("OfflinePages.RedirectToOfflineCount", 1);
   content::NavigationController::LoadURLParams load_params(offline_url);
   load_params.transition_type = ui::PAGE_TRANSITION_CLIENT_REDIRECT;
+  load_params.should_replace_current_entry = true;
   web_contents()->GetController().LoadURLWithParams(load_params);
 }
 
diff --git a/chrome/browser/android/preferences/website_preference_bridge.cc b/chrome/browser/android/preferences/website_preference_bridge.cc
index 7d68c30..f044ab92 100644
--- a/chrome/browser/android/preferences/website_preference_bridge.cc
+++ b/chrome/browser/android/preferences/website_preference_bridge.cc
@@ -462,19 +462,14 @@
                                       jint value,
                                       jboolean is_incognito) {
   GURL url(ConvertJavaStringToUTF8(env, origin));
-  ContentSettingsPattern primary_pattern(
-      ContentSettingsPattern::FromURLNoWildcard(url));
-  ContentSettingsPattern secondary_pattern(ContentSettingsPattern::Wildcard());
-  ContentSetting setting = CONTENT_SETTING_DEFAULT;
-  if (value == -1) {
+  ContentSetting setting = static_cast<ContentSetting>(value);
+  if (setting == CONTENT_SETTING_DEFAULT) {
     GetCookieSettings()->ResetCookieSetting(url);
   } else {
-    setting = value ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
-    GetCookieSettings()->SetCookieSetting(primary_pattern, secondary_pattern,
-                                          setting);
+    GetCookieSettings()->SetCookieSetting(url, setting);
   }
-  WebSiteSettingsUmaUtil::LogPermissionChange(
-      CONTENT_SETTINGS_TYPE_NOTIFICATIONS, setting);
+  WebSiteSettingsUmaUtil::LogPermissionChange(CONTENT_SETTINGS_TYPE_COOKIES,
+                                              setting);
 }
 
 static jboolean IsContentSettingsPatternValid(
diff --git a/chrome/browser/browsing_data/cookies_tree_model.cc b/chrome/browser/browsing_data/cookies_tree_model.cc
index 26a67f6..a8fc041 100644
--- a/chrome/browser/browsing_data/cookies_tree_model.cc
+++ b/chrome/browser/browsing_data/cookies_tree_model.cc
@@ -765,9 +765,7 @@
          setting == CONTENT_SETTING_SESSION_ONLY);
   if (CanCreateContentException()) {
     cookie_settings->ResetCookieSetting(url_);
-    cookie_settings->SetCookieSetting(
-        ContentSettingsPattern::FromURL(url_),
-        ContentSettingsPattern::Wildcard(), setting);
+    cookie_settings->SetCookieSetting(url_, setting);
   }
 }
 
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 52efcab..0311f133 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -144,6 +144,7 @@
 #include "content/public/browser/power_usage_monitor.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/common/content_client.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
 #include "grit/platform_locale_settings.h"
@@ -1253,9 +1254,11 @@
 
 #if !defined(OS_ANDROID)
   // WebUSB is an experimental web API. The sites these notifications will link
-  // to will only work if the experiment is enabled.
+  // to will only work if the experiment is enabled and WebUSB feature is
+  // enabled.
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableExperimentalWebPlatformFeatures)) {
+          switches::kEnableExperimentalWebPlatformFeatures) &&
+      base::FeatureList::IsEnabled(features::kWebUsb)) {
     webusb_browser_client_.reset(new ChromeWebUsbBrowserClient());
     webusb_detector_.reset(
         new webusb::WebUsbDetector(webusb_browser_client_.get()));
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 99a1e69d..a98e46b7 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -149,6 +149,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/child_process_host.h"
 #include "content/public/common/content_descriptors.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/sandbox_type.h"
 #include "content/public/common/service_registry.h"
@@ -2800,11 +2801,18 @@
 void ChromeContentBrowserClient::RegisterRenderFrameMojoServices(
     content::ServiceRegistry* registry,
     content::RenderFrameHost* render_frame_host) {
-  registry->AddService(base::Bind(&CreateUsbDeviceManager, render_frame_host));
+  // WebUSB is an experimental web API. It will only work if the experiment
+  // is enabled and WebUSB feature is enabled.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableExperimentalWebPlatformFeatures) &&
+      base::FeatureList::IsEnabled(features::kWebUsb)) {
+    registry->AddService(
+        base::Bind(&CreateUsbDeviceManager, render_frame_host));
 #if !defined(OS_ANDROID)
-  registry->AddService(
-      base::Bind(&CreateWebUsbChooserService, render_frame_host));
+    registry->AddService(
+        base::Bind(&CreateWebUsbChooserService, render_frame_host));
 #endif  // !defined(OS_ANDROID)
+  }
 }
 
 void ChromeContentBrowserClient::RegisterInProcessMojoApplications(
diff --git a/chrome/browser/chromeos/accessibility/accessibility_highlight_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_highlight_manager.cc
new file mode 100644
index 0000000..e63d3e6
--- /dev/null
+++ b/chrome/browser/chromeos/accessibility/accessibility_highlight_manager.cc
@@ -0,0 +1,137 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/shell.h"
+#include "chrome/browser/chromeos/accessibility/accessibility_highlight_manager.h"
+#include "chrome/browser/chromeos/ui/accessibility_focus_ring_controller.h"
+#include "content/public/browser/focused_node_details.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "ui/aura/window_tree_host.h"
+
+namespace chromeos {
+
+namespace {
+
+const gfx::Rect& OffscreenRect() {
+  CR_DEFINE_STATIC_LOCAL(const gfx::Rect, r, (INT_MIN, INT_MIN, 0, 0));
+  return r;
+}
+
+const gfx::Point& OffscreenPoint() {
+  CR_DEFINE_STATIC_LOCAL(const gfx::Point, p, (INT_MIN, INT_MIN));
+  return p;
+}
+
+ui::InputMethod* GetInputMethod(aura::Window* root_window) {
+  if (root_window->GetHost())
+    return root_window->GetHost()->GetInputMethod();
+  return nullptr;
+}
+
+}  // namespace
+
+AccessibilityHighlightManager::AccessibilityHighlightManager() {
+  ash::Shell::GetInstance()->AddPreTargetHandler(this);
+  registrar_.Add(this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
+                 content::NotificationService::AllSources());
+  aura::Window* root_window = ash::Shell::GetPrimaryRootWindow();
+  ui::InputMethod* input_method = GetInputMethod(root_window);
+  input_method->AddObserver(this);
+  focus_rect_ = OffscreenRect();
+  cursor_point_ = OffscreenPoint();
+  caret_point_ = OffscreenPoint();
+}
+
+AccessibilityHighlightManager::~AccessibilityHighlightManager() {
+  // No need to do anything during shutdown
+  if (!ash::Shell::HasInstance())
+    return;
+
+  ash::Shell* shell = ash::Shell::GetInstance();
+  if (shell) {
+    shell->RemovePreTargetHandler(this);
+
+    AccessibilityFocusRingController::GetInstance()->SetFocusRing(
+        std::vector<gfx::Rect>());
+    AccessibilityFocusRingController::GetInstance()->SetCaretRing(
+        OffscreenPoint());
+    AccessibilityFocusRingController::GetInstance()->SetCursorRing(
+        OffscreenPoint());
+
+    aura::Window* root_window = shell->GetPrimaryRootWindow();
+    ui::InputMethod* input_method = GetInputMethod(root_window);
+    input_method->RemoveObserver(this);
+  }
+}
+
+void AccessibilityHighlightManager::HighlightFocus(bool focus) {
+  focus_ = focus;
+
+  std::vector<gfx::Rect> rects;
+  rects.push_back(focus_ ? focus_rect_ : OffscreenRect());
+  AccessibilityFocusRingController::GetInstance()->SetFocusRing(rects);
+}
+
+void AccessibilityHighlightManager::HighlightCursor(bool cursor) {
+  cursor_ = cursor;
+
+  AccessibilityFocusRingController::GetInstance()->SetCursorRing(
+      cursor_ ? cursor_point_ : OffscreenPoint());
+}
+
+void AccessibilityHighlightManager::HighlightCaret(bool caret) {
+  caret_ = caret;
+
+  AccessibilityFocusRingController::GetInstance()->SetCaretRing(
+      caret_ ? caret_point_ : OffscreenPoint());
+}
+
+void AccessibilityHighlightManager::OnMouseEvent(ui::MouseEvent* event) {
+  if (event->type() == ui::ET_MOUSE_MOVED) {
+    cursor_point_ = event->root_location();
+    AccessibilityFocusRingController::GetInstance()->SetCursorRing(
+        cursor_ ? cursor_point_ : OffscreenPoint());
+  }
+}
+
+void AccessibilityHighlightManager::Observe(
+    int type,
+    const content::NotificationSource& source,
+    const content::NotificationDetails& details) {
+  DCHECK_EQ(type, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE);
+  content::FocusedNodeDetails* node_details =
+      content::Details<content::FocusedNodeDetails>(details).ptr();
+  focus_rect_ = node_details->node_bounds_in_screen;
+
+  if (focus_) {
+    std::vector<gfx::Rect> rects;
+    rects.push_back(focus_rect_);
+    AccessibilityFocusRingController::GetInstance()->SetFocusRing(rects);
+  }
+}
+
+void AccessibilityHighlightManager::OnTextInputStateChanged(
+    const ui::TextInputClient* client) {
+  if (!client || client->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) {
+    caret_point_ = OffscreenPoint();
+    if (caret_) {
+      AccessibilityFocusRingController::GetInstance()->SetCaretRing(
+          caret_point_);
+    }
+  }
+}
+
+void AccessibilityHighlightManager::OnCaretBoundsChanged(
+    const ui::TextInputClient* client) {
+  gfx::Rect caret_bounds = client->GetCaretBounds();
+  if (caret_bounds.width() == 0 && caret_bounds.height() == 0)
+    caret_bounds = OffscreenRect();
+  caret_point_ = caret_bounds.CenterPoint();
+
+  if (caret_)
+    AccessibilityFocusRingController::GetInstance()->SetCaretRing(caret_point_);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/accessibility/accessibility_highlight_manager.h b/chrome/browser/chromeos/accessibility/accessibility_highlight_manager.h
new file mode 100644
index 0000000..3804612
--- /dev/null
+++ b/chrome/browser/chromeos/accessibility/accessibility_highlight_manager.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_ACCESSIBILITY_HIGHLIGHT_MANAGER_H_
+#define CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_ACCESSIBILITY_HIGHLIGHT_MANAGER_H_
+
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/notification_source.h"
+#include "ui/base/ime/input_method.h"
+#include "ui/base/ime/input_method_observer.h"
+#include "ui/base/ime/text_input_client.h"
+#include "ui/events/event.h"
+#include "ui/events/event_handler.h"
+
+namespace chromeos {
+
+// Manage visual highlights that Chrome OS can draw around the focused
+// object, the cursor, and the text caret for accessibility.
+class AccessibilityHighlightManager : public ui::EventHandler,
+                                      public content::NotificationObserver,
+                                      public ui::InputMethodObserver {
+ public:
+  AccessibilityHighlightManager();
+  ~AccessibilityHighlightManager() override;
+
+  void HighlightFocus(bool focus);
+  void HighlightCursor(bool cursor);
+  void HighlightCaret(bool caret);
+
+ private:
+  // ui::EventHandler overrides:
+  void OnMouseEvent(ui::MouseEvent* event) override;
+
+  // content::NotificationObserver overrides:
+  void Observe(int type,
+               const content::NotificationSource& source,
+               const content::NotificationDetails& details) override;
+
+  // ui::InputMethodObserver overrides:
+  void OnTextInputTypeChanged(const ui::TextInputClient* client) override {}
+  void OnFocus() override {}
+  void OnBlur() override {}
+  void OnInputMethodDestroyed(const ui::InputMethod* input_method) override {}
+  void OnShowImeIfNeeded() override {}
+  void OnTextInputStateChanged(const ui::TextInputClient* client) override;
+  void OnCaretBoundsChanged(const ui::TextInputClient* client) override;
+
+  bool focus_ = false;
+  gfx::Rect focus_rect_;
+
+  bool cursor_ = false;
+  gfx::Point cursor_point_;
+
+  bool caret_ = false;
+  gfx::Point caret_point_;
+
+  content::NotificationRegistrar registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(AccessibilityHighlightManager);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_ACCESSIBILITY_HIGHLIGHT_MANAGER_H_
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index 1ea9351..cdf37a7 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -33,6 +33,7 @@
 #include "chrome/browser/accessibility/accessibility_extension_api.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/chromeos/accessibility/accessibility_highlight_manager.h"
 #include "chrome/browser/chromeos/accessibility/magnification_manager.h"
 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
@@ -901,7 +902,7 @@
     return;
   caret_highlight_enabled_ = enabled;
 
-  // TODO(dmazzoni): implement feature here.
+  UpdateAccessibilityHighlightingFromPrefs();
 }
 
 void AccessibilityManager::SetCursorHighlightEnabled(bool enabled) {
@@ -929,7 +930,7 @@
     return;
   cursor_highlight_enabled_ = enabled;
 
-  // TODO(dmazzoni): implement feature here.
+  UpdateAccessibilityHighlightingFromPrefs();
 }
 
 void AccessibilityManager::SetFocusHighlightEnabled(bool enabled) {
@@ -956,7 +957,7 @@
     return;
   focus_highlight_enabled_ = enabled;
 
-  // TODO(dmazzoni): implement feature here.
+  UpdateAccessibilityHighlightingFromPrefs();
 }
 
 void AccessibilityManager::SetSelectToSpeakEnabled(bool enabled) {
@@ -1013,6 +1014,22 @@
   // TODO(dmazzoni): implement feature here.
 }
 
+void AccessibilityManager::UpdateAccessibilityHighlightingFromPrefs() {
+  if (!focus_highlight_enabled_ && !caret_highlight_enabled_ &&
+      !cursor_highlight_enabled_) {
+    if (accessibility_highlight_manager_)
+      accessibility_highlight_manager_.reset();
+    return;
+  }
+
+  if (!accessibility_highlight_manager_)
+    accessibility_highlight_manager_.reset(new AccessibilityHighlightManager());
+
+  accessibility_highlight_manager_->HighlightFocus(focus_highlight_enabled_);
+  accessibility_highlight_manager_->HighlightCaret(caret_highlight_enabled_);
+  accessibility_highlight_manager_->HighlightCursor(cursor_highlight_enabled_);
+}
+
 bool AccessibilityManager::IsBrailleDisplayConnected() const {
   return braille_display_connected_;
 }
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h
index 3fbc377d..a6cb843 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -34,6 +34,8 @@
 
 namespace chromeos {
 
+class AccessibilityHighlightManager;
+
 enum AccessibilityNotificationType {
   ACCESSIBILITY_MANAGER_SHUTDOWN,
   ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE,
@@ -281,6 +283,7 @@
   void UpdateFocusHighlightFromPref();
   void UpdateSelectToSpeakFromPref();
   void UpdateSwitchAccessFromPref();
+  void UpdateAccessibilityHighlightingFromPrefs();
 
   void CheckBrailleState();
   void ReceiveBrailleDisplayState(
@@ -379,6 +382,8 @@
                  extensions::ExtensionRegistryObserver>
       extension_registry_observer_;
 
+  scoped_ptr<AccessibilityHighlightManager> accessibility_highlight_manager_;
+
   base::WeakPtrFactory<AccessibilityManager> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(AccessibilityManager);
diff --git a/chrome/browser/chromeos/base/file_flusher.cc b/chrome/browser/chromeos/base/file_flusher.cc
new file mode 100644
index 0000000..4315dbf2
--- /dev/null
+++ b/chrome/browser/chromeos/base/file_flusher.cc
@@ -0,0 +1,206 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/base/file_flusher.h"
+
+#include <set>
+
+#include "base/bind.h"
+#include "base/files/file.h"
+#include "base/files/file_enumerator.h"
+#include "base/logging.h"
+#include "base/synchronization/cancellation_flag.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace chromeos {
+
+namespace {
+
+std::set<base::FilePath> MakeAbsoutePathSet(
+    const base::FilePath& base,
+    const std::vector<base::FilePath>& paths) {
+  std::set<base::FilePath> result;
+  for (const auto& path : paths) {
+    result.insert(path.IsAbsolute() ? path : base.Append(path));
+  }
+  return result;
+}
+
+}  // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// FileFlusher::Job
+
+class FileFlusher::Job {
+ public:
+  Job(const base::WeakPtr<FileFlusher>& master,
+      const base::FilePath& path,
+      const std::vector<base::FilePath>& excludes,
+      const FileFlusher::OnFlushCallback& on_flush_callback,
+      const base::Closure& callback);
+  ~Job() = default;
+
+  void Start();
+  void Cancel();
+
+  const base::FilePath& path() const { return path_; }
+  bool started() const { return started_; }
+
+ private:
+  // Flush files on a blocking pool thread.
+  void FlushOnBlockingPool();
+
+  // Whether to exclude the |path| from flushing.
+  bool ShouldExclude(const base::FilePath& path) const;
+
+  // Schedule a FinishOnUIThread task to run on the UI thread.
+  void ScheduleFinish();
+
+  // Finish the job by notifying |master_| and self destruct on the UI thread.
+  void FinishOnUIThread();
+
+  base::WeakPtr<FileFlusher> master_;
+  const base::FilePath path_;
+  const std::set<base::FilePath> excludes_;
+  const FileFlusher::OnFlushCallback on_flush_callback_;
+  const base::Closure callback_;
+
+  bool started_ = false;
+  base::CancellationFlag cancel_flag_;
+
+  DISALLOW_COPY_AND_ASSIGN(Job);
+};
+
+FileFlusher::Job::Job(const base::WeakPtr<FileFlusher>& master,
+                      const base::FilePath& path,
+                      const std::vector<base::FilePath>& excludes,
+                      const FileFlusher::OnFlushCallback& on_flush_callback,
+                      const base::Closure& callback)
+    : master_(master),
+      path_(path),
+      excludes_(MakeAbsoutePathSet(path, excludes)),
+      on_flush_callback_(on_flush_callback),
+      callback_(callback) {}
+
+void FileFlusher::Job::Start() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  DCHECK(!started());
+
+  started_ = true;
+
+  if (cancel_flag_.IsSet()) {
+    ScheduleFinish();
+    return;
+  }
+
+  content::BrowserThread::PostBlockingPoolTaskAndReply(
+      FROM_HERE, base::Bind(&FileFlusher::Job::FlushOnBlockingPool,
+                            base::Unretained(this)),
+      base::Bind(&FileFlusher::Job::FinishOnUIThread, base::Unretained(this)));
+}
+
+void FileFlusher::Job::Cancel() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  cancel_flag_.Set();
+
+  // Cancel() could be called in an iterator/range loop in master thus don't
+  // invoke FinishOnUIThread in-place.
+  if (!started())
+    ScheduleFinish();
+}
+
+void FileFlusher::Job::FlushOnBlockingPool() {
+  DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
+
+  VLOG(1) << "Flushing files under " << path_.value();
+
+  base::FileEnumerator traversal(path_, true /* recursive */,
+                                 base::FileEnumerator::FILES);
+  for (base::FilePath current = traversal.Next();
+       !current.empty() && !cancel_flag_.IsSet(); current = traversal.Next()) {
+    if (ShouldExclude(current))
+      continue;
+
+    base::File currentFile(current,
+                           base::File::FLAG_OPEN | base::File::FLAG_WRITE);
+    if (!currentFile.IsValid()) {
+      VLOG(1) << "Unable to flush file:" << current.value();
+      continue;
+    }
+
+    currentFile.Flush();
+    currentFile.Close();
+
+    if (!on_flush_callback_.is_null())
+      on_flush_callback_.Run(current);
+  }
+}
+
+bool FileFlusher::Job::ShouldExclude(const base::FilePath& path) const {
+  return excludes_.find(path) != excludes_.end();
+}
+
+void FileFlusher::Job::ScheduleFinish() {
+  content::BrowserThread::PostTask(
+      content::BrowserThread::UI, FROM_HERE,
+      base::Bind(&Job::FinishOnUIThread, base::Unretained(this)));
+}
+
+void FileFlusher::Job::FinishOnUIThread() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  if (!callback_.is_null())
+    callback_.Run();
+
+  if (master_)
+    master_->OnJobDone(this);
+
+  delete this;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// FileFlusher
+
+FileFlusher::FileFlusher() : weak_factory_(this) {}
+
+FileFlusher::~FileFlusher() {
+  for (const auto& job : jobs_)
+    job->Cancel();
+}
+
+void FileFlusher::RequestFlush(const base::FilePath& path,
+                               const std::vector<base::FilePath>& excludes,
+                               const base::Closure& callback) {
+  for (const auto& job : jobs_) {
+    if (path == job->path() || path.IsParent(job->path()))
+      job->Cancel();
+  }
+
+  jobs_.push_back(new Job(weak_factory_.GetWeakPtr(), path, excludes,
+                          on_flush_callback_for_test_, callback));
+  ScheduleJob();
+}
+
+void FileFlusher::ScheduleJob() {
+  if (jobs_.empty())
+    return;
+
+  auto job = jobs_.front();
+  if (!job->started())
+    job->Start();
+}
+
+void FileFlusher::OnJobDone(FileFlusher::Job* job) {
+  for (auto it = jobs_.begin(); it != jobs_.end(); ++it) {
+    if (*it == job) {
+      jobs_.erase(it);
+      break;
+    }
+  }
+
+  ScheduleJob();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/base/file_flusher.h b/chrome/browser/chromeos/base/file_flusher.h
new file mode 100644
index 0000000..d33f983
--- /dev/null
+++ b/chrome/browser/chromeos/base/file_flusher.h
@@ -0,0 +1,64 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_BASE_FILE_FLUSHER_H_
+#define CHROME_BROWSER_CHROMEOS_BASE_FILE_FLUSHER_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+
+namespace chromeos {
+
+// Flushes files under the requested directories in the blocking pool. If the
+// same directory is requested more than once, the last request cancels all
+// previous ones and start a new flushing process.
+class FileFlusher {
+ public:
+  FileFlusher();
+  ~FileFlusher();
+
+  // Flush everything under |path| except the directories/files in |excludes|.
+  // |excluedes| can hold both absolute or relative paths, where absolute paths
+  // are used as-is and relative paths are appended to |path| to make it
+  // absolute. |callback| is invoked when the request is finished or canceled.
+  void RequestFlush(const base::FilePath& path,
+                    const std::vector<base::FilePath>& excludes,
+                    const base::Closure& callback);
+
+  // Set a callback for every file flush for test. Note the callback is
+  // called on a blocking pool thread.
+  using OnFlushCallback = base::Callback<void(const base::FilePath&)>;
+  void set_on_flush_callback_for_test(
+      const OnFlushCallback& on_flush_callback) {
+    on_flush_callback_for_test_ = on_flush_callback;
+  }
+
+ private:
+  // Job for the flushing requests.
+  class Job;
+
+  // Starts the first job in |jobs_|.
+  void ScheduleJob();
+
+  // Invoked by a Job when it finishes.
+  void OnJobDone(Job* job);
+
+  // Not owned. Job manages its own life time.
+  std::vector<Job*> jobs_;
+
+  // A callback for testing to be invoked when a file is flushed.
+  OnFlushCallback on_flush_callback_for_test_;
+
+  base::WeakPtrFactory<FileFlusher> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(FileFlusher);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_BASE_FILE_FLUSHER_H_
diff --git a/chrome/browser/chromeos/base/file_flusher_unittest.cc b/chrome/browser/chromeos/base/file_flusher_unittest.cc
new file mode 100644
index 0000000..e295f85
--- /dev/null
+++ b/chrome/browser/chromeos/base/file_flusher_unittest.cc
@@ -0,0 +1,150 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/base/file_flusher.h"
+
+#include <map>
+
+#include "base/bind.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+namespace {
+
+void WriteStringToFile(const base::FilePath path, const std::string& data) {
+  ASSERT_TRUE(base::CreateDirectory(path.DirName()))
+      << "Failed to create directory " << path.DirName().value();
+
+  int size = data.size();
+  ASSERT_TRUE(base::WriteFile(path, data.c_str(), size) == size)
+      << "Failed to write " << path.value();
+}
+
+}  // namespace
+
+// Provide basic sanity test of the FileFlusher. Note it only tests that
+// flush is called for the expected files but not testing the underlying
+// file system for actually persisting the data.
+class FileFlusherTest : public testing::Test {
+ public:
+  FileFlusherTest() {}
+  ~FileFlusherTest() override {}
+
+  // testing::Test
+  void SetUp() override {
+    // Create test files under a temp dir.
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+    const size_t kNumDirs = 2;
+    const size_t kNumFiles = 3;
+    for (size_t i = 1; i <= kNumDirs; ++i) {
+      for (size_t j = 1; j <= kNumFiles; ++j) {
+        const std::string path = base::StringPrintf("dir%zu/file%zu", i, j);
+        const std::string content = base::StringPrintf("content %zu %zu", i, j);
+        WriteStringToFile(temp_dir_.path().AppendASCII(path), content);
+      }
+    }
+  }
+
+  void TearDown() override {
+    content::BrowserThread::GetBlockingPool()->FlushForTesting();
+    base::RunLoop().RunUntilIdle();
+  }
+
+  scoped_ptr<FileFlusher> CreateFileFlusher() {
+    scoped_ptr<FileFlusher> flusher(new FileFlusher);
+    flusher->set_on_flush_callback_for_test(
+        base::Bind(&FileFlusherTest::OnFlush, base::Unretained(this)));
+    return flusher;
+  }
+
+  base::FilePath GetTestFilePath(const std::string& path_string) const {
+    const base::FilePath path = base::FilePath::FromUTF8Unsafe(path_string);
+    if (path.IsAbsolute())
+      return path;
+
+    return temp_dir_.path().Append(path);
+  }
+
+  void OnFlush(const base::FilePath& path) { ++flush_counts_[path]; }
+
+  int GetFlushCount(const std::string& path_string) const {
+    const base::FilePath path(GetTestFilePath(path_string));
+    const auto& it = flush_counts_.find(path);
+    return it == flush_counts_.end() ? 0 : it->second;
+  }
+
+ private:
+  content::TestBrowserThreadBundle thread_bundle_;
+  base::ScopedTempDir temp_dir_;
+  std::map<base::FilePath, int> flush_counts_;
+
+  DISALLOW_COPY_AND_ASSIGN(FileFlusherTest);
+};
+
+TEST_F(FileFlusherTest, Flush) {
+  scoped_ptr<FileFlusher> flusher(CreateFileFlusher());
+  base::RunLoop run_loop;
+  flusher->RequestFlush(GetTestFilePath("dir1"), std::vector<base::FilePath>(),
+                        base::Closure());
+  flusher->RequestFlush(GetTestFilePath("dir2"), std::vector<base::FilePath>(),
+                        run_loop.QuitClosure());
+  run_loop.Run();
+
+  EXPECT_EQ(1, GetFlushCount("dir1/file1"));
+  EXPECT_EQ(1, GetFlushCount("dir1/file2"));
+  EXPECT_EQ(1, GetFlushCount("dir1/file3"));
+
+  EXPECT_EQ(1, GetFlushCount("dir2/file1"));
+  EXPECT_EQ(1, GetFlushCount("dir2/file2"));
+  EXPECT_EQ(1, GetFlushCount("dir2/file3"));
+}
+
+TEST_F(FileFlusherTest, Exclude) {
+  scoped_ptr<FileFlusher> flusher(CreateFileFlusher());
+
+  std::vector<base::FilePath> excludes;
+  // Relative exclude
+  excludes.push_back(base::FilePath::FromUTF8Unsafe("file1"));
+  // Absolute exclude
+  excludes.push_back(GetTestFilePath("dir1/file2"));
+  // Invalid exclude will be ignored.
+  excludes.push_back(base::FilePath::FromUTF8Unsafe("Bad file"));
+
+  base::RunLoop run_loop;
+  flusher->RequestFlush(GetTestFilePath("dir1"), excludes,
+                        run_loop.QuitClosure());
+  run_loop.Run();
+
+  EXPECT_EQ(0, GetFlushCount("dir1/file1"));
+  EXPECT_EQ(0, GetFlushCount("dir1/file2"));
+  EXPECT_EQ(1, GetFlushCount("dir1/file3"));
+
+  EXPECT_EQ(0, GetFlushCount("dir1/Bad file"));
+}
+
+TEST_F(FileFlusherTest, DuplicateRequests) {
+  scoped_ptr<FileFlusher> flusher(CreateFileFlusher());
+  base::RunLoop run_loop;
+  flusher->RequestFlush(GetTestFilePath("dir1"), std::vector<base::FilePath>(),
+                        base::Closure());
+  flusher->RequestFlush(GetTestFilePath("dir1"), std::vector<base::FilePath>(),
+                        run_loop.QuitClosure());
+  run_loop.Run();
+
+  EXPECT_EQ(1, GetFlushCount("dir1/file1"));
+  EXPECT_EQ(1, GetFlushCount("dir1/file2"));
+  EXPECT_EQ(1, GetFlushCount("dir1/file3"));
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index cd13f690..1b571b8a 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -613,11 +613,17 @@
   // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun()
   // -- just after CreateProfile().
 
-  // Force loading of signin profile if it was not loaded before. It is possible
-  // when we are restoring session or skipping login screen for some other
-  // reason.
-  if (!chromeos::ProfileHelper::IsSigninProfile(profile()))
+  if (chromeos::ProfileHelper::IsSigninProfile(profile())) {
+    // Flush signin profile if it is just created (new device or after recovery)
+    // to ensure it is correctly persisted.
+    if (profile()->IsNewProfile())
+      ProfileHelper::Get()->FlushProfile(profile());
+  } else {
+    // Force loading of signin profile if it was not loaded before. It is
+    // possible when we are restoring session or skipping login screen for some
+    // other reason.
     chromeos::ProfileHelper::GetSigninProfile();
+  }
 
   BootTimesRecorder::Get()->OnChromeProcessStart();
 
diff --git a/chrome/browser/chromeos/display/display_preferences_unittest.cc b/chrome/browser/chromeos/display/display_preferences_unittest.cc
index 3aa5862..18f0d2ab 100644
--- a/chrome/browser/chromeos/display/display_preferences_unittest.cc
+++ b/chrome/browser/chromeos/display/display_preferences_unittest.cc
@@ -108,8 +108,7 @@
     std::string name = ash::DisplayIdListToString(list);
     DictionaryPrefUpdate update(&local_state_, prefs::kSecondaryDisplays);
     ash::DisplayLayout display_layout;
-    display_layout.placement_list.push_back(
-        new ash::DisplayPlacement(position, offset));
+    display_layout.placement_list.emplace_back(position, offset);
     display_layout.primary_id = primary_id;
 
     DCHECK(!name.empty());
@@ -197,7 +196,7 @@
         ->layout_store()
         ->GetRegisteredDisplayLayout(list)
         .placement_list[0]
-        ->ToString();
+        .ToString();
   }
 
   PrefService* local_state() { return &local_state_; }
@@ -244,7 +243,7 @@
             shell->display_manager()
                 ->GetCurrentDisplayLayout()
                 .placement_list[0]
-                ->ToString());
+                .ToString());
   EXPECT_EQ("id=2200000001, parent=2200000000, top, 20",
             GetRegisteredDisplayPlacementStr(list));
   EXPECT_EQ("id=2200000002, parent=2200000000, left, 30",
@@ -278,8 +277,8 @@
   display_manager->SetLayoutForCurrentDisplays(
       ash::test::CreateDisplayLayout(ash::DisplayPlacement::TOP, 10));
   const ash::DisplayLayout& layout = display_manager->GetCurrentDisplayLayout();
-  EXPECT_EQ(ash::DisplayPlacement::TOP, layout.placement_list[0]->position);
-  EXPECT_EQ(10, layout.placement_list[0]->offset);
+  EXPECT_EQ(ash::DisplayPlacement::TOP, layout.placement_list[0].position);
+  EXPECT_EQ(10, layout.placement_list[0].offset);
 
   ash::DisplayLayoutBuilder dummy_layout_builder(id1);
   dummy_layout_builder.SetSecondaryPlacement(dummy_id,
@@ -310,10 +309,10 @@
   EXPECT_TRUE(ash::JsonToDisplayLayout(*layout_value, &stored_layout));
   ASSERT_EQ(1u, stored_layout.placement_list.size());
 
-  EXPECT_EQ(dummy_layout->placement_list[0]->position,
-            stored_layout.placement_list[0]->position);
-  EXPECT_EQ(dummy_layout->placement_list[0]->offset,
-            stored_layout.placement_list[0]->offset);
+  EXPECT_EQ(dummy_layout->placement_list[0].position,
+            stored_layout.placement_list[0].position);
+  EXPECT_EQ(dummy_layout->placement_list[0].offset,
+            stored_layout.placement_list[0].offset);
 
   bool mirrored = true;
   EXPECT_TRUE(layout_value->GetBoolean(kMirroredKey, &mirrored));
@@ -404,7 +403,7 @@
   EXPECT_TRUE(ash::JsonToDisplayLayout(*layout_value, &stored_layout));
   ASSERT_EQ(1u, stored_layout.placement_list.size());
   const ash::DisplayPlacement& stored_placement =
-      *stored_layout.placement_list[0];
+      stored_layout.placement_list[0];
   EXPECT_EQ(ash::DisplayPlacement::BOTTOM, stored_placement.position);
   EXPECT_EQ(-10, stored_placement.offset);
   EXPECT_EQ(id1, stored_placement.display_id);
@@ -581,7 +580,7 @@
     EXPECT_TRUE(ash::JsonToDisplayLayout(*new_value, &stored_layout));
     ASSERT_EQ(1u, stored_layout.placement_list.size());
     const ash::DisplayPlacement& stored_placement =
-        *stored_layout.placement_list[0];
+        stored_layout.placement_list[0];
     EXPECT_EQ(ash::DisplayPlacement::LEFT, stored_placement.position);
     EXPECT_EQ(0, stored_placement.offset);
     EXPECT_EQ(id1, stored_placement.display_id);
@@ -599,7 +598,7 @@
     EXPECT_TRUE(ash::JsonToDisplayLayout(*new_value, &stored_layout));
     ASSERT_EQ(1u, stored_layout.placement_list.size());
     const ash::DisplayPlacement& stored_placement =
-        *stored_layout.placement_list[0];
+        stored_layout.placement_list[0];
     EXPECT_EQ(ash::DisplayPlacement::TOP, stored_placement.position);
     EXPECT_EQ(10, stored_placement.offset);
     EXPECT_EQ(id1, stored_placement.display_id);
@@ -618,7 +617,7 @@
     EXPECT_TRUE(ash::JsonToDisplayLayout(*new_value, &stored_layout));
     ASSERT_EQ(1u, stored_layout.placement_list.size());
     const ash::DisplayPlacement& stored_placement =
-        *stored_layout.placement_list[0];
+        stored_layout.placement_list[0];
     EXPECT_EQ(ash::DisplayPlacement::BOTTOM, stored_placement.position);
     EXPECT_EQ(-10, stored_placement.offset);
     EXPECT_EQ(id2, stored_placement.display_id);
@@ -688,7 +687,7 @@
   gfx::Screen* screen = gfx::Screen::GetScreen();
   EXPECT_EQ(id2, screen->GetPrimaryDisplay().id());
   const ash::DisplayPlacement& placement =
-      *display_manager->GetCurrentDisplayLayout().placement_list[0];
+      display_manager->GetCurrentDisplayLayout().placement_list[0];
   EXPECT_EQ(ash::DisplayPlacement::BOTTOM, placement.position);
   EXPECT_EQ(-10, placement.offset);
   const gfx::Display& primary_display = screen->GetPrimaryDisplay();
diff --git a/chrome/browser/chromeos/drive/fileapi/webkit_file_stream_writer_impl.cc b/chrome/browser/chromeos/drive/fileapi/webkit_file_stream_writer_impl.cc
index a4bf4ad..6953256 100644
--- a/chrome/browser/chromeos/drive/fileapi/webkit_file_stream_writer_impl.cc
+++ b/chrome/browser/chromeos/drive/fileapi/webkit_file_stream_writer_impl.cc
@@ -85,7 +85,7 @@
       file_system_getter_, file_path_,
       base::Bind(
           &WebkitFileStreamWriterImpl::WriteAfterCreateWritableSnapshotFile,
-          weak_ptr_factory_.GetWeakPtr(), make_scoped_refptr(buf), buf_len));
+          weak_ptr_factory_.GetWeakPtr(), base::RetainedRef(buf), buf_len));
   return net::ERR_IO_PENDING;
 }
 
diff --git a/chrome/browser/chromeos/extensions/wallpaper_api.cc b/chrome/browser/chromeos/extensions/wallpaper_api.cc
index 58e0c30..7a5cd78 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_api.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_api.cc
@@ -205,7 +205,8 @@
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::Bind(&WallpaperSetWallpaperFunction::ThumbnailGenerated, this,
-                 original_data, thumbnail_data));
+                 base::RetainedRef(original_data),
+                 base::RetainedRef(thumbnail_data)));
 }
 
 void WallpaperSetWallpaperFunction::ThumbnailGenerated(
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
index a51750f0..ce46325 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
@@ -670,10 +670,10 @@
       wallpaper::kWallpaperThumbnailWidth, wallpaper::kWallpaperThumbnailHeight,
       &data, NULL);
   BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE,
-        base::Bind(
-            &WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated,
-            this, data));
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(
+          &WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated, this,
+          base::RetainedRef(data)));
 }
 
 void WallpaperPrivateSetCustomWallpaperFunction::ThumbnailGenerated(
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 2173069..77d4939 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -304,8 +304,8 @@
     content::BrowserThread::PostDelayedTask(
         content::BrowserThread::IO, FROM_HERE,
         base::Bind(&TransferContextAuthenticationsOnIOThread,
-                   signin_profile_context_getter,
-                   browser_process_context_getter),
+                   base::RetainedRef(signin_profile_context_getter),
+                   base::RetainedRef(browser_process_context_getter)),
         base::TimeDelta::FromMilliseconds(kAuthCacheTransferDelayMs));
   }
 }
@@ -334,12 +334,16 @@
 }
 
 void ExistingUserController::CompleteLogin(const UserContext& user_context) {
-  login_display_->set_signin_completed(true);
   if (!host_) {
     // Complete login event was generated already from UI. Ignore notification.
     return;
   }
 
+  if (is_login_in_progress_)
+    return;
+
+  is_login_in_progress_ = true;
+
   ContinueLoginIfDeviceNotDisabled(base::Bind(
       &ExistingUserController::DoCompleteLogin,
       weak_factory_.GetWeakPtr(),
@@ -356,6 +360,24 @@
 
 void ExistingUserController::Login(const UserContext& user_context,
                                    const SigninSpecifics& specifics) {
+  if (is_login_in_progress_) {
+    // If there is another login in progress, bail out. Do not re-enable
+    // clicking on other windows and the status area. Do not start the
+    // auto-login timer.
+    return;
+  }
+
+  is_login_in_progress_ = true;
+
+  if (user_context.GetUserType() != user_manager::USER_TYPE_REGULAR &&
+      user_manager::UserManager::Get()->IsUserLoggedIn()) {
+    // Multi-login is only allowed for regular users. If we are attempting to
+    // do multi-login as another type of user somehow, bail out. Do not
+    // re-enable clicking on other windows and the status area. Do not start the
+    // auto-login timer.
+    return;
+  }
+
   ContinueLoginIfDeviceNotDisabled(base::Bind(
       &ExistingUserController::DoLogin,
       weak_factory_.GetWeakPtr(),
@@ -1039,14 +1061,7 @@
     last_login_attempt_account_id_ = user_context.GetAccountId();
     num_login_attempts_ = 0;
   }
-
-  // Guard in cases when we're called twice but login process is still active.
-  // This might happen when login process is paused till signed settings status
-  // is verified which results in Login* method called again as a callback.
-  if (!is_login_in_progress_)
-    num_login_attempts_++;
-
-  is_login_in_progress_ = true;
+  num_login_attempts_++;
 
   // Stop the auto-login timer when attempting login.
   StopPublicSessionAutoLoginTimer();
@@ -1166,22 +1181,6 @@
 
 void ExistingUserController::DoLogin(const UserContext& user_context,
                                      const SigninSpecifics& specifics) {
-  if (is_login_in_progress_) {
-    // If there is another login in progress, bail out. Do not re-enable
-    // clicking on other windows and the status area. Do not start the
-    // auto-login timer.
-    return;
-  }
-
-  if (user_context.GetUserType() != user_manager::USER_TYPE_REGULAR &&
-      user_manager::UserManager::Get()->IsUserLoggedIn()) {
-    // Multi-login is only allowed for regular users. If we are attempting to
-    // do multi-login as another type of user somehow, bail out. Do not
-    // re-enable clicking on other windows and the status area. Do not start the
-    // auto-login timer.
-    return;
-  }
-
   if (user_context.GetUserType() == user_manager::USER_TYPE_GUEST) {
     if (!specifics.guest_mode_url.empty()) {
       guest_mode_url_ = GURL(specifics.guest_mode_url);
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc
index 62797795..710e3659 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -801,6 +801,11 @@
     // We need to restart cleanly in this case to make sure OAuth2 RT is
     // actually saved.
     chrome::AttemptRestart();
+  } else {
+    // Schedule another flush after session restore for non-ephemeral profile
+    // if not restarting.
+    if (!ProfileHelper::IsEphemeralUserProfile(user_profile))
+      ProfileHelper::Get()->FlushProfile(user_profile);
   }
 }
 
@@ -1175,6 +1180,10 @@
   // If needed, create browser observer to display first run OOBE Goodies page.
   first_run::GoodiesDisplayer::Init();
 
+  // Schedule a flush if profile is not ephemeral.
+  if (!ProfileHelper::IsEphemeralUserProfile(profile))
+    ProfileHelper::Get()->FlushProfile(profile);
+
   // TODO(nkostylev): This pointer should probably never be NULL, but it looks
   // like OnProfileCreated() may be getting called before
   // UserSessionManager::PrepareProfile() has set |delegate_| when Chrome is
diff --git a/chrome/browser/chromeos/profiles/profile_helper.cc b/chrome/browser/chromeos/profiles/profile_helper.cc
index ee28d782..d492f72b 100644
--- a/chrome/browser/chromeos/profiles/profile_helper.cc
+++ b/chrome/browser/chromeos/profiles/profile_helper.cc
@@ -11,13 +11,17 @@
 #include "chrome/browser/browsing_data/browsing_data_helper.h"
 #include "chrome/browser/browsing_data/browsing_data_remover.h"
 #include "chrome/browser/browsing_data/browsing_data_remover_factory.h"
+#include "chrome/browser/chromeos/base/file_flusher.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h"
+#include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
+#include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_switches.h"
+#include "chromeos/chromeos_constants.h"
 #include "chromeos/chromeos_switches.h"
 #include "components/guest_view/browser/guest_view_manager.h"
 #include "components/user_manager/user.h"
@@ -26,6 +30,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/guest_view/web_view/web_view_guest.h"
+#include "extensions/common/constants.h"
 
 namespace chromeos {
 
@@ -157,7 +162,7 @@
 }
 
 // static
-bool ProfileHelper::IsOwnerProfile(Profile* profile) {
+bool ProfileHelper::IsOwnerProfile(const Profile* profile) {
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           chromeos::switches::kStubCrosSettings)) {
     return true;
@@ -184,6 +189,31 @@
   return user == user_manager::UserManager::Get()->GetPrimaryUser();
 }
 
+// static
+bool ProfileHelper::IsEphemeralUserProfile(const Profile* profile) {
+  if (!profile)
+    return false;
+
+  // Owner profile is always persistent.
+  if (IsOwnerProfile(profile))
+    return false;
+
+  const user_manager::User* user =
+      ProfileHelper::Get()->GetUserByProfile(profile);
+  if (!user)
+    return false;
+
+  // Guest and public account is ephemeral.
+  const user_manager::UserType user_type = user->GetType();
+  if (user_type == user_manager::USER_TYPE_GUEST ||
+      user_type == user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
+    return true;
+  }
+
+  // Otherwise, users are ephemeral when the policy is enabled.
+  return ChromeUserManager::Get()->AreEphemeralUsersEnabled();
+}
+
 void ProfileHelper::ProfileStartup(Profile* profile, bool process_startup) {
   // Initialize Chrome OS preferences like touch pad sensitivity. For the
   // preferences to work in the guest mode, the initialization has to be
@@ -431,4 +461,28 @@
   return user_id + kUserIdHashSuffix;
 }
 
+void ProfileHelper::FlushProfile(Profile* profile) {
+  if (!profile_flusher_)
+    profile_flusher_.reset(new FileFlusher);
+
+  // Files/directories that do not need to be flushed.
+  std::vector<base::FilePath> excludes;
+
+  // Preferences file is handled by ImportantFileWriter.
+  excludes.push_back(base::FilePath(chrome::kPreferencesFilename));
+  // Do not flush cache files.
+  excludes.push_back(base::FilePath(chrome::kCacheDirname));
+  excludes.push_back(base::FilePath(chrome::kMediaCacheDirname));
+  excludes.push_back(base::FilePath(FILE_PATH_LITERAL("GPUCache")));
+  // Do not flush user Downloads.
+  excludes.push_back(
+      DownloadPrefs::FromBrowserContext(profile)->DownloadPath());
+  // Let extension system handle extension files.
+  excludes.push_back(base::FilePath(extensions::kInstallDirectoryName));
+  // Do not flush Drive cache.
+  excludes.push_back(base::FilePath(chromeos::kDriveCacheDirname));
+
+  profile_flusher_->RequestFlush(profile->GetPath(), excludes, base::Closure());
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/profiles/profile_helper.h b/chrome/browser/chromeos/profiles/profile_helper.h
index c0f8d34..20fecf9f 100644
--- a/chrome/browser/chromeos/profiles/profile_helper.h
+++ b/chrome/browser/chromeos/profiles/profile_helper.h
@@ -11,6 +11,7 @@
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/browsing_data/browsing_data_remover.h"
 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h"
@@ -34,6 +35,8 @@
 
 namespace chromeos {
 
+class FileFlusher;
+
 // This helper class is used on Chrome OS to keep track of currently
 // active user profile.
 // Whenever active user is changed (either add another user into session or
@@ -84,12 +87,15 @@
   static bool IsSigninProfile(const Profile* profile);
 
   // Returns true when |profile| corresponds to owner's profile.
-  static bool IsOwnerProfile(Profile* profile);
+  static bool IsOwnerProfile(const Profile* profile);
 
   // Returns true when |profile| corresponds to the primary user profile
   // of the current session.
   static bool IsPrimaryProfile(const Profile* profile);
 
+  // Returns true when |profile| is for an ephemeral user.
+  static bool IsEphemeralUserProfile(const Profile* profile);
+
   // Initialize a bunch of services that are tied to a browser profile.
   // TODO(dzhioev): Investigate whether or not this method is needed.
   void ProfileStartup(Profile* profile, bool process_startup);
@@ -129,6 +135,9 @@
   static std::string GetUserIdHashByUserIdForTesting(
       const std::string& user_id);
 
+  // Flushes all files of |profile|.
+  void FlushProfile(Profile* profile);
+
  private:
   // TODO(nkostylev): Create a test API class that will be the only one allowed
   // to access private test methods.
@@ -206,6 +215,8 @@
   // always be returned by GetUserByProfile().
   static bool always_return_primary_user_for_testing;
 
+  scoped_ptr<FileFlusher> profile_flusher_;
+
   base::WeakPtrFactory<ProfileHelper> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ProfileHelper);
diff --git a/chrome/browser/chromeos/ui/accessibility_cursor_ring_layer.cc b/chrome/browser/chromeos/ui/accessibility_cursor_ring_layer.cc
new file mode 100644
index 0000000..fe841c3
--- /dev/null
+++ b/chrome/browser/chromeos/ui/accessibility_cursor_ring_layer.cc
@@ -0,0 +1,85 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/ui/accessibility_cursor_ring_layer.h"
+
+#include "ash/display/window_tree_host_manager.h"
+#include "ash/shell.h"
+#include "base/bind.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkPath.h"
+#include "ui/aura/window.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/paint_recorder.h"
+#include "ui/gfx/canvas.h"
+
+namespace chromeos {
+
+namespace {
+
+// The number of pixels in the color gradient that fades to transparent.
+const int kGradientWidth = 8;
+
+// The radius of the ring in pixels.
+const int kCursorRingRadius = 24;
+
+// Extra margin to add to the layer in pixels.
+const int kLayerMargin = 8;
+
+}  // namespace
+
+AccessibilityCursorRingLayer::AccessibilityCursorRingLayer(
+    FocusRingLayerDelegate* delegate,
+    int red,
+    int green,
+    int blue)
+    : FocusRingLayer(delegate), red_(red), green_(green), blue_(blue) {}
+
+AccessibilityCursorRingLayer::~AccessibilityCursorRingLayer() {}
+
+void AccessibilityCursorRingLayer::Set(const gfx::Point& location) {
+  location_ = location;
+
+  gfx::Rect bounds = gfx::Rect(location.x(), location.y(), 0, 0);
+  int inset = kGradientWidth + kCursorRingRadius + kLayerMargin;
+  bounds.Inset(-inset, -inset, -inset, -inset);
+
+  gfx::Display display = gfx::Screen::GetScreen()->GetDisplayMatching(bounds);
+  aura::Window* root_window = ash::Shell::GetInstance()
+                                  ->window_tree_host_manager()
+                                  ->GetRootWindowForDisplayId(display.id());
+  CreateOrUpdateLayer(root_window, "AccessibilityCursorRing");
+
+  // Update the layer bounds.
+  layer()->SetBounds(bounds);
+}
+
+void AccessibilityCursorRingLayer::SetOpacity(float opacity) {
+  layer()->SetOpacity(opacity);
+}
+
+void AccessibilityCursorRingLayer::OnPaintLayer(
+    const ui::PaintContext& context) {
+  ui::PaintRecorder recorder(context, layer()->size());
+
+  SkPaint paint;
+  paint.setFlags(SkPaint::kAntiAlias_Flag);
+  paint.setStyle(SkPaint::kStroke_Style);
+  paint.setStrokeWidth(2);
+
+  gfx::Rect r = layer()->bounds();
+  r.Offset(-r.OffsetFromOrigin());
+  r.Inset(kLayerMargin, kLayerMargin, kLayerMargin, kLayerMargin);
+  const int w = kGradientWidth;
+  for (int i = 0; i < w; ++i) {
+    paint.setColor(
+        SkColorSetARGBMacro(255 * (i) * (i) / (w * w), red_, green_, blue_));
+    SkPath path;
+    path.addOval(SkRect::MakeXYWH(r.x(), r.y(), r.width(), r.height()));
+    r.Inset(1, 1, 1, 1);
+    recorder.canvas()->DrawPath(path, paint);
+  }
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/ui/accessibility_cursor_ring_layer.h b/chrome/browser/chromeos/ui/accessibility_cursor_ring_layer.h
new file mode 100644
index 0000000..4990360
--- /dev/null
+++ b/chrome/browser/chromeos/ui/accessibility_cursor_ring_layer.h
@@ -0,0 +1,45 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_UI_ACCESSIBILITY_CURSOR_RING_LAYER_H_
+#define CHROME_BROWSER_CHROMEOS_UI_ACCESSIBILITY_CURSOR_RING_LAYER_H_
+
+#include "chrome/browser/chromeos/ui/accessibility_focus_ring.h"
+#include "chrome/browser/chromeos/ui/focus_ring_layer.h"
+
+namespace chromeos {
+
+// A subclass of FocusRingLayer that highlights the mouse cursor while it's
+// moving, to make it easier to find visually.
+class AccessibilityCursorRingLayer : public FocusRingLayer {
+ public:
+  AccessibilityCursorRingLayer(FocusRingLayerDelegate* delegate,
+                               int red,
+                               int green,
+                               int blue);
+  ~AccessibilityCursorRingLayer() override;
+
+  // Create the layer and update its bounds and position in the hierarchy.
+  void Set(const gfx::Point& location);
+
+  // Set the layer's opacity.
+  void SetOpacity(float opacity);
+
+ private:
+  // ui::LayerDelegate overrides:
+  void OnPaintLayer(const ui::PaintContext& context) override;
+
+  // The current location.
+  gfx::Point location_;
+
+  int red_;
+  int green_;
+  int blue_;
+
+  DISALLOW_COPY_AND_ASSIGN(AccessibilityCursorRingLayer);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_UI_ACCESSIBILITY_CURSOR_RING_LAYER_H_
diff --git a/chrome/browser/chromeos/ui/accessibility_focus_ring_controller.cc b/chrome/browser/chromeos/ui/accessibility_focus_ring_controller.cc
index c34aa443..6cbad6e4 100644
--- a/chrome/browser/chromeos/ui/accessibility_focus_ring_controller.cc
+++ b/chrome/browser/chromeos/ui/accessibility_focus_ring_controller.cc
@@ -6,6 +6,8 @@
 
 #include <stddef.h>
 
+#include <algorithm>
+
 #include "ash/display/window_tree_host_manager.h"
 #include "ash/shell.h"
 #include "base/logging.h"
@@ -24,6 +26,19 @@
 // Time to transition between one location and the next.
 const int kTransitionTimeMilliseconds = 300;
 
+const int kCursorFadeInTimeMilliseconds = 400;
+const int kCursorFadeOutTimeMilliseconds = 1200;
+
+// The color of the cursor ring.
+const int kCursorRingColorRed = 255;
+const int kCursorRingColorGreen = 51;
+const int kCursorRingColorBlue = 51;
+
+// The color of the caret ring.
+const int kCaretRingColorRed = 51;
+const int kCaretRingColorGreen = 51;
+const int kCaretRingColorBlue = 255;
+
 // A Region is an unordered collection of Rects that maintains its
 // bounding box. Used in the middle of an algorithm that groups
 // adjacent and overlapping rects.
@@ -45,8 +60,7 @@
 }
 
 AccessibilityFocusRingController::AccessibilityFocusRingController()
-    : compositor_(nullptr) {
-}
+    : compositor_(nullptr), cursor_opacity_(0), cursor_compositor_(nullptr) {}
 
 AccessibilityFocusRingController::~AccessibilityFocusRingController() {
 }
@@ -62,6 +76,9 @@
   rings_.clear();
   RectsToRings(rects_, &rings_);
   layers_.resize(rings_.size());
+  if (rings_.empty())
+    return;
+
   for (size_t i = 0; i < rings_.size(); ++i) {
     if (!layers_[i])
       layers_[i] = new AccessibilityFocusRingLayer(this);
@@ -69,30 +86,80 @@
     if (i > 0) {
       // Focus rings other than the first one don't animate.
       layers_[i]->Set(rings_[i]);
-      continue;
-    }
-
-    gfx::Rect bounds = rings_[0].GetBounds();
-    gfx::Display display = gfx::Screen::GetScreen()->GetDisplayMatching(bounds);
-    aura::Window* root_window = ash::Shell::GetInstance()
-                                    ->window_tree_host_manager()
-                                    ->GetRootWindowForDisplayId(display.id());
-    ui::Compositor* compositor = root_window->layer()->GetCompositor();
-    if (!compositor || root_window != layers_[0]->root_window()) {
-      layers_[0]->Set(rings_[0]);
-      if (compositor_ && compositor_->HasAnimationObserver(this)) {
-        compositor_->RemoveAnimationObserver(this);
-        compositor_ = nullptr;
-      }
-      continue;
-    }
-
-    focus_change_time_ = base::TimeTicks::Now();
-    if (!compositor->HasAnimationObserver(this)) {
-      compositor_ = compositor;
-      compositor_->AddAnimationObserver(this);
     }
   }
+
+  ui::Compositor* compositor = CompositorForBounds(rings_[0].GetBounds());
+  if (compositor != compositor_) {
+    RemoveAnimationObservers();
+    compositor_ = compositor;
+    AddAnimationObservers();
+  }
+
+  if (compositor_ && compositor_->HasAnimationObserver(this)) {
+    focus_change_time_ = base::TimeTicks::Now();
+  } else {
+    // If we can't animate, set the location of the first ring.
+    layers_[0]->Set(rings_[0]);
+  }
+}
+
+ui::Compositor* AccessibilityFocusRingController::CompositorForBounds(
+    const gfx::Rect& bounds) {
+  gfx::Display display = gfx::Screen::GetScreen()->GetDisplayMatching(bounds);
+  aura::Window* root_window = ash::Shell::GetInstance()
+                                  ->window_tree_host_manager()
+                                  ->GetRootWindowForDisplayId(display.id());
+  return root_window->layer()->GetCompositor();
+}
+
+void AccessibilityFocusRingController::RemoveAnimationObservers() {
+  if (compositor_ && compositor_->HasAnimationObserver(this))
+    compositor_->RemoveAnimationObserver(this);
+  if (cursor_compositor_ && cursor_compositor_->HasAnimationObserver(this))
+    cursor_compositor_->RemoveAnimationObserver(this);
+}
+
+void AccessibilityFocusRingController::AddAnimationObservers() {
+  if (compositor_ && !compositor_->HasAnimationObserver(this))
+    compositor_->AddAnimationObserver(this);
+  if (cursor_compositor_ && !cursor_compositor_->HasAnimationObserver(this))
+    cursor_compositor_->AddAnimationObserver(this);
+}
+
+void AccessibilityFocusRingController::SetCursorRing(
+    const gfx::Point& location) {
+  cursor_location_ = location;
+  cursor_change_time_ = base::TimeTicks::Now();
+  if (cursor_opacity_ == 0)
+    cursor_start_time_ = cursor_change_time_;
+
+  if (!cursor_layer_) {
+    cursor_layer_.reset(new AccessibilityCursorRingLayer(
+        this, kCursorRingColorRed, kCursorRingColorGreen,
+        kCursorRingColorBlue));
+  }
+  cursor_layer_->Set(location);
+
+  ui::Compositor* compositor =
+      CompositorForBounds(gfx::Rect(location.x(), location.y(), 0, 0));
+  if (compositor != cursor_compositor_) {
+    RemoveAnimationObservers();
+    cursor_compositor_ = compositor;
+    AddAnimationObservers();
+  }
+}
+
+void AccessibilityFocusRingController::SetCaretRing(
+    const gfx::Point& location) {
+  caret_location_ = location;
+
+  if (!caret_layer_) {
+    caret_layer_.reset(new AccessibilityCursorRingLayer(
+        this, kCaretRingColorRed, kCaretRingColorGreen, kCaretRingColorBlue));
+  }
+
+  caret_layer_->Set(location);
 }
 
 void AccessibilityFocusRingController::RectsToRings(
@@ -291,10 +358,15 @@
 
 void AccessibilityFocusRingController::OnAnimationStep(
     base::TimeTicks timestamp) {
-  if (rings_.empty())
-    return;
+  if (!rings_.empty() && compositor_)
+    AnimateFocusRings(timestamp);
 
-  CHECK(compositor_);
+  if (cursor_layer_ && cursor_compositor_)
+    AnimateCursorRing(timestamp);
+}
+
+void AccessibilityFocusRingController::AnimateFocusRings(
+    base::TimeTicks timestamp) {
   CHECK(!rings_.empty());
   CHECK(!layers_.empty());
   CHECK(layers_[0]);
@@ -310,8 +382,10 @@
       base::TimeDelta::FromMilliseconds(kTransitionTimeMilliseconds);
   if (delta >= transition_time) {
     layers_[0]->Set(rings_[0]);
-    compositor_->RemoveAnimationObserver(this);
+
+    RemoveAnimationObservers();
     compositor_ = nullptr;
+    AddAnimationObservers();
     return;
   }
 
@@ -320,15 +394,60 @@
   // Ease-in effect.
   fraction = pow(fraction, 0.3);
 
+  // Handle corner case where we're animating but we don't have previous
+  // rings.
+  if (previous_rings_.empty())
+    previous_rings_ = rings_;
+
   layers_[0]->Set(AccessibilityFocusRing::Interpolate(
       previous_rings_[0], rings_[0], fraction));
 }
 
+void AccessibilityFocusRingController::AnimateCursorRing(
+    base::TimeTicks timestamp) {
+  CHECK(cursor_layer_);
+
+  // It's quite possible for the first 1 or 2 animation frames to be
+  // for a timestamp that's earlier than the time we received the
+  // mouse movement, so we just treat those as a delta of zero.
+  if (timestamp < cursor_start_time_)
+    timestamp = cursor_start_time_;
+
+  base::TimeDelta start_delta = timestamp - cursor_start_time_;
+  base::TimeDelta change_delta = timestamp - cursor_change_time_;
+  base::TimeDelta fade_in_time =
+      base::TimeDelta::FromMilliseconds(kCursorFadeInTimeMilliseconds);
+  base::TimeDelta fade_out_time =
+      base::TimeDelta::FromMilliseconds(kCursorFadeOutTimeMilliseconds);
+
+  if (change_delta > fade_in_time + fade_out_time) {
+    cursor_opacity_ = 0.0;
+    cursor_layer_.reset();
+    return;
+  }
+
+  if (start_delta < fade_in_time) {
+    cursor_opacity_ = start_delta.InSecondsF() / fade_in_time.InSecondsF();
+    if (cursor_opacity_ > 1.0)
+      cursor_opacity_ = 1.0;
+  } else {
+    cursor_opacity_ = 1.0 - (change_delta.InSecondsF() /
+                             (fade_in_time + fade_out_time).InSecondsF());
+    if (cursor_opacity_ < 0.0)
+      cursor_opacity_ = 0.0;
+  }
+  cursor_layer_->SetOpacity(cursor_opacity_);
+}
+
 void AccessibilityFocusRingController::OnCompositingShuttingDown(
     ui::Compositor* compositor) {
-  DCHECK_EQ(compositor_, compositor);
-  compositor_->RemoveAnimationObserver(this);
-  compositor_ = nullptr;
+  if (compositor == compositor_ || compositor == cursor_compositor_)
+    compositor->RemoveAnimationObserver(this);
+
+  if (compositor == compositor_)
+    compositor_ = nullptr;
+  if (compositor == cursor_compositor_)
+    cursor_compositor_ = nullptr;
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/ui/accessibility_focus_ring_controller.h b/chrome/browser/chromeos/ui/accessibility_focus_ring_controller.h
index c5f4a0f..09024b0 100644
--- a/chrome/browser/chromeos/ui/accessibility_focus_ring_controller.h
+++ b/chrome/browser/chromeos/ui/accessibility_focus_ring_controller.h
@@ -11,6 +11,7 @@
 #include "base/memory/scoped_vector.h"
 #include "base/memory/singleton.h"
 #include "base/time/time.h"
+#include "chrome/browser/chromeos/ui/accessibility_cursor_ring_layer.h"
 #include "chrome/browser/chromeos/ui/accessibility_focus_ring_layer.h"
 #include "ui/compositor/compositor_animation_observer.h"
 #include "ui/gfx/geometry/rect.h"
@@ -21,8 +22,8 @@
 
 namespace chromeos {
 
-// AccessibilityFocusRingController manages a custom focus ring (or multiple
-// rings) for accessibility.
+// AccessibilityFocusRingController handles drawing custom rings around
+// the focused object, cursor, and/or caret for accessibility.
 class AccessibilityFocusRingController
     : public FocusRingLayerDelegate,
       public ui::CompositorAnimationObserver {
@@ -34,6 +35,12 @@
   // coordinates.
   void SetFocusRing(const std::vector<gfx::Rect>& rects);
 
+  // Draw a ring around the mouse cursor.
+  void SetCursorRing(const gfx::Point& location);
+
+  // Draw a ring around the text caret.
+  void SetCaretRing(const gfx::Point& location);
+
  protected:
   AccessibilityFocusRingController();
   ~AccessibilityFocusRingController() override;
@@ -58,6 +65,9 @@
 
   void Update();
 
+  void AnimateFocusRings(base::TimeTicks timestamp);
+  void AnimateCursorRing(base::TimeTicks timestamp);
+
   AccessibilityFocusRing RingFromSortedRects(
       const std::vector<gfx::Rect>& rects) const;
   void SplitIntoParagraphShape(
@@ -66,6 +76,9 @@
       gfx::Rect* middle,
       gfx::Rect* bottom) const;
   bool Intersects(const gfx::Rect& r1, const gfx::Rect& r2) const;
+  ui::Compositor* CompositorForBounds(const gfx::Rect& bounds);
+  void RemoveAnimationObservers();
+  void AddAnimationObservers();
 
   std::vector<gfx::Rect> rects_;
   std::vector<AccessibilityFocusRing> previous_rings_;
@@ -74,6 +87,16 @@
   base::TimeTicks focus_change_time_;
   ui::Compositor* compositor_;
 
+  base::TimeTicks cursor_start_time_;
+  base::TimeTicks cursor_change_time_;
+  gfx::Point cursor_location_;
+  float cursor_opacity_;
+  scoped_ptr<AccessibilityCursorRingLayer> cursor_layer_;
+  ui::Compositor* cursor_compositor_;
+
+  gfx::Point caret_location_;
+  scoped_ptr<AccessibilityCursorRingLayer> caret_layer_;
+
   friend struct base::DefaultSingletonTraits<AccessibilityFocusRingController>;
 
   DISALLOW_COPY_AND_ASSIGN(AccessibilityFocusRingController);
diff --git a/chrome/browser/content_settings/content_settings_browsertest.cc b/chrome/browser/content_settings/content_settings_browsertest.cc
index 65ecc14..7af3c5d 100644
--- a/chrome/browser/content_settings/content_settings_browsertest.cc
+++ b/chrome/browser/content_settings/content_settings_browsertest.cc
@@ -166,9 +166,7 @@
   ui_test_utils::NavigateToURL(browser(), url);
   ASSERT_TRUE(GetCookies(browser()->profile(), url).empty());
 
-  settings->SetCookieSetting(
-      ContentSettingsPattern::FromURL(url),
-      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_ALLOW);
+  settings->SetCookieSetting(url, CONTENT_SETTING_ALLOW);
 
   ui_test_utils::NavigateToURL(browser(), url);
   ASSERT_FALSE(GetCookies(browser()->profile(), url).empty());
@@ -180,9 +178,7 @@
   GURL url = embedded_test_server()->GetURL("/setcookie.html");
   content_settings::CookieSettings* settings =
       CookieSettingsFactory::GetForProfile(browser()->profile()).get();
-  settings->SetCookieSetting(ContentSettingsPattern::FromURL(url),
-                             ContentSettingsPattern::Wildcard(),
-                             CONTENT_SETTING_BLOCK);
+  settings->SetCookieSetting(url, CONTENT_SETTING_BLOCK);
 
   ui_test_utils::NavigateToURL(browser(), url);
   ASSERT_TRUE(GetCookies(browser()->profile(), url).empty());
@@ -212,9 +208,7 @@
   ui_test_utils::NavigateToURL(browser(), url);
   ASSERT_TRUE(GetCookies(browser()->profile(), url).empty());
 
-  settings->SetCookieSetting(
-      ContentSettingsPattern::FromURL(url),
-      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_SESSION_ONLY);
+  settings->SetCookieSetting(url, CONTENT_SETTING_SESSION_ONLY);
   ui_test_utils::NavigateToURL(browser(), url);
   ASSERT_FALSE(GetCookies(browser()->profile(), url).empty());
 }
diff --git a/chrome/browser/content_settings/cookie_settings_factory_unittest.cc b/chrome/browser/content_settings/cookie_settings_factory_unittest.cc
index beed137..a9cbafa 100644
--- a/chrome/browser/content_settings/cookie_settings_factory_unittest.cc
+++ b/chrome/browser/content_settings/cookie_settings_factory_unittest.cc
@@ -41,9 +41,7 @@
 
   // Modify the regular cookie settings after the incognito cookie settings have
   // been instantiated.
-  cookie_settings_->SetCookieSetting(
-      ContentSettingsPattern::FromURL(kBlockedSite),
-      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_BLOCK);
+  cookie_settings_->SetCookieSetting(kBlockedSite, CONTENT_SETTING_BLOCK);
 
   // The modification should apply to the regular profile and incognito profile.
   EXPECT_FALSE(
@@ -53,9 +51,7 @@
 
   // Modify an incognito cookie setting and check that this does not propagate
   // into regular mode.
-  incognito_settings->SetCookieSetting(
-      ContentSettingsPattern::FromURL(kHttpsSite),
-      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_BLOCK);
+  incognito_settings->SetCookieSetting(kHttpsSite, CONTENT_SETTING_BLOCK);
   EXPECT_TRUE(cookie_settings_->IsReadingCookieAllowed(kHttpsSite, kHttpsSite));
   EXPECT_FALSE(
       incognito_settings->IsReadingCookieAllowed(kHttpsSite, kHttpsSite));
@@ -76,9 +72,7 @@
 
   // A whitelisted item set in incognito mode should only apply to incognito
   // mode.
-  incognito_settings->SetCookieSetting(
-      ContentSettingsPattern::FromURL(kAllowedSite),
-      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_ALLOW);
+  incognito_settings->SetCookieSetting(kAllowedSite, CONTENT_SETTING_ALLOW);
   EXPECT_TRUE(
       incognito_settings->IsReadingCookieAllowed(kAllowedSite, kAllowedSite));
   EXPECT_FALSE(
@@ -86,9 +80,7 @@
 
   // A whitelisted item set in regular mode should apply to regular and
   // incognito mode.
-  cookie_settings_->SetCookieSetting(
-      ContentSettingsPattern::FromURL(kHttpsSite),
-      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_ALLOW);
+  cookie_settings_->SetCookieSetting(kHttpsSite, CONTENT_SETTING_ALLOW);
   EXPECT_TRUE(
       incognito_settings->IsReadingCookieAllowed(kHttpsSite, kHttpsSite));
   EXPECT_TRUE(cookie_settings_->IsReadingCookieAllowed(kHttpsSite, kHttpsSite));
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
index ea3def5..d03deec 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
+++ b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
@@ -154,7 +154,7 @@
                           : shell_integration::IS_DEFAULT;
   }
 
-  AttemptResult SetAsDefaultImpl() override { return AttemptResult::SUCCESS; }
+  void SetAsDefaultImpl() override {}
 
  private:
   bool force_failure_;
diff --git a/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc b/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc
index 68c26a77..0bd96db 100644
--- a/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc
+++ b/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc
@@ -210,5 +210,7 @@
                      &Delegate::RemovePreference, delegate);
   d->RegisterHandler("clearPreferences",
                      &Delegate::ClearPreferences, delegate);
+  d->RegisterHandler("readyForTest",
+                     &Delegate::ReadyForTest, delegate);
   return d;
 }
diff --git a/chrome/browser/devtools/devtools_embedder_message_dispatcher.h b/chrome/browser/devtools/devtools_embedder_message_dispatcher.h
index cddc540..9c938ab 100644
--- a/chrome/browser/devtools/devtools_embedder_message_dispatcher.h
+++ b/chrome/browser/devtools/devtools_embedder_message_dispatcher.h
@@ -88,6 +88,7 @@
                                  const std::string& browser_id,
                                  const std::string& url) = 0;
     virtual void SendFrontendAPINotification(const std::string& message) = 0;
+    virtual void ReadyForTest() = 0;
   };
 
   using DispatchCallback = Delegate::DispatchCallback;
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc
index d6451bd2..01c4109 100644
--- a/chrome/browser/devtools/devtools_ui_bindings.cc
+++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -199,6 +199,7 @@
 
   void InspectedContentsClosing() override;
   void OnLoadCompleted() override {}
+  void ReadyForTest() override {}
   InfoBarService* GetInfoBarService() override;
   void RenderProcessGone(bool crashed) override {}
 
@@ -911,6 +912,10 @@
   update.Get()->Clear();
 }
 
+void DevToolsUIBindings::ReadyForTest() {
+  delegate_->ReadyForTest();
+}
+
 void DevToolsUIBindings::DispatchProtocolMessageFromDevToolsFrontend(
     const std::string& message) {
   if (agent_host_.get())
diff --git a/chrome/browser/devtools/devtools_ui_bindings.h b/chrome/browser/devtools/devtools_ui_bindings.h
index 8b1b6d9..8703bc9 100644
--- a/chrome/browser/devtools/devtools_ui_bindings.h
+++ b/chrome/browser/devtools/devtools_ui_bindings.h
@@ -58,6 +58,7 @@
 
     virtual void InspectedContentsClosing() = 0;
     virtual void OnLoadCompleted() = 0;
+    virtual void ReadyForTest() = 0;
     virtual InfoBarService* GetInfoBarService() = 0;
     virtual void RenderProcessGone(bool crashed) = 0;
   };
@@ -147,6 +148,7 @@
                      const std::string& value) override;
   void RemovePreference(const std::string& name) override;
   void ClearPreferences() override;
+  void ReadyForTest() override;
 
   // net::URLFetcherDelegate overrides.
   void OnURLFetchComplete(const net::URLFetcher* source) override;
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc
index 51c2069e..956b799a 100644
--- a/chrome/browser/devtools/devtools_window.cc
+++ b/chrome/browser/devtools/devtools_window.cc
@@ -1183,6 +1183,13 @@
     LoadCompleted();
 }
 
+void DevToolsWindow::ReadyForTest() {
+  if (!ready_for_test_callback_.is_null()) {
+    ready_for_test_callback_.Run();
+    ready_for_test_callback_ = base::Closure();
+  }
+}
+
 void DevToolsWindow::CreateDevToolsBrowser() {
   PrefService* prefs = profile_->GetPrefs();
   if (!prefs->GetDictionary(prefs::kAppWindowPlacement)->HasKey(kDevToolsApp)) {
diff --git a/chrome/browser/devtools/devtools_window.h b/chrome/browser/devtools/devtools_window.h
index fc17c12..b248aa89 100644
--- a/chrome/browser/devtools/devtools_window.h
+++ b/chrome/browser/devtools/devtools_window.h
@@ -312,6 +312,7 @@
   void SetWhitelistedShortcuts(const std::string& message) override;
   void InspectedContentsClosing() override;
   void OnLoadCompleted() override;
+  void ReadyForTest() override;
   InfoBarService* GetInfoBarService() override;
   void RenderProcessGone(bool crashed) override;
 
@@ -342,6 +343,7 @@
   bool intercepted_page_beforeunload_;
   base::Closure load_completed_callback_;
   base::Closure close_callback_;
+  base::Closure ready_for_test_callback_;
 
   base::TimeTicks inspect_element_start_time_;
   scoped_ptr<DevToolsEventForwarder> event_forwarder_;
diff --git a/chrome/browser/devtools/devtools_window_testing.cc b/chrome/browser/devtools/devtools_window_testing.cc
index 0f27344..f87939d3 100644
--- a/chrome/browser/devtools/devtools_window_testing.cc
+++ b/chrome/browser/devtools/devtools_window_testing.cc
@@ -5,17 +5,20 @@
 #include "chrome/browser/devtools/devtools_window_testing.h"
 
 #include "base/lazy_instance.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "content/public/browser/devtools_agent_host.h"
-#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/test_utils.h"
 
 namespace {
 
+const char kHarnessScript[] = "Tests.js";
+
 typedef std::vector<DevToolsWindowTesting*> DevToolsWindowTestings;
 base::LazyInstance<DevToolsWindowTestings>::Leaky g_instances =
     LAZY_INSTANCE_INITIALIZER;
@@ -95,8 +98,11 @@
 void DevToolsWindowTesting::WaitForDevToolsWindowLoad(DevToolsWindow* window) {
   scoped_refptr<content::MessageLoopRunner> runner =
       new content::MessageLoopRunner;
-  window->SetLoadCompletedCallback(runner->QuitClosure());
+  window->ready_for_test_callback_ = runner->QuitClosure();
   runner->Run();
+  base::string16 harness = base::UTF8ToUTF16(
+      content::DevToolsFrontendHost::GetFrontendResource(kHarnessScript));
+  window->main_web_contents_->GetMainFrame()->ExecuteJavaScript(harness);
 }
 
 // static
diff --git a/chrome/browser/download/save_page_browsertest.cc b/chrome/browser/download/save_page_browsertest.cc
index d5d11de..daa8e12 100644
--- a/chrome/browser/download/save_page_browsertest.cc
+++ b/chrome/browser/download/save_page_browsertest.cc
@@ -1220,8 +1220,14 @@
   TestOriginalVsSavedPage(save_page_type, url, 6, expected_substrings);
 }
 
-// Test for saving a page with a broken image (see also crbug.com/586680).
+// Test for saving a page with broken subresources:
+// - Broken, undecodable image (see also https://crbug.com/586680)
+// - Broken link, to unresolvable host (see also https://crbug.com/594219)
 IN_PROC_BROWSER_TEST_P(SavePageOriginalVsSavedComparisonTest, BrokenImage) {
+  // Clear resolver rules to make sure that *.no.such.host used in the test html
+  // doesn't resolve to 127.0.0.1
+  host_resolver()->ClearRules();
+
   content::SavePageType save_page_type = GetParam();
 
   std::string arr[] = {
@@ -1229,8 +1235,8 @@
   };
   std::vector<std::string> expected_substrings(std::begin(arr), std::end(arr));
 
-  GURL url(
-      embedded_test_server()->GetURL("a.com", "/save_page/broken-image.htm"));
+  GURL url(embedded_test_server()->GetURL("127.0.0.1",
+                                          "/save_page/broken-image.htm"));
 
   TestOriginalVsSavedPage(save_page_type, url, 1, expected_substrings);
 }
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index 2604a1ac..52b4ff9 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -388,25 +388,19 @@
     developer::EventType event_type,
     const std::string& extension_id,
     scoped_ptr<ExtensionInfoGenerator> info_generator,
-    const ExtensionInfoGenerator::ExtensionInfoList& infos) {
+    ExtensionInfoGenerator::ExtensionInfoList infos) {
   DCHECK_LE(infos.size(), 1u);
 
   developer::EventData event_data;
   event_data.event_type = event_type;
   event_data.item_id = extension_id;
-  scoped_ptr<base::DictionaryValue> dict = event_data.ToValue();
-
   if (!infos.empty()) {
-    // Hack: Ideally, we would use event_data.extension_info to set the
-    // extension info, but since it's an optional field, it's implemented as a
-    // scoped ptr, and so ownership between that and the vector of linked ptrs
-    // here is, well, messy. Easier to just set it like this.
-    dict->SetWithoutPathExpansion("extensionInfo",
-                                  infos[0]->ToValue().release());
+    event_data.extension_info.reset(
+        new developer::ExtensionInfo(std::move(infos[0])));
   }
 
   scoped_ptr<base::ListValue> args(new base::ListValue());
-  args->Append(dict.release());
+  args->Append(event_data.ToValue());
   scoped_ptr<Event> event(
       new Event(events::DEVELOPER_PRIVATE_ON_ITEM_STATE_CHANGED,
                 developer::OnItemStateChanged::kEventName, std::move(args)));
@@ -510,7 +504,7 @@
 }
 
 void DeveloperPrivateGetExtensionsInfoFunction::OnInfosGenerated(
-    const ExtensionInfoGenerator::ExtensionInfoList& list) {
+    ExtensionInfoGenerator::ExtensionInfoList list) {
   Respond(ArgumentList(developer::GetExtensionsInfo::Results::Create(list)));
 }
 
@@ -538,11 +532,10 @@
 }
 
 void DeveloperPrivateGetExtensionInfoFunction::OnInfosGenerated(
-    const ExtensionInfoGenerator::ExtensionInfoList& list) {
-  DCHECK_EQ(1u, list.size());
-  const linked_ptr<developer::ExtensionInfo>& info = list[0];
-  Respond(info.get() ? OneArgument(info->ToValue()) :
-      Error(kNoSuchExtensionError));
+    ExtensionInfoGenerator::ExtensionInfoList list) {
+  DCHECK_LE(1u, list.size());
+  Respond(list.empty() ? Error(kNoSuchExtensionError)
+                       : OneArgument(list[0].ToValue()));
 }
 
 DeveloperPrivateGetItemsInfoFunction::DeveloperPrivateGetItemsInfoFunction() {}
@@ -564,10 +557,10 @@
 }
 
 void DeveloperPrivateGetItemsInfoFunction::OnInfosGenerated(
-    const ExtensionInfoGenerator::ExtensionInfoList& list) {
-  std::vector<linked_ptr<developer::ItemInfo>> item_list;
-  for (const linked_ptr<developer::ExtensionInfo>& info : list)
-    item_list.push_back(developer_private_mangle::MangleExtensionInfo(*info));
+    ExtensionInfoGenerator::ExtensionInfoList list) {
+  std::vector<developer::ItemInfo> item_list;
+  for (const developer::ExtensionInfo& info : list)
+    item_list.push_back(developer_private_mangle::MangleExtensionInfo(info));
 
   Respond(ArgumentList(developer::GetItemsInfo::Results::Create(item_list)));
 }
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.h b/chrome/browser/extensions/api/developer_private/developer_private_api.h
index 94fc694..ffbf718 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.h
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.h
@@ -132,8 +132,7 @@
       api::developer_private::EventType event_type,
       const std::string& extension_id,
       scoped_ptr<ExtensionInfoGenerator> info_generator,
-      const std::vector<linked_ptr<api::developer_private::ExtensionInfo>>&
-          infos);
+      std::vector<api::developer_private::ExtensionInfo> infos);
 
   ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
       extension_registry_observer_;
@@ -261,8 +260,7 @@
   ResponseAction Run() override;
 
   void OnInfosGenerated(
-      const std::vector<linked_ptr<api::developer_private::ExtensionInfo>>&
-          infos);
+      std::vector<api::developer_private::ExtensionInfo> infos);
 
   scoped_ptr<ExtensionInfoGenerator> info_generator_;
 
@@ -281,8 +279,7 @@
   ResponseAction Run() override;
 
   void OnInfosGenerated(
-      const std::vector<linked_ptr<api::developer_private::ExtensionInfo>>&
-          infos);
+      std::vector<api::developer_private::ExtensionInfo> infos);
 
   scoped_ptr<ExtensionInfoGenerator> info_generator_;
 
@@ -301,8 +298,7 @@
   ResponseAction Run() override;
 
   void OnInfosGenerated(
-      const std::vector<linked_ptr<api::developer_private::ExtensionInfo>>&
-          infos);
+      std::vector<api::developer_private::ExtensionInfo> infos);
 
   scoped_ptr<ExtensionInfoGenerator> info_generator_;
 
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc b/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc
index ec28633..40bb0eba 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc
@@ -57,10 +57,10 @@
   // There should be two inspectable views - the background page and the app
   // window.  Find the app window.
   ASSERT_EQ(2u, info->views.size());
-  api::developer_private::ExtensionView* window_view = nullptr;
+  const api::developer_private::ExtensionView* window_view = nullptr;
   for (const auto& view : info->views) {
-    if (view->type == api::developer_private::VIEW_TYPE_APP_WINDOW) {
-      window_view = view.get();
+    if (view.type == api::developer_private::VIEW_TYPE_APP_WINDOW) {
+      window_view = &view;
       break;
     }
   }
@@ -110,21 +110,20 @@
 
   // The embedded options page should show up.
   ASSERT_EQ(1u, info->views.size());
-  api::developer_private::ExtensionView* view = info->views[0].get();
-  ASSERT_TRUE(view);
-  ASSERT_EQ(api::developer_private::VIEW_TYPE_EXTENSION_GUEST, view->type);
+  const api::developer_private::ExtensionView& view = info->views[0];
+  ASSERT_EQ(api::developer_private::VIEW_TYPE_EXTENSION_GUEST, view.type);
 
   // Inspect the embedded options page.
   function = new api::DeveloperPrivateOpenDevToolsFunction();
   extension_function_test_utils::RunFunction(
       function.get(),
       base::StringPrintf("[{\"renderViewId\": %d, \"renderProcessId\": %d}]",
-                         view->render_view_id, view->render_process_id),
+                         view.render_view_id, view.render_process_id),
       browser(), extension_function_test_utils::NONE);
 
   // Verify that dev tools opened.
   content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
-      view->render_process_id, view->render_view_id);
+      view.render_process_id, view.render_view_id);
   ASSERT_TRUE(rfh);
   content::WebContents* wc = content::WebContents::FromRenderFrameHost(rfh);
   ASSERT_TRUE(wc);
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_mangle.cc b/chrome/browser/extensions/api/developer_private/developer_private_mangle.cc
index 073df5b..7f43b82 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_mangle.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_mangle.cc
@@ -13,37 +13,36 @@
 namespace extensions {
 namespace developer_private_mangle {
 
-linked_ptr<api::developer_private::ItemInfo> MangleExtensionInfo(
+api::developer_private::ItemInfo MangleExtensionInfo(
     const api::developer_private::ExtensionInfo& info) {
-  linked_ptr<api::developer_private::ItemInfo> result(
-      new api::developer_private::ItemInfo());
-  result->id = info.id;
-  result->name = info.name;
-  result->version = info.version;
-  result->description = info.description;
-  result->may_disable = info.user_may_modify;
-  result->enabled =
+  api::developer_private::ItemInfo result;
+  result.id = info.id;
+  result.name = info.name;
+  result.version = info.version;
+  result.description = info.description;
+  result.may_disable = info.user_may_modify;
+  result.enabled =
       info.state == api::developer_private::EXTENSION_STATE_ENABLED;
   switch (info.type) {
     case api::developer_private::EXTENSION_TYPE_HOSTED_APP:
-      result->type = api::developer_private::ITEM_TYPE_HOSTED_APP;
-      result->is_app = true;
+      result.type = api::developer_private::ITEM_TYPE_HOSTED_APP;
+      result.is_app = true;
       break;
     case api::developer_private::EXTENSION_TYPE_PLATFORM_APP:
-      result->type = api::developer_private::ITEM_TYPE_PACKAGED_APP;
-      result->is_app = true;
+      result.type = api::developer_private::ITEM_TYPE_PACKAGED_APP;
+      result.is_app = true;
       break;
     case api::developer_private::EXTENSION_TYPE_LEGACY_PACKAGED_APP:
-      result->type = api::developer_private::ITEM_TYPE_LEGACY_PACKAGED_APP;
-      result->is_app = true;
+      result.type = api::developer_private::ITEM_TYPE_LEGACY_PACKAGED_APP;
+      result.is_app = true;
       break;
     case api::developer_private::EXTENSION_TYPE_EXTENSION:
-      result->type = api::developer_private::ITEM_TYPE_EXTENSION;
-      result->is_app = false;
+      result.type = api::developer_private::ITEM_TYPE_EXTENSION;
+      result.is_app = false;
       break;
     case api::developer_private::EXTENSION_TYPE_THEME:
-      result->type = api::developer_private::ITEM_TYPE_THEME;
-      result->is_app = false;
+      result.type = api::developer_private::ITEM_TYPE_THEME;
+      result.is_app = false;
       break;
     case api::developer_private::EXTENSION_TYPE_SHARED_MODULE:
       // Old api doesn't account for this.
@@ -51,75 +50,70 @@
     default:
       NOTREACHED();
   }
-  result->allow_file_access = info.file_access.is_active;
-  result->wants_file_access = info.file_access.is_enabled;
+  result.allow_file_access = info.file_access.is_active;
+  result.wants_file_access = info.file_access.is_enabled;
 
-  result->icon_url = info.icon_url;
+  result.icon_url = info.icon_url;
 
-  result->incognito_enabled = info.incognito_access.is_active;
-  result->allow_incognito = info.incognito_access.is_enabled;
+  result.incognito_enabled = info.incognito_access.is_active;
+  result.allow_incognito = info.incognito_access.is_enabled;
 
-  result->is_unpacked =
+  result.is_unpacked =
       info.location == api::developer_private::LOCATION_UNPACKED;
-  result->allow_reload = result->is_unpacked;
-  result->terminated =
+  result.allow_reload = result.is_unpacked;
+  result.terminated =
       info.state == api::developer_private::EXTENSION_STATE_TERMINATED;
 
   if (info.path)
-    result->path.reset(new std::string(*info.path));
+    result.path.reset(new std::string(*info.path));
   if (info.options_page)
-    result->options_url.reset(new std::string(info.options_page->url));
+    result.options_url.reset(new std::string(info.options_page->url));
   if (info.launch_url)
-    result->app_launch_url.reset(new std::string(*info.launch_url));
+    result.app_launch_url.reset(new std::string(*info.launch_url));
   if (!info.home_page.url.empty())
-    result->homepage_url.reset(new std::string(info.home_page.url));
-  result->update_url.reset(new std::string(info.update_url));
+    result.homepage_url.reset(new std::string(info.home_page.url));
+  result.update_url.reset(new std::string(info.update_url));
   for (const std::string& str_warning : info.install_warnings) {
-    scoped_ptr<api::developer_private::InstallWarning> warning(
-        new api::developer_private::InstallWarning());
-    warning->message = str_warning;
-    result->install_warnings.push_back(make_linked_ptr(warning.release()));
+    api::developer_private::InstallWarning warning;
+    warning.message = str_warning;
+    result.install_warnings.push_back(std::move(warning));
   }
-  for (const linked_ptr<api::developer_private::ManifestError>& error :
-           info.manifest_errors) {
-    CHECK(error.get());
-    scoped_ptr<base::DictionaryValue> value = error->ToValue();
+  for (const api::developer_private::ManifestError& error :
+       info.manifest_errors) {
+    scoped_ptr<base::DictionaryValue> value = error.ToValue();
     value->SetInteger("type", static_cast<int>(ExtensionError::MANIFEST_ERROR));
     value->SetInteger("level", static_cast<int>(logging::LOG_WARNING));
-    result->manifest_errors.push_back(make_linked_ptr(value.release()));
+    result.manifest_errors.push_back(make_linked_ptr(value.release()));
   }
-  for (const linked_ptr<api::developer_private::RuntimeError>& error :
-           info.runtime_errors) {
-    CHECK(error.get());
-    scoped_ptr<base::DictionaryValue> value = error->ToValue();
+  for (const api::developer_private::RuntimeError& error :
+       info.runtime_errors) {
+    scoped_ptr<base::DictionaryValue> value = error.ToValue();
     value->SetInteger("type", static_cast<int>(ExtensionError::RUNTIME_ERROR));
     logging::LogSeverity severity = logging::LOG_INFO;
-    if (error->severity == api::developer_private::ERROR_LEVEL_WARN)
+    if (error.severity == api::developer_private::ERROR_LEVEL_WARN)
       severity = logging::LOG_WARNING;
-    else if (error->severity == api::developer_private::ERROR_LEVEL_ERROR)
+    else if (error.severity == api::developer_private::ERROR_LEVEL_ERROR)
       severity = logging::LOG_ERROR;
     value->SetInteger("level", static_cast<int>(severity));
-    result->runtime_errors.push_back(make_linked_ptr(value.release()));
+    result.runtime_errors.push_back(make_linked_ptr(value.release()));
   }
-  result->offline_enabled = info.offline_enabled;
-  for (const linked_ptr<api::developer_private::ExtensionView>& view :
-           info.views) {
-    linked_ptr<api::developer_private::ItemInspectView> view_copy(
-        new api::developer_private::ItemInspectView());
-    GURL url(view->url);
+  result.offline_enabled = info.offline_enabled;
+  for (const api::developer_private::ExtensionView& view : info.views) {
+    api::developer_private::ItemInspectView view_copy;
+    GURL url(view.url);
     if (url.scheme() == kExtensionScheme) {
       // No leading slash.
-      view_copy->path = url.path().substr(1);
+      view_copy.path = url.path().substr(1);
     } else {
       // For live pages, use the full URL.
-      view_copy->path = url.spec();
+      view_copy.path = url.spec();
     }
-    view_copy->render_process_id = view->render_process_id;
-    view_copy->render_view_id = view->render_view_id;
-    view_copy->incognito = view->incognito;
-    view_copy->generated_background_page =
-        view_copy->path == kGeneratedBackgroundPageFilename;
-    result->views.push_back(view_copy);
+    view_copy.render_process_id = view.render_process_id;
+    view_copy.render_view_id = view.render_view_id;
+    view_copy.incognito = view.incognito;
+    view_copy.generated_background_page =
+        view_copy.path == kGeneratedBackgroundPageFilename;
+    result.views.push_back(std::move(view_copy));
   }
 
   return result;
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_mangle.h b/chrome/browser/extensions/api/developer_private/developer_private_mangle.h
index 12f38e45..c3d4b5e4 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_mangle.h
+++ b/chrome/browser/extensions/api/developer_private/developer_private_mangle.h
@@ -21,7 +21,7 @@
 // Converts a developer_private::ExtensionInfo into a
 // developer_private::ItemInfo for compatability with deprecated API
 // functions.
-linked_ptr<api::developer_private::ItemInfo> MangleExtensionInfo(
+api::developer_private::ItemInfo MangleExtensionInfo(
     const api::developer_private::ExtensionInfo& info);
 
 }  // namespace developer_private_mangle
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
index 858e9b8..e19393b4 100644
--- a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
+++ b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/base64.h"
+#include "base/callback_helpers.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
@@ -103,13 +104,12 @@
 
 // Given a ManifestError object, converts it into its developer_private
 // counterpart.
-linked_ptr<developer::ManifestError> ConstructManifestError(
-    const ManifestError& error) {
-  linked_ptr<developer::ManifestError> result(new developer::ManifestError());
-  PopulateErrorBase(error, result.get());
-  result->manifest_key = base::UTF16ToUTF8(error.manifest_key());
+developer::ManifestError ConstructManifestError(const ManifestError& error) {
+  developer::ManifestError result;
+  PopulateErrorBase(error, &result);
+  result.manifest_key = base::UTF16ToUTF8(error.manifest_key());
   if (!error.manifest_specific().empty()) {
-    result->manifest_specific.reset(
+    result.manifest_specific.reset(
         new std::string(base::UTF16ToUTF8(error.manifest_specific())));
   }
   return result;
@@ -117,40 +117,39 @@
 
 // Given a RuntimeError object, converts it into its developer_private
 // counterpart.
-linked_ptr<developer::RuntimeError> ConstructRuntimeError(
-    const RuntimeError& error) {
-  linked_ptr<developer::RuntimeError> result(new developer::RuntimeError());
-  PopulateErrorBase(error, result.get());
+developer::RuntimeError ConstructRuntimeError(const RuntimeError& error) {
+  developer::RuntimeError result;
+  PopulateErrorBase(error, &result);
   switch (error.level()) {
     case logging::LOG_VERBOSE:
     case logging::LOG_INFO:
-      result->severity = developer::ERROR_LEVEL_LOG;
+      result.severity = developer::ERROR_LEVEL_LOG;
       break;
     case logging::LOG_WARNING:
-      result->severity = developer::ERROR_LEVEL_WARN;
+      result.severity = developer::ERROR_LEVEL_WARN;
       break;
     case logging::LOG_FATAL:
     case logging::LOG_ERROR:
-      result->severity = developer::ERROR_LEVEL_ERROR;
+      result.severity = developer::ERROR_LEVEL_ERROR;
       break;
     default:
       NOTREACHED();
   }
-  result->occurrences = error.occurrences();
+  result.occurrences = error.occurrences();
   // NOTE(devlin): This is called "render_view_id" in the api for legacy
   // reasons, but it's not a high priority to change.
-  result->render_view_id = error.render_frame_id();
-  result->render_process_id = error.render_process_id();
-  result->can_inspect =
+  result.render_view_id = error.render_frame_id();
+  result.render_process_id = error.render_process_id();
+  result.can_inspect =
       content::RenderFrameHost::FromID(error.render_process_id(),
                                        error.render_frame_id()) != nullptr;
   for (const StackFrame& f : error.stack_trace()) {
-    linked_ptr<developer::StackFrame> frame(new developer::StackFrame());
-    frame->line_number = f.line_number;
-    frame->column_number = f.column_number;
-    frame->url = base::UTF16ToUTF8(f.source);
-    frame->function_name = base::UTF16ToUTF8(f.function);
-    result->stack_trace.push_back(frame);
+    developer::StackFrame frame;
+    frame.line_number = f.line_number;
+    frame.column_number = f.column_number;
+    frame.url = base::UTF16ToUTF8(f.source);
+    frame.function_name = base::UTF16ToUTF8(f.function);
+    result.stack_trace.push_back(std::move(frame));
   }
   return result;
 }
@@ -159,21 +158,21 @@
 // to the list of |commands|.
 void ConstructCommands(CommandService* command_service,
                        const std::string& extension_id,
-                       std::vector<linked_ptr<developer::Command>>* commands) {
-  auto construct_command = [](const Command& command,
-                              bool active,
+                       std::vector<developer::Command>* commands) {
+  auto construct_command = [](const Command& command, bool active,
                               bool is_extension_action) {
-    developer::Command* command_value = new developer::Command();
-    command_value->description = is_extension_action ?
-        l10n_util::GetStringUTF8(IDS_EXTENSION_COMMANDS_GENERIC_ACTIVATE) :
-        base::UTF16ToUTF8(command.description());
-    command_value->keybinding =
+    developer::Command command_value;
+    command_value.description =
+        is_extension_action
+            ? l10n_util::GetStringUTF8(IDS_EXTENSION_COMMANDS_GENERIC_ACTIVATE)
+            : base::UTF16ToUTF8(command.description());
+    command_value.keybinding =
         base::UTF16ToUTF8(command.accelerator().GetShortcutText());
-    command_value->name = command.command_name();
-    command_value->is_active = active;
-    command_value->scope = command.global() ? developer::COMMAND_SCOPE_GLOBAL :
-        developer::COMMAND_SCOPE_CHROME;
-    command_value->is_extension_action = is_extension_action;
+    command_value.name = command.command_name();
+    command_value.is_active = active;
+    command_value.scope = command.global() ? developer::COMMAND_SCOPE_GLOBAL
+                                           : developer::COMMAND_SCOPE_CHROME;
+    command_value.is_extension_action = is_extension_action;
     return command_value;
   };
   bool active = false;
@@ -182,8 +181,7 @@
                                                CommandService::ALL,
                                                &browser_action,
                                                &active)) {
-    commands->push_back(
-        make_linked_ptr(construct_command(browser_action, active, true)));
+    commands->push_back(construct_command(browser_action, active, true));
   }
 
   Command page_action;
@@ -191,8 +189,7 @@
                                             CommandService::ALL,
                                             &page_action,
                                             &active)) {
-    commands->push_back(
-        make_linked_ptr(construct_command(page_action, active, true)));
+    commands->push_back(construct_command(page_action, active, true));
   }
 
   CommandMap named_commands;
@@ -214,8 +211,7 @@
       command_to_use.set_accelerator(active_command.accelerator());
       command_to_use.set_global(active_command.global());
       bool active = command_to_use.accelerator().key_code() != ui::VKEY_UNKNOWN;
-      commands->push_back(
-          make_linked_ptr(construct_command(command_to_use, active, false)));
+      commands->push_back(construct_command(command_to_use, active, false));
     }
   }
 }
@@ -260,8 +256,8 @@
 
   if (pending_image_loads_ == 0) {
     // Don't call the callback re-entrantly.
-    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                  base::Bind(callback, list_));
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::Bind(callback, base::Passed(&list_)));
     list_.clear();
   } else {
     callback_ = callback;
@@ -296,8 +292,8 @@
 
   if (pending_image_loads_ == 0) {
     // Don't call the callback re-entrantly.
-    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                  base::Bind(callback, list_));
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::Bind(callback, base::Passed(&list_)));
     list_.clear();
   } else {
     callback_ = callback;
@@ -540,7 +536,7 @@
                                  ExtensionIconSet::MATCH_BIGGER);
   if (icon.empty()) {
     info->icon_url = GetDefaultIconUrl(extension.is_app(), !is_enabled);
-    list_.push_back(make_linked_ptr(info.release()));
+    list_.push_back(std::move(*info));
   } else {
     ++pending_image_loads_;
     // Max size of 128x128 is a random guess at a nice balance between being
@@ -550,7 +546,7 @@
     image_loader_->LoadImageAsync(
         &extension, icon, max_size,
         base::Bind(&ExtensionInfoGenerator::OnImageLoaded,
-                   weak_factory_.GetWeakPtr(), base::Passed(std::move(info))));
+                   weak_factory_.GetWeakPtr(), base::Passed(&info)));
   }
 }
 
@@ -615,18 +611,15 @@
         is_app, info->state != developer::EXTENSION_STATE_ENABLED);
   }
 
-  list_.push_back(make_linked_ptr(info.release()));
+  list_.push_back(std::move(*info));
 
   --pending_image_loads_;
 
   if (pending_image_loads_ == 0) {  // All done!
-    // We assign to a temporary callback and list and reset the stored values so
-    // that at the end of the method, any stored refs are destroyed.
-    ExtensionInfoList list;
-    list.swap(list_);
-    ExtensionInfosCallback callback = callback_;
-    callback_.Reset();
-    callback.Run(list);  // WARNING: |this| is possibly deleted after this line!
+    ExtensionInfoList list = std::move(list_);
+    list_.clear();
+    base::ResetAndReturn(&callback_).Run(std::move(list));
+    // WARNING: |this| is possibly deleted after this line!
   }
 }
 
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator.h b/chrome/browser/extensions/api/developer_private/extension_info_generator.h
index 2b82e4b..5a47e84 100644
--- a/chrome/browser/extensions/api/developer_private/extension_info_generator.h
+++ b/chrome/browser/extensions/api/developer_private/extension_info_generator.h
@@ -35,10 +35,9 @@
 // This class is designed to only have one generation running at a time!
 class ExtensionInfoGenerator {
  public:
-  using ExtensionInfoList =
-      std::vector<linked_ptr<api::developer_private::ExtensionInfo>>;
+  using ExtensionInfoList = std::vector<api::developer_private::ExtensionInfo>;
 
-  using ExtensionInfosCallback = base::Callback<void(const ExtensionInfoList&)>;
+  using ExtensionInfosCallback = base::Callback<void(ExtensionInfoList)>;
 
   explicit ExtensionInfoGenerator(content::BrowserContext* context);
   ~ExtensionInfoGenerator();
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
index c008601..90b6c11 100644
--- a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
+++ b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
@@ -4,6 +4,7 @@
 
 #include <utility>
 
+#include "base/callback_helpers.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/json/json_writer.h"
 #include "base/macros.h"
@@ -57,18 +58,17 @@
     InitializeEmptyExtensionService();
   }
 
-  void OnInfosGenerated(linked_ptr<developer::ExtensionInfo>* info_out,
-                        const ExtensionInfoGenerator::ExtensionInfoList& list) {
+  void OnInfosGenerated(scoped_ptr<developer::ExtensionInfo>* info_out,
+                        ExtensionInfoGenerator::ExtensionInfoList list) {
     EXPECT_EQ(1u, list.size());
     if (!list.empty())
-      *info_out = list[0];
-    quit_closure_.Run();
-    quit_closure_.Reset();
+      info_out->reset(new developer::ExtensionInfo(std::move(list[0])));
+    base::ResetAndReturn(&quit_closure_).Run();
   }
 
   scoped_ptr<developer::ExtensionInfo> GenerateExtensionInfo(
       const std::string& extension_id) {
-    linked_ptr<developer::ExtensionInfo> info;
+    scoped_ptr<developer::ExtensionInfo> info;
     base::RunLoop run_loop;
     quit_closure_ = run_loop.QuitClosure();
     scoped_ptr<ExtensionInfoGenerator> generator(
@@ -79,7 +79,7 @@
                    base::Unretained(this),
                    base::Unretained(&info)));
     run_loop.Run();
-    return make_scoped_ptr(info.release());
+    return info;
   }
 
   const scoped_refptr<const Extension> CreateExtension(
@@ -126,7 +126,7 @@
 
   void CompareExpectedAndActualOutput(
       const base::FilePath& extension_path,
-      const InspectableViewsFinder::ViewList& views,
+      InspectableViewsFinder::ViewList views,
       const base::FilePath& expected_output_path) {
     std::string error;
     scoped_ptr<base::DictionaryValue> expected_output_data(
@@ -136,7 +136,7 @@
     // Produce test output.
     scoped_ptr<developer::ExtensionInfo> info =
         CreateExtensionInfoFromPath(extension_path, Manifest::INVALID_LOCATION);
-    info->views = views;
+    info->views = std::move(views);
     scoped_ptr<base::DictionaryValue> actual_output_data = info->ToValue();
     ASSERT_TRUE(actual_output_data);
 
@@ -253,7 +253,7 @@
   EXPECT_FALSE(info->incognito_access.is_active);
   ASSERT_EQ(2u, info->runtime_errors.size());
   const api::developer_private::RuntimeError& runtime_error =
-      *info->runtime_errors[0];
+      info->runtime_errors[0];
   EXPECT_EQ(extension->id(), runtime_error.extension_id);
   EXPECT_EQ(api::developer_private::ERROR_TYPE_RUNTIME, runtime_error.type);
   EXPECT_EQ(api::developer_private::ERROR_LEVEL_ERROR,
@@ -261,11 +261,11 @@
   EXPECT_EQ(1u, runtime_error.stack_trace.size());
   ASSERT_EQ(1u, info->manifest_errors.size());
   const api::developer_private::RuntimeError& runtime_error_verbose =
-      *info->runtime_errors[1];
+      info->runtime_errors[1];
   EXPECT_EQ(api::developer_private::ERROR_LEVEL_LOG,
             runtime_error_verbose.severity);
   const api::developer_private::ManifestError& manifest_error =
-      *info->manifest_errors[0];
+      info->manifest_errors[0];
   EXPECT_EQ(extension->id(), manifest_error.extension_id);
 
   // Test an extension that isn't unpacked.
@@ -292,24 +292,25 @@
                 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
                 .AppendASCII("1.0.0.0");
 
-  InspectableViewsFinder::ViewList views;
-  views.push_back(InspectableViewsFinder::ConstructView(
-      GURL("chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/bar.html"),
-      42, 88, true, false, VIEW_TYPE_TAB_CONTENTS));
-  views.push_back(InspectableViewsFinder::ConstructView(
-      GURL("chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/dog.html"),
-      0, 0, false, true, VIEW_TYPE_TAB_CONTENTS));
-
   base::FilePath expected_outputs_path =
       data_dir().AppendASCII("api_test")
                 .AppendASCII("developer")
                 .AppendASCII("generated_output");
 
-  CompareExpectedAndActualOutput(
-      extension_path,
-      views,
-      expected_outputs_path.AppendASCII(
-          "behllobkkfkfnphdnhnkndlbkcpglgmj.json"));
+  {
+    InspectableViewsFinder::ViewList views;
+    views.push_back(InspectableViewsFinder::ConstructView(
+        GURL("chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/bar.html"),
+        42, 88, true, false, VIEW_TYPE_TAB_CONTENTS));
+    views.push_back(InspectableViewsFinder::ConstructView(
+        GURL("chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/dog.html"), 0,
+        0, false, true, VIEW_TYPE_TAB_CONTENTS));
+
+    CompareExpectedAndActualOutput(
+        extension_path, std::move(views),
+        expected_outputs_path.AppendASCII(
+            "behllobkkfkfnphdnhnkndlbkcpglgmj.json"));
+  }
 
 #if !defined(OS_CHROMEOS)
   // Test Extension2
@@ -318,16 +319,21 @@
                              .AppendASCII("hpiknbiabeeppbpihjehijgoemciehgk")
                              .AppendASCII("2");
 
-  // It's OK to have duplicate URLs, so long as the IDs are different.
-  views[0]->url =
-      "chrome-extension://hpiknbiabeeppbpihjehijgoemciehgk/bar.html";
-  views[1]->url = views[0]->url;
+  {
+    // It's OK to have duplicate URLs, so long as the IDs are different.
+    InspectableViewsFinder::ViewList views;
+    views.push_back(InspectableViewsFinder::ConstructView(
+        GURL("chrome-extension://hpiknbiabeeppbpihjehijgoemciehgk/bar.html"),
+        42, 88, true, false, VIEW_TYPE_TAB_CONTENTS));
+    views.push_back(InspectableViewsFinder::ConstructView(
+        GURL("chrome-extension://hpiknbiabeeppbpihjehijgoemciehgk/bar.html"), 0,
+        0, false, true, VIEW_TYPE_TAB_CONTENTS));
 
-  CompareExpectedAndActualOutput(
-      extension_path,
-      views,
-      expected_outputs_path.AppendASCII(
-          "hpiknbiabeeppbpihjehijgoemciehgk.json"));
+    CompareExpectedAndActualOutput(
+        extension_path, std::move(views),
+        expected_outputs_path.AppendASCII(
+            "hpiknbiabeeppbpihjehijgoemciehgk.json"));
+  }
 #endif
 
   // Test Extension3
@@ -335,13 +341,10 @@
                              .AppendASCII("Extensions")
                              .AppendASCII("bjafgdebaacbbbecmhlhpofkepfkgcpa")
                              .AppendASCII("1.0");
-  views.clear();
-
-  CompareExpectedAndActualOutput(
-      extension_path,
-      views,
-      expected_outputs_path.AppendASCII(
-          "bjafgdebaacbbbecmhlhpofkepfkgcpa.json"));
+  CompareExpectedAndActualOutput(extension_path,
+                                 InspectableViewsFinder::ViewList(),
+                                 expected_outputs_path.AppendASCII(
+                                     "bjafgdebaacbbbecmhlhpofkepfkgcpa.json"));
 }
 
 // Test that the all_urls checkbox only shows up for extensions that want all
diff --git a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
index f12df3a..e5051949e 100644
--- a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
+++ b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
@@ -38,45 +38,44 @@
     bool incognito,
     bool is_iframe,
     ViewType type) {
-  linked_ptr<api::developer_private::ExtensionView> view(
-      new api::developer_private::ExtensionView());
-  view->url = url.spec();
-  view->render_process_id = render_process_id;
+  api::developer_private::ExtensionView view;
+  view.url = url.spec();
+  view.render_process_id = render_process_id;
   // NOTE(devlin): This is called "render_view_id" in the api for legacy
   // reasons, but it's not a high priority to change.
-  view->render_view_id = render_frame_id;
-  view->incognito = incognito;
-  view->is_iframe = is_iframe;
+  view.render_view_id = render_frame_id;
+  view.incognito = incognito;
+  view.is_iframe = is_iframe;
   switch (type) {
     case VIEW_TYPE_APP_WINDOW:
-      view->type = api::developer_private::VIEW_TYPE_APP_WINDOW;
+      view.type = api::developer_private::VIEW_TYPE_APP_WINDOW;
       break;
     case VIEW_TYPE_BACKGROUND_CONTENTS:
-      view->type = api::developer_private::VIEW_TYPE_BACKGROUND_CONTENTS;
+      view.type = api::developer_private::VIEW_TYPE_BACKGROUND_CONTENTS;
       break;
     case VIEW_TYPE_COMPONENT:
-      view->type = api::developer_private::VIEW_TYPE_COMPONENT;
+      view.type = api::developer_private::VIEW_TYPE_COMPONENT;
       break;
     case VIEW_TYPE_EXTENSION_BACKGROUND_PAGE:
-      view->type = api::developer_private::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE;
+      view.type = api::developer_private::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE;
       break;
     case VIEW_TYPE_EXTENSION_DIALOG:
-      view->type = api::developer_private::VIEW_TYPE_EXTENSION_DIALOG;
+      view.type = api::developer_private::VIEW_TYPE_EXTENSION_DIALOG;
       break;
     case VIEW_TYPE_EXTENSION_GUEST:
-      view->type = api::developer_private::VIEW_TYPE_EXTENSION_GUEST;
+      view.type = api::developer_private::VIEW_TYPE_EXTENSION_GUEST;
       break;
     case VIEW_TYPE_EXTENSION_POPUP:
-      view->type = api::developer_private::VIEW_TYPE_EXTENSION_POPUP;
+      view.type = api::developer_private::VIEW_TYPE_EXTENSION_POPUP;
       break;
     case VIEW_TYPE_LAUNCHER_PAGE:
-      view->type = api::developer_private::VIEW_TYPE_LAUNCHER_PAGE;
+      view.type = api::developer_private::VIEW_TYPE_LAUNCHER_PAGE;
       break;
     case VIEW_TYPE_PANEL:
-      view->type = api::developer_private::VIEW_TYPE_PANEL;
+      view.type = api::developer_private::VIEW_TYPE_PANEL;
       break;
     case VIEW_TYPE_TAB_CONTENTS:
-      view->type = api::developer_private::VIEW_TYPE_TAB_CONTENTS;
+      view.type = api::developer_private::VIEW_TYPE_TAB_CONTENTS;
       break;
     default:
       NOTREACHED();
diff --git a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.h b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.h
index 20346aa..f904c372 100644
--- a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.h
+++ b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.h
@@ -28,7 +28,7 @@
 // by the developerPrivate API structure and schema compiler.
 class InspectableViewsFinder {
  public:
-  using View = linked_ptr<api::developer_private::ExtensionView>;
+  using View = api::developer_private::ExtensionView;
   using ViewList = std::vector<View>;
 
   explicit InspectableViewsFinder(Profile* profile);
diff --git a/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc b/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
index d4c5e3c..3160400 100644
--- a/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
+++ b/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
@@ -128,7 +128,7 @@
 
 }  // anonymous namespace
 
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_Metrics) {
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Metrics) {
   base::UserActionTester user_action_tester;
 
   base::FieldTrialList::CreateFieldTrial("apitestfieldtrial2", "group1");
diff --git a/chrome/browser/extensions/chrome_mojo_service_registration.cc b/chrome/browser/extensions/chrome_mojo_service_registration.cc
index 89e37f7..2f50799f 100644
--- a/chrome/browser/extensions/chrome_mojo_service_registration.cc
+++ b/chrome/browser/extensions/chrome_mojo_service_registration.cc
@@ -33,7 +33,7 @@
             APIPermission::kMediaRouterPrivate)) {
       render_frame_host->GetServiceRegistry()->AddService(
           base::Bind(media_router::MediaRouterMojoImpl::BindToRequest,
-                     extension->id(), context));
+                     extension, context));
     }
   }
 #endif  // defined(ENABLE_MEDIA_ROUTER)
diff --git a/chrome/browser/extensions/display_info_provider_chromeos.cc b/chrome/browser/extensions/display_info_provider_chromeos.cc
index 89f3339..aeab4997 100644
--- a/chrome/browser/extensions/display_info_provider_chromeos.cc
+++ b/chrome/browser/extensions/display_info_provider_chromeos.cc
@@ -97,7 +97,7 @@
 //
 // The rectangle shares an egde with the reference's bottom edge, but it's
 // center point is in the left area.
-scoped_ptr<ash::DisplayPlacement> CreatePlacementForRectangles(
+ash::DisplayPlacement CreatePlacementForRectangles(
     const gfx::Rect& reference,
     const gfx::Rect& rectangle) {
   // Translate coordinate system so origin is in the reference's top left point
@@ -153,7 +153,7 @@
                 position == ash::DisplayPlacement::RIGHT)
                    ? rectangle.y()
                    : rectangle.x();
-  return make_scoped_ptr(new ash::DisplayPlacement(position, offset));
+  return ash::DisplayPlacement(position, offset);
 }
 
 // Updates the display layout for the target display in reference to the primary
@@ -162,13 +162,13 @@
                          int64_t primary_display_id,
                          const gfx::Rect& target_display_bounds,
                          int64_t target_display_id) {
-  scoped_ptr<ash::DisplayPlacement> placement(CreatePlacementForRectangles(
+  ash::DisplayPlacement placement(CreatePlacementForRectangles(
       primary_display_bounds, target_display_bounds));
-  placement->display_id = target_display_id;
-  placement->parent_display_id = primary_display_id;
+  placement.display_id = target_display_id;
+  placement.parent_display_id = primary_display_id;
 
   scoped_ptr<ash::DisplayLayout> layout(new ash::DisplayLayout);
-  layout->placement_list.push_back(std::move(placement));
+  layout->placement_list.push_back(placement);
   layout->primary_id = primary_display_id;
 
   ash::Shell::GetInstance()
diff --git a/chrome/browser/extensions/extension_special_storage_policy_unittest.cc b/chrome/browser/extensions/extension_special_storage_policy_unittest.cc
index 7ce7aaf..542ca9c5b 100644
--- a/chrome/browser/extensions/extension_special_storage_policy_unittest.cc
+++ b/chrome/browser/extensions/extension_special_storage_policy_unittest.cc
@@ -331,17 +331,13 @@
   EXPECT_FALSE(policy_->HasSessionOnlyOrigins());
 
   // Or the session-onlyness can affect individual origins.
-  ContentSettingsPattern pattern =
-      ContentSettingsPattern::FromString("pattern.com");
-
-  cookie_settings->SetCookieSetting(pattern,
-                                    ContentSettingsPattern::Wildcard(),
-                                    CONTENT_SETTING_SESSION_ONLY);
+  GURL url("http://pattern.com");
+  cookie_settings->SetCookieSetting(url, CONTENT_SETTING_SESSION_ONLY);
 
   EXPECT_TRUE(policy_->HasSessionOnlyOrigins());
 
   // Clearing an origin-specific rule.
-  cookie_settings->ResetCookieSetting(GURL("http://pattern.com"));
+  cookie_settings->ResetCookieSetting(url);
 
   EXPECT_FALSE(policy_->HasSessionOnlyOrigins());
 }
diff --git a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
index db94860c..0a2ac2941a 100644
--- a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
+++ b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
@@ -27,7 +27,7 @@
     return os_state_;
   }
 
-  AttemptResult SetAsDefaultImpl() override { return AttemptResult::SUCCESS; }
+  void SetAsDefaultImpl() override {}
 
   shell_integration::DefaultWebClientState os_state_;
 };
diff --git a/chrome/browser/jumplist_win.cc b/chrome/browser/jumplist_win.cc
index a54409f..35c5e93 100644
--- a/chrome/browser/jumplist_win.cc
+++ b/chrome/browser/jumplist_win.cc
@@ -575,7 +575,7 @@
                  incognito_availability,
                  app_id_,
                  icon_dir_,
-                 jumplist_data_));
+                 base::RetainedRef(jumplist_data_)));
 }
 
 void JumpList::TopSitesLoaded(history::TopSites* top_sites) {
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn
index 5fb15b0..0ad5f57 100644
--- a/chrome/browser/media/router/BUILD.gn
+++ b/chrome/browser/media/router/BUILD.gn
@@ -45,6 +45,7 @@
 source_set("test_support") {
   testonly = true
   deps = [
+    # TODO(crbug.com/596999): Move non-Android code to mojo/
     ":mojo_bindings",
     ":router",
     "//chrome/test:test_support",
@@ -53,4 +54,11 @@
   sources = rebase_path(gypi_values.media_router_test_support_sources,
                         ".",
                         "//chrome/browser/media/router")
+  if (!is_android) {
+    deps += [ "//extensions/common" ]
+    sources +=
+        rebase_path(gypi_values.media_router_non_android_test_support_sources,
+                    ".",
+                    "//chrome/browser/media/router")
+  }
 }
diff --git a/chrome/browser/media/router/media_router.gyp b/chrome/browser/media/router/media_router.gyp
index 78c49b4e..7c33a46a 100644
--- a/chrome/browser/media/router/media_router.gyp
+++ b/chrome/browser/media/router/media_router.gyp
@@ -70,6 +70,7 @@
       ],
       'dependencies': [
         'media_router',
+        # TODO(crbug.com/596999): Move non-Android code to mojo/
         'media_router_mojo',
         'media_router_mojo_gen',
         '<(DEPTH)/base/base.gyp:base',
@@ -78,6 +79,16 @@
       'sources': [
         '<@(media_router_test_support_sources)',
       ],
+      'conditions': [
+        [ 'OS!="android" and OS!="ios"', {
+          'dependencies': [
+            '<(DEPTH)/extensions/extensions.gyp:extensions_common',
+          ],
+          'sources': [
+            '<@(media_router_non_android_test_support_sources)',
+          ]
+        }],
+      ]
     },
   ],
 }
diff --git a/chrome/browser/media/router/media_router.gypi b/chrome/browser/media/router/media_router.gypi
index 7556a6c..073db22 100644
--- a/chrome/browser/media/router/media_router.gypi
+++ b/chrome/browser/media/router/media_router.gypi
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+# TODO(crbug.com/596999): Move non-Android code to mojo/
 {
   'variables': {
     # File lists shared with GN build.
@@ -55,8 +56,6 @@
       'media_router_type_converters.h',
     ],
     'media_router_test_support_sources': [
-      'media_router_mojo_test.cc',
-      'media_router_mojo_test.h',
       'mock_media_router.cc',
       'mock_media_router.h',
       'mock_screen_availability_listener.cc',
@@ -64,5 +63,9 @@
       'test_helper.cc',
       'test_helper.h',
     ],
+    'media_router_non_android_test_support_sources': [
+      'media_router_mojo_test.cc',
+      'media_router_mojo_test.h',
+    ],
   },
 }
diff --git a/chrome/browser/media/router/media_router_metrics.cc b/chrome/browser/media/router/media_router_metrics.cc
index cda93c8e..707a3a1 100644
--- a/chrome/browser/media/router/media_router_metrics.cc
+++ b/chrome/browser/media/router/media_router_metrics.cc
@@ -6,13 +6,18 @@
 
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
+#if !defined(OS_ANDROID)
+#include "base/version.h"
+#include "components/version_info/version_info.h"
+#include "extensions/common/extension.h"
+#endif  // !defined(OS_ANDROID)
 
 namespace media_router {
 
 // static
 void MediaRouterMetrics::RecordMediaRouterDialogOrigin(
     MediaRouterDialogOpenOrigin origin) {
-  DCHECK_NE(static_cast<int>(origin),
+  DCHECK_LT(static_cast<int>(origin),
             static_cast<int>(MediaRouterDialogOpenOrigin::TOTAL_COUNT));
   UMA_HISTOGRAM_ENUMERATION(
       "MediaRouter.Icon.Click.Location", static_cast<int>(origin),
@@ -20,16 +25,6 @@
 }
 
 // static
-void MediaRouterMetrics::RecordMediaRouteProviderWakeReason(
-    MediaRouteProviderWakeReason reason) {
-  DCHECK_NE(static_cast<int>(reason),
-            static_cast<int>(MediaRouteProviderWakeReason::TOTAL_COUNT));
-  UMA_HISTOGRAM_ENUMERATION(
-      "MediaRouter.Provider.WakeReason", static_cast<int>(reason),
-      static_cast<int>(MediaRouteProviderWakeReason::TOTAL_COUNT));
-}
-
-// static
 void MediaRouterMetrics::RecordMediaRouterDialogPaint(
     const base::TimeDelta delta) {
   UMA_HISTOGRAM_TIMES("MediaRouter.Ui.Dialog.Paint",
@@ -46,7 +41,7 @@
 // static
 void MediaRouterMetrics::RecordMediaRouterInitialUserAction(
     MediaRouterUserAction action) {
-  DCHECK_NE(static_cast<int>(action),
+  DCHECK_LT(static_cast<int>(action),
             static_cast<int>(MediaRouterUserAction::TOTAL_COUNT));
   UMA_HISTOGRAM_ENUMERATION(
       "MediaRouter.Ui.FirstAction", static_cast<int>(action),
@@ -56,12 +51,73 @@
 // static
 void MediaRouterMetrics::RecordRouteCreationOutcome(
     MediaRouterRouteCreationOutcome outcome) {
-  DCHECK_NE(static_cast<int>(outcome),
-            static_cast<int>(
-                MediaRouterRouteCreationOutcome::TOTAL_COUNT));
+  DCHECK_LT(static_cast<int>(outcome),
+            static_cast<int>(MediaRouterRouteCreationOutcome::TOTAL_COUNT));
   UMA_HISTOGRAM_ENUMERATION(
     "MediaRouter.Route.CreationOutcome", static_cast<int>(outcome),
     static_cast<int>(MediaRouterRouteCreationOutcome::TOTAL_COUNT));
 }
 
+#if !defined(OS_ANDROID)
+// static
+void MediaRouterMetrics::RecordMediaRouteProviderWakeReason(
+    MediaRouteProviderWakeReason reason) {
+  DCHECK_LT(static_cast<int>(reason),
+            static_cast<int>(MediaRouteProviderWakeReason::TOTAL_COUNT));
+  UMA_HISTOGRAM_ENUMERATION(
+      "MediaRouter.Provider.WakeReason", static_cast<int>(reason),
+      static_cast<int>(MediaRouteProviderWakeReason::TOTAL_COUNT));
+}
+
+// static
+void MediaRouterMetrics::RecordMediaRouteProviderVersion(
+    const extensions::Extension& extension) {
+  MediaRouteProviderVersion version = MediaRouteProviderVersion::UNKNOWN;
+  const base::Version* extension_version = extension.version();
+  if (extension_version) {
+    version = GetMediaRouteProviderVersion(
+        *extension_version, base::Version(version_info::GetVersionNumber()));
+  }
+
+  DCHECK_LT(static_cast<int>(version),
+            static_cast<int>(MediaRouteProviderVersion::TOTAL_COUNT));
+  UMA_HISTOGRAM_ENUMERATION(
+      "MediaRouter.Provider.Version", static_cast<int>(version),
+      static_cast<int>(MediaRouteProviderVersion::TOTAL_COUNT));
+}
+
+// static
+void MediaRouterMetrics::RecordMediaRouteProviderWakeup(
+    MediaRouteProviderWakeup wakeup) {
+  DCHECK_LT(static_cast<int>(wakeup),
+            static_cast<int>(MediaRouteProviderWakeup::TOTAL_COUNT));
+  UMA_HISTOGRAM_ENUMERATION(
+      "MediaRouter.Provider.Wakeup", static_cast<int>(wakeup),
+      static_cast<int>(MediaRouteProviderWakeup::TOTAL_COUNT));
+}
+
+// static
+MediaRouteProviderVersion MediaRouterMetrics::GetMediaRouteProviderVersion(
+    const base::Version& extension_version,
+    const base::Version& browser_version) {
+  if (!extension_version.IsValid() || extension_version.components().empty() ||
+      !browser_version.IsValid() || browser_version.components().empty()) {
+    return MediaRouteProviderVersion::UNKNOWN;
+  }
+
+  uint32_t extension_major = extension_version.components()[0];
+  uint32_t browser_major = browser_version.components()[0];
+  // Sanity check.
+  if (extension_major == 0 || browser_major == 0) {
+    return MediaRouteProviderVersion::UNKNOWN;
+  } else if (extension_major >= browser_major) {
+    return MediaRouteProviderVersion::SAME_VERSION_AS_CHROME;
+  } else if (browser_major - extension_major == 1) {
+    return MediaRouteProviderVersion::ONE_VERSION_BEHIND_CHROME;
+  } else {
+    return MediaRouteProviderVersion::MULTIPLE_VERSIONS_BEHIND_CHROME;
+  }
+}
+#endif  // !defined(OS_ANDROID)
+
 }  // namespace media_router
diff --git a/chrome/browser/media/router/media_router_metrics.h b/chrome/browser/media/router/media_router_metrics.h
index dbdeb198..9eda482 100644
--- a/chrome/browser/media/router/media_router_metrics.h
+++ b/chrome/browser/media/router/media_router_metrics.h
@@ -5,8 +5,19 @@
 #ifndef CHROME_BROWSER_MEDIA_ROUTER_MEDIA_ROUTER_METRICS_H_
 #define CHROME_BROWSER_MEDIA_ROUTER_MEDIA_ROUTER_METRICS_H_
 
+#include "base/gtest_prod_util.h"
 #include "base/time/time.h"
 
+namespace base {
+class Version;
+}  // namespace base
+
+#if !defined(OS_ANDROID)
+namespace extensions {
+class Extension;
+}  // namespace extensions
+#endif  // !defined(OS_ANDROID)
+
 namespace media_router {
 
 // NOTE: Do not renumber enums as that would confuse interpretation of
@@ -24,28 +35,6 @@
   TOTAL_COUNT = 4
 };
 
-// Why the Media Route Provider process was woken up.
-enum class MediaRouteProviderWakeReason {
-  CREATE_ROUTE = 0,
-  JOIN_ROUTE = 1,
-  TERMINATE_ROUTE = 2,
-  SEND_SESSION_MESSAGE = 3,
-  SEND_SESSION_BINARY_MESSAGE = 4,
-  DETACH_ROUTE = 5,
-  START_OBSERVING_MEDIA_SINKS = 6,
-  STOP_OBSERVING_MEDIA_SINKS = 7,
-  START_OBSERVING_MEDIA_ROUTES = 8,
-  STOP_OBSERVING_MEDIA_ROUTES = 9,
-  LISTEN_FOR_ROUTE_MESSAGES = 10,
-  STOP_LISTENING_FOR_ROUTE_MESSAGES = 11,
-  CONNECTION_ERROR = 12,
-  REGISTER_MEDIA_ROUTE_PROVIDER = 13,
-  CONNECT_ROUTE_BY_ROUTE_ID = 14,
-
-  // NOTE: Add entries only immediately above this line.
-  TOTAL_COUNT = 15
-};
-
 // The possible outcomes from a route creation response.
 enum class MediaRouterRouteCreationOutcome {
   SUCCESS = 0,
@@ -69,16 +58,61 @@
   TOTAL_COUNT = 5
 };
 
+#if !defined(OS_ANDROID)
+// Why the Media Route Provider process was woken up.
+enum class MediaRouteProviderWakeReason {
+  CREATE_ROUTE = 0,
+  JOIN_ROUTE = 1,
+  TERMINATE_ROUTE = 2,
+  SEND_SESSION_MESSAGE = 3,
+  SEND_SESSION_BINARY_MESSAGE = 4,
+  DETACH_ROUTE = 5,
+  START_OBSERVING_MEDIA_SINKS = 6,
+  STOP_OBSERVING_MEDIA_SINKS = 7,
+  START_OBSERVING_MEDIA_ROUTES = 8,
+  STOP_OBSERVING_MEDIA_ROUTES = 9,
+  LISTEN_FOR_ROUTE_MESSAGES = 10,
+  STOP_LISTENING_FOR_ROUTE_MESSAGES = 11,
+  CONNECTION_ERROR = 12,
+  REGISTER_MEDIA_ROUTE_PROVIDER = 13,
+  CONNECT_ROUTE_BY_ROUTE_ID = 14,
+
+  // NOTE: Add entries only immediately above this line.
+  TOTAL_COUNT = 15
+};
+
+// The install status of the Media Router component extension.
+enum class MediaRouteProviderVersion {
+  // Installed but version is invalid or cannot be determined.
+  UNKNOWN = 0,
+  // Installed and the extension version matches the browser version.
+  SAME_VERSION_AS_CHROME = 1,
+  // Installed and the extension version is one version behind the browser
+  // version.
+  ONE_VERSION_BEHIND_CHROME = 2,
+  // Installed and the extension version is more than one version behind the
+  // browser version.
+  MULTIPLE_VERSIONS_BEHIND_CHROME = 3,
+  // Note: Add entries only immediately above this line.
+  TOTAL_COUNT = 4
+};
+
+// The outcome of an attempt to wake the Media Router component event page.
+enum class MediaRouteProviderWakeup {
+  SUCCESS = 0,
+  ERROR_UNKNOWN = 1,
+  ERROR_TOO_MANY_RETRIES = 2,
+  // Note: Add entries only immediately above this line.
+  TOTAL_COUNT = 3
+};
+#endif  // !defined(OS_ANDROID)
+
 class MediaRouterMetrics {
  public:
   // Records where the user clicked to open the Media Router dialog.
   static void RecordMediaRouterDialogOrigin(
       MediaRouterDialogOpenOrigin origin);
 
-  // Records why the media route provider extension was woken up.
-  static void RecordMediaRouteProviderWakeReason(
-      MediaRouteProviderWakeReason reason);
-
   // Records the duration it takes for the Media Router dialog to open and
   // finish painting after a user clicks to open the dialog.
   static void RecordMediaRouterDialogPaint(
@@ -97,6 +131,29 @@
   // Records the outcome in a create route response.
   static void RecordRouteCreationOutcome(
       MediaRouterRouteCreationOutcome outcome);
+
+#if !defined(OS_ANDROID)
+  // Records the installed version of the Media Router component extension.
+  static void RecordMediaRouteProviderVersion(
+      const extensions::Extension& extension);
+
+  // Records why the media route provider extension was woken up.
+  static void RecordMediaRouteProviderWakeReason(
+      MediaRouteProviderWakeReason reason);
+
+  // Records the outcome of an attempt to wake the Media Router component event
+  // page.
+  static void RecordMediaRouteProviderWakeup(MediaRouteProviderWakeup wakeup);
+
+ private:
+  FRIEND_TEST_ALL_PREFIXES(MediaRouteProviderMetricsTest,
+                           TestGetMediaRouteProviderVersion);
+
+  // Returns the version status of the Media Router component extension.
+  static MediaRouteProviderVersion GetMediaRouteProviderVersion(
+      const base::Version& extension_version,
+      const base::Version& browser_version);
+#endif  // !defined(OS_ANDROID)
 };
 
 }  // namespace media_router
diff --git a/chrome/browser/media/router/media_router_metrics_unittest.cc b/chrome/browser/media/router/media_router_metrics_unittest.cc
new file mode 100644
index 0000000..da0212b
--- /dev/null
+++ b/chrome/browser/media/router/media_router_metrics_unittest.cc
@@ -0,0 +1,43 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/router/media_router_metrics.h"
+
+#include "base/version.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media_router {
+
+TEST(MediaRouteProviderMetricsTest, TestGetMediaRouteProviderVersion) {
+  const base::Version kBrowserVersion("50.0.2396.71");
+  EXPECT_EQ(MediaRouteProviderVersion::SAME_VERSION_AS_CHROME,
+            MediaRouterMetrics::GetMediaRouteProviderVersion(
+                base::Version("50.0.2396.71"), kBrowserVersion));
+  EXPECT_EQ(MediaRouteProviderVersion::SAME_VERSION_AS_CHROME,
+            MediaRouterMetrics::GetMediaRouteProviderVersion(
+                base::Version("50.0.2100.0"), kBrowserVersion));
+  EXPECT_EQ(MediaRouteProviderVersion::SAME_VERSION_AS_CHROME,
+            MediaRouterMetrics::GetMediaRouteProviderVersion(
+                base::Version("51.0.2117.0"), kBrowserVersion));
+  EXPECT_EQ(MediaRouteProviderVersion::ONE_VERSION_BEHIND_CHROME,
+            MediaRouterMetrics::GetMediaRouteProviderVersion(
+                base::Version("49.0.2138.0"), kBrowserVersion));
+  EXPECT_EQ(MediaRouteProviderVersion::MULTIPLE_VERSIONS_BEHIND_CHROME,
+            MediaRouterMetrics::GetMediaRouteProviderVersion(
+                base::Version("47.0.1134.0"), kBrowserVersion));
+  EXPECT_EQ(MediaRouteProviderVersion::UNKNOWN,
+            MediaRouterMetrics::GetMediaRouteProviderVersion(
+                base::Version("blargh"), kBrowserVersion));
+  EXPECT_EQ(MediaRouteProviderVersion::UNKNOWN,
+            MediaRouterMetrics::GetMediaRouteProviderVersion(base::Version(""),
+                                                             kBrowserVersion));
+  EXPECT_EQ(MediaRouteProviderVersion::UNKNOWN,
+            MediaRouterMetrics::GetMediaRouteProviderVersion(
+                base::Version("-1.0.0.0"), kBrowserVersion));
+  EXPECT_EQ(MediaRouteProviderVersion::UNKNOWN,
+            MediaRouterMetrics::GetMediaRouteProviderVersion(base::Version("0"),
+                                                             kBrowserVersion));
+}
+
+}  // namespace media_router
diff --git a/chrome/browser/media/router/media_router_mojo_impl.cc b/chrome/browser/media/router/media_router_mojo_impl.cc
index 37ea11c..54c50ee 100644
--- a/chrome/browser/media/router/media_router_mojo_impl.cc
+++ b/chrome/browser/media/router/media_router_mojo_impl.cc
@@ -78,7 +78,6 @@
     : event_page_tracker_(event_page_tracker),
       instance_id_(base::GenerateGUID()),
       availability_(interfaces::MediaRouter::SinkAvailability::UNAVAILABLE),
-      wakeup_attempt_count_(0),
       current_wake_reason_(MediaRouteProviderWakeReason::TOTAL_COUNT),
       weak_factory_(this) {
   DCHECK(event_page_tracker_);
@@ -90,19 +89,19 @@
 
 // static
 void MediaRouterMojoImpl::BindToRequest(
-    const std::string& extension_id,
+    const extensions::Extension* extension,
     content::BrowserContext* context,
     mojo::InterfaceRequest<interfaces::MediaRouter> request) {
   MediaRouterMojoImpl* impl = static_cast<MediaRouterMojoImpl*>(
       MediaRouterFactory::GetApiForBrowserContext(context));
   DCHECK(impl);
 
-  impl->BindToMojoRequest(std::move(request), extension_id);
+  impl->BindToMojoRequest(std::move(request), *extension);
 }
 
 void MediaRouterMojoImpl::BindToMojoRequest(
     mojo::InterfaceRequest<interfaces::MediaRouter> request,
-    const std::string& extension_id) {
+    const extensions::Extension& extension) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   binding_.reset(
@@ -110,7 +109,11 @@
   binding_->set_connection_error_handler(base::Bind(
       &MediaRouterMojoImpl::OnConnectionError, base::Unretained(this)));
 
-  media_route_provider_extension_id_ = extension_id;
+  media_route_provider_extension_id_ = extension.id();
+  if (!provider_version_was_recorded_) {
+    MediaRouterMetrics::RecordMediaRouteProviderVersion(extension);
+    provider_version_was_recorded_ = true;
+  }
 }
 
 void MediaRouterMojoImpl::OnConnectionError() {
@@ -859,6 +862,8 @@
                               << "page.";
     DrainPendingRequests();
     wakeup_attempt_count_ = 0;
+    MediaRouterMetrics::RecordMediaRouteProviderWakeup(
+        MediaRouteProviderWakeup::ERROR_TOO_MANY_RETRIES);
     return;
   }
 
@@ -893,6 +898,8 @@
     MediaRouterMetrics::RecordMediaRouteProviderWakeReason(
         current_wake_reason_);
     ClearWakeReason();
+    MediaRouterMetrics::RecordMediaRouteProviderWakeup(
+        MediaRouteProviderWakeup::SUCCESS);
     return;
   }
 
@@ -901,6 +908,8 @@
       << "An error encountered while waking the event page.";
   ClearWakeReason();
   DrainPendingRequests();
+  MediaRouterMetrics::RecordMediaRouteProviderWakeup(
+      MediaRouteProviderWakeup::ERROR_UNKNOWN);
 }
 
 void MediaRouterMojoImpl::DrainPendingRequests() {
diff --git a/chrome/browser/media/router/media_router_mojo_impl.h b/chrome/browser/media/router/media_router_mojo_impl.h
index ff088aa..35ca51e 100644
--- a/chrome/browser/media/router/media_router_mojo_impl.h
+++ b/chrome/browser/media/router/media_router_mojo_impl.h
@@ -34,6 +34,7 @@
 
 namespace extensions {
 class EventPageTracker;
+class Extension;
 }
 
 namespace media_router {
@@ -49,15 +50,15 @@
 
   // Sets up the MediaRouterMojoImpl instance owned by |context| to handle
   // MediaRouterObserver requests from the component extension given by
-  // |extension_id|. Creates the MediaRouterMojoImpl instance if it does not
+  // |extension|. Creates the MediaRouterMojoImpl instance if it does not
   // exist.
   // Called by the Mojo module registry.
-  // |extension_id|: The ID of the component extension, used for querying
+  // |extension|: The component extension, used for querying
   //     suspension state.
   // |context|: The BrowserContext which owns the extension process.
   // |request|: The Mojo connection request used for binding.
   static void BindToRequest(
-      const std::string& extension_id,
+      const extensions::Extension* extension,
       content::BrowserContext* context,
       mojo::InterfaceRequest<interfaces::MediaRouter> request);
 
@@ -182,10 +183,10 @@
 
   // Binds |this| to a Mojo interface request, so that clients can acquire a
   // handle to a MediaRouterMojoImpl instance via the Mojo service connector.
-  // Stores the |extension_id| of the component extension.
+  // Stores the ID of |extension| in |media_route_provider_extension_id_|.
   void BindToMojoRequest(
       mojo::InterfaceRequest<interfaces::MediaRouter> request,
-      const std::string& extension_id);
+      const extensions::Extension& extension);
 
   // Enqueues a closure for later execution by ExecutePendingRequests().
   void EnqueueTask(const base::Closure& closure);
@@ -370,12 +371,16 @@
   // The last reported sink availability from the media route provider manager.
   interfaces::MediaRouter::SinkAvailability availability_;
 
-  int wakeup_attempt_count_;
+  int wakeup_attempt_count_ = 0;
 
   // Records the current reason the extension is being woken up.  Is set to
   // MediaRouteProviderWakeReason::TOTAL_COUNT if there is no pending reason.
   MediaRouteProviderWakeReason current_wake_reason_;
 
+  // A flag to ensure that we record the provider version once, during the
+  // initial event page wakeup attempt.
+  bool provider_version_was_recorded_ = false;
+
   base::WeakPtrFactory<MediaRouterMojoImpl> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaRouterMojoImpl);
diff --git a/chrome/browser/media/router/media_router_mojo_impl_unittest.cc b/chrome/browser/media/router/media_router_mojo_impl_unittest.cc
index 0cd285a..469da5d1 100644
--- a/chrome/browser/media/router/media_router_mojo_impl_unittest.cc
+++ b/chrome/browser/media/router/media_router_mojo_impl_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/run_loop.h"
 #include "base/synchronization/waitable_event.h"
@@ -26,9 +27,14 @@
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/version_info/version_info.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/process_manager.h"
 #include "extensions/browser/process_manager_factory.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/extension_builder.h"
+#include "extensions/common/test_util.h"
+#include "extensions/common/value_builder.h"
 #include "media/base/gmock_callback_support.h"
 #include "mojo/message_pump/message_pump_mojo.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -57,7 +63,6 @@
 
 const char kDescription[] = "description";
 const char kError[] = "error";
-const char kExtensionId[] = "extension1234";
 const char kMessage[] = "message";
 const char kSource[] = "source1";
 const char kSource2[] = "source2";
@@ -1208,14 +1213,21 @@
 class MediaRouterMojoExtensionTest : public ::testing::Test {
  public:
   MediaRouterMojoExtensionTest()
-    : process_manager_(nullptr),
-      message_loop_(mojo::common::MessagePumpMojo::Create())
-  {}
+      : process_manager_(nullptr),
+        message_loop_(mojo::common::MessagePumpMojo::Create()) {}
 
   ~MediaRouterMojoExtensionTest() override {}
 
  protected:
   void SetUp() override {
+    // Set the extension's version number to be identical to the browser's.
+    extension_ =
+        extensions::test_util::BuildExtension(extensions::ExtensionBuilder())
+            .MergeManifest(extensions::DictionaryBuilder()
+                               .Set("version", version_info::GetVersionNumber())
+                               .Build())
+            .Build();
+
     profile_.reset(new TestingProfile);
     // Set up a mock ProcessManager instance.
     extensions::ProcessManagerFactory::GetInstance()->SetTestingFactory(
@@ -1245,13 +1257,13 @@
         &mock_media_route_provider_,
         mojo::GetProxy(&media_route_provider_proxy_)));
     media_router_->BindToMojoRequest(mojo::GetProxy(&media_router_proxy_),
-                                     kExtensionId);
+                                     *extension_);
   }
 
   void ResetMediaRouteProvider() {
     binding_.reset();
     media_router_->BindToMojoRequest(mojo::GetProxy(&media_router_proxy_),
-                                     kExtensionId);
+                                     *extension_);
   }
 
   void RegisterMediaRouteProvider() {
@@ -1272,11 +1284,26 @@
                                         expected_count);
   }
 
+  void ExpectVersionBucketCount(MediaRouteProviderVersion version,
+                                int expected_count) {
+    histogram_tester_.ExpectBucketCount("MediaRouter.Provider.Version",
+                                        static_cast<int>(version),
+                                        expected_count);
+  }
+
+  void ExpectWakeupBucketCount(MediaRouteProviderWakeup wakeup,
+                               int expected_count) {
+    histogram_tester_.ExpectBucketCount("MediaRouter.Provider.Wakeup",
+                                        static_cast<int>(wakeup),
+                                        expected_count);
+  }
+
   scoped_ptr<MediaRouterMojoImpl> media_router_;
   RegisterMediaRouteProviderHandler provide_handler_;
   TestProcessManager* process_manager_;
   testing::StrictMock<MockMediaRouteProvider> mock_media_route_provider_;
   interfaces::MediaRouterPtr media_router_proxy_;
+  scoped_refptr<extensions::Extension> extension_;
 
  private:
   scoped_ptr<TestingProfile> profile_;
@@ -1304,7 +1331,7 @@
       .WillOnce(InvokeWithoutArgs([&run_loop]() {
                   run_loop.Quit();
                 }));
-  EXPECT_CALL(*process_manager_, IsEventPageSuspended(kExtensionId))
+  EXPECT_CALL(*process_manager_, IsEventPageSuspended(extension_->id()))
       .WillOnce(Return(false));
   EXPECT_CALL(mock_media_route_provider_, DetachRoute(mojo::String(kRouteId)))
       .WillOnce(InvokeWithoutArgs([&run_loop2]() {
@@ -1317,14 +1344,13 @@
   base::RunLoop run_loop3;
   // Extension is suspended and re-awoken.
   ResetMediaRouteProvider();
-  EXPECT_CALL(*process_manager_, IsEventPageSuspended(kExtensionId))
+  EXPECT_CALL(*process_manager_, IsEventPageSuspended(extension_->id()))
       .WillOnce(Return(true));
-  EXPECT_CALL(*process_manager_, WakeEventPage(kExtensionId, _))
-      .WillOnce(testing::DoAll(media::RunCallback<1>(true),
-                               InvokeWithoutArgs([&run_loop3]() {
-                                 run_loop3.Quit();
-                               }),
-                               Return(true)));
+  EXPECT_CALL(*process_manager_, WakeEventPage(extension_->id(), _))
+      .WillOnce(testing::DoAll(
+          media::RunCallback<1>(true),
+          InvokeWithoutArgs([&run_loop3]() { run_loop3.Quit(); }),
+          Return(true)));
   media_router_->DetachRoute(kRouteId2);
   run_loop3.Run();
 
@@ -1335,7 +1361,7 @@
       .WillOnce(InvokeWithoutArgs([&run_loop4]() {
                   run_loop4.Quit();
                 }));
-  EXPECT_CALL(*process_manager_, IsEventPageSuspended(kExtensionId))
+  EXPECT_CALL(*process_manager_, IsEventPageSuspended(extension_->id()))
       .WillOnce(Return(false));
   EXPECT_CALL(mock_media_route_provider_, DetachRoute(mojo::String(kRouteId2)))
       .WillOnce(InvokeWithoutArgs([&run_loop5]() {
@@ -1346,6 +1372,9 @@
   run_loop4.Run();
   run_loop5.Run();
   ExpectWakeReasonBucketCount(MediaRouteProviderWakeReason::DETACH_ROUTE, 1);
+  ExpectWakeupBucketCount(MediaRouteProviderWakeup::SUCCESS, 1);
+  ExpectVersionBucketCount(MediaRouteProviderVersion::SAME_VERSION_AS_CHROME,
+                           1);
 }
 
 TEST_F(MediaRouterMojoExtensionTest, AttemptedWakeupTooManyTimes) {
@@ -1353,17 +1382,18 @@
 
   // DetachRoute is called while extension is suspended. It should be queued.
   // Schedule a component extension wakeup.
-  EXPECT_CALL(*process_manager_, IsEventPageSuspended(kExtensionId))
+  EXPECT_CALL(*process_manager_, IsEventPageSuspended(extension_->id()))
       .WillOnce(Return(true));
-  EXPECT_CALL(*process_manager_, WakeEventPage(kExtensionId, _))
+  EXPECT_CALL(*process_manager_, WakeEventPage(extension_->id(), _))
       .WillOnce(testing::DoAll(media::RunCallback<1>(true), Return(true)));
   media_router_->DetachRoute(kRouteId);
   EXPECT_EQ(1u, media_router_->pending_requests_.size());
   ExpectWakeReasonBucketCount(MediaRouteProviderWakeReason::DETACH_ROUTE, 1);
+  ExpectWakeupBucketCount(MediaRouteProviderWakeup::SUCCESS, 1);
 
   // Media route provider fails to connect to media router before extension is
   // suspended again, and |OnConnectionError| is invoked. Retry the wakeup.
-  EXPECT_CALL(*process_manager_, WakeEventPage(kExtensionId, _))
+  EXPECT_CALL(*process_manager_, WakeEventPage(extension_->id(), _))
       .Times(MediaRouterMojoImpl::kMaxWakeupAttemptCount - 1)
       .WillRepeatedly(
           testing::DoAll(media::RunCallback<1>(true), Return(true)));
@@ -1376,14 +1406,17 @@
   EXPECT_TRUE(media_router_->pending_requests_.empty());
   ExpectWakeReasonBucketCount(MediaRouteProviderWakeReason::CONNECTION_ERROR,
                               MediaRouterMojoImpl::kMaxWakeupAttemptCount - 1);
+  ExpectWakeupBucketCount(MediaRouteProviderWakeup::ERROR_TOO_MANY_RETRIES, 1);
 
   // Requests that comes in after queue is drained should be queued.
-  EXPECT_CALL(*process_manager_, IsEventPageSuspended(kExtensionId))
+  EXPECT_CALL(*process_manager_, IsEventPageSuspended(extension_->id()))
       .WillOnce(Return(true));
-  EXPECT_CALL(*process_manager_, WakeEventPage(kExtensionId, _))
+  EXPECT_CALL(*process_manager_, WakeEventPage(extension_->id(), _))
       .WillOnce(testing::DoAll(media::RunCallback<1>(true), Return(true)));
   media_router_->DetachRoute(kRouteId);
   EXPECT_EQ(1u, media_router_->pending_requests_.size());
+  ExpectVersionBucketCount(MediaRouteProviderVersion::SAME_VERSION_AS_CHROME,
+                           1);
 }
 
 TEST_F(MediaRouterMojoExtensionTest, WakeupFailedDrainsQueue) {
@@ -1391,10 +1424,10 @@
 
   // DetachRoute is called while extension is suspended. It should be queued.
   // Schedule a component extension wakeup.
-  EXPECT_CALL(*process_manager_, IsEventPageSuspended(kExtensionId))
+  EXPECT_CALL(*process_manager_, IsEventPageSuspended(extension_->id()))
       .WillOnce(Return(true));
   base::Callback<void(bool)> extension_wakeup_callback;
-  EXPECT_CALL(*process_manager_, WakeEventPage(kExtensionId, _))
+  EXPECT_CALL(*process_manager_, WakeEventPage(extension_->id(), _))
       .WillOnce(
           testing::DoAll(SaveArg<1>(&extension_wakeup_callback), Return(true)));
   media_router_->DetachRoute(kRouteId);
@@ -1406,13 +1439,16 @@
   EXPECT_TRUE(media_router_->pending_requests_.empty());
 
   // Requests that comes in after queue is drained should be queued.
-  EXPECT_CALL(*process_manager_, IsEventPageSuspended(kExtensionId))
+  EXPECT_CALL(*process_manager_, IsEventPageSuspended(extension_->id()))
       .WillOnce(Return(true));
-  EXPECT_CALL(*process_manager_, WakeEventPage(kExtensionId, _))
+  EXPECT_CALL(*process_manager_, WakeEventPage(extension_->id(), _))
       .WillOnce(testing::DoAll(media::RunCallback<1>(true), Return(true)));
   media_router_->DetachRoute(kRouteId);
   EXPECT_EQ(1u, media_router_->pending_requests_.size());
   ExpectWakeReasonBucketCount(MediaRouteProviderWakeReason::DETACH_ROUTE, 1);
+  ExpectWakeupBucketCount(MediaRouteProviderWakeup::ERROR_UNKNOWN, 1);
+  ExpectVersionBucketCount(MediaRouteProviderVersion::SAME_VERSION_AS_CHROME,
+                           1);
 }
 
 TEST_F(MediaRouterMojoExtensionTest, DropOldestPendingRequest) {
@@ -1437,7 +1473,7 @@
       .WillOnce(InvokeWithoutArgs([&run_loop]() {
                   run_loop.Quit();
                 }));
-  EXPECT_CALL(*process_manager_, IsEventPageSuspended(kExtensionId));
+  EXPECT_CALL(*process_manager_, IsEventPageSuspended(extension_->id()));
   EXPECT_CALL(mock_media_route_provider_, DetachRoute(mojo::String(kRouteId2)))
       .Times(kMaxPendingRequests)
       .WillRepeatedly(InvokeWithoutArgs([&run_loop2, &count]() {
@@ -1447,6 +1483,8 @@
   RegisterMediaRouteProvider();
   run_loop.Run();
   run_loop2.Run();
+  ExpectVersionBucketCount(MediaRouteProviderVersion::SAME_VERSION_AS_CHROME,
+                           1);
 }
 
 }  // namespace media_router
diff --git a/chrome/browser/media/router/media_router_mojo_test.cc b/chrome/browser/media/router/media_router_mojo_test.cc
index 1b8869f..e5cd8144 100644
--- a/chrome/browser/media/router/media_router_mojo_test.cc
+++ b/chrome/browser/media/router/media_router_mojo_test.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "extensions/common/test_util.h"
 #include "mojo/message_pump/message_pump_mojo.h"
 
 namespace media_router {
@@ -27,10 +28,10 @@
 }
 
 MediaRouterMojoTest::MediaRouterMojoTest()
-    : extension_id_("ext-123"),
-      mock_media_router_(new MediaRouterMojoImpl(&mock_event_page_tracker_)),
+    : mock_media_router_(new MediaRouterMojoImpl(&mock_event_page_tracker_)),
       message_loop_(mojo::common::MessagePumpMojo::Create()) {
   mock_media_router_->set_instance_id_for_test(kInstanceId);
+  extension_ = extensions::test_util::CreateEmptyExtension();
 }
 
 MediaRouterMojoTest::~MediaRouterMojoTest() {
@@ -39,7 +40,7 @@
 void MediaRouterMojoTest::ConnectProviderManagerService() {
   // Bind the |media_route_provider| interface to |media_route_provider_|.
   auto request = mojo::GetProxy(&media_router_proxy_);
-  mock_media_router_->BindToMojoRequest(std::move(request), extension_id_);
+  mock_media_router_->BindToMojoRequest(std::move(request), *extension_);
 
   // Bind the Mojo MediaRouter interface used by |mock_media_router_| to
   // |mock_media_route_provider_service_|.
@@ -53,7 +54,7 @@
 }
 
 void MediaRouterMojoTest::SetUp() {
-  ON_CALL(mock_event_page_tracker_, IsEventPageSuspended(extension_id_))
+  ON_CALL(mock_event_page_tracker_, IsEventPageSuspended(extension_id()))
       .WillByDefault(testing::Return(false));
   ConnectProviderManagerService();
   message_loop_.RunUntilIdle();
diff --git a/chrome/browser/media/router/media_router_mojo_test.h b/chrome/browser/media/router/media_router_mojo_test.h
index e56aa7c..de05a43 100644
--- a/chrome/browser/media/router/media_router_mojo_test.h
+++ b/chrome/browser/media/router/media_router_mojo_test.h
@@ -8,11 +8,13 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
 #include "chrome/browser/media/router/media_router_mojo_impl.h"
 #include "chrome/browser/media/router/mock_media_router.h"
 #include "chrome/browser/media/router/test_helper.h"
 #include "chrome/test/base/testing_profile.h"
+#include "extensions/common/extension.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -36,7 +38,7 @@
 
   void ConnectProviderManagerService();
 
-  const std::string& extension_id() const { return extension_id_; }
+  const std::string& extension_id() const { return extension_->id(); }
 
   MediaRouterMojoImpl* router() const { return mock_media_router_.get(); }
 
@@ -48,7 +50,7 @@
   media_router::interfaces::MediaRouterPtr media_router_proxy_;
 
  private:
-  std::string extension_id_;
+  scoped_refptr<extensions::Extension> extension_;
   scoped_ptr<MediaRouterMojoImpl> mock_media_router_;
   scoped_ptr<mojo::Binding<interfaces::MediaRouteProvider>> binding_;
   base::MessageLoop message_loop_;
diff --git a/chrome/browser/metrics/chrome_metrics_service_accessor.h b/chrome/browser/metrics/chrome_metrics_service_accessor.h
index d7ae682..80332149 100644
--- a/chrome/browser/metrics/chrome_metrics_service_accessor.h
+++ b/chrome/browser/metrics/chrome_metrics_service_accessor.h
@@ -56,6 +56,10 @@
 class SRTFetcher;
 }
 
+namespace settings {
+class SystemHandler;
+}
+
 namespace speech {
 class ChromeSpeechRecognitionManagerDelegate;
 }
@@ -94,6 +98,7 @@
   friend class safe_browsing::DownloadSBClient;
   friend class safe_browsing::SafeBrowsingService;
   friend class safe_browsing::SafeBrowsingUIManager;
+  friend class settings::SystemHandler;
 
   FRIEND_TEST_ALL_PREFIXES(ChromeMetricsServiceAccessorTest,
                            MetricsReportingEnabled);
diff --git a/chrome/browser/net/chrome_network_delegate_unittest.cc b/chrome/browser/net/chrome_network_delegate_unittest.cc
index 868e53d..b6feec3 100644
--- a/chrome/browser/net/chrome_network_delegate_unittest.cc
+++ b/chrome/browser/net/chrome_network_delegate_unittest.cc
@@ -499,10 +499,7 @@
   EXPECT_FALSE(network_delegate_->CanEnablePrivacyMode(kBlockedSite,
                                                        kEmptyFirstPartySite));
 
-  cookie_settings_->SetCookieSetting(
-      ContentSettingsPattern::FromURL(kBlockedSite),
-      ContentSettingsPattern::Wildcard(),
-      CONTENT_SETTING_BLOCK);
+  cookie_settings_->SetCookieSetting(kBlockedSite, CONTENT_SETTING_BLOCK);
   EXPECT_TRUE(network_delegate_->CanEnablePrivacyMode(kBlockedSite,
                                                       kEmptyFirstPartySite));
 }
@@ -530,10 +527,8 @@
   EXPECT_FALSE(network_delegate_->CanEnablePrivacyMode(kAllowedSite,
                                                        kBlockedFirstPartySite));
 
-  cookie_settings_->SetCookieSetting(
-      ContentSettingsPattern::FromURL(kBlockedFirstPartySite),
-      ContentSettingsPattern::Wildcard(),
-      CONTENT_SETTING_BLOCK);
+  cookie_settings_->SetCookieSetting(kBlockedFirstPartySite,
+                                     CONTENT_SETTING_BLOCK);
   // Privacy mode is disabled as kAllowedSite is still getting cookies
   EXPECT_FALSE(network_delegate_->CanEnablePrivacyMode(kAllowedSite,
                                                        kBlockedFirstPartySite));
diff --git a/chrome/browser/resources/chromeos/login/screen_unrecoverable_cryptohome_error.html b/chrome/browser/resources/chromeos/login/screen_unrecoverable_cryptohome_error.html
index 7901074..c878c48 100644
--- a/chrome/browser/resources/chromeos/login/screen_unrecoverable_cryptohome_error.html
+++ b/chrome/browser/resources/chromeos/login/screen_unrecoverable_cryptohome_error.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://oobe/custom_elements.html">
 
-<div id="unrecoverable-cryptohome-error" class="step faded no-logo" hidden>
+<div id="unrecoverable-cryptohome-error" class="step faded no-logo"
+    aria-live="polite" hidden>
   <unrecoverable-cryptohome-error-card id="unrecoverable-cryptohome-error-card">
   </unrecoverable-cryptohome-error-card>
   <div id="unrecoverable-cryptohome-error-busy" class="step-loading" hidden>
diff --git a/chrome/browser/resources/md_downloads/crisper.js b/chrome/browser/resources/md_downloads/crisper.js
index 9ff07dea..352b5bf7 100644
--- a/chrome/browser/resources/md_downloads/crisper.js
+++ b/chrome/browser/resources/md_downloads/crisper.js
@@ -1,3 +1,38 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview PromiseResolver is a helper class that allows creating a
+ * Promise that will be fulfilled (resolved or rejected) some time later.
+ *
+ * Example:
+ *  var resolver = new PromiseResolver();
+ *  resolver.promise.then(function(result) {
+ *    console.log('resolved with', result);
+ *  });
+ *  ...
+ *  ...
+ *  resolver.resolve({hello: 'world'});
+ */
+
+/**
+ * @constructor @struct
+ * @template T
+ */
+function PromiseResolver() {
+  /** @type {function(T): void} */
+  this.resolve;
+
+  /** @type {function(*=): void} */
+  this.reject;
+
+  /** @type {!Promise<T>} */
+  this.promise = new Promise(function(resolve, reject) {
+    this.resolve = resolve;
+    this.reject = reject;
+  }.bind(this));
+};
 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
@@ -13,7 +48,7 @@
 var WebUIListener;
 
 /** Platform, package, object property, and Event support. **/
-var cr = function() {
+var cr = cr || function() {
   'use strict';
 
   /**
@@ -25,6 +60,8 @@
    * @param {*=} opt_object The object to expose at the end of the path.
    * @param {Object=} opt_objectToExportTo The object to add the path to;
    *     default is {@code global}.
+   * @return {!Object} The last object exported (i.e. exportPath('cr.ui')
+   *     returns a reference to the ui property of window.cr).
    * @private
    */
   function exportPath(name, opt_object, opt_objectToExportTo) {
@@ -42,7 +79,7 @@
       }
     }
     return cur;
-  };
+  }
 
   /**
    * Fires a property change event on the target.
@@ -318,9 +355,9 @@
   /**
    * The mapping used by the sendWithPromise mechanism to tie the Promise
    * returned to callers with the corresponding WebUI response. The mapping is
-   * from ID to the Promise resolver function; the ID is generated by
+   * from ID to the PromiseResolver helper; the ID is generated by
    * sendWithPromise and is unique across all invocations of said method.
-   * @type {!Object<!Function>}
+   * @type {!Object<!PromiseResolver>}
    */
   var chromeSendResolverMap = {};
 
@@ -334,12 +371,17 @@
    * supply any number of other arguments that will be included in the response.
    * @param {string} id The unique ID identifying the Promise this response is
    *     tied to.
+   * @param {boolean} isSuccess Whether the request was successful.
    * @param {*} response The response as sent from C++.
    */
-  function webUIResponse(id, response) {
-    var resolverFn = chromeSendResolverMap[id];
+  function webUIResponse(id, isSuccess, response) {
+    var resolver = chromeSendResolverMap[id];
     delete chromeSendResolverMap[id];
-    resolverFn(response);
+
+    if (isSuccess)
+      resolver.resolve(response);
+    else
+      resolver.reject(response);
   }
 
   /**
@@ -352,11 +394,11 @@
    */
   function sendWithPromise(methodName, var_args) {
     var args = Array.prototype.slice.call(arguments, 1);
-    return new Promise(function(resolve, reject) {
-      var id = methodName + '_' + createUid();
-      chromeSendResolverMap[id] = resolve;
-      chrome.send(methodName, [id].concat(args));
-    });
+    var promiseResolver = new PromiseResolver();
+    var id = methodName + '_' + createUid();
+    chromeSendResolverMap[id] = promiseResolver;
+    chrome.send(methodName, [id].concat(args));
+    return promiseResolver.promise;
   }
 
   /**
@@ -1470,6 +1512,15 @@
   if (original.length <= maxLength)
     return original;
   return original.substring(0, maxLength - 1) + '\u2026';
+}
+
+/**
+ * Quote a string so it can be used in a regular expression.
+ * @param {string} str The source string.
+ * @return {string} The escaped string.
+ */
+function quoteString(str) {
+  return str.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, '\\$1');
 };
 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
@@ -1840,11 +1891,13 @@
    * size or hidden state of their children) and "resizables" (elements that need to be
    * notified when they are resized or un-hidden by their parents in order to take
    * action on their new measurements).
+   * 
    * Elements that perform measurement should add the `IronResizableBehavior` behavior to
    * their element definition and listen for the `iron-resize` event on themselves.
    * This event will be fired when they become showing after having been hidden,
    * when they are resized explicitly by another resizable, or when the window has been
    * resized.
+   * 
    * Note, the `iron-resize` event is non-bubbling.
    *
    * @polymerBehavior Polymer.IronResizableBehavior
@@ -2508,9 +2561,9 @@
         // Support element id references
         if (typeof scrollTarget === 'string') {
 
-          var ownerRoot = Polymer.dom(this).getOwnerRoot();
-          this.scrollTarget = (ownerRoot && ownerRoot.$) ?
-              ownerRoot.$[scrollTarget] : Polymer.dom(this.ownerDocument).querySelector('#' + scrollTarget);
+          var host = this.domHost;
+          this.scrollTarget = host && host.$ ? host.$[scrollTarget] : 
+              Polymer.dom(this.ownerDocument).querySelector('#' + scrollTarget);
 
         } else if (this._scrollHandler) {
 
@@ -2609,15 +2662,15 @@
      * Scrolls the content to a particular place.
      *
      * @method scroll
-     * @param {number} top The top position
      * @param {number} left The left position
+     * @param {number} top The top position
      */
-    scroll: function(top, left) {
+    scroll: function(left, top) {
        if (this.scrollTarget === this._doc) {
-        window.scrollTo(top, left);
+        window.scrollTo(left, top);
       } else if (this._isValidScrollTarget()) {
-        this.scrollTarget.scrollTop = top;
         this.scrollTarget.scrollLeft = left;
+        this.scrollTarget.scrollTop = top;
       }
     },
 
@@ -2774,7 +2827,7 @@
     _ratio: 0.5,
 
     /**
-     * The padding-top value of the `scroller` element
+     * The padding-top value for the list.
      */
     _scrollerPaddingTop: 0,
 
@@ -2784,21 +2837,6 @@
     _scrollPosition: 0,
 
     /**
-     * The number of tiles in the DOM.
-     */
-    _physicalCount: 0,
-
-    /**
-     * The k-th tile that is at the top of the scrolling list.
-     */
-    _physicalStart: 0,
-
-    /**
-     * The k-th tile that is at the bottom of the scrolling list.
-     */
-    _physicalEnd: 0,
-
-    /**
      * The sum of the heights of all the tiles in the DOM.
      */
     _physicalSize: 0,
@@ -2825,11 +2863,6 @@
     _virtualCount: 0,
 
     /**
-     * The n-th item rendered in the `_physicalStart` tile.
-     */
-    _virtualStartVal: 0,
-
-    /**
      * A map between an item key and its physical item index
      */
     _physicalIndexForKey: null,
@@ -2875,7 +2908,6 @@
      */
     _lastVisibleIndexVal: null,
 
-
     /**
      * A Polymer collection for the items.
      * @type {?Polymer.Collection}
@@ -2899,9 +2931,14 @@
     _maxPages: 3,
 
     /**
-     * The currently focused item index.
+     * The currently focused physical item.
      */
-    _focusedIndex: 0,
+    _focusedItem: null,
+
+    /**
+     * The index of the `_focusedItem`.
+     */
+    _focusedIndex: -1,
 
     /**
      * The the item that is focused if it is moved offscreen.
@@ -2937,6 +2974,20 @@
     },
 
     /**
+     * The height of the physical content that isn't on the screen.
+     */
+    get _hiddenContentSize() {
+      return this._physicalSize - this._viewportSize;
+    },
+
+    /**
+     * The maximum scroll top value.
+     */
+    get _maxScrollTop() {
+      return this._estScrollHeight - this._viewportSize + this._scrollerPaddingTop;
+    },
+
+    /**
      * The lowest n-th value for an item such that it can be rendered in `_physicalStart`.
      */
     _minVirtualStart: 0,
@@ -2949,41 +3000,54 @@
     },
 
     /**
-     * The height of the physical content that isn't on the screen.
+     * The n-th item rendered in the `_physicalStart` tile.
      */
-    get _hiddenContentSize() {
-      return this._physicalSize - this._viewportSize;
-    },
+    _virtualStartVal: 0,
 
-    /**
-     * The maximum scroll top value.
-     */
-    get _maxScrollTop() {
-      return this._estScrollHeight - this._viewportSize;
-    },
-
-    /**
-     * Sets the n-th item rendered in `_physicalStart`
-     */
     set _virtualStart(val) {
-      // clamp the value so that _minVirtualStart <= val <= _maxVirtualStart
       this._virtualStartVal = Math.min(this._maxVirtualStart, Math.max(this._minVirtualStart, val));
-      if (this._physicalCount === 0)  {
-        this._physicalStart = 0;
-        this._physicalEnd = 0;
-      } else {
-        this._physicalStart = this._virtualStartVal % this._physicalCount;
-        this._physicalEnd = (this._physicalStart + this._physicalCount - 1) % this._physicalCount;
-      }
+    },
+
+    get _virtualStart() {
+      return this._virtualStartVal || 0;
     },
 
     /**
-     * Gets the n-th item rendered in `_physicalStart`
+     * The k-th tile that is at the top of the scrolling list.
      */
-    get _virtualStart() {
-      return this._virtualStartVal;
+    _physicalStartVal: 0,
+
+    set _physicalStart(val) {
+      this._physicalStartVal = val % this._physicalCount;
+      if (this._physicalStartVal < 0) {
+        this._physicalStartVal = this._physicalCount + this._physicalStartVal;
+      }
+      this._physicalEnd = (this._physicalStart + this._physicalCount - 1) % this._physicalCount;
     },
 
+    get _physicalStart() {
+      return this._physicalStartVal || 0;
+    },
+
+    /**
+     * The number of tiles in the DOM.
+     */
+    _physicalCountVal: 0,
+
+    set _physicalCount(val) {
+      this._physicalCountVal = val;
+      this._physicalEnd = (this._physicalStart + this._physicalCount - 1) % this._physicalCount;
+    },
+
+    get _physicalCount() {
+      return this._physicalCountVal;
+    },
+
+    /**
+     * The k-th tile that is at the bottom of the scrolling list.
+     */
+    _physicalEnd: 0,
+
     /**
      * An optimal physical size such that we will have enough physical items
      * to fill up the viewport and recycle when the user scrolls.
@@ -3009,12 +3073,11 @@
      */
     get firstVisibleIndex() {
       if (this._firstVisibleIndexVal === null) {
-        var physicalOffset = this._physicalTop;
+        var physicalOffset = this._physicalTop + this._scrollerPaddingTop;
 
         this._firstVisibleIndexVal = this._iterateItems(
           function(pidx, vidx) {
             physicalOffset += this._physicalSizes[pidx];
-
             if (physicalOffset > this._scrollPosition) {
               return vidx;
             }
@@ -3035,14 +3098,18 @@
         this._iterateItems(function(pidx, vidx) {
           physicalOffset += this._physicalSizes[pidx];
 
-          if(physicalOffset <= this._scrollBottom) {
-              this._lastVisibleIndexVal = vidx;
+          if (physicalOffset <= this._scrollBottom) {
+            this._lastVisibleIndexVal = vidx;
           }
         });
       }
       return this._lastVisibleIndexVal;
     },
 
+    get _defaultScrollTarget() {
+      return this;
+    },
+
     ready: function() {
       this.addEventListener('focus', this._didFocus.bind(this), true);
     },
@@ -3056,10 +3123,6 @@
       this._itemsRendered = false;
     },
 
-    get _defaultScrollTarget() {
-      return this;
-    },
-
     /**
      * Set the overflow property if this element has its own scrolling region
      */
@@ -3075,8 +3138,9 @@
      * @method updateViewportBoundaries
      */
     updateViewportBoundaries: function() {
-      var scrollerStyle = window.getComputedStyle(this.scrollTarget);
-      this._scrollerPaddingTop = parseInt(scrollerStyle['padding-top'], 10);
+      this._scrollerPaddingTop = this.scrollTarget === this ? 0 :
+          parseInt(window.getComputedStyle(this)['padding-top'], 10);
+
       this._viewportSize = this._scrollTargetHeight;
     },
 
@@ -3086,12 +3150,10 @@
      */
     _scrollHandler: function() {
       // clamp the `scrollTop` value
-      // IE 10|11 scrollTop may go above `_maxScrollTop`
-      // iOS `scrollTop` may go below 0 and above `_maxScrollTop`
       var scrollTop = Math.max(0, Math.min(this._maxScrollTop, this._scrollTop));
+      var delta = scrollTop - this._scrollPosition;
       var tileHeight, tileTop, kth, recycledTileSet, scrollBottom, physicalBottom;
       var ratio = this._ratio;
-      var delta = scrollTop - this._scrollPosition;
       var recycledTiles = 0;
       var hiddenContentSize = this._hiddenContentSize;
       var currentRatio = ratio;
@@ -3100,7 +3162,7 @@
       // track the last `scrollTop`
       this._scrollPosition = scrollTop;
 
-      // clear cached visible index
+      // clear cached visible indexes
       this._firstVisibleIndexVal = null;
       this._lastVisibleIndexVal = null;
 
@@ -3187,6 +3249,7 @@
         }
       } else {
         this._virtualStart = this._virtualStart + recycledTiles;
+        this._physicalStart = this._physicalStart + recycledTiles;
         this._update(recycledTileSet, movingUp);
       }
     },
@@ -3198,11 +3261,7 @@
      */
     _update: function(itemSet, movingUp) {
       // manage focus
-      if (this._isIndexRendered(this._focusedIndex)) {
-        this._restoreFocusedItem();
-      } else {
-        this._createFocusBackfillItem();
-      }
+      this._manageFocus();
       // update models
       this._assignModels(itemSet);
       // measure heights
@@ -3269,7 +3328,6 @@
      * Increases the pool size.
      */
     _increasePool: function(missingItems) {
-      // limit the size
       var nextPhysicalCount = Math.min(
           this._physicalCount + missingItems,
           this._virtualCount - this._virtualStart,
@@ -3278,14 +3336,24 @@
       var prevPhysicalCount = this._physicalCount;
       var delta = nextPhysicalCount - prevPhysicalCount;
 
-      if (delta > 0) {
-        [].push.apply(this._physicalItems, this._createPool(delta));
-        [].push.apply(this._physicalSizes, new Array(delta));
-
-        this._physicalCount = prevPhysicalCount + delta;
-        // tail call
-        return this._update();
+      if (delta <= 0) {
+        return;
       }
+
+      [].push.apply(this._physicalItems, this._createPool(delta));
+      [].push.apply(this._physicalSizes, new Array(delta));
+
+      this._physicalCount = prevPhysicalCount + delta;
+
+      // update the physical start if we need to preserve the model of the focused item.
+      // In this situation, the focused item is currently rendered and its model would
+      // have changed after increasing the pool if the physical start remained unchanged.
+      if (this._physicalStart > this._physicalEnd &&
+          this._isIndexRendered(this._focusedIndex) &&
+          this._getPhysicalIndex(this._focusedIndex) < this._physicalEnd) {
+        this._physicalStart = this._physicalStart + delta;
+      }
+      this._update();
     },
 
     /**
@@ -3374,27 +3442,36 @@
 
     /**
      * Called as a side effect of a host items.<key>.<path> path change,
-     * responsible for notifying item.<path> changes to row for key.
+     * responsible for notifying item.<path> changes.
      */
     _forwardItemPath: function(path, value) {
-      if (this._physicalIndexForKey) {
-        var dot = path.indexOf('.');
-        var key = path.substring(0, dot < 0 ? path.length : dot);
-        var idx = this._physicalIndexForKey[key];
-        var row = this._physicalItems[idx];
+      if (!this._physicalIndexForKey) {
+        return;
+      }
+      var inst;
+      var dot = path.indexOf('.');
+      var key = path.substring(0, dot < 0 ? path.length : dot);
+      var idx = this._physicalIndexForKey[key];
+      var el = this._physicalItems[idx];
 
-        if (idx === this._focusedIndex && this._offscreenFocusedItem) {
-          row = this._offscreenFocusedItem;
-        }
-        if (row) {
-          var inst = row._templateInstance;
-          if (dot >= 0) {
-            path = this.as + '.' + path.substring(dot+1);
-            inst.notifyPath(path, value, true);
-          } else {
-            inst[this.as] = value;
-          }
-        }
+
+      if (idx === this._focusedIndex && this._offscreenFocusedItem) {
+        el = this._offscreenFocusedItem;
+      }
+      if (!el) {
+        return;
+      }
+        
+      inst = el._templateInstance;
+
+      if (inst.__key__ !== key) {
+        return;
+      }
+      if (dot >= 0) {
+        path = this.as + '.' + path.substring(dot+1);
+        inst.notifyPath(path, value, true);
+      } else {
+        inst[this.as] = value;
       }
     },
 
@@ -3404,19 +3481,15 @@
      */
     _itemsChanged: function(change) {
       if (change.path === 'items') {
-
-        this._restoreFocusedItem();
-        // render the new set
-        this._itemsRendered = false;
-        // update the whole set
+        // reset items
         this._virtualStart = 0;
         this._physicalTop = 0;
         this._virtualCount = this.items ? this.items.length : 0;
-        this._focusedIndex = 0;
         this._collection = this.items ? Polymer.Collection.get(this.items) : null;
         this._physicalIndexForKey = {};
 
         this._resetScrollPosition(0);
+        this._removeFocusedItem();
 
         // create the initial physical items
         if (!this._physicalItems) {
@@ -3424,47 +3497,50 @@
           this._physicalItems = this._createPool(this._physicalCount);
           this._physicalSizes = new Array(this._physicalCount);
         }
-        this._debounceTemplate(this._render);
+
+        this._physicalStart = 0;
 
       } else if (change.path === 'items.splices') {
-        // render the new set
-        this._itemsRendered = false;
         this._adjustVirtualIndex(change.value.indexSplices);
         this._virtualCount = this.items ? this.items.length : 0;
 
-        this._debounceTemplate(this._render);
-
-        if (this._focusedIndex < 0 || this._focusedIndex >= this._virtualCount) {
-          this._focusedIndex = 0;
-        }
-        this._debounceTemplate(this._render);
-
       } else {
         // update a single item
         this._forwardItemPath(change.path.split('.').slice(1).join('.'), change.value);
+        return;
       }
+
+      this._itemsRendered = false;
+      this._debounceTemplate(this._render);
     },
 
     /**
      * @param {!Array<!PolymerSplice>} splices
      */
     _adjustVirtualIndex: function(splices) {
-      var i, splice, idx;
-
-      for (i = 0; i < splices.length; i++) {
-        splice = splices[i];
-
+      splices.forEach(function(splice) {
         // deselect removed items
-        splice.removed.forEach(this.$.selector.deselect, this.$.selector);
-
-        idx = splice.index;
+        splice.removed.forEach(this._removeItem, this);
         // We only need to care about changes happening above the current position
-        if (idx >= this._virtualStart) {
-          break;
-        }
+        if (splice.index < this._virtualStart) {
+          var delta = Math.max(
+              splice.addedCount - splice.removed.length,
+              splice.index - this._virtualStart);
 
-        this._virtualStart = this._virtualStart +
-            Math.max(splice.addedCount - splice.removed.length, idx - this._virtualStart);
+          this._virtualStart = this._virtualStart + delta;
+
+          if (this._focusedIndex >= 0) {
+            this._focusedIndex = this._focusedIndex + delta;
+          }
+        }
+      }, this);
+    },
+
+    _removeItem: function(item) {
+      this.$.selector.deselect(item);
+      // remove the current focused item
+      if (this._focusedItem && this._focusedItem._templateInstance[this.as] === item) {
+        this._removeFocusedItem();
       }
     },
 
@@ -3517,19 +3593,18 @@
         var inst = el._templateInstance;
         var item = this.items && this.items[vidx];
 
-        if (item !== undefined && item !== null) {
+        if (item != null) {
           inst[this.as] = item;
           inst.__key__ = this._collection.getKey(item);
           inst[this.selectedAs] = /** @type {!ArraySelectorElement} */ (this.$.selector).isSelected(item);
           inst[this.indexAs] = vidx;
-          inst.tabIndex = vidx === this._focusedIndex ? 0 : -1;
-          el.removeAttribute('hidden');
+          inst.tabIndex = this._focusedIndex === vidx ? 0 : -1;
           this._physicalIndexForKey[inst.__key__] = pidx;
+          el.removeAttribute('hidden');
         } else {
           inst.__key__ = null;
           el.setAttribute('hidden', '');
         }
-
       }, itemSet);
     },
 
@@ -3577,10 +3652,8 @@
       var y = this._physicalTop;
 
       this._iterateItems(function(pidx) {
-
         this.translate3d(0, y + 'px', 0, this._physicalItems[pidx]);
         y += this._physicalSizes[pidx];
-
       });
     },
 
@@ -3628,7 +3701,6 @@
         this._scrollHeight = this._estScrollHeight;
       }
     },
-
     /**
      * Scroll to a specific item in the virtual list regardless
      * of the physical items in the DOM tree.
@@ -3643,12 +3715,13 @@
 
       Polymer.dom.flush();
 
-      var firstVisible = this.firstVisibleIndex;
       idx = Math.min(Math.max(idx, 0), this._virtualCount-1);
-
-      // start at the previous virtual item
-      // so we have a item above the first visible item
-      this._virtualStart = idx - 1;
+      // update the virtual start only when needed
+      if (!this._isIndexRendered(idx) || idx >= this._maxVirtualStart) {
+        this._virtualStart = idx - 1;
+      }
+      // manage focus
+      this._manageFocus();
       // assign new models
       this._assignModels();
       // measure the new sizes
@@ -3711,7 +3784,7 @@
       var key = this._collection.getKey(item);
       var pidx = this._physicalIndexForKey[key];
 
-      if (pidx !== undefined) {
+      if (pidx != null) {
         return this._physicalItems[pidx]._templateInstance;
       }
       return null;
@@ -3849,139 +3922,179 @@
       var key = this._collection.getKey(item);
       var pidx = this._physicalIndexForKey[key];
 
-      if (pidx !== undefined) {
+      if (pidx != null) {
         this._updateMetrics([pidx]);
         this._positionItems();
       }
     },
 
+    /**
+     * Creates a temporary backfill item in the rendered pool of physical items
+     * to replace the main focused item. The focused item has tabIndex = 0
+     * and might be currently focused by the user.
+     *
+     * This dynamic replacement helps to preserve the focus state.
+     */
+    _manageFocus: function() {
+      var fidx = this._focusedIndex;
+
+      if (fidx >= 0 && fidx < this._virtualCount) {
+        // if it's a valid index, check if that index is rendered
+        // in a physical item.
+        if (this._isIndexRendered(fidx)) {
+          this._restoreFocusedItem();
+        } else {
+          this._createFocusBackfillItem();
+        }
+      } else if (this._virtualCount > 0 && this._physicalCount > 0) {
+        // otherwise, assign the initial focused index.
+        this._focusedIndex = this._virtualStart;
+        this._focusedItem = this._physicalItems[this._physicalStart];
+      }
+    },
+
     _isIndexRendered: function(idx) {
       return idx >= this._virtualStart && idx <= this._virtualEnd;
     },
 
-    _getPhysicalItemForIndex: function(idx, force) {
-      if (!this._collection) {
-        return null;
-      }
-      if (!this._isIndexRendered(idx)) {
-        if (force) {
-          this.scrollToIndex(idx);
-          return this._getPhysicalItemForIndex(idx, false);
-        }
-        return null;
-      }
-      var item = this._getNormalizedItem(idx);
-      var physicalItem = this._physicalItems[this._physicalIndexForKey[this._collection.getKey(item)]];
+    _isIndexVisible: function(idx) {
+      return idx >= this.firstVisibleIndex && idx <= this.lastVisibleIndex;
+    },
 
-      return physicalItem || null;
+    _getPhysicalIndex: function(idx) {
+      return this._physicalIndexForKey[this._collection.getKey(this._getNormalizedItem(idx))];
     },
 
     _focusPhysicalItem: function(idx) {
-      this._restoreFocusedItem();
-
-      var physicalItem = this._getPhysicalItemForIndex(idx, true);
-      if (!physicalItem) {
+      if (idx < 0 || idx >= this._virtualCount) {
         return;
       }
+      this._restoreFocusedItem();
+      // scroll to index to make sure it's rendered
+      if (!this._isIndexRendered(idx)) {
+        this.scrollToIndex(idx);
+      }
+
+      var physicalItem = this._physicalItems[this._getPhysicalIndex(idx)];
       var SECRET = ~(Math.random() * 100);
       var model = physicalItem._templateInstance;
       var focusable;
 
+      // set a secret tab index
       model.tabIndex = SECRET;
-      // the focusable element could be the entire physical item
+      // check if focusable element is the physical item
       if (physicalItem.tabIndex === SECRET) {
        focusable = physicalItem;
       }
-      // the focusable element could be somewhere within the physical item
+      // search for the element which tabindex is bound to the secret tab index
       if (!focusable) {
         focusable = Polymer.dom(physicalItem).querySelector('[tabindex="' + SECRET + '"]');
       }
       // restore the tab index
       model.tabIndex = 0;
+      // focus the focusable element
+      this._focusedIndex = idx;
       focusable && focusable.focus();
     },
 
-    _restoreFocusedItem: function() {
-      if (!this._offscreenFocusedItem) {
-        return;
-      }
-      var item = this._getNormalizedItem(this._focusedIndex);
-      var pidx = this._physicalIndexForKey[this._collection.getKey(item)];
-
-      if (pidx !== undefined) {
-        this.translate3d(0, HIDDEN_Y, 0, this._physicalItems[pidx]);
-        this._physicalItems[pidx] = this._offscreenFocusedItem;
-      }
-      this._offscreenFocusedItem = null;
-    },
-
     _removeFocusedItem: function() {
-      if (!this._offscreenFocusedItem) {
-        return;
+      if (this._offscreenFocusedItem) {
+        Polymer.dom(this).removeChild(this._offscreenFocusedItem);
       }
-      Polymer.dom(this).removeChild(this._offscreenFocusedItem);
       this._offscreenFocusedItem = null;
       this._focusBackfillItem = null;
+      this._focusedItem = null;
+      this._focusedIndex = -1;
     },
 
     _createFocusBackfillItem: function() {
-      if (this._offscreenFocusedItem) {
+      var pidx, fidx = this._focusedIndex;
+      if (this._offscreenFocusedItem || fidx < 0) {
         return;
       }
-      var item = this._getNormalizedItem(this._focusedIndex);
-      var pidx = this._physicalIndexForKey[this._collection.getKey(item)];
-
-      this._offscreenFocusedItem = this._physicalItems[pidx];
-      this.translate3d(0, HIDDEN_Y, 0, this._offscreenFocusedItem);
-
       if (!this._focusBackfillItem) {
+        // create a physical item, so that it backfills the focused item.
         var stampedTemplate = this.stamp(null);
         this._focusBackfillItem = stampedTemplate.root.querySelector('*');
         Polymer.dom(this).appendChild(stampedTemplate.root);
       }
-      this._physicalItems[pidx] = this._focusBackfillItem;
+      // get the physical index for the focused index
+      pidx = this._getPhysicalIndex(fidx);
+
+      if (pidx != null) {
+        // set the offcreen focused physical item
+        this._offscreenFocusedItem = this._physicalItems[pidx];
+        // backfill the focused physical item
+        this._physicalItems[pidx] = this._focusBackfillItem;
+        // hide the focused physical
+        this.translate3d(0, HIDDEN_Y, 0, this._offscreenFocusedItem);
+      }
+    },
+
+    _restoreFocusedItem: function() {
+      var pidx, fidx = this._focusedIndex;
+
+      if (!this._offscreenFocusedItem || this._focusedIndex < 0) {
+        return;
+      }
+      // assign models to the focused index
+      this._assignModels();
+      // get the new physical index for the focused index
+      pidx = this._getPhysicalIndex(fidx);
+
+      if (pidx != null) {
+        // flip the focus backfill
+        this._focusBackfillItem = this._physicalItems[pidx];
+        // restore the focused physical item
+        this._physicalItems[pidx] = this._offscreenFocusedItem;
+        // reset the offscreen focused item
+        this._offscreenFocusedItem = null;
+        // hide the physical item that backfills
+        this.translate3d(0, HIDDEN_Y, 0, this._focusBackfillItem);
+      }
     },
 
     _didFocus: function(e) {
       var targetModel = this.modelForElement(e.target);
+      var focusedModel = this._focusedItem ? this._focusedItem._templateInstance : null;
+      var hasOffscreenFocusedItem = this._offscreenFocusedItem !== null;
       var fidx = this._focusedIndex;
 
-      if (!targetModel) {
+      if (!targetModel || !focusedModel) {
         return;
       }
-      this._restoreFocusedItem();
-
-      if (this.modelForElement(this._offscreenFocusedItem) === targetModel) {
-        this.scrollToIndex(fidx);
+      if (focusedModel === targetModel) {
+        // if the user focused the same item, then bring it into view if it's not visible
+        if (!this._isIndexVisible(fidx)) {
+          this.scrollToIndex(fidx);
+        }
       } else {
+        this._restoreFocusedItem();
         // restore tabIndex for the currently focused item
-        this._getModelFromItem(this._getNormalizedItem(fidx)).tabIndex = -1;
+        focusedModel.tabIndex = -1;
         // set the tabIndex for the next focused item
         targetModel.tabIndex = 0;
-        fidx = /** @type {{index: number}} */(targetModel).index;
+        fidx = targetModel[this.indexAs];
         this._focusedIndex = fidx;
-        // bring the item into view
-        if (fidx < this.firstVisibleIndex || fidx > this.lastVisibleIndex) {
-          this.scrollToIndex(fidx);
-        } else {
+        this._focusedItem = this._physicalItems[this._getPhysicalIndex(fidx)];
+
+        if (hasOffscreenFocusedItem && !this._offscreenFocusedItem) {
           this._update();
         }
       }
     },
 
     _didMoveUp: function() {
-      this._focusPhysicalItem(Math.max(0, this._focusedIndex - 1));
+      this._focusPhysicalItem(this._focusedIndex - 1);
     },
 
     _didMoveDown: function() {
-      this._focusPhysicalItem(Math.min(this._virtualCount, this._focusedIndex + 1));
+      this._focusPhysicalItem(this._focusedIndex + 1);
     },
 
     _didEnter: function(e) {
-      // focus the currently focused physical item
       this._focusPhysicalItem(this._focusedIndex);
-      // toggle selection
-      this._selectionHandler(/** @type {{keyboardEvent: Event}} */(e.detail).keyboardEvent);
+      this._selectionHandler(e.detail.keyboardEvent);
     }
   });
 
@@ -4301,7 +4414,8 @@
          * @type {!Polymer.IronMeta}
          */
         _meta: {
-          value: Polymer.Base.create('iron-meta', {type: 'iconset'})
+          value: Polymer.Base.create('iron-meta', {type: 'iconset'}),
+          observer: '_updateIcon'
         }
 
       },
@@ -4326,7 +4440,14 @@
       /** @suppress {visibility} */
       _updateIcon: function() {
         if (this._usesIconset()) {
-          if (this._iconsetName) {
+          if (this._img && this._img.parentNode) {
+            Polymer.dom(this.root).removeChild(this._img);
+          }
+          if (this._iconName === "") {
+            if (this._iconset) {
+              this._iconset.removeIcon(this);
+            }
+          } else if (this._iconsetName && this._meta) {
             this._iconset = /** @type {?Polymer.Iconset} */ (
               this._meta.byKey(this._iconsetName));
             if (this._iconset) {
@@ -4337,6 +4458,9 @@
             }
           }
         } else {
+          if (this._iconset) {
+            this._iconset.removeIcon(this);
+          }
           if (!this._img) {
             this._img = document.createElement('img');
             this._img.style.width = '100%';
@@ -4605,6 +4729,7 @@
         this._oldTabIndex = this.tabIndex;
         this.focused = false;
         this.tabIndex = -1;
+        this.blur();
       } else if (this._oldTabIndex !== undefined) {
         this.tabIndex = this._oldTabIndex;
       }
@@ -6335,16 +6460,19 @@
      */
     setItemSelected: function(item, isSelected) {
       if (item != null) {
-        if (isSelected) {
-          this.selection.push(item);
-        } else {
-          var i = this.selection.indexOf(item);
-          if (i >= 0) {
-            this.selection.splice(i, 1);
+        if (isSelected !== this.isSelected(item)) {
+          // proceed to update selection only if requested state differs from current
+          if (isSelected) {
+            this.selection.push(item);
+          } else {
+            var i = this.selection.indexOf(item);
+            if (i >= 0) {
+              this.selection.splice(i, 1);
+            }
           }
-        }
-        if (this.selectCallback) {
-          this.selectCallback(item, isSelected);
+          if (this.selectCallback) {
+            this.selectCallback(item, isSelected);
+          }
         }
       }
     },
@@ -6501,7 +6629,8 @@
     },
 
     observers: [
-      '_updateSelected(attrForSelected, selected)'
+      '_updateAttrForSelected(attrForSelected)',
+      '_updateSelected(selected)'
     ],
 
     created: function() {
@@ -6513,7 +6642,7 @@
       this._observer = this._observeItems(this);
       this._updateItems();
       if (!this._shouldUpdateSelection) {
-        this._updateSelected(this.attrForSelected,this.selected)
+        this._updateSelected();
       }
       this._addListener(this.activateEvent);
     },
@@ -6606,6 +6735,12 @@
       this._setItems(nodes);
     },
 
+    _updateAttrForSelected: function() {
+      if (this._shouldUpdateSelection) {
+        this.selected = this._indexToValue(this.indexOf(this.selectedItem));        
+      }
+    },
+
     _updateSelected: function() {
       this._selectSelected(this.selected);
     },
@@ -6675,7 +6810,7 @@
         }
 
         // Let other interested parties know about the change so that
-        // we don't have to recreate mutation observers everywher.
+        // we don't have to recreate mutation observers everywhere.
         this.fire('iron-items-changed', mutations, {
           bubbles: false,
           cancelable: false
@@ -6739,7 +6874,7 @@
     },
 
     observers: [
-      '_updateSelected(attrForSelected, selectedValues)'
+      '_updateSelected(selectedValues)'
     ],
 
     /**
@@ -6770,6 +6905,18 @@
         (this.selectedValues != null && this.selectedValues.length);
     },
 
+    _updateAttrForSelected: function() {
+      if (!this.multi) {
+        Polymer.IronSelectableBehavior._updateAttrForSelected.apply(this);
+      } else if (this._shouldUpdateSelection) {
+        this.selectedValues = this.selectedItems.map(function(selectedItem) {
+          return this._indexToValue(this.indexOf(selectedItem));        
+        }, this).filter(function(unfilteredValue) {
+          return unfilteredValue != null;
+        }, this);
+      }
+    },
+
     _updateSelected: function() {
       if (this.multi) {
         this._selectMulti(this.selectedValues);
@@ -6779,11 +6926,16 @@
     },
 
     _selectMulti: function(values) {
-      this._selection.clear();
       if (values) {
-        for (var i = 0; i < values.length; i++) {
-          this._selection.setItemSelected(this._valueToItem(values[i]), true);
+        var selectedItems = this._valuesToItems(values);
+        // clear all but the current selected items
+        this._selection.clear(selectedItems);
+        // select only those not selected yet
+        for (var i = 0; i < selectedItems.length; i++) {
+          this._selection.setItemSelected(selectedItems[i], true);
         }
+      } else {
+        this._selection.clear();
       }
     },
 
@@ -6806,6 +6958,12 @@
         this.splice('selectedValues',i,1);
       }
       this._selection.setItemSelected(this._valueToItem(value), unselected);
+    },
+
+    _valuesToItems: function(values) {
+      return (values == null) ? null : values.map(function(value) {
+        return this._valueToItem(value);
+      }, this);
     }
   };
 
@@ -7039,6 +7197,14 @@
         return;
       }
 
+      // Do not focus the selected tab if the deepest target is part of the
+      // menu element's local DOM and is focusable.
+      var rootTarget = /** @type {?HTMLElement} */(
+          Polymer.dom(event).rootTarget);
+      if (rootTarget !== this && typeof rootTarget.tabIndex !== "undefined" && !this.isLightDescendant(rootTarget)) {
+        return;
+      }
+
       this.blur();
 
       // clear the cached focus item
@@ -7066,6 +7232,7 @@
     _onUpKey: function(event) {
       // up and down arrows moves the focus
       this._focusPrevious();
+      event.detail.keyboardEvent.preventDefault();
     },
 
     /**
@@ -7075,6 +7242,7 @@
      */
     _onDownKey: function(event) {
       this._focusNext();
+      event.detail.keyboardEvent.preventDefault();
     },
 
     /**
@@ -7283,14 +7451,14 @@
      * the memoized data.
      */
     resetFit: function() {
-      if (!this._fitInfo || !this._fitInfo.sizedBy.height) {
-        this.sizingTarget.style.maxHeight = '';
-        this.style.top = this._fitInfo ? this._fitInfo.inlineStyle.top : '';
-      }
       if (!this._fitInfo || !this._fitInfo.sizedBy.width) {
         this.sizingTarget.style.maxWidth = '';
-        this.style.left = this._fitInfo ? this._fitInfo.inlineStyle.left : '';
       }
+      if (!this._fitInfo || !this._fitInfo.sizedBy.height) {
+        this.sizingTarget.style.maxHeight = '';
+      }
+      this.style.top = this._fitInfo ? this._fitInfo.inlineStyle.top : '';
+      this.style.left = this._fitInfo ? this._fitInfo.inlineStyle.left : '';
       if (this._fitInfo) {
         this.style.position = this._fitInfo.positionedBy.css;
       }
@@ -7351,18 +7519,30 @@
      * `position:fixed`.
      */
     center: function() {
-      if (!this._fitInfo.positionedBy.vertically || !this._fitInfo.positionedBy.horizontally) {
-        // need position:fixed to center
-        this.style.position = 'fixed';
+      var positionedBy = this._fitInfo.positionedBy;
+      if (positionedBy.vertically && positionedBy.horizontally) {
+        // Already positioned.
+        return;
       }
-      if (!this._fitInfo.positionedBy.vertically) {
-        var top = (this._fitHeight - this.offsetHeight) / 2 + this._fitTop;
-        top -= this._fitInfo.margin.top;
+      // Need position:fixed to center
+      this.style.position = 'fixed';
+      // Take into account the offset caused by parents that create stacking
+      // contexts (e.g. with transform: translate3d). Translate to 0,0 and
+      // measure the bounding rect.
+      if (!positionedBy.vertically) {
+        this.style.top = '0px';
+      }
+      if (!positionedBy.horizontally) {
+        this.style.left = '0px';
+      }
+      // It will take in consideration margins and transforms
+      var rect = this.getBoundingClientRect();
+      if (!positionedBy.vertically) {
+        var top = this._fitTop - rect.top + (this._fitHeight - rect.height) / 2;
         this.style.top = top + 'px';
       }
-      if (!this._fitInfo.positionedBy.horizontally) {
-        var left = (this._fitWidth - this.offsetWidth) / 2 + this._fitLeft;
-        left -= this._fitInfo.margin.left;
+      if (!positionedBy.horizontally) {
+        var left = this._fitLeft - rect.left + (this._fitWidth - rect.width) / 2;
         this.style.left = left + 'px';
       }
     }
@@ -7374,6 +7554,9 @@
    */
   Polymer.IronOverlayManagerClass = function() {
     this._overlays = [];
+    // Used to keep track of the last focused node before an overlay gets opened.
+    this._lastFocusedNodes = [];
+
     /**
      * iframes have a default z-index of 100, so this default should be at least
      * that.
@@ -7382,7 +7565,52 @@
     this._minimumZ = 101;
 
     this._backdrops = [];
-  }
+
+    this._backdropElement = null;
+    Object.defineProperty(this, 'backdropElement', {
+      get: function() {
+        if (!this._backdropElement) {
+          this._backdropElement = document.createElement('iron-overlay-backdrop');
+        }
+        return this._backdropElement;
+      }.bind(this)
+    });
+
+    /**
+     * The deepest active element.
+     * returns {?Node} element the active element
+     */
+    this.deepActiveElement = null;
+    Object.defineProperty(this, 'deepActiveElement', {
+      get: function() {
+        var active = document.activeElement;
+        // document.activeElement can be null
+        // https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement
+        while (active && active.root && Polymer.dom(active.root).activeElement) {
+          active = Polymer.dom(active.root).activeElement;
+        }
+        return active;
+      }.bind(this)
+    });
+  };
+
+  /**
+   * If a node is contained in an overlay.
+   * @private
+   * @param {Node} node
+   * @returns {Boolean}
+   */
+  Polymer.IronOverlayManagerClass.prototype._isChildOfOverlay = function(node) {
+    while (node && node !== document.body) {
+      // Use logical parentNode, or native ShadowRoot host.
+      node = Polymer.dom(node).parentNode || node.host;
+      // Check if it is an overlay.
+      if (node && node.behaviors && node.behaviors.indexOf(Polymer.IronOverlayBehaviorImpl) !== -1) {
+        return true;
+      }
+    }
+    return false;
+  };
 
   Polymer.IronOverlayManagerClass.prototype._applyOverlayZ = function(overlay, aboveZ) {
     this._setZ(overlay, aboveZ + 2);
@@ -7402,6 +7630,12 @@
     if (newZ <= minimumZ) {
       this._applyOverlayZ(overlay, minimumZ);
     }
+    var element = this.deepActiveElement;
+    // If already in other overlay, don't reset focus there.
+    if (this._isChildOfOverlay(element)) {
+      element = null;
+    }
+    this._lastFocusedNodes.push(element);
   };
 
   Polymer.IronOverlayManagerClass.prototype.removeOverlay = function(overlay) {
@@ -7409,6 +7643,13 @@
     if (i >= 0) {
       this._overlays.splice(i, 1);
       this._setZ(overlay, '');
+
+      var node = this._lastFocusedNodes[i];
+      // Focus only if still contained in document.body
+      if (overlay.restoreFocusOnClose && node && Polymer.dom(document.body).deepContains(node)) {
+        node.focus();
+      }
+      this._lastFocusedNodes.splice(i, 1);
     }
   };
 
@@ -7463,15 +7704,6 @@
     }
   };
 
-  Object.defineProperty(Polymer.IronOverlayManagerClass.prototype, "backdropElement", {
-    get: function() {
-      if (!this._backdropElement) {
-        this._backdropElement = document.createElement('iron-overlay-backdrop');
-      }
-      return this._backdropElement;
-    }
-  });
-
   Polymer.IronOverlayManagerClass.prototype.getBackdrops = function() {
     return this._backdrops;
   };
@@ -7701,6 +7933,23 @@
         type: Object
       },
 
+      /**
+       * The HTMLElement that will be firing relevant KeyboardEvents.
+       * Used for capturing esc and tab. Overridden from `IronA11yKeysBehavior`.
+       */
+      keyEventTarget: {
+        type: Object,
+        value: document
+      },
+
+      /**
+       * Set to true to enable restoring of focus when overlay is closed.
+       */
+      restoreFocusOnClose: {
+        type: Boolean,
+        value: false
+      },
+
       _manager: {
         type: Object,
         value: Polymer.IronOverlayManager
@@ -7713,13 +7962,6 @@
         }
       },
 
-      _boundOnCaptureKeydown: {
-        type: Function,
-        value: function() {
-          return this._onCaptureKeydown.bind(this);
-        }
-      },
-
       _boundOnCaptureFocus: {
         type: Function,
         value: function() {
@@ -7727,44 +7969,113 @@
         }
       },
 
-      /** @type {?Node} */
+      /**
+       * The node being focused.
+       * @type {?Node}
+       */
       _focusedChild: {
         type: Object
       }
 
     },
 
+    keyBindings: {
+      'esc': '__onEsc',
+      'tab': '__onTab'
+    },
+
     listeners: {
       'iron-resize': '_onIronResize'
     },
 
     /**
      * The backdrop element.
-     * @type Node
+     * @type {Node}
      */
     get backdropElement() {
       return this._manager.backdropElement;
     },
 
+    /**
+     * Returns the node to give focus to.
+     * @type {Node}
+     */
     get _focusNode() {
       return this._focusedChild || Polymer.dom(this).querySelector('[autofocus]') || this;
     },
 
+    /**
+     * Array of nodes that can receive focus (overlay included), ordered by `tabindex`.
+     * This is used to retrieve which is the first and last focusable nodes in order
+     * to wrap the focus for overlays `with-backdrop`.
+     *
+     * If you know what is your content (specifically the first and last focusable children),
+     * you can override this method to return only `[firstFocusable, lastFocusable];`
+     * @type {[Node]}
+     * @protected
+     */
+    get _focusableNodes() {
+      // Elements that can be focused even if they have [disabled] attribute.
+      var FOCUSABLE_WITH_DISABLED = [
+        'a[href]',
+        'area[href]',
+        'iframe',
+        '[tabindex]',
+        '[contentEditable=true]'
+      ];
+
+      // Elements that cannot be focused if they have [disabled] attribute.
+      var FOCUSABLE_WITHOUT_DISABLED = [
+        'input',
+        'select',
+        'textarea',
+        'button'
+      ];
+
+      // Discard elements with tabindex=-1 (makes them not focusable).
+      var selector = FOCUSABLE_WITH_DISABLED.join(':not([tabindex="-1"]),') +
+        ':not([tabindex="-1"]),' +
+        FOCUSABLE_WITHOUT_DISABLED.join(':not([disabled]):not([tabindex="-1"]),') +
+        ':not([disabled]):not([tabindex="-1"])';
+
+      var focusables = Polymer.dom(this).querySelectorAll(selector);
+      if (this.tabIndex >= 0) {
+        // Insert at the beginning because we might have all elements with tabIndex = 0,
+        // and the overlay should be the first of the list.
+        focusables.splice(0, 0, this);
+      }
+      // Sort by tabindex.
+      return focusables.sort(function (a, b) {
+        if (a.tabIndex === b.tabIndex) {
+          return 0;
+        }
+        if (a.tabIndex === 0 || a.tabIndex > b.tabIndex) {
+          return 1;
+        }
+        return -1;
+      });
+    },
+
     ready: function() {
-      // with-backdrop need tabindex to be set in order to trap the focus.
+      // with-backdrop needs tabindex to be set in order to trap the focus.
       // If it is not set, IronOverlayBehavior will set it, and remove it if with-backdrop = false.
       this.__shouldRemoveTabIndex = false;
+      // Used for wrapping the focus on TAB / Shift+TAB.
+      this.__firstFocusableNode = this.__lastFocusableNode = null;
       this._ensureSetup();
     },
 
     attached: function() {
       // Call _openedChanged here so that position can be computed correctly.
-      if (this._callOpenedWhenReady) {
+      if (this.opened) {
         this._openedChanged();
       }
+      this._observer = Polymer.dom(this).observeNodes(this._onNodesChange);
     },
 
     detached: function() {
+      Polymer.dom(this).unobserveNodes(this._observer);
+      this._observer = null;
       this.opened = false;
       this._manager.trackBackdrop(this);
       this._manager.removeOverlay(this);
@@ -7796,9 +8107,10 @@
 
     /**
      * Cancels the overlay.
+     * @param {?Event} event The original event
      */
-    cancel: function() {
-      var cancelEvent = this.fire('iron-overlay-canceled', undefined, {cancelable: true});
+    cancel: function(event) {
+      var cancelEvent = this.fire('iron-overlay-canceled', event, {cancelable: true});
       if (cancelEvent.defaultPrevented) {
         return;
       }
@@ -7821,12 +8133,10 @@
         this.removeAttribute('aria-hidden');
       } else {
         this.setAttribute('aria-hidden', 'true');
-        Polymer.dom(this).unobserveNodes(this._observer);
       }
 
       // wait to call after ready only if we're initially open
       if (!this._overlaySetup) {
-        this._callOpenedWhenReady = this.opened;
         return;
       }
 
@@ -7901,16 +8211,18 @@
       }
     },
 
-    _toggleListeners: function () {
+    _toggleListeners: function() {
       this._toggleListener(this.opened, document, 'tap', this._boundOnCaptureClick, true);
-      this._toggleListener(this.opened, document, 'keydown', this._boundOnCaptureKeydown, true);
       this._toggleListener(this.opened, document, 'focus', this._boundOnCaptureFocus, true);
     },
 
     // tasks which must occur before opening; e.g. making the element visible
     _prepareRenderOpened: function() {
+
       this._manager.addOverlay(this);
 
+      // Needed to calculate the size of the overlay so that transitions on its size
+      // will have the correct starting points.
       this._preparePositioning();
       this.fit();
       this._finishPositioning();
@@ -7918,6 +8230,12 @@
       if (this.withBackdrop) {
         this.backdropElement.prepare();
       }
+
+      // Safari will apply the focus to the autofocus element when displayed for the first time,
+      // so we blur it. Later, _applyFocus will set the focus if necessary.
+      if (this.noAutoFocus && document.activeElement === this._focusNode) {
+        this._focusNode.blur();
+      }
     },
 
     // tasks which cause the overlay to actually open; typically play an
@@ -7937,23 +8255,24 @@
     },
 
     _finishRenderOpened: function() {
-      // focus the child node with [autofocus]
+      // This ensures the overlay is visible before we set the focus
+      // (by calling _onIronResize -> refit).
+      this.notifyResize();
+      // Focus the child node with [autofocus]
       this._applyFocus();
 
-      this._observer = Polymer.dom(this).observeNodes(this.notifyResize);
       this.fire('iron-overlay-opened');
     },
 
     _finishRenderClosed: function() {
-      // hide the overlay and remove the backdrop
+      // Hide the overlay and remove the backdrop.
       this.resetFit();
       this.style.display = 'none';
       this._manager.removeOverlay(this);
 
-      this._focusedChild = null;
       this._applyFocus();
-
       this.notifyResize();
+
       this.fire('iron-overlay-closed', this.closingReason);
     },
 
@@ -7966,8 +8285,9 @@
     _finishPositioning: function() {
       this.style.display = 'none';
       this.style.transform = this.style.webkitTransform = '';
-      // force layout to avoid application of transform
-      /** @suppress {suspiciousCode} */ this.offsetWidth;
+      // Force layout layout to avoid application of transform.
+      // Set offsetWidth to itself so that compilers won't remove it.
+      this.offsetWidth = this.offsetWidth;
       this.style.transition = this.style.webkitTransition = '';
     },
 
@@ -7978,6 +8298,7 @@
         }
       } else {
         this._focusNode.blur();
+        this._focusedChild = null;
         this._manager.focusOverlay();
       }
     },
@@ -7988,23 +8309,13 @@
         if (this.noCancelOnOutsideClick) {
           this._applyFocus();
         } else {
-          this.cancel();
+          this.cancel(event);
         }
       }
     },
 
-    _onCaptureKeydown: function(event) {
-      var ESC = 27;
-      if (this._manager.currentOverlay() === this &&
-          !this.noCancelOnEscKey &&
-          event.keyCode === ESC) {
-        this.cancel();
-      }
-    },
-
     _onCaptureFocus: function (event) {
-      if (this._manager.currentOverlay() === this &&
-          this.withBackdrop) {
+      if (this._manager.currentOverlay() === this && this.withBackdrop) {
         var path = Polymer.dom(event).path;
         if (path.indexOf(this) === -1) {
           event.stopPropagation();
@@ -8019,28 +8330,73 @@
       if (this.opened) {
         this.refit();
       }
+    },
+
+    /**
+     * @protected
+     * Will call notifyResize if overlay is opened.
+     * Can be overridden in order to avoid multiple observers on the same node.
+     */
+    _onNodesChange: function() {
+      if (this.opened) {
+        this.notifyResize();
+      }
+      // Store it so we don't query too much.
+      var focusableNodes = this._focusableNodes;
+      this.__firstFocusableNode = focusableNodes[0];
+      this.__lastFocusableNode = focusableNodes[focusableNodes.length - 1];
+    },
+
+    __onEsc: function(event) {
+      // Not opened or not on top, so return.
+      if (this._manager.currentOverlay() !== this) {
+        return;
+      }
+      if (!this.noCancelOnEscKey) {
+        this.cancel(event);
+      }
+    },
+
+    __onTab: function(event) {
+      // Not opened or not on top, so return.
+      if (this._manager.currentOverlay() !== this) {
+        return;
+      }
+      // TAB wraps from last to first focusable.
+      // Shift + TAB wraps from first to last focusable.
+      var shift = event.detail.keyboardEvent.shiftKey;
+      var nodeToCheck = shift ? this.__firstFocusableNode : this.__lastFocusableNode;
+      var nodeToSet = shift ? this.__lastFocusableNode : this.__firstFocusableNode;
+      if (this.withBackdrop && this._focusedChild === nodeToCheck) {
+        // We set here the _focusedChild so that _onCaptureFocus will handle the
+        // wrapping of the focus (the next event after tab is focus).
+        this._focusedChild = nodeToSet;
+      }
     }
-
-/**
- * Fired after the `iron-overlay` opens.
- * @event iron-overlay-opened
- */
-
-/**
- * Fired when the `iron-overlay` is canceled, but before it is closed.
- * Cancel the event to prevent the `iron-overlay` from closing.
- * @event iron-overlay-canceled
- */
-
-/**
- * Fired after the `iron-overlay` closes.
- * @event iron-overlay-closed
- * @param {{canceled: (boolean|undefined)}} set to the `closingReason` attribute
- */
   };
 
   /** @polymerBehavior */
-  Polymer.IronOverlayBehavior = [Polymer.IronFitBehavior, Polymer.IronResizableBehavior, Polymer.IronOverlayBehaviorImpl];
+  Polymer.IronOverlayBehavior = [Polymer.IronA11yKeysBehavior, Polymer.IronFitBehavior, Polymer.IronResizableBehavior, Polymer.IronOverlayBehaviorImpl];
+
+  /**
+  * Fired after the `iron-overlay` opens.
+  * @event iron-overlay-opened
+  */
+
+  /**
+  * Fired when the `iron-overlay` is canceled, but before it is closed.
+  * Cancel the event to prevent the `iron-overlay` from closing.
+  * @event iron-overlay-canceled
+  * @param {Event} event The closing of the `iron-overlay` can be prevented
+  * by calling `event.preventDefault()`. The `event.detail` is the original event that originated
+  * the canceling (e.g. ESC keyboard event or click event outside the `iron-overlay`).
+  */
+
+  /**
+  * Fired after the `iron-overlay` closes.
+  * @event iron-overlay-closed
+  * @param {{canceled: (boolean|undefined)}} closingReason Contains `canceled` (whether the overlay was canceled).
+  */
 /**
    * Use `Polymer.NeonAnimationBehavior` to implement an animation.
    * @polymerBehavior
diff --git a/chrome/browser/resources/md_downloads/vulcanized.html b/chrome/browser/resources/md_downloads/vulcanized.html
index 7010722..8666191 100644
--- a/chrome/browser/resources/md_downloads/vulcanized.html
+++ b/chrome/browser/resources/md_downloads/vulcanized.html
@@ -1,13 +1,5 @@
 <!DOCTYPE html><html i18n-values="dir:textdirection;lang:language"><head><!--
 @license
-Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
-This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
-The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
-The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
-Code distributed by Google as part of the polymer project is also
-subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
---><!--
-@license
 Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
 This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
@@ -22,6 +14,14 @@
 The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 Code distributed by Google as part of the polymer project is also
 subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+--><!--
+@license
+Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 -->
   <meta charset="utf-8">
   <title i18n-content="title"></title>
@@ -237,7 +237,7 @@
     };
 
     --layout-around-justified: {
-      -ms-flex-pack: around;
+      -ms-flex-pack: distribute;
       -webkit-justify-content: space-around;
       justify-content: space-around;
     };
@@ -754,24 +754,26 @@
     --secondary-text-color: var(--light-theme-secondary-color);
     --disabled-text-color: var(--light-theme-disabled-color);
     --divider-color: var(--light-theme-divider-color);
+    --error-color: var(--paper-deep-orange-a700);
 
     /*
      * Primary and accent colors. Also see color.html for more colors.
      */
-    --primary-color: #3f51b5;  /* --paper-indigo-500 */
-    --light-primary-color: #c5cae9;  /* --paper-indigo-100 */
-    --dark-primary-color: #303f9f;  /* --paper-indigo-700 */
+    --primary-color: var(--paper-indigo-500);
+    --light-primary-color: var(--paper-indigo-100);
+    --dark-primary-color: var(--paper-indigo-700);
 
-    --accent-color: #ff4081;  /* --paper-pink-a200 */
-    --light-accent-color: #ff80ab;  /* --paper-pink-a100 */
-    --dark-accent-color: #f50057;  /* --paper-pink-a400 */
+    --accent-color: var(--paper-pink-a200);
+    --light-accent-color: var(--paper-pink-a100);
+    --dark-accent-color: var(--paper-pink-a400);
+
 
     /*
      * Material Design Light background theme
      */
     --light-theme-background-color: #ffffff;
     --light-theme-base-color: #000000;
-    --light-theme-text-color: #212121;
+    --light-theme-text-color: var(--paper-grey-900);
     --light-theme-secondary-color: #737373;  /* for secondary text and icons */
     --light-theme-disabled-color: #9b9b9b;  /* disabled/hint text */
     --light-theme-divider-color: #dbdbdb;
@@ -779,7 +781,7 @@
     /*
      * Material Design Dark background theme
      */
-    --dark-theme-background-color: #212121;
+    --dark-theme-background-color: var(--paper-grey-900);
     --dark-theme-base-color: #ffffff;
     --dark-theme-text-color: #ffffff;
     --dark-theme-secondary-color: #bcbcbc;  /* for secondary text and icons */
@@ -2357,8 +2359,9 @@
       .focused-line {
         @apply(--layout-fit);
 
-        background: var(--paper-input-container-focus-color, --default-primary-color);
+        background: var(--paper-input-container-focus-color, --primary-color);
         height: 2px;
+
         -webkit-transform-origin: center center;
         transform-origin: center center;
         -webkit-transform: scale3d(0,1,1);
@@ -2377,7 +2380,7 @@
       }
 
       .underline.is-invalid .focused-line {
-        background: var(--paper-input-container-invalid-color, --google-red-500);
+        background: var(--paper-input-container-invalid-color, --error-color);
         -webkit-transform: none;
         transform: none;
         -webkit-transition: -webkit-transform 0.25s;
@@ -2389,8 +2392,8 @@
       .unfocused-line {
         @apply(--layout-fit);
 
-        height: 1px;
         background: var(--paper-input-container-color, --secondary-text-color);
+        height: 1px;
 
         @apply(--paper-input-container-underline);
       }
@@ -2406,6 +2409,7 @@
       .label-and-input-container {
         @apply(--layout-flex-auto);
         @apply(--layout-relative);
+
         width: 100%;
         max-width: 100%;
       }
@@ -2426,26 +2430,26 @@
         width: 100%;
         font: inherit;
         color: var(--paper-input-container-color, --secondary-text-color);
+        -webkit-transition: -webkit-transform 0.25s, width 0.25s;
+        transition: transform 0.25s, width 0.25s;
+        -webkit-transform-origin: left top;
+        transform-origin: left top;
 
         @apply(--paper-font-common-nowrap);
         @apply(--paper-font-subhead);
         @apply(--paper-input-container-label);
+        @apply(--paper-transition-easing);
       }
 
       .input-content.label-is-floating ::content label,
       .input-content.label-is-floating ::content .paper-input-label {
         -webkit-transform: translateY(-75%) scale(0.75);
         transform: translateY(-75%) scale(0.75);
-        -webkit-transition: -webkit-transform 0.25s, width 0.25s;
-        transition: transform 0.25s, width 0.25s;
-        -webkit-transform-origin: left top;
-        transform-origin: left top;
 
         /* Since we scale to 75/100 of the size, we actually have 100/75 of the
         original space now available */
         width: 133%;
 
-        @apply(--paper-transition-easing);
         @apply(--paper-input-container-label-floating);
       }
 
@@ -2461,14 +2465,14 @@
 
       .input-content.label-is-highlighted ::content label,
       .input-content.label-is-highlighted ::content .paper-input-label {
-        color: var(--paper-input-container-focus-color, --default-primary-color);
+        color: var(--paper-input-container-focus-color, --primary-color);
 
         @apply(--paper-input-container-label-focus);
       }
 
       .input-content.is-invalid ::content label,
       .input-content.is-invalid ::content .paper-input-label {
-        color: var(--paper-input-container-invalid-color, --google-red-500);
+        color: var(--paper-input-container-invalid-color, --error-color);
       }
 
       .input-content.label-is-hidden ::content label,
@@ -2498,12 +2502,14 @@
 
       ::content [prefix] {
         @apply(--paper-font-subhead);
+
         @apply(--paper-input-prefix);
         @apply(--layout-flex-none);
       }
 
       ::content [suffix] {
         @apply(--paper-font-subhead);
+
         @apply(--paper-input-suffix);
         @apply(--layout-flex-none);
       }
@@ -2522,11 +2528,11 @@
       }
 
       .add-on-content.is-invalid ::content * {
-        color: var(--paper-input-container-invalid-color, --google-red-500);
+        color: var(--paper-input-container-invalid-color, --error-color);
       }
 
       .add-on-content.is-highlighted ::content * {
-        color: var(--paper-input-container-focus-color, --default-primary-color);
+        color: var(--paper-input-container-focus-color, --primary-color);
       }
     </style>
 
diff --git a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js
index c531484..1ab592af 100644
--- a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js
+++ b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js
@@ -1195,7 +1195,9 @@
   },
 
   /**
-   * Updates |currentView_| if there is a new blocking issue.
+   * Updates |currentView_| if there is a new blocking issue. Clears any
+   * pending route creation properties if the issue corresponds with
+   * |pendingCreatedRouteId_|.
    *
    * @param {?media_router.Issue} issue The new issue.
    * @private
@@ -1205,6 +1207,11 @@
       this.currentView_ = media_router.MediaRouterView.ISSUE;
     else
       this.updateElementPositioning_();
+
+    if (!!this.pendingCreatedRouteId_ && !!issue &&
+        issue.routeId == this.pendingCreatedRouteId_) {
+      this.resetRouteCreationProperties_(false);
+    }
   },
 
   /**
diff --git a/chrome/browser/resources/media_router/media_router_data.js b/chrome/browser/resources/media_router/media_router_data.js
index f7e0a73..15b07e72 100644
--- a/chrome/browser/resources/media_router/media_router_data.js
+++ b/chrome/browser/resources/media_router/media_router_data.js
@@ -120,7 +120,7 @@
    * @param {string} message The issue message.
    * @param {number} defaultActionType The type of default action.
    * @param {?number} secondaryActionType The type of optional action.
-   * @param {?string} mediaRouteId The route ID to which this issue
+   * @param {?string} routeId The route ID to which this issue
    *                  pertains. If not set, this is a global issue.
    * @param {boolean} isBlocking True if this issue blocks other UI.
    * @param {?number} helpPageId The numeric help center ID.
@@ -128,7 +128,7 @@
    * @struct
    */
   var Issue = function(id, title, message, defaultActionType,
-                       secondaryActionType, mediaRouteId, isBlocking,
+                       secondaryActionType, routeId, isBlocking,
                        helpPageId) {
     /** @type {string} */
     this.id = id;
@@ -146,7 +146,7 @@
     this.secondaryActionType = secondaryActionType;
 
     /** @type {?string} */
-    this.mediaRouteId = mediaRouteId;
+    this.routeId = routeId;
 
     /** @type {boolean} */
     this.isBlocking = isBlocking;
diff --git a/chrome/browser/resources/settings/advanced_page/advanced_page.html b/chrome/browser/resources/settings/advanced_page/advanced_page.html
index 3623aa81..406f1bf 100644
--- a/chrome/browser/resources/settings/advanced_page/advanced_page.html
+++ b/chrome/browser/resources/settings/advanced_page/advanced_page.html
@@ -19,7 +19,6 @@
 
 <if expr="not chromeos">
 <link rel="import" href="chrome://md-settings/system_page/system_page.html">
-<link rel="import" href="chrome://md-settings/system_page/system_page_delegate.html">
 </if>
 
 <dom-module id="settings-advanced-page">
diff --git a/chrome/browser/resources/settings/advanced_page/advanced_page.js b/chrome/browser/resources/settings/advanced_page/advanced_page.js
index e6655247..8df43773 100644
--- a/chrome/browser/resources/settings/advanced_page/advanced_page.js
+++ b/chrome/browser/resources/settings/advanced_page/advanced_page.js
@@ -45,25 +45,9 @@
    */
   sectionSelector: 'settings-section',
 
-<if expr="not chromeos">
-  listeners: {
-    'dom-change': 'onDomChange_',
-  },
-</if>
-
   /** @override */
   attached: function() {
     /** @override */
     this.scroller = this.parentElement;
   },
-
-<if expr="not chromeos">
-  /** @private */
-  onDomChange_: function() {
-    var systemPage = /** @type {?SettingsSystemPageElement} */(
-        this.$$('settings-system-page'));
-    if (systemPage && !systemPage.delegate)
-      systemPage.delegate = new settings.SystemPageDelegateImpl;
-  },
-</if>
 });
diff --git a/chrome/browser/resources/settings/advanced_page/compiled_resources2.gyp b/chrome/browser/resources/settings/advanced_page/compiled_resources2.gyp
index ee927f3..5a4abab 100644
--- a/chrome/browser/resources/settings/advanced_page/compiled_resources2.gyp
+++ b/chrome/browser/resources/settings/advanced_page/compiled_resources2.gyp
@@ -11,7 +11,6 @@
         '../settings_page/compiled_resources2.gyp:settings_page_visibility',
         '../settings_page/compiled_resources2.gyp:transition_behavior',
         '../system_page/compiled_resources2.gyp:system_page',
-        '../system_page/compiled_resources2.gyp:system_page_delegate',
       ],
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
diff --git a/chrome/browser/resources/settings/people_page/compiled_resources2.gyp b/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
index 0ac1416..d53802e2 100644
--- a/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
+++ b/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
@@ -40,6 +40,16 @@
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
     {
+      'target_name': 'easy_unlock_turn_off_dialog',
+      'dependencies': [
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
+        'easy_unlock_browser_proxy',
+      ],
+      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+    {
       'target_name': 'people_page',
       'dependencies': [
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
@@ -48,6 +58,7 @@
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
         '../settings_page/compiled_resources2.gyp:settings_animated_pages',
         'easy_unlock_browser_proxy',
+        'easy_unlock_turn_off_dialog',
         'sync_private_api',
       ],
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
diff --git a/chrome/browser/resources/settings/people_page/easy_unlock_browser_proxy.js b/chrome/browser/resources/settings/people_page/easy_unlock_browser_proxy.js
index d46ec7ec..72f0a9b 100644
--- a/chrome/browser/resources/settings/people_page/easy_unlock_browser_proxy.js
+++ b/chrome/browser/resources/settings/people_page/easy_unlock_browser_proxy.js
@@ -22,7 +22,23 @@
     /**
      * Starts the Easy Unlock setup flow.
      */
-    launchSetup: function() {}
+    startTurnOnFlow: function() {},
+
+    /**
+     * Returns the Easy Unlock turn off flow status.
+     * @return {!Promise<string>}
+     */
+    getTurnOffFlowStatus: function() {},
+
+    /**
+     * Begins the Easy Unlock turn off flow.
+     */
+    startTurnOffFlow: function() {},
+
+    /**
+     * Cancels any in-progress Easy Unlock turn-off flows.
+     */
+    cancelTurnOffFlow: function() {},
   };
 
   /**
@@ -41,8 +57,23 @@
     },
 
     /** @override */
-    launchSetup: function() {
-      chrome.send('easyUnlockLaunchSetup');
+    startTurnOnFlow: function() {
+      chrome.send('easyUnlockStartTurnOnFlow');
+    },
+
+    /** @override */
+    getTurnOffFlowStatus: function() {
+      return cr.sendWithPromise('easyUnlockGetTurnOffFlowStatus');
+    },
+
+    /** @override */
+    startTurnOffFlow: function() {
+      chrome.send('easyUnlockStartTurnOffFlow');
+    },
+
+    /** @override */
+    cancelTurnOffFlow: function() {
+      chrome.send('easyUnlockCancelTurnOffFlow');
     },
   };
 
diff --git a/chrome/browser/resources/settings/people_page/easy_unlock_turn_off_dialog.html b/chrome/browser/resources/settings/people_page/easy_unlock_turn_off_dialog.html
new file mode 100644
index 0000000..3c3df6e5
--- /dev/null
+++ b/chrome/browser/resources/settings/people_page/easy_unlock_turn_off_dialog.html
@@ -0,0 +1,33 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner.html">
+<link rel="import" href="chrome://md-settings/i18n_setup.html">
+<link rel="import" href="chrome://md-settings/people_page/easy_unlock_browser_proxy.html">
+<link rel="import" href="chrome://md-settings/settings_dialog.html">
+<link rel="import" href="chrome://md-settings/settings_shared_css.html">
+
+<dom-module id="easy-unlock-turn-off-dialog">
+  <template>
+    <style include="settings-shared"></style>
+    <settings-dialog id="dialog">
+      <div class="title">[[getTitleText_(state_)]]</div>
+      <div class="body">
+        [[getDescriptionText_(state_)]]
+      </div>
+      <div class="button-container" hidden="[[isButtonBarHidden_(state_)]]">
+        <paper-spinner active="[[isSpinnerActive_(state_)]]">
+        </paper-spinner>
+        <paper-button class="cancel-button" on-tap="onCancelTap_"
+            hidden="[[isCancelButtonHidden_(state_)]]">
+          $i18n{cancel}
+        </paper-button>
+        <paper-button id="turnOff" class="action-button" on-tap="onTurnOffTap_"
+            disabled="[[!isTurnOffButtonEnabled_(state_)]]">
+          [[getTurnOffButtonText_(state_)]]
+        </paper-button>
+      </div>
+    </settings-dialog>
+  </template>
+  <script src="easy_unlock_turn_off_dialog.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/settings/people_page/easy_unlock_turn_off_dialog.js b/chrome/browser/resources/settings/people_page/easy_unlock_turn_off_dialog.js
new file mode 100644
index 0000000..e658dee3
--- /dev/null
+++ b/chrome/browser/resources/settings/people_page/easy_unlock_turn_off_dialog.js
@@ -0,0 +1,206 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview A dialog allowing the user to turn off the Easy Unlock feature.
+ */
+
+(function() {
+
+/**
+ * Possible UI statuses for the EasyUnlockTurnOffDialogElement.
+ * See easy_unlock_settings_handler.cc.
+ * @enum {string}
+ */
+var EasyUnlockTurnOffStatus = {
+  UNKNOWN: 'unknown',
+  OFFLINE: 'offline',
+  IDLE: 'idle',
+  PENDING: 'pending',
+  SERVER_ERROR: 'server-error',
+};
+
+Polymer({
+  is: 'easy-unlock-turn-off-dialog',
+
+  behaviors: [I18nBehavior, WebUIListenerBehavior],
+
+  properties: {
+    /** @private {!settings.EasyUnlockBrowserProxyImpl} */
+    browserProxy_: Object,
+
+    /** @private {!EasyUnlockTurnOffStatus} */
+    status_: {
+      type: String,
+      value: EasyUnlockTurnOffStatus.UNKNOWN,
+    },
+
+    /** @private {?WebUIListener} */
+    turnOffStatusWebUiListener_: {
+      type: Object,
+      value: null,
+    },
+  },
+
+  /** @override */
+  ready: function() {
+    this.browserProxy_ = settings.EasyUnlockBrowserProxyImpl.getInstance();
+
+    this.addWebUIListener(
+        'easy-unlock-enabled-status',
+        this.handleEasyUnlockEnabledStatusChanged_.bind(this));
+  },
+
+  /**
+   * Opens the dialog.
+   */
+  open: function() {
+    this.getTurnOffStatus_().then(function(status) {
+      this.status_ = status;
+      this.$.dialog.open();
+    }.bind(this));
+
+    // The turn off flow status listener should only be active when the dialog
+    // is actually open.
+    assert(this.turnOffStatusWebUiListener_ == null);
+    this.turnOffStatusWebUiListener_ = cr.addWebUIListener(
+        'easy-unlock-turn-off-flow-status',
+        function(status) { this.status_ = status; }.bind(this));
+  },
+
+  /**
+   * @return {!Promise<!EasyUnlockTurnOffStatus>}
+   * @private
+   */
+  getTurnOffStatus_: function() {
+    return navigator.onLine ?
+        this.browserProxy_.getTurnOffFlowStatus() :
+        Promise.resolve(EasyUnlockTurnOffStatus.OFFLINE);
+  },
+
+  /**
+   * This dialog listens for Easy Unlock to become disabled. This signals
+   * that the turnoff process has succeeded. Regardless of whether the turnoff
+   * was initiated from this tab or another, this closes the dialog.
+   * @param {boolean} easyUnlockEnabled
+   * @private
+   */
+  handleEasyUnlockEnabledStatusChanged_: function(easyUnlockEnabled) {
+    var dialog = /** @type {{opened: boolean}} */ this.$.dialog;
+    if (!easyUnlockEnabled && dialog.opened)
+      this.onCancelTap_();
+  },
+
+  /** @private */
+  onCancelTap_: function() {
+    if (this.turnOffStatusWebUiListener_) {
+      cr.removeWebUIListener(this.turnOffStatusWebUiListener_);
+      this.turnOffStatusWebUiListener_ = null;
+    }
+
+    this.browserProxy_.cancelTurnOffFlow();
+    this.$.dialog.close();
+  },
+
+  /** @private */
+  onTurnOffTap_: function() {
+    this.browserProxy_.startTurnOffFlow();
+  },
+
+  /**
+   * @param {!EasyUnlockTurnOffStatus} status
+   * @return {string}
+   * @private
+   */
+  getTitleText_: function(status) {
+    switch (status) {
+      case EasyUnlockTurnOffStatus.OFFLINE:
+        return this.i18n('easyUnlockTurnOffOfflineTitle');
+      case EasyUnlockTurnOffStatus.UNKNOWN:
+      case EasyUnlockTurnOffStatus.IDLE:
+      case EasyUnlockTurnOffStatus.PENDING:
+        return this.i18n('easyUnlockTurnOffTitle');
+      case EasyUnlockTurnOffStatus.SERVER_ERROR:
+        return this.i18n('easyUnlockTurnOffErrorTitle');
+    }
+    assertNotReached();
+  },
+
+  /**
+   * @param {!EasyUnlockTurnOffStatus} status
+   * @return {string}
+   * @private
+   */
+  getDescriptionText_: function(status) {
+    switch (status) {
+      case EasyUnlockTurnOffStatus.OFFLINE:
+        return this.i18n('easyUnlockTurnOffOfflineMessage');
+      case EasyUnlockTurnOffStatus.UNKNOWN:
+      case EasyUnlockTurnOffStatus.IDLE:
+      case EasyUnlockTurnOffStatus.PENDING:
+        return this.i18n('easyUnlockTurnOffDescription');
+      case EasyUnlockTurnOffStatus.SERVER_ERROR:
+        return this.i18n('easyUnlockTurnOffErrorMessage');
+    }
+    assertNotReached();
+  },
+
+  /**
+   * @param {!EasyUnlockTurnOffStatus} status
+   * @return {string}
+   * @private
+   */
+  getTurnOffButtonText_: function(status) {
+    switch (status) {
+      case EasyUnlockTurnOffStatus.OFFLINE:
+        return '';
+      case EasyUnlockTurnOffStatus.UNKNOWN:
+      case EasyUnlockTurnOffStatus.IDLE:
+      case EasyUnlockTurnOffStatus.PENDING:
+        return this.i18n('easyUnlockTurnOffButton');
+      case EasyUnlockTurnOffStatus.SERVER_ERROR:
+        return this.i18n('easyUnlockTurnOffRetryButton');
+    }
+    assertNotReached();
+  },
+
+  /**
+   * @param {!EasyUnlockTurnOffStatus} status
+   * @return {boolean}
+   * @private
+   */
+  isButtonBarHidden_: function(status) {
+    return status == EasyUnlockTurnOffStatus.OFFLINE;
+  },
+
+  /**
+   * @param {!EasyUnlockTurnOffStatus} status
+   * @return {boolean}
+   * @private
+   */
+  isSpinnerActive_: function(status) {
+    return status == EasyUnlockTurnOffStatus.PENDING;
+  },
+
+  /**
+   * @param {!EasyUnlockTurnOffStatus} status
+   * @return {boolean}
+   * @private
+   */
+  isCancelButtonHidden_: function(status) {
+    return status == EasyUnlockTurnOffStatus.SERVER_ERROR;
+  },
+
+  /**
+   * @param {!EasyUnlockTurnOffStatus} status
+   * @return {boolean}
+   * @private
+   */
+  isTurnOffButtonEnabled_: function(status) {
+    return status == EasyUnlockTurnOffStatus.IDLE ||
+        status == EasyUnlockTurnOffStatus.SERVER_ERROR;
+  },
+});
+
+})();
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html
index 61718da..bcaf789 100644
--- a/chrome/browser/resources/settings/people_page/people_page.html
+++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -15,6 +15,7 @@
 <if expr="chromeos">
 <link rel="import" href="chrome://md-settings/people_page/change_picture.html">
 <link rel="import" href="chrome://md-settings/people_page/easy_unlock_browser_proxy.html">
+<link rel="import" href="chrome://md-settings/people_page/easy_unlock_turn_off_dialog.html">
 <link rel="import" href="chrome://md-settings/people_page/users_page.html">
 </if>
 <if expr="not chromeos">
@@ -120,7 +121,7 @@
                 </paper-button>
               </template>
               <template is="dom-if" if=[[easyUnlockEnabled_]]>
-                <paper-button class="secondary-button"
+                <paper-button id="easyUnlockTurnOff" class="secondary-button"
                     on-tap="onEasyUnlockTurnOffTap_">
                   [[i18n('easyUnlockTurnOffButton')]]
                 </paper-button>
@@ -181,6 +182,13 @@
         </paper-button>
       </div>
     </paper-dialog>
+
+<if expr="chromeos">
+    <template is="dom-if" if="[[easyUnlockEnabled_]]">
+      <easy-unlock-turn-off-dialog id="easyUnlockTurnOffDialog">
+      </easy-unlock-turn-off-dialog>
+    </template>
+</if>
   </template>
   <script src="people_page.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/people_page/people_page.js b/chrome/browser/resources/settings/people_page/people_page.js
index 19d109aa..88d3616 100644
--- a/chrome/browser/resources/settings/people_page/people_page.js
+++ b/chrome/browser/resources/settings/people_page/people_page.js
@@ -196,12 +196,12 @@
 <if expr="chromeos">
   /** @private */
   onEasyUnlockSetupTap_: function() {
-    this.browserProxy_.launchSetup();
+    this.browserProxy_.startTurnOnFlow();
   },
 
   /** @private */
   onEasyUnlockTurnOffTap_: function() {
-    // TODO(tommycli): Implement Easy Unlock turn off functionality.
+    this.$$('#easyUnlockTurnOffDialog').open();
   },
 </if>
 
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index fecce4e..a1b0c03 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -623,11 +623,11 @@
                  type="chrome_html"
                  flattenhtml="true"
                  allowexternalscript="true" />
-      <structure name="IDR_SETTINGS_SYSTEM_PAGE_DELEGATE_HTML"
-                 file="system_page/system_page_delegate.html"
+      <structure name="IDR_SETTINGS_SYSTEM_PAGE_BROWSER_PROXY_HTML"
+                 file="system_page/system_page_browser_proxy.html"
                  type="chrome_html" />
-      <structure name="IDR_SETTINGS_SYSTEM_PAGE_DELEGATE_JS"
-                 file="system_page/system_page_delegate.js"
+      <structure name="IDR_SETTINGS_SYSTEM_PAGE_BROWSER_PROXY"
+                 file="system_page/system_page_browser_proxy.js"
                  type="chrome_html" />
       <structure name="IDR_SETTINGS_SYSTEM_PAGE_HTML"
                  file="system_page/system_page.html"
@@ -837,6 +837,14 @@
                    type="chrome_html"
                    flattenhtml="true"
                    allowexternalscript="true" />
+        <structure name="IDR_SETTINGS_PEOPLE_EASY_UNLOCK_TURN_OFF_DIALOG_JS"
+                   file="people_page/easy_unlock_turn_off_dialog.js"
+                   type="chrome_html" />
+        <structure name="IDR_SETTINGS_PEOPLE_EASY_UNLOCK_TURN_OFF_DIALOG_HTML"
+                   file="people_page/easy_unlock_turn_off_dialog.html"
+                   type="chrome_html"
+                   flattenhtml="true"
+                   allowexternalscript="true" />
         <structure name="IDR_SETTINGS_USERS_PAGE_USER_LIST_JS"
                    file="people_page/user_list.js"
                    type="chrome_html" />
diff --git a/chrome/browser/resources/settings/settings_ui/settings_ui.html b/chrome/browser/resources/settings/settings_ui/settings_ui.html
index ef34d45..9a8d8d8 100644
--- a/chrome/browser/resources/settings/settings_ui/settings_ui.html
+++ b/chrome/browser/resources/settings/settings_ui/settings_ui.html
@@ -46,6 +46,10 @@
           background-color: var(--settings-background-color);
           margin-top: 8px;
         };
+        --paper-drawer-panel-right-drawer-container: {
+          background-color: var(--settings-background-color);
+          margin-top: 8px;
+        };
         position: relative;
       }
 
diff --git a/chrome/browser/resources/settings/system_page/compiled_resources2.gyp b/chrome/browser/resources/settings/system_page/compiled_resources2.gyp
index a56c089e7..7da27f25 100644
--- a/chrome/browser/resources/settings/system_page/compiled_resources2.gyp
+++ b/chrome/browser/resources/settings/system_page/compiled_resources2.gyp
@@ -4,9 +4,10 @@
 {
   'targets': [
     {
-      'target_name': 'system_page_delegate',
+      'target_name': 'system_page_browser_proxy',
       'dependencies': [
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
         '<(EXTERNS_GYP):chrome_send',
       ],
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
@@ -14,7 +15,7 @@
     {
       'target_name': 'system_page',
       'dependencies': [
-        'system_page_delegate',
+        'system_page_browser_proxy',
       ],
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
diff --git a/chrome/browser/resources/settings/system_page/system_page.html b/chrome/browser/resources/settings/system_page/system_page.html
index 4ec41c0..1ce9f83 100644
--- a/chrome/browser/resources/settings/system_page/system_page.html
+++ b/chrome/browser/resources/settings/system_page/system_page.html
@@ -1,26 +1,44 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://md-settings/controls/settings_checkbox.html">
+<link rel="import" href="chrome://md-settings/prefs/prefs.html">
 <link rel="import" href="chrome://md-settings/settings_shared_css.html">
+<link rel="import" href="chrome://md-settings/system_page/system_page_browser_proxy.html">
 
 <dom-module id="settings-system-page">
   <template>
-    <style include="settings-shared"></style>
+    <style include="settings-shared">
+      /* TODO(dbeam): is it worth generalizing this style? Does something like
+       * this already exist (buttons after a checkbox in the same row)? */
+      #hardware-acceleration {
+        align-items: center;
+        display: flex;
+      }
+
+      #hardware-acceleration settings-checkbox {
+        flex: 1;
+      }
+    </style>
     <div class="settings-box block first">
 <if expr="not is_macosx">
       <settings-checkbox i18n-values="label:backgroundAppsLabel"
           pref="{{prefs.background_mode.enabled}}">
       </settings-checkbox>
 </if>
-      <settings-checkbox i18n-values="label:hardwareAccelerationLabel"
-          pref="{{prefs.hardware_acceleration_mode.enabled}}">
-        <!-- TODO(dbeam): restart button. -->
-      </settings-checkbox>
+      <div id="hardware-acceleration">
+        <settings-checkbox i18n-values="label:hardwareAccelerationLabel"
+            pref="{{prefs.hardware_acceleration_mode.enabled}}">
+        </settings-checkbox>
+        <template is="dom-if" if="[[shouldShowRestart_(prefs.hardware_acceleration_mode.enabled.value)]]">
+          <paper-button on-tap="onRestartTap_">$i18n{restart}</paper-button>
+        </template>
+      </div>
     </div>
     <div class="settings-box">
       <div class="button-strip">
-        <paper-button i18n-content="changeProxySettings" class="primary-button"
-            on-tap="onChangeProxySettingsTap_"></paper-button>
+        <paper-button class="primary-button" on-tap="onChangeProxySettingsTap_">
+          $i18n{changeProxySettings}
+        </paper-button>
       </div>
     </div>
   </template>
diff --git a/chrome/browser/resources/settings/system_page/system_page.js b/chrome/browser/resources/settings/system_page/system_page.js
index cd9c667e..088f928 100644
--- a/chrome/browser/resources/settings/system_page/system_page.js
+++ b/chrome/browser/resources/settings/system_page/system_page.js
@@ -11,19 +11,30 @@
   is: 'settings-system-page',
 
   properties: {
-    /** @type {settings.SystemPageDelegate} */
-    delegate: {
-      type: Object,
-    },
-
     prefs: {
       type: Object,
       notify: true,
     },
   },
 
+  /**
+   * @param {boolean} enabled Whether hardware acceleration is currently
+   *     enabled.
+   * @private
+   */
+  shouldShowRestart_: function(enabled) {
+    var proxy = settings.SystemPageBrowserProxyImpl.getInstance();
+    return enabled != proxy.wasHardwareAccelerationEnabledAtStartup();
+  },
+
   /** @private */
   onChangeProxySettingsTap_: function() {
-    this.delegate.changeProxySettings();
+    settings.SystemPageBrowserProxyImpl.getInstance().changeProxySettings();
+  },
+
+  /** @private */
+  onRestartTap_: function() {
+    // TODO(dbeam): we should prompt before restarting the browser.
+    settings.SystemPageBrowserProxyImpl.getInstance().restartBrowser();
   },
 });
diff --git a/chrome/browser/resources/settings/system_page/system_page_browser_proxy.html b/chrome/browser/resources/settings/system_page/system_page_browser_proxy.html
new file mode 100644
index 0000000..8cdd1f7
--- /dev/null
+++ b/chrome/browser/resources/settings/system_page/system_page_browser_proxy.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="chrome://md-settings/system_page/system_page_browser_proxy.js"></script>
diff --git a/chrome/browser/resources/settings/system_page/system_page_browser_proxy.js b/chrome/browser/resources/settings/system_page/system_page_browser_proxy.js
new file mode 100644
index 0000000..654e6af
--- /dev/null
+++ b/chrome/browser/resources/settings/system_page/system_page_browser_proxy.js
@@ -0,0 +1,54 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/** @fileoverview Handles interprocess communcation for the system page. */
+
+cr.define('settings', function() {
+  /** @interface */
+  function SystemPageBrowserProxy() {}
+
+  SystemPageBrowserProxy.prototype = {
+    /** Allows the user to change native system proxy settings. */
+    changeProxySettings: function() {},
+
+    /** Restarts Chrome so "Use hardware acceleration" can take effect. */
+    restartBrowser: function() {},
+
+    /**
+     * @return {boolean} Whether hardware acceleration was enabled when the user
+     *     started Chrome.
+     */
+    wasHardwareAccelerationEnabledAtStartup: function() {},
+  };
+
+  /**
+   * @constructor
+   * @implements {settings.SystemPageBrowserProxy}
+   */
+  function SystemPageBrowserProxyImpl() {}
+
+  cr.addSingletonGetter(SystemPageBrowserProxyImpl);
+
+  SystemPageBrowserProxyImpl.prototype = {
+    /** @override */
+    changeProxySettings: function() {
+      chrome.send('changeProxySettings');
+    },
+
+    /** @override */
+    restartBrowser: function() {
+      chrome.send('restartBrowser');
+    },
+
+    /** @override */
+    wasHardwareAccelerationEnabledAtStartup: function() {
+      return loadTimeData.getBoolean('hardwareAccelerationEnabledAtStartup');
+    },
+  };
+
+  return {
+    SystemPageBrowserProxy: SystemPageBrowserProxy,
+    SystemPageBrowserProxyImpl: SystemPageBrowserProxyImpl,
+  };
+});
diff --git a/chrome/browser/resources/settings/system_page/system_page_delegate.html b/chrome/browser/resources/settings/system_page/system_page_delegate.html
deleted file mode 100644
index bf573c9c..0000000
--- a/chrome/browser/resources/settings/system_page/system_page_delegate.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<link rel="import" href="chrome://resources/html/cr.html">
-<script src="chrome://md-settings/system_page/system_page_delegate.js"></script>
diff --git a/chrome/browser/resources/settings/system_page/system_page_delegate.js b/chrome/browser/resources/settings/system_page/system_page_delegate.js
deleted file mode 100644
index 1084ab6..0000000
--- a/chrome/browser/resources/settings/system_page/system_page_delegate.js
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/** @fileoverview Handles interprocess communcation for the system page. */
-
-cr.define('settings', function() {
-  /** @interface */
-  function SystemPageDelegate() {}
-
-  SystemPageDelegate.prototype = {
-    /** Allows the user to change native system proxy settings. */
-    changeProxySettings: assertNotReached,
-  };
-
-  /**
-   * @constructor
-   * @implements {settings.SystemPageDelegate}
-   */
-  function SystemPageDelegateImpl() {}
-
-  SystemPageDelegateImpl.prototype = {
-    /** @override */
-    changeProxySettings: function() {
-      chrome.send('changeProxySettings');
-    },
-  };
-
-  return {
-    SystemPageDelegate: SystemPageDelegate,
-    SystemPageDelegateImpl: SystemPageDelegateImpl,
-  };
-});
diff --git a/chrome/browser/shell_integration.cc b/chrome/browser/shell_integration.cc
index bcce7d8..43b6dbc 100644
--- a/chrome/browser/shell_integration.cc
+++ b/chrome/browser/shell_integration.cc
@@ -144,7 +144,7 @@
 void DefaultWebClientWorker::StartCheckIsDefault() {
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
-      base::Bind(&DefaultWebClientWorker::CheckIsDefault, this));
+      base::Bind(&DefaultWebClientWorker::CheckIsDefault, this, false));
 }
 
 void DefaultWebClientWorker::StartSetAsDefault() {
@@ -164,61 +164,41 @@
 DefaultWebClientWorker::~DefaultWebClientWorker() = default;
 
 void DefaultWebClientWorker::OnCheckIsDefaultComplete(
-    DefaultWebClientState state) {
+    DefaultWebClientState state,
+    bool is_following_set_as_default) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   UpdateUI(state);
 
-  if (check_default_should_report_success_) {
-    check_default_should_report_success_ = false;
-
-    ReportAttemptResult(state == DefaultWebClientState::IS_DEFAULT
-                            ? AttemptResult::SUCCESS
-                            : AttemptResult::NO_ERRORS_NOT_DEFAULT);
-  }
-}
-
-void DefaultWebClientWorker::OnSetAsDefaultAttemptComplete(
-    AttemptResult result) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-  // Report failures here. Successes are reported in
-  // OnCheckIsDefaultComplete() after checking that the change is verified.
-  check_default_should_report_success_ = result == AttemptResult::SUCCESS;
-  if (!check_default_should_report_success_)
-    ReportAttemptResult(result);
-
-  // Start the default browser check. The default state will be reported to
-  // the caller via the |callback_|.
-  StartCheckIsDefault();
+  if (is_following_set_as_default)
+    ReportSetDefaultResult(state);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // DefaultWebClientWorker, private:
 
-void DefaultWebClientWorker::CheckIsDefault() {
+void DefaultWebClientWorker::CheckIsDefault(bool is_following_set_as_default) {
   DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DefaultWebClientState state = CheckIsDefaultImpl();
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&DefaultBrowserWorker::OnCheckIsDefaultComplete, this, state));
+      base::Bind(&DefaultBrowserWorker::OnCheckIsDefaultComplete, this, state,
+                 is_following_set_as_default));
 }
 
 void DefaultWebClientWorker::SetAsDefault() {
   DCHECK_CURRENTLY_ON(BrowserThread::FILE);
-  AttemptResult result = SetAsDefaultImpl();
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&DefaultBrowserWorker::OnSetAsDefaultAttemptComplete, this,
-                 result));
+  SetAsDefaultImpl();
+  CheckIsDefault(true);
 }
 
-void DefaultWebClientWorker::ReportAttemptResult(AttemptResult result) {
+void DefaultWebClientWorker::ReportSetDefaultResult(
+    DefaultWebClientState state) {
   base::LinearHistogram::FactoryGet(
-      base::StringPrintf("%s.SetDefaultResult", worker_name_), 1,
-      AttemptResult::NUM_ATTEMPT_RESULT_TYPES,
-      AttemptResult::NUM_ATTEMPT_RESULT_TYPES + 1,
+      base::StringPrintf("%s.SetDefaultResult2", worker_name_), 1,
+      DefaultWebClientState::NUM_DEFAULT_STATES,
+      DefaultWebClientState::NUM_DEFAULT_STATES + 1,
       base::HistogramBase::kUmaTargetedHistogramFlag)
-      ->Add(result);
+      ->Add(state);
 }
 
 void DefaultWebClientWorker::UpdateUI(DefaultWebClientState state) {
@@ -257,22 +237,19 @@
   return GetDefaultBrowser();
 }
 
-DefaultWebClientWorker::AttemptResult DefaultBrowserWorker::SetAsDefaultImpl() {
-  AttemptResult result = AttemptResult::FAILURE;
+void DefaultBrowserWorker::SetAsDefaultImpl() {
   switch (CanSetAsDefaultBrowser()) {
     case SET_DEFAULT_NOT_ALLOWED:
       NOTREACHED();
       break;
     case SET_DEFAULT_UNATTENDED:
-      if (SetAsDefaultBrowser())
-        result = AttemptResult::SUCCESS;
+      SetAsDefaultBrowser();
       break;
     case SET_DEFAULT_INTERACTIVE:
-      if (interactive_permitted_ && SetAsDefaultBrowserInteractive())
-        result = AttemptResult::SUCCESS;
+      if (interactive_permitted_)
+        SetAsDefaultBrowserInteractive();
       break;
   }
-  return result;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -297,25 +274,20 @@
   return IsDefaultProtocolClient(protocol_);
 }
 
-DefaultWebClientWorker::AttemptResult
-DefaultProtocolClientWorker::SetAsDefaultImpl() {
-  AttemptResult result = AttemptResult::FAILURE;
+void DefaultProtocolClientWorker::SetAsDefaultImpl() {
   switch (CanSetAsDefaultProtocolClient()) {
     case SET_DEFAULT_NOT_ALLOWED:
       // Not allowed, do nothing.
       break;
     case SET_DEFAULT_UNATTENDED:
-      if (SetAsDefaultProtocolClient(protocol_))
-        result = AttemptResult::SUCCESS;
+      SetAsDefaultProtocolClient(protocol_);
       break;
     case SET_DEFAULT_INTERACTIVE:
-      if (interactive_permitted_ &&
-          SetAsDefaultProtocolClientInteractive(protocol_)) {
-        result = AttemptResult::SUCCESS;
+      if (interactive_permitted_) {
+        SetAsDefaultProtocolClientInteractive(protocol_);
       }
       break;
   }
-  return result;
 }
 
 }  // namespace shell_integration
diff --git a/chrome/browser/shell_integration.h b/chrome/browser/shell_integration.h
index 99ef326e..e71dbfe 100644
--- a/chrome/browser/shell_integration.h
+++ b/chrome/browser/shell_integration.h
@@ -207,55 +207,15 @@
  protected:
   friend class base::RefCountedThreadSafe<DefaultWebClientWorker>;
 
-  // Possible result codes for a set-as-default operation.
-  // Do not modify the ordering as it is important for UMA.
-  enum AttemptResult {
-    // Chrome was set as the default web client.
-    SUCCESS = 0,
-    // Chrome was already the default web client. This counts as a successful
-    // attempt.
-    // Note: This result is no longer used since the removal of the Win10
-    // default browser experiment.
-    // ALREADY_DEFAULT = 1,
-    // Chrome was not set as the default web client.
-    FAILURE = 2,
-    // The attempt was abandoned because the observer was destroyed.
-    // Note: This result is no longer used since the removal of
-    // DefaultWebClientObserver.
-    // ABANDONED = 3,
-    // Failed to launch the process to set Chrome as the default web client
-    // asynchronously.
-    // Note: This result is no longer used since the removal of the Win10
-    // default browser experiment.
-    // LAUNCH_FAILURE = 4,
-    // Another worker is already in progress to make Chrome the default web
-    // client.
-    // Note: This result is no longer used since the removal of the Win10
-    // default browser experiment.
-    // OTHER_WORKER = 5,
-    // The user initiated another attempt while the asynchronous operation was
-    // already in progress.
-    RETRY = 6,
-    // No errors were encountered yet Chrome is still not the default web
-    // client.
-    NO_ERRORS_NOT_DEFAULT = 7,
-    NUM_ATTEMPT_RESULT_TYPES
-  };
-
   DefaultWebClientWorker(const DefaultWebClientWorkerCallback& callback,
                          const char* worker_name);
   virtual ~DefaultWebClientWorker();
 
-  // Communicates the result via the |callback_|. In contrast to
-  // OnSetAsDefaultAttemptComplete(), this should not be called multiple
-  // times.
-  void OnCheckIsDefaultComplete(DefaultWebClientState state);
-
-  // Called when the set as default operation is completed. This then invokes
-  // FinalizeSetAsDefault() and starts the check is default process.
-  // It is safe to call this multiple times. Only the first call is processed
-  // after StartSetAsDefault() is invoked.
-  void OnSetAsDefaultAttemptComplete(AttemptResult result);
+  // Communicates the result via the |callback_|. When
+  // |is_following_set_as_default| is true, |state| will be reported to UMA as
+  // the result of the set-as-default operation.
+  void OnCheckIsDefaultComplete(DefaultWebClientState state,
+                                bool is_following_set_as_default);
 
   // When false, the operation to set as default will fail for interactive
   // flows.
@@ -263,18 +223,19 @@
 
  private:
   // Checks whether Chrome is the default web client. Always called on the
-  // FILE thread.
-  void CheckIsDefault();
+  // FILE thread. When |is_following_set_as_default| is true, The default state
+  // will be reported to UMA as the result of the set-as-default operation.
+  void CheckIsDefault(bool is_following_set_as_default);
 
   // Sets Chrome as the default web client. Always called on the FILE thread.
   void SetAsDefault();
 
   // Implementation of CheckIsDefault() and SetAsDefault() for subclasses.
   virtual DefaultWebClientState CheckIsDefaultImpl() = 0;
-  virtual AttemptResult SetAsDefaultImpl() = 0;
+  virtual void SetAsDefaultImpl() = 0;
 
-  // Reports the result and duration for one set-as-default attempt.
-  void ReportAttemptResult(AttemptResult result);
+  // Reports the result for the set-as-default operation.
+  void ReportSetDefaultResult(DefaultWebClientState state);
 
   // Updates the UI in our associated view with the current default web
   // client state.
@@ -307,7 +268,7 @@
   DefaultWebClientState CheckIsDefaultImpl() override;
 
   // Set Chrome as the default browser.
-  AttemptResult SetAsDefaultImpl() override;
+  void SetAsDefaultImpl() override;
 
   DISALLOW_COPY_AND_ASSIGN(DefaultBrowserWorker);
 };
@@ -331,7 +292,7 @@
   DefaultWebClientState CheckIsDefaultImpl() override;
 
   // Set Chrome as the default handler for this protocol.
-  AttemptResult SetAsDefaultImpl() override;
+  void SetAsDefaultImpl() override;
 
   std::string protocol_;
 
diff --git a/chrome/browser/ssl/chrome_expect_ct_reporter.cc b/chrome/browser/ssl/chrome_expect_ct_reporter.cc
index f6e0175..9e3bd30 100644
--- a/chrome/browser/ssl/chrome_expect_ct_reporter.cc
+++ b/chrome/browser/ssl/chrome_expect_ct_reporter.cc
@@ -6,8 +6,102 @@
 
 #include <string>
 
+#include "base/base64.h"
+#include "base/command_line.h"
+#include "base/json/json_writer.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "chrome/common/chrome_switches.h"
 #include "net/url_request/certificate_report_sender.h"
 
+namespace {
+
+std::string TimeToISO8601(const base::Time& t) {
+  base::Time::Exploded exploded;
+  t.UTCExplode(&exploded);
+  return base::StringPrintf(
+      "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month,
+      exploded.day_of_month, exploded.hour, exploded.minute, exploded.second,
+      exploded.millisecond);
+}
+
+scoped_ptr<base::ListValue> GetPEMEncodedChainAsList(
+    const net::X509Certificate* cert_chain) {
+  if (!cert_chain)
+    return make_scoped_ptr(new base::ListValue());
+
+  scoped_ptr<base::ListValue> result(new base::ListValue());
+  std::vector<std::string> pem_encoded_chain;
+  cert_chain->GetPEMEncodedChain(&pem_encoded_chain);
+  for (const std::string& cert : pem_encoded_chain)
+    result->Append(make_scoped_ptr(new base::StringValue(cert)));
+
+  return result;
+}
+
+std::string SCTOriginToString(
+    net::ct::SignedCertificateTimestamp::Origin origin) {
+  switch (origin) {
+    case net::ct::SignedCertificateTimestamp::SCT_EMBEDDED:
+      return "embedded";
+    case net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION:
+      return "from-tls-extension";
+    case net::ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE:
+      return "from-ocsp-response";
+    default:
+      NOTREACHED();
+  }
+  return "";
+}
+
+void AddUnknownSCT(
+    const net::SignedCertificateTimestampAndStatus& sct_and_status,
+    base::ListValue* list) {
+  scoped_ptr<base::DictionaryValue> list_item(new base::DictionaryValue());
+  list_item->SetString("origin", SCTOriginToString(sct_and_status.sct->origin));
+  list->Append(std::move(list_item));
+}
+
+void AddInvalidSCT(
+    const net::SignedCertificateTimestampAndStatus& sct_and_status,
+    base::ListValue* list) {
+  scoped_ptr<base::DictionaryValue> list_item(new base::DictionaryValue());
+  list_item->SetString("origin", SCTOriginToString(sct_and_status.sct->origin));
+  std::string log_id;
+  base::Base64Encode(sct_and_status.sct->log_id, &log_id);
+  list_item->SetString("id", log_id);
+  list->Append(std::move(list_item));
+}
+
+void AddValidSCT(const net::SignedCertificateTimestampAndStatus& sct_and_status,
+                 base::ListValue* list) {
+  scoped_ptr<base::DictionaryValue> list_item(new base::DictionaryValue());
+  list_item->SetString("origin", SCTOriginToString(sct_and_status.sct->origin));
+
+  // The structure of the SCT object is defined in
+  // http://tools.ietf.org/html/rfc6962#section-4.1.
+  scoped_ptr<base::DictionaryValue> sct(new base::DictionaryValue());
+  sct->SetInteger("sct_version", sct_and_status.sct->version);
+  std::string log_id;
+  base::Base64Encode(sct_and_status.sct->log_id, &log_id);
+  sct->SetString("id", log_id);
+  base::TimeDelta timestamp =
+      sct_and_status.sct->timestamp - base::Time::UnixEpoch();
+  sct->SetString("timestamp", base::Int64ToString(timestamp.InMilliseconds()));
+  std::string extensions;
+  base::Base64Encode(sct_and_status.sct->extensions, &extensions);
+  sct->SetString("extensions", extensions);
+  std::string signature;
+  base::Base64Encode(sct_and_status.sct->signature.signature_data, &signature);
+  sct->SetString("signature", signature);
+
+  list_item->Set("sct", std::move(sct));
+  list->Append(std::move(list_item));
+}
+
+}  // namespace
+
 ChromeExpectCTReporter::ChromeExpectCTReporter(
     net::URLRequestContext* request_context)
     : report_sender_(new net::CertificateReportSender(
@@ -20,6 +114,55 @@
     const net::HostPortPair& host_port_pair,
     const GURL& report_uri,
     const net::SSLInfo& ssl_info) {
-  // TODO(estark): build and send a report about the policy
-  // violation. https://crbug.com/568806
+  if (report_uri.is_empty())
+    return;
+
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableExpectCTReporting)) {
+    return;
+  }
+
+  // TODO(estark): De-duplicate reports so that the same report isn't
+  // sent too often in some period of time.
+
+  base::DictionaryValue report;
+  report.SetString("hostname", host_port_pair.host());
+  report.SetInteger("port", host_port_pair.port());
+  report.SetString("date-time", TimeToISO8601(base::Time::Now()));
+  report.Set("served-certificate-chain",
+             GetPEMEncodedChainAsList(ssl_info.unverified_cert.get()));
+  report.Set("validated-certificate-chain",
+             GetPEMEncodedChainAsList(ssl_info.cert.get()));
+
+  scoped_ptr<base::ListValue> unknown_scts(new base::ListValue());
+  scoped_ptr<base::ListValue> invalid_scts(new base::ListValue());
+  scoped_ptr<base::ListValue> valid_scts(new base::ListValue());
+
+  for (const auto& sct_and_status : ssl_info.signed_certificate_timestamps) {
+    switch (sct_and_status.status) {
+      case net::ct::SCT_STATUS_LOG_UNKNOWN:
+        AddUnknownSCT(sct_and_status, unknown_scts.get());
+        break;
+      case net::ct::SCT_STATUS_INVALID:
+        AddInvalidSCT(sct_and_status, invalid_scts.get());
+        break;
+      case net::ct::SCT_STATUS_OK:
+        AddValidSCT(sct_and_status, valid_scts.get());
+        break;
+      default:
+        NOTREACHED();
+    }
+  }
+
+  report.Set("unknown-scts", std::move(unknown_scts));
+  report.Set("invalid-scts", std::move(invalid_scts));
+  report.Set("valid-scts", std::move(valid_scts));
+
+  std::string serialized_report;
+  if (!base::JSONWriter::Write(report, &serialized_report)) {
+    LOG(ERROR) << "Failed to serialize Expect CT report";
+    return;
+  }
+
+  report_sender_->Send(report_uri, serialized_report);
 }
diff --git a/chrome/browser/ssl/chrome_expect_ct_reporter.h b/chrome/browser/ssl/chrome_expect_ct_reporter.h
index 15e74da..c0cf4a4 100644
--- a/chrome/browser/ssl/chrome_expect_ct_reporter.h
+++ b/chrome/browser/ssl/chrome_expect_ct_reporter.h
@@ -30,6 +30,10 @@
                         const net::SSLInfo& ssl_info) override;
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(ChromeExpectCTReporterTest, NoCommandLineSwitch);
+  FRIEND_TEST_ALL_PREFIXES(ChromeExpectCTReporterTest, EmptyReportURI);
+  FRIEND_TEST_ALL_PREFIXES(ChromeExpectCTReporterTest, SendReport);
+
   scoped_ptr<net::CertificateReportSender> report_sender_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeExpectCTReporter);
diff --git a/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc b/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc
new file mode 100644
index 0000000..d8bd6beb
--- /dev/null
+++ b/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc
@@ -0,0 +1,353 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ssl/chrome_expect_ct_reporter.h"
+
+#include <string>
+
+#include "base/base64.h"
+#include "base/command_line.h"
+#include "base/json/json_reader.h"
+#include "base/values.h"
+#include "chrome/common/chrome_switches.h"
+#include "net/base/test_data_directory.h"
+#include "net/ssl/signed_certificate_timestamp_and_status.h"
+#include "net/test/cert_test_util.h"
+#include "net/url_request/certificate_report_sender.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace {
+
+// A test CertificateReportSender that exposes the latest report URI and
+// serialized report to be sent.
+class TestCertificateReportSender : public net::CertificateReportSender {
+ public:
+  TestCertificateReportSender()
+      : CertificateReportSender(
+            nullptr,
+            net::CertificateReportSender::DO_NOT_SEND_COOKIES) {}
+  ~TestCertificateReportSender() override {}
+
+  void Send(const GURL& report_uri,
+            const std::string& serialized_report) override {
+    latest_report_uri_ = report_uri;
+    latest_serialized_report_ = serialized_report;
+  }
+
+  const GURL& latest_report_uri() { return latest_report_uri_; }
+
+  const std::string& latest_serialized_report() {
+    return latest_serialized_report_;
+  }
+
+ private:
+  GURL latest_report_uri_;
+  std::string latest_serialized_report_;
+};
+
+// Constructs a net::SignedCertificateTimestampAndStatus with the given
+// information and appends it to |sct_list|.
+void MakeTestSCTAndStatus(
+    net::ct::SignedCertificateTimestamp::Origin origin,
+    const std::string& log_id,
+    const std::string& extensions,
+    const std::string& signature_data,
+    const base::Time& timestamp,
+    net::ct::SCTVerifyStatus status,
+    net::SignedCertificateTimestampAndStatusList* sct_list) {
+  scoped_refptr<net::ct::SignedCertificateTimestamp> sct(
+      new net::ct::SignedCertificateTimestamp());
+  sct->version = net::ct::SignedCertificateTimestamp::SCT_VERSION_1;
+  sct->log_id = log_id;
+  sct->extensions = extensions;
+  sct->timestamp = timestamp;
+  sct->signature.signature_data = signature_data;
+  sct->origin = origin;
+  sct_list->push_back(net::SignedCertificateTimestampAndStatus(sct, status));
+}
+
+// Checks that |expected_cert| matches the PEM-encoded certificate chain
+// in |chain|.
+void CheckReportCertificateChain(
+    const scoped_refptr<net::X509Certificate>& expected_cert,
+    const base::ListValue& chain) {
+  std::vector<std::string> pem_encoded_chain;
+  expected_cert->GetPEMEncodedChain(&pem_encoded_chain);
+  ASSERT_EQ(pem_encoded_chain.size(), chain.GetSize());
+
+  for (size_t i = 0; i < pem_encoded_chain.size(); i++) {
+    std::string cert_pem;
+    ASSERT_TRUE(chain.GetString(i, &cert_pem));
+    EXPECT_EQ(pem_encoded_chain[i], cert_pem);
+  }
+}
+
+// Converts the string value of a reported SCT's origin to a
+// net::ct::SignedCertificateTimestamp::Origin value.
+net::ct::SignedCertificateTimestamp::Origin SCTOriginStringToOrigin(
+    const std::string& origin_string) {
+  if (origin_string == "embedded")
+    return net::ct::SignedCertificateTimestamp::SCT_EMBEDDED;
+  if (origin_string == "from-tls-extension")
+    return net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION;
+  if (origin_string == "from-ocsp-response")
+    return net::ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE;
+  NOTREACHED();
+  return net::ct::SignedCertificateTimestamp::SCT_EMBEDDED;
+}
+
+// Checks that an SCT |sct| appears (with the format determined by
+// |status|) in |report_list|, a list of SCTs from an Expect CT
+// report. |status| determines the format in that only certain fields
+// are reported for certain verify statuses; SCTs from unknown logs
+// contain very little information, for example, to avoid compromising
+// privacy.
+void FindSCTInReportList(
+    const scoped_refptr<net::ct::SignedCertificateTimestamp>& sct,
+    net::ct::SCTVerifyStatus status,
+    const base::ListValue& report_list) {
+  bool found = false;
+  for (size_t i = 0; !found && i < report_list.GetSize(); i++) {
+    const base::DictionaryValue* report_sct;
+    ASSERT_TRUE(report_list.GetDictionary(i, &report_sct));
+
+    std::string origin;
+    ASSERT_TRUE(report_sct->GetString("origin", &origin));
+
+    switch (status) {
+      case net::ct::SCT_STATUS_LOG_UNKNOWN:
+        // SCTs from unknown logs only have an origin.
+        EXPECT_FALSE(report_sct->HasKey("sct"));
+        EXPECT_FALSE(report_sct->HasKey("id"));
+        if (SCTOriginStringToOrigin(origin) == sct->origin)
+          found = true;
+        break;
+
+      case net::ct::SCT_STATUS_INVALID: {
+        // Invalid SCTs have a log id and an origin and nothing else.
+        EXPECT_FALSE(report_sct->HasKey("sct"));
+        std::string id_base64;
+        ASSERT_TRUE(report_sct->GetString("id", &id_base64));
+        std::string id;
+        ASSERT_TRUE(base::Base64Decode(id_base64, &id));
+        if (SCTOriginStringToOrigin(origin) == sct->origin && id == sct->log_id)
+          found = true;
+        break;
+      }
+
+      case net::ct::SCT_STATUS_OK: {
+        // Valid SCTs have the full SCT.
+        const base::DictionaryValue* report_sct_object;
+        ASSERT_TRUE(report_sct->GetDictionary("sct", &report_sct_object));
+        int version;
+        ASSERT_TRUE(report_sct_object->GetInteger("sct_version", &version));
+        std::string id_base64;
+        ASSERT_TRUE(report_sct_object->GetString("id", &id_base64));
+        std::string id;
+        ASSERT_TRUE(base::Base64Decode(id_base64, &id));
+        std::string extensions_base64;
+        ASSERT_TRUE(
+            report_sct_object->GetString("extensions", &extensions_base64));
+        std::string extensions;
+        ASSERT_TRUE(base::Base64Decode(extensions_base64, &extensions));
+        std::string signature_data_base64;
+        ASSERT_TRUE(
+            report_sct_object->GetString("signature", &signature_data_base64));
+        std::string signature_data;
+        ASSERT_TRUE(base::Base64Decode(signature_data_base64, &signature_data));
+
+        if (version == sct->version &&
+            SCTOriginStringToOrigin(origin) == sct->origin &&
+            id == sct->log_id && extensions == sct->extensions &&
+            signature_data == sct->signature.signature_data) {
+          found = true;
+        }
+        break;
+      }
+      default:
+        NOTREACHED();
+    }
+  }
+  EXPECT_TRUE(found);
+}
+
+// Checks that all |expected_scts| appears in the given lists of SCTs
+// from an Expect CT report.
+void CheckReportSCTs(
+    const net::SignedCertificateTimestampAndStatusList& expected_scts,
+    const base::ListValue& unknown_scts,
+    const base::ListValue& invalid_scts,
+    const base::ListValue& valid_scts) {
+  EXPECT_EQ(
+      expected_scts.size(),
+      unknown_scts.GetSize() + invalid_scts.GetSize() + valid_scts.GetSize());
+  for (const auto& expected_sct : expected_scts) {
+    switch (expected_sct.status) {
+      case net::ct::SCT_STATUS_LOG_UNKNOWN:
+        ASSERT_NO_FATAL_FAILURE(FindSCTInReportList(
+            expected_sct.sct, net::ct::SCT_STATUS_LOG_UNKNOWN, unknown_scts));
+        break;
+      case net::ct::SCT_STATUS_INVALID:
+        ASSERT_NO_FATAL_FAILURE(FindSCTInReportList(
+            expected_sct.sct, net::ct::SCT_STATUS_INVALID, invalid_scts));
+        break;
+      case net::ct::SCT_STATUS_OK:
+        ASSERT_NO_FATAL_FAILURE(FindSCTInReportList(
+            expected_sct.sct, net::ct::SCT_STATUS_OK, valid_scts));
+        break;
+      default:
+        NOTREACHED();
+    }
+  }
+}
+
+// Checks that the |serialized_report| deserializes properly and
+// contains the correct information (hostname, port, served and
+// validated certificate chains, SCTs) for the given |host_port| and
+// |ssl_info|.
+void CheckExpectCTReport(const std::string& serialized_report,
+                         const net::HostPortPair& host_port,
+                         const net::SSLInfo& ssl_info) {
+  scoped_ptr<base::Value> value(base::JSONReader::Read(serialized_report));
+  ASSERT_TRUE(value);
+  ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY));
+
+  base::DictionaryValue* report_dict;
+  ASSERT_TRUE(value->GetAsDictionary(&report_dict));
+
+  std::string report_hostname;
+  EXPECT_TRUE(report_dict->GetString("hostname", &report_hostname));
+  EXPECT_EQ(host_port.host(), report_hostname);
+  int report_port;
+  EXPECT_TRUE(report_dict->GetInteger("port", &report_port));
+  EXPECT_EQ(host_port.port(), report_port);
+
+  const base::ListValue* report_served_certificate_chain = nullptr;
+  ASSERT_TRUE(report_dict->GetList("served-certificate-chain",
+                                   &report_served_certificate_chain));
+  ASSERT_NO_FATAL_FAILURE(CheckReportCertificateChain(
+      ssl_info.unverified_cert, *report_served_certificate_chain));
+
+  const base::ListValue* report_validated_certificate_chain = nullptr;
+  ASSERT_TRUE(report_dict->GetList("validated-certificate-chain",
+                                   &report_validated_certificate_chain));
+  ASSERT_NO_FATAL_FAILURE(CheckReportCertificateChain(
+      ssl_info.cert, *report_validated_certificate_chain));
+
+  const base::ListValue* report_unknown_scts = nullptr;
+  ASSERT_TRUE(report_dict->GetList("unknown-scts", &report_unknown_scts));
+  const base::ListValue* report_invalid_scts = nullptr;
+  ASSERT_TRUE(report_dict->GetList("invalid-scts", &report_invalid_scts));
+  const base::ListValue* report_valid_scts = nullptr;
+  ASSERT_TRUE(report_dict->GetList("valid-scts", &report_valid_scts));
+
+  ASSERT_NO_FATAL_FAILURE(CheckReportSCTs(
+      ssl_info.signed_certificate_timestamps, *report_unknown_scts,
+      *report_invalid_scts, *report_valid_scts));
+}
+
+}  // namespace
+
+// Test that no report is sent when the command line switch is not
+// enabled.
+TEST(ChromeExpectCTReporterTest, NoCommandLineSwitch) {
+  TestCertificateReportSender* sender = new TestCertificateReportSender();
+  net::TestURLRequestContext context;
+  ChromeExpectCTReporter reporter(&context);
+  reporter.report_sender_.reset(sender);
+  EXPECT_TRUE(sender->latest_report_uri().is_empty());
+  EXPECT_TRUE(sender->latest_serialized_report().empty());
+
+  net::SSLInfo ssl_info;
+  ssl_info.cert =
+      net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
+  ssl_info.unverified_cert = net::ImportCertFromFile(
+      net::GetTestCertsDirectory(), "localhost_cert.pem");
+
+  net::HostPortPair host_port("example.test", 443);
+  GURL report_uri("http://example-report.test");
+
+  reporter.OnExpectCTFailed(host_port, report_uri, ssl_info);
+  EXPECT_TRUE(sender->latest_report_uri().is_empty());
+  EXPECT_TRUE(sender->latest_serialized_report().empty());
+}
+
+// Test that no report is sent if the report URI is empty.
+TEST(ChromeExpectCTReporterTest, EmptyReportURI) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableExpectCTReporting);
+  TestCertificateReportSender* sender = new TestCertificateReportSender();
+  net::TestURLRequestContext context;
+  ChromeExpectCTReporter reporter(&context);
+  reporter.report_sender_.reset(sender);
+  EXPECT_TRUE(sender->latest_report_uri().is_empty());
+  EXPECT_TRUE(sender->latest_serialized_report().empty());
+
+  reporter.OnExpectCTFailed(net::HostPortPair("example.test", 443), GURL(),
+                            net::SSLInfo());
+  EXPECT_TRUE(sender->latest_report_uri().is_empty());
+  EXPECT_TRUE(sender->latest_serialized_report().empty());
+}
+
+// Test that a sent report has the right format.
+TEST(ChromeExpectCTReporterTest, SendReport) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableExpectCTReporting);
+  TestCertificateReportSender* sender = new TestCertificateReportSender();
+  net::TestURLRequestContext context;
+  ChromeExpectCTReporter reporter(&context);
+  reporter.report_sender_.reset(sender);
+  EXPECT_TRUE(sender->latest_report_uri().is_empty());
+  EXPECT_TRUE(sender->latest_serialized_report().empty());
+
+  net::SSLInfo ssl_info;
+  ssl_info.cert =
+      net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
+  ssl_info.unverified_cert = net::ImportCertFromFile(
+      net::GetTestCertsDirectory(), "localhost_cert.pem");
+
+  base::Time now = base::Time::Now();
+
+  // Append a variety of SCTs: two of each possible status, with a
+  // mixture of different origins.
+
+  MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+                       "unknown_log_id1", "extensions1", "signature1", now,
+                       net::ct::SCT_STATUS_LOG_UNKNOWN,
+                       &ssl_info.signed_certificate_timestamps);
+  MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+                       "unknown_log_id2", "extensions2", "signature2", now,
+                       net::ct::SCT_STATUS_LOG_UNKNOWN,
+                       &ssl_info.signed_certificate_timestamps);
+
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
+      "invalid_log_id1", "extensions1", "signature1", now,
+      net::ct::SCT_STATUS_INVALID, &ssl_info.signed_certificate_timestamps);
+  MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+                       "invalid_log_id2", "extensions2", "signature2", now,
+                       net::ct::SCT_STATUS_INVALID,
+                       &ssl_info.signed_certificate_timestamps);
+
+  MakeTestSCTAndStatus(
+      net::ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE,
+      "valid_log_id1", "extensions1", "signature1", now, net::ct::SCT_STATUS_OK,
+      &ssl_info.signed_certificate_timestamps);
+  MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+                       "valid_log_id2", "extensions2", "signature2", now,
+                       net::ct::SCT_STATUS_OK,
+                       &ssl_info.signed_certificate_timestamps);
+
+  net::HostPortPair host_port("example.test", 443);
+  GURL report_uri("http://example-report.test");
+
+  // Check that the report is sent and contains the correct information.
+  reporter.OnExpectCTFailed(host_port, report_uri, ssl_info);
+  EXPECT_EQ(report_uri, sender->latest_report_uri());
+  EXPECT_FALSE(sender->latest_serialized_report().empty());
+  ASSERT_NO_FATAL_FAILURE(CheckExpectCTReport(
+      sender->latest_serialized_report(), host_port, ssl_info));
+}
diff --git a/chrome/browser/ui/android/ssl_client_certificate_request.cc b/chrome/browser/ui/android/ssl_client_certificate_request.cc
index 1f11945..d9fd7a30 100644
--- a/chrome/browser/ui/android/ssl_client_certificate_request.cc
+++ b/chrome/browser/ui/android/ssl_client_certificate_request.cc
@@ -175,7 +175,8 @@
       base::Bind(&RecordClientCertificateKey, client_cert,
                  base::Passed(&private_key)),
       base::Bind(&content::ClientCertificateDelegate::ContinueWithCertificate,
-                 base::Owned(delegate.release()), client_cert));
+                 base::Owned(delegate.release()),
+                 base::RetainedRef(client_cert)));
 }
 
 static void NotifyClientCertificatesChanged() {
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc
index 86e85c52..69486c21 100644
--- a/chrome/browser/ui/app_list/app_list_view_delegate.cc
+++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -85,6 +85,11 @@
 #include "chrome/browser/web_applications/web_app_win.h"
 #endif
 
+#if !defined(OS_CHROMEOS)
+#include "chrome/grit/chromium_strings.h"
+#include "chrome/grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#endif
 
 namespace chrome {
 const char kAppLauncherCategoryTag[] = "AppLauncher";
@@ -786,6 +791,42 @@
   observers_.RemoveObserver(observer);
 }
 
+#if !defined(OS_CHROMEOS)
+base::string16 AppListViewDelegate::GetMessageTitle() const {
+  return l10n_util::GetStringUTF16(IDS_APP_LIST_MESSAGE_TITLE);
+}
+
+base::string16 AppListViewDelegate::GetMessageText(
+    size_t* message_break) const {
+  return l10n_util::GetStringFUTF16(IDS_APP_LIST_MESSAGE_TEXT, base::string16(),
+                                    message_break);
+}
+
+base::string16 AppListViewDelegate::GetAppsShortcutName() const {
+  return l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_APPS_SHORTCUT_NAME);
+}
+
+base::string16 AppListViewDelegate::GetLearnMoreText() const {
+  return l10n_util::GetStringUTF16(IDS_APP_LIST_MESSAGE_LEARN_MORE_TEXT);
+}
+
+base::string16 AppListViewDelegate::GetLearnMoreLink() const {
+  return l10n_util::GetStringUTF16(IDS_APP_LIST_MESSAGE_LEARN_MORE_LINK);
+}
+
+gfx::ImageSkia* AppListViewDelegate::GetAppsIcon() const {
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  // Ensure it's backed by a native image type in the ResourceBundle cache.
+  rb.GetNativeImageNamed(IDR_BOOKMARK_BAR_APPS_SHORTCUT);
+  return rb.GetImageSkiaNamed(IDR_BOOKMARK_BAR_APPS_SHORTCUT);
+}
+
+void AppListViewDelegate::OpenLearnMoreLink() {
+  controller_->OpenURL(profile_, GURL(GetLearnMoreLink()),
+                       ui::PAGE_TRANSITION_LINK, CURRENT_TAB);
+}
+#endif  // !defined(OS_CHROMEOS)
+
 void AppListViewDelegate::OnTemplateURLServiceChanged() {
   if (!app_list::switches::IsExperimentalAppListEnabled())
     return;
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.h b/chrome/browser/ui/app_list/app_list_view_delegate.h
index cb670a00..4453257 100644
--- a/chrome/browser/ui/app_list/app_list_view_delegate.h
+++ b/chrome/browser/ui/app_list/app_list_view_delegate.h
@@ -120,6 +120,15 @@
   bool ShouldCenterWindow() const override;
   void AddObserver(app_list::AppListViewDelegateObserver* observer) override;
   void RemoveObserver(app_list::AppListViewDelegateObserver* observer) override;
+#if !defined(OS_CHROMEOS)
+  base::string16 GetMessageTitle() const override;
+  base::string16 GetMessageText(size_t* message_break) const override;
+  base::string16 GetAppsShortcutName() const override;
+  base::string16 GetLearnMoreText() const override;
+  base::string16 GetLearnMoreLink() const override;
+  gfx::ImageSkia* GetAppsIcon() const override;
+  void OpenLearnMoreLink() override;
+#endif
 
   // Overridden from TemplateURLServiceObserver:
   void OnTemplateURLServiceChanged() override;
diff --git a/chrome/browser/ui/cocoa/animatable_view.h b/chrome/browser/ui/cocoa/animatable_view.h
index f84c2a58..e787419 100644
--- a/chrome/browser/ui/cocoa/animatable_view.h
+++ b/chrome/browser/ui/cocoa/animatable_view.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/mac/scoped_nsobject.h"
+#import "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/background_gradient_view.h"
 #import "chrome/browser/ui/cocoa/view_resizer.h"
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_bridge_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_bridge_unittest.mm
index 01b01d7..13a628c 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_bridge_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_bridge_unittest.mm
@@ -41,8 +41,7 @@
 - (id)initWithBrowser:(Browser*)browser {
   if ((self = [super initWithBrowser:browser
                         initialWidth:100  // arbitrary
-                            delegate:nil
-                      resizeDelegate:nil])) {
+                            delegate:nil])) {
     callbacks_.reset([[NSMutableArray alloc] init]);
   }
   return self;
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h
index 0fb924b..de9b1619 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h
@@ -209,9 +209,6 @@
   // Delegate that is informed about state changes in the bookmark bar.
   id<BookmarkBarControllerDelegate> delegate_;  // weak
 
-  // Delegate that can resize us.
-  id<ViewResizer> resizeDelegate_;  // weak
-
   // Logic for dealing with a click on a bookmark folder button.
   base::scoped_nsobject<BookmarkFolderTarget> folderTarget_;
 
@@ -306,16 +303,20 @@
 @property(assign, nonatomic) BOOL stateAnimationsEnabled;
 @property(assign, nonatomic) BOOL innerContentAnimationsEnabled;
 
-// Initializes the bookmark bar controller with the given browser
-// profile and delegates.
+// Initializes the bookmark bar controller with the given browser and delegate.
+// To properly manage vertical resizing of the bookmark bar, the caller must
+// also call -setResizeDelegate on the -controlledView. This should be done once
+// the initializer returns, since it will trigger nib loading.
 - (id)initWithBrowser:(Browser*)browser
          initialWidth:(CGFloat)initialWidth
-             delegate:(id<BookmarkBarControllerDelegate>)delegate
-       resizeDelegate:(id<ViewResizer>)resizeDelegate;
+             delegate:(id<BookmarkBarControllerDelegate>)delegate;
 
 // The Browser corresponding to this BookmarkBarController.
 - (Browser*)browser;
 
+// Strongly-typed version of [self view]. Note this may trigger nib loading.
+- (BookmarkBarToolbarView*)controlledView;
+
 // The controller for all bookmark bar context menus.
 - (BookmarkContextMenuCocoaController*)menuController;
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
index a42e5f6..44f18e5 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
@@ -6,8 +6,9 @@
 
 #include <stddef.h>
 
-#include "base/mac/bundle_locations.h"
-#include "base/mac/sdk_forward_declarations.h"
+#import "base/mac/bundle_locations.h"
+#import "base/mac/foundation_util.h"
+#import "base/mac/sdk_forward_declarations.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/sys_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -166,10 +167,6 @@
 - (void)moveToState:(BookmarkBar::State)nextState
       withAnimation:(BOOL)animate;
 
-// Return the backdrop to the bookmark bar as various types.
-- (BackgroundGradientView*)backgroundGradientView;
-- (AnimatableView*)animatableView;
-
 // Create buttons for all items in the given bookmark node tree.
 // Modifies self->buttons_.  Do not add more buttons than will fit on the view.
 - (void)addNodesToButtonList:(const BookmarkNode*)node;
@@ -257,8 +254,7 @@
 
 - (id)initWithBrowser:(Browser*)browser
          initialWidth:(CGFloat)initialWidth
-             delegate:(id<BookmarkBarControllerDelegate>)delegate
-       resizeDelegate:(id<ViewResizer>)resizeDelegate {
+             delegate:(id<BookmarkBarControllerDelegate>)delegate {
   if ((self = [super initWithNibName:@"BookmarkBar"
                               bundle:base::mac::FrameworkBundle()])) {
     currentState_ = BookmarkBar::HIDDEN;
@@ -271,7 +267,6 @@
         ManagedBookmarkServiceFactory::GetForProfile(browser_->profile());
     buttons_.reset([[NSMutableArray alloc] init]);
     delegate_ = delegate;
-    resizeDelegate_ = resizeDelegate;
     folderTarget_.reset(
         [[BookmarkFolderTarget alloc] initWithController:self
                                                  profile:browser_->profile()]);
@@ -295,11 +290,6 @@
     contextMenuController_.reset(
         [[BookmarkContextMenuCocoaController alloc]
             initWithBookmarkBarController:self]);
-
-    // This call triggers an -awakeFromNib, which builds the bar, which might
-    // use |folderImage_| and |contextMenuController_|. Ensure it happens after
-    // |folderImage_| is loaded and |contextMenuController_| is created.
-    [[self animatableView] setResizeDelegate:resizeDelegate];
   }
   return self;
 }
@@ -308,6 +298,10 @@
   return browser_;
 }
 
+- (BookmarkBarToolbarView*)controlledView {
+  return base::mac::ObjCCastStrict<BookmarkBarToolbarView>([self view]);
+}
+
 - (BookmarkContextMenuCocoaController*)menuController {
   return contextMenuController_.get();
 }
@@ -375,20 +369,28 @@
 }
 
 - (void)browserWillBeDestroyed {
+  // If |bridge_| is null it means -viewDidLoad has not yet been called, which
+  // can only happen if the nib wasn't loaded. Retrieving it via -[self view]
+  // would load it now, but it's too late for that, so let it be nil. Note this
+  // should only happen in tests.
+  BookmarkBarToolbarView* view = nil;
+  if (bridge_)
+    view = [self controlledView];
+
   // Clear delegate so it doesn't get called during stopAnimation.
-  [[self animatableView] setResizeDelegate:nil];
+  [view setResizeDelegate:nil];
 
   // We better stop any in-flight animation if we're being killed.
-  [[self animatableView] stopAnimation];
+  [view stopAnimation];
 
   // Remove our view from its superview so it doesn't attempt to reference
   // it when the controller is gone.
   //TODO(dmaclach): Remove -- http://crbug.com/25845
-  [[self view] removeFromSuperview];
+  [view removeFromSuperview];
 
   // Be sure there is no dangling pointer.
-  if ([[self view] respondsToSelector:@selector(setController:)])
-    [[self view] performSelector:@selector(setController:) withObject:nil];
+  if ([view respondsToSelector:@selector(setController:)])
+    [view performSelector:@selector(setController:) withObject:nil];
 
   // For safety, make sure the buttons can no longer call us.
   for (BookmarkButton* button in buttons_.get()) {
@@ -815,18 +817,6 @@
   [self updateTheme:[[[self view] window] themeProvider]];
 }
 
-// (Private) Method is the same as [self view], but is provided to be explicit.
-- (BackgroundGradientView*)backgroundGradientView {
-  DCHECK([[self view] isKindOfClass:[BackgroundGradientView class]]);
-  return (BackgroundGradientView*)[self view];
-}
-
-// (Private) Method is the same as [self view], but is provided to be explicit.
-- (AnimatableView*)animatableView {
-  DCHECK([[self view] isKindOfClass:[AnimatableView class]]);
-  return (AnimatableView*)[self view];
-}
-
 - (BookmarkLaunchLocation)bookmarkLaunchLocation {
   return currentState_ == BookmarkBar::DETACHED ?
       BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR :
@@ -960,16 +950,17 @@
     // Else fall through and do the change instantly.
   }
 
-  // Set our height.
-  [resizeDelegate_ resizeView:[self view]
-                    newHeight:[self preferredHeight]];
+  BookmarkBarToolbarView* view = [self controlledView];
+
+  // Set our height immediately via -[AnimatableView setHeight:].
+  [view setHeight:[self preferredHeight]];
 
   // Only show the divider if showing the normal bookmark bar.
   BOOL showsDivider = [self isInState:BookmarkBar::SHOW];
-  [[self backgroundGradientView] setShowsDivider:showsDivider];
+  [view setShowsDivider:showsDivider];
 
   // Make sure we're shown.
-  [[self view] setHidden:![self isVisible]];
+  [view setHidden:![self isVisible]];
 
   // Update everything else.
   [self layoutSubviews];
@@ -978,11 +969,11 @@
 
 // (Private)
 - (BOOL)doBookmarkBarAnimation {
+  BookmarkBarToolbarView* view = [self controlledView];
   if ([self isAnimatingFromState:BookmarkBar::HIDDEN
                          toState:BookmarkBar::SHOW]) {
-    [[self backgroundGradientView] setShowsDivider:YES];
-    [[self view] setHidden:NO];
-    AnimatableView* view = [self animatableView];
+    [view setShowsDivider:YES];
+    [view setHidden:NO];
     // Height takes into account the extra height we have since the toolbar
     // only compresses when we're done.
     [view animateToNewHeight:(chrome::kBookmarkBarHeight -
@@ -990,23 +981,20 @@
                     duration:kBookmarkBarAnimationDuration];
   } else if ([self isAnimatingFromState:BookmarkBar::SHOW
                                 toState:BookmarkBar::HIDDEN]) {
-    [[self backgroundGradientView] setShowsDivider:YES];
-    [[self view] setHidden:NO];
-    AnimatableView* view = [self animatableView];
+    [view setShowsDivider:YES];
+    [view setHidden:NO];
     [view animateToNewHeight:0
                     duration:kBookmarkBarAnimationDuration];
   } else if ([self isAnimatingFromState:BookmarkBar::SHOW
                                 toState:BookmarkBar::DETACHED]) {
-    [[self backgroundGradientView] setShowsDivider:YES];
-    [[self view] setHidden:NO];
-    AnimatableView* view = [self animatableView];
+    [view setShowsDivider:YES];
+    [view setHidden:NO];
     [view animateToNewHeight:chrome::kNTPBookmarkBarHeight
                     duration:kBookmarkBarAnimationDuration];
   } else if ([self isAnimatingFromState:BookmarkBar::DETACHED
                                 toState:BookmarkBar::SHOW]) {
-    [[self backgroundGradientView] setShowsDivider:YES];
-    [[self view] setHidden:NO];
-    AnimatableView* view = [self animatableView];
+    [view setShowsDivider:YES];
+    [view setHidden:NO];
     // Height takes into account the extra height we have since the toolbar
     // only compresses when we're done.
     [view animateToNewHeight:(chrome::kBookmarkBarHeight -
@@ -1525,7 +1513,7 @@
 
 // (Private)
 - (void)stopCurrentAnimation {
-  [[self animatableView] stopAnimation];
+  [[self controlledView] stopAnimation];
 }
 
 // Delegate method for |AnimatableView| (a superclass of
@@ -2452,11 +2440,11 @@
   }
   if ([self isAnimatingToState:BookmarkBar::DETACHED]) {
     return static_cast<CGFloat>(
-        [[self animatableView] currentAnimationProgress]);
+        [[self controlledView] currentAnimationProgress]);
   }
   if ([self isAnimatingFromState:BookmarkBar::DETACHED]) {
     return static_cast<CGFloat>(
-        1 - [[self animatableView] currentAnimationProgress]);
+        1 - [[self controlledView] currentAnimationProgress]);
   }
   return 0;
 }
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm
index 864d720..c3cde00b 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm
@@ -57,12 +57,10 @@
 
 - (id)initWithBrowser:(Browser*)browser
          initialWidth:(CGFloat)initialWidth
-             delegate:(id<BookmarkBarControllerDelegate>)delegate
-       resizeDelegate:(id<ViewResizer>)resizeDelegate {
+             delegate:(id<BookmarkBarControllerDelegate>)delegate {
   if ((self = [super initWithBrowser:browser
                         initialWidth:initialWidth
-                            delegate:delegate
-                      resizeDelegate:resizeDelegate])) {
+                            delegate:delegate])) {
     [self setStateAnimationsEnabled:NO];
     [self setInnerContentAnimationsEnabled:NO];
   }
@@ -190,12 +188,10 @@
 
 - (id)initWithBrowser:(Browser*)browser
          initialWidth:(CGFloat)initialWidth
-             delegate:(id<BookmarkBarControllerDelegate>)delegate
-       resizeDelegate:(id<ViewResizer>)resizeDelegate {
+             delegate:(id<BookmarkBarControllerDelegate>)delegate {
   if ((self = [super initWithBrowser:browser
                         initialWidth:initialWidth
-                            delegate:delegate
-                      resizeDelegate:resizeDelegate])) {
+                            delegate:delegate])) {
     dragDataNode_ = NULL;
   }
   return self;
@@ -312,8 +308,14 @@
   }
 
   void InstallAndToggleBar(BookmarkBarController* bar) {
-    // Force loading of the nib.
-    [bar view];
+    // In OSX 10.10, the owner of a nib file is retain/autoreleased during the
+    // initialization of the nib. Wrapping the nib loading in an
+    // autoreleasepool ensures that tests can control the destruction timing of
+    // the controller.
+    @autoreleasepool {
+      // Forces loading of the nib.
+      [[bar controlledView] setResizeDelegate:resizeDelegate_];
+    }
     // Awkwardness to look like we've been installed.
     for (NSView* subView in [parent_view_ subviews])
       [subView removeFromSuperview];
@@ -342,18 +344,10 @@
     ASSERT_TRUE(browser());
     AddCommandLineSwitches();
 
-    // In OSX 10.10, the owner of a nib file is retain/autoreleased during the
-    // initialization of the nib. Wrapping the constructor in an
-    // autoreleasepool ensures that tests can control the destruction timing of
-    // |bar_|.
-    @autoreleasepool {
-      bar_.reset([[BookmarkBarControllerNoOpen alloc]
-          initWithBrowser:browser()
-             initialWidth:NSWidth([parent_view_ frame])
-                 delegate:nil
-           resizeDelegate:resizeDelegate_.get()]);
-    }
-
+    bar_.reset([[BookmarkBarControllerNoOpen alloc]
+        initWithBrowser:browser()
+           initialWidth:NSWidth([parent_view_ frame])
+               delegate:nil]);
     InstallAndToggleBar(bar_.get());
 
     // AppKit methods are not guaranteed to complete synchronously. Some of them
@@ -508,12 +502,10 @@
 // Make sure we're watching for frame change notifications.
 TEST_F(BookmarkBarControllerTest, FrameChangeNotification) {
   base::scoped_nsobject<BookmarkBarControllerTogglePong> bar;
-  bar.reset(
-    [[BookmarkBarControllerTogglePong alloc]
-          initWithBrowser:browser()
-             initialWidth:100  // arbitrary
-                 delegate:nil
-           resizeDelegate:resizeDelegate_.get()]);
+  bar.reset([[BookmarkBarControllerTogglePong alloc]
+      initWithBrowser:browser()
+         initialWidth:100  // arbitrary
+             delegate:nil]);
   InstallAndToggleBar(bar.get());
 
   // Send a frame did change notification for the pong's view.
@@ -1223,7 +1215,8 @@
     EXPECT_TRUE([button action]);
   }
 
-  // This will dealloc....
+  // This should dealloc. In production code, this is typically achieved more
+  // reliably by using -[HasWeakBrowserPointer browserWillBeDestroyed].
   bar_.reset();
 
   // Make sure that everything is cleared.
@@ -1685,13 +1678,12 @@
 
     resizeDelegate_.reset([[ViewResizerPong alloc] init]);
     NSRect parent_frame = NSMakeRect(0, 0, 800, 50);
-    bar_.reset(
-               [[BookmarkBarControllerOpenAllPong alloc]
-                initWithBrowser:browser()
-                   initialWidth:NSWidth(parent_frame)
-                       delegate:nil
-                 resizeDelegate:resizeDelegate_.get()]);
-    [bar_ view];
+    bar_.reset([[BookmarkBarControllerOpenAllPong alloc]
+        initWithBrowser:browser()
+           initialWidth:NSWidth(parent_frame)
+               delegate:nil]);
+    // Forces loading of the nib.
+    [[bar_ controlledView] setResizeDelegate:resizeDelegate_];
     // Awkwardness to look like we've been installed.
     [parent_view_ addSubview:[bar_ view]];
     NSRect frame = [[[bar_ view] superview] frame];
@@ -1754,15 +1746,13 @@
     NSRect parent_frame = NSMakeRect(0, 0, 800, 50);
     parent_view_.reset([[NSView alloc] initWithFrame:parent_frame]);
     [parent_view_ setHidden:YES];
-    bar_.reset(
-      [[BookmarkBarControllerNotificationPong alloc]
-          initWithBrowser:browser()
-             initialWidth:NSWidth(parent_frame)
-                 delegate:nil
-           resizeDelegate:resizeDelegate_.get()]);
+    bar_.reset([[BookmarkBarControllerNotificationPong alloc]
+        initWithBrowser:browser()
+           initialWidth:NSWidth(parent_frame)
+               delegate:nil]);
 
-    // Force loading of the nib.
-    [bar_ view];
+    // Forces loading of the nib.
+    [[bar_ controlledView] setResizeDelegate:resizeDelegate_];
     // Awkwardness to look like we've been installed.
     [parent_view_ addSubview:[bar_ view]];
     NSRect frame = [[[bar_ view] superview] frame];
@@ -1816,12 +1806,10 @@
     BookmarkBarControllerTestBase::SetUp();
     ASSERT_TRUE(browser());
 
-    bar_.reset(
-               [[BookmarkBarControllerDragData alloc]
-                initWithBrowser:browser()
-                   initialWidth:NSWidth([parent_view_ frame])
-                       delegate:nil
-                 resizeDelegate:resizeDelegate_.get()]);
+    bar_.reset([[BookmarkBarControllerDragData alloc]
+        initWithBrowser:browser()
+           initialWidth:NSWidth([parent_view_ frame])
+               delegate:nil]);
     InstallAndToggleBar(bar_.get());
   }
 };
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm
index fa15a13..7aed14e 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm
@@ -170,12 +170,10 @@
     model->AddURL(folderB, folderB->child_count(), ASCIIToUTF16("t"),
                   GURL("http://www.google.com/c"));
 
-    bar_.reset(
-      [[BookmarkBarControllerChildFolderRedirect alloc]
-          initWithBrowser:browser()
-             initialWidth:300
-                 delegate:nil
-           resizeDelegate:nil]);
+    bar_.reset([[BookmarkBarControllerChildFolderRedirect alloc]
+        initWithBrowser:browser()
+           initialWidth:300
+               delegate:nil]);
     [bar_ loaded:model];
     // Make parent frame for bookmark bar then open it.
     NSRect frame = [[test_window() contentView] frame];
@@ -723,16 +721,15 @@
     parent_view_.reset([[NSView alloc] initWithFrame:parent_frame]);
     [parent_view_ setHidden:YES];
     bar_.reset([[BookmarkBarController alloc]
-                initWithBrowser:browser()
-                   initialWidth:NSWidth(parent_frame)
-                       delegate:nil
-                 resizeDelegate:resizeDelegate_.get()]);
+        initWithBrowser:browser()
+           initialWidth:NSWidth(parent_frame)
+               delegate:nil]);
     InstallAndToggleBar(bar_.get());
   }
 
   void InstallAndToggleBar(BookmarkBarController* bar) {
-    // Force loading of the nib.
-    [bar view];
+    // Forces loading of the nib.
+    [[bar controlledView] setResizeDelegate:resizeDelegate_];
     // Awkwardness to look like we've been installed.
     [parent_view_ addSubview:[bar view]];
     NSRect frame = [[[bar view] superview] frame];
@@ -1628,10 +1625,9 @@
     ASSERT_TRUE(browser());
 
     bar_.reset([[BookmarkBarControllerNoDelete alloc]
-                initWithBrowser:browser()
-                   initialWidth:NSWidth([parent_view_ frame])
-                       delegate:nil
-                 resizeDelegate:resizeDelegate_.get()]);
+        initWithBrowser:browser()
+           initialWidth:NSWidth([parent_view_ frame])
+               delegate:nil]);
     InstallAndToggleBar(bar_.get());
   }
 };
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_state.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_state.h
index 1a7eb51..f6e8dcc 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_state.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_state.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_BAR_STATE_H_
 #define CHROME_BROWSER_UI_COCOA_BOOKMARKS_BOOKMARK_BAR_STATE_H_
 
-#import <Cocoa/Cocoa.h>
+#include <CoreGraphics/CoreGraphics.h>
 
 #include "chrome/browser/ui/bookmarks/bookmark_bar.h"
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h
index 1ff85e3..ace88f6 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h
@@ -15,8 +15,6 @@
 #import "chrome/browser/ui/cocoa/animatable_view.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_state.h"
 
-@class BookmarkBarView;
-
 class Profile;
 
 // An interface to allow mocking of a BookmarkBarController by the
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_button.h
index 3f3d3abb..b968911 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button.h
@@ -190,7 +190,8 @@
 
 
 // Class for bookmark bar buttons that can be drag sources.
-@interface BookmarkButton : DraggableButton<ThemedWindowDrawing> {
+@interface BookmarkButton
+    : DraggableButton<ThemedWindowDrawing, NSDraggingSource> {
  @private
   IBOutlet NSObject<BookmarkButtonDelegate>* delegate_;  // Weak.
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_button.mm
index 6eea9367..4366431 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button.mm
@@ -9,8 +9,10 @@
 #include "base/logging.h"
 #include "base/mac/foundation_util.h"
 #import "base/mac/scoped_nsobject.h"
+#include "base/mac/sdk_forward_declarations.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h"
+#import "chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #import "chrome/browser/ui/cocoa/view_id_util.h"
 #include "components/bookmarks/browser/bookmark_model.h"
@@ -33,7 +35,19 @@
 BookmarkButton* gDraggedButton = nil; // Weak
 };
 
-@interface BookmarkButton(Private)
+@interface BookmarkButton() <NSPasteboardItemDataProvider>
+
+// NSPasteboardItemDataProvider:
+- (void)pasteboard:(NSPasteboard*)sender
+                  item:(NSPasteboardItem*)item
+    provideDataForType:(NSString*)type;
+
+// NSDraggingSource:
+- (void)draggingSession:(NSDraggingSession*)session
+           endedAtPoint:(NSPoint)aPoint
+              operation:(NSDragOperation)operation;
+- (NSDragOperation)draggingSession:(NSDraggingSession*)session
+    sourceOperationMaskForDraggingContext:(NSDraggingContext)context;
 
 // Make a drag image for the button.
 - (NSImage*)dragImage;
@@ -42,7 +56,6 @@
 
 @end  // @interface BookmarkButton(Private)
 
-
 @implementation BookmarkButton
 
 @synthesize delegate = delegate_;
@@ -175,10 +188,6 @@
   // the stack.
   [self retain];
 
-  // Ask our delegate to fill the pasteboard for us.
-  NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
-  [[self delegate] fillPasteboard:pboard forDragOfButton:self];
-
   // Lock bar visibility, forcing the overlay to stay visible if we are in
   // fullscreen mode.
   if ([[self delegate] dragShouldLockBarVisibility]) {
@@ -202,12 +211,23 @@
   dragPending_ = YES;
   gDraggedButton = self;
 
-  CGFloat yAt = [self bounds].size.height;
-  NSSize dragOffset = NSMakeSize(0.0, 0.0);
   NSImage* image = [self dragImage];
   [self setHidden:YES];
-  [self dragImage:image at:NSMakePoint(0, yAt) offset:dragOffset
-            event:event pasteboard:pboard source:self slideBack:YES];
+
+  NSPasteboardItem* pbItem = [NSPasteboardItem new];
+  [pbItem setDataProvider:self forTypes:@[ kBookmarkButtonDragType ]];
+
+  base::scoped_nsobject<NSDraggingItem> dragItem(
+      [[NSDraggingItem alloc] initWithPasteboardWriter:pbItem]);
+  [dragItem setDraggingFrame:[self bounds] contents:image];
+
+  [self beginDraggingSessionWithItems:@[ dragItem.get() ]
+                                event:event
+                               source:self];
+  while (gDraggedButton != nil) {
+    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
+                             beforeDate:[NSDate distantFuture]];
+  }
   [self setHidden:NO];
 
   // And we're done.
@@ -217,6 +237,27 @@
   [self autorelease];
 }
 
+- (void)pasteboard:(NSPasteboard*)sender
+                  item:(NSPasteboardItem*)item
+    provideDataForType:(NSString*)type {
+  [sender setData:[NSData dataWithBytes:&gDraggedButton
+                                 length:sizeof(gDraggedButton)]
+          forType:kBookmarkButtonDragType];
+}
+
+- (NSDragOperation)draggingSession:(NSDraggingSession*)session
+    sourceOperationMaskForDraggingContext:(NSDraggingContext)context {
+  NSDragOperation operation = NSDragOperationCopy;
+
+  if (context == NSDraggingContextWithinApplication)
+    operation |= NSDragOperationMove;
+
+  if ([delegate_ canDragBookmarkButtonToTrash:self])
+    operation |= NSDragOperationDelete;
+
+  return operation;
+}
+
 // Overridden to release bar visibility.
 - (DraggableButtonResult)endDrag {
   gDraggedButton = nil;
@@ -230,20 +271,9 @@
   return kDraggableButtonImplUseBase;
 }
 
-- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {
-  NSDragOperation operation = NSDragOperationCopy;
-  if (isLocal) {
-    operation |= NSDragOperationMove;
-  }
-  if ([delegate_ canDragBookmarkButtonToTrash:self]) {
-    operation |= NSDragOperationDelete;
-  }
-  return operation;
-}
-
-- (void)draggedImage:(NSImage *)anImage
-             endedAt:(NSPoint)aPoint
-           operation:(NSDragOperation)operation {
+- (void)draggingSession:(NSDraggingSession*)session
+           endedAtPoint:(NSPoint)aPoint
+              operation:(NSDragOperation)operation {
   gDraggedButton = nil;
   // Inform delegate of drag source that we're finished dragging,
   // so it can close auto-opened bookmark folders etc.
@@ -325,8 +355,6 @@
   return kDraggableButtonMixinDidWork;
 }
 
-
-
 // mouseEntered: and mouseExited: are called from our
 // BookmarkButtonCell.  We redirect this information to our delegate.
 // The controller can then perform menu-like actions (e.g. "hover over
@@ -428,11 +456,6 @@
   [self setNeedsDisplay:YES];
 }
 
-@end
-
-@implementation BookmarkButton(Private)
-
-
 - (void)installCustomTrackingArea {
   const NSTrackingAreaOptions options =
       NSTrackingActiveAlways |
@@ -451,7 +474,6 @@
   [self addTrackingArea:area_];
 }
 
-
 - (NSImage*)dragImage {
   NSRect bounds = [self bounds];
   base::scoped_nsobject<NSImage> image(
@@ -474,4 +496,4 @@
   return image.autorelease();
 }
 
-@end  // @implementation BookmarkButton(Private)
+@end
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_unittest.mm
index d7b8f7e..d92f30c 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_unittest.mm
@@ -154,27 +154,39 @@
   // Verify that if canDragBookmarkButtonToTrash is NO then the button can't
   // be dragged to the trash.
   delegate.get()->canDragToTrash_ = NO;
-  NSDragOperation operation = [button draggingSourceOperationMaskForLocal:NO];
+  NSDragOperation operation = [button draggingSession:nil
+                sourceOperationMaskForDraggingContext:
+                    NSDraggingContextOutsideApplication];
   EXPECT_EQ(0u, operation & NSDragOperationDelete);
-  operation = [button draggingSourceOperationMaskForLocal:YES];
+  operation = [button draggingSession:nil
+      sourceOperationMaskForDraggingContext:NSDraggingContextWithinApplication];
   EXPECT_EQ(0u, operation & NSDragOperationDelete);
 
   // Verify that if canDragBookmarkButtonToTrash is YES then the button can
   // be dragged to the trash.
   delegate.get()->canDragToTrash_ = YES;
-  operation = [button draggingSourceOperationMaskForLocal:NO];
+  operation = [button draggingSession:nil
+      sourceOperationMaskForDraggingContext:
+          NSDraggingContextOutsideApplication];
   EXPECT_EQ(NSDragOperationDelete, operation & NSDragOperationDelete);
-  operation = [button draggingSourceOperationMaskForLocal:YES];
+  operation = [button draggingSession:nil
+      sourceOperationMaskForDraggingContext:NSDraggingContextWithinApplication];
   EXPECT_EQ(NSDragOperationDelete, operation & NSDragOperationDelete);
 
   // Verify that canDragBookmarkButtonToTrash is called when expected.
   delegate.get()->canDragToTrash_ = YES;
   EXPECT_EQ(0, delegate.get()->didDragToTrashCount_);
-  [button draggedImage:nil endedAt:NSZeroPoint operation:NSDragOperationCopy];
+  [button draggingSession:nil
+             endedAtPoint:NSZeroPoint
+                operation:NSDragOperationCopy];
   EXPECT_EQ(0, delegate.get()->didDragToTrashCount_);
-  [button draggedImage:nil endedAt:NSZeroPoint operation:NSDragOperationMove];
+  [button draggingSession:nil
+             endedAtPoint:NSZeroPoint
+                operation:NSDragOperationMove];
   EXPECT_EQ(0, delegate.get()->didDragToTrashCount_);
-  [button draggedImage:nil endedAt:NSZeroPoint operation:NSDragOperationDelete];
+  [button draggingSession:nil
+             endedAtPoint:NSZeroPoint
+                operation:NSDragOperationDelete];
   EXPECT_EQ(1, delegate.get()->didDragToTrashCount_);
 }
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.mm
index c46cbc94..ba59cb2 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.mm
@@ -17,7 +17,7 @@
 using bookmarks::BookmarkNode;
 using bookmarks::BookmarkNodeData;
 
-NSString* kBookmarkButtonDragType = @"ChromiumBookmarkButtonDragType";
+NSString* kBookmarkButtonDragType = @"com.google.chrome.BookmarkButtonDrag";
 
 @interface BookmarkFolderTarget()
 // Copies the given bookmark node to the given pasteboard, declaring appropriate
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm
index c660dfd7a..e3e5683d 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -347,12 +347,13 @@
                        hasLocationBar:[self hasLocationBar]];
 
     // Create a sub-controller for the bookmark bar.
-    bookmarkBarController_.reset(
-        [[BookmarkBarController alloc]
-            initWithBrowser:browser_.get()
-               initialWidth:NSWidth([[[self window] contentView] frame])
-                   delegate:self
-             resizeDelegate:self]);
+    bookmarkBarController_.reset([[BookmarkBarController alloc]
+        initWithBrowser:browser_.get()
+           initialWidth:NSWidth([[[self window] contentView] frame])
+               delegate:self]);
+    // This call triggers an -awakeFromNib for ToolbarView.xib.
+    [[bookmarkBarController_ controlledView] setResizeDelegate:self];
+
     [bookmarkBarController_ setBookmarkBarEnabled:[self supportsBookmarkBar]];
 
     // Create the infobar container view, so we can pass it to the
diff --git a/chrome/browser/ui/cocoa/view_resizer.h b/chrome/browser/ui/cocoa/view_resizer.h
index 8b8f898..98fc983 100644
--- a/chrome/browser/ui/cocoa/view_resizer.h
+++ b/chrome/browser/ui/cocoa/view_resizer.h
@@ -5,9 +5,9 @@
 #ifndef CHROME_BROWSER_UI_COCOA_VIEW_RESIZER_H_
 #define CHROME_BROWSER_UI_COCOA_VIEW_RESIZER_H_
 
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#import <Foundation/Foundation.h>
 
-#import <Cocoa/Cocoa.h>
+@class NSView;
 
 // Defines a protocol that allows controllers to delegate resizing their views
 // to their parents.  When a controller needs to change a view's height, rather
diff --git a/chrome/browser/ui/views/bar_control_button.cc b/chrome/browser/ui/views/bar_control_button.cc
index eecd5186..6a7dff0 100644
--- a/chrome/browser/ui/views/bar_control_button.cc
+++ b/chrome/browser/ui/views/bar_control_button.cc
@@ -9,6 +9,7 @@
 #include "ui/gfx/vector_icons_public.h"
 #include "ui/views/animation/button_ink_drop_delegate.h"
 #include "ui/views/border.h"
+#include "ui/views/painter.h"
 
 namespace {
 
@@ -25,6 +26,8 @@
   set_has_ink_drop_action_on_click(true);
   SetImageAlignment(views::ImageButton::ALIGN_CENTER,
                     views::ImageButton::ALIGN_MIDDLE);
+  SetFocusPainter(nullptr);
+  UseMdFocusRing();
 }
 
 BarControlButton::~BarControlButton() {}
diff --git a/chrome/browser/ui/views/download/download_shelf_view.cc b/chrome/browser/ui/views/download/download_shelf_view.cc
index aedab020..9fb5f3a 100644
--- a/chrome/browser/ui/views/download/download_shelf_view.cc
+++ b/chrome/browser/ui/views/download/download_shelf_view.cc
@@ -318,13 +318,9 @@
                             show_all_size.width(),
                             show_all_size.height());
   next_x += show_all_size.width() + GetCloseAndLinkPadding();
-  // If the window is maximized, we want to expand the hitbox of the close
-  // button to the right and bottom to make it easier to click.
-  bool is_maximized = browser_->window()->IsMaximized();
-  int y = CenterPosition(close_button_size.height(), height());
-  close_button_->SetBounds(next_x, y,
-      is_maximized ? width() - next_x : close_button_size.width(),
-      is_maximized ? height() - y : close_button_size.height());
+  close_button_->SizeToPreferredSize();
+  close_button_->SetPosition(
+      gfx::Point(next_x, CenterPosition(close_button_->height(), height())));
   if (show_link_only) {
     // Let's hide all the items.
     for (auto ri = download_views_.rbegin(); ri != download_views_.rend(); ++ri)
diff --git a/chrome/browser/ui/views/find_bar_view.cc b/chrome/browser/ui/views/find_bar_view.cc
index 40b16b7..0420d9a 100644
--- a/chrome/browser/ui/views/find_bar_view.cc
+++ b/chrome/browser/ui/views/find_bar_view.cc
@@ -332,35 +332,30 @@
     if (view_width && view_width < panel_width)
       panel_width = view_width;
 
-    // First we draw the close button on the far right.
-    gfx::Size sz = close_button_->GetPreferredSize();
-    close_button_->SetBounds(panel_width - sz.width() -
-                                 kMarginRightOfCloseButton,
-                             (height() - sz.height()) / 2,
-                             sz.width(),
-                             sz.height());
     // Set the color.
     OnThemeChanged();
 
-    // Next, the FindNext button to the left the close button.
-    sz = find_next_button_->GetPreferredSize();
-    find_next_button_->SetBounds(close_button_->x() -
-                                     find_next_button_->width() -
-                                     kMarginLeftOfCloseButton,
-                                 (height() - sz.height()) / 2,
-                                  sz.width(),
-                                  sz.height());
+    // First we position the close button on the far right.
+    close_button_->SizeToPreferredSize();
+    close_button_->SetPosition(gfx::Point(
+        panel_width - close_button_->width() - kMarginRightOfCloseButton,
+        (height() - close_button_->height()) / 2));
 
-    // Then, the FindPrevious button to the left the FindNext button.
-    sz = find_previous_button_->GetPreferredSize();
-    find_previous_button_->SetBounds(find_next_button_->x() -
-                                         find_previous_button_->width(),
-                                     (height() - sz.height()) / 2,
-                                     sz.width(),
-                                     sz.height());
+    // Then, the next button to the left of the close button.
+    find_next_button_->SizeToPreferredSize();
+    find_next_button_->SetPosition(
+        gfx::Point(close_button_->x() - find_next_button_->width() -
+                       kMarginLeftOfCloseButton,
+                   (height() - find_next_button_->height()) / 2));
+
+    // Then, the previous button to the left of the next button.
+    find_previous_button_->SizeToPreferredSize();
+    find_previous_button_->SetPosition(gfx::Point(
+        find_next_button_->x() - find_previous_button_->width(),
+        (height() - find_previous_button_->height()) / 2));
 
     // Then the label showing the match count number.
-    sz = match_count_text_->GetPreferredSize();
+    gfx::Size sz = match_count_text_->GetPreferredSize();
     // We extend the label bounds a bit to give the background highlighting a
     // bit of breathing room (margins around the text).
     sz.Enlarge(kMatchCountExtraWidth, 0);
diff --git a/chrome/browser/ui/views/infobars/infobar_view.cc b/chrome/browser/ui/views/infobars/infobar_view.cc
index b0012dc..d7f97bb 100644
--- a/chrome/browser/ui/views/infobars/infobar_view.cc
+++ b/chrome/browser/ui/views/infobars/infobar_view.cc
@@ -234,6 +234,7 @@
   }
 
   int content_minimum_width = ContentMinimumWidth();
+  close_button_->SizeToPreferredSize();
   close_button_->SetPosition(gfx::Point(
       std::max(
           start_x + content_minimum_width +
@@ -275,7 +276,6 @@
       close_button_->SetImage(views::CustomButton::STATE_PRESSED,
                               rb.GetImageNamed(IDR_CLOSE_1_P).ToImageSkia());
     }
-    close_button_->SizeToPreferredSize();
     close_button_->SetAccessibleName(
         l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE));
     close_button_->SetFocusable(true);
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
index 702d763..defa838 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -265,15 +265,6 @@
   return model_->ContainsIndex(model_index) && model_->IsTabPinned(model_index);
 }
 
-bool BrowserTabStripController::IsNewTabPage(int model_index) const {
-  if (!model_->ContainsIndex(model_index))
-    return false;
-
-  const WebContents* contents = model_->GetWebContentsAt(model_index);
-  return contents && (contents->GetURL() == GURL(chrome::kChromeUINewTabURL) ||
-                      search::IsInstantNTP(contents));
-}
-
 void BrowserTabStripController::SelectTab(int model_index) {
   model_->ActivateTabAt(model_index, true);
 }
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
index 8ca58dd4..f06435d 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
@@ -53,7 +53,6 @@
   int GetActiveIndex() const override;
   bool IsTabSelected(int model_index) const override;
   bool IsTabPinned(int model_index) const override;
-  bool IsNewTabPage(int model_index) const override;
   void SelectTab(int model_index) override;
   void ExtendSelectionTo(int model_index) override;
   void ToggleSelected(int model_index) override;
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
index 8b5695c..3f79b7f 100644
--- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
@@ -70,10 +70,6 @@
   return false;
 }
 
-bool FakeBaseTabStripController::IsNewTabPage(int index) const {
-  return false;
-}
-
 void FakeBaseTabStripController::SelectTab(int index) {
   if (!IsValidIndex(index) || active_index_ == index)
     return;
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
index 675d499b..f2d8229 100644
--- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
@@ -31,7 +31,6 @@
   int GetActiveIndex() const override;
   bool IsTabSelected(int index) const override;
   bool IsTabPinned(int index) const override;
-  bool IsNewTabPage(int index) const override;
   void SelectTab(int index) override;
   void ExtendSelectionTo(int index) override;
   void ToggleSelected(int index) override;
diff --git a/chrome/browser/ui/views/tabs/tab_strip_controller.h b/chrome/browser/ui/views/tabs/tab_strip_controller.h
index 93357c3..b08a7295 100644
--- a/chrome/browser/ui/views/tabs/tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_strip_controller.h
@@ -50,9 +50,6 @@
   // Returns true if the selected index is pinned.
   virtual bool IsTabPinned(int index) const = 0;
 
-  // Returns true if the selected index is the new tab page.
-  virtual bool IsNewTabPage(int index) const = 0;
-
   // Select the tab at the specified index in the model.
   virtual void SelectTab(int index) = 0;
 
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index 6e05725..9f5e0980 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -1058,6 +1058,11 @@
 }
 
 void SigninScreenHandler::HandleRemoveUser(const AccountId& account_id) {
+  if (delegate_ &&
+      (delegate_->IsUserSigninCompleted() || delegate_->IsSigninInProgress())) {
+    return;
+  }
+
   ProfileMetrics::LogProfileDeleteUser(
       ProfileMetrics::DELETE_PROFILE_USER_MANAGER);
 
diff --git a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
index 75488fcb..b6d53be 100644
--- a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
@@ -339,14 +339,14 @@
     js_display->Set("availableColorProfiles", available_color_profiles);
 
     if (display_manager->GetNumDisplays() > 1) {
-      const ash::DisplayPlacement* placement =
+      const ash::DisplayPlacement placement =
           display_manager->GetCurrentDisplayLayout().FindPlacementById(
               display.id());
-      if (placement) {
+      if (placement.display_id != gfx::Display::kInvalidDisplayID) {
         js_display->SetString(
-            "parentId", base::Int64ToString(placement->parent_display_id));
-        js_display->SetInteger("layoutType", placement->position);
-        js_display->SetInteger("offset", placement->offset);
+            "parentId", base::Int64ToString(placement.parent_display_id));
+        js_display->SetInteger("layoutType", placement.position);
+        js_display->SetInteger("offset", placement.offset);
       }
     }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc b/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc
index ce26f05..4245c3b 100644
--- a/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc
@@ -56,20 +56,20 @@
       base::Bind(&EasyUnlockSettingsHandler::HandleGetEnabledStatus,
                  base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "easyUnlockLaunchSetup",
-      base::Bind(&EasyUnlockSettingsHandler::HandleLaunchSetup,
+      "easyUnlockStartTurnOnFlow",
+      base::Bind(&EasyUnlockSettingsHandler::HandleStartTurnOnFlow,
                  base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "easyUnlockGetTurnOffFlowStatus",
       base::Bind(&EasyUnlockSettingsHandler::HandleGetTurnOffFlowStatus,
                  base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "easyUnlockRequestTurnOff",
-      base::Bind(&EasyUnlockSettingsHandler::HandleRequestTurnOff,
+      "easyUnlockStartTurnOffFlow",
+      base::Bind(&EasyUnlockSettingsHandler::HandleStartTurnOffFlow,
                  base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "easyUnlockTurnOffOverlayDismissed",
-      base::Bind(&EasyUnlockSettingsHandler::HandlePageDismissed,
+      "easyUnlockCancelTurnOffFlow",
+      base::Bind(&EasyUnlockSettingsHandler::HandleCancelTurnOffFlow,
                  base::Unretained(this)));
 }
 
@@ -86,7 +86,10 @@
 }
 
 void EasyUnlockSettingsHandler::OnTurnOffOperationStatusChanged() {
-  SendTurnOffOperationStatus();
+  web_ui()->CallJavascriptFunction(
+      "cr.webUIListenerCallback",
+      base::StringValue("easy-unlock-turn-off-flow-status"),
+      base::StringValue(GetTurnOffFlowStatus()));
 }
 
 void EasyUnlockSettingsHandler::SendEnabledStatus() {
@@ -96,12 +99,12 @@
       base::FundamentalValue(EasyUnlockService::Get(profile_)->IsEnabled()));
 }
 
-void EasyUnlockSettingsHandler::SendTurnOffOperationStatus() {
+std::string EasyUnlockSettingsHandler::GetTurnOffFlowStatus() {
   EasyUnlockService::TurnOffFlowStatus status =
       EasyUnlockService::Get(profile_)->GetTurnOffFlowStatus();
 
   // Translate status into JS UI state string. Note the translated string
-  // should match UIState defined in easy_unlock_turn_off_overlay.js.
+  // should match UIState defined in easy_unlock_turn_off_dialog.js.
   std::string status_string;
   switch (status) {
     case EasyUnlockService::IDLE:
@@ -119,10 +122,7 @@
       break;
   }
 
-  web_ui()->CallJavascriptFunction(
-      "cr.webUIListenerCallback",
-      base::StringValue("easy-unlock-turn-off-flow-status"),
-      base::StringValue(status_string));
+  return status_string;
 }
 
 void EasyUnlockSettingsHandler::HandleGetEnabledStatus(
@@ -148,22 +148,26 @@
       base::FundamentalValue(EasyUnlockService::Get(profile_)->IsEnabled()));
 }
 
-void EasyUnlockSettingsHandler::HandleLaunchSetup(
+void EasyUnlockSettingsHandler::HandleStartTurnOnFlow(
     const base::ListValue* args) {
   EasyUnlockService::Get(profile_)->LaunchSetup();
 }
 
 void EasyUnlockSettingsHandler::HandleGetTurnOffFlowStatus(
     const base::ListValue* args) {
-  SendTurnOffOperationStatus();
+  CHECK_EQ(1U, args->GetSize());
+  const base::Value* callback_id;
+  CHECK(args->Get(0, &callback_id));
+  ResolveJavascriptCallback(*callback_id,
+                            base::StringValue(GetTurnOffFlowStatus()));
 }
 
-void EasyUnlockSettingsHandler::HandleRequestTurnOff(
+void EasyUnlockSettingsHandler::HandleStartTurnOffFlow(
     const base::ListValue* args) {
   EasyUnlockService::Get(profile_)->RunTurnOffFlow();
 }
 
-void EasyUnlockSettingsHandler::HandlePageDismissed(
+void EasyUnlockSettingsHandler::HandleCancelTurnOffFlow(
     const base::ListValue* args) {
   EasyUnlockService::Get(profile_)->ResetTurnOffFlow();
 }
diff --git a/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.h b/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.h
index 992461e..e3f5e82 100644
--- a/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.h
@@ -41,17 +41,17 @@
 
  private:
   FRIEND_TEST_ALL_PREFIXES(EasyUnlockSettingsHandlerTest, EnabledStatus);
-  FRIEND_TEST_ALL_PREFIXES(EasyUnlockSettingsHandlerTest, TurnOffStatus);
+  FRIEND_TEST_ALL_PREFIXES(EasyUnlockSettingsHandlerTest, TurnOffFlowStatus);
 
   void SendEnabledStatus();
-  void SendTurnOffOperationStatus();
+  std::string GetTurnOffFlowStatus();
 
   // JS callbacks.
   void HandleGetEnabledStatus(const base::ListValue* args);
-  void HandleLaunchSetup(const base::ListValue* args);
+  void HandleStartTurnOnFlow(const base::ListValue* args);
   void HandleGetTurnOffFlowStatus(const base::ListValue* args);
-  void HandleRequestTurnOff(const base::ListValue* args);
-  void HandlePageDismissed(const base::ListValue* args);
+  void HandleStartTurnOffFlow(const base::ListValue* args);
+  void HandleCancelTurnOffFlow(const base::ListValue* args);
 
   Profile* const profile_;
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc
index 47f2885..9b825b0 100644
--- a/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc
@@ -46,7 +46,7 @@
     NotifyTurnOffOperationStatusChanged();
   }
 
-  void SetTurnOffFailForTest() {
+  void SetTurnOffFlowFailForTest() {
     turn_off_status_ = FAIL;
     NotifyTurnOffOperationStatusChanged();
   }
@@ -134,8 +134,9 @@
     EXPECT_EQ(expected_status, status);
   }
 
-  void VerifyTurnOffStatusCallback(size_t expected_total_calls,
-                                   const std::string& expected_status) {
+  void VerifyTurnOffFlowStatusWebUIListenerCallback(
+      size_t expected_total_calls,
+      const std::string& expected_status) {
     std::string event;
     std::string status;
 
@@ -150,6 +151,24 @@
     EXPECT_EQ(expected_status, status);
   }
 
+  void VerifyTurnOffFlowStatusWebUIResponse(
+      size_t expected_total_calls,
+      const std::string& expected_callback_id,
+      const std::string& expected_status) {
+    EXPECT_EQ(expected_total_calls, web_ui()->call_data().size());
+
+    const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
+    EXPECT_EQ("cr.webUIResponse", data.function_name());
+
+    std::string callback_id;
+    ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
+    EXPECT_EQ(expected_callback_id, callback_id);
+
+    std::string actual_status;
+    ASSERT_TRUE(data.arg3()->GetAsString(&actual_status));
+    EXPECT_EQ(expected_status, actual_status);
+  }
+
  private:
   content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> profile_;
@@ -188,49 +207,55 @@
   list_args.Append(new base::StringValue("test-callback-id"));
   handler->HandleGetEnabledStatus(&list_args);
 
-  std::string callback_id;
-  bool enabled_status;
-
   EXPECT_EQ(3U, web_ui()->call_data().size());
 
   const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
   EXPECT_EQ("cr.webUIResponse", data.function_name());
 
+  std::string callback_id;
   ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
   EXPECT_EQ("test-callback-id", callback_id);
 
-  ASSERT_TRUE(data.arg2()->GetAsBoolean(&enabled_status));
+  bool enabled_status = false;
+  ASSERT_TRUE(data.arg3()->GetAsBoolean(&enabled_status));
   EXPECT_TRUE(enabled_status);
 }
 
-TEST_F(EasyUnlockSettingsHandlerTest, TurnOffStatus) {
+TEST_F(EasyUnlockSettingsHandlerTest, TurnOffFlowStatus) {
   scoped_ptr<EasyUnlockSettingsHandler> handler;
   handler.reset(new TestEasyUnlockSettingsHandler(profile()));
   handler->set_web_ui(web_ui());
 
   // Send an initial status query to turn on service observer.
-  base::ListValue list_args;
-  list_args.Append(new base::StringValue("test-callback-id"));
-  handler->HandleGetEnabledStatus(&list_args);
+  base::ListValue list_args1;
+  list_args1.Append(new base::StringValue("test-callback-id-1"));
+  handler->HandleGetEnabledStatus(&list_args1);
   EXPECT_EQ(1U, web_ui()->call_data().size());
 
-  handler->HandleGetTurnOffFlowStatus(nullptr);
-  VerifyTurnOffStatusCallback(2U, "idle");
+  base::ListValue list_args2;
+  list_args2.Append(new base::StringValue("test-callback-id-2"));
+  handler->HandleGetTurnOffFlowStatus(&list_args2);
+  VerifyTurnOffFlowStatusWebUIResponse(2U, "test-callback-id-2", "idle");
 
-  handler->HandleRequestTurnOff(nullptr);
-  VerifyTurnOffStatusCallback(3U, "pending");
+  handler->HandleStartTurnOffFlow(nullptr);
+  VerifyTurnOffFlowStatusWebUIListenerCallback(3U, "pending");
 
-  handler->HandleGetTurnOffFlowStatus(nullptr);
-  VerifyTurnOffStatusCallback(4U, "pending");
+  base::ListValue list_args3;
+  list_args3.Append(new base::StringValue("test-callback-id-3"));
+  handler->HandleGetTurnOffFlowStatus(&list_args3);
+  VerifyTurnOffFlowStatusWebUIResponse(4U, "test-callback-id-3", "pending");
 
-  handler->HandlePageDismissed(nullptr);
-  VerifyTurnOffStatusCallback(5U, "idle");
+  handler->HandleCancelTurnOffFlow(nullptr);
+  VerifyTurnOffFlowStatusWebUIListenerCallback(5U, "idle");
 
-  fake_easy_unlock_service()->SetTurnOffFailForTest();
-  VerifyTurnOffStatusCallback(6U, "server-error");
+  fake_easy_unlock_service()->SetTurnOffFlowFailForTest();
+  VerifyTurnOffFlowStatusWebUIListenerCallback(6U, "server-error");
 
-  handler->HandleGetTurnOffFlowStatus(nullptr);
-  VerifyTurnOffStatusCallback(7U, "server-error");
+  base::ListValue list_args4;
+  list_args4.Append(new base::StringValue("test-callback-id-4"));
+  handler->HandleGetTurnOffFlowStatus(&list_args4);
+  VerifyTurnOffFlowStatusWebUIResponse(7U, "test-callback-id-4",
+                                       "server-error");
 }
 
 }  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index e53229a..e39adbd0 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -34,8 +34,11 @@
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
 #include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
+#else
+#include "chrome/browser/ui/webui/settings/system_handler.h"
 #endif
 
+namespace settings {
 namespace {
 
 // Note that settings.html contains a <script> tag which imports a script of
@@ -67,6 +70,7 @@
       {"advancedPageTitle", IDS_SETTINGS_ADVANCED},
       {"basicPageTitle", IDS_SETTINGS_BASIC},
       {"settings", IDS_SETTINGS_SETTINGS},
+      {"restart", IDS_SETTINGS_RESTART},
   };
   AddLocalizedStringsBulk(html_source, localized_strings,
                           arraysize(localized_strings));
@@ -366,7 +370,7 @@
     {"powerwashTitle", IDS_OPTIONS_FACTORY_RESET},
     {"powerwashDialogTitle", IDS_OPTIONS_FACTORY_RESET_HEADING},
     {"powerwashDialogExplanation", IDS_OPTIONS_FACTORY_RESET_WARNING},
-    {"powerwashDialogButton", IDS_RELAUNCH_BUTTON},
+    {"powerwashDialogButton", IDS_SETTINGS_RESTART},
     {"powerwashLearnMoreUrl", IDS_FACTORY_RESET_HELP_URL},
 #endif
     // Automatic reset banner.
@@ -497,7 +501,6 @@
        IDS_OPTIONS_LANGUAGES_OFFER_TO_TRANSLATE_IN_THIS_LANGUAGE},
       {"cannotTranslateInThisLanguage",
        IDS_OPTIONS_LANGUAGES_CANNOT_TRANSLATE_IN_THIS_LANGUAGE},
-      {"restart", IDS_OPTIONS_SETTINGS_LANGUAGES_RELAUNCH_BUTTON},
       {"editDictionaryPageTitle", IDS_SETTINGS_LANGUAGES_EDIT_DICTIONARY_TITLE},
       {"addDictionaryWordLabel", IDS_SETTINGS_LANGUAGES_ADD_DICTIONARY_WORD},
       {"addDictionaryWordButton",
@@ -810,6 +813,10 @@
   };
   AddLocalizedStringsBulk(html_source, localized_strings,
                           arraysize(localized_strings));
+
+  // TODO(dbeam): we should probably rename anything involving "localized
+  // strings" to "load time data" as all primitive types are used now.
+  SystemHandler::AddLoadTimeData(html_source);
 }
 #endif
 
@@ -846,8 +853,6 @@
 
 }  // namespace
 
-namespace settings {
-
 void AddLocalizedStrings(content::WebUIDataSource* html_source,
                          Profile* profile) {
   AddCommonStrings(html_source);
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index c748fbd..035e5e84 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -22,7 +22,6 @@
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 #include "chrome/browser/ui/webui/settings/settings_startup_pages_handler.h"
 #include "chrome/browser/ui/webui/settings/site_settings_handler.h"
-#include "chrome/browser/ui/webui/settings/system_handler.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
@@ -37,6 +36,7 @@
 #else  // !defined(OS_CHROMEOS)
 #include "chrome/browser/ui/webui/settings/settings_default_browser_handler.h"
 #include "chrome/browser/ui/webui/settings/settings_manage_profile_handler.h"
+#include "chrome/browser/ui/webui/settings/system_handler.h"
 #endif  // defined(OS_CHROMEOS)
 
 #if defined(USE_NSS_CERTS)
@@ -63,7 +63,6 @@
   AddSettingsPageUIHandler(new SearchEnginesHandler(profile));
   AddSettingsPageUIHandler(new SiteSettingsHandler(profile));
   AddSettingsPageUIHandler(new StartupPagesHandler(web_ui));
-  AddSettingsPageUIHandler(new SystemHandler());
 
 #if defined(OS_CHROMEOS)
   AddSettingsPageUIHandler(new chromeos::settings::ChangePictureHandler());
@@ -71,6 +70,7 @@
 #else
   AddSettingsPageUIHandler(new DefaultBrowserHandler(web_ui));
   AddSettingsPageUIHandler(new ManageProfileHandler(profile));
+  AddSettingsPageUIHandler(new SystemHandler());
 #endif
 
   content::WebUIDataSource* html_source =
diff --git a/chrome/browser/ui/webui/settings/system_handler.cc b/chrome/browser/ui/webui/settings/system_handler.cc
index 49835c5d..bbfedae 100644
--- a/chrome/browser/ui/webui/settings/system_handler.cc
+++ b/chrome/browser/ui/webui/settings/system_handler.cc
@@ -4,14 +4,24 @@
 
 #include "chrome/browser/ui/webui/settings/system_handler.h"
 
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
-#include "content/public/browser/web_ui.h"
-
-#if !defined(OS_CHROMEOS)
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/gpu/gpu_mode_manager.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/ui/webui/settings_utils.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+
+#if defined(OS_WIN)
+#include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
+#include "chrome/common/chrome_constants.h"
 #endif
 
 namespace settings {
@@ -20,19 +30,45 @@
 
 SystemHandler::~SystemHandler() {}
 
+// static
+void SystemHandler::AddLoadTimeData(content::WebUIDataSource* data_source) {
+  data_source->AddBoolean("hardwareAccelerationEnabledAtStartup",
+      g_browser_process->gpu_mode_manager()->initial_gpu_mode_pref());
+}
+
 void SystemHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback("changeProxySettings",
       base::Bind(&SystemHandler::HandleChangeProxySettings,
                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback("restartBrowser",
+      base::Bind(&SystemHandler::HandleRestartBrowser,
+                 base::Unretained(this)));
 }
 
 void SystemHandler::HandleChangeProxySettings(const base::ListValue* /*args*/) {
   base::RecordAction(base::UserMetricsAction("Options_ShowProxySettings"));
-#if defined(OS_CHROMEOS)
-  NOTREACHED();
-#else
   settings_utils::ShowNetworkProxySettings(web_ui()->GetWebContents());
+}
+
+void SystemHandler::HandleRestartBrowser(const base::ListValue* /*args*/) {
+#if defined(OS_WIN)
+  // On Windows Breakpad will upload crash reports if the breakpad pipe name
+  // environment variable is defined. So we undefine this environment variable
+  // before restarting, as the restarted processes will inherit their
+  // environment variables from ours, thus suppressing crash uploads.
+  if (!ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled()) {
+    HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName);
+    if (exe_module) {
+      typedef void (__cdecl *ClearBreakpadPipeEnvVar)();
+      ClearBreakpadPipeEnvVar clear = reinterpret_cast<ClearBreakpadPipeEnvVar>(
+          GetProcAddress(exe_module, "ClearBreakpadPipeEnvironmentVariable"));
+      if (clear)
+        clear();
+    }
+  }
 #endif
+
+  chrome::AttemptRestart();
 }
 
 }  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/system_handler.h b/chrome/browser/ui/webui/settings/system_handler.h
index ea7ca04..446cc5f2 100644
--- a/chrome/browser/ui/webui/settings/system_handler.h
+++ b/chrome/browser/ui/webui/settings/system_handler.h
@@ -12,6 +12,10 @@
 class ListValue;
 }
 
+namespace content {
+class WebUIDataSource;
+}
+
 namespace settings {
 
 class SystemHandler : public SettingsPageUIHandler {
@@ -19,6 +23,9 @@
   SystemHandler();
   ~SystemHandler() override;
 
+  // Populates handler-specific loadTimeData values used by the system page.
+  static void AddLoadTimeData(content::WebUIDataSource* data_source);
+
   // SettingsPageUIHandler:
   void RegisterMessages() override;
 
@@ -26,6 +33,9 @@
   // Handler for the "changeProxySettings" message. No args.
   void HandleChangeProxySettings(const base::ListValue* /*args*/);
 
+  // Handler for the "restartBrowser" message. No args.
+  void HandleRestartBrowser(const base::ListValue* /*args*/);
+
   DISALLOW_COPY_AND_ASSIGN(SystemHandler);
 };
 
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index b752241f..b7d3609 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -9,6 +9,8 @@
     'browser_chromeos_sources': [
         # All .cc, .h, .m, and .mm files under browser/chromeos, except for tests
         # and mocks.
+        'browser/chromeos/accessibility/accessibility_highlight_manager.cc',
+        'browser/chromeos/accessibility/accessibility_highlight_manager.h',
         'browser/chromeos/accessibility/accessibility_manager.cc',
         'browser/chromeos/accessibility/accessibility_manager.h',
         'browser/chromeos/accessibility/accessibility_util.cc',
@@ -81,6 +83,8 @@
         'browser/chromeos/attestation/platform_verification_impl.h',
         'browser/chromeos/background/ash_user_wallpaper_delegate.cc',
         'browser/chromeos/background/ash_user_wallpaper_delegate.h',
+        'browser/chromeos/base/file_flusher.cc',
+        'browser/chromeos/base/file_flusher.h',
         'browser/chromeos/base/locale_util.cc',
         'browser/chromeos/base/locale_util.h',
         'browser/chromeos/bluetooth/bluetooth_pairing_dialog.cc',
@@ -1006,6 +1010,8 @@
         'browser/chromeos/system_logs/touch_log_source.h',
         'browser/chromeos/system_logs/touch_log_source_ozone.cc',
         'browser/chromeos/system_logs/touch_log_source_x11.cc',
+        'browser/chromeos/ui/accessibility_cursor_ring_layer.cc',
+        'browser/chromeos/ui/accessibility_cursor_ring_layer.h',
         'browser/chromeos/ui/accessibility_focus_ring.cc',
         'browser/chromeos/ui/accessibility_focus_ring.h',
         'browser/chromeos/ui/accessibility_focus_ring_controller.cc',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index 0fc47a9c..3239cda 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -1343,6 +1343,8 @@
       'browser/ui/webui/app_launcher_page_ui.h',
       'browser/ui/webui/settings/settings_default_browser_handler.cc',
       'browser/ui/webui/settings/settings_default_browser_handler.h',
+      'browser/ui/webui/settings/system_handler.cc',
+      'browser/ui/webui/settings/system_handler.h',
       'browser/ui/webui/signin/inline_login_handler.cc',
       'browser/ui/webui/signin/inline_login_handler.h',
       'browser/ui/webui/signin/inline_login_handler_impl.cc',
@@ -2037,8 +2039,6 @@
       'browser/ui/webui/settings/settings_startup_pages_handler.h',
       'browser/ui/webui/settings/site_settings_handler.cc',
       'browser/ui/webui/settings/site_settings_handler.h',
-      'browser/ui/webui/settings/system_handler.cc',
-      'browser/ui/webui/settings/system_handler.h',
       'browser/ui/webui/settings_utils.h',
       'browser/ui/webui/settings_utils_linux.cc',
       'browser/ui/webui/settings_utils_mac.mm',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index fce94942..dae5910 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -238,6 +238,7 @@
       'browser/signin/signin_status_metrics_provider_chromeos_unittest.cc',
       'browser/signin/signin_tracker_unittest.cc',
       'browser/signin/test_signin_client_builder.cc',
+      'browser/ssl/chrome_expect_ct_reporter_unittest.cc',
       'browser/ssl/ssl_error_handler_unittest.cc',
       'browser/status_icons/status_icon_menu_model_unittest.cc',
       'browser/status_icons/status_icon_unittest.cc',
@@ -949,6 +950,7 @@
       'browser/chromeos/attestation/fake_certificate.cc',
       'browser/chromeos/attestation/fake_certificate.h',
       'browser/chromeos/attestation/platform_verification_flow_unittest.cc',
+      'browser/chromeos/base/file_flusher_unittest.cc',
       'browser/chromeos/certificate_provider/certificate_provider_service_unittest.cc',
       'browser/chromeos/customization/customization_document_unittest.cc',
       'browser/chromeos/display/display_preferences_unittest.cc',
@@ -1438,6 +1440,7 @@
       'browser/media/router/presentation_service_delegate_impl_unittest.cc',
     ],
     'chrome_unit_tests_media_router_non_android_sources': [
+      'browser/media/router/media_router_metrics_unittest.cc',
       'browser/media/router/media_router_mojo_impl_unittest.cc',
       'browser/media/router/media_router_type_converters_unittest.cc',
       'browser/ui/toolbar/media_router_action_unittest.cc',
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 040608a..a5595ff 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -402,6 +402,10 @@
 // Enables Domain Reliability Monitoring.
 const char kEnableDomainReliability[] = "enable-domain-reliability";
 
+// Enables Expect CT reporting, which sends reports for opted-in sites
+// that don't serve sufficient Certificate Transparency information.
+const char kEnableExpectCTReporting[] = "enable-expect-ct-reporting";
+
 // Enables experimental hotword features specific to always-on.
 const char kEnableExperimentalHotwordHardware[] = "enable-hotword-hardware";
 
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index e7963b6..feed2261 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -116,6 +116,7 @@
 extern const char kEnableDevToolsExperiments[];
 extern const char kEnableDeviceDiscoveryNotifications[];
 extern const char kEnableDomainReliability[];
+extern const char kEnableExpectCTReporting[];
 extern const char kEnableExperimentalHotwordHardware[];
 extern const char kEnableExtensionActivityLogging[];
 extern const char kEnableExtensionActivityLogTesting[];
diff --git a/chrome/common/crash_keys.cc b/chrome/common/crash_keys.cc
index 75fcfda1..f627dc934 100644
--- a/chrome/common/crash_keys.cc
+++ b/chrome/common/crash_keys.cc
@@ -174,6 +174,10 @@
     { "initrf_view_id", kSmallSize },
     { "initrf_main_frame_id", kSmallSize },
     { "initrf_view_is_live", kSmallSize },
+
+    // Temporary for https://crbug.com/591478.
+    { "initrf_parent_proxy_exists", kSmallSize },
+    { "initrf_render_view_is_live", kSmallSize },
   };
 
   // This dynamic set of keys is used for sets of key value pairs when gathering
diff --git a/chrome/common/extensions/api/developer_private.idl b/chrome/common/extensions/api/developer_private.idl
index 564b1cb..bf6e490 100644
--- a/chrome/common/extensions/api/developer_private.idl
+++ b/chrome/common/extensions/api/developer_private.idl
@@ -5,7 +5,7 @@
 // developerPrivate API.
 // This is a private API exposing developing and debugging functionalities for
 // apps and extensions.
-namespace developerPrivate {
+[use_movable_types=true] namespace developerPrivate {
 
   // DEPRECATED: Prefer ExtensionType.
   enum ItemType {
diff --git a/chrome/test/data/android/media/mp3-play.html b/chrome/test/data/android/media/audio-play.html
similarity index 88%
rename from chrome/test/data/android/media/mp3-play.html
rename to chrome/test/data/android/media/audio-play.html
index 2800f9c..2596373 100644
--- a/chrome/test/data/android/media/mp3-play.html
+++ b/chrome/test/data/android/media/audio-play.html
@@ -1,7 +1,7 @@
 <html>
 <title>test</title>
 <body bgcolor="Silver">
-  <audio id='audio1' src="mpthreetest.mp3" controls></audio>
+  <audio id='audio1' src="audio.ogg" controls></audio>
   <script>
     var audio = document.getElementById('audio1');
     var mediaElement = audio;
diff --git a/chrome/test/data/android/media/audio.ogg b/chrome/test/data/android/media/audio.ogg
new file mode 100644
index 0000000..f576e1b6
--- /dev/null
+++ b/chrome/test/data/android/media/audio.ogg
Binary files differ
diff --git a/chrome/test/data/android/media/mpthreetest.mp3 b/chrome/test/data/android/media/mpthreetest.mp3
deleted file mode 100644
index a6853a7..0000000
--- a/chrome/test/data/android/media/mpthreetest.mp3
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/media/simple_video.html b/chrome/test/data/android/media/simple_video.html
index 5c76e8c..4a6496e 100644
--- a/chrome/test/data/android/media/simple_video.html
+++ b/chrome/test/data/android/media/simple_video.html
@@ -1,6 +1,6 @@
 <html>
 <title>test</title>
 <body bgcolor="Silver">
-<video src="test.mp4" controls id="video"></video>
+<video src="test.webm" controls id="video"></video>
 </body>
 </html>
diff --git a/chrome/test/data/android/media/simple_video2.html b/chrome/test/data/android/media/simple_video2.html
index ffe6758..7e227e6 100644
--- a/chrome/test/data/android/media/simple_video2.html
+++ b/chrome/test/data/android/media/simple_video2.html
@@ -1,6 +1,6 @@
 <html>
 <title>test</title>
 <body bgcolor="Silver">
-<video src="test2.mp4" controls id="video"></video>
+<video src="test2.webm" controls id="video"></video>
 </body>
 </html>
diff --git a/chrome/test/data/android/media/test.mp4 b/chrome/test/data/android/media/test.mp4
deleted file mode 100644
index d278c8a..0000000
--- a/chrome/test/data/android/media/test.mp4
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/media/test.webm b/chrome/test/data/android/media/test.webm
index f1a92fc..274bb75 100644
--- a/chrome/test/data/android/media/test.webm
+++ b/chrome/test/data/android/media/test.webm
Binary files differ
diff --git a/chrome/test/data/android/media/test2.mp4 b/chrome/test/data/android/media/test2.mp4
deleted file mode 100644
index d278c8a..0000000
--- a/chrome/test/data/android/media/test2.mp4
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/media/test2.webm b/chrome/test/data/android/media/test2.webm
new file mode 100644
index 0000000..db2e3bdc
--- /dev/null
+++ b/chrome/test/data/android/media/test2.webm
Binary files differ
diff --git a/chrome/test/data/android/media/two_videos.html b/chrome/test/data/android/media/two_videos.html
index 0481e59..8c35180 100644
--- a/chrome/test/data/android/media/two_videos.html
+++ b/chrome/test/data/android/media/two_videos.html
@@ -1,7 +1,7 @@
 <html>
 <title>test</title>
 <body bgcolor="Silver">
-<video src="test.mp4" controls id="video"></video>
-<video src="test2.mp4" controls id="video2"></video>
+<video src="test.webm" controls id="video"></video>
+<video src="test2.webm" controls id="video2"></video>
 </body>
 </html>
diff --git a/chrome/test/data/android/media/video-fullscreen.html b/chrome/test/data/android/media/video-fullscreen.html
index 7cf12db..f9387cd9 100644
--- a/chrome/test/data/android/media/video-fullscreen.html
+++ b/chrome/test/data/android/media/video-fullscreen.html
@@ -6,6 +6,6 @@
 };
 </script>
 <body>
-<video src="test.mp4" controls id="video"></video>
+<video src="test.webm" controls id="video"></video>
 </body>
 </html>
diff --git a/chrome/test/data/android/media/video-play.html b/chrome/test/data/android/media/video-play.html
index 6c264af..a95ca41 100644
--- a/chrome/test/data/android/media/video-play.html
+++ b/chrome/test/data/android/media/video-play.html
@@ -1,7 +1,7 @@
 <html>
 <title>test</title>
 <body bgcolor="Silver">
-  <video id='video1' src="test.mp4" controls></video>
+  <video id='video1' src="test.webm" controls></video>
   <script>
     var video = document.getElementById('video1');
     var mediaElement = video;
diff --git a/chrome/test/data/save_page/broken-image.htm b/chrome/test/data/save_page/broken-image.htm
index 3991b6d..9a671b2 100644
--- a/chrome/test/data/save_page/broken-image.htm
+++ b/chrome/test/data/save_page/broken-image.htm
@@ -25,5 +25,14 @@
     OTOH, this test hopefully covers more than just testing this one
     DCHECK - hopefully the broken image scenario hits some other corner
     cases as well.
+    <br><br>
+
+    The link to the image below is broken on purpose, to test additional code
+    paths - in particular in this case ResourceHandler::OnResponseStarted
+    is not called at all and the failure is reported directly via
+    ResourceHandler::OnResponseCompleted.  See also https://crbug.com/594219.
+    <img src="http://f0b310b1-4038-46a8-ac98-529187682f2d.no.such.host/x.png">
+    <br><br>
+
   </body>
 </html>
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js
index aa59941..52287e82 100644
--- a/chrome/test/data/webui/settings/cr_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -199,8 +199,7 @@
   __proto__: CrSettingsBrowserTest.prototype,
 
   /** @override */
-  browsePreload:
-      'chrome://md-settings/device_page/device_page.html',
+  browsePreload: 'chrome://md-settings/device_page/device_page.html',
 
   /** @override */
   extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([
@@ -214,3 +213,29 @@
   mocha.run();
 });
 GEN('#endif');
+
+GEN('#if !defined(OS_CHROMEOS)');
+/**
+ * @constructor
+ * @extends {CrSettingsBrowserTest}
+*/
+function CrSettingsSystemPageTest() {}
+
+CrSettingsSystemPageTest.prototype = {
+  __proto__: CrSettingsBrowserTest.prototype,
+
+  /** @override */
+  browsePreload: 'chrome://md-settings/system_page/system_page.html',
+
+  /** @override */
+  extraLibraries: CrSettingsBrowserTest.prototype.extraLibraries.concat([
+    ROOT_PATH + 'ui/webui/resources/js/promise_resolver.js',
+    'test_browser_proxy.js',
+    'system_page_tests.js',
+  ]),
+};
+
+TEST_F('CrSettingsSystemPageTest', 'Restart', function() {
+  mocha.run();
+});
+GEN('#endif');
diff --git a/chrome/test/data/webui/settings/device_page_tests.js b/chrome/test/data/webui/settings/device_page_tests.js
index b09d72c90..f22753f6 100644
--- a/chrome/test/data/webui/settings/device_page_tests.js
+++ b/chrome/test/data/webui/settings/device_page_tests.js
@@ -15,12 +15,6 @@
   };
 
   suite('SettingsDevicePage', function() {
-    /** @type {CrSettingsPrefsElement} */
-    var settingsPrefs = null;
-
-    /** @type {settings.FakeSettingsPrivate} */
-    var fakeApi = null;
-
     var fakePrefs = [{
       key: 'settings.touchpad.enable_tap_to_click',
       type: chrome.settingsPrivate.PrefType.BOOLEAN,
@@ -59,19 +53,10 @@
       value: false,
     }];
 
-    // Initialize <settings-device-page> before each test.
-    setup(function() {
-      CrSettingsPrefs.deferInitialization = true;
-      fakeApi = new settings.FakeSettingsPrivate(fakePrefs);
-      settingsPrefs = document.createElement('settings-prefs');
-      settingsPrefs.initializeForTesting(fakeApi);
-      return CrSettingsPrefs.initialized;
-    });
-
     test('keyboard subpage', function() {
       var devicePage = document.createElement('settings-device-page');
       devicePage.currentRoute = {page: 'basic', section: '', subpage: []};
-      devicePage.prefs = settingsPrefs.prefs;
+      devicePage.prefs = fakePrefs;
 
       // Open the keyboard subpage.
       var keyboardRow = devicePage.$$('#main #keyboardRow');
diff --git a/chrome/test/data/webui/settings/easy_unlock_browsertest_chromeos.js b/chrome/test/data/webui/settings/easy_unlock_browsertest_chromeos.js
index f4fb4138..7c22ef49 100644
--- a/chrome/test/data/webui/settings/easy_unlock_browsertest_chromeos.js
+++ b/chrome/test/data/webui/settings/easy_unlock_browsertest_chromeos.js
@@ -46,7 +46,10 @@
   var TestEasyUnlockBrowserProxy = function() {
     settings.TestBrowserProxy.call(this, [
       'getEnabledStatus',
-      'launchSetup',
+      'startTurnOnFlow',
+      'getTurnOffFlowStatus',
+      'startTurnOffFlow',
+      'cancelTurnOffFlow',
     ]);
 
     /** @private {boolean} */
@@ -70,8 +73,24 @@
     },
 
     /** @override */
-    launchSetup: function() {
-      this.methodCalled('launchSetup');
+    startTurnOnFlow: function() {
+      this.methodCalled('startTurnOnFlow');
+    },
+
+    /** @override */
+    getTurnOffFlowStatus: function() {
+      this.methodCalled('getTurnOffFlowStatus');
+      return Promise.resolve('idle');
+    },
+
+    /** @override */
+    startTurnOffFlow: function() {
+      this.methodCalled('startTurnOffFlow');
+    },
+
+    /** @override */
+    cancelTurnOffFlow: function() {
+      this.methodCalled('cancelTurnOffFlow');
     },
   };
 
@@ -81,8 +100,11 @@
   /** @type {?TestEasyUnlockBrowserProxy} */
   var browserProxy = null;
 
+  /** @type {?CrSettingsPrefs} */
+  var prefs = null;
+
   suite('SettingsEasyUnlock', function() {
-    setup(function() {
+    suiteSetup(function() {
       // These overrides are necessary for this test to function on ChromeOS
       // bots that do not have Bluetooth (don't actually support Easy Unlock).
       loadTimeData.overrideValues({
@@ -93,15 +115,21 @@
         easyUnlockLearnMoreURL: '',
         easyUnlockSetupIntro: '',
         easyUnlockSetupButton: '',
-      });
 
-      browserProxy = new TestEasyUnlockBrowserProxy();
-      settings.EasyUnlockBrowserProxyImpl.instance_ = browserProxy;
+        easyUnlockDescription: '',
+        easyUnlockTurnOffTitle: '',
+        easyUnlockTurnOffDescription: '',
+        easyUnlockTurnOffButton: '',
+      });
 
       // Before clearing the body, save a copy of the real prefs so we can
       // cleanly re-create the People page element.
-      var prefs =
-          document.querySelector('cr-settings').$$('settings-prefs').prefs;
+      prefs = document.querySelector('cr-settings').$$('settings-prefs').prefs;
+    });
+
+    setup(function() {
+      browserProxy = new TestEasyUnlockBrowserProxy();
+      settings.EasyUnlockBrowserProxyImpl.instance_ = browserProxy;
 
       PolymerTest.clearBody();
       page = document.createElement('settings-people-page');
@@ -111,11 +139,11 @@
         subpage: [],
       };
       page.prefs = prefs;
-
-      document.body.appendChild(page);
     });
 
     test('setup button', function() {
+      document.body.appendChild(page);
+
       return browserProxy.whenCalled('getEnabledStatus').then(function() {
         assertTrue(page.easyUnlockAllowed_);
         expectFalse(page.easyUnlockEnabled_);
@@ -124,9 +152,53 @@
 
         var setupButton = page.$$('#easyUnlockSetup');
         assertTrue(!!setupButton);
+        expectFalse(setupButton.hidden);
 
         MockInteractions.tap(setupButton);
-        return browserProxy.whenCalled('launchSetup');
+        return browserProxy.whenCalled('startTurnOnFlow');
+      });
+    });
+
+    test('turn off dialog', function() {
+      browserProxy.setEnabledStatus(true);
+      document.body.appendChild(page);
+
+      return browserProxy.whenCalled('getEnabledStatus').then(function() {
+        assertTrue(page.easyUnlockAllowed_);
+        expectTrue(page.easyUnlockEnabled_);
+
+        Polymer.dom.flush();
+
+        var turnOffButton = page.$$('#easyUnlockTurnOff');
+        assertTrue(!!turnOffButton);
+        expectFalse(turnOffButton.hidden)
+
+        MockInteractions.tap(turnOffButton);
+        return browserProxy.whenCalled('getTurnOffFlowStatus').then(function() {
+          Polymer.dom.flush();
+
+          var turnOffDialog = page.$$('#easyUnlockTurnOffDialog');
+          assertTrue(!!turnOffDialog);
+
+          var turnOffDialogConfirmButton = turnOffDialog.$$('#turnOff');
+          assertTrue(!!turnOffDialogConfirmButton);
+          expectFalse(turnOffDialogConfirmButton.hidden);
+
+          MockInteractions.tap(turnOffDialogConfirmButton);
+
+          return browserProxy.whenCalled('startTurnOffFlow').then(function() {
+            // To signal successful turnoff, the enabled status is broadcast
+            // as false. At that point, the dialog should close and cancel
+            // any in-progress turnoff flow. The cancellation should be
+            // a no-op assuming the turnoff originated from this tab.
+            cr.webUIListenerCallback('easy-unlock-enabled-status', false);
+            return browserProxy.whenCalled('cancelTurnOffFlow').then(
+                function() {
+                  Polymer.dom.flush();
+                  expectFalse(turnOffDialog.$.dialog.opened);
+                });
+          });
+        });
       });
     });
   });
diff --git a/chrome/test/data/webui/settings/system_page_tests.js b/chrome/test/data/webui/settings/system_page_tests.js
new file mode 100644
index 0000000..27ff9a50
--- /dev/null
+++ b/chrome/test/data/webui/settings/system_page_tests.js
@@ -0,0 +1,87 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('settings_system_page', function() {
+  /** @const {boolean} */
+  var HARDWARE_ACCELERATION_AT_STARTUP = true;
+
+  /**
+   * @constructor
+   * @extends {TestBrowserProxy}
+   * @implements {settings.SystemPageBrowserProxy}
+   */
+  function TestSystemPageBrowserProxy() {
+    settings.TestBrowserProxy.call(this, ['restartBrowser']);
+  }
+
+  TestSystemPageBrowserProxy.prototype = {
+    __proto__: settings.TestBrowserProxy.prototype,
+
+    /** @override */
+    changeProxySettings: assertNotReached,
+
+    /** @override */
+    restartBrowser: function() {
+      this.methodCalled('restartBrowser');
+    },
+
+    /** @override */
+    wasHardwareAccelerationEnabledAtStartup: function() {
+      return HARDWARE_ACCELERATION_AT_STARTUP;
+    },
+  };
+
+  suite('SettingsDevicePage', function() {
+    /** @type {settings.TestSystemPageBrowserProxy} */
+    var testBrowserProxy;
+
+    /** @type {SettingsSystemPageElement} */
+    var systemPage;
+
+    setup(function() {
+      testBrowserProxy = new TestSystemPageBrowserProxy;
+      settings.SystemPageBrowserProxyImpl.instance_ = testBrowserProxy;
+
+      systemPage = document.createElement('settings-system-page');
+      systemPage.set('prefs', {
+        background_mode: {
+          enabled: {
+            key: 'background_mode.enabled',
+            type: chrome.settingsPrivate.PrefType.BOOLEAN,
+            value: true,
+          },
+        },
+        hardware_acceleration_mode: {
+          enabled: {
+            key: 'hardware_acceleration_mode.enabled',
+            type: chrome.settingsPrivate.PrefType.BOOLEAN,
+            value: HARDWARE_ACCELERATION_AT_STARTUP,
+          },
+        },
+      });
+      document.body.appendChild(systemPage);
+    });
+
+    teardown(function() { systemPage.remove(); });
+
+    test('restart button', function() {
+      var checkbox = systemPage.$$('#hardware-acceleration settings-checkbox');
+      expectEquals(checkbox.checked, HARDWARE_ACCELERATION_AT_STARTUP);
+
+      // Restart button should be hidden by default.
+      expectFalse(!!systemPage.$$('#hardware-acceleration paper-button'));
+
+      systemPage.set('prefs.hardware_acceleration_mode.enabled.value',
+                     !HARDWARE_ACCELERATION_AT_STARTUP);
+      Polymer.dom.flush();
+      expectNotEquals(checkbox.checked, HARDWARE_ACCELERATION_AT_STARTUP);
+
+      var restart = systemPage.$$('#hardware-acceleration paper-button');
+      expectTrue(!!restart);  // The "RESTART" button should be showing now.
+
+      MockInteractions.tap(restart);
+      return testBrowserProxy.whenCalled('restartBrowser');
+    });
+  });
+});
diff --git a/components/content_settings/core/browser/cookie_settings.cc b/components/content_settings/core/browser/cookie_settings.cc
index ebcc382..475b642 100644
--- a/components/content_settings/core/browser/cookie_settings.cc
+++ b/components/content_settings/core/browser/cookie_settings.cc
@@ -92,17 +92,12 @@
       CONTENT_SETTINGS_TYPE_COOKIES, setting);
 }
 
-void CookieSettings::SetCookieSetting(
-    const ContentSettingsPattern& primary_pattern,
-    const ContentSettingsPattern& secondary_pattern,
-    ContentSetting setting) {
+void CookieSettings::SetCookieSetting(const GURL& primary_url,
+                                      ContentSetting setting) {
   DCHECK(IsValidSetting(setting));
-  if (setting == CONTENT_SETTING_SESSION_ONLY) {
-    DCHECK(secondary_pattern == ContentSettingsPattern::Wildcard());
-  }
-  host_content_settings_map_->SetContentSetting(
-      primary_pattern, secondary_pattern, CONTENT_SETTINGS_TYPE_COOKIES,
-      std::string(), setting);
+  host_content_settings_map_->SetContentSettingDefaultScope(
+      primary_url, GURL(), CONTENT_SETTINGS_TYPE_COOKIES, std::string(),
+      setting);
 }
 
 void CookieSettings::ResetCookieSetting(const GURL& primary_url) {
diff --git a/components/content_settings/core/browser/cookie_settings.h b/components/content_settings/core/browser/cookie_settings.h
index f3c62791..26ffa806 100644
--- a/components/content_settings/core/browser/cookie_settings.h
+++ b/components/content_settings/core/browser/cookie_settings.h
@@ -77,12 +77,10 @@
   // This should only be called on the UI thread.
   void SetDefaultCookieSetting(ContentSetting setting);
 
-  // Sets the cookie setting for the given patterns.
+  // Sets the cookie setting for the given url.
   //
   // This should only be called on the UI thread.
-  void SetCookieSetting(const ContentSettingsPattern& primary_pattern,
-                        const ContentSettingsPattern& secondary_pattern,
-                        ContentSetting setting);
+  void SetCookieSetting(const GURL& primary_url, ContentSetting setting);
 
   // Resets the cookie setting for the given url.
   //
diff --git a/components/content_settings/core/browser/cookie_settings_unittest.cc b/components/content_settings/core/browser/cookie_settings_unittest.cc
index ab2f1c8..c1d0ef7 100644
--- a/components/content_settings/core/browser/cookie_settings_unittest.cc
+++ b/components/content_settings/core/browser/cookie_settings_unittest.cc
@@ -51,9 +51,7 @@
 };
 
 TEST_F(CookieSettingsTest, TestWhitelistedScheme) {
-  cookie_settings_->SetCookieSetting(ContentSettingsPattern::Wildcard(),
-                                     ContentSettingsPattern::Wildcard(),
-                                     CONTENT_SETTING_BLOCK);
+  cookie_settings_->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
   EXPECT_FALSE(cookie_settings_->IsReadingCookieAllowed(kHttpSite, kChromeURL));
   EXPECT_TRUE(cookie_settings_->IsReadingCookieAllowed(kHttpsSite, kChromeURL));
   EXPECT_TRUE(cookie_settings_->IsReadingCookieAllowed(kChromeURL, kHttpSite));
@@ -69,9 +67,7 @@
 }
 
 TEST_F(CookieSettingsTest, CookiesBlockSingle) {
-  cookie_settings_->SetCookieSetting(
-      ContentSettingsPattern::FromURL(kBlockedSite),
-      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_BLOCK);
+  cookie_settings_->SetCookieSetting(kBlockedSite, CONTENT_SETTING_BLOCK);
   EXPECT_FALSE(
       cookie_settings_->IsReadingCookieAllowed(kBlockedSite, kBlockedSite));
 }
@@ -94,9 +90,7 @@
 }
 
 TEST_F(CookieSettingsTest, CookiesExplicitBlockSingleThirdParty) {
-  cookie_settings_->SetCookieSetting(
-      ContentSettingsPattern::FromURL(kBlockedSite),
-      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_BLOCK);
+  cookie_settings_->SetCookieSetting(kBlockedSite, CONTENT_SETTING_BLOCK);
   EXPECT_FALSE(
       cookie_settings_->IsReadingCookieAllowed(kBlockedSite, kFirstPartySite));
   EXPECT_FALSE(
@@ -106,9 +100,8 @@
 }
 
 TEST_F(CookieSettingsTest, CookiesExplicitSessionOnly) {
-  cookie_settings_->SetCookieSetting(
-      ContentSettingsPattern::FromURL(kBlockedSite),
-      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_SESSION_ONLY);
+  cookie_settings_->SetCookieSetting(kBlockedSite,
+                                     CONTENT_SETTING_SESSION_ONLY);
   EXPECT_TRUE(
       cookie_settings_->IsReadingCookieAllowed(kBlockedSite, kFirstPartySite));
   EXPECT_TRUE(
@@ -124,9 +117,7 @@
 }
 
 TEST_F(CookieSettingsTest, CookiesThirdPartyBlockedExplicitAllow) {
-  cookie_settings_->SetCookieSetting(
-      ContentSettingsPattern::FromURL(kAllowedSite),
-      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_ALLOW);
+  cookie_settings_->SetCookieSetting(kAllowedSite, CONTENT_SETTING_ALLOW);
   prefs_.SetBoolean(prefs::kBlockThirdPartyCookies, true);
   EXPECT_TRUE(
       cookie_settings_->IsReadingCookieAllowed(kAllowedSite, kFirstPartySite));
@@ -142,15 +133,13 @@
 }
 
 TEST_F(CookieSettingsTest, CookiesThirdPartyBlockedAllSitesAllowed) {
-  cookie_settings_->SetCookieSetting(
-      ContentSettingsPattern::FromURL(kAllowedSite),
-      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_ALLOW);
+  cookie_settings_->SetCookieSetting(kAllowedSite, CONTENT_SETTING_ALLOW);
   prefs_.SetBoolean(prefs::kBlockThirdPartyCookies, true);
-  // As an example for a pattern that matches all hosts but not all origins,
+  // As an example for a url that matches all hosts but not all origins,
   // match all HTTPS sites.
-  cookie_settings_->SetCookieSetting(kAllHttpsSitesPattern,
-                                     ContentSettingsPattern::Wildcard(),
-                                     CONTENT_SETTING_ALLOW);
+  settings_map_->SetContentSetting(
+      kAllHttpsSitesPattern, ContentSettingsPattern::Wildcard(),
+      CONTENT_SETTINGS_TYPE_COOKIES, std::string(), CONTENT_SETTING_ALLOW);
   cookie_settings_->SetDefaultCookieSetting(CONTENT_SETTING_SESSION_ONLY);
 
   // |kAllowedSite| should be allowed.
@@ -196,9 +185,7 @@
 
 TEST_F(CookieSettingsTest, CookiesBlockEverythingExceptAllowed) {
   cookie_settings_->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
-  cookie_settings_->SetCookieSetting(
-      ContentSettingsPattern::FromURL(kAllowedSite),
-      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_ALLOW);
+  cookie_settings_->SetCookieSetting(kAllowedSite, CONTENT_SETTING_ALLOW);
   EXPECT_FALSE(cookie_settings_->IsReadingCookieAllowed(kFirstPartySite,
                                                         kFirstPartySite));
   EXPECT_FALSE(cookie_settings_->IsSettingCookieAllowed(kFirstPartySite,
@@ -215,9 +202,7 @@
 }
 
 TEST_F(CookieSettingsTest, ExtensionsRegularSettings) {
-  cookie_settings_->SetCookieSetting(
-      ContentSettingsPattern::FromURL(kBlockedSite),
-      ContentSettingsPattern::Wildcard(), CONTENT_SETTING_BLOCK);
+  cookie_settings_->SetCookieSetting(kBlockedSite, CONTENT_SETTING_BLOCK);
 
   // Regular cookie settings also apply to extensions.
   EXPECT_FALSE(
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_decider.cc b/components/data_reduction_proxy/content/browser/content_lofi_decider.cc
index 733a814..d4ba531 100644
--- a/components/data_reduction_proxy/content/browser/content_lofi_decider.cc
+++ b/components/data_reduction_proxy/content/browser/content_lofi_decider.cc
@@ -63,43 +63,40 @@
       params::AreLoFiPreviewsEnabledViaFlags() ||
       params::IsIncludedInLoFiPreviewFieldTrial();
 
+  // User is not using Lo-Fi or is part of the "Control" group.
+  if (!request_info->IsUsingLoFi() || !lofi_enabled_via_flag_or_field_trial)
+    return false;
+
   std::string header_value;
 
-  // User is using Lo-Fi and not part of the "Control" group.
-  if (request_info->IsUsingLoFi() && lofi_enabled_via_flag_or_field_trial) {
-    if (headers->HasHeader(chrome_proxy_header())) {
-      headers->GetHeader(chrome_proxy_header(), &header_value);
-      headers->RemoveHeader(chrome_proxy_header());
-      header_value += ", ";
-    }
-
-    // If in the preview field trial or the preview flag is enabled, only add
-    // the "q=preview" directive on main frame requests. Do not add Lo-Fi
-    // directives to other requests when previews are enabled. If previews are
-    // not enabled, add "q=low".
-    if (lofi_preview_via_flag_or_field_trial) {
-      if (request.load_flags() & net::LOAD_MAIN_FRAME)
-        header_value += chrome_proxy_lo_fi_preview_directive();
-    } else {
-      header_value += chrome_proxy_lo_fi_directive();
-    }
-
-    headers->SetHeader(chrome_proxy_header(), header_value);
-    return true;
+  if (headers->HasHeader(chrome_proxy_header())) {
+    headers->GetHeader(chrome_proxy_header(), &header_value);
+    headers->RemoveHeader(chrome_proxy_header());
+    header_value += ", ";
   }
 
-  // User is part of Lo-Fi active control experiment.
-  if (request_info->IsUsingLoFi() &&
-      params::IsIncludedInLoFiControlFieldTrial()) {
-    if (headers->HasHeader(chrome_proxy_header())) {
-      headers->GetHeader(chrome_proxy_header(), &header_value);
-      headers->RemoveHeader(chrome_proxy_header());
-      header_value += ", ";
+  // If in the preview field trial or the preview flag is enabled, only add the
+  // "q=preview" directive on main frame requests. Do not add Lo-Fi directives
+  // to other requests when previews are enabled. If previews are not enabled,
+  // add "q=low".
+  if (lofi_preview_via_flag_or_field_trial) {
+    if (request.load_flags() & net::LOAD_MAIN_FRAME) {
+      if (params::AreLoFiPreviewsEnabledViaFlags()) {
+        header_value += chrome_proxy_lo_fi_ignore_preview_blacklist_directive();
+        header_value += ", ";
+      }
+      header_value += chrome_proxy_lo_fi_preview_directive();
     }
-    headers->SetHeader(chrome_proxy_header(), header_value);
+  } else {
+    header_value += chrome_proxy_lo_fi_directive();
   }
 
-  return false;
+  // |header_value| may be empty because the Lo-Fi directive is not added
+  // to subrequests when preview mode is enabled.
+  if (!header_value.empty())
+    headers->SetHeader(chrome_proxy_header(), header_value);
+
+  return true;
 }
 
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc b/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
index 117a387..3e824e3 100644
--- a/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
+++ b/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
@@ -145,6 +145,18 @@
                   std::string::npos);
   }
 
+  static void VerifyLoFiIgnorePreviewBlacklistHeader(
+      bool expected_lofi_preview_used,
+      const net::HttpRequestHeaders& headers) {
+    EXPECT_TRUE(headers.HasHeader(chrome_proxy_header()));
+    std::string header_value;
+    headers.GetHeader(chrome_proxy_header(), &header_value);
+    EXPECT_EQ(expected_lofi_preview_used,
+              header_value.find(
+                  chrome_proxy_lo_fi_ignore_preview_blacklist_directive()) !=
+                  std::string::npos);
+  }
+
  protected:
   base::MessageLoopForIO message_loop_;
   net::MockClientSocketFactory mock_socket_factory_;
@@ -178,6 +190,7 @@
     NotifyBeforeSendProxyHeaders(&headers, request.get(), true);
     VerifyLoFiHeader(false, headers);
     VerifyLoFiPreviewHeader(false, headers);
+    VerifyLoFiIgnorePreviewBlacklistHeader(false, headers);
 
     // The Lo-Fi flag is "always-on", Lo-Fi is being used, and it's a main frame
     // request. Lo-Fi preview header should be added.
@@ -191,6 +204,8 @@
                      headers);
     VerifyLoFiPreviewHeader(
         tests[i].is_using_lofi && tests[i].is_using_previews, headers);
+    VerifyLoFiIgnorePreviewBlacklistHeader(
+        tests[i].is_using_lofi && tests[i].is_using_previews, headers);
 
     // The Lo-Fi flag is "always-on" and Lo-Fi is being used. Lo-Fi header
     // should be added.
@@ -200,6 +215,7 @@
     VerifyLoFiHeader(tests[i].is_using_lofi && !tests[i].is_using_previews,
                      headers);
     VerifyLoFiPreviewHeader(false, headers);
+    VerifyLoFiIgnorePreviewBlacklistHeader(false, headers);
 
     // The Lo-Fi flag is "cellular-only" and Lo-Fi is being used. Lo-Fi header
     // should be added.
@@ -211,6 +227,7 @@
     VerifyLoFiHeader(tests[i].is_using_lofi && !tests[i].is_using_previews,
                      headers);
     VerifyLoFiPreviewHeader(false, headers);
+    VerifyLoFiIgnorePreviewBlacklistHeader(false, headers);
 
     // The Lo-Fi flag is "slow-connections-only" and Lo-Fi is being used. Lo-Fi
     // header should be added.
@@ -222,6 +239,7 @@
     VerifyLoFiHeader(tests[i].is_using_lofi && !tests[i].is_using_previews,
                      headers);
     VerifyLoFiPreviewHeader(false, headers);
+    VerifyLoFiIgnorePreviewBlacklistHeader(false, headers);
   }
 }
 
@@ -242,6 +260,7 @@
     NotifyBeforeSendProxyHeaders(&headers, request.get(), true);
     VerifyLoFiHeader(tests[i].is_using_lofi, headers);
     VerifyLoFiPreviewHeader(false, headers);
+    VerifyLoFiIgnorePreviewBlacklistHeader(false, headers);
   }
 }
 
@@ -262,6 +281,7 @@
     NotifyBeforeSendProxyHeaders(&headers, request.get(), true);
     VerifyLoFiHeader(false, headers);
     VerifyLoFiPreviewHeader(false, headers);
+    VerifyLoFiIgnorePreviewBlacklistHeader(false, headers);
   }
 }
 
@@ -286,6 +306,7 @@
     VerifyLoFiHeader(false, headers);
     VerifyLoFiPreviewHeader(tests[i].is_using_lofi && tests[i].is_main_frame,
                             headers);
+    VerifyLoFiIgnorePreviewBlacklistHeader(false, headers);
   }
 }
 
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc
index 8ec2ad4f..15e8239 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc
@@ -31,6 +31,8 @@
 
 const char kChromeProxyLoFiDirective[] = "q=low";
 const char kChromeProxyLoFiPreviewDirective[] = "q=preview";
+const char kChromeProxyLoFiIngorePreviewBlacklistDirective[] =
+    "exp=ignore_preview_blacklist";
 
 const char kChromeProxyActionBlockOnce[] = "block-once";
 const char kChromeProxyActionBlock[] = "block";
@@ -69,6 +71,10 @@
   return kChromeProxyLoFiPreviewDirective;
 }
 
+const char* chrome_proxy_lo_fi_ignore_preview_blacklist_directive() {
+  return kChromeProxyLoFiIngorePreviewBlacklistDirective;
+}
+
 bool GetDataReductionProxyActionValue(
     const net::HttpResponseHeaders* headers,
     const std::string& action_prefix,
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h
index 093c6ab..41e00b67 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h
@@ -78,6 +78,10 @@
 // requests and responses.
 const char* chrome_proxy_lo_fi_preview_directive();
 
+// Gets the Chrome-Proxy directive used by data reduction proxy Lo-Fi preview
+// experiment to ignore the blacklist.
+const char* chrome_proxy_lo_fi_ignore_preview_blacklist_directive();
+
 // Returns true if the Chrome-Proxy header is present and contains a bypass
 // delay. Sets |proxy_info->bypass_duration| to the specified delay if greater
 // than 0, and to 0 otherwise to indicate that the default proxy delay
diff --git a/components/data_reduction_proxy/core/common/lofi_decider.h b/components/data_reduction_proxy/core/common/lofi_decider.h
index 8247666..6eb8e51 100644
--- a/components/data_reduction_proxy/core/common/lofi_decider.h
+++ b/components/data_reduction_proxy/core/common/lofi_decider.h
@@ -33,7 +33,6 @@
   // request adds the "q=preview" and it is a main frame request directive to
   // the |headers|. Only adds this header if the provided |proxy_server| is a
   // data reduction proxy as identified by the given |config|.
-
   virtual bool MaybeAddLoFiDirectiveToHeaders(
       const net::URLRequest& request,
       net::HttpRequestHeaders* headers,
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index 72e3085..1047197b 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -403,13 +403,12 @@
     aura::client::ActivationChangeObserver::ActivationReason reason,
     aura::Window* gained_active,
     aura::Window* lost_active) {
-  DCHECK(activatable_);
-
   if (!widget_)
     return;
 
   if (gained_active == widget_->GetNativeWindow() ||
       lost_active == widget_->GetNativeWindow()) {
+    DCHECK(activatable_);
     Configure();
   }
 }
diff --git a/components/filesystem/file_system_app.cc b/components/filesystem/file_system_app.cc
index 2163351..92f78b7 100644
--- a/components/filesystem/file_system_app.cc
+++ b/components/filesystem/file_system_app.cc
@@ -55,10 +55,6 @@
                      lock_table_);
 }
 
-void FileSystemApp::ShellConnectionLost() {
-  _exit(1);
-}
-
 //static
 base::FilePath FileSystemApp::GetUserDataDir() {
   base::FilePath path;
diff --git a/components/filesystem/file_system_app.h b/components/filesystem/file_system_app.h
index 5e297ad8..5b1d866 100644
--- a/components/filesystem/file_system_app.h
+++ b/components/filesystem/file_system_app.h
@@ -34,8 +34,6 @@
   void Initialize(mojo::Connector* connector, const mojo::Identity& identity,
                   uint32_t id) override;
   bool AcceptConnection(mojo::Connection* connection) override;
-  void ShellConnectionLost() override;
-
   // |InterfaceFactory<Files>| implementation:
   void Create(mojo::Connection* connection,
               mojo::InterfaceRequest<FileSystem> request) override;
diff --git a/components/font_service/font_service_app.cc b/components/font_service/font_service_app.cc
index 5942cb12..6e73b99 100644
--- a/components/font_service/font_service_app.cc
+++ b/components/font_service/font_service_app.cc
@@ -69,10 +69,6 @@
   return true;
 }
 
-void FontServiceApp::ShellConnectionLost() {
-  _exit(1);
-}
-
 void FontServiceApp::Create(mojo::Connection* connection,
                             mojo::InterfaceRequest<FontService> request) {
   bindings_.AddBinding(this, std::move(request));
diff --git a/components/font_service/font_service_app.h b/components/font_service/font_service_app.h
index b7537da..957f231f 100644
--- a/components/font_service/font_service_app.h
+++ b/components/font_service/font_service_app.h
@@ -30,7 +30,6 @@
   void Initialize(mojo::Connector* connector, const mojo::Identity& identity,
                   uint32_t id) override;
   bool AcceptConnection(mojo::Connection* connection) override;
-  void ShellConnectionLost() override;
 
   // mojo::InterfaceFactory<FontService>:
   void Create(mojo::Connection* connection,
diff --git a/components/leveldb/leveldb_app.cc b/components/leveldb/leveldb_app.cc
index ac2855f..e216391 100644
--- a/components/leveldb/leveldb_app.cc
+++ b/components/leveldb/leveldb_app.cc
@@ -25,11 +25,6 @@
   return true;
 }
 
-void LevelDBApp::ShellConnectionLost() {
-  // TODO: This should exit cleanly.
-  _exit(1);
-}
-
 void LevelDBApp::Create(mojo::Connection* connection,
                         leveldb::LevelDBServiceRequest request) {
   if (!service_)
diff --git a/components/leveldb/leveldb_app.h b/components/leveldb/leveldb_app.h
index 6db51949..26a11522 100644
--- a/components/leveldb/leveldb_app.h
+++ b/components/leveldb/leveldb_app.h
@@ -25,7 +25,6 @@
                   const mojo::Identity& identity,
                   uint32_t id) override;
   bool AcceptConnection(mojo::Connection* connection) override;
-  void ShellConnectionLost() override;
 
   // |InterfaceFactory<LevelDBService>| implementation:
   void Create(mojo::Connection* connection,
diff --git a/components/leveldb/leveldb_database_impl.cc b/components/leveldb/leveldb_database_impl.cc
index d5e8fa6..6beb5f4a 100644
--- a/components/leveldb/leveldb_database_impl.cc
+++ b/components/leveldb/leveldb_database_impl.cc
@@ -29,7 +29,7 @@
 
 LevelDBDatabaseImpl::LevelDBDatabaseImpl(
     leveldb::LevelDBDatabaseRequest request,
-    scoped_ptr<MojoEnv> environment,
+    scoped_ptr<leveldb::Env> environment,
     scoped_ptr<leveldb::DB> db)
     : binding_(this, std::move(request)),
       environment_(std::move(environment)),
diff --git a/components/leveldb/leveldb_database_impl.h b/components/leveldb/leveldb_database_impl.h
index 29ff697..0f218d3 100644
--- a/components/leveldb/leveldb_database_impl.h
+++ b/components/leveldb/leveldb_database_impl.h
@@ -19,7 +19,7 @@
 class LevelDBDatabaseImpl : public LevelDBDatabase {
  public:
   LevelDBDatabaseImpl(leveldb::LevelDBDatabaseRequest request,
-                      scoped_ptr<MojoEnv> environment,
+                      scoped_ptr<leveldb::Env> environment,
                       scoped_ptr<leveldb::DB> db);
   ~LevelDBDatabaseImpl() override;
 
@@ -40,7 +40,7 @@
 
  private:
   mojo::StrongBinding<LevelDBDatabase> binding_;
-  scoped_ptr<MojoEnv> environment_;
+  scoped_ptr<leveldb::Env> environment_;
   scoped_ptr<leveldb::DB> db_;
 
   std::map<uint64_t, const Snapshot*> snapshot_map_;
diff --git a/components/leveldb/leveldb_service_impl.cc b/components/leveldb/leveldb_service_impl.cc
index baff56b..1cabe73 100644
--- a/components/leveldb/leveldb_service_impl.cc
+++ b/components/leveldb/leveldb_service_impl.cc
@@ -8,6 +8,7 @@
 #include "components/leveldb/leveldb_database_impl.h"
 #include "components/leveldb/util.h"
 #include "third_party/leveldatabase/env_chromium.h"
+#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
 #include "third_party/leveldatabase/src/include/leveldb/db.h"
 #include "third_party/leveldatabase/src/include/leveldb/env.h"
 #include "third_party/leveldatabase/src/include/leveldb/filter_policy.h"
@@ -53,4 +54,25 @@
   callback.Run(LeveldbStatusToError(s));
 }
 
+void LevelDBServiceImpl::OpenInMemory(leveldb::LevelDBDatabaseRequest database,
+                                      const OpenCallback& callback) {
+  leveldb::Options options;
+  options.create_if_missing = true;
+  options.max_open_files = 0;  // Use minimum.
+  options.reuse_logs = leveldb_env::kDefaultLogReuseOptionValue;
+
+  scoped_ptr<leveldb::Env> env(leveldb::NewMemEnv(leveldb::Env::Default()));
+  options.env = env.get();
+
+  leveldb::DB* db = nullptr;
+  leveldb::Status s = leveldb::DB::Open(options, "", &db);
+
+  if (s.ok()) {
+    new LevelDBDatabaseImpl(std::move(database), std::move(env),
+                            scoped_ptr<leveldb::DB>(db));
+  }
+
+  callback.Run(LeveldbStatusToError(s));
+}
+
 }  // namespace leveldb
diff --git a/components/leveldb/leveldb_service_impl.h b/components/leveldb/leveldb_service_impl.h
index 8d554f70..b5f90006 100644
--- a/components/leveldb/leveldb_service_impl.h
+++ b/components/leveldb/leveldb_service_impl.h
@@ -23,6 +23,8 @@
             const mojo::String& dbname,
             leveldb::LevelDBDatabaseRequest database,
             const OpenCallback& callback) override;
+  void OpenInMemory(leveldb::LevelDBDatabaseRequest database,
+                    const OpenInMemoryCallback& callback) override;
 
  private:
   // Thread to own the mojo message pipe. Because leveldb spawns multiple
diff --git a/components/leveldb/leveldb_service_unittest.cc b/components/leveldb/leveldb_service_unittest.cc
index 7711deb0..2e0ce66 100644
--- a/components/leveldb/leveldb_service_unittest.cc
+++ b/components/leveldb/leveldb_service_unittest.cc
@@ -303,5 +303,47 @@
   EXPECT_EQ(DatabaseError::INVALID_ARGUMENT, error);
 }
 
+TEST_F(LevelDBApptest, MemoryDBReadWrite) {
+  LevelDBDatabasePtr database;
+  DatabaseError error = DatabaseError::INVALID_ARGUMENT;
+  leveldb()->OpenInMemory(GetProxy(&database), Capture(&error));
+  ASSERT_TRUE(leveldb().WaitForIncomingResponse());
+  EXPECT_EQ(DatabaseError::OK, error);
+
+  // Write a key to the database.
+  error = DatabaseError::INVALID_ARGUMENT;
+  database->Put(mojo::Array<uint8_t>::From(std::string("key")),
+                mojo::Array<uint8_t>::From(std::string("value")),
+                Capture(&error));
+  ASSERT_TRUE(database.WaitForIncomingResponse());
+  EXPECT_EQ(DatabaseError::OK, error);
+
+  // Read the key back from the database.
+  error = DatabaseError::INVALID_ARGUMENT;
+  mojo::Array<uint8_t> value;
+  database->Get(mojo::Array<uint8_t>::From(std::string("key")),
+                Capture(&error, &value));
+  ASSERT_TRUE(database.WaitForIncomingResponse());
+  EXPECT_EQ(DatabaseError::OK, error);
+  EXPECT_EQ("value", value.To<std::string>());
+
+  // Delete the key from the database.
+  error = DatabaseError::INVALID_ARGUMENT;
+  database->Delete(mojo::Array<uint8_t>::From(std::string("key")),
+                   Capture(&error));
+  ASSERT_TRUE(database.WaitForIncomingResponse());
+  EXPECT_EQ(DatabaseError::OK, error);
+
+  // Read the key back from the database.
+  error = DatabaseError::INVALID_ARGUMENT;
+  value.SetToEmpty();
+  database->Get(mojo::Array<uint8_t>::From(std::string("key")),
+                Capture(&error, &value));
+  ASSERT_TRUE(database.WaitForIncomingResponse());
+  EXPECT_EQ(DatabaseError::NOT_FOUND, error);
+  EXPECT_EQ("", value.To<std::string>());
+}
+
+
 }  // namespace
 }  // namespace leveldb
diff --git a/components/leveldb/public/interfaces/leveldb.mojom b/components/leveldb/public/interfaces/leveldb.mojom
index ebd9646..d595f315 100644
--- a/components/leveldb/public/interfaces/leveldb.mojom
+++ b/components/leveldb/public/interfaces/leveldb.mojom
@@ -32,6 +32,8 @@
   Open(filesystem.Directory directory,
        string dbname,
        LevelDBDatabase& database) => (DatabaseError status);
+
+  OpenInMemory(LevelDBDatabase& database) => (DatabaseError status);
 };
 
 // A leveldb database.
diff --git a/components/metrics/leak_detector/leak_detector.cc b/components/metrics/leak_detector/leak_detector.cc
index 0240b58..952c5bc2 100644
--- a/components/metrics/leak_detector/leak_detector.cc
+++ b/components/metrics/leak_detector/leak_detector.cc
@@ -85,7 +85,7 @@
     const InternalVector<InternalLeakReport>& leak_reports,
     std::vector<LeakReport>* reports_for_observers) {
   reports_for_observers->clear();
-  reports_for_observers->resize(leak_reports.size());
+  reports_for_observers->reserve(leak_reports.size());
   for (const InternalLeakReport& report : leak_reports) {
     reports_for_observers->push_back(LeakReport());
     LeakReport* new_report = &reports_for_observers->back();
diff --git a/components/mus/gles2/gpu_state.cc b/components/mus/gles2/gpu_state.cc
index cd3c842..b78f198 100644
--- a/components/mus/gles2/gpu_state.cc
+++ b/components/mus/gles2/gpu_state.cc
@@ -25,6 +25,7 @@
   base::ThreadRestrictions::ScopedAllowWait allow_wait;
   gpu_thread_.Start();
   control_thread_.Start();
+  control_thread_task_runner_ = control_thread_.task_runner();
   base::WaitableEvent event(true, false);
   gpu_thread_.task_runner()->PostTask(
       FROM_HERE, base::Bind(&GpuState::InitializeOnGpuThread,
@@ -36,6 +37,9 @@
 
 void GpuState::StopThreads() {
   control_thread_.Stop();
+  gpu_thread_.task_runner()->PostTask(
+      FROM_HERE,
+      base::Bind(&GpuState::DestroyGpuSpecificStateOnGpuThread, this));
   gpu_thread_.Stop();
 }
 
@@ -69,4 +73,8 @@
 #endif
 }
 
+void GpuState::DestroyGpuSpecificStateOnGpuThread() {
+  driver_manager_.reset();
+}
+
 }  // namespace mus
diff --git a/components/mus/gles2/gpu_state.h b/components/mus/gles2/gpu_state.h
index dca04b6..aec23e4 100644
--- a/components/mus/gles2/gpu_state.h
+++ b/components/mus/gles2/gpu_state.h
@@ -33,7 +33,7 @@
   // most method class to the CommandBufferDriver, which runs on the "driver",
   // thread (i.e., the thread on which GpuImpl instances are created).
   scoped_refptr<base::SingleThreadTaskRunner> control_task_runner() {
-    return control_thread_.task_runner();
+    return control_thread_task_runner_;
   }
 
   void StopThreads();
@@ -74,11 +74,17 @@
 
   void InitializeOnGpuThread(base::WaitableEvent* event);
 
+  void DestroyGpuSpecificStateOnGpuThread();
+
   // |gpu_thread_| is for executing OS GL calls.
   base::Thread gpu_thread_;
   // |control_thread_| is for mojo incoming calls of CommandBufferImpl.
   base::Thread control_thread_;
 
+  // Same as control_thread_->task_runner(). The TaskRunner is cached as it may
+  // be needed during shutdown.
+  scoped_refptr<base::SingleThreadTaskRunner> control_thread_task_runner_;
+
   gpu::GpuPreferences gpu_preferences_;
   scoped_refptr<CommandBufferTaskRunner> command_buffer_task_runner_;
   scoped_ptr<CommandBufferDriverManager> driver_manager_;
diff --git a/components/mus/mus_app.cc b/components/mus/mus_app.cc
index 9f226a9..6d15e5b 100644
--- a/components/mus/mus_app.cc
+++ b/components/mus/mus_app.cc
@@ -69,10 +69,13 @@
 MandolineUIServicesApp::MandolineUIServicesApp() {}
 
 MandolineUIServicesApp::~MandolineUIServicesApp() {
+  // Destroy |window_server_| first, since it depends on |event_source_|.
+  // WindowServer (or more correctly its Displays) may have state that needs to
+  // be destroyed before GpuState as well.
+  window_server_.reset();
+
   if (platform_display_init_params_.gpu_state)
     platform_display_init_params_.gpu_state->StopThreads();
-  // Destroy |window_server_| first, since it depends on |event_source_|.
-  window_server_.reset();
 }
 
 void MandolineUIServicesApp::InitializeResources(mojo::Connector* connector) {
@@ -168,11 +171,6 @@
   return true;
 }
 
-void MandolineUIServicesApp::ShellConnectionLost() {
-  // TODO: This should exit cleanly.
-  _exit(1);
-}
-
 void MandolineUIServicesApp::OnFirstDisplayReady() {
   PendingRequests requests;
   requests.swap(pending_requests_);
@@ -181,7 +179,9 @@
 }
 
 void MandolineUIServicesApp::OnNoMoreDisplays() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  // We may get here from the destructor, in which case there is no messageloop.
+  if (base::MessageLoop::current())
+    base::MessageLoop::current()->QuitWhenIdle();
 }
 
 scoped_ptr<ws::WindowTreeBinding>
diff --git a/components/mus/mus_app.h b/components/mus/mus_app.h
index e217fba..c66267f 100644
--- a/components/mus/mus_app.h
+++ b/components/mus/mus_app.h
@@ -75,7 +75,6 @@
   void Initialize(mojo::Connector* connector, const mojo::Identity& identity,
                   uint32_t id) override;
   bool AcceptConnection(mojo::Connection* connection) override;
-  void ShellConnectionLost() override;
 
   // WindowServerDelegate:
   void OnFirstDisplayReady() override;
diff --git a/components/mus/ws/event_dispatcher.cc b/components/mus/ws/event_dispatcher.cc
index 32b38315..98e09b71 100644
--- a/components/mus/ws/event_dispatcher.cc
+++ b/components/mus/ws/event_dispatcher.cc
@@ -180,8 +180,9 @@
 
 void EventDispatcher::RemoveAccelerator(uint32_t id) {
   auto it = accelerators_.find(id);
-  DCHECK(it != accelerators_.end());
-  accelerators_.erase(it);
+  // Clients may pass bogus ids.
+  if (it != accelerators_.end())
+    accelerators_.erase(it);
 }
 
 void EventDispatcher::ProcessEvent(const ui::Event& event) {
diff --git a/components/mus/ws/platform_display.cc b/components/mus/ws/platform_display.cc
index 4e7536e..08619e1 100644
--- a/components/mus/ws/platform_display.cc
+++ b/components/mus/ws/platform_display.cc
@@ -200,7 +200,9 @@
 }
 
 DefaultPlatformDisplay::~DefaultPlatformDisplay() {
-  delegate_->OnTopLevelSurfaceChanged(cc::SurfaceId());
+  // Don't notify the delegate from the destructor.
+  delegate_ = nullptr;
+
   // Invalidate WeakPtrs now to avoid callbacks back into the
   // DefaultPlatformDisplay during destruction of |top_level_display_client_|.
   weak_factory_.InvalidateWeakPtrs();
@@ -399,7 +401,8 @@
 }
 
 void DefaultPlatformDisplay::OnClosed() {
-  delegate_->OnDisplayClosed();
+  if (delegate_)
+    delegate_->OnDisplayClosed();
 }
 
 void DefaultPlatformDisplay::OnWindowStateChanged(
diff --git a/components/mus/ws/server_window_surface.cc b/components/mus/ws/server_window_surface.cc
index 800de90..48fa3c6 100644
--- a/components/mus/ws/server_window_surface.cc
+++ b/components/mus/ws/server_window_surface.cc
@@ -155,7 +155,7 @@
 
 void ServerWindowSurface::ReturnResources(
     const cc::ReturnedResourceArray& resources) {
-  if (!client_)
+  if (!client_ || !base::MessageLoop::current())
     return;
   client_->ReturnResources(
       mojo::Array<mojom::ReturnedResourcePtr>::From(resources));
diff --git a/components/plugins/renderer/webview_plugin.h b/components/plugins/renderer/webview_plugin.h
index a703816..a189ae7 100644
--- a/components/plugins/renderer/webview_plugin.h
+++ b/components/plugins/renderer/webview_plugin.h
@@ -83,6 +83,8 @@
 
   // WebPlugin methods:
   blink::WebPluginContainer* container() const override;
+  // The WebViewPlugin, by design, never fails to initialize. It's used to
+  // display placeholders and error messages, so it must never fail.
   bool initialize(blink::WebPluginContainer*) override;
   void destroy() override;
 
diff --git a/components/resource_provider/resource_provider_app.cc b/components/resource_provider/resource_provider_app.cc
index 18b4e42..cd16a98894 100644
--- a/components/resource_provider/resource_provider_app.cc
+++ b/components/resource_provider/resource_provider_app.cc
@@ -37,11 +37,6 @@
   return true;
 }
 
-void ResourceProviderApp::ShellConnectionLost() {
-  // TODO: This should exit cleanly.
-  _exit(1);
-}
-
 void ResourceProviderApp::Create(
     mojo::Connection* connection,
     mojo::InterfaceRequest<ResourceProvider> request) {
diff --git a/components/resource_provider/resource_provider_app.h b/components/resource_provider/resource_provider_app.h
index 96d6125..10f7602 100644
--- a/components/resource_provider/resource_provider_app.h
+++ b/components/resource_provider/resource_provider_app.h
@@ -28,7 +28,6 @@
   void Initialize(mojo::Connector* connector, const mojo::Identity& identity,
                   uint32_t id) override;
   bool AcceptConnection(mojo::Connection* connection) override;
-  void ShellConnectionLost() override;
 
   // mojo::InterfaceFactory<ResourceProvider>:
   void Create(mojo::Connection* connection,
diff --git a/components/resource_provider/resource_provider_test_app.cc b/components/resource_provider/resource_provider_test_app.cc
index ab0147f4..2c78352 100644
--- a/components/resource_provider/resource_provider_test_app.cc
+++ b/components/resource_provider/resource_provider_test_app.cc
@@ -99,9 +99,6 @@
     connection->AddInterface<mojom::Test>(this);
     return true;
   }
-  void ShellConnectionLost() override {
-    base::MessageLoop::current()->QuitWhenIdle();
-  }
 
   // InterfaceFactory<mojom::Test>:
   void Create(mojo::Connection* connection,
diff --git a/components/test_runner/DEPS b/components/test_runner/DEPS
index d0f42ccc..c2f1ea16 100644
--- a/components/test_runner/DEPS
+++ b/components/test_runner/DEPS
@@ -4,6 +4,7 @@
   "+gpu/command_buffer/client",
   "+net/base",
   "+skia",
+  "+third_party/khronos/GLES2/gl2.h",
   "+third_party/skia",
   "+third_party/WebKit/public/platform",
   "+third_party/WebKit/public/web",
diff --git a/components/test_runner/test_plugin.cc b/components/test_runner/test_plugin.cc
index 155fd6b..b7ab570 100644
--- a/components/test_runner/test_plugin.cc
+++ b/components/test_runner/test_plugin.cc
@@ -20,6 +20,7 @@
 #include "third_party/WebKit/public/platform/Platform.h"
 #include "third_party/WebKit/public/platform/WebCompositorSupport.h"
 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h"
 #include "third_party/WebKit/public/platform/WebTaskRunner.h"
 #include "third_party/WebKit/public/platform/WebThread.h"
 #include "third_party/WebKit/public/platform/WebTraceLocation.h"
@@ -39,7 +40,7 @@
 
 namespace {
 
-void PremultiplyAlpha(const unsigned color_in[3],
+void PremultiplyAlpha(const uint8_t color_in[3],
                       float alpha,
                       float color_out[4]) {
   for (int i = 0; i < 3; ++i)
@@ -173,9 +174,12 @@
 
 bool TestPlugin::initialize(blink::WebPluginContainer* container) {
   blink::WebGraphicsContext3D::Attributes attrs;
-  context_ =
-      blink::Platform::current()->createOffscreenGraphicsContext3D(attrs);
-  gl_ = context_ ? context_->getGLES2Interface() : nullptr;
+  blink::WebGraphicsContext3D::WebGraphicsInfo gl_info;
+  context_provider_ = make_scoped_ptr(
+      blink::Platform::current()->createOffscreenGraphicsContext3DProvider(
+          attrs, nullptr, &gl_info));
+  context_ = context_provider_ ? context_provider_->context3d() : nullptr;
+  gl_ = context_provider_ ? context_provider_->contextGL() : nullptr;
 
   if (!InitScene())
     return false;
@@ -205,8 +209,7 @@
   DestroyScene();
 
   gl_ = nullptr;
-  delete context_;
-  context_ = nullptr;
+  context_provider_.reset();
 
   container_ = nullptr;
   frame_ = nullptr;
@@ -240,7 +243,7 @@
 
   if (rect_.isEmpty()) {
     texture_mailbox_ = cc::TextureMailbox();
-  } else if (context_) {
+  } else if (gl_) {
     gl_->Viewport(0, 0, rect_.width, rect_.height);
 
     gl_->BindTexture(GL_TEXTURE_2D, color_texture_);
@@ -334,7 +337,7 @@
 
 // FIXME: This method should already exist. Use it.
 // For now just parse primary colors.
-void TestPlugin::ParseColor(const blink::WebString& string, unsigned color[3]) {
+void TestPlugin::ParseColor(const blink::WebString& string, uint8_t color[3]) {
   color[0] = color[1] = color[2] = 0;
   if (string == "black")
     return;
@@ -359,14 +362,14 @@
 }
 
 bool TestPlugin::InitScene() {
-  if (!context_)
+  if (!gl_)
     return true;
 
   float color[4];
   PremultiplyAlpha(scene_.background_color, scene_.opacity, color);
 
-  color_texture_ = context_->createTexture();
-  framebuffer_ = context_->createFramebuffer();
+  gl_->GenTextures(1, &color_texture_);
+  gl_->GenFramebuffers(1, &framebuffer_);
 
   gl_->Viewport(0, 0, rect_.width, rect_.height);
   gl_->Disable(GL_DEPTH_TEST);
@@ -423,17 +426,17 @@
     scene_.program = 0;
   }
   if (scene_.vbo) {
-    context_->deleteBuffer(scene_.vbo);
+    gl_->DeleteBuffers(1, &scene_.vbo);
     scene_.vbo = 0;
   }
 
   if (framebuffer_) {
-    context_->deleteFramebuffer(framebuffer_);
+    gl_->DeleteFramebuffers(1, &framebuffer_);
     framebuffer_ = 0;
   }
 
   if (color_texture_) {
-    context_->deleteTexture(color_texture_);
+    gl_->DeleteTextures(1, &color_texture_);
     color_texture_ = 0;
   }
 }
@@ -464,7 +467,7 @@
 bool TestPlugin::InitPrimitive() {
   DCHECK_EQ(scene_.primitive, PrimitiveTriangle);
 
-  scene_.vbo = context_->createBuffer();
+  gl_->GenBuffers(1, &scene_.vbo);
   if (!scene_.vbo)
     return false;
 
@@ -496,10 +499,12 @@
   gl_->DrawArrays(GL_TRIANGLES, 0, 3);
 }
 
-unsigned TestPlugin::LoadShader(unsigned type, const std::string& source) {
-  unsigned shader = gl_->CreateShader(type);
+GLuint TestPlugin::LoadShader(GLenum type, const std::string& source) {
+  GLuint shader = gl_->CreateShader(type);
   if (shader) {
-    context_->shaderSource(shader, source.data());
+    const GLchar* shader_data = source.data();
+    GLint shader_length = strlen(shader_data); //source.length();
+    gl_->ShaderSource(shader, 1, &shader_data, &shader_length);
     gl_->CompileShader(shader);
 
     int compiled = 0;
@@ -512,11 +517,11 @@
   return shader;
 }
 
-unsigned TestPlugin::LoadProgram(const std::string& vertex_source,
-                                 const std::string& fragment_source) {
-  unsigned vertex_shader = LoadShader(GL_VERTEX_SHADER, vertex_source);
-  unsigned fragment_shader = LoadShader(GL_FRAGMENT_SHADER, fragment_source);
-  unsigned program = gl_->CreateProgram();
+GLuint TestPlugin::LoadProgram(const std::string& vertex_source,
+                               const std::string& fragment_source) {
+  GLuint vertex_shader = LoadShader(GL_VERTEX_SHADER, vertex_source);
+  GLuint fragment_shader = LoadShader(GL_FRAGMENT_SHADER, fragment_source);
+  GLuint program = gl_->CreateProgram();
   if (vertex_shader && fragment_shader && program) {
     gl_->AttachShader(program, vertex_shader);
     gl_->AttachShader(program, fragment_shader);
diff --git a/components/test_runner/test_plugin.h b/components/test_runner/test_plugin.h
index cc91cbd..4e595aa 100644
--- a/components/test_runner/test_plugin.h
+++ b/components/test_runner/test_plugin.h
@@ -17,10 +17,12 @@
 #include "third_party/WebKit/public/platform/WebLayer.h"
 #include "third_party/WebKit/public/web/WebPlugin.h"
 #include "third_party/WebKit/public/web/WebPluginContainer.h"
+#include "third_party/khronos/GLES2/gl2.h"
 
 namespace blink {
 class WebFrame;
 class WebGraphicsContext3D;
+class WebGraphicsContext3DProvider;
 class WebLayer;
 struct WebPluginParams;
 }
@@ -108,12 +110,12 @@
 
   struct Scene {
     Primitive primitive;
-    unsigned background_color[3];
-    unsigned primitive_color[3];
+    uint8_t background_color[3];
+    uint8_t primitive_color[3];
     float opacity;
 
-    unsigned vbo;
-    unsigned program;
+    GLuint vbo;
+    GLuint program;
     int color_location;
     int position_location;
 
@@ -132,7 +134,7 @@
 
   // Functions for parsing plugin parameters.
   Primitive ParsePrimitive(const blink::WebString& string);
-  void ParseColor(const blink::WebString& string, unsigned color[3]);
+  void ParseColor(const blink::WebString& string, uint8_t color[3]);
   float ParseOpacity(const blink::WebString& string);
   bool ParseBoolean(const blink::WebString& string);
 
@@ -143,9 +145,9 @@
   bool InitProgram();
   bool InitPrimitive();
   void DrawPrimitive();
-  unsigned LoadShader(unsigned type, const std::string& source);
-  unsigned LoadProgram(const std::string& vertex_source,
-                       const std::string& fragment_source);
+  GLuint LoadShader(GLenum type, const std::string& source);
+  GLuint LoadProgram(const std::string& vertex_source,
+                     const std::string& fragment_source);
 
   // Functions for drawing scene in Software.
   void DrawSceneSoftware(void* memory);
@@ -155,13 +157,14 @@
   blink::WebPluginContainer* container_;
 
   blink::WebRect rect_;
+  scoped_ptr<blink::WebGraphicsContext3DProvider> context_provider_;
   blink::WebGraphicsContext3D* context_;
   gpu::gles2::GLES2Interface* gl_;
-  unsigned color_texture_;
+  GLuint color_texture_;
   cc::TextureMailbox texture_mailbox_;
   scoped_ptr<cc::SharedBitmap> shared_bitmap_;
   bool mailbox_changed_;
-  unsigned framebuffer_;
+  GLuint framebuffer_;
   Scene scene_;
   scoped_refptr<cc::TextureLayer> layer_;
   scoped_ptr<blink::WebLayer> web_layer_;
diff --git a/components/test_runner/test_runner.cc b/components/test_runner/test_runner.cc
index 5ef5b5ea2..3282deb 100644
--- a/components/test_runner/test_runner.cc
+++ b/components/test_runner/test_runner.cc
@@ -167,185 +167,185 @@
   gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
       v8::Isolate* isolate) override;
 
-  void LogToStderr(const std::string& output);
-  void NotifyDone();
-  void WaitUntilDone();
-  void QueueBackNavigation(int how_far_back);
-  void QueueForwardNavigation(int how_far_forward);
-  void QueueReload();
-  void QueueLoadingScript(const std::string& script);
-  void QueueNonLoadingScript(const std::string& script);
-  void QueueLoad(gin::Arguments* args);
-  void QueueLoadHTMLString(gin::Arguments* args);
-  void SetCustomPolicyDelegate(gin::Arguments* args);
-  void WaitForPolicyDelegate();
-  int WindowCount();
-  void SetCloseRemainingWindowsWhenComplete(gin::Arguments* args);
-  void ResetTestHelperControllers();
-  void SetTabKeyCyclesThroughElements(bool tab_key_cycles_through_elements);
-  void ExecCommand(gin::Arguments* args);
-  bool IsCommandEnabled(const std::string& command);
-  bool CallShouldCloseOnWebView();
-  void SetDomainRelaxationForbiddenForURLScheme(bool forbidden,
-                                                const std::string& scheme);
-  v8::Local<v8::Value> EvaluateScriptInIsolatedWorldAndReturnValue(
-      int world_id, const std::string& script);
-  void EvaluateScriptInIsolatedWorld(int world_id, const std::string& script);
-  void SetIsolatedWorldSecurityOrigin(int world_id,
-                                      v8::Local<v8::Value> origin);
-  void SetIsolatedWorldContentSecurityPolicy(int world_id,
-                                             const std::string& policy);
+  void AddMockSpeechRecognitionResult(const std::string& transcript,
+                                      double confidence);
   void AddOriginAccessWhitelistEntry(const std::string& source_origin,
                                      const std::string& destination_protocol,
                                      const std::string& destination_host,
                                      bool allow_destination_subdomains);
-  void RemoveOriginAccessWhitelistEntry(const std::string& source_origin,
-                                        const std::string& destination_protocol,
-                                        const std::string& destination_host,
-                                        bool allow_destination_subdomains);
-  bool HasCustomPageSizeStyle(int page_index);
-  void ForceRedSelectionColors();
-  void InsertStyleSheet(const std::string& source_code);
-  bool FindString(const std::string& search_text,
-                  const std::vector<std::string>& options_array);
-  std::string SelectionAsMarkup();
-  void SetTextSubpixelPositioning(bool value);
-  void SetPageVisibility(const std::string& new_visibility);
-  void SetTextDirection(const std::string& direction_name);
-  void UseUnfortunateSynchronousResizeMode();
-  bool EnableAutoResizeMode(int min_width,
-                            int min_height,
-                            int max_width,
-                            int max_height);
-  bool DisableAutoResizeMode(int new_width, int new_height);
-  void SetMockDeviceLight(double value);
-  void ResetDeviceLight();
-  void SetMockDeviceMotion(gin::Arguments* args);
-  void SetMockDeviceOrientation(gin::Arguments* args);
-  void SetMockScreenOrientation(const std::string& orientation);
-  void DisableMockScreenOrientation();
-  void DidAcquirePointerLock();
-  void DidNotAcquirePointerLock();
-  void DidLosePointerLock();
-  void SetPointerLockWillFailSynchronously();
-  void SetPointerLockWillRespondAsynchronously();
-  void SetPopupBlockingEnabled(bool block_popups);
-  void SetJavaScriptCanAccessClipboard(bool can_access);
-  void SetXSSAuditorEnabled(bool enabled);
-  void SetAllowUniversalAccessFromFileURLs(bool allow);
-  void SetAllowFileAccessFromFileURLs(bool allow);
-  void OverridePreference(const std::string& key, v8::Local<v8::Value> value);
-  void SetAcceptLanguages(const std::string& accept_languages);
-  void SetPluginsEnabled(bool enabled);
-  bool AnimationScheduled();
-  void DumpEditingCallbacks();
-  void DumpAsMarkup();
-  void DumpAsText();
-  void DumpAsTextWithPixelResults();
-  void DumpChildFrameScrollPositions();
-  void DumpChildFramesAsMarkup();
-  void DumpChildFramesAsText();
-  void DumpIconChanges();
-  void SetAudioData(const gin::ArrayBufferView& view);
-  void DumpFrameLoadCallbacks();
-  void DumpPingLoaderCallbacks();
-  void DumpUserGestureInFrameLoadCallbacks();
-  void DumpTitleChanges();
-  void DumpCreateView();
-  void SetCanOpenWindows();
-  void DumpResourceLoadCallbacks();
-  void DumpResourceRequestCallbacks();
-  void DumpResourceResponseMIMETypes();
-  void SetImagesAllowed(bool allowed);
-  void SetMediaAllowed(bool allowed);
-  void SetScriptsAllowed(bool allowed);
-  void SetStorageAllowed(bool allowed);
-  void SetPluginsAllowed(bool allowed);
-  void SetAllowDisplayOfInsecureContent(bool allowed);
-  void SetAllowRunningOfInsecureContent(bool allowed);
-  void DumpPermissionClientCallbacks();
-  void DumpWindowStatusChanges();
-  void DumpSpellCheckCallbacks();
-  void DumpBackForwardList();
-  void DumpSelectionRect();
-  void SetPrinting();
-  void ClearPrinting();
-  void SetShouldStayOnPageAfterHandlingBeforeUnload(bool value);
-  void SetWillSendRequestClearHeader(const std::string& header);
-  void DumpResourceRequestPriorities();
-  void SetUseMockTheme(bool use);
-  void WaitUntilExternalURLLoad();
-  void DumpDragImage();
-  void DumpNavigationPolicy();
-  void DumpPageImportanceSignals();
-  void ShowWebInspector(gin::Arguments* args);
-  void CloseWebInspector();
-  bool IsChooserShown();
-  void EvaluateInWebInspector(int call_id, const std::string& script);
-  std::string EvaluateInWebInspectorOverlay(const std::string& script);
-  void ClearAllDatabases();
-  void SetDatabaseQuota(int quota);
-  void SetAlwaysAcceptCookies(bool accept);
-  void SetWindowIsKey(bool value);
-  std::string PathToLocalResource(const std::string& path);
-  void SetBackingScaleFactor(double value, v8::Local<v8::Function> callback);
-  void EnableUseZoomForDSF(v8::Local<v8::Function> callback);
-  void SetColorProfile(const std::string& name,
-                       v8::Local<v8::Function> callback);
-  void SetPOSIXLocale(const std::string& locale);
-  void SetMIDIAccessorResult(bool result);
-  void SimulateWebNotificationClick(const std::string& title, int action_index);
-  void SimulateWebNotificationClose(const std::string& title, bool by_user);
-  void AddMockSpeechRecognitionResult(const std::string& transcript,
-                                      double confidence);
-  void SetMockSpeechRecognitionError(const std::string& error,
-                                     const std::string& message);
-  bool WasMockSpeechRecognitionAborted();
-  void AddMockCredentialManagerResponse(const std::string& id,
-                                        const std::string& name,
-                                        const std::string& avatar,
-                                        const std::string& password);
-  void AddMockCredentialManagerError(const std::string& error);
   void AddWebPageOverlay();
-  void RemoveWebPageOverlay();
-  void LayoutAndPaintAsync();
-  void LayoutAndPaintAsyncThen(v8::Local<v8::Function> callback);
-  void GetManifestThen(v8::Local<v8::Function> callback);
   void CapturePixelsAsyncThen(v8::Local<v8::Function> callback);
+  void ClearAllDatabases();
+  void ClearGeofencingMockProvider();
+  void ClearPrinting();
+  void CloseWebInspector();
   void CopyImageAtAndCapturePixelsAsyncThen(int x,
                                             int y,
                                             v8::Local<v8::Function> callback);
-  void SetCustomTextOutput(const std::string& output);
-  void SetViewSourceForFrame(const std::string& name, bool enabled);
-  void SetBluetoothMockDataSet(const std::string& dataset_name);
-  void SetBluetoothManualChooser();
-  void GetBluetoothManualChooserEvents(v8::Local<v8::Function> callback);
-  void SendBluetoothManualChooserEvent(const std::string& event,
-                                       const std::string& argument);
-  void SetGeofencingMockProvider(bool service_available);
-  void ClearGeofencingMockProvider();
-  void SetGeofencingMockPosition(double latitude, double longitude);
-  void SetPermission(const std::string& name,
-                     const std::string& value,
-                     const std::string& origin,
-                     const std::string& embedding_origin);
+  void DidAcquirePointerLock();
+  void DidLosePointerLock();
+  void DidNotAcquirePointerLock();
+  void DisableMockScreenOrientation();
   void DispatchBeforeInstallPromptEvent(
       int request_id,
       const std::vector<std::string>& event_platforms,
       v8::Local<v8::Function> callback);
+  void DumpAsMarkup();
+  void DumpAsText();
+  void DumpAsTextWithPixelResults();
+  void DumpBackForwardList();
+  void DumpChildFrameScrollPositions();
+  void DumpChildFramesAsMarkup();
+  void DumpChildFramesAsText();
+  void DumpCreateView();
+  void DumpDragImage();
+  void DumpEditingCallbacks();
+  void DumpFrameLoadCallbacks();
+  void DumpIconChanges();
+  void DumpNavigationPolicy();
+  void DumpPageImportanceSignals();
+  void DumpPermissionClientCallbacks();
+  void DumpPingLoaderCallbacks();
+  void DumpResourceLoadCallbacks();
+  void DumpResourceRequestCallbacks();
+  void DumpResourceRequestPriorities();
+  void DumpResourceResponseMIMETypes();
+  void DumpSelectionRect();
+  void DumpSpellCheckCallbacks();
+  void DumpTitleChanges();
+  void DumpUserGestureInFrameLoadCallbacks();
+  void DumpWindowStatusChanges();
+  void EnableUseZoomForDSF(v8::Local<v8::Function> callback);
+  void EvaluateInWebInspector(int call_id, const std::string& script);
+  void EvaluateScriptInIsolatedWorld(int world_id, const std::string& script);
+  void ExecCommand(gin::Arguments* args);
+  void ForceNextDrawingBufferCreationToFail();
+  void ForceNextWebGLContextCreationToFail();
+  void ForceRedSelectionColors();
+  void GetBluetoothManualChooserEvents(v8::Local<v8::Function> callback);
+  void GetManifestThen(v8::Local<v8::Function> callback);
+  void InsertStyleSheet(const std::string& source_code);
+  void LayoutAndPaintAsync();
+  void LayoutAndPaintAsyncThen(v8::Local<v8::Function> callback);
+  void LogToStderr(const std::string& output);
+  void NotImplemented(const gin::Arguments& args);
+  void NotifyDone();
+  void OverridePreference(const std::string& key, v8::Local<v8::Value> value);
+  void QueueBackNavigation(int how_far_back);
+  void QueueForwardNavigation(int how_far_forward);
+  void QueueLoad(gin::Arguments* args);
+  void QueueLoadHTMLString(gin::Arguments* args);
+  void QueueLoadingScript(const std::string& script);
+  void QueueNonLoadingScript(const std::string& script);
+  void QueueReload();
+  void RemoveOriginAccessWhitelistEntry(const std::string& source_origin,
+                                        const std::string& destination_protocol,
+                                        const std::string& destination_host,
+                                        bool allow_destination_subdomains);
+  void RemoveWebPageOverlay();
+  void ResetDeviceLight();
+  void ResetTestHelperControllers();
   void ResolveBeforeInstallPromptPromise(int request_id,
                                          const std::string& platform);
-
-  std::string PlatformName();
-  std::string TooltipText();
-  int WebHistoryItemCount();
-  bool InterceptPostMessage();
+  void SendBluetoothManualChooserEvent(const std::string& event,
+                                       const std::string& argument);
+  void SetAcceptLanguages(const std::string& accept_languages);
+  void SetAllowDisplayOfInsecureContent(bool allowed);
+  void SetAllowFileAccessFromFileURLs(bool allow);
+  void SetAllowRunningOfInsecureContent(bool allowed);
+  void SetAllowUniversalAccessFromFileURLs(bool allow);
+  void SetAlwaysAcceptCookies(bool accept);
+  void SetAudioData(const gin::ArrayBufferView& view);
+  void SetBackingScaleFactor(double value, v8::Local<v8::Function> callback);
+  void SetBluetoothManualChooser();
+  void SetBluetoothMockDataSet(const std::string& dataset_name);
+  void SetCanOpenWindows();
+  void SetCloseRemainingWindowsWhenComplete(gin::Arguments* args);
+  void SetColorProfile(const std::string& name,
+                       v8::Local<v8::Function> callback);
+  void SetCustomPolicyDelegate(gin::Arguments* args);
+  void SetCustomTextOutput(const std::string& output);
+  void SetDatabaseQuota(int quota);
+  void SetDomainRelaxationForbiddenForURLScheme(bool forbidden,
+                                                const std::string& scheme);
+  void SetGeofencingMockPosition(double latitude, double longitude);
+  void SetGeofencingMockProvider(bool service_available);
+  void SetImagesAllowed(bool allowed);
   void SetInterceptPostMessage(bool value);
+  void SetIsolatedWorldContentSecurityPolicy(int world_id,
+                                             const std::string& policy);
+  void SetIsolatedWorldSecurityOrigin(int world_id,
+                                      v8::Local<v8::Value> origin);
+  void SetJavaScriptCanAccessClipboard(bool can_access);
+  void SetMIDIAccessorResult(bool result);
+  void SetMediaAllowed(bool allowed);
+  void SetMockDeviceLight(double value);
+  void SetMockDeviceMotion(gin::Arguments* args);
+  void SetMockDeviceOrientation(gin::Arguments* args);
+  void SetMockScreenOrientation(const std::string& orientation);
+  void SetMockSpeechRecognitionError(const std::string& error,
+                                     const std::string& message);
+  void SetPOSIXLocale(const std::string& locale);
+  void SetPageVisibility(const std::string& new_visibility);
+  void SetPermission(const std::string& name,
+                     const std::string& value,
+                     const std::string& origin,
+                     const std::string& embedding_origin);
+  void SetPluginsAllowed(bool allowed);
+  void SetPluginsEnabled(bool enabled);
+  void SetPointerLockWillFailSynchronously();
+  void SetPointerLockWillRespondAsynchronously();
+  void SetPopupBlockingEnabled(bool block_popups);
+  void SetPrinting();
+  void SetScriptsAllowed(bool allowed);
+  void SetShouldStayOnPageAfterHandlingBeforeUnload(bool value);
+  void SetStorageAllowed(bool allowed);
+  void SetTabKeyCyclesThroughElements(bool tab_key_cycles_through_elements);
+  void SetTextDirection(const std::string& direction_name);
+  void SetTextSubpixelPositioning(bool value);
+  void SetUseMockTheme(bool use);
+  void SetViewSourceForFrame(const std::string& name, bool enabled);
+  void SetWillSendRequestClearHeader(const std::string& header);
+  void SetWindowIsKey(bool value);
+  void SetXSSAuditorEnabled(bool enabled);
+  void ShowWebInspector(gin::Arguments* args);
+  void SimulateWebNotificationClick(const std::string& title, int action_index);
+  void SimulateWebNotificationClose(const std::string& title, bool by_user);
+  void UseUnfortunateSynchronousResizeMode();
+  void WaitForPolicyDelegate();
+  void WaitUntilDone();
+  void WaitUntilExternalURLLoad();
+  void AddMockCredentialManagerError(const std::string& error);
+  void AddMockCredentialManagerResponse(const std::string& id,
+                                        const std::string& name,
+                                        const std::string& avatar,
+                                        const std::string& password);
+  bool AnimationScheduled();
+  bool CallShouldCloseOnWebView();
+  bool DisableAutoResizeMode(int new_width, int new_height);
+  bool EnableAutoResizeMode(int min_width,
+                            int min_height,
+                            int max_width,
+                            int max_height);
+  std::string EvaluateInWebInspectorOverlay(const std::string& script);
+  v8::Local<v8::Value> EvaluateScriptInIsolatedWorldAndReturnValue(
+      int world_id, const std::string& script);
+  bool FindString(const std::string& search_text,
+                  const std::vector<std::string>& options_array);
+  bool HasCustomPageSizeStyle(int page_index);
+  bool InterceptPostMessage();
+  bool IsChooserShown();
 
-  void NotImplemented(const gin::Arguments& args);
+  bool IsCommandEnabled(const std::string& command);
+  std::string PathToLocalResource(const std::string& path);
+  std::string PlatformName();
+  std::string SelectionAsMarkup();
+  std::string TooltipText();
 
-  void ForceNextWebGLContextCreationToFail();
-  void ForceNextDrawingBufferCreationToFail();
+  bool WasMockSpeechRecognitionAborted();
+
+  int WebHistoryItemCount();
+  int WindowCount();
 
   base::WeakPtr<TestRunner> runner_;
 
@@ -389,288 +389,290 @@
 gin::ObjectTemplateBuilder TestRunnerBindings::GetObjectTemplateBuilder(
     v8::Isolate* isolate) {
   return gin::Wrappable<TestRunnerBindings>::GetObjectTemplateBuilder(isolate)
-      // Methods controlling test execution.
+      .SetMethod("abortModal", &TestRunnerBindings::NotImplemented)
+      .SetMethod("addDisallowedURL", &TestRunnerBindings::NotImplemented)
+      .SetMethod("addMockCredentialManagerError",
+                 &TestRunnerBindings::AddMockCredentialManagerError)
+      .SetMethod("addMockCredentialManagerResponse",
+                 &TestRunnerBindings::AddMockCredentialManagerResponse)
+      .SetMethod("addMockSpeechRecognitionResult",
+                 &TestRunnerBindings::AddMockSpeechRecognitionResult)
+      .SetMethod("addOriginAccessWhitelistEntry",
+                 &TestRunnerBindings::AddOriginAccessWhitelistEntry)
+      .SetMethod("addWebPageOverlay", &TestRunnerBindings::AddWebPageOverlay)
+      .SetMethod("animationScheduled", &TestRunnerBindings::AnimationScheduled)
+      .SetMethod("applicationCacheDiskUsageForOrigin",
+                 &TestRunnerBindings::NotImplemented)
+      .SetMethod("callShouldCloseOnWebView",
+                 &TestRunnerBindings::CallShouldCloseOnWebView)
+      .SetMethod("capturePixelsAsyncThen",
+                 &TestRunnerBindings::CapturePixelsAsyncThen)
+      .SetMethod("clearAllApplicationCaches",
+                 &TestRunnerBindings::NotImplemented)
+      .SetMethod("clearAllDatabases", &TestRunnerBindings::ClearAllDatabases)
+      .SetMethod("clearApplicationCacheForOrigin",
+                 &TestRunnerBindings::NotImplemented)
+      .SetMethod("clearBackForwardList", &TestRunnerBindings::NotImplemented)
+      .SetMethod("clearGeofencingMockProvider",
+                 &TestRunnerBindings::ClearGeofencingMockProvider)
+      .SetMethod("clearPrinting", &TestRunnerBindings::ClearPrinting)
+      .SetMethod("closeWebInspector", &TestRunnerBindings::CloseWebInspector)
+      .SetMethod("copyImageAtAndCapturePixelsAsyncThen",
+                 &TestRunnerBindings::CopyImageAtAndCapturePixelsAsyncThen)
+      .SetMethod("deleteAllLocalStorage", &TestRunnerBindings::NotImplemented)
+      .SetMethod("deleteLocalStorageForOrigin",
+                 &TestRunnerBindings::NotImplemented)
+      .SetMethod("didAcquirePointerLock",
+                 &TestRunnerBindings::DidAcquirePointerLock)
+      .SetMethod("didLosePointerLock", &TestRunnerBindings::DidLosePointerLock)
+      .SetMethod("didNotAcquirePointerLock",
+                 &TestRunnerBindings::DidNotAcquirePointerLock)
+      .SetMethod("disableAutoResizeMode",
+                 &TestRunnerBindings::DisableAutoResizeMode)
+      .SetMethod("disableMockScreenOrientation",
+                 &TestRunnerBindings::DisableMockScreenOrientation)
+      .SetMethod("dispatchBeforeInstallPromptEvent",
+                 &TestRunnerBindings::DispatchBeforeInstallPromptEvent)
+      .SetMethod("dumpAsMarkup", &TestRunnerBindings::DumpAsMarkup)
+      .SetMethod("dumpAsText", &TestRunnerBindings::DumpAsText)
+      .SetMethod("dumpAsTextWithPixelResults",
+                 &TestRunnerBindings::DumpAsTextWithPixelResults)
+      .SetMethod("dumpBackForwardList",
+                 &TestRunnerBindings::DumpBackForwardList)
+      .SetMethod("dumpChildFrameScrollPositions",
+                 &TestRunnerBindings::DumpChildFrameScrollPositions)
+      .SetMethod("dumpChildFramesAsMarkup",
+                 &TestRunnerBindings::DumpChildFramesAsMarkup)
+      .SetMethod("dumpChildFramesAsText",
+                 &TestRunnerBindings::DumpChildFramesAsText)
+      .SetMethod("dumpCreateView", &TestRunnerBindings::DumpCreateView)
+      .SetMethod("dumpDatabaseCallbacks", &TestRunnerBindings::NotImplemented)
+      .SetMethod("dumpDragImage", &TestRunnerBindings::DumpDragImage)
+      .SetMethod("dumpEditingCallbacks",
+                 &TestRunnerBindings::DumpEditingCallbacks)
+      .SetMethod("dumpFrameLoadCallbacks",
+                 &TestRunnerBindings::DumpFrameLoadCallbacks)
+      .SetMethod("dumpIconChanges", &TestRunnerBindings::DumpIconChanges)
+      .SetMethod("dumpNavigationPolicy",
+                 &TestRunnerBindings::DumpNavigationPolicy)
+      .SetMethod("dumpPageImportanceSignals",
+                 &TestRunnerBindings::DumpPageImportanceSignals)
+      .SetMethod("dumpPermissionClientCallbacks",
+                 &TestRunnerBindings::DumpPermissionClientCallbacks)
+      .SetMethod("dumpPingLoaderCallbacks",
+                 &TestRunnerBindings::DumpPingLoaderCallbacks)
+      .SetMethod("dumpResourceLoadCallbacks",
+                 &TestRunnerBindings::DumpResourceLoadCallbacks)
+      .SetMethod("dumpResourceRequestCallbacks",
+                 &TestRunnerBindings::DumpResourceRequestCallbacks)
+      .SetMethod("dumpResourceRequestPriorities",
+                 &TestRunnerBindings::DumpResourceRequestPriorities)
+      .SetMethod("dumpResourceResponseMIMETypes",
+                 &TestRunnerBindings::DumpResourceResponseMIMETypes)
+      .SetMethod("dumpSelectionRect", &TestRunnerBindings::DumpSelectionRect)
+      .SetMethod("dumpSpellCheckCallbacks",
+                 &TestRunnerBindings::DumpSpellCheckCallbacks)
+
+      // Used at fast/dom/assign-to-window-status.html
+      .SetMethod("dumpStatusCallbacks",
+                 &TestRunnerBindings::DumpWindowStatusChanges)
+      .SetMethod("dumpTitleChanges", &TestRunnerBindings::DumpTitleChanges)
+      .SetMethod("dumpUserGestureInFrameLoadCallbacks",
+                 &TestRunnerBindings::DumpUserGestureInFrameLoadCallbacks)
+      .SetMethod("dumpWindowStatusChanges",
+                 &TestRunnerBindings::DumpWindowStatusChanges)
+      .SetMethod("enableAutoResizeMode",
+                 &TestRunnerBindings::EnableAutoResizeMode)
+      .SetMethod("enableUseZoomForDSF",
+                 &TestRunnerBindings::EnableUseZoomForDSF)
+      .SetMethod("evaluateInWebInspector",
+                 &TestRunnerBindings::EvaluateInWebInspector)
+      .SetMethod("evaluateInWebInspectorOverlay",
+                 &TestRunnerBindings::EvaluateInWebInspectorOverlay)
+      .SetMethod("evaluateScriptInIsolatedWorld",
+                 &TestRunnerBindings::EvaluateScriptInIsolatedWorld)
+      .SetMethod(
+          "evaluateScriptInIsolatedWorldAndReturnValue",
+          &TestRunnerBindings::EvaluateScriptInIsolatedWorldAndReturnValue)
+      .SetMethod("execCommand", &TestRunnerBindings::ExecCommand)
+      .SetMethod("findString", &TestRunnerBindings::FindString)
+      .SetMethod("forceNextDrawingBufferCreationToFail",
+                 &TestRunnerBindings::ForceNextDrawingBufferCreationToFail)
+      .SetMethod("forceNextWebGLContextCreationToFail",
+                 &TestRunnerBindings::ForceNextWebGLContextCreationToFail)
+      .SetMethod("forceRedSelectionColors",
+                 &TestRunnerBindings::ForceRedSelectionColors)
+
+      // The Bluetooth functions are specified at
+      // https://webbluetoothcg.github.io/web-bluetooth/tests/.
+      .SetMethod("getBluetoothManualChooserEvents",
+                 &TestRunnerBindings::GetBluetoothManualChooserEvents)
+      .SetMethod("getManifestThen", &TestRunnerBindings::GetManifestThen)
+      .SetMethod("hasCustomPageSizeStyle",
+                 &TestRunnerBindings::HasCustomPageSizeStyle)
+      .SetMethod("insertStyleSheet", &TestRunnerBindings::InsertStyleSheet)
+      .SetProperty("interceptPostMessage",
+                   &TestRunnerBindings::InterceptPostMessage,
+                   &TestRunnerBindings::SetInterceptPostMessage)
+      .SetMethod("isChooserShown", &TestRunnerBindings::IsChooserShown)
+      .SetMethod("isCommandEnabled", &TestRunnerBindings::IsCommandEnabled)
+      .SetMethod("keepWebHistory", &TestRunnerBindings::NotImplemented)
+      .SetMethod("layoutAndPaintAsync",
+                 &TestRunnerBindings::LayoutAndPaintAsync)
+      .SetMethod("layoutAndPaintAsyncThen",
+                 &TestRunnerBindings::LayoutAndPaintAsyncThen)
+      .SetMethod("localStorageDiskUsageForOrigin",
+                 &TestRunnerBindings::NotImplemented)
       .SetMethod("logToStderr", &TestRunnerBindings::LogToStderr)
       .SetMethod("notifyDone", &TestRunnerBindings::NotifyDone)
-      .SetMethod("waitUntilDone", &TestRunnerBindings::WaitUntilDone)
+      .SetMethod("observeStorageTrackerNotifications",
+                 &TestRunnerBindings::NotImplemented)
+      .SetMethod("originsWithLocalStorage", &TestRunnerBindings::NotImplemented)
+      .SetMethod("overridePreference", &TestRunnerBindings::OverridePreference)
+      .SetMethod("pathToLocalResource",
+                 &TestRunnerBindings::PathToLocalResource)
+      .SetProperty("platformName", &TestRunnerBindings::PlatformName)
       .SetMethod("queueBackNavigation",
                  &TestRunnerBindings::QueueBackNavigation)
       .SetMethod("queueForwardNavigation",
                  &TestRunnerBindings::QueueForwardNavigation)
-      .SetMethod("queueReload", &TestRunnerBindings::QueueReload)
-      .SetMethod("queueLoadingScript", &TestRunnerBindings::QueueLoadingScript)
-      .SetMethod("queueNonLoadingScript",
-                 &TestRunnerBindings::QueueNonLoadingScript)
       .SetMethod("queueLoad", &TestRunnerBindings::QueueLoad)
       .SetMethod("queueLoadHTMLString",
                  &TestRunnerBindings::QueueLoadHTMLString)
-      .SetMethod("setCustomPolicyDelegate",
-                 &TestRunnerBindings::SetCustomPolicyDelegate)
-      .SetMethod("waitForPolicyDelegate",
-                 &TestRunnerBindings::WaitForPolicyDelegate)
-      .SetMethod("windowCount", &TestRunnerBindings::WindowCount)
-      .SetMethod("setCloseRemainingWindowsWhenComplete",
-                 &TestRunnerBindings::SetCloseRemainingWindowsWhenComplete)
-      .SetMethod("resetTestHelperControllers",
-                 &TestRunnerBindings::ResetTestHelperControllers)
-      .SetMethod("setTabKeyCyclesThroughElements",
-                 &TestRunnerBindings::SetTabKeyCyclesThroughElements)
-      .SetMethod("execCommand", &TestRunnerBindings::ExecCommand)
-      .SetMethod("isCommandEnabled", &TestRunnerBindings::IsCommandEnabled)
-      .SetMethod("callShouldCloseOnWebView",
-                 &TestRunnerBindings::CallShouldCloseOnWebView)
-      .SetMethod("setDomainRelaxationForbiddenForURLScheme",
-                 &TestRunnerBindings::SetDomainRelaxationForbiddenForURLScheme)
-      .SetMethod(
-          "evaluateScriptInIsolatedWorldAndReturnValue",
-          &TestRunnerBindings::EvaluateScriptInIsolatedWorldAndReturnValue)
-      .SetMethod("evaluateScriptInIsolatedWorld",
-                 &TestRunnerBindings::EvaluateScriptInIsolatedWorld)
-      .SetMethod("setIsolatedWorldSecurityOrigin",
-                 &TestRunnerBindings::SetIsolatedWorldSecurityOrigin)
-      .SetMethod("setIsolatedWorldContentSecurityPolicy",
-                 &TestRunnerBindings::SetIsolatedWorldContentSecurityPolicy)
-      .SetMethod("addOriginAccessWhitelistEntry",
-                 &TestRunnerBindings::AddOriginAccessWhitelistEntry)
+      .SetMethod("queueLoadingScript", &TestRunnerBindings::QueueLoadingScript)
+      .SetMethod("queueNonLoadingScript",
+                 &TestRunnerBindings::QueueNonLoadingScript)
+      .SetMethod("queueReload", &TestRunnerBindings::QueueReload)
       .SetMethod("removeOriginAccessWhitelistEntry",
                  &TestRunnerBindings::RemoveOriginAccessWhitelistEntry)
-      .SetMethod("hasCustomPageSizeStyle",
-                 &TestRunnerBindings::HasCustomPageSizeStyle)
-      .SetMethod("forceRedSelectionColors",
-                 &TestRunnerBindings::ForceRedSelectionColors)
-      .SetMethod("insertStyleSheet", &TestRunnerBindings::InsertStyleSheet)
-      .SetMethod("findString", &TestRunnerBindings::FindString)
-      .SetMethod("selectionAsMarkup", &TestRunnerBindings::SelectionAsMarkup)
-      .SetMethod("setTextSubpixelPositioning",
-                 &TestRunnerBindings::SetTextSubpixelPositioning)
-      .SetMethod("setPageVisibility", &TestRunnerBindings::SetPageVisibility)
-      .SetMethod("setTextDirection", &TestRunnerBindings::SetTextDirection)
-      .SetMethod("useUnfortunateSynchronousResizeMode",
-                 &TestRunnerBindings::UseUnfortunateSynchronousResizeMode)
-      .SetMethod("enableAutoResizeMode",
-                 &TestRunnerBindings::EnableAutoResizeMode)
-      .SetMethod("disableAutoResizeMode",
-                 &TestRunnerBindings::DisableAutoResizeMode)
-      .SetMethod("setMockDeviceLight", &TestRunnerBindings::SetMockDeviceLight)
+      .SetMethod("removeWebPageOverlay",
+                 &TestRunnerBindings::RemoveWebPageOverlay)
       .SetMethod("resetDeviceLight", &TestRunnerBindings::ResetDeviceLight)
+      .SetMethod("resetTestHelperControllers",
+                 &TestRunnerBindings::ResetTestHelperControllers)
+      .SetMethod("resolveBeforeInstallPromptPromise",
+                 &TestRunnerBindings::ResolveBeforeInstallPromptPromise)
+      .SetMethod("selectionAsMarkup", &TestRunnerBindings::SelectionAsMarkup)
+
+      // The Bluetooth functions are specified at
+      // https://webbluetoothcg.github.io/web-bluetooth/tests/.
+      .SetMethod("sendBluetoothManualChooserEvent",
+                 &TestRunnerBindings::SendBluetoothManualChooserEvent)
+      .SetMethod("setAcceptLanguages", &TestRunnerBindings::SetAcceptLanguages)
+      .SetMethod("setAllowDisplayOfInsecureContent",
+                 &TestRunnerBindings::SetAllowDisplayOfInsecureContent)
+      .SetMethod("setAllowFileAccessFromFileURLs",
+                 &TestRunnerBindings::SetAllowFileAccessFromFileURLs)
+      .SetMethod("setAllowRunningOfInsecureContent",
+                 &TestRunnerBindings::SetAllowRunningOfInsecureContent)
+      .SetMethod("setAllowUniversalAccessFromFileURLs",
+                 &TestRunnerBindings::SetAllowUniversalAccessFromFileURLs)
+      .SetMethod("setAlwaysAcceptCookies",
+                 &TestRunnerBindings::SetAlwaysAcceptCookies)
+      .SetMethod("setApplicationCacheOriginQuota",
+                 &TestRunnerBindings::NotImplemented)
+      .SetMethod("setAudioData", &TestRunnerBindings::SetAudioData)
+      .SetMethod("setBackingScaleFactor",
+                 &TestRunnerBindings::SetBackingScaleFactor)
+
+      // The Bluetooth functions are specified at
+      // https://webbluetoothcg.github.io/web-bluetooth/tests/.
+      .SetMethod("setBluetoothManualChooser",
+                 &TestRunnerBindings::SetBluetoothManualChooser)
+      .SetMethod("setBluetoothMockDataSet",
+                 &TestRunnerBindings::SetBluetoothMockDataSet)
+      .SetMethod("setCallCloseOnWebViews", &TestRunnerBindings::NotImplemented)
+      .SetMethod("setCanOpenWindows", &TestRunnerBindings::SetCanOpenWindows)
+      .SetMethod("setCloseRemainingWindowsWhenComplete",
+                 &TestRunnerBindings::SetCloseRemainingWindowsWhenComplete)
+      .SetMethod("setColorProfile", &TestRunnerBindings::SetColorProfile)
+      .SetMethod("setCustomPolicyDelegate",
+                 &TestRunnerBindings::SetCustomPolicyDelegate)
+      .SetMethod("setCustomTextOutput",
+                 &TestRunnerBindings::SetCustomTextOutput)
+      .SetMethod("setDatabaseQuota", &TestRunnerBindings::SetDatabaseQuota)
+      .SetMethod("setDomainRelaxationForbiddenForURLScheme",
+                 &TestRunnerBindings::SetDomainRelaxationForbiddenForURLScheme)
+      .SetMethod("setGeofencingMockPosition",
+                 &TestRunnerBindings::SetGeofencingMockPosition)
+      .SetMethod("setGeofencingMockProvider",
+                 &TestRunnerBindings::SetGeofencingMockProvider)
+      .SetMethod("setIconDatabaseEnabled", &TestRunnerBindings::NotImplemented)
+      .SetMethod("setImagesAllowed", &TestRunnerBindings::SetImagesAllowed)
+      .SetMethod("setIsolatedWorldContentSecurityPolicy",
+                 &TestRunnerBindings::SetIsolatedWorldContentSecurityPolicy)
+      .SetMethod("setIsolatedWorldSecurityOrigin",
+                 &TestRunnerBindings::SetIsolatedWorldSecurityOrigin)
+      .SetMethod("setJavaScriptCanAccessClipboard",
+                 &TestRunnerBindings::SetJavaScriptCanAccessClipboard)
+      .SetMethod("setMIDIAccessorResult",
+                 &TestRunnerBindings::SetMIDIAccessorResult)
+      .SetMethod("setMainFrameIsFirstResponder",
+                 &TestRunnerBindings::NotImplemented)
+      .SetMethod("setMediaAllowed", &TestRunnerBindings::SetMediaAllowed)
+      .SetMethod("setMockDeviceLight", &TestRunnerBindings::SetMockDeviceLight)
       .SetMethod("setMockDeviceMotion",
                  &TestRunnerBindings::SetMockDeviceMotion)
       .SetMethod("setMockDeviceOrientation",
                  &TestRunnerBindings::SetMockDeviceOrientation)
       .SetMethod("setMockScreenOrientation",
                  &TestRunnerBindings::SetMockScreenOrientation)
-      .SetMethod("disableMockScreenOrientation",
-                 &TestRunnerBindings::DisableMockScreenOrientation)
-      .SetMethod("didAcquirePointerLock",
-                 &TestRunnerBindings::DidAcquirePointerLock)
-      .SetMethod("didNotAcquirePointerLock",
-                 &TestRunnerBindings::DidNotAcquirePointerLock)
-      .SetMethod("didLosePointerLock", &TestRunnerBindings::DidLosePointerLock)
+      .SetMethod("setMockSpeechRecognitionError",
+                 &TestRunnerBindings::SetMockSpeechRecognitionError)
+      .SetMethod("setPOSIXLocale", &TestRunnerBindings::SetPOSIXLocale)
+      .SetMethod("setPageVisibility", &TestRunnerBindings::SetPageVisibility)
+      .SetMethod("setPermission", &TestRunnerBindings::SetPermission)
+      .SetMethod("setPluginsAllowed", &TestRunnerBindings::SetPluginsAllowed)
+      .SetMethod("setPluginsEnabled", &TestRunnerBindings::SetPluginsEnabled)
       .SetMethod("setPointerLockWillFailSynchronously",
                  &TestRunnerBindings::SetPointerLockWillFailSynchronously)
       .SetMethod("setPointerLockWillRespondAsynchronously",
                  &TestRunnerBindings::SetPointerLockWillRespondAsynchronously)
       .SetMethod("setPopupBlockingEnabled",
                  &TestRunnerBindings::SetPopupBlockingEnabled)
-      .SetMethod("setJavaScriptCanAccessClipboard",
-                 &TestRunnerBindings::SetJavaScriptCanAccessClipboard)
-      .SetMethod("setXSSAuditorEnabled",
-                 &TestRunnerBindings::SetXSSAuditorEnabled)
-      .SetMethod("setAllowUniversalAccessFromFileURLs",
-                 &TestRunnerBindings::SetAllowUniversalAccessFromFileURLs)
-      .SetMethod("setAllowFileAccessFromFileURLs",
-                 &TestRunnerBindings::SetAllowFileAccessFromFileURLs)
-      .SetMethod("overridePreference", &TestRunnerBindings::OverridePreference)
-      .SetMethod("setAcceptLanguages", &TestRunnerBindings::SetAcceptLanguages)
-      .SetMethod("setPluginsEnabled", &TestRunnerBindings::SetPluginsEnabled)
-      .SetMethod("dumpEditingCallbacks",
-                 &TestRunnerBindings::DumpEditingCallbacks)
-      .SetMethod("dumpAsMarkup", &TestRunnerBindings::DumpAsMarkup)
-      .SetMethod("dumpAsText", &TestRunnerBindings::DumpAsText)
-      .SetMethod("dumpAsTextWithPixelResults",
-                 &TestRunnerBindings::DumpAsTextWithPixelResults)
-      .SetMethod("dumpChildFrameScrollPositions",
-                 &TestRunnerBindings::DumpChildFrameScrollPositions)
-      .SetMethod("dumpChildFramesAsText",
-                 &TestRunnerBindings::DumpChildFramesAsText)
-      .SetMethod("dumpChildFramesAsMarkup",
-                 &TestRunnerBindings::DumpChildFramesAsMarkup)
-      .SetMethod("dumpIconChanges", &TestRunnerBindings::DumpIconChanges)
-      .SetMethod("setAudioData", &TestRunnerBindings::SetAudioData)
-      .SetMethod("dumpFrameLoadCallbacks",
-                 &TestRunnerBindings::DumpFrameLoadCallbacks)
-      .SetMethod("dumpPingLoaderCallbacks",
-                 &TestRunnerBindings::DumpPingLoaderCallbacks)
-      .SetMethod("dumpUserGestureInFrameLoadCallbacks",
-                 &TestRunnerBindings::DumpUserGestureInFrameLoadCallbacks)
-      .SetMethod("dumpTitleChanges", &TestRunnerBindings::DumpTitleChanges)
-      .SetMethod("dumpCreateView", &TestRunnerBindings::DumpCreateView)
-      .SetMethod("setCanOpenWindows", &TestRunnerBindings::SetCanOpenWindows)
-      .SetMethod("dumpResourceLoadCallbacks",
-                 &TestRunnerBindings::DumpResourceLoadCallbacks)
-      .SetMethod("dumpResourceRequestCallbacks",
-                 &TestRunnerBindings::DumpResourceRequestCallbacks)
-      .SetMethod("dumpResourceResponseMIMETypes",
-                 &TestRunnerBindings::DumpResourceResponseMIMETypes)
-      .SetMethod("setImagesAllowed", &TestRunnerBindings::SetImagesAllowed)
-      .SetMethod("setMediaAllowed", &TestRunnerBindings::SetMediaAllowed)
-      .SetMethod("setScriptsAllowed", &TestRunnerBindings::SetScriptsAllowed)
-      .SetMethod("setStorageAllowed", &TestRunnerBindings::SetStorageAllowed)
-      .SetMethod("setPluginsAllowed", &TestRunnerBindings::SetPluginsAllowed)
-      .SetMethod("animationScheduled", &TestRunnerBindings::AnimationScheduled)
-      .SetMethod("setAllowDisplayOfInsecureContent",
-                 &TestRunnerBindings::SetAllowDisplayOfInsecureContent)
-      .SetMethod("setAllowRunningOfInsecureContent",
-                 &TestRunnerBindings::SetAllowRunningOfInsecureContent)
-      .SetMethod("dumpPermissionClientCallbacks",
-                 &TestRunnerBindings::DumpPermissionClientCallbacks)
-      .SetMethod("dumpWindowStatusChanges",
-                 &TestRunnerBindings::DumpWindowStatusChanges)
-      .SetMethod("dumpSpellCheckCallbacks",
-                 &TestRunnerBindings::DumpSpellCheckCallbacks)
-      .SetMethod("dumpBackForwardList",
-                 &TestRunnerBindings::DumpBackForwardList)
-      .SetMethod("dumpSelectionRect", &TestRunnerBindings::DumpSelectionRect)
       .SetMethod("setPrinting", &TestRunnerBindings::SetPrinting)
-      .SetMethod("clearPrinting", &TestRunnerBindings::ClearPrinting)
+      .SetMethod("setScriptsAllowed", &TestRunnerBindings::SetScriptsAllowed)
+      .SetMethod("setScrollbarPolicy", &TestRunnerBindings::NotImplemented)
       .SetMethod(
           "setShouldStayOnPageAfterHandlingBeforeUnload",
           &TestRunnerBindings::SetShouldStayOnPageAfterHandlingBeforeUnload)
+      .SetMethod("setStorageAllowed", &TestRunnerBindings::SetStorageAllowed)
+      .SetMethod("setTabKeyCyclesThroughElements",
+                 &TestRunnerBindings::SetTabKeyCyclesThroughElements)
+      .SetMethod("setTextDirection", &TestRunnerBindings::SetTextDirection)
+      .SetMethod("setTextSubpixelPositioning",
+                 &TestRunnerBindings::SetTextSubpixelPositioning)
+      .SetMethod("setUseDashboardCompatibilityMode",
+                 &TestRunnerBindings::NotImplemented)
+      .SetMethod("setUseMockTheme", &TestRunnerBindings::SetUseMockTheme)
+      .SetMethod("setViewSourceForFrame",
+                 &TestRunnerBindings::SetViewSourceForFrame)
       .SetMethod("setWillSendRequestClearHeader",
                  &TestRunnerBindings::SetWillSendRequestClearHeader)
-      .SetMethod("dumpResourceRequestPriorities",
-                 &TestRunnerBindings::DumpResourceRequestPriorities)
-      .SetMethod("setUseMockTheme", &TestRunnerBindings::SetUseMockTheme)
-      .SetMethod("waitUntilExternalURLLoad",
-                 &TestRunnerBindings::WaitUntilExternalURLLoad)
-      .SetMethod("dumpDragImage", &TestRunnerBindings::DumpDragImage)
-      .SetMethod("dumpNavigationPolicy",
-                 &TestRunnerBindings::DumpNavigationPolicy)
-      .SetMethod("dumpPageImportanceSignals",
-                 &TestRunnerBindings::DumpPageImportanceSignals)
-      .SetMethod("showWebInspector", &TestRunnerBindings::ShowWebInspector)
-      .SetMethod("closeWebInspector", &TestRunnerBindings::CloseWebInspector)
-      .SetMethod("isChooserShown", &TestRunnerBindings::IsChooserShown)
-      .SetMethod("evaluateInWebInspector",
-                 &TestRunnerBindings::EvaluateInWebInspector)
-      .SetMethod("evaluateInWebInspectorOverlay",
-                 &TestRunnerBindings::EvaluateInWebInspectorOverlay)
-      .SetMethod("clearAllDatabases", &TestRunnerBindings::ClearAllDatabases)
-      .SetMethod("setDatabaseQuota", &TestRunnerBindings::SetDatabaseQuota)
-      .SetMethod("setAlwaysAcceptCookies",
-                 &TestRunnerBindings::SetAlwaysAcceptCookies)
       .SetMethod("setWindowIsKey", &TestRunnerBindings::SetWindowIsKey)
-      .SetMethod("pathToLocalResource",
-                 &TestRunnerBindings::PathToLocalResource)
-      .SetMethod("setBackingScaleFactor",
-                 &TestRunnerBindings::SetBackingScaleFactor)
-      .SetMethod("enableUseZoomForDSF",
-                 &TestRunnerBindings::EnableUseZoomForDSF)
-      .SetMethod("setColorProfile", &TestRunnerBindings::SetColorProfile)
-      .SetMethod("setPOSIXLocale", &TestRunnerBindings::SetPOSIXLocale)
-      .SetMethod("setMIDIAccessorResult",
-                 &TestRunnerBindings::SetMIDIAccessorResult)
+      .SetMethod("setXSSAuditorEnabled",
+                 &TestRunnerBindings::SetXSSAuditorEnabled)
+      .SetMethod("showWebInspector", &TestRunnerBindings::ShowWebInspector)
       .SetMethod("simulateWebNotificationClick",
                  &TestRunnerBindings::SimulateWebNotificationClick)
       .SetMethod("simulateWebNotificationClose",
                  &TestRunnerBindings::SimulateWebNotificationClose)
-      .SetMethod("addMockSpeechRecognitionResult",
-                 &TestRunnerBindings::AddMockSpeechRecognitionResult)
-      .SetMethod("setMockSpeechRecognitionError",
-                 &TestRunnerBindings::SetMockSpeechRecognitionError)
+      .SetMethod("syncLocalStorage", &TestRunnerBindings::NotImplemented)
+      .SetProperty("tooltipText", &TestRunnerBindings::TooltipText)
+      .SetMethod("useUnfortunateSynchronousResizeMode",
+                 &TestRunnerBindings::UseUnfortunateSynchronousResizeMode)
+      .SetMethod("waitForPolicyDelegate",
+                 &TestRunnerBindings::WaitForPolicyDelegate)
+      .SetMethod("waitUntilDone", &TestRunnerBindings::WaitUntilDone)
+      .SetMethod("waitUntilExternalURLLoad",
+                 &TestRunnerBindings::WaitUntilExternalURLLoad)
       .SetMethod("wasMockSpeechRecognitionAborted",
                  &TestRunnerBindings::WasMockSpeechRecognitionAborted)
-      .SetMethod("addMockCredentialManagerResponse",
-                 &TestRunnerBindings::AddMockCredentialManagerResponse)
-      .SetMethod("addMockCredentialManagerError",
-                 &TestRunnerBindings::AddMockCredentialManagerError)
-      .SetMethod("addWebPageOverlay", &TestRunnerBindings::AddWebPageOverlay)
-      .SetMethod("removeWebPageOverlay",
-                 &TestRunnerBindings::RemoveWebPageOverlay)
-      .SetMethod("layoutAndPaintAsync",
-                 &TestRunnerBindings::LayoutAndPaintAsync)
-      .SetMethod("layoutAndPaintAsyncThen",
-                 &TestRunnerBindings::LayoutAndPaintAsyncThen)
-      .SetMethod("getManifestThen", &TestRunnerBindings::GetManifestThen)
-      .SetMethod("capturePixelsAsyncThen",
-                 &TestRunnerBindings::CapturePixelsAsyncThen)
-      .SetMethod("copyImageAtAndCapturePixelsAsyncThen",
-                 &TestRunnerBindings::CopyImageAtAndCapturePixelsAsyncThen)
-      .SetMethod("setCustomTextOutput",
-                 &TestRunnerBindings::SetCustomTextOutput)
-      .SetMethod("setViewSourceForFrame",
-                 &TestRunnerBindings::SetViewSourceForFrame)
-      // The 4 Bluetooth functions are specified at
-      // https://webbluetoothcg.github.io/web-bluetooth/tests/.
-      .SetMethod("setBluetoothMockDataSet",
-                 &TestRunnerBindings::SetBluetoothMockDataSet)
-      .SetMethod("setBluetoothManualChooser",
-                 &TestRunnerBindings::SetBluetoothManualChooser)
-      .SetMethod("getBluetoothManualChooserEvents",
-                 &TestRunnerBindings::GetBluetoothManualChooserEvents)
-      .SetMethod("sendBluetoothManualChooserEvent",
-                 &TestRunnerBindings::SendBluetoothManualChooserEvent)
-      .SetMethod("forceNextWebGLContextCreationToFail",
-                 &TestRunnerBindings::ForceNextWebGLContextCreationToFail)
-      .SetMethod("forceNextDrawingBufferCreationToFail",
-                 &TestRunnerBindings::ForceNextDrawingBufferCreationToFail)
-      .SetMethod("setGeofencingMockProvider",
-                 &TestRunnerBindings::SetGeofencingMockProvider)
-      .SetMethod("clearGeofencingMockProvider",
-                 &TestRunnerBindings::ClearGeofencingMockProvider)
-      .SetMethod("setGeofencingMockPosition",
-                 &TestRunnerBindings::SetGeofencingMockPosition)
-      .SetMethod("setPermission", &TestRunnerBindings::SetPermission)
-      .SetMethod("dispatchBeforeInstallPromptEvent",
-                 &TestRunnerBindings::DispatchBeforeInstallPromptEvent)
-      .SetMethod("resolveBeforeInstallPromptPromise",
-                 &TestRunnerBindings::ResolveBeforeInstallPromptPromise)
 
-      // Properties.
-      .SetProperty("platformName", &TestRunnerBindings::PlatformName)
-      .SetProperty("tooltipText", &TestRunnerBindings::TooltipText)
       // webHistoryItemCount is used by tests in LayoutTests\http\tests\history
       .SetProperty("webHistoryItemCount",
                    &TestRunnerBindings::WebHistoryItemCount)
-      .SetProperty("interceptPostMessage",
-                   &TestRunnerBindings::InterceptPostMessage,
-                   &TestRunnerBindings::SetInterceptPostMessage)
-
-      // The following are stubs.
-      .SetMethod("dumpDatabaseCallbacks", &TestRunnerBindings::NotImplemented)
-      .SetMethod("setIconDatabaseEnabled", &TestRunnerBindings::NotImplemented)
-      .SetMethod("setScrollbarPolicy", &TestRunnerBindings::NotImplemented)
-      .SetMethod("clearAllApplicationCaches",
-                 &TestRunnerBindings::NotImplemented)
-      .SetMethod("clearApplicationCacheForOrigin",
-                 &TestRunnerBindings::NotImplemented)
-      .SetMethod("clearBackForwardList", &TestRunnerBindings::NotImplemented)
-      .SetMethod("keepWebHistory", &TestRunnerBindings::NotImplemented)
-      .SetMethod("setApplicationCacheOriginQuota",
-                 &TestRunnerBindings::NotImplemented)
-      .SetMethod("setCallCloseOnWebViews", &TestRunnerBindings::NotImplemented)
-      .SetMethod("setMainFrameIsFirstResponder",
-                 &TestRunnerBindings::NotImplemented)
-      .SetMethod("setUseDashboardCompatibilityMode",
-                 &TestRunnerBindings::NotImplemented)
-      .SetMethod("deleteAllLocalStorage", &TestRunnerBindings::NotImplemented)
-      .SetMethod("localStorageDiskUsageForOrigin",
-                 &TestRunnerBindings::NotImplemented)
-      .SetMethod("originsWithLocalStorage", &TestRunnerBindings::NotImplemented)
-      .SetMethod("deleteLocalStorageForOrigin",
-                 &TestRunnerBindings::NotImplemented)
-      .SetMethod("observeStorageTrackerNotifications",
-                 &TestRunnerBindings::NotImplemented)
-      .SetMethod("syncLocalStorage", &TestRunnerBindings::NotImplemented)
-      .SetMethod("addDisallowedURL", &TestRunnerBindings::NotImplemented)
-      .SetMethod("applicationCacheDiskUsageForOrigin",
-                 &TestRunnerBindings::NotImplemented)
-      .SetMethod("abortModal", &TestRunnerBindings::NotImplemented)
-
-      // Aliases.
-      // Used at fast/dom/assign-to-window-status.html
-      .SetMethod("dumpStatusCallbacks",
-                 &TestRunnerBindings::DumpWindowStatusChanges);
+      .SetMethod("windowCount", &TestRunnerBindings::WindowCount);
 }
 
 void TestRunnerBindings::LogToStderr(const std::string& output) {
diff --git a/components/user_manager/user_manager_base.cc b/components/user_manager/user_manager_base.cc
index c45efef..f6f5cf80 100644
--- a/components/user_manager/user_manager_base.cc
+++ b/components/user_manager/user_manager_base.cc
@@ -256,10 +256,7 @@
   session_manager::SessionManager::Get()->SetSessionState(
       session_manager::SESSION_STATE_ACTIVE);
 
-  if (IsCurrentUserNew()) {
-    // Make sure that the new user's data is persisted to Local State.
-    GetLocalState()->CommitPendingWrite();
-  }
+  GetLocalState()->CommitPendingWrite();
 }
 
 void UserManagerBase::RemoveUser(const AccountId& account_id,
@@ -368,11 +365,14 @@
   if (IsUserNonCryptohomeDataEphemeral(account_id))
     return;
 
-  DictionaryPrefUpdate oauth_status_update(GetLocalState(),
-                                           kUserOAuthTokenStatus);
-  oauth_status_update->SetWithoutPathExpansion(
-      account_id.GetUserEmail(),
-      new base::FundamentalValue(static_cast<int>(oauth_token_status)));
+  {
+    DictionaryPrefUpdate oauth_status_update(GetLocalState(),
+                                             kUserOAuthTokenStatus);
+    oauth_status_update->SetWithoutPathExpansion(
+        account_id.GetUserEmail(),
+        new base::FundamentalValue(static_cast<int>(oauth_token_status)));
+  }
+  GetLocalState()->CommitPendingWrite();
 }
 
 void UserManagerBase::SaveForceOnlineSignin(const AccountId& account_id,
@@ -384,10 +384,13 @@
   if (IsUserNonCryptohomeDataEphemeral(account_id))
     return;
 
-  DictionaryPrefUpdate force_online_update(GetLocalState(),
-                                           kUserForceOnlineSignin);
-  force_online_update->SetBooleanWithoutPathExpansion(account_id.GetUserEmail(),
-                                                      force_online_signin);
+  {
+    DictionaryPrefUpdate force_online_update(GetLocalState(),
+                                             kUserForceOnlineSignin);
+    force_online_update->SetBooleanWithoutPathExpansion(
+        account_id.GetUserEmail(), force_online_signin);
+  }
+  GetLocalState()->CommitPendingWrite();
 }
 
 void UserManagerBase::SaveUserDisplayName(const AccountId& account_id,
diff --git a/content/DEPS b/content/DEPS
index b7cda859..b0e052b 100644
--- a/content/DEPS
+++ b/content/DEPS
@@ -10,7 +10,6 @@
   "+content/grit",
   "+content/public/common",
   "+content/public/test",
-  "+content/shell",  # for content_browsertests
   "+content/test",
 
   "+blink",
@@ -112,3 +111,12 @@
   # For generated JNI includes.
   "+jni",
 ]
+
+# content -> content/shell dependency is not allowed, except for browser tests.
+specific_include_rules = {
+  ".*_browsertest[a-z_]*\.cc": [
+    "+content/shell/browser",
+    "+content/shell/common",
+  ],
+}
+
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 48ba0e1..9245309 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -49,7 +49,6 @@
     "//content/browser/service_worker:service_worker_proto",
     "//content/browser/speech/proto",
     "//content/common:mojo_bindings",
-    "//content/gpu:gpu_sources",
     "//content/public/common:common_sources",
     "//content/public/common:mojo_bindings",
     "//crypto",
@@ -233,6 +232,7 @@
       "dinput8.lib",
       "dwmapi.lib",
       "dxguid.lib",
+      "imm32.lib",
       "oleacc.lib",
       "sensorsapi.lib",
       "portabledeviceguids.lib",
diff --git a/content/browser/DEPS b/content/browser/DEPS
index cac7295..e681ca7 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -12,7 +12,6 @@
   "+components/url_formatter",
 
   "+content/app/strings/grit",  # For generated headers
-  "+content/gpu",
   "+content/public/browser",
   "+device/battery",  # For battery status service.
   "+device/vibration",  # For Vibration API
diff --git a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
index 4dba524b..6d9e64a 100644
--- a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
+++ b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
@@ -104,11 +104,12 @@
 scoped_ptr<cc::OutputSurface>
 SynchronousCompositorFactoryImpl::CreateOutputSurface(
     int routing_id,
+    uint32_t output_surface_id,
     const scoped_refptr<FrameSwapMessageQueue>& frame_swap_message_queue,
     const scoped_refptr<cc::ContextProvider>& onscreen_context,
     const scoped_refptr<cc::ContextProvider>& worker_context) {
   return make_scoped_ptr(new SynchronousCompositorOutputSurface(
-      onscreen_context, worker_context, routing_id,
+      onscreen_context, worker_context, routing_id, output_surface_id,
       SynchronousCompositorRegistryInProc::GetInstance(),
       frame_swap_message_queue));
 }
diff --git a/content/browser/android/in_process/synchronous_compositor_factory_impl.h b/content/browser/android/in_process/synchronous_compositor_factory_impl.h
index 79b2625..4842e85 100644
--- a/content/browser/android/in_process/synchronous_compositor_factory_impl.h
+++ b/content/browser/android/in_process/synchronous_compositor_factory_impl.h
@@ -41,6 +41,7 @@
       override;
   scoped_ptr<cc::OutputSurface> CreateOutputSurface(
       int routing_id,
+      uint32_t output_surface_id,
       const scoped_refptr<FrameSwapMessageQueue>& frame_swap_message_queue,
       const scoped_refptr<cc::ContextProvider>& onscreen_context,
       const scoped_refptr<cc::ContextProvider>& worker_context) override;
diff --git a/content/browser/android/in_process/synchronous_compositor_impl.cc b/content/browser/android/in_process/synchronous_compositor_impl.cc
index ed99e093..1b06e510 100644
--- a/content/browser/android/in_process/synchronous_compositor_impl.cc
+++ b/content/browser/android/in_process/synchronous_compositor_impl.cc
@@ -150,7 +150,7 @@
   need_animate_input_ = false;
 }
 
-scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw(
+SynchronousCompositor::Frame SynchronousCompositorImpl::DemandDrawHw(
     const gfx::Size& surface_size,
     const gfx::Transform& transform,
     const gfx::Rect& viewport,
@@ -160,45 +160,48 @@
   DCHECK(CalledOnValidThread());
   DCHECK(output_surface_);
   DCHECK(begin_frame_source_);
-  DCHECK(!frame_holder_);
+  DCHECK(!frame_holder_.frame);
 
   output_surface_->DemandDrawHw(surface_size, transform, viewport, clip,
                                 viewport_rect_for_tile_priority,
                                 transform_for_tile_priority);
 
-  if (frame_holder_)
-    UpdateFrameMetaData(frame_holder_->metadata);
+  if (frame_holder_.frame)
+    UpdateFrameMetaData(frame_holder_.frame->metadata);
 
   return std::move(frame_holder_);
 }
 
 void SynchronousCompositorImpl::ReturnResources(
+    uint32_t output_surface_id,
     const cc::CompositorFrameAck& frame_ack) {
   DCHECK(CalledOnValidThread());
-  output_surface_->ReturnResources(frame_ack);
+  output_surface_->ReturnResources(output_surface_id, frame_ack);
 }
 
 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
   DCHECK(CalledOnValidThread());
   DCHECK(output_surface_);
   DCHECK(begin_frame_source_);
-  DCHECK(!frame_holder_);
+  DCHECK(!frame_holder_.frame);
 
   output_surface_->DemandDrawSw(canvas);
 
-  bool success = !!frame_holder_;
-  if (frame_holder_) {
-    UpdateFrameMetaData(frame_holder_->metadata);
-    frame_holder_.reset();
+  bool success = !!frame_holder_.frame;
+  if (frame_holder_.frame) {
+    UpdateFrameMetaData(frame_holder_.frame->metadata);
+    frame_holder_.frame.reset();
   }
 
   return success;
 }
 
-void SynchronousCompositorImpl::SwapBuffers(cc::CompositorFrame* frame) {
-  DCHECK(!frame_holder_);
-  frame_holder_.reset(new cc::CompositorFrame);
-  frame->AssignTo(frame_holder_.get());
+void SynchronousCompositorImpl::SwapBuffers(uint32_t output_surface_id,
+                                            cc::CompositorFrame* frame) {
+  DCHECK(!frame_holder_.frame);
+  frame_holder_.output_surface_id = output_surface_id;
+  frame_holder_.frame.reset(new cc::CompositorFrame);
+  frame->AssignTo(frame_holder_.frame.get());
 }
 
 void SynchronousCompositorImpl::UpdateFrameMetaData(
diff --git a/content/browser/android/in_process/synchronous_compositor_impl.h b/content/browser/android/in_process/synchronous_compositor_impl.h
index 2c7e5b5..4f3155a 100644
--- a/content/browser/android/in_process/synchronous_compositor_impl.h
+++ b/content/browser/android/in_process/synchronous_compositor_impl.h
@@ -57,10 +57,11 @@
 
   // SynchronousCompositorOutputSurfaceClient overrides.
   void Invalidate() override;
-  void SwapBuffers(cc::CompositorFrame* frame) override;
+  void SwapBuffers(uint32_t output_surface_id,
+                   cc::CompositorFrame* frame) override;
 
   // SynchronousCompositor overrides.
-  scoped_ptr<cc::CompositorFrame> DemandDrawHw(
+  SynchronousCompositor::Frame DemandDrawHw(
       const gfx::Size& surface_size,
       const gfx::Transform& transform,
       const gfx::Rect& viewport,
@@ -68,7 +69,8 @@
       const gfx::Rect& viewport_rect_for_tile_priority,
       const gfx::Transform& transform_for_tile_priority) override;
   bool DemandDrawSw(SkCanvas* canvas) override;
-  void ReturnResources(const cc::CompositorFrameAck& frame_ack) override;
+  void ReturnResources(uint32_t output_surface_id,
+                       const cc::CompositorFrameAck& frame_ack) override;
   void SetMemoryPolicy(size_t bytes_limit) override;
   void DidChangeRootLayerScrollOffset(
       const gfx::ScrollOffset& root_offset) override;
@@ -116,7 +118,7 @@
   bool is_active_;
   bool renderer_needs_begin_frames_;
   bool need_animate_input_;
-  scoped_ptr<cc::CompositorFrame> frame_holder_;
+  SynchronousCompositor::Frame frame_holder_;
 
   base::WeakPtrFactory<SynchronousCompositorImpl> weak_ptr_factory_;
 
diff --git a/content/browser/android/synchronous_compositor_host.cc b/content/browser/android/synchronous_compositor_host.cc
index 6cb4907..2d937c5 100644
--- a/content/browser/android/synchronous_compositor_host.cc
+++ b/content/browser/android/synchronous_compositor_host.cc
@@ -42,6 +42,7 @@
       use_in_process_zero_copy_software_draw_(use_in_proc_software_draw),
       is_active_(false),
       bytes_limit_(0u),
+      output_surface_id_from_last_draw_(0u),
       root_scroll_offset_updated_by_browser_(false),
       renderer_param_version_(0u),
       need_animate_scroll_(false),
@@ -72,7 +73,7 @@
   client_->DidBecomeCurrent(this);
 }
 
-scoped_ptr<cc::CompositorFrame> SynchronousCompositorHost::DemandDrawHw(
+SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw(
     const gfx::Size& surface_size,
     const gfx::Transform& transform,
     const gfx::Rect& viewport,
@@ -82,22 +83,27 @@
   SyncCompositorDemandDrawHwParams params(surface_size, transform, viewport,
                                           clip, viewport_rect_for_tile_priority,
                                           transform_for_tile_priority);
-  scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
+  SynchronousCompositor::Frame frame;
+  frame.frame.reset(new cc::CompositorFrame);
   SyncCompositorCommonBrowserParams common_browser_params;
   PopulateCommonParams(&common_browser_params);
   SyncCompositorCommonRendererParams common_renderer_params;
   if (!sender_->Send(new SyncCompositorMsg_DemandDrawHw(
           routing_id_, common_browser_params, params, &common_renderer_params,
-          frame.get()))) {
-    return nullptr;
+          &frame.output_surface_id, frame.frame.get()))) {
+    return SynchronousCompositor::Frame();
   }
   ProcessCommonParams(common_renderer_params);
-  if (!frame->delegated_frame_data) {
+  if (!frame.frame->delegated_frame_data) {
     // This can happen if compositor did not swap in this draw.
-    frame.reset();
+    frame.frame.reset();
   }
-  if (frame)
-    UpdateFrameMetaData(frame->metadata);
+  if (frame.frame) {
+    UpdateFrameMetaData(frame.frame->metadata);
+    if (output_surface_id_from_last_draw_ != frame.output_surface_id)
+      returned_resources_.clear();
+    output_surface_id_from_last_draw_ = frame.output_surface_id;
+  }
   return frame;
 }
 
@@ -269,7 +275,13 @@
 }
 
 void SynchronousCompositorHost::ReturnResources(
+    uint32_t output_surface_id,
     const cc::CompositorFrameAck& frame_ack) {
+  // If output_surface_id does not match, then renderer side has switched
+  // to a new OutputSurface, so dropping resources for old OutputSurface
+  // is allowed.
+  if (output_surface_id_from_last_draw_ != output_surface_id)
+    return;
   returned_resources_.insert(returned_resources_.end(),
                              frame_ack.resources.begin(),
                              frame_ack.resources.end());
@@ -389,6 +401,8 @@
   DCHECK(params);
   DCHECK(params->ack.resources.empty());
   params->bytes_limit = bytes_limit_;
+  params->output_surface_id_for_returned_resources =
+      output_surface_id_from_last_draw_;
   params->ack.resources.swap(returned_resources_);
   if (root_scroll_offset_updated_by_browser_) {
     params->root_scroll_offset = root_scroll_offset_;
diff --git a/content/browser/android/synchronous_compositor_host.h b/content/browser/android/synchronous_compositor_host.h
index 90aafe5..6c0001b 100644
--- a/content/browser/android/synchronous_compositor_host.h
+++ b/content/browser/android/synchronous_compositor_host.h
@@ -33,7 +33,7 @@
   ~SynchronousCompositorHost() override;
 
   // SynchronousCompositor overrides.
-  scoped_ptr<cc::CompositorFrame> DemandDrawHw(
+  SynchronousCompositor::Frame DemandDrawHw(
       const gfx::Size& surface_size,
       const gfx::Transform& transform,
       const gfx::Rect& viewport,
@@ -41,7 +41,8 @@
       const gfx::Rect& viewport_rect_for_tile_priority,
       const gfx::Transform& transform_for_tile_priority) override;
   bool DemandDrawSw(SkCanvas* canvas) override;
-  void ReturnResources(const cc::CompositorFrameAck& frame_ack) override;
+  void ReturnResources(uint32_t output_surface_id,
+                       const cc::CompositorFrameAck& frame_ack) override;
   void SetMemoryPolicy(size_t bytes_limit) override;
   void DidChangeRootLayerScrollOffset(
       const gfx::ScrollOffset& root_offset) override;
@@ -88,6 +89,7 @@
 
   bool is_active_;
   size_t bytes_limit_;
+  uint32_t output_surface_id_from_last_draw_;
   cc::ReturnedResourceArray returned_resources_;
   scoped_ptr<SharedMemoryWithSize> software_draw_shm_;
 
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index 7d4769ac..01dcecd 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -42,7 +42,7 @@
 #include "content/common/gpu/client/context_provider_command_buffer.h"
 #include "content/common/gpu/client/gpu_channel_host.h"
 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
 #include "content/common/host_shared_bitmap_manager.h"
 #include "content/public/common/content_switches.h"
 #include "gpu/GLES2/gl2extchromium.h"
diff --git a/content/browser/dom_storage/dom_storage_context_wrapper.cc b/content/browser/dom_storage/dom_storage_context_wrapper.cc
index cfacb08..eea4dc5 100644
--- a/content/browser/dom_storage/dom_storage_context_wrapper.cc
+++ b/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -128,26 +128,30 @@
 void DOMStorageContextWrapper::MojoState::OpenLocalStorage(
     const url::Origin& origin,
     LevelDBWrapperRequest request) {
-  // If we don't have a specific subdirectory where we want to put our data
-  // (ie, we're in incognito mode), just bind the storage with a null leveldb_
-  // database.
-  if (subdirectory_.empty()) {
-    BindLocalStorage(origin, std::move(request));
-    return;
-  }
-
   // If we don't have a filesystem_connection_, we'll need to establish one.
   if (connection_state_ == NO_CONNECTION) {
     profile_app_connection_ = MojoAppConnection::Create(
         mojo_user_id_, "mojo:profile", kBrowserMojoAppUrl);
-    profile_app_connection_->GetInterface(&profile_service_);
 
-    profile_service_->GetSubDirectory(
-        mojo::String::From(subdirectory_.AsUTF8Unsafe()),
-        GetProxy(&directory_),
-        base::Bind(&MojoState::OnDirectoryOpened,
-                   weak_ptr_factory_.GetWeakPtr()));
     connection_state_ = CONNECTION_IN_PROGRESS;
+
+    if (!subdirectory_.empty()) {
+      // We were given a subdirectory to write to. Get it and use a disk backed
+      // database.
+      profile_app_connection_->GetInterface(&profile_service_);
+      profile_service_->GetSubDirectory(
+          mojo::String::From(subdirectory_.AsUTF8Unsafe()),
+          GetProxy(&directory_),
+          base::Bind(&MojoState::OnDirectoryOpened,
+                     weak_ptr_factory_.GetWeakPtr()));
+    } else {
+      // We were not given a subdirectory. Use a memory backed database.
+      profile_app_connection_->GetInterface(&leveldb_service_);
+      leveldb_service_->OpenInMemory(
+          GetProxy(&database_),
+          base::Bind(&MojoState::OnDatabaseOpened,
+                     weak_ptr_factory_.GetWeakPtr()));
+    }
   }
 
   if (connection_state_ == CONNECTION_IN_PROGRESS) {
diff --git a/content/browser/download/docs/save-page-as.md b/content/browser/download/docs/save-page-as.md
new file mode 100644
index 0000000..2661289
--- /dev/null
+++ b/content/browser/download/docs/save-page-as.md
@@ -0,0 +1,137 @@
+# High-level overview of Save-Page-As code
+
+This document describes code under `//content/browser/downloads`
+restricting the scope only to code handling Save-Page-As functionality
+(i.e. leaving out other downloads-related code).
+This document focuses on high-level overview and aspects of the code that
+span multiple compilation units (hoping that individual compilation units
+are described by their code comments or by their code structure).
+
+## Classes overview
+
+* SavePackage class
+    * coordinates overall save-page-as request
+    * created and owned by `WebContents`
+      (ref-counted today, but it is unnecessary - see https://crbug.com/596953)
+    * UI-thread object
+
+* SaveFileCreateInfo::SaveFileSource enum
+    * classifies `SaveItem` and `SaveFile` processing into 3 flavours:
+        * `SAVE_FILE_FROM_NET` (see `SaveFileResourceHandler`)
+        * `SAVE_FILE_FROM_DOM` (see "Complete HTML" section below)
+        * `SAVE_FILE_FROM_FILE` (see `SaveFileManager::SaveLocalFile`)
+
+* SaveItem class
+    * tracks saving a single file
+    * created and owned by `SavePackage`
+    * UI-thread object
+
+* SaveFileManager class
+    * coordinates between FILE and UI threads
+        * Gets requests from `SavePackage` and communicates results back to
+          `SavePackage` on the UI thread.
+        * Shephards data (received from the network OR from DOM) into
+          FILE thread - via `SaveFileManager::UpdateSaveProgress`
+    * created and owned by `ResourceDispatchedHostImpl`
+      (ref-counted today, but it is unnecessary - see https://crbug.com/596953)
+
+* SaveFile class
+    * tracks saving a single file
+    * created and owned by `SaveFileManager`
+    * FILE-thread object
+
+* SaveFileResourceHandler class
+    * tracks network downloads + forwards their status into `SaveFileManager`
+      (onto FILE-thread)
+    * created by `ResourceDispatcherHostImpl::BeginSaveFile`
+    * IO-thread object
+
+* SaveFileCreateInfo POD struct
+    * short-lived object holding data passed to callbacks handling start of
+      saving a file.
+
+* MHTMLGenerationManager class
+    * singleton that manages progress of jobs responsible for saving individual
+      MHTML files (represented by `MHTMLGenerationManager::Job`).
+
+
+## Overview of the processing flow
+
+Save-Page-As flow starts with `WebContents::OnSavePage`.
+The flow is different depending on the save format chosen by the user
+(each flow is described in a separate section below).
+
+### Complete HTML
+
+Very high-level flow of saving a page as "Complete HTML":
+
+* Step 1: `SavePackage` asks all frames for "savable resources"
+          and creates `SaveItem` for each of files that need to be saved
+
+* Step 2: `SavePackage` first processes `SAVE_FILE_FROM_NET` and
+          `SAVE_FILE_FROM_FILE` `SaveItem`s and asks `SaveFileManager` to save
+          them.
+
+* Step 3: `SavePackage` handles remaining `SAVE_FILE_FROM_DOM` `SaveItem`s and
+          asks each frame to serialize its DOM/HTML (each frame gets from
+          `SavePackage` a map covering local paths that need to be referenced by
+          the frame).  Responses from frames get forwarded to `SaveFileManager`
+          to be written to disk.
+
+
+### MHTML
+
+Very high-level flow of saving a page as MHTML:
+
+* Step 1: `WebContents::GenerateMHTML` is called by either `SavePackage` (for
+          Save-Page-As UI) or Extensions (via `chrome.pageCapture` extensions
+          API) or by an embedder of `WebContents` (since this is public API of
+          //content).
+
+* Step 2: `MHTMLGenerationManager` coordinates generation of the MHTML file
+          by sequentially (one-at-a-time) asking each frame to write its portion
+          of MHTML to a file handle.  Other classes (i.e. `SavePackage` and/or
+          `SaveFileManager`) are not used at this step at all.
+
+* Step 3: When done `MHTMLGenerationManager` calls a completion callback
+          which in case of Save-Page-As will end up in
+          `SavePackage::OnMHTMLGenerated`.
+
+Note: MHTML format is by default disabled in Save-Page-As UI on Windows, MacOS
+and Linux (it is the default on ChromeOS), but for testing this can be easily
+changed using `--save-page-as-mhtml` command line switch.
+
+
+### HTML Only
+
+Very high-level flow of saving a page as "HTML Only":
+
+* `SavePackage` creates only a single `SaveItem` (either `SAVE_FILE_FROM_NET` or
+  `SAVE_FILE_FROM_FILE`) and asks `SaveFileManager` to process it
+  (as in the Complete HTML individual SaveItem handling above.).
+
+
+## Other relevant code
+
+Pointers to related code outside of `//content/browser/download`:
+
+* End-to-end tests:
+    * `//chrome/browser/downloads/save_page_browsertest.cc`
+    * `//chrome/test/data/save_page/...`
+
+* Other tests:
+    * `//content/browser/downloads/*test*.cc`
+    * `//content/renderer/dom_serializer_browsertest.cc` - single process... :-/
+
+* Elsewhere in `//content`:
+    * `//content/renderer/savable_resources...`
+
+* Blink:
+    * `//third_party/WebKit/public/web/WebFrameSerializer...`
+    * `//third_party/WebKit/Source/web/WebFrameSerializerImpl...`
+      (used for Complete HTML today;  should use `FrameSerializer` instead in
+      the long-term - see https://crbug.com/328354).
+    * `//third_party/WebKit/Source/core/frame/FrameSerializer...`
+      (used for MHTML today)
+    * `//third_party/WebKit/Source/platform/mhtml/MHTMLArchive...`
+
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 23f86aba..01547b08 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -1849,6 +1849,24 @@
     }
   }
 
+  // TODO(alexmos): These CHECKs are temporary to track down
+  // https://crbug.com/591478. Verify that the parent routing ID
+  // points to a live RenderFrameProxy when this is not a remote-to-local
+  // navigation (i.e., when there's no |existing_proxy|).
+  if (!existing_proxy && frame_tree_node_->parent()) {
+    RenderFrameProxyHost* parent_proxy = RenderFrameProxyHost::FromID(
+        render_frame_host->GetProcess()->GetID(), parent_routing_id);
+    if (!parent_proxy || !parent_proxy->is_render_frame_proxy_live()) {
+      base::debug::SetCrashKeyValue("initrf_parent_proxy_exists",
+                                    parent_proxy ? "yes" : "no");
+      base::debug::SetCrashKeyValue(
+          "initrf_render_view_is_live",
+          render_frame_host->render_view_host()->IsRenderViewLive() ? "yes"
+                                                                    : "no");
+      base::debug::DumpWithoutCrashing();
+    }
+  }
+
   return delegate_->CreateRenderFrameForRenderManager(
       render_frame_host, proxy_routing_id, opener_routing_id, parent_routing_id,
       previous_sibling_routing_id);
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc
index 027f5e4..602be87 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -538,11 +538,6 @@
 void RenderWidgetHostViewChildFrame::SetParentNativeViewAccessible(
     gfx::NativeViewAccessible accessible_parent) {
 }
-
-gfx::NativeViewId RenderWidgetHostViewChildFrame::GetParentForWindowlessPlugin()
-    const {
-  return NULL;
-}
 #endif  // defined(OS_WIN)
 
 // cc::SurfaceFactoryClient implementation.
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.h b/content/browser/frame_host/render_widget_host_view_child_frame.h
index 4336e107..507fce5 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame.h
+++ b/content/browser/frame_host/render_widget_host_view_child_frame.h
@@ -167,7 +167,6 @@
 #if defined(OS_WIN)
   void SetParentNativeViewAccessible(
       gfx::NativeViewAccessible accessible_parent) override;
-  gfx::NativeViewId GetParentForWindowlessPlugin() const override;
 #endif
   BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
       BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
diff --git a/content/browser/frame_host/render_widget_host_view_guest.cc b/content/browser/frame_host/render_widget_host_view_guest.cc
index 10c8313..e9516eba 100644
--- a/content/browser/frame_host/render_widget_host_view_guest.cc
+++ b/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -515,11 +515,6 @@
 void RenderWidgetHostViewGuest::SetParentNativeViewAccessible(
     gfx::NativeViewAccessible accessible_parent) {
 }
-
-gfx::NativeViewId RenderWidgetHostViewGuest::GetParentForWindowlessPlugin()
-    const {
-  return NULL;
-}
 #endif
 
 void RenderWidgetHostViewGuest::DestroyGuestView() {
diff --git a/content/browser/frame_host/render_widget_host_view_guest.h b/content/browser/frame_host/render_widget_host_view_guest.h
index c46b6ef..52f1f8b 100644
--- a/content/browser/frame_host/render_widget_host_view_guest.h
+++ b/content/browser/frame_host/render_widget_host_view_guest.h
@@ -137,7 +137,6 @@
 #if defined(OS_WIN)
   void SetParentNativeViewAccessible(
       gfx::NativeViewAccessible accessible_parent) override;
-  gfx::NativeViewId GetParentForWindowlessPlugin() const override;
 #endif
 
   void WheelEventAck(const blink::WebMouseWheelEvent& event,
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h
index e8919d2..e88696d 100644
--- a/content/browser/gpu/browser_gpu_channel_host_factory.h
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.h
@@ -16,6 +16,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "build/build_config.h"
 #include "content/common/gpu/client/gpu_channel_host.h"
+#include "content/common/gpu_process_launch_causes.h"
 #include "ipc/message_filter.h"
 
 namespace content {
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc
index 5a63868..fd3b225 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -19,7 +19,7 @@
 #include "build/build_config.h"
 #include "cc/base/switches.h"
 #include "content/browser/gpu/gpu_process_host.h"
-#include "content/gpu/gpu_host_messages.h"
+#include "content/common/gpu_host_messages.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/gpu_data_manager_observer.h"
 #include "content/public/common/content_client.h"
diff --git a/content/browser/gpu/gpu_ipc_browsertests.cc b/content/browser/gpu/gpu_ipc_browsertests.cc
index d825668..4b1ca91 100644
--- a/content/browser/gpu/gpu_ipc_browsertests.cc
+++ b/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -9,7 +9,7 @@
 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
 #include "content/common/gpu/client/context_provider_command_buffer.h"
 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
 #include "content/public/browser/gpu_data_manager.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/content_browser_test.h"
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index e4ba59f5..6b7a2047 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -31,10 +31,10 @@
 #include "content/browser/mojo/mojo_application_host.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/common/child_process_host_impl.h"
+#include "content/common/establish_channel_params.h"
+#include "content/common/gpu_host_messages.h"
 #include "content/common/in_process_child_thread_params.h"
 #include "content/common/view_messages.h"
-#include "content/gpu/establish_channel_params.h"
-#include "content/gpu/gpu_host_messages.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/gpu_utils.h"
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h
index 04dc52c..e3e6ccb 100644
--- a/content/browser/gpu/gpu_process_host.h
+++ b/content/browser/gpu/gpu_process_host.h
@@ -21,7 +21,7 @@
 #include "build/build_config.h"
 #include "content/common/content_export.h"
 #include "content/common/gpu/gpu_memory_uma_stats.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
 #include "content/public/browser/browser_child_process_host_delegate.h"
 #include "content/public/browser/gpu_data_manager.h"
 #include "gpu/command_buffer/common/constants.h"
diff --git a/content/browser/gpu/gpu_process_host_ui_shim.cc b/content/browser/gpu/gpu_process_host_ui_shim.cc
index e3b2732..95f07244 100644
--- a/content/browser/gpu/gpu_process_host_ui_shim.cc
+++ b/content/browser/gpu/gpu_process_host_ui_shim.cc
@@ -22,7 +22,7 @@
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/renderer_host/render_widget_helper.h"
 #include "content/browser/renderer_host/render_widget_host_view_base.h"
-#include "content/gpu/gpu_host_messages.h"
+#include "content/common/gpu_host_messages.h"
 #include "content/public/browser/browser_thread.h"
 #include "gpu/ipc/common/memory_stats.h"
 #include "ui/gfx/swap_result.h"
diff --git a/content/browser/mojo/mojo_shell_context.cc b/content/browser/mojo/mojo_shell_context.cc
index 6aa7587..6308b682 100644
--- a/content/browser/mojo/mojo_shell_context.cc
+++ b/content/browser/mojo/mojo_shell_context.cc
@@ -15,7 +15,7 @@
 #include "base/thread_task_runner_handle.h"
 #include "components/profile_service/profile_app.h"
 #include "content/browser/gpu/gpu_process_host.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
 #include "content/common/mojo/current_thread_loader.h"
 #include "content/common/mojo/mojo_shell_connection_impl.h"
 #include "content/common/mojo/static_loader.h"
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 82db867..f9555f67 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -53,7 +53,7 @@
 #include "content/common/gpu/client/context_provider_command_buffer.h"
 #include "content/common/gpu/client/gpu_channel_host.h"
 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
 #include "content/common/host_shared_bitmap_manager.h"
 #include "content/public/browser/android/compositor.h"
 #include "content/public/browser/android/compositor_client.h"
diff --git a/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc b/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
index e793d6a..6d16572 100644
--- a/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
+++ b/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
@@ -71,7 +71,6 @@
                                        font_path_chars.data(), CSIDL_FONTS,
                                        FALSE /* fCreate */);
   DCHECK(result);
-  CHECK(result);
   return base::i18n::FoldCase(font_path_chars.data());
 }
 
@@ -144,19 +143,14 @@
   mswr::ComPtr<IDWriteFontFamily> family;
   HRESULT hr = collection_->GetFontFamily(family_index, &family);
   if (!SUCCEEDED(hr)) {
-    // Crash only if index was not out of bounds.
-    CHECK(family_index >= collection_->GetFontFamilyCount());
     return;
   }
-  CHECK(family);
 
   mswr::ComPtr<IDWriteLocalizedStrings> localized_names;
   hr = family->GetFamilyNames(&localized_names);
   if (!SUCCEEDED(hr)) {
-    CHECK(false);
     return;
   }
-  CHECK(localized_names);
 
   size_t string_count = localized_names->GetCount();
 
@@ -166,14 +160,12 @@
     UINT32 length = 0;
     hr = localized_names->GetLocaleNameLength(index, &length);
     if (!SUCCEEDED(hr)) {
-      CHECK(false);
       return;
     }
     ++length;  // Reserve space for the null terminator.
     locale.resize(length);
     hr = localized_names->GetLocaleName(index, locale.data(), length);
     if (!SUCCEEDED(hr)) {
-      CHECK(false);
       return;
     }
     CHECK_EQ(L'\0', locale[length - 1]);
@@ -181,14 +173,12 @@
     length = 0;
     hr = localized_names->GetStringLength(index, &length);
     if (!SUCCEEDED(hr)) {
-      CHECK(false);
       return;
     }
     ++length;  // Reserve space for the null terminator.
     name.resize(length);
     hr = localized_names->GetString(index, name.data(), length);
     if (!SUCCEEDED(hr)) {
-      CHECK(false);
       return;
     }
     CHECK_EQ(L'\0', name[length - 1]);
@@ -211,8 +201,6 @@
   mswr::ComPtr<IDWriteFontFamily> family;
   HRESULT hr = collection_->GetFontFamily(family_index, &family);
   if (!SUCCEEDED(hr)) {
-    // Crash only if index was not out of bounds.
-    CHECK(family_index >= collection_->GetFontFamilyCount());
     return;
   }
 
@@ -226,10 +214,8 @@
     mswr::ComPtr<IDWriteFont> font;
     hr = family->GetFont(font_index, &font);
     if (!SUCCEEDED(hr)) {
-      CHECK(false);
       return;
     }
-    CHECK(font);
 
     AddFilesForFont(&path_set, font.Get());
   }
@@ -246,15 +232,13 @@
   mswr::ComPtr<IDWriteFactory> factory;
   gfx::win::CreateDWriteFactory(&factory);
   if (factory == nullptr) {
-    CHECK(false);
     // We won't be able to load fonts, but we should still return messages so
     // renderers don't hang if they for some reason send us a font message.
     return;
   }
 
   HRESULT hr = factory->GetSystemFontCollection(&collection_);
-  CHECK(SUCCEEDED(hr));
-  CHECK(collection_);
+  DCHECK(SUCCEEDED(hr));
 }
 
 bool DWriteFontProxyMessageFilter::AddFilesForFont(
@@ -264,14 +248,12 @@
   HRESULT hr;
   hr = font->CreateFontFace(&font_face);
   if (!SUCCEEDED(hr)) {
-    CHECK(false);
     return false;
   }
 
   UINT32 file_count;
   hr = font_face->GetFiles(&file_count, nullptr);
   if (!SUCCEEDED(hr)) {
-    CHECK(false);
     return false;
   }
 
@@ -280,7 +262,6 @@
   hr = font_face->GetFiles(
       &file_count, reinterpret_cast<IDWriteFontFile**>(font_files.data()));
   if (!SUCCEEDED(hr)) {
-    CHECK(false);
     return false;
   }
 
@@ -288,7 +269,6 @@
     mswr::ComPtr<IDWriteFontFileLoader> loader;
     hr = font_files[file_index]->GetLoader(&loader);
     if (!SUCCEEDED(hr)) {
-      CHECK(false);
       return false;
     }
 
@@ -308,13 +288,8 @@
       LogLoaderType(OTHER_LOADER);
       DCHECK(false);
 
-      // UMA indicates zero results for loaderType=OTHER_LOADER, so doing this
-      // CHECK should be safe to rule out this case as a possibility.
-      CHECK(false);
-
       return false;
     } else if (!SUCCEEDED(hr)) {
-      CHECK(false);
       return false;
     }
 
@@ -335,14 +310,12 @@
   UINT32 key_size;
   hr = font_file->GetReferenceKey(&key, &key_size);
   if (!SUCCEEDED(hr)) {
-    CHECK(false);
     return false;
   }
 
   UINT32 path_length = 0;
   hr = local_loader->GetFilePathLengthFromKey(key, key_size, &path_length);
   if (!SUCCEEDED(hr)) {
-    CHECK(false);
     return false;
   }
   ++path_length;  // Reserve space for the null terminator.
@@ -351,7 +324,6 @@
   hr = local_loader->GetFilePathFromKey(key, key_size, file_path_chars.data(),
                                         path_length);
   if (!SUCCEEDED(hr)) {
-    CHECK(false);
     return false;
   }
 
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h
index fe369ec..a42690e 100644
--- a/content/browser/renderer_host/render_message_filter.h
+++ b/content/browser/renderer_host/render_message_filter.h
@@ -20,7 +20,7 @@
 #include "base/strings/string16.h"
 #include "build/build_config.h"
 #include "cc/resources/shared_bitmap_manager.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
 #include "content/common/host_discardable_shared_memory_manager.h"
 #include "content/common/host_shared_bitmap_manager.h"
 #include "content/public/browser/browser_message_filter.h"
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 25b9a4e..e52c354 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -120,6 +120,7 @@
 #include "content/common/child_process_messages.h"
 #include "content/common/content_switches_internal.h"
 #include "content/common/frame_messages.h"
+#include "content/common/gpu_host_messages.h"
 #include "content/common/in_process_child_thread_params.h"
 #include "content/common/mojo/channel_init.h"
 #include "content/common/mojo/mojo_messages.h"
@@ -128,7 +129,6 @@
 #include "content/common/resource_messages.h"
 #include "content/common/site_isolation_policy.h"
 #include "content/common/view_messages.h"
-#include "content/gpu/gpu_host_messages.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 59cf26f..0f80e942 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -469,12 +469,6 @@
     IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged, OnSelectionChanged)
     IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionBoundsChanged,
                         OnSelectionBoundsChanged)
-#if defined(OS_WIN)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowCreated,
-                        OnWindowlessPluginDummyWindowCreated)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowDestroyed,
-                        OnWindowlessPluginDummyWindowDestroyed)
-#endif
     IPC_MESSAGE_HANDLER(InputHostMsg_ImeCompositionRangeChanged,
                         OnImeCompositionRangeChanged)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DidFirstPaintAfterLoad,
@@ -1818,43 +1812,6 @@
   Send(new ViewMsg_ReleaseDisambiguationPopupBitmap(GetRoutingID(), id));
 }
 
-#if defined(OS_WIN)
-void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowCreated(
-    gfx::NativeViewId dummy_activation_window) {
-  HWND hwnd = reinterpret_cast<HWND>(dummy_activation_window);
-
-  // This may happen as a result of a race condition when the plugin is going
-  // away.
-  wchar_t window_title[MAX_PATH + 1] = {0};
-  if (!IsWindow(hwnd) ||
-      !GetWindowText(hwnd, window_title, arraysize(window_title)) ||
-      lstrcmpiW(window_title, kDummyActivationWindowName) != 0) {
-    return;
-  }
-
-#if defined(USE_AURA)
-  SetParent(hwnd,
-            reinterpret_cast<HWND>(view_->GetParentForWindowlessPlugin()));
-#else
-  SetParent(hwnd, reinterpret_cast<HWND>(GetNativeViewId()));
-#endif
-  dummy_windows_for_activation_.push_back(hwnd);
-}
-
-void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowDestroyed(
-    gfx::NativeViewId dummy_activation_window) {
-  HWND hwnd = reinterpret_cast<HWND>(dummy_activation_window);
-  std::list<HWND>::iterator i = dummy_windows_for_activation_.begin();
-  for (; i != dummy_windows_for_activation_.end(); ++i) {
-    if ((*i) == hwnd) {
-      dummy_windows_for_activation_.erase(i);
-      return;
-    }
-  }
-  NOTREACHED() << "Unknown dummy window";
-}
-#endif
-
 void RenderWidgetHostImpl::SetIgnoreInputEvents(bool ignore_input_events) {
   ignore_input_events_ = ignore_input_events;
 }
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 6094b9b..f9600fca 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -589,12 +589,6 @@
   void OnShowDisambiguationPopup(const gfx::Rect& rect_pixels,
                                  const gfx::Size& size,
                                  const cc::SharedBitmapId& id);
-#if defined(OS_WIN)
-  void OnWindowlessPluginDummyWindowCreated(
-      gfx::NativeViewId dummy_activation_window);
-  void OnWindowlessPluginDummyWindowDestroyed(
-      gfx::NativeViewId dummy_activation_window);
-#endif
   void OnSelectionChanged(const base::string16& text,
                           uint32_t offset,
                           const gfx::Range& range);
@@ -804,10 +798,6 @@
   // being sent, in which case the timer should fire).
   bool received_paint_after_load_;
 
-#if defined(OS_WIN)
-  std::list<HWND> dummy_windows_for_activation_;
-#endif
-
   RenderWidgetHostLatencyTracker latency_tracker_;
 
   int next_browser_snapshot_id_;
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 836b298..72d6570 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -56,11 +56,11 @@
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_host_messages.h"
+#include "content/common/gpu_process_launch_causes.h"
 #include "content/common/input/did_overscroll_params.h"
 #include "content/common/input_messages.h"
 #include "content/common/view_messages.h"
-#include "content/gpu/gpu_host_messages.h"
 #include "content/public/browser/android/compositor.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/devtools_agent_host.h"
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index b5f413f..add56ff 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1075,15 +1075,6 @@
 void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
     gfx::NativeViewAccessible accessible_parent) {
 }
-
-gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
-    const {
-  if (legacy_render_widget_host_HWND_) {
-    return reinterpret_cast<gfx::NativeViewId>(
-        legacy_render_widget_host_HWND_->hwnd());
-  }
-  return NULL;
-}
 #endif
 
 bool RenderWidgetHostViewAura::HasAcceleratedSurface(
@@ -2586,10 +2577,8 @@
   delegated_frame_host_->WasResized();
 #if defined(OS_WIN)
   // Create the legacy dummy window which corresponds to the bounds of the
-  // webcontents. This will be passed as the container window for windowless
-  // plugins.
-  // Additonally the legacy dummy window is needed for accessibility and for
-  // scrolling to work in legacy drivers for trackpoints/trackpads, etc.
+  // webcontents. It is needed for accessibility and for scrolling to work in
+  // legacy drivers for trackpoints/trackpads, etc.
   if (!legacy_window_destroyed_ && GetNativeViewId()) {
     if (!legacy_render_widget_host_HWND_) {
       legacy_render_widget_host_HWND_ = LegacyRenderWidgetHostHWND::Create(
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 932fd37..245105f 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -210,7 +210,6 @@
 #if defined(OS_WIN)
   void SetParentNativeViewAccessible(
       gfx::NativeViewAccessible accessible_parent) override;
-  gfx::NativeViewId GetParentForWindowlessPlugin() const override;
 #endif
 
   // Overridden from ui::TextInputClient:
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index 0422f82..ff99d5f2 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -381,10 +381,6 @@
 #if defined(OS_WIN)
   virtual void SetParentNativeViewAccessible(
       gfx::NativeViewAccessible accessible_parent) = 0;
-
-  // Returns an HWND that's given as the parent window for windowless Flash to
-  // workaround crbug.com/301548.
-  virtual gfx::NativeViewId GetParentForWindowlessPlugin() const = 0;
 #endif
 
   // Add and remove observers for lifetime event notifications. The order in
diff --git a/content/browser/renderer_host/render_widget_host_view_mus.cc b/content/browser/renderer_host/render_widget_host_view_mus.cc
index 9d2d21f7..8b945da9 100644
--- a/content/browser/renderer_host/render_widget_host_view_mus.cc
+++ b/content/browser/renderer_host/render_widget_host_view_mus.cc
@@ -319,11 +319,6 @@
 #if defined(OS_WIN)
 void RenderWidgetHostViewMus::SetParentNativeViewAccessible(
     gfx::NativeViewAccessible accessible_parent) {}
-
-gfx::NativeViewId RenderWidgetHostViewMus::GetParentForWindowlessPlugin()
-    const {
-  return gfx::NativeViewId();
-}
 #endif
 
 }  // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_mus.h b/content/browser/renderer_host/render_widget_host_view_mus.h
index 69b1686..d63ae6e 100644
--- a/content/browser/renderer_host/render_widget_host_view_mus.h
+++ b/content/browser/renderer_host/render_widget_host_view_mus.h
@@ -124,7 +124,6 @@
 #if defined(OS_WIN)
   void SetParentNativeViewAccessible(
       gfx::NativeViewAccessible accessible_parent) override;
-  gfx::NativeViewId GetParentForWindowlessPlugin() const override;
 #endif
 
   RenderWidgetHostImpl* host_;
diff --git a/content/child/BUILD.gn b/content/child/BUILD.gn
index d6993ef..ee79f181 100644
--- a/content/child/BUILD.gn
+++ b/content/child/BUILD.gn
@@ -93,11 +93,7 @@
         "npapi/webplugin_delegate_impl_mac.mm",
       ]
     } else if (is_win) {
-      sources -= [
-        "npapi/webplugin_delegate_impl_win.cc",
-        "npapi/webplugin_ime_win.cc",
-        "npapi/webplugin_ime_win.h",
-      ]
+      sources -= [ "npapi/webplugin_delegate_impl_win.cc" ]
     } else if (is_android) {
       sources -= [ "npapi/webplugin_delegate_impl_android.cc" ]
     }
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc
index f825419..ed43c6b 100644
--- a/content/child/blink_platform_impl.cc
+++ b/content/child/blink_platform_impl.cc
@@ -954,7 +954,7 @@
 }
 
 long long BlinkPlatformImpl::databaseGetSpaceAvailableForOrigin(
-    const blink::WebString& origin_identifier) {
+    const blink::WebSecurityOrigin& origin) {
   return 0;
 }
 
diff --git a/content/child/blink_platform_impl.h b/content/child/blink_platform_impl.h
index aa821d0..9e2886a 100644
--- a/content/child/blink_platform_impl.h
+++ b/content/child/blink_platform_impl.h
@@ -72,7 +72,7 @@
       const blink::WebString& vfs_file_name) override;
   long long databaseGetFileSize(const blink::WebString& vfs_file_name) override;
   long long databaseGetSpaceAvailableForOrigin(
-      const blink::WebString& origin_identifier) override;
+      const blink::WebSecurityOrigin& origin) override;
   bool databaseSetFileSize(const blink::WebString& vfs_file_name,
                            long long size) override;
   blink::WebString signedPublicKeyAndChallengeString(
diff --git a/content/child/db_message_filter.cc b/content/child/db_message_filter.cc
index 9bd9af4d..9e65a38 100644
--- a/content/child/db_message_filter.cc
+++ b/content/child/db_message_filter.cc
@@ -5,13 +5,28 @@
 #include "content/child/db_message_filter.h"
 
 #include "content/common/database_messages.h"
+#include "storage/common/database/database_identifier.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
 #include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/web/WebDatabase.h"
 
+using blink::WebSecurityOrigin;
 using blink::WebString;
 
 namespace content {
 
+namespace {
+
+// TODO(jsbell): Pass url::Origin over IPC instead of database identifier/GURL.
+// https://crbug.com/591482
+WebSecurityOrigin OriginFromIdentifier(const std::string& identifier) {
+  return WebSecurityOrigin::create(
+      storage::GetOriginFromIdentifier(identifier));
+}
+
+}  // namespace
+
 DBMessageFilter::DBMessageFilter() {
 }
 
@@ -34,27 +49,27 @@
                                            const base::string16& database_name,
                                            int64_t database_size) {
   blink::WebDatabase::updateDatabaseSize(
-      WebString::fromUTF8(origin_identifier), database_name, database_size);
+      OriginFromIdentifier(origin_identifier), database_name, database_size);
 }
 
 void DBMessageFilter::OnDatabaseUpdateSpaceAvailable(
     const std::string& origin_identifier,
     int64_t space_available) {
   blink::WebDatabase::updateSpaceAvailable(
-      WebString::fromUTF8(origin_identifier), space_available);
+      OriginFromIdentifier(origin_identifier), space_available);
 }
 
 void DBMessageFilter::OnDatabaseResetSpaceAvailable(
     const std::string& origin_identifier) {
   blink::WebDatabase::resetSpaceAvailable(
-      WebString::fromUTF8(origin_identifier));
+      OriginFromIdentifier(origin_identifier));
 }
 
 void DBMessageFilter::OnDatabaseCloseImmediately(
     const std::string& origin_identifier,
     const base::string16& database_name) {
   blink::WebDatabase::closeDatabaseImmediately(
-      WebString::fromUTF8(origin_identifier), database_name);
+      OriginFromIdentifier(origin_identifier), database_name);
 }
 
 }  // namespace content
diff --git a/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc b/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
index ef9a459c..1e28fd69 100644
--- a/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
+++ b/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
@@ -117,7 +117,6 @@
           new DWriteFontProxyMsg_GetFamilyCount(&family_count))) {
     return 0;
   }
-  CHECK(family_count != 0);
   family_count_ = family_count;
   return family_count;
 }
@@ -134,7 +133,7 @@
     }
   }
   // If the font came from our collection, at least one family should match
-  CHECK(false);
+  DCHECK(false);
 
   return E_FAIL;
 }
@@ -145,7 +144,6 @@
     UINT32 collection_key_size,
     IDWriteFontFileEnumerator** font_file_enumerator) {
   if (!collection_key || collection_key_size != sizeof(uint32_t)) {
-    CHECK(false);
     return E_INVALIDARG;
   }
 
@@ -171,7 +169,7 @@
       font_file_enumerator, factory, this, &file_names);
 
   if (!SUCCEEDED(hr)) {
-    CHECK(false);
+    DCHECK(false);
     return E_FAIL;
   }
 
@@ -183,7 +181,6 @@
     UINT32 font_file_reference_key_size,
     IDWriteFontFileStream** font_file_stream) {
   if (!font_file_reference_key) {
-    CHECK(false);
     return E_FAIL;
   }
 
@@ -194,7 +191,6 @@
       static_cast<size_t>(font_file_reference_key_size) / sizeof(base::char16);
 
   if (file_name_size == 0 || file_name[file_name_size - 1] != L'\0') {
-    CHECK(false);
     return E_FAIL;
   }
 
@@ -202,7 +198,7 @@
 
   mswr::ComPtr<IDWriteFontFileStream> stream;
   if (!SUCCEEDED(mswr::MakeAndInitialize<FontFileStream>(&stream, file_name))) {
-    CHECK(false);
+    DCHECK(false);
     return E_FAIL;
   }
   *font_file_stream = stream.Detach();
@@ -212,15 +208,15 @@
 HRESULT DWriteFontCollectionProxy::RuntimeClassInitialize(
     IDWriteFactory* factory,
     const base::Callback<IPC::Sender*(void)>& sender) {
-  CHECK(factory);
+  DCHECK(factory);
 
   factory_ = factory;
   sender_ = sender;
 
   HRESULT hr = factory->RegisterFontCollectionLoader(this);
-  CHECK(SUCCEEDED(hr));
+  DCHECK(SUCCEEDED(hr));
   hr = factory_->RegisterFontFileLoader(this);
-  CHECK(SUCCEEDED(hr));
+  DCHECK(SUCCEEDED(hr));
   return S_OK;
 }
 
@@ -240,7 +236,6 @@
   HRESULT hr = factory_->CreateCustomFontCollection(
       this /*collectionLoader*/, reinterpret_cast<const void*>(&index),
       sizeof(index), containing_collection);
-  CHECK(SUCCEEDED(hr));
 
   return SUCCEEDED(hr);
 }
@@ -259,7 +254,6 @@
   HRESULT hr = mswr::MakeAndInitialize<DWriteLocalizedStrings>(
       localized_strings, &strings);
 
-  CHECK(SUCCEEDED(hr));
   return SUCCEEDED(hr);
 }
 
@@ -278,8 +272,8 @@
   mswr::ComPtr<DWriteFontFamilyProxy> family;
   HRESULT hr = mswr::MakeAndInitialize<DWriteFontFamilyProxy>(&family, this,
                                                               family_index);
-  CHECK(SUCCEEDED(hr));
-  CHECK_LT(family_index, families_.size());
+  DCHECK(SUCCEEDED(hr));
+  DCHECK_LT(family_index, families_.size());
 
   families_[family_index] = family;
   return true;
@@ -312,7 +306,6 @@
   DCHECK(font);
 
   if (index >= GetFontCount()) {
-    CHECK(false);
     return E_INVALIDARG;
   }
   if (!LoadFamily())
@@ -392,7 +385,7 @@
 
   mswr::ComPtr<IDWriteFontCollection> collection;
   HRESULT hr = family_->GetFontCollection(&collection);
-  CHECK(SUCCEEDED(hr));
+  DCHECK(SUCCEEDED(hr));
   hr = collection->GetFontFromFontFace(font_face, font);
 
   return SUCCEEDED(hr);
@@ -435,7 +428,6 @@
     if (SUCCEEDED(hr) && found) {
       hr = collection->GetFontFamily(family_index, &family_);
       LogLoadFamilyResult(LOAD_FAMILY_SUCCESS_MATCHED_FAMILY);
-      CHECK(SUCCEEDED(hr));
       return SUCCEEDED(hr);
     }
   }
@@ -453,8 +445,6 @@
 
   hr = collection->GetFontFamily(0, &family_);
 
-  CHECK(SUCCEEDED(hr));
-
   return SUCCEEDED(hr);
 }
 
@@ -465,7 +455,6 @@
 HRESULT FontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** file) {
   DCHECK(file);
   if (current_file_ >= file_names_.size()) {
-    CHECK(false);
     return E_FAIL;
   }
 
@@ -476,7 +465,7 @@
       reinterpret_cast<const void*>(file_names_[current_file_].c_str()),
       (file_names_[current_file_].length() + 1) * sizeof(base::char16),
       loader_.Get() /*IDWriteFontFileLoader*/, file);
-  CHECK(SUCCEEDED(hr));
+  DCHECK(SUCCEEDED(hr));
   return hr;
 }
 
@@ -525,14 +514,10 @@
                                          UINT64 fragment_offset,
                                          UINT64 fragment_size,
                                          void** fragment_context) {
-  if (fragment_offset + fragment_size < fragment_offset) {
-    CHECK(false);
+  if (fragment_offset + fragment_size < fragment_offset)
     return E_FAIL;
-  }
-  if (fragment_offset + fragment_size > data_.length()) {
-    CHECK(false);
+  if (fragment_offset + fragment_size > data_.length())
     return E_FAIL;
-  }
   *fragment_start = data_.data() + fragment_offset;
   *fragment_context = nullptr;
   return S_OK;
@@ -541,10 +526,8 @@
 HRESULT FontFileStream::RuntimeClassInitialize(
     const base::string16& file_name) {
   data_.Initialize(base::FilePath(file_name));
-  if (!data_.IsValid()) {
-    CHECK(false);
+  if (!data_.IsValid())
     return E_FAIL;
-  }
   return S_OK;
 }
 
diff --git a/content/child/npapi/plugin_host.cc b/content/child/npapi/plugin_host.cc
index f5a04ef..f560061 100644
--- a/content/child/npapi/plugin_host.cc
+++ b/content/child/npapi/plugin_host.cc
@@ -502,8 +502,6 @@
   // Variables:
   //    NPNVxDisplay (unix only)
   //    NPNVxtAppContext (unix only)
-  //    NPNVnetscapeWindow (win only) - Gets the native window on which the
-  //              plugin drawing occurs, returns HWND
   //    NPNVjavascriptEnabledBool:  tells whether Javascript is enabled
   //    NPNVasdEnabledBool:  tells whether SmartUpdate is enabled
   //    NPNVOfflineBool: tells whether offline-mode is enabled
@@ -551,19 +549,6 @@
       }
       break;
     }
-  #if !defined(OS_MACOSX)  // OS X doesn't have windowed plugins.
-    case NPNVnetscapeWindow: {
-      scoped_refptr<PluginInstance> plugin = FindInstance(id);
-      if (!plugin.get()) {
-        NOTREACHED();
-        return NPERR_INVALID_INSTANCE_ERROR;
-      }
-      gfx::PluginWindowHandle handle = plugin->window_handle();
-      *((void**)value) = (void*)handle;
-      rv = NPERR_NO_ERROR;
-      break;
-    }
-  #endif
     case NPNVjavascriptEnabledBool: {
       // yes, JS is enabled.
       *((void**)value) = (void*)1;
diff --git a/content/child/npapi/plugin_instance.cc b/content/child/npapi/plugin_instance.cc
index 3889bd73..3e9808e 100644
--- a/content/child/npapi/plugin_instance.cc
+++ b/content/child/npapi/plugin_instance.cc
@@ -35,7 +35,6 @@
       npp_(0),
       host_(PluginHost::Singleton()),
       npp_functions_(plugin->functions()),
-      window_handle_(0),
       transparent_(true),
       webplugin_(0),
       mime_type_(mime_type),
diff --git a/content/child/npapi/plugin_instance.h b/content/child/npapi/plugin_instance.h
index 75a1e99..8eeaa3e 100644
--- a/content/child/npapi/plugin_instance.h
+++ b/content/child/npapi/plugin_instance.h
@@ -76,12 +76,6 @@
   // NPAPI's instance identifier for this instance
   NPP npp() { return npp_; }
 
-  // Get/Set for the instance's window handle.
-  gfx::PluginWindowHandle window_handle() const { return window_handle_; }
-  void set_window_handle(gfx::PluginWindowHandle value) {
-    window_handle_ = value;
-  }
-
   // Get/Set whether this instance is transparent. This only applies to
   // windowless plugins.  Transparent plugins require that webkit paint the
   // background.
@@ -227,7 +221,6 @@
   NPP                                      npp_;
   scoped_refptr<PluginHost>                host_;
   NPPluginFuncs*                           npp_functions_;
-  gfx::PluginWindowHandle                  window_handle_;
   bool                                     transparent_;
   WebPlugin*                               webplugin_;
   std::string                              mime_type_;
diff --git a/content/child/npapi/webplugin.h b/content/child/npapi/webplugin.h
index 9e7f1ed80..48da4ab 100644
--- a/content/child/npapi/webplugin.h
+++ b/content/child/npapi/webplugin.h
@@ -66,15 +66,6 @@
   // Returns true iff in incognito mode.
   virtual bool IsOffTheRecord() = 0;
 
-#if defined(OS_WIN)
-  // |pump_messages_event| is a event handle which is used in NPP_HandleEvent
-  // calls to pump messages if the plugin enters a modal loop.
-  // |dummy_activation_window} is used to ensure correct keyboard activation.
-  // It needs to be a child of the parent window.
-  virtual void SetWindowlessData(HANDLE pump_messages_event,
-                                 gfx::NativeViewId dummy_activation_window) = 0;
-#endif
-
 #if defined(OS_MACOSX)
   // Called to inform the WebPlugin that the plugin has gained or lost focus.
   virtual void FocusChanged(bool focused) {}
diff --git a/content/child/npapi/webplugin_delegate_impl.h b/content/child/npapi/webplugin_delegate_impl.h
index f07256b..3ed44c4 100644
--- a/content/child/npapi/webplugin_delegate_impl.h
+++ b/content/child/npapi/webplugin_delegate_impl.h
@@ -46,10 +46,6 @@
 class ExternalDragTracker;
 #endif  // OS_MACOSX
 
-#if defined(OS_WIN)
-class WebPluginIMEWin;
-#endif  // OS_WIN
-
 // An implementation of WebPluginDelegate that runs in the plugin process,
 // proxied from the renderer by WebPluginDelegateProxy.
 class WebPluginDelegateImpl : public WebPluginDelegate {
@@ -111,21 +107,6 @@
   // Informs the plugin that the view it is in has gained or lost focus.
   void SetContentAreaHasFocus(bool has_focus);
 
-#if defined(OS_WIN)
-  // Informs the plugin that an IME has changed its status.
-  void ImeCompositionUpdated(const base::string16& text,
-                             const std::vector<int>& clauses,
-                             const std::vector<int>& target,
-                             int cursor_position);
-
-  // Informs the plugin that IME composition has completed./ If |text| is empty,
-  // IME was cancelled.
-  void ImeCompositionCompleted(const base::string16& text);
-
-  // Returns the IME status retrieved from a plugin.
-  bool GetIMEStatus(int* input_type, gfx::Rect* caret_rect);
-#endif
-
 #if defined(OS_MACOSX) && !defined(USE_AURA)
   // Informs the plugin that the geometry has changed, as with UpdateGeometry,
   // but also includes the new buffer context for that new geometry.
@@ -175,20 +156,6 @@
   // Called by DestroyInstance(), used for platform-specific destruction.
   void PlatformDestroyInstance();
 
-#if defined(OS_WIN)
-  // Our WndProc functions.
-  static LRESULT CALLBACK FlashWindowlessWndProc(
-      HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
-  static LRESULT CALLBACK DummyWindowProc(
-      HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
-
-  // Used for throttling Flash messages.
-  static void ClearThrottleQueueForWindow(HWND window);
-  static void OnThrottleMessage();
-  static void ThrottleMessage(WNDPROC proc, HWND hwnd, UINT message,
-      WPARAM wParam, LPARAM lParam);
-#endif
-
   //----------------------------
   // used for windowless plugins
   void WindowlessUpdateGeometry(const gfx::Rect& window_rect,
@@ -227,67 +194,12 @@
   WebPlugin* plugin_;
   scoped_refptr<PluginInstance> instance_;
 
-#if defined(OS_WIN)
-  // An IME emulator used by a windowless plugin to retrieve IME data through
-  // IMM32 functions.
-  scoped_ptr<WebPluginIMEWin> plugin_ime_;
-#endif  // defined(OS_WIN)
-
   NPWindow window_;
   gfx::Rect window_rect_;
   gfx::Rect clip_rect_;
   int quirks_;
 
-#if defined(OS_WIN)
-  // Windowless plugins don't have keyboard focus causing issues with the
-  // plugin not receiving keyboard events if the plugin enters a modal
-  // loop like TrackPopupMenuEx or MessageBox, etc.
-  // This is a basic issue with windows activation and focus arising due to
-  // the fact that these windows are created by different threads. Activation
-  // and focus are thread specific states, and if the browser has focus,
-  // the plugin may not have focus.
-  // To fix a majority of these activation issues we create a dummy visible
-  // child window to which we set focus whenever the windowless plugin
-  // receives a WM_LBUTTONDOWN/WM_RBUTTONDOWN message via NPP_HandleEvent.
-
-  HWND dummy_window_for_activation_;
-  HWND dummy_window_parent_;
-  WNDPROC old_dummy_window_proc_;
-  bool CreateDummyWindowForActivation();
-
-  // Returns true if the event passed in needs to be tracked for a potential
-  // modal loop.
-  static bool ShouldTrackEventForModalLoops(NPEvent* event);
-
-  // The message filter hook procedure, which tracks modal loops entered by
-  // a plugin in the course of a NPP_HandleEvent call.
-  static LRESULT CALLBACK HandleEventMessageFilterHook(int code, WPARAM wParam,
-                                                       LPARAM lParam);
-
-  // TrackPopupMenu interceptor. Parameters are the same as the Win32 function
-  // TrackPopupMenu.
-  static BOOL WINAPI TrackPopupMenuPatch(HMENU menu, unsigned int flags, int x,
-                                         int y, int reserved, HWND window,
-                                         const RECT* rect);
-
-  // SetCursor interceptor for windowless plugins.
-  static HCURSOR WINAPI SetCursorPatch(HCURSOR cursor);
-
-  // RegEnumKeyExW interceptor.
-  static LONG WINAPI RegEnumKeyExWPatch(
-      HKEY key, DWORD index, LPWSTR name, LPDWORD name_size, LPDWORD reserved,
-      LPWSTR class_name, LPDWORD class_size, PFILETIME last_write_time);
-
-  // GetProcAddress intercepter for windowless plugins.
-  static FARPROC WINAPI GetProcAddressPatch(HMODULE module, LPCSTR name);
-
-  // WindowFromPoint patch for Flash windowless plugins. When flash receives
-  // mouse move messages it calls the WindowFromPoint API to eventually convert
-  // the mouse coordinates to screen. We need to return the dummy plugin parent
-  // window for Aura to ensure that these conversions occur correctly.
-  static HWND WINAPI WindowFromPointPatch(POINT point);
-
-#elif defined(OS_MACOSX) && !defined(USE_AURA)
+#if defined(OS_MACOSX) && !defined(USE_AURA)
   // Sets window_rect_ to |rect|
   void SetPluginRect(const gfx::Rect& rect);
   // Sets content_area_origin to |origin|
@@ -340,15 +252,6 @@
   // The url with which the plugin was instantiated.
   std::string plugin_url_;
 
-#if defined(OS_WIN)
-  // Handle to the message filter hook
-  HHOOK handle_event_message_filter_hook_;
-
-  // Event which is set when the plugin enters a modal loop in the course
-  // of a NPP_HandleEvent call.
-  HANDLE handle_event_pump_messages_event_;
-#endif
-
   // Holds the depth of the HandleEvent callstack.
   int handle_event_depth_;
 
diff --git a/content/child/npapi/webplugin_delegate_impl_win.cc b/content/child/npapi/webplugin_delegate_impl_win.cc
index f0213e3..70657052 100644
--- a/content/child/npapi/webplugin_delegate_impl_win.cc
+++ b/content/child/npapi/webplugin_delegate_impl_win.cc
@@ -22,13 +22,10 @@
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/lock.h"
 #include "base/version.h"
-#include "base/win/iat_patch_function.h"
-#include "base/win/registry.h"
 #include "base/win/windows_version.h"
 #include "content/child/npapi/plugin_instance.h"
 #include "content/child/npapi/plugin_lib.h"
 #include "content/child/npapi/webplugin.h"
-#include "content/child/npapi/webplugin_ime_win.h"
 #include "content/common/cursors/webcursor.h"
 #include "content/common/plugin_constants_win.h"
 #include "content/public/common/content_constants.h"
@@ -45,47 +42,6 @@
 
 namespace {
 
-const wchar_t kWebPluginDelegateProperty[] = L"WebPluginDelegateProperty";
-
-// The fastest we are willing to process WM_USER+1 events for Flash.
-// Flash can easily exceed the limits of our CPU if we don't throttle it.
-// The throttle has been chosen by testing various delays and compromising
-// on acceptable Flash performance and reasonable CPU consumption.
-//
-// I'd like to make the throttle delay variable, based on the amount of
-// time currently required to paint Flash plugins.  There isn't a good
-// way to count the time spent in aggregate plugin painting, however, so
-// this seems to work well enough.
-const int kFlashWMUSERMessageThrottleDelayMs = 5;
-
-// The current instance of the plugin which entered the modal loop.
-WebPluginDelegateImpl* g_current_plugin_instance = NULL;
-
-typedef std::deque<MSG> ThrottleQueue;
-base::LazyInstance<ThrottleQueue> g_throttle_queue = LAZY_INSTANCE_INITIALIZER;
-
-base::LazyInstance<std::map<HWND, WNDPROC> > g_window_handle_proc_map =
-    LAZY_INSTANCE_INITIALIZER;
-
-// Helper object for patching the TrackPopupMenu API.
-base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_track_popup_menu =
-    LAZY_INSTANCE_INITIALIZER;
-
-// Helper object for patching the SetCursor API.
-base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_set_cursor =
-    LAZY_INSTANCE_INITIALIZER;
-
-// Helper object for patching the RegEnumKeyExW API.
-base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w =
-    LAZY_INSTANCE_INITIALIZER;
-
-// Helper object for patching the GetProcAddress API.
-base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_get_proc_address =
-    LAZY_INSTANCE_INITIALIZER;
-
-base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_window_from_point =
-    LAZY_INSTANCE_INITIALIZER;
-
 // http://crbug.com/16114
 // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow
 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL.
@@ -118,104 +74,13 @@
   bool disposable_dc_;
 };
 
-// These are from ntddk.h
-typedef LONG NTSTATUS;
-
-#ifndef STATUS_SUCCESS
-#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
-#endif
-
-#ifndef STATUS_BUFFER_TOO_SMALL
-#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
-#endif
-
-typedef enum _KEY_INFORMATION_CLASS {
-  KeyBasicInformation,
-  KeyNodeInformation,
-  KeyFullInformation,
-  KeyNameInformation,
-  KeyCachedInformation,
-  KeyVirtualizationInformation
-} KEY_INFORMATION_CLASS;
-
-typedef struct _KEY_NAME_INFORMATION {
-  ULONG NameLength;
-  WCHAR Name[1];
-} KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION;
-
-typedef DWORD (__stdcall *ZwQueryKeyType)(
-    HANDLE  key_handle,
-    int key_information_class,
-    PVOID  key_information,
-    ULONG  length,
-    PULONG  result_length);
-
-// Returns a key's full path.
-std::wstring GetKeyPath(HKEY key) {
-  if (key == NULL)
-    return L"";
-
-  HMODULE dll = GetModuleHandle(L"ntdll.dll");
-  if (dll == NULL)
-    return L"";
-
-  ZwQueryKeyType func = reinterpret_cast<ZwQueryKeyType>(
-      ::GetProcAddress(dll, "ZwQueryKey"));
-  if (func == NULL)
-    return L"";
-
-  DWORD size = 0;
-  DWORD result = 0;
-  result = func(key, KeyNameInformation, 0, 0, &size);
-  if (result != static_cast<DWORD>(STATUS_BUFFER_TOO_SMALL))
-    return L"";
-
-  scoped_ptr<char[]> buffer(new char[size]);
-  if (buffer.get() == NULL)
-    return L"";
-
-  result = func(key, KeyNameInformation, buffer.get(), size, &size);
-  if (result != static_cast<DWORD>(STATUS_SUCCESS))
-    return L"";
-
-  KEY_NAME_INFORMATION* info =
-      reinterpret_cast<KEY_NAME_INFORMATION*>(buffer.get());
-  return std::wstring(info->Name, info->NameLength / sizeof(wchar_t));
-}
-
-uint32_t GetPluginMajorVersion(const WebPluginInfo& plugin_info) {
-  Version plugin_version;
-  WebPluginInfo::CreateVersionFromString(plugin_info.version, &plugin_version);
-
-  uint32_t major_version = 0;
-  if (plugin_version.IsValid())
-    major_version = plugin_version.components()[0];
-
-  return major_version;
-}
-
 }  // namespace
 
-LRESULT CALLBACK WebPluginDelegateImpl::HandleEventMessageFilterHook(
-    int code, WPARAM wParam, LPARAM lParam) {
-  if (g_current_plugin_instance) {
-    g_current_plugin_instance->OnModalLoopEntered();
-  } else {
-    NOTREACHED();
-  }
-  return CallNextHookEx(NULL, code, wParam, lParam);
-}
-
 WebPluginDelegateImpl::WebPluginDelegateImpl(WebPlugin* plugin,
                                              PluginInstance* instance)
     : plugin_(plugin),
       instance_(instance),
       quirks_(0),
-      dummy_window_for_activation_(NULL),
-      dummy_window_parent_(NULL),
-      old_dummy_window_proc_(NULL),
-      handle_event_message_filter_hook_(NULL),
-      handle_event_pump_messages_event_(NULL),
       handle_event_depth_(0),
       first_set_window_call_(true),
       plugin_has_focus_(false),
@@ -224,182 +89,17 @@
       creation_succeeded_(false),
       user_gesture_msg_factory_(this) {
   memset(&window_, 0, sizeof(window_));
-
-  const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info();
-  base::string16 filename =
-      base::ToLowerASCII(plugin_info.path.BaseName().value());
-
-  if (instance_->mime_type() == kFlashPluginSwfMimeType ||
-      filename == kFlashPlugin) {
-    // Flash only requests windowless plugins if we return a Mozilla user
-    // agent.
-    instance_->set_use_mozilla_user_agent();
-    quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE;
-    quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR;
-    quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS;
-    quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE;
-    quirks_ |= PLUGIN_QUIRK_EMULATE_IME;
-    quirks_ |= PLUGIN_QUIRK_FAKE_WINDOW_FROM_POINT;
-  } else if (filename == kAcrobatReaderPlugin) {
-    // Check for the version number above or equal 9.
-    uint32_t major_version = GetPluginMajorVersion(plugin_info);
-    if (major_version >= 9) {
-      quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD;
-      // 9.2 needs this.
-      quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE;
-    }
-    quirks_ |= PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS;
-  } else if (plugin_info.name.find(L"Windows Media Player") !=
-             std::wstring::npos) {
-    // Windows Media Player needs two NPP_SetWindow calls.
-    quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE;
-
-    // Windowless mode doesn't work in the WMP NPAPI plugin.
-    quirks_ |= PLUGIN_QUIRK_NO_WINDOWLESS;
-
-    // The media player plugin sets its size on the first NPP_SetWindow call
-    // and never updates its size. We should call the underlying NPP_SetWindow
-    // only when we have the correct size.
-    quirks_ |= PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL;
-
-    if (filename == kOldWMPPlugin) {
-      // Non-admin users on XP couldn't modify the key to force the new UI.
-      quirks_ |= PLUGIN_QUIRK_PATCH_REGENUMKEYEXW;
-    }
-  } else if (instance_->mime_type() == "audio/x-pn-realaudio-plugin" ||
-             filename == kRealPlayerPlugin) {
-    quirks_ |= PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY;
-  } else if (plugin_info.name.find(L"VLC Multimedia Plugin") !=
-             std::wstring::npos ||
-             plugin_info.name.find(L"VLC Multimedia Plug-in") !=
-             std::wstring::npos) {
-    // VLC hangs on NPP_Destroy if we call NPP_SetWindow with a null window
-    // handle
-    quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY;
-    uint32_t major_version = GetPluginMajorVersion(plugin_info);
-    if (major_version == 0) {
-      // VLC 0.8.6d and 0.8.6e crash if multiple instances are created.
-      quirks_ |= PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES;
-    }
-  } else if (filename == kSilverlightPlugin) {
-    // Explanation for this quirk can be found in
-    // WebPluginDelegateImpl::Initialize.
-    quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR;
-  } else if (plugin_info.name.find(L"DivX Web Player") !=
-             std::wstring::npos) {
-    // The divx plugin sets its size on the first NPP_SetWindow call and never
-    // updates its size. We should call the underlying NPP_SetWindow only when
-    // we have the correct size.
-    quirks_ |= PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL;
-  }
 }
 
 WebPluginDelegateImpl::~WebPluginDelegateImpl() {
-  if (::IsWindow(dummy_window_for_activation_)) {
-    WNDPROC current_wnd_proc = reinterpret_cast<WNDPROC>(
-        GetWindowLongPtr(dummy_window_for_activation_, GWLP_WNDPROC));
-    if (current_wnd_proc == DummyWindowProc) {
-      SetWindowLongPtr(dummy_window_for_activation_,
-                       GWLP_WNDPROC,
-                       reinterpret_cast<LONG_PTR>(old_dummy_window_proc_));
-    }
-    ::DestroyWindow(dummy_window_for_activation_);
-  }
-
   DestroyInstance();
-
-  if (handle_event_pump_messages_event_) {
-    CloseHandle(handle_event_pump_messages_event_);
-  }
 }
 
 bool WebPluginDelegateImpl::PlatformInitialize() {
-  CreateDummyWindowForActivation();
-  handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
-  plugin_->SetWindowlessData(
-      handle_event_pump_messages_event_,
-      reinterpret_cast<gfx::NativeViewId>(dummy_window_for_activation_));
-
-  // Windowless plugins call the WindowFromPoint API and passes the result of
-  // that to the TrackPopupMenu API call as the owner window. This causes the
-  // API to fail as the API expects the window handle to live on the same
-  // thread as the caller. It works in the other browsers as the plugin lives
-  // on the browser thread. Our workaround is to intercept the TrackPopupMenu
-  // API and replace the window handle with the dummy activation window.
-  if (!g_iat_patch_track_popup_menu.Pointer()->is_patched()) {
-    g_iat_patch_track_popup_menu.Pointer()->Patch(
-        GetPluginPath().value().c_str(), "user32.dll", "TrackPopupMenu",
-        WebPluginDelegateImpl::TrackPopupMenuPatch);
-  }
-
-  // Windowless plugins can set cursors by calling the SetCursor API. This
-  // works because the thread inputs of the browser UI thread and the plugin
-  // thread are attached. We intercept the SetCursor API for windowless
-  // plugins and remember the cursor being set. This is shipped over to the
-  // browser in the HandleEvent call, which ensures that the cursor does not
-  // change when a windowless plugin instance changes the cursor
-  // in a background tab.
-  if (!g_iat_patch_set_cursor.Pointer()->is_patched() &&
-      (quirks_ & PLUGIN_QUIRK_PATCH_SETCURSOR)) {
-    g_iat_patch_set_cursor.Pointer()->Patch(
-        GetPluginPath().value().c_str(), "user32.dll", "SetCursor",
-        WebPluginDelegateImpl::SetCursorPatch);
-  }
-
-  // On XP, WMP will use its old UI unless a registry key under HKLM has the
-  // name of the current process.  We do it in the installer for admin users,
-  // for the rest patch this function.
-  if ((quirks_ & PLUGIN_QUIRK_PATCH_REGENUMKEYEXW) &&
-      base::win::GetVersion() == base::win::VERSION_XP &&
-      (base::win::RegKey().Open(HKEY_LOCAL_MACHINE,
-          L"SOFTWARE\\Microsoft\\MediaPlayer\\ShimInclusionList\\chrome.exe",
-          KEY_READ) != ERROR_SUCCESS) &&
-      !g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched()) {
-    g_iat_patch_reg_enum_key_ex_w.Pointer()->Patch(
-        L"wmpdxm.dll", "advapi32.dll", "RegEnumKeyExW",
-        WebPluginDelegateImpl::RegEnumKeyExWPatch);
-  }
-
-  // Flash retrieves the pointers to IMM32 functions with GetProcAddress() calls
-  // and use them to retrieve IME data. We add a patch to this function so we
-  // can dispatch these IMM32 calls to the WebPluginIMEWin class, which emulates
-  // IMM32 functions for Flash.
-  if (!g_iat_patch_get_proc_address.Pointer()->is_patched() &&
-      (quirks_ & PLUGIN_QUIRK_EMULATE_IME)) {
-    g_iat_patch_get_proc_address.Pointer()->Patch(
-        GetPluginPath().value().c_str(), "kernel32.dll", "GetProcAddress",
-        GetProcAddressPatch);
-  }
-
-  if (!g_iat_patch_window_from_point.Pointer()->is_patched() &&
-      (quirks_ & PLUGIN_QUIRK_FAKE_WINDOW_FROM_POINT)) {
-    g_iat_patch_window_from_point.Pointer()->Patch(
-        GetPluginPath().value().c_str(), "user32.dll", "WindowFromPoint",
-        WebPluginDelegateImpl::WindowFromPointPatch);
-  }
-
   return true;
 }
 
 void WebPluginDelegateImpl::PlatformDestroyInstance() {
-  if (!instance_->plugin_lib())
-    return;
-
-  // Unpatch if this is the last plugin instance.
-  if (instance_->plugin_lib()->instance_count() != 1)
-    return;
-
-  if (g_iat_patch_set_cursor.Pointer()->is_patched())
-    g_iat_patch_set_cursor.Pointer()->Unpatch();
-
-  if (g_iat_patch_track_popup_menu.Pointer()->is_patched())
-    g_iat_patch_track_popup_menu.Pointer()->Unpatch();
-
-  if (g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched())
-    g_iat_patch_reg_enum_key_ex_w.Pointer()->Unpatch();
-
-  if (g_iat_patch_window_from_point.Pointer()->is_patched())
-    g_iat_patch_window_from_point.Pointer()->Unpatch();
 }
 
 void WebPluginDelegateImpl::Paint(SkCanvas* canvas, const gfx::Rect& rect) {
@@ -410,234 +110,6 @@
   }
 }
 
-// Erase all messages in the queue destined for a particular window.
-// When windows are closing, callers should use this function to clear
-// the queue.
-// static
-void WebPluginDelegateImpl::ClearThrottleQueueForWindow(HWND window) {
-  ThrottleQueue* throttle_queue = g_throttle_queue.Pointer();
-
-  ThrottleQueue::iterator it;
-  for (it = throttle_queue->begin(); it != throttle_queue->end(); ) {
-    if (it->hwnd == window) {
-      it = throttle_queue->erase(it);
-    } else {
-      it++;
-    }
-  }
-}
-
-// Delayed callback for processing throttled messages.
-// Throttled messages are aggregated globally across all plugins.
-// static
-void WebPluginDelegateImpl::OnThrottleMessage() {
-  // The current algorithm walks the list and processes the first
-  // message it finds for each plugin.  It is important to service
-  // all active plugins with each pass through the throttle, otherwise
-  // we see video jankiness.  Copy the set to notify before notifying
-  // since we may re-enter OnThrottleMessage from CallWindowProc!
-  ThrottleQueue* throttle_queue = g_throttle_queue.Pointer();
-  ThrottleQueue notify_queue;
-  std::set<HWND> processed;
-
-  ThrottleQueue::iterator it = throttle_queue->begin();
-  while (it != throttle_queue->end()) {
-    const MSG& msg = *it;
-    if (processed.find(msg.hwnd) == processed.end()) {
-      processed.insert(msg.hwnd);
-      notify_queue.push_back(msg);
-      it = throttle_queue->erase(it);
-    } else {
-      it++;
-    }
-  }
-
-  // Due to re-entrancy, we must save our queue state now.  Otherwise, we may
-  // self-post below, and *also* start up another delayed task when the first
-  // entry is pushed onto the queue in ThrottleMessage().
-  bool throttle_queue_was_empty = throttle_queue->empty();
-
-  for (it = notify_queue.begin(); it != notify_queue.end(); ++it) {
-    const MSG& msg = *it;
-    WNDPROC proc = reinterpret_cast<WNDPROC>(msg.time);
-    // It is possible that the window was closed after we queued
-    // this message.  This is a rare event; just verify the window
-    // is alive.  (see also bug 1259488)
-    if (IsWindow(msg.hwnd))
-      CallWindowProc(proc, msg.hwnd, msg.message, msg.wParam, msg.lParam);
-  }
-
-  if (!throttle_queue_was_empty) {
-    base::MessageLoop::current()->PostDelayedTask(
-        FROM_HERE,
-        base::Bind(&WebPluginDelegateImpl::OnThrottleMessage),
-        base::TimeDelta::FromMilliseconds(kFlashWMUSERMessageThrottleDelayMs));
-  }
-}
-
-// Schedule a windows message for delivery later.
-// static
-void WebPluginDelegateImpl::ThrottleMessage(WNDPROC proc, HWND hwnd,
-                                            UINT message, WPARAM wParam,
-                                            LPARAM lParam) {
-  MSG msg;
-  // Cast through uintptr_t and then DWORD to make the truncation explicit.
-  msg.time = static_cast<DWORD>(reinterpret_cast<uintptr_t>(proc));
-  msg.hwnd = hwnd;
-  msg.message = message;
-  msg.wParam = wParam;
-  msg.lParam = lParam;
-
-  ThrottleQueue* throttle_queue = g_throttle_queue.Pointer();
-
-  throttle_queue->push_back(msg);
-
-  if (throttle_queue->size() == 1) {
-    base::MessageLoop::current()->PostDelayedTask(
-        FROM_HERE,
-        base::Bind(&WebPluginDelegateImpl::OnThrottleMessage),
-        base::TimeDelta::FromMilliseconds(kFlashWMUSERMessageThrottleDelayMs));
-  }
-}
-
-// We go out of our way to find the hidden windows created by Flash for
-// windowless plugins.  We throttle the rate at which they deliver messages
-// so that they will not consume outrageous amounts of CPU.
-// static
-LRESULT CALLBACK WebPluginDelegateImpl::FlashWindowlessWndProc(
-    HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
-  std::map<HWND, WNDPROC>::iterator index =
-      g_window_handle_proc_map.Get().find(hwnd);
-
-  WNDPROC old_proc = (*index).second;
-  DCHECK(old_proc);
-
-  switch (message) {
-    case WM_NCDESTROY: {
-      WebPluginDelegateImpl::ClearThrottleQueueForWindow(hwnd);
-      g_window_handle_proc_map.Get().erase(index);
-      break;
-    }
-    // Flash may flood the message queue with WM_USER+1 message causing 100% CPU
-    // usage.  See https://bugzilla.mozilla.org/show_bug.cgi?id=132759.  We
-    // prevent this by throttling the messages.
-    case WM_USER + 1: {
-      WebPluginDelegateImpl::ThrottleMessage(old_proc, hwnd, message, wparam,
-                                             lparam);
-      return TRUE;
-    }
-
-    default: {
-      break;
-    }
-  }
-  return CallWindowProc(old_proc, hwnd, message, wparam, lparam);
-}
-
-LRESULT CALLBACK WebPluginDelegateImpl::DummyWindowProc(
-    HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param) {
-  WebPluginDelegateImpl* delegate = reinterpret_cast<WebPluginDelegateImpl*>(
-      GetProp(hwnd, kWebPluginDelegateProperty));
-  CHECK(delegate);
-  if (message == WM_WINDOWPOSCHANGING) {
-    // We need to know when the dummy window is parented because windowless
-    // plugins need the parent window for things like menus. There's no message
-    // for a parent being changed, but a WM_WINDOWPOSCHANGING is sent so we
-    // check every time we get it.
-    // For non-aura builds, this never changes since RenderWidgetHostViewWin's
-    // window is constant. For aura builds, this changes every time the tab gets
-    // dragged to a new window.
-    HWND parent = GetParent(hwnd);
-    if (parent != delegate->dummy_window_parent_) {
-      delegate->dummy_window_parent_ = parent;
-
-      // Set the containing window handle as the instance window handle. This is
-      // what Safari does. Not having a valid window handle causes subtle bugs
-      // with plugins which retrieve the window handle and use it for things
-      // like context menus. The window handle can be retrieved via
-      // NPN_GetValue of NPNVnetscapeWindow.
-      delegate->instance_->set_window_handle(parent);
-
-      // The plugin caches the result of NPNVnetscapeWindow when we originally
-      // called NPP_SetWindow, so force it to get the new value.
-      delegate->WindowlessSetWindow();
-    }
-  } else if (message == WM_NCDESTROY) {
-    RemoveProp(hwnd, kWebPluginDelegateProperty);
-  }
-  return CallWindowProc(
-      delegate->old_dummy_window_proc_, hwnd, message, w_param, l_param);
-}
-
-// Callback for enumerating the Flash windows.
-BOOL CALLBACK EnumFlashWindows(HWND window, LPARAM arg) {
-  WNDPROC wnd_proc = reinterpret_cast<WNDPROC>(arg);
-  TCHAR class_name[1024];
-  if (!RealGetWindowClass(window, class_name,
-                          sizeof(class_name)/sizeof(TCHAR))) {
-    LOG(ERROR) << "RealGetWindowClass failure: " << GetLastError();
-    return FALSE;
-  }
-
-  if (wcscmp(class_name, L"SWFlash_PlaceholderX"))
-    return TRUE;
-
-  WNDPROC current_wnd_proc = reinterpret_cast<WNDPROC>(
-        GetWindowLongPtr(window, GWLP_WNDPROC));
-  if (current_wnd_proc != wnd_proc) {
-    WNDPROC old_flash_proc = reinterpret_cast<WNDPROC>(SetWindowLongPtr(
-        window, GWLP_WNDPROC,
-        reinterpret_cast<LONG_PTR>(wnd_proc)));
-    DCHECK(old_flash_proc);
-    g_window_handle_proc_map.Get()[window] = old_flash_proc;
-  }
-
-  return TRUE;
-}
-
-bool WebPluginDelegateImpl::CreateDummyWindowForActivation() {
-  DCHECK(!dummy_window_for_activation_);
-
-  dummy_window_for_activation_ = CreateWindowEx(
-    0,
-    L"Static",
-    kDummyActivationWindowName,
-    WS_CHILD,
-    0,
-    0,
-    0,
-    0,
-    // We don't know the parent of the dummy window yet, so just set it to the
-    // desktop and it'll get parented by the browser.
-    GetDesktopWindow(),
-    0,
-    GetModuleHandle(NULL),
-    0);
-
-  if (dummy_window_for_activation_ == 0)
-    return false;
-
-  BOOL result = SetProp(dummy_window_for_activation_,
-                        kWebPluginDelegateProperty, this);
-  DCHECK(result == TRUE) << "SetProp failed, last error = " << GetLastError();
-  old_dummy_window_proc_ = reinterpret_cast<WNDPROC>(SetWindowLongPtr(
-      dummy_window_for_activation_, GWLP_WNDPROC,
-      reinterpret_cast<LONG_PTR>(DummyWindowProc)));
-
-  // Flash creates background windows which use excessive CPU in our
-  // environment; we wrap these windows and throttle them so that they don't
-  // get out of hand.
-  if (!EnumThreadWindows(::GetCurrentThreadId(), EnumFlashWindows,
-      reinterpret_cast<LPARAM>(
-      &WebPluginDelegateImpl::FlashWindowlessWndProc))) {
-    // Log that this happened.  Flash will still work; it just means the
-    // throttle isn't installed (and Flash will use more CPU).
-    NOTREACHED();
-    LOG(ERROR) << "Failed to wrap all windowless Flash windows";
-  }
-  return true;
-}
-
 // Returns true if the message passed in corresponds to a user gesture.
 static bool IsUserGestureMessage(unsigned int message) {
   switch (message) {
@@ -860,51 +332,6 @@
     return false;
   }
 
-  // Allow this plugin to access this IME emulator through IMM32 API while the
-  // plugin is processing this event.
-  if (GetQuirks() & PLUGIN_QUIRK_EMULATE_IME) {
-    if (!plugin_ime_)
-      plugin_ime_.reset(new WebPluginIMEWin);
-  }
-  WebPluginIMEWin::ScopedLock lock(
-      event.isKeyboardEventType(event.type) ? plugin_ime_.get() : NULL);
-
-  HWND last_focus_window = NULL;
-
-  if (ShouldTrackEventForModalLoops(&np_event)) {
-    // A windowless plugin can enter a modal loop in a NPP_HandleEvent call.
-    // For e.g. Flash puts up a context menu when we right click on the
-    // windowless plugin area. We detect this by setting up a message filter
-    // hook pror to calling NPP_HandleEvent on the plugin and unhook on
-    // return from NPP_HandleEvent. If the plugin does enter a modal loop
-    // in that context we unhook on receiving the first notification in
-    // the message filter hook.
-    handle_event_message_filter_hook_ =
-        SetWindowsHookEx(WH_MSGFILTER, HandleEventMessageFilterHook, NULL,
-                         GetCurrentThreadId());
-    // To ensure that the plugin receives keyboard events we set focus to the
-    // dummy window.
-    // TODO(iyengar) We need a framework in the renderer to identify which
-    // windowless plugin is under the mouse and to handle this. This would
-    // also require some changes in RenderWidgetHost to detect this in the
-    // WM_MOUSEACTIVATE handler and inform the renderer accordingly.
-    bool valid = GetParent(dummy_window_for_activation_) != GetDesktopWindow();
-    if (valid) {
-      last_focus_window = ::SetFocus(dummy_window_for_activation_);
-    } else {
-      NOTREACHED() << "Dummy window not parented";
-    }
-  }
-
-  bool old_task_reentrancy_state =
-      base::MessageLoop::current()->NestableTasksAllowed();
-
-  // Maintain a local/global stack for the g_current_plugin_instance variable
-  // as this may be a nested invocation.
-  WebPluginDelegateImpl* last_plugin_instance = g_current_plugin_instance;
-
-  g_current_plugin_instance = this;
-
   handle_event_depth_++;
 
   bool popups_enabled = false;
@@ -936,174 +363,7 @@
 
   handle_event_depth_--;
 
-  g_current_plugin_instance = last_plugin_instance;
-
-  // We could have multiple NPP_HandleEvent calls nested together in case
-  // the plugin enters a modal loop. Reset the pump messages event when
-  // the outermost NPP_HandleEvent call unwinds.
-  if (handle_event_depth_ == 0) {
-    ResetEvent(handle_event_pump_messages_event_);
-  }
-
-  // If we didn't enter a modal loop, need to unhook the filter.
-  if (handle_event_message_filter_hook_) {
-    UnhookWindowsHookEx(handle_event_message_filter_hook_);
-    handle_event_message_filter_hook_ = NULL;
-  }
-
-  if (::IsWindow(last_focus_window)) {
-    // Restore the nestable tasks allowed state in the message loop and reset
-    // the os modal loop state as the plugin returned from the TrackPopupMenu
-    // API call.
-    base::MessageLoop::current()->SetNestableTasksAllowed(
-        old_task_reentrancy_state);
-    base::MessageLoop::current()->set_os_modal_loop(false);
-    // The Flash plugin at times sets focus to its hidden top level window
-    // with class name SWFlash_PlaceholderX. This causes the chrome browser
-    // window to receive a WM_ACTIVATEAPP message as a top level window from
-    // another thread is now active. We end up in a state where the chrome
-    // browser window is not active even though the user clicked on it.
-    // Our workaround for this is to send over a raw
-    // WM_LBUTTONDOWN/WM_LBUTTONUP combination to the last focus window, which
-    // does the trick.
-    if (dummy_window_for_activation_ != ::GetFocus()) {
-      INPUT input_info = {0};
-      input_info.type = INPUT_MOUSE;
-      input_info.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
-      ::SendInput(1, &input_info, sizeof(INPUT));
-
-      input_info.type = INPUT_MOUSE;
-      input_info.mi.dwFlags = MOUSEEVENTF_LEFTUP;
-      ::SendInput(1, &input_info, sizeof(INPUT));
-    } else {
-      ::SetFocus(last_focus_window);
-    }
-  }
   return ret;
 }
 
-
-void WebPluginDelegateImpl::OnModalLoopEntered() {
-  DCHECK(handle_event_pump_messages_event_ != NULL);
-  SetEvent(handle_event_pump_messages_event_);
-
-  base::MessageLoop::current()->SetNestableTasksAllowed(true);
-  base::MessageLoop::current()->set_os_modal_loop(true);
-
-  UnhookWindowsHookEx(handle_event_message_filter_hook_);
-  handle_event_message_filter_hook_ = NULL;
-}
-
-bool WebPluginDelegateImpl::ShouldTrackEventForModalLoops(NPEvent* event) {
-  if (event->event == WM_RBUTTONDOWN)
-    return true;
-  return false;
-}
-
-BOOL WINAPI WebPluginDelegateImpl::TrackPopupMenuPatch(
-    HMENU menu, unsigned int flags, int x, int y, int reserved,
-    HWND window, const RECT* rect) {
-
-  if (g_current_plugin_instance) {
-    unsigned long window_process_id = 0;
-    unsigned long window_thread_id =
-        GetWindowThreadProcessId(window, &window_process_id);
-    // TrackPopupMenu fails if the window passed in belongs to a different
-    // thread.
-    if (::GetCurrentThreadId() != window_thread_id) {
-      bool valid =
-          GetParent(g_current_plugin_instance->dummy_window_for_activation_) !=
-              GetDesktopWindow();
-      if (valid) {
-        window = g_current_plugin_instance->dummy_window_for_activation_;
-      } else {
-        NOTREACHED() << "Dummy window not parented";
-      }
-    }
-  }
-
-  BOOL result = TrackPopupMenu(menu, flags, x, y, reserved, window, rect);
-  return result;
-}
-
-HCURSOR WINAPI WebPluginDelegateImpl::SetCursorPatch(HCURSOR cursor) {
-  // The windowless flash plugin periodically calls SetCursor in a wndproc
-  // instantiated on the plugin thread. This causes annoying cursor flicker
-  // when the mouse is moved on a foreground tab, with a windowless plugin
-  // instance in a background tab. We just ignore the call here.
-  if (!g_current_plugin_instance) {
-    HCURSOR current_cursor = GetCursor();
-    if (current_cursor != cursor) {
-      ::SetCursor(cursor);
-    }
-    return current_cursor;
-  }
-  return ::SetCursor(cursor);
-}
-
-LONG WINAPI WebPluginDelegateImpl::RegEnumKeyExWPatch(
-    HKEY key, DWORD index, LPWSTR name, LPDWORD name_size, LPDWORD reserved,
-    LPWSTR class_name, LPDWORD class_size, PFILETIME last_write_time) {
-  DWORD orig_size = *name_size;
-  LONG rv = RegEnumKeyExW(key, index, name, name_size, reserved, class_name,
-                          class_size, last_write_time);
-  if (rv == ERROR_SUCCESS &&
-      GetKeyPath(key).find(L"Microsoft\\MediaPlayer\\ShimInclusionList") !=
-          std::wstring::npos) {
-    static const wchar_t kChromeExeName[] = L"chrome.exe";
-    wcsncpy_s(name, orig_size, kChromeExeName, arraysize(kChromeExeName));
-    *name_size =
-        std::min(orig_size, static_cast<DWORD>(arraysize(kChromeExeName)));
-  }
-
-  return rv;
-}
-
-void WebPluginDelegateImpl::ImeCompositionUpdated(
-    const base::string16& text,
-    const std::vector<int>& clauses,
-    const std::vector<int>& target,
-    int cursor_position) {
-  if (!plugin_ime_)
-    plugin_ime_.reset(new WebPluginIMEWin);
-
-  plugin_ime_->CompositionUpdated(text, clauses, target, cursor_position);
-  plugin_ime_->SendEvents(instance());
-}
-
-void WebPluginDelegateImpl::ImeCompositionCompleted(
-    const base::string16& text) {
-  if (!plugin_ime_)
-    plugin_ime_.reset(new WebPluginIMEWin);
-  plugin_ime_->CompositionCompleted(text);
-  plugin_ime_->SendEvents(instance());
-}
-
-bool WebPluginDelegateImpl::GetIMEStatus(int* input_type,
-                                         gfx::Rect* caret_rect) {
-  if (!plugin_ime_)
-    return false;
-  return plugin_ime_->GetStatus(input_type, caret_rect);
-}
-
-// static
-FARPROC WINAPI WebPluginDelegateImpl::GetProcAddressPatch(HMODULE module,
-                                                          LPCSTR name) {
-  FARPROC imm_function = WebPluginIMEWin::GetProcAddress(name);
-  if (imm_function)
-    return imm_function;
-  return ::GetProcAddress(module, name);
-}
-
-HWND WINAPI WebPluginDelegateImpl::WindowFromPointPatch(POINT point) {
-  HWND window = WindowFromPoint(point);
-  if (::ScreenToClient(window, &point)) {
-    HWND child = ChildWindowFromPoint(window, point);
-    if (::IsWindow(child) &&
-        ::GetProp(child, content::kPluginDummyParentProperty))
-      return child;
-  }
-  return window;
-}
-
 }  // namespace content
diff --git a/content/child/npapi/webplugin_ime_win.cc b/content/child/npapi/webplugin_ime_win.cc
deleted file mode 100644
index 75234959..0000000
--- a/content/child/npapi/webplugin_ime_win.cc
+++ /dev/null
@@ -1,314 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/npapi/webplugin_ime_win.h"
-
-#include <stddef.h>
-#include <string.h>
-
-#include <cstring>
-#include <string>
-#include <vector>
-
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/lock.h"
-#include "content/child/npapi/plugin_instance.h"
-#include "content/common/plugin_constants_win.h"
-
-#pragma comment(lib, "imm32.lib")
-
-namespace content {
-
-// A critical section that prevents two or more plugins from accessing a
-// WebPluginIMEWin instance through our patch function.
-base::LazyInstance<base::Lock>::Leaky
-    g_webplugin_ime_lock = LAZY_INSTANCE_INITIALIZER;
-
-WebPluginIMEWin* WebPluginIMEWin::instance_ = NULL;
-
-WebPluginIMEWin::WebPluginIMEWin()
-    : cursor_position_(0),
-      delta_start_(0),
-      composing_text_(false),
-      support_ime_messages_(false),
-      status_updated_(false),
-      input_type_(1) {
-  memset(result_clauses_, 0, sizeof(result_clauses_));
-}
-
-WebPluginIMEWin::~WebPluginIMEWin() {
-}
-
-void WebPluginIMEWin::CompositionUpdated(const base::string16& text,
-                                         std::vector<int> clauses,
-                                         std::vector<int> target,
-                                         int cursor_position) {
-  // Send a WM_IME_STARTCOMPOSITION message when a user starts a composition.
-  NPEvent np_event;
-  if (!composing_text_) {
-    composing_text_ = true;
-    result_text_.clear();
-
-    np_event.event = WM_IME_STARTCOMPOSITION;
-    np_event.wParam = 0;
-    np_event.lParam = 0;
-    events_.push_back(np_event);
-  }
-
-  // We can update the following values from this event: GCS_COMPSTR,
-  // GCS_COMPATTR, GCSCOMPCLAUSE, GCS_CURSORPOS, and GCS_DELTASTART. We send a
-  // WM_IME_COMPOSITION message to notify the list of updated values.
-  np_event.event = WM_IME_COMPOSITION;
-  np_event.wParam = 0;
-  np_event.lParam = GCS_COMPSTR | GCS_COMPATTR | GCS_COMPCLAUSE |
-      GCS_CURSORPOS | GCS_DELTASTART;
-  events_.push_back(np_event);
-
-  // Converts this event to the IMM32 data so we do not have to convert it every
-  // time when a plugin call an IMM32 function.
-  composition_text_ = text;
-
-  // Create the composition clauses returned when a plugin calls
-  // ImmGetCompositionString() with GCS_COMPCLAUSE.
-  composition_clauses_.clear();
-  for (size_t i = 0; i < clauses.size(); ++i)
-    composition_clauses_.push_back(clauses[i]);
-
-  // Create the composition attributes used by GCS_COMPATTR.
-  if (target.size() == 2) {
-    composition_attributes_.assign(text.length(), ATTR_CONVERTED);
-    for (int i = target[0]; i < target[1]; ++i)
-        composition_attributes_[i] = ATTR_TARGET_CONVERTED;
-  } else {
-    composition_attributes_.assign(text.length(), ATTR_INPUT);
-  }
-
-  cursor_position_ = cursor_position;
-  delta_start_ = cursor_position;
-}
-
-void WebPluginIMEWin::CompositionCompleted(const base::string16& text) {
-  composing_text_ = false;
-
-  // We should update the following values when we finish a composition:
-  // GCS_RESULTSTR, GCS_RESULTCLAUSE, GCS_CURSORPOS, and GCS_DELTASTART. We
-  // send a WM_IME_COMPOSITION message to notify the list of updated values.
-  NPEvent np_event;
-  np_event.event = WM_IME_COMPOSITION;
-  np_event.wParam = 0;
-  np_event.lParam = GCS_CURSORPOS | GCS_DELTASTART | GCS_RESULTSTR |
-      GCS_RESULTCLAUSE;
-  events_.push_back(np_event);
-
-  // We also send a WM_IME_ENDCOMPOSITION message after the final
-  // WM_IME_COMPOSITION message (i.e. after finishing a composition).
-  np_event.event = WM_IME_ENDCOMPOSITION;
-  np_event.wParam = 0;
-  np_event.lParam = 0;
-  events_.push_back(np_event);
-
-  // If the target plugin does not seem to support IME messages, we send
-  // each character in IME text with a WM_CHAR message so the plugin can
-  // insert the IME text.
-  if (!support_ime_messages_) {
-    np_event.event = WM_CHAR;
-    np_event.wParam = 0;
-    np_event.lParam = 0;
-    for (size_t i = 0; i < result_text_.length(); ++i) {
-      np_event.wParam = result_text_[i];
-      events_.push_back(np_event);
-    }
-  }
-
-  // Updated the result text and its clause. (Unlike composition clauses, a
-  // result clause consists of only one region.)
-  result_text_ = text;
-
-  result_clauses_[0] = 0;
-  result_clauses_[1] = result_text_.length();
-
-  cursor_position_ = result_clauses_[1];
-  delta_start_ = result_clauses_[1];
-}
-
-bool WebPluginIMEWin::SendEvents(PluginInstance* instance) {
-  // We allow the patch functions to access this WebPluginIMEWin instance only
-  // while we send IME events to the plugin.
-  ScopedLock lock(this);
-
-  bool ret = true;
-  for (std::vector<NPEvent>::iterator it = events_.begin();
-       it != events_.end(); ++it) {
-    if (!instance->NPP_HandleEvent(&(*it)))
-      ret = false;
-  }
-
-  events_.clear();
-  return ret;
-}
-
-bool WebPluginIMEWin::GetStatus(int* input_type, gfx::Rect* caret_rect) {
-  *input_type = input_type_;
-  *caret_rect = caret_rect_;
-  return true;
-}
-
-// static
-FARPROC WebPluginIMEWin::GetProcAddress(LPCSTR name) {
-  static const struct {
-    const char* name;
-    FARPROC function;
-  } kImm32Functions[] = {
-    { "ImmAssociateContextEx",
-        reinterpret_cast<FARPROC>(ImmAssociateContextEx) },
-    { "ImmGetCompositionStringW",
-        reinterpret_cast<FARPROC>(ImmGetCompositionStringW) },
-    { "ImmGetContext", reinterpret_cast<FARPROC>(ImmGetContext) },
-    { "ImmReleaseContext", reinterpret_cast<FARPROC>(ImmReleaseContext) },
-    { "ImmSetCandidateWindow",
-        reinterpret_cast<FARPROC>(ImmSetCandidateWindow) },
-    { "ImmSetOpenStatus", reinterpret_cast<FARPROC>(ImmSetOpenStatus) },
-  };
-  for (size_t i = 0; i < arraysize(kImm32Functions); ++i) {
-    if (!lstrcmpiA(name, kImm32Functions[i].name))
-      return kImm32Functions[i].function;
-  }
-  return NULL;
-}
-
-void WebPluginIMEWin::Lock() {
-  g_webplugin_ime_lock.Pointer()->Acquire();
-  instance_ = this;
-}
-
-void WebPluginIMEWin::Unlock() {
-  instance_ = NULL;
-  g_webplugin_ime_lock.Pointer()->Release();
-}
-
-// static
-WebPluginIMEWin* WebPluginIMEWin::GetInstance(HIMC context) {
-  return instance_ && context == reinterpret_cast<HIMC>(instance_) ?
-      instance_ : NULL;
-}
-
-// static
-BOOL WINAPI WebPluginIMEWin::ImmAssociateContextEx(HWND window,
-                                                   HIMC context,
-                                                   DWORD flags) {
-  WebPluginIMEWin* instance = GetInstance(context);
-  if (!instance)
-    return ::ImmAssociateContextEx(window, context, flags);
-
-  int input_type = !context && !flags;
-  instance->input_type_ = input_type;
-  instance->status_updated_ = true;
-  return TRUE;
-}
-
-// static
-LONG WINAPI WebPluginIMEWin::ImmGetCompositionStringW(HIMC context,
-                                                      DWORD index,
-                                                      LPVOID dst_data,
-                                                      DWORD dst_size) {
-  WebPluginIMEWin* instance = GetInstance(context);
-  if (!instance)
-    return ::ImmGetCompositionStringW(context, index, dst_data, dst_size);
-
-  const void* src_data = NULL;
-  DWORD src_size = 0;
-  switch (index) {
-    case GCS_COMPSTR:
-      src_data = instance->composition_text_.c_str();
-      src_size = instance->composition_text_.length() * sizeof(wchar_t);
-      break;
-
-    case GCS_COMPATTR:
-      src_data = instance->composition_attributes_.c_str();
-      src_size = instance->composition_attributes_.length();
-      break;
-
-    case GCS_COMPCLAUSE:
-      src_data = &instance->composition_clauses_[0];
-      src_size = instance->composition_clauses_.size() * sizeof(uint32_t);
-      break;
-
-    case GCS_CURSORPOS:
-      return instance->cursor_position_;
-
-    case GCS_DELTASTART:
-      return instance->delta_start_;
-
-    case GCS_RESULTSTR:
-      src_data = instance->result_text_.c_str();
-      src_size = instance->result_text_.length() * sizeof(wchar_t);
-      break;
-
-    case GCS_RESULTCLAUSE:
-      src_data = &instance->result_clauses_[0];
-      src_size = sizeof(instance->result_clauses_);
-      break;
-
-    default:
-      break;
-  }
-  if (!src_data || !src_size)
-    return IMM_ERROR_NODATA;
-
-  if (dst_size >= src_size)
-    memcpy(dst_data, src_data, src_size);
-
-  return src_size;
-}
-
-// static
-HIMC WINAPI WebPluginIMEWin::ImmGetContext(HWND window) {
-  WebPluginIMEWin* instance = instance_;
-  if (instance)
-    instance->support_ime_messages_ = true;
-  return reinterpret_cast<HIMC>(instance);
-}
-
-// static
-BOOL WINAPI WebPluginIMEWin::ImmReleaseContext(HWND window, HIMC context) {
-  if (!GetInstance(context))
-    return ::ImmReleaseContext(window, context);
-  return TRUE;
-}
-
-// static
-BOOL WINAPI WebPluginIMEWin::ImmSetCandidateWindow(HIMC context,
-                                                   CANDIDATEFORM* candidate) {
-  WebPluginIMEWin* instance = GetInstance(context);
-  if (!instance)
-    return ::ImmSetCandidateWindow(context, candidate);
-
-  gfx::Rect caret_rect(candidate->rcArea);
-  if ((candidate->dwStyle & CFS_EXCLUDE) &&
-      instance->caret_rect_ != caret_rect) {
-    instance->caret_rect_ = caret_rect;
-    instance->status_updated_ = true;
-  }
-  return TRUE;
-}
-
-// static
-BOOL WINAPI WebPluginIMEWin::ImmSetOpenStatus(HIMC context, BOOL open) {
-  WebPluginIMEWin* instance = GetInstance(context);
-  if (!instance)
-    return ::ImmSetOpenStatus(context, open);
-
-  int input_type = open ? 1 : 0;
-  if (instance->input_type_ != input_type) {
-    instance->input_type_ = input_type;
-    instance->status_updated_ = true;
-  }
-
-  return TRUE;
-}
-
-}  // namespace content
diff --git a/content/child/npapi/webplugin_ime_win.h b/content/child/npapi/webplugin_ime_win.h
deleted file mode 100644
index 006705eb..0000000
--- a/content/child/npapi/webplugin_ime_win.h
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_NPAPI_WEBPLUGIN_IME_WIN_H_
-#define CONTENT_CHILD_NPAPI_WEBPLUGIN_IME_WIN_H_
-
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/strings/string16.h"
-#include "third_party/npapi/bindings/npapi.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace content {
-
-class PluginInstance;
-
-// A class that emulates an IME for windowless plugins. A windowless plugin
-// does not have a window. Therefore, we cannot attach an IME to a windowless
-// plugin. To allow such windowless plugins to use IMEs without any changes to
-// them, this class receives the IME data from a browser and patches IMM32
-// functions to return the IME data when a windowless plugin calls IMM32
-// functions. I would not Flash retrieves pointers to IMM32 functions with
-// GetProcAddress(), this class also needs a hook to GetProcAddress() to
-// dispatch IMM32 function calls from a plugin to this class as listed in the
-// following snippet.
-//
-//   FARPROC WINAPI GetProcAddressPatch(HMODULE module, LPCSTR name) {
-//     FARPROC* proc = WebPluginIMEWin::GetProcAddress(name);
-//     if (proc)
-//       return proc;
-//     return ::GetProcAddress(module, name);
-//   }
-//   ...
-//   app::win::IATPatchFunction get_proc_address;
-//   get_proc_address.Patch(
-//       GetPluginPath().value().c_str(), "kernel32.dll", "GetProcAddress",
-//       GetProcAddressPatch);
-//
-// After we successfuly dispatch IMM32 calls from a plugin to this class, we
-// need to update its IME data so the class can return it to the plugin through
-// its IMM32 calls. To update the IME data, we call CompositionUpdated() or
-// CompositionCompleted() BEFORE sending an IMM32 Window message to the plugin
-// with a SendEvents() call as listed in the following snippet. (Plugins call
-// IMM32 functions when it receives IMM32 window messages. We need to update the
-// IME data of this class before sending IMM32 messages so the plugins can get
-// the latest data.)
-//
-//   WebPluginIMEWin ime;
-//   ...
-//   base::string16 text = "composing";
-//   std::vector<int> clauses;
-//   clauses.push_back(0);
-//   clauses.push_back(text.length());
-//   std::vector<int> target;
-//   ime.CompositionUpdated(text, clauses, target, text.length());
-//   ime.SendEvents(instance());
-//
-//   base::string16 result = "result";
-//   ime.CompositionCompleted(result);
-//   ime.SendEvents(instance());
-//
-// This class also provides GetStatus() so we can retrieve the IME status
-// changed by a plugin with IMM32 functions. This function is mainly used for
-// retrieving the position of a caret.
-//
-class WebPluginIMEWin {
- public:
-  // A simple class that allows a plugin to access a WebPluginIMEWin instance
-  // only in a scope.
-  class ScopedLock {
-   public:
-    explicit ScopedLock(WebPluginIMEWin* instance) : instance_(instance) {
-      if (instance_)
-        instance_->Lock();
-    }
-    ~ScopedLock() {
-      if (instance_)
-        instance_->Unlock();
-    }
-
-   private:
-    WebPluginIMEWin* instance_;
-  };
-
-  WebPluginIMEWin();
-  ~WebPluginIMEWin();
-
-  // Sends raw IME events sent from a browser to this IME emulator and updates
-  // the list of Windows events to be sent to a plugin. A raw IME event is
-  // mapped to two or more Windows events and it is not so trivial to send these
-  // Windows events to a plugin. This function inserts Windows events in the
-  // order expected by a plugin.
-  void CompositionUpdated(const base::string16& text,
-                          std::vector<int> clauses,
-                          std::vector<int> target,
-                          int cursor_position);
-  void CompositionCompleted(const base::string16& text);
-
-  // Send all the events added in Update() to a plugin.
-  bool SendEvents(PluginInstance* instance);
-
-  // Retrieves the status of this IME emulator.
-  bool GetStatus(int* input_type, gfx::Rect* caret_rect);
-
-  // Returns the pointers to IMM32-emulation functions implemented by this
-  // class. This function is used for over-writing the ones returned from
-  // GetProcAddress() calls of Win32 API.
-  static FARPROC GetProcAddress(const char* name);
-
- private:
-  // Allow (or disallow) the patch functions to use this WebPluginIMEWin
-  // instance through our patch functions. Our patch functions need a static
-  // member variable |instance_| to access a WebPluginIMEWIn instance. We lock
-  // this static variable to prevent two or more plugins from accessing a
-  // WebPluginIMEWin instance.
-  void Lock();
-  void Unlock();
-
-  // Retrieve the instance of this class.
-  static WebPluginIMEWin* GetInstance(HIMC context);
-
-  // IMM32 patch functions implemented by this class.
-  static BOOL WINAPI ImmAssociateContextEx(HWND window,
-                                           HIMC context,
-                                           DWORD flags);
-  static LONG WINAPI ImmGetCompositionStringW(HIMC context,
-                                              DWORD index,
-                                              LPVOID dst_data,
-                                              DWORD dst_size);
-  static HIMC WINAPI ImmGetContext(HWND window);
-  static BOOL WINAPI ImmReleaseContext(HWND window, HIMC context);
-  static BOOL WINAPI ImmSetCandidateWindow(HIMC context,
-                                           CANDIDATEFORM* candidate);
-  static BOOL WINAPI ImmSetOpenStatus(HIMC context, BOOL open);
-
-  // a list of NPEvents to be sent to a plugin.
-  std::vector<NPEvent> events_;
-
-  // The return value for GCS_COMPSTR.
-  base::string16 composition_text_;
-
-  // The return value for GCS_RESULTSTR.
-  base::string16 result_text_;
-
-  // The return value for GCS_COMPATTR.
-  std::string composition_attributes_;
-
-  // The return value for GCS_COMPCLAUSE.
-  std::vector<uint32_t> composition_clauses_;
-
-  // The return value for GCS_RESULTCLAUSE.
-  uint32_t result_clauses_[2];
-
-  // The return value for GCS_CURSORPOS.
-  int cursor_position_;
-
-  // The return value for GCS_DELTASTART.
-  int delta_start_;
-
-  // Whether we are composing text. This variable is used for sending a
-  // WM_IME_STARTCOMPOSITION message when we start composing IME text.
-  bool composing_text_;
-
-  // Whether a plugin supports IME messages. When a plugin cannot handle
-  // IME messages, we need to send the IME text with WM_CHAR messages as Windows
-  // does.
-  bool support_ime_messages_;
-
-  // The IME status received from a plugin.
-  bool status_updated_;
-  int input_type_;
-  gfx::Rect caret_rect_;
-
-  // The pointer to the WebPluginIMEWin instance used by patch functions.
-  static WebPluginIMEWin* instance_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_CHILD_NPAPI_WEBPLUGIN_IME_WIN_H_
diff --git a/content/child/plugin_messages.h b/content/child/plugin_messages.h
index f6ceca20..63a0f458 100644
--- a/content/child/plugin_messages.h
+++ b/content/child/plugin_messages.h
@@ -111,17 +111,6 @@
 IPC_MESSAGE_CONTROL1(PluginMsg_ResetModalDialogEvent,
                      int /* render_view_id */)
 
-#if defined(OS_WIN)
-IPC_MESSAGE_ROUTED4(PluginMsg_ImeCompositionUpdated,
-                    base::string16 /* text */,
-                    std::vector<int> /* clauses */,
-                    std::vector<int>, /* target */
-                    int /* cursor_position */)
-
-IPC_MESSAGE_ROUTED1(PluginMsg_ImeCompositionCompleted,
-                    base::string16 /* text */)
-#endif
-
 #if defined(OS_MACOSX)
 IPC_MESSAGE_ROUTED1(PluginMsg_SetWindowFocus,
                     bool /* has_focus */)
@@ -182,26 +171,6 @@
 
 IPC_MESSAGE_CONTROL0(PluginHostMsg_PluginShuttingDown)
 
-#if defined(OS_WIN)
-// The modal_loop_pump_messages_event parameter is an event handle which is
-// passed in for windowless plugins and is used to indicate if messages
-// are to be pumped in sync calls to the plugin process. Currently used
-// in HandleEvent calls.
-IPC_SYNC_MESSAGE_ROUTED2_0(PluginHostMsg_SetWindowlessData,
-                           HANDLE /* modal_loop_pump_messages_event */,
-                           gfx::NativeViewId /* dummy_activation_window*/)
-
-// Send the IME status retrieved from a windowless plugin. A windowless plugin
-// uses the IME attached to a browser process as a renderer does. A plugin
-// sends this message to control the IME status of a browser process. I would
-// note that a plugin sends this message to a renderer process that hosts this
-// plugin (not directly to a browser process) so the renderer process can
-// update its IME status.
-IPC_MESSAGE_ROUTED2(PluginHostMsg_NotifyIMEStatus,
-                    int /* input_type */,
-                    gfx::Rect /* caret_rect */)
-#endif
-
 #if defined(OS_MACOSX)
 IPC_MESSAGE_ROUTED1(PluginHostMsg_FocusChanged,
                     bool /* focused */)
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index af698f9..de78d1e 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -65,6 +65,9 @@
   if (command_line.HasSwitch(switches::kEnableWebBluetooth))
     WebRuntimeFeatures::enableWebBluetooth(true);
 
+  if (!base::FeatureList::IsEnabled(features::kWebUsb))
+    WebRuntimeFeatures::enableWebUsb(false);
+
   SetRuntimeFeatureDefaultsForPlatform();
 
   if (command_line.HasSwitch(switches::kDisableDatabases))
diff --git a/content/child/web_database_observer_impl.cc b/content/child/web_database_observer_impl.cc
index c0b1038c..0172152e 100644
--- a/content/child/web_database_observer_impl.cc
+++ b/content/child/web_database_observer_impl.cc
@@ -9,10 +9,14 @@
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string16.h"
 #include "base/thread_task_runner_handle.h"
+#include "content/child/storage_util.h"
 #include "content/common/database_messages.h"
+#include "storage/common/database/database_identifier.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 #include "third_party/sqlite/sqlite3.h"
 
+using blink::WebSecurityOrigin;
 using blink::WebString;
 
 namespace content {
@@ -52,6 +56,13 @@
                                 callsite, kCallsiteHistogramSize); \
     } \
   } while (0)
+
+// TODO(jsbell): Replace with use of url::Origin end-to-end.
+// https://crbug.com/591482
+std::string GetIdentifierFromOrigin(const WebSecurityOrigin& origin) {
+  return storage::GetIdentifierFromOrigin(WebSecurityOriginToGURL(origin));
+}
+
 }  // namespace
 
 WebDatabaseObserverImpl::WebDatabaseObserverImpl(IPC::SyncMessageFilter* sender)
@@ -66,40 +77,35 @@
 }
 
 void WebDatabaseObserverImpl::databaseOpened(
-    const WebString& origin_identifier,
+    const WebSecurityOrigin& origin,
     const WebString& database_name,
     const WebString& database_display_name,
     unsigned long estimated_size) {
-  open_connections_->AddOpenConnection(origin_identifier.utf8(),
-                                       database_name);
+  const std::string origin_identifier = GetIdentifierFromOrigin(origin);
+  open_connections_->AddOpenConnection(origin_identifier, database_name);
   sender_->Send(new DatabaseHostMsg_Opened(
-      origin_identifier.utf8(), database_name,
-      database_display_name, estimated_size));
+      origin_identifier, database_name, database_display_name, estimated_size));
 }
 
-void WebDatabaseObserverImpl::databaseModified(
-    const WebString& origin_identifier,
-    const WebString& database_name) {
-  sender_->Send(new DatabaseHostMsg_Modified(
-      origin_identifier.utf8(), database_name));
+void WebDatabaseObserverImpl::databaseModified(const WebSecurityOrigin& origin,
+                                               const WebString& database_name) {
+  sender_->Send(new DatabaseHostMsg_Modified(GetIdentifierFromOrigin(origin),
+                                             database_name));
 }
 
-void WebDatabaseObserverImpl::databaseClosed(
-    const WebString& origin_identifier,
-    const WebString& database_name) {
+void WebDatabaseObserverImpl::databaseClosed(const WebSecurityOrigin& origin,
+                                             const WebString& database_name) {
   DCHECK(!main_thread_task_runner_->RunsTasksOnCurrentThread());
+  const std::string origin_identifier = GetIdentifierFromOrigin(origin);
   main_thread_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(
-          base::IgnoreResult(&IPC::SyncMessageFilter::Send),
-          sender_,
-          new DatabaseHostMsg_Closed(origin_identifier.utf8(), database_name)));
-  open_connections_->RemoveOpenConnection(origin_identifier.utf8(),
-                                          database_name);
+      base::Bind(base::IgnoreResult(&IPC::SyncMessageFilter::Send), sender_,
+                 new DatabaseHostMsg_Closed(origin_identifier, database_name)));
+  open_connections_->RemoveOpenConnection(origin_identifier, database_name);
 }
 
 void WebDatabaseObserverImpl::reportOpenDatabaseResult(
-    const WebString& origin_identifier,
+    const WebSecurityOrigin& origin,
     const WebString& database_name,
     int callsite,
     int websql_error,
@@ -107,7 +113,7 @@
     double call_time) {
   UMA_HISTOGRAM_WEBSQL_RESULT("OpenResult", callsite,
                               websql_error, sqlite_error);
-  HandleSqliteError(origin_identifier, database_name, sqlite_error);
+  HandleSqliteError(origin, database_name, sqlite_error);
 
   if (websql_error == kWebSQLSuccess && sqlite_error == SQLITE_OK) {
     UMA_HISTOGRAM_TIMES("websql.Async.OpenTime.Success",
@@ -119,50 +125,57 @@
 }
 
 void WebDatabaseObserverImpl::reportChangeVersionResult(
-    const WebString& origin_identifier,
+    const WebSecurityOrigin& origin,
     const WebString& database_name,
-    int callsite, int websql_error, int sqlite_error) {
+    int callsite,
+    int websql_error,
+    int sqlite_error) {
   UMA_HISTOGRAM_WEBSQL_RESULT("ChangeVersionResult", callsite,
                               websql_error, sqlite_error);
-  HandleSqliteError(origin_identifier, database_name, sqlite_error);
+  HandleSqliteError(origin, database_name, sqlite_error);
 }
 
 void WebDatabaseObserverImpl::reportStartTransactionResult(
-    const WebString& origin_identifier,
+    const WebSecurityOrigin& origin,
     const WebString& database_name,
-    int callsite, int websql_error, int sqlite_error) {
+    int callsite,
+    int websql_error,
+    int sqlite_error) {
   UMA_HISTOGRAM_WEBSQL_RESULT("BeginResult", callsite,
                               websql_error, sqlite_error);
-  HandleSqliteError(origin_identifier, database_name, sqlite_error);
+  HandleSqliteError(origin, database_name, sqlite_error);
 }
 
 void WebDatabaseObserverImpl::reportCommitTransactionResult(
-    const WebString& origin_identifier,
+    const WebSecurityOrigin& origin,
     const WebString& database_name,
-    int callsite, int websql_error, int sqlite_error) {
+    int callsite,
+    int websql_error,
+    int sqlite_error) {
   UMA_HISTOGRAM_WEBSQL_RESULT("CommitResult", callsite,
                               websql_error, sqlite_error);
-  HandleSqliteError(origin_identifier, database_name, sqlite_error);
+  HandleSqliteError(origin, database_name, sqlite_error);
 }
 
 void WebDatabaseObserverImpl::reportExecuteStatementResult(
-    const WebString& origin_identifier,
+    const WebSecurityOrigin& origin,
     const WebString& database_name,
-    int callsite, int websql_error, int sqlite_error) {
+    int callsite,
+    int websql_error,
+    int sqlite_error) {
   UMA_HISTOGRAM_WEBSQL_RESULT("StatementResult", callsite,
                               websql_error, sqlite_error);
-  HandleSqliteError(origin_identifier, database_name, sqlite_error);
+  HandleSqliteError(origin, database_name, sqlite_error);
 }
 
 void WebDatabaseObserverImpl::reportVacuumDatabaseResult(
-    const WebString& origin_identifier,
+    const WebSecurityOrigin& origin,
     const WebString& database_name,
     int sqlite_error) {
   int result = DetermineHistogramResult(-1, sqlite_error);
   UMA_HISTOGRAM_ENUMERATION("websql.Async.VacuumResult",
                               result, kResultHistogramSize);
-
-  HandleSqliteError(origin_identifier, database_name, sqlite_error);
+  HandleSqliteError(origin, database_name, sqlite_error);
 }
 
 bool WebDatabaseObserverImpl::WaitForAllDatabasesToClose(
@@ -171,18 +184,15 @@
   return open_connections_->WaitForAllDatabasesToClose(timeout);
 }
 
-void WebDatabaseObserverImpl::HandleSqliteError(
-    const WebString& origin_identifier,
-    const WebString& database_name,
-    int error) {
+void WebDatabaseObserverImpl::HandleSqliteError(const WebSecurityOrigin& origin,
+                                                const WebString& database_name,
+                                                int error) {
   // We filter out errors which the backend doesn't act on to avoid
   // a unnecessary ipc traffic, this method can get called at a fairly
   // high frequency (per-sqlstatement).
   if (error == SQLITE_CORRUPT || error == SQLITE_NOTADB) {
     sender_->Send(new DatabaseHostMsg_HandleSqliteError(
-        origin_identifier.utf8(),
-        database_name,
-        error));
+        GetIdentifierFromOrigin(origin), database_name, error));
   }
 }
 
diff --git a/content/child/web_database_observer_impl.h b/content/child/web_database_observer_impl.h
index ff283fb..236ae853 100644
--- a/content/child/web_database_observer_impl.h
+++ b/content/child/web_database_observer_impl.h
@@ -22,48 +22,48 @@
   explicit WebDatabaseObserverImpl(IPC::SyncMessageFilter* sender);
   virtual ~WebDatabaseObserverImpl();
 
-  void databaseOpened(const blink::WebString& origin_identifier,
+  void databaseOpened(const blink::WebSecurityOrigin& origin,
                       const blink::WebString& database_name,
                       const blink::WebString& database_display_name,
                       unsigned long estimated_size) override;
-  void databaseModified(const blink::WebString& origin_identifier,
+  void databaseModified(const blink::WebSecurityOrigin& origin,
                         const blink::WebString& database_name) override;
-  void databaseClosed(const blink::WebString& origin_identifier,
+  void databaseClosed(const blink::WebSecurityOrigin& origin,
                       const blink::WebString& database_name) override;
-  void reportOpenDatabaseResult(const blink::WebString& origin_identifier,
+  void reportOpenDatabaseResult(const blink::WebSecurityOrigin& origin,
                                 const blink::WebString& database_name,
                                 int callsite,
                                 int websql_error,
                                 int sqlite_error,
                                 double call_time) override;
-  void reportChangeVersionResult(const blink::WebString& origin_identifier,
+  void reportChangeVersionResult(const blink::WebSecurityOrigin& origin,
                                  const blink::WebString& database_name,
                                  int callsite,
                                  int websql_error,
                                  int sqlite_error) override;
-  void reportStartTransactionResult(const blink::WebString& origin_identifier,
+  void reportStartTransactionResult(const blink::WebSecurityOrigin& origin,
                                     const blink::WebString& database_name,
                                     int callsite,
                                     int websql_error,
                                     int sqlite_error) override;
-  void reportCommitTransactionResult(const blink::WebString& origin_identifier,
+  void reportCommitTransactionResult(const blink::WebSecurityOrigin& origin,
                                      const blink::WebString& database_name,
                                      int callsite,
                                      int websql_error,
                                      int sqlite_error) override;
-  void reportExecuteStatementResult(const blink::WebString& origin_identifier,
+  void reportExecuteStatementResult(const blink::WebSecurityOrigin& origin,
                                     const blink::WebString& database_name,
                                     int callsite,
                                     int websql_error,
                                     int sqlite_error) override;
-  void reportVacuumDatabaseResult(const blink::WebString& origin_identifier,
+  void reportVacuumDatabaseResult(const blink::WebSecurityOrigin& origin,
                                   const blink::WebString& database_name,
                                   int sqlite_error) override;
 
   bool WaitForAllDatabasesToClose(base::TimeDelta timeout);
 
  private:
-  void HandleSqliteError(const blink::WebString& origin_identifier,
+  void HandleSqliteError(const blink::WebSecurityOrigin& origin,
                          const blink::WebString& database_name,
                          int error);
 
diff --git a/content/common/DEPS b/content/common/DEPS
index e3623a7..caf3f5d1 100644
--- a/content/common/DEPS
+++ b/content/common/DEPS
@@ -65,10 +65,3 @@
   "+third_party/WebKit/public/web/mac/WebScrollbarTheme.h",
   "+third_party/WebKit/public/web/win/WebFontRendering.h"
 ]
-
-specific_include_rules = {
-# Java bridge code passes NPAPI types to the browser process. Crazy!
-  "java_bridge_messages\.h": [
-    "+content/child"
-  ]
-}
diff --git a/content/common/android/sync_compositor_messages.cc b/content/common/android/sync_compositor_messages.cc
index 638483e3..1423091b 100644
--- a/content/common/android/sync_compositor_messages.cc
+++ b/content/common/android/sync_compositor_messages.cc
@@ -8,6 +8,7 @@
 
 SyncCompositorCommonBrowserParams::SyncCompositorCommonBrowserParams()
     : bytes_limit(0u),
+      output_surface_id_for_returned_resources(0u),
       update_root_scroll_offset(false),
       begin_frame_source_paused(false) {}
 
diff --git a/content/common/android/sync_compositor_messages.h b/content/common/android/sync_compositor_messages.h
index 0ad1cf1..2e9af1a 100644
--- a/content/common/android/sync_compositor_messages.h
+++ b/content/common/android/sync_compositor_messages.h
@@ -26,6 +26,7 @@
   ~SyncCompositorCommonBrowserParams();
 
   uint32_t bytes_limit;
+  uint32_t output_surface_id_for_returned_resources;
   cc::CompositorFrameAck ack;
   gfx::ScrollOffset root_scroll_offset;
   bool update_root_scroll_offset;
@@ -96,6 +97,7 @@
 
 IPC_STRUCT_TRAITS_BEGIN(content::SyncCompositorCommonBrowserParams)
   IPC_STRUCT_TRAITS_MEMBER(bytes_limit)
+  IPC_STRUCT_TRAITS_MEMBER(output_surface_id_for_returned_resources)
   IPC_STRUCT_TRAITS_MEMBER(ack)
   IPC_STRUCT_TRAITS_MEMBER(root_scroll_offset)
   IPC_STRUCT_TRAITS_MEMBER(update_root_scroll_offset)
@@ -153,10 +155,11 @@
                     content::SyncCompositorCommonBrowserParams,
                     base::TimeTicks);
 
-IPC_SYNC_MESSAGE_ROUTED2_2(SyncCompositorMsg_DemandDrawHw,
+IPC_SYNC_MESSAGE_ROUTED2_3(SyncCompositorMsg_DemandDrawHw,
                            content::SyncCompositorCommonBrowserParams,
                            content::SyncCompositorDemandDrawHwParams,
                            content::SyncCompositorCommonRendererParams,
+                           uint32_t /* output_surface_id */,
                            cc::CompositorFrame)
 
 IPC_SYNC_MESSAGE_ROUTED2_2(SyncCompositorMsg_SetSharedMemory,
diff --git a/content/common/child_process_messages.h b/content/common/child_process_messages.h
index 611296d..9476f1a 100644
--- a/content/common/child_process_messages.h
+++ b/content/common/child_process_messages.h
@@ -17,7 +17,7 @@
 #include "cc/resources/shared_bitmap_manager.h"
 #include "content/common/content_export.h"
 #include "content/common/content_param_traits_macros.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
 #include "content/common/host_discardable_shared_memory_manager.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "gpu/ipc/common/gpu_param_traits_macros.h"
diff --git a/content/common/content_message_generator.h b/content/common/content_message_generator.h
index e6b3022..595684e 100644
--- a/content/common/content_message_generator.h
+++ b/content/common/content_message_generator.h
@@ -29,6 +29,7 @@
 #include "content/common/gamepad_messages.h"
 #include "content/common/geofencing_messages.h"
 #include "content/common/gpu/media/media_messages.h"
+#include "content/common/gpu_host_messages.h"
 #include "content/common/indexed_db/indexed_db_messages.h"
 #include "content/common/input_messages.h"
 #include "content/common/manifest_manager_messages.h"
diff --git a/content/gpu/establish_channel_params.cc b/content/common/establish_channel_params.cc
similarity index 89%
rename from content/gpu/establish_channel_params.cc
rename to content/common/establish_channel_params.cc
index 770c3bf..6ca5ac6 100644
--- a/content/gpu/establish_channel_params.cc
+++ b/content/common/establish_channel_params.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/gpu/establish_channel_params.h"
+#include "content/common/establish_channel_params.h"
 
 namespace content {
 
diff --git a/content/gpu/establish_channel_params.h b/content/common/establish_channel_params.h
similarity index 76%
rename from content/gpu/establish_channel_params.h
rename to content/common/establish_channel_params.h
index a416bff..f77b1bd 100644
--- a/content/gpu/establish_channel_params.h
+++ b/content/common/establish_channel_params.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_GPU_ESTABLISH_CHANNEL_PARAMS_H_
-#define CONTENT_GPU_ESTABLISH_CHANNEL_PARAMS_H_
+#ifndef CONTENT_COMMON_ESTABLISH_CHANNEL_PARAMS_H_
+#define CONTENT_COMMON_ESTABLISH_CHANNEL_PARAMS_H_
 
 #include <stdint.h>
 
@@ -24,4 +24,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_GPU_ESTABLISH_CHANNEL_PARAMS_H_
+#endif  // CONTENT_COMMON_ESTABLISH_CHANNEL_PARAMS_H_
diff --git a/content/common/gpu/client/gpu_channel_host.h b/content/common/gpu/client/gpu_channel_host.h
index 4d6716f..ab879de3 100644
--- a/content/common/gpu/client/gpu_channel_host.h
+++ b/content/common/gpu/client/gpu_channel_host.h
@@ -20,7 +20,6 @@
 #include "base/process/process.h"
 #include "base/synchronization/lock.h"
 #include "content/common/content_export.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
 #include "gpu/config/gpu_info.h"
 #include "gpu/ipc/common/gpu_stream_constants.h"
 #include "gpu/ipc/common/surface_handle.h"
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc
index ecb252e..ca4689b 100644
--- a/content/common/gpu/gpu_command_buffer_stub.cc
+++ b/content/common/gpu/gpu_command_buffer_stub.cc
@@ -105,7 +105,7 @@
 // url_hash matches.
 void FastSetActiveURL(const GURL& url, size_t url_hash, GpuChannel* channel) {
   // Leave the previously set URL in the empty case -- empty URLs are given by
-  // BlinkPlatformImpl::createOffscreenGraphicsContext3D. Hopefully the
+  // BlinkPlatformImpl::createOffscreenGraphicsContext3DProvider. Hopefully the
   // onscreen context URL was set previously and will show up even when a crash
   // occurs during offscreen command processing.
   if (url.is_empty())
diff --git a/content/common/gpu/media/android_video_decode_accelerator.cc b/content/common/gpu/media/android_video_decode_accelerator.cc
index 5e719f9..d79a7fe 100644
--- a/content/common/gpu/media/android_video_decode_accelerator.cc
+++ b/content/common/gpu/media/android_video_decode_accelerator.cc
@@ -38,7 +38,6 @@
 #include "ui/gl/gl_bindings.h"
 
 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
-#include "media/base/media_keys.h"
 #include "media/mojo/services/mojo_cdm_service.h"
 #endif
 
@@ -263,6 +262,7 @@
       state_(NO_ERROR),
       picturebuffers_requested_(false),
       gl_decoder_(decoder),
+      media_drm_bridge_cdm_context_(nullptr),
       cdm_registration_id_(0),
       pending_input_buf_index_(-1),
       error_sequence_token_(0),
@@ -285,11 +285,11 @@
   g_avda_timer.Pointer()->StopTimer(this);
 
 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
-  if (cdm_) {
-    DCHECK(cdm_registration_id_);
-    static_cast<media::MediaDrmBridge*>(cdm_.get())
-        ->UnregisterPlayer(cdm_registration_id_);
-  }
+  if (!media_drm_bridge_cdm_context_)
+    return;
+
+  DCHECK(cdm_registration_id_);
+  media_drm_bridge_cdm_context_->UnregisterPlayer(cdm_registration_id_);
 #endif  // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
 }
 
@@ -360,21 +360,22 @@
   DVLOG(2) << __FUNCTION__ << ": " << cdm_id;
 
 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
-  using media::MediaDrmBridge;
-
   DCHECK(client_) << "SetCdm() must be called after Initialize().";
 
-  if (cdm_) {
+  if (media_drm_bridge_cdm_context_) {
     NOTREACHED() << "We do not support resetting CDM.";
     NotifyCdmAttached(false);
     return;
   }
 
-  cdm_ = media::MojoCdmService::LegacyGetCdm(cdm_id);
-  DCHECK(cdm_);
+  // Store the CDM to hold a reference to it.
+  cdm_for_reference_holding_only_ = media::MojoCdmService::LegacyGetCdm(cdm_id);
+  DCHECK(cdm_for_reference_holding_only_);
 
-  // On Android platform the MediaKeys will be its subclass MediaDrmBridge.
-  MediaDrmBridge* drm_bridge = static_cast<MediaDrmBridge*>(cdm_.get());
+  // On Android platform the CdmContext must be a MediaDrmBridgeCdmContext.
+  media_drm_bridge_cdm_context_ = static_cast<media::MediaDrmBridgeCdmContext*>(
+      cdm_for_reference_holding_only_->GetCdmContext());
+  DCHECK(media_drm_bridge_cdm_context_);
 
   // Register CDM callbacks. The callbacks registered will be posted back to
   // this thread via BindToCurrentLoop.
@@ -384,19 +385,18 @@
   // destructed as well. So the |cdm_unset_cb| will never have a chance to be
   // called.
   // TODO(xhwang): Remove |cdm_unset_cb| after it's not used on all platforms.
-  cdm_registration_id_ =
-      drm_bridge->RegisterPlayer(media::BindToCurrentLoop(base::Bind(
-                                     &AndroidVideoDecodeAccelerator::OnKeyAdded,
-                                     weak_this_factory_.GetWeakPtr())),
-                                 base::Bind(&base::DoNothing));
+  cdm_registration_id_ = media_drm_bridge_cdm_context_->RegisterPlayer(
+      media::BindToCurrentLoop(
+          base::Bind(&AndroidVideoDecodeAccelerator::OnKeyAdded,
+                     weak_this_factory_.GetWeakPtr())),
+      base::Bind(&base::DoNothing));
 
-  drm_bridge->SetMediaCryptoReadyCB(media::BindToCurrentLoop(
+  media_drm_bridge_cdm_context_->SetMediaCryptoReadyCB(media::BindToCurrentLoop(
       base::Bind(&AndroidVideoDecodeAccelerator::OnMediaCryptoReady,
                  weak_this_factory_.GetWeakPtr())));
 
   // Postpone NotifyCdmAttached() call till we create the MediaCodec after
   // OnMediaCryptoReady().
-
 #else
 
   NOTIMPLEMENTED();
@@ -1066,12 +1066,14 @@
 }
 
 void AndroidVideoDecodeAccelerator::OnMediaCryptoReady(
-    media::MediaDrmBridge::JavaObjectPtr media_crypto,
+    media::MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto,
     bool needs_protected_surface) {
   DVLOG(1) << __FUNCTION__;
 
   if (!media_crypto) {
     LOG(ERROR) << "MediaCrypto is not available, can't play encrypted stream.";
+    cdm_for_reference_holding_only_ = nullptr;
+    media_drm_bridge_cdm_context_ = nullptr;
     NotifyCdmAttached(false);
     return;
   }
diff --git a/content/common/gpu/media/android_video_decode_accelerator.h b/content/common/gpu/media/android_video_decode_accelerator.h
index ea4f6e86..cb411e3 100644
--- a/content/common/gpu/media/android_video_decode_accelerator.h
+++ b/content/common/gpu/media/android_video_decode_accelerator.h
@@ -19,7 +19,7 @@
 #include "content/common/content_export.h"
 #include "content/common/gpu/media/avda_state_provider.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "media/base/android/media_drm_bridge.h"
+#include "media/base/android/media_drm_bridge_cdm_context.h"
 #include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/base/media_keys.h"
 #include "media/video/video_decode_accelerator.h"
@@ -182,8 +182,9 @@
   void DecodeBuffer(const media::BitstreamBuffer& bitstream_buffer);
 
   // This callback is called after CDM obtained a MediaCrypto object.
-  void OnMediaCryptoReady(media::MediaDrmBridge::JavaObjectPtr media_crypto,
-                          bool needs_protected_surface);
+  void OnMediaCryptoReady(
+      media::MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto,
+      bool needs_protected_surface);
 
   // This callback is called when a new key is added to CDM.
   void OnKeyAdded();
@@ -310,8 +311,10 @@
 
   // CDM related stuff.
 
-  // Holds a ref-count to the CDM.
-  scoped_refptr<media::MediaKeys> cdm_;
+  // Holds a ref-count to the CDM to avoid using the CDM after it's destroyed.
+  scoped_refptr<media::MediaKeys> cdm_for_reference_holding_only_;
+
+  media::MediaDrmBridgeCdmContext* media_drm_bridge_cdm_context_;
 
   // MediaDrmBridge requires registration/unregistration of the player, this
   // registration id is used for this.
@@ -319,7 +322,7 @@
 
   // The MediaCrypto object is used in the MediaCodec.configure() in case of
   // an encrypted stream.
-  media::MediaDrmBridge::JavaObjectPtr media_crypto_;
+  media::MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto_;
 
   // Index of the dequeued and filled buffer that we keep trying to enqueue.
   // Such buffer appears in MEDIA_CODEC_NO_KEY processing.
diff --git a/content/gpu/gpu_host_messages.h b/content/common/gpu_host_messages.h
similarity index 99%
rename from content/gpu/gpu_host_messages.h
rename to content/common/gpu_host_messages.h
index 7693cac..df61d13 100644
--- a/content/gpu/gpu_host_messages.h
+++ b/content/common/gpu_host_messages.h
@@ -7,8 +7,8 @@
 
 #include "build/build_config.h"
 #include "content/common/content_export.h"
+#include "content/common/establish_channel_params.h"
 #include "content/common/gpu/gpu_memory_uma_stats.h"
-#include "content/gpu/establish_channel_params.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "gpu/command_buffer/common/value_state.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
diff --git a/content/common/gpu/gpu_process_launch_causes.h b/content/common/gpu_process_launch_causes.h
similarity index 87%
rename from content/common/gpu/gpu_process_launch_causes.h
rename to content/common/gpu_process_launch_causes.h
index 1fcdc27..b7acd35 100644
--- a/content/common/gpu/gpu_process_launch_causes.h
+++ b/content/common/gpu_process_launch_causes.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_COMMON_GPU_GPU_PROCESS_LAUNCH_CAUSES_H_
-#define CONTENT_COMMON_GPU_GPU_PROCESS_LAUNCH_CAUSES_H_
+#ifndef CONTENT_COMMON_GPU_PROCESS_LAUNCH_CAUSES_H_
+#define CONTENT_COMMON_GPU_PROCESS_LAUNCH_CAUSES_H_
 
 namespace content {
 
@@ -32,4 +32,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_COMMON_GPU_GPU_PROCESS_LAUNCH_CAUSES_H_
+#endif  // CONTENT_COMMON_GPU_PROCESS_LAUNCH_CAUSES_H_
diff --git a/content/common/mojo/mojo_shell_connection_impl.cc b/content/common/mojo/mojo_shell_connection_impl.cc
index 44310d3..42cfada6 100644
--- a/content/common/mojo/mojo_shell_connection_impl.cc
+++ b/content/common/mojo/mojo_shell_connection_impl.cc
@@ -126,10 +126,6 @@
   return found;
 }
 
-void MojoShellConnectionImpl::ShellConnectionLost() {
-  LOG(ERROR) << "Shell connection lost.";
-}
-
 mojo::Connector* MojoShellConnectionImpl::GetConnector() {
   DCHECK(shell_connection_);
   return shell_connection_->connector();
diff --git a/content/common/mojo/mojo_shell_connection_impl.h b/content/common/mojo/mojo_shell_connection_impl.h
index 52ce78e..49bfefc 100644
--- a/content/common/mojo/mojo_shell_connection_impl.h
+++ b/content/common/mojo/mojo_shell_connection_impl.h
@@ -53,7 +53,6 @@
                   const mojo::Identity& identity,
                   uint32_t id) override;
   bool AcceptConnection(mojo::Connection* connection) override;
-  void ShellConnectionLost() override;
 
   // MojoShellConnection:
   mojo::Connector* GetConnector() override;
diff --git a/content/common/plugin_constants_win.cc b/content/common/plugin_constants_win.cc
index 9330c819..5f2a5cb 100644
--- a/content/common/plugin_constants_win.cc
+++ b/content/common/plugin_constants_win.cc
@@ -6,20 +6,13 @@
 
 namespace content {
 
-const base::char16 kDummyActivationWindowName[] = L"DummyWindowForActivation";
 const base::char16 kRegistryMozillaPlugins[] = L"SOFTWARE\\MozillaPlugins";
 const base::char16 kMozillaActiveXPlugin[] = L"npmozax.dll";
 const base::char16 kNewWMPPlugin[] = L"np-mswmp.dll";
 const base::char16 kOldWMPPlugin[] = L"npdsplay.dll";
 const base::char16 kYahooApplicationStatePlugin[] = L"npystate.dll";
 const base::char16 kWanWangProtocolHandlerPlugin[] = L"npww.dll";
-const base::char16 kFlashPlugin[] = L"npswf32.dll";
-const base::char16 kAcrobatReaderPlugin[] = L"nppdf32.dll";
-const base::char16 kRealPlayerPlugin[] = L"nppl3260.dll";
-const base::char16 kSilverlightPlugin[] = L"npctrl.dll";
 const base::char16 kJavaPlugin1[] = L"npjp2.dll";
 const base::char16 kJavaPlugin2[] = L"npdeploytk.dll";
-const char kGPUPluginMimeType[] = "application/vnd.google.chrome.gpu-plugin";
-const base::char16 kPluginDummyParentProperty[] = L"NPAPIPluginDummyParent";
 
 }  // namespace content
diff --git a/content/common/plugin_constants_win.h b/content/common/plugin_constants_win.h
index 815cbf4..5363868c 100644
--- a/content/common/plugin_constants_win.h
+++ b/content/common/plugin_constants_win.h
@@ -14,8 +14,6 @@
 
 namespace content {
 
-extern const base::char16 kDummyActivationWindowName[];
-
 // The name of the registry key which NPAPI plugins update on installation.
 extern const base::char16 kRegistryMozillaPlugins[];
 
@@ -24,17 +22,9 @@
 extern const base::char16 kOldWMPPlugin[];
 extern const base::char16 kYahooApplicationStatePlugin[];
 extern const base::char16 kWanWangProtocolHandlerPlugin[];
-extern const base::char16 kFlashPlugin[];
-extern const base::char16 kAcrobatReaderPlugin[];
-extern const base::char16 kRealPlayerPlugin[];
-extern const base::char16 kSilverlightPlugin[];
 extern const base::char16 kJavaPlugin1[];
 extern const base::char16 kJavaPlugin2[];
 
-extern const char kGPUPluginMimeType[];
-
-extern const base::char16 kPluginDummyParentProperty[];
-
 }  // namespace content
 
 #endif  // CONTENT_COMMON_PLUGIN_CONSTANTS_WIN_H_
diff --git a/content/common/swapped_out_messages.cc b/content/common/swapped_out_messages.cc
index 6815b1d..718dd08 100644
--- a/content/common/swapped_out_messages.cc
+++ b/content/common/swapped_out_messages.cc
@@ -9,7 +9,6 @@
 #include "content/common/input_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/common/content_client.h"
-#include "content/shell/common/shell_messages.h"
 
 namespace content {
 
@@ -48,9 +47,7 @@
     case FrameHostMsg_DidAssignPageId::ID:
     // A swapped-out frame's opener might be updated with window.open.
     case FrameHostMsg_DidChangeOpener::ID:
-    // Used in layout tests; handled in BlinkTestController.
-    case ShellViewHostMsg_PrintMessage::ID:
-    case ShellViewHostMsg_LayoutDumpFlagsChanged::ID:
+    // For handling pop-ups from cross-site frames.
     case ViewHostMsg_CreateWidget::ID:
       return true;
     default:
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 9346980..a17ad851 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -1055,14 +1055,6 @@
 
 IPC_MESSAGE_ROUTED1(ViewHostMsg_SetCursor, content::WebCursor)
 
-#if defined(OS_WIN)
-IPC_MESSAGE_ROUTED1(ViewHostMsg_WindowlessPluginDummyWindowCreated,
-                    gfx::NativeViewId /* dummy_activation_window */)
-
-IPC_MESSAGE_ROUTED1(ViewHostMsg_WindowlessPluginDummyWindowDestroyed,
-                    gfx::NativeViewId /* dummy_activation_window */)
-#endif
-
 // Get the list of proxies to use for |url|, as a semicolon delimited list
 // of "<TYPE> <HOST>:<PORT>" | "DIRECT".
 IPC_SYNC_MESSAGE_CONTROL1_2(ViewHostMsg_ResolveProxy,
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 945fe25c..a112a3b 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -106,6 +106,7 @@
       'public/browser/android/download_controller_android.cc',
       'public/browser/android/download_controller_android.h',
       'public/browser/android/external_video_surface_container.h',
+      'public/browser/android/synchronous_compositor.cc',
       'public/browser/android/synchronous_compositor.h',
       'public/browser/android/synchronous_compositor_client.h',
       'public/browser/appcache_service.h',
@@ -1994,6 +1995,7 @@
           '-ldinput8.lib',
           '-ldwmapi.lib',
           '-ldxguid.lib',
+          '-limm32.lib',
           '-lsensorsapi.lib',
           '-lportabledeviceguids.lib',
         ],
diff --git a/content/content_child.gypi b/content/content_child.gypi
index eb92f42..ead38e5 100644
--- a/content/content_child.gypi
+++ b/content/content_child.gypi
@@ -180,8 +180,6 @@
       'child/npapi/webplugin_delegate_impl_aura.cc',
       'child/npapi/webplugin_delegate_impl_mac.mm',
       'child/npapi/webplugin_delegate_impl_win.cc',
-      'child/npapi/webplugin_ime_win.cc',
-      'child/npapi/webplugin_ime_win.h',
       'child/npapi/webplugin_resource_client.h',
       'child/permissions/permission_dispatcher.cc',
       'child/permissions/permission_dispatcher.h',
diff --git a/content/content_common.gypi b/content/content_common.gypi
index f8307e7..307703a 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -307,6 +307,8 @@
       'common/dwrite_font_platform_win.cc',
       'common/dwrite_font_proxy_messages.h',
       'common/edit_command.h',
+      'common/establish_channel_params.cc',
+      'common/establish_channel_params.h',
       'common/file_utilities_messages.h',
       'common/fileapi/file_system_messages.h',
       'common/fileapi/webblob_messages.h',
@@ -337,10 +339,17 @@
       'common/geofencing_types.cc',
       'common/geofencing_types.h',
       'common/gin_java_bridge_messages.h',
+      'common/gpu_host_messages.h',
       'common/gpu/accelerated_surface_buffers_swapped_params_mac.cc',
       'common/gpu/accelerated_surface_buffers_swapped_params_mac.h',
       'common/gpu/buffer_presented_params_mac.cc',
       'common/gpu/buffer_presented_params_mac.h',
+      'common/gpu/ca_layer_partial_damage_tree_mac.h',
+      'common/gpu/ca_layer_partial_damage_tree_mac.mm',
+      'common/gpu/ca_layer_tree_mac.h',
+      'common/gpu/ca_layer_tree_mac.mm',
+      'common/gpu/child_window_surface_win.cc',
+      'common/gpu/child_window_surface_win.h',
       'common/gpu/client/command_buffer_metrics.cc',
       'common/gpu/client/command_buffer_metrics.h',
       'common/gpu/client/command_buffer_proxy_impl.cc',
@@ -365,12 +374,6 @@
       'common/gpu/client/grcontext_for_webgraphicscontext3d.h',
       'common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc',
       'common/gpu/client/webgraphicscontext3d_command_buffer_impl.h',
-      'common/gpu/ca_layer_partial_damage_tree_mac.h',
-      'common/gpu/ca_layer_partial_damage_tree_mac.mm',
-      'common/gpu/ca_layer_tree_mac.h',
-      'common/gpu/ca_layer_tree_mac.mm',
-      'common/gpu/child_window_surface_win.cc',
-      'common/gpu/child_window_surface_win.h',
       'common/gpu/gpu_channel.cc',
       'common/gpu/gpu_channel.h',
       'common/gpu/gpu_channel_manager.cc',
@@ -388,7 +391,6 @@
       'common/gpu/gpu_memory_tracking.cc',
       'common/gpu/gpu_memory_tracking.h',
       'common/gpu/gpu_memory_uma_stats.h',
-      'common/gpu/gpu_process_launch_causes.h',
       'common/gpu/gpu_surface_lookup.cc',
       'common/gpu/gpu_surface_lookup.h',
       'common/gpu/gpu_watchdog.h',
@@ -423,6 +425,7 @@
       'common/gpu/pass_through_image_transport_surface.h',
       'common/gpu/stream_texture_android.cc',
       'common/gpu/stream_texture_android.h',
+      'common/gpu_process_launch_causes.h',
       'common/host_discardable_shared_memory_manager.cc',
       'common/host_discardable_shared_memory_manager.h',
       'common/host_shared_bitmap_manager.cc',
diff --git a/content/content_gpu.gypi b/content/content_gpu.gypi
index 9727704..f134890 100644
--- a/content/content_gpu.gypi
+++ b/content/content_gpu.gypi
@@ -6,19 +6,13 @@
   'dependencies': [
     '../base/base.gyp:base',
     '../gpu/gpu.gyp:gpu',
-    '../ipc/ipc.gyp:ipc',
     '../skia/skia.gyp:skia',
     '../ui/gl/gl.gyp:gl',
     'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
   ],
   'sources': [
-    'gpu/content_gpu_message_generator.cc',
-    'gpu/content_gpu_message_generator.h',
-    'gpu/establish_channel_params.cc',
-    'gpu/establish_channel_params.h',
     'gpu/gpu_child_thread.cc',
     'gpu/gpu_child_thread.h',
-    'gpu/gpu_host_messages.h',
     'gpu/gpu_main.cc',
     'gpu/gpu_process.cc',
     'gpu/gpu_process.h',
diff --git a/content/content_shell.gypi b/content/content_shell.gypi
index dff8369a..4f089e6 100644
--- a/content/content_shell.gypi
+++ b/content/content_shell.gypi
@@ -195,6 +195,8 @@
         'shell/browser/shell_web_contents_view_delegate_creator.h',
         'shell/browser/shell_web_contents_view_delegate_mac.mm',
         'shell/browser/shell_web_contents_view_delegate_win.cc',
+        'shell/common/layout_test/layout_test_content_client.cc',
+        'shell/common/layout_test/layout_test_content_client.h',
         'shell/common/layout_test/layout_test_messages.cc',
         'shell/common/layout_test/layout_test_messages.h',
         'shell/common/layout_test/layout_test_switches.cc',
diff --git a/content/gpu/BUILD.gn b/content/gpu/BUILD.gn
index ff076ea..7736a55 100644
--- a/content/gpu/BUILD.gn
+++ b/content/gpu/BUILD.gn
@@ -25,13 +25,8 @@
   visibility = [ "//content/*" ]
 
   sources = [
-    "content_gpu_message_generator.cc",
-    "content_gpu_message_generator.h",
-    "establish_channel_params.cc",
-    "establlish_channel_params.h",
     "gpu_child_thread.cc",
     "gpu_child_thread.h",
-    "gpu_host_messages.h",
     "gpu_main.cc",
     "gpu_process.cc",
     "gpu_process.h",
diff --git a/content/gpu/content_gpu_message_generator.cc b/content/gpu/content_gpu_message_generator.cc
deleted file mode 100644
index ff21717..0000000
--- a/content/gpu/content_gpu_message_generator.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Get basic type definitions.
-#define IPC_MESSAGE_IMPL
-#include "content/gpu/content_gpu_message_generator.h"
-
-// Generate constructors.
-#include "ipc/struct_constructor_macros.h"
-#include "content/gpu/content_gpu_message_generator.h"
-
-// Generate destructors.
-#include "ipc/struct_destructor_macros.h"
-#include "content/gpu/content_gpu_message_generator.h"
-
-// Generate param traits write methods.
-#include "ipc/param_traits_write_macros.h"
-namespace IPC {
-#include "content/gpu/content_gpu_message_generator.h"
-}  // namespace IPC
-
-// Generate param traits read methods.
-#include "ipc/param_traits_read_macros.h"
-namespace IPC {
-#include "content/gpu/content_gpu_message_generator.h"
-}  // namespace IPC
-
-// Generate param traits log methods.
-#include "ipc/param_traits_log_macros.h"
-namespace IPC {
-#include "content/gpu/content_gpu_message_generator.h"
-}  // namespace IPC
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc
index 6703021..b4ec902b 100644
--- a/content/gpu/gpu_child_thread.cc
+++ b/content/gpu/gpu_child_thread.cc
@@ -14,13 +14,13 @@
 #include "build/build_config.h"
 #include "content/child/child_process.h"
 #include "content/child/thread_safe_sender.h"
+#include "content/common/establish_channel_params.h"
 #include "content/common/gpu/gpu_memory_buffer_factory.h"
 #include "content/common/gpu/media/gpu_jpeg_decode_accelerator.h"
 #include "content/common/gpu/media/gpu_video_decode_accelerator.h"
 #include "content/common/gpu/media/gpu_video_encode_accelerator.h"
 #include "content/common/gpu/media/media_service.h"
-#include "content/gpu/establish_channel_params.h"
-#include "content/gpu/gpu_host_messages.h"
+#include "content/common/gpu_host_messages.h"
 #include "content/gpu/gpu_process_control_impl.h"
 #include "content/gpu/gpu_watchdog_thread.h"
 #include "content/public/common/content_client.h"
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index 47c5e57..9c2211ed 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -22,9 +22,9 @@
 #include "content/common/content_constants_internal.h"
 #include "content/common/gpu/gpu_config.h"
 #include "content/common/gpu/gpu_memory_buffer_factory.h"
+#include "content/common/gpu_host_messages.h"
 #include "content/common/sandbox_linux/sandbox_linux.h"
 #include "content/gpu/gpu_child_thread.h"
-#include "content/gpu/gpu_host_messages.h"
 #include "content/gpu/gpu_process.h"
 #include "content/gpu/gpu_watchdog_thread.h"
 #include "content/public/common/content_client.h"
diff --git a/content/plugin/webplugin_delegate_stub.cc b/content/plugin/webplugin_delegate_stub.cc
index 0f1db98f..a70be976 100644
--- a/content/plugin/webplugin_delegate_stub.cc
+++ b/content/plugin/webplugin_delegate_stub.cc
@@ -103,12 +103,6 @@
     IPC_MESSAGE_HANDLER(PluginMsg_UpdateGeometry, OnUpdateGeometry)
     IPC_MESSAGE_HANDLER(PluginMsg_UpdateGeometrySync, OnUpdateGeometry)
     IPC_MESSAGE_HANDLER(PluginMsg_SetContentAreaFocus, OnSetContentAreaFocus)
-#if defined(OS_WIN) && !defined(USE_AURA)
-    IPC_MESSAGE_HANDLER(PluginMsg_ImeCompositionUpdated,
-                        OnImeCompositionUpdated)
-    IPC_MESSAGE_HANDLER(PluginMsg_ImeCompositionCompleted,
-                        OnImeCompositionCompleted)
-#endif
 #if defined(OS_MACOSX)
     IPC_MESSAGE_HANDLER(PluginMsg_SetWindowFocus, OnSetWindowFocus)
     IPC_MESSAGE_HANDLER(PluginMsg_ContainerHidden, OnContainerHidden)
@@ -179,10 +173,6 @@
 
 void WebPluginDelegateStub::OnSetFocus(bool focused) {
   delegate_->SetFocus(focused);
-#if defined(OS_WIN) && !defined(USE_AURA)
-  if (focused)
-    webplugin_->UpdateIMEStatus();
-#endif
 }
 
 void WebPluginDelegateStub::OnHandleInputEvent(
@@ -243,24 +233,6 @@
     delegate_->SetContentAreaHasFocus(has_focus);
 }
 
-#if defined(OS_WIN) && !defined(USE_AURA)
-void WebPluginDelegateStub::OnImeCompositionUpdated(
-    const base::string16& text,
-    const std::vector<int>& clauses,
-    const std::vector<int>& target,
-    int cursor_position) {
-  if (delegate_)
-    delegate_->ImeCompositionUpdated(text, clauses, target, cursor_position);
-  webplugin_->UpdateIMEStatus();
-}
-
-void WebPluginDelegateStub::OnImeCompositionCompleted(
-    const base::string16& text) {
-  if (delegate_)
-    delegate_->ImeCompositionCompleted(text);
-}
-#endif
-
 #if defined(OS_MACOSX)
 void WebPluginDelegateStub::OnSetWindowFocus(bool has_focus) {
   if (delegate_)
diff --git a/content/plugin/webplugin_delegate_stub.h b/content/plugin/webplugin_delegate_stub.h
index bd999669..c42141c 100644
--- a/content/plugin/webplugin_delegate_stub.h
+++ b/content/plugin/webplugin_delegate_stub.h
@@ -71,13 +71,6 @@
   void OnGetFormValue(base::string16* value, bool* success);
 
   void OnSetContentAreaFocus(bool has_focus);
-#if defined(OS_WIN) && !defined(USE_AURA)
-  void OnImeCompositionUpdated(const base::string16& text,
-                               const std::vector<int>& clauses,
-                               const std::vector<int>& target,
-                               int cursor_position);
-  void OnImeCompositionCompleted(const base::string16& text);
-#endif
 #if defined(OS_MACOSX)
   void OnSetWindowFocus(bool has_focus);
   void OnContainerHidden();
diff --git a/content/plugin/webplugin_proxy.cc b/content/plugin/webplugin_proxy.cc
index 8744d22c..89c1915 100644
--- a/content/plugin/webplugin_proxy.cc
+++ b/content/plugin/webplugin_proxy.cc
@@ -76,19 +76,6 @@
   return channel_->Send(msg);
 }
 
-#if defined(OS_WIN)
-void WebPluginProxy::SetWindowlessData(
-    HANDLE pump_messages_event, gfx::NativeViewId dummy_activation_window) {
-  HANDLE pump_messages_event_for_renderer = NULL;
-  BrokerDuplicateHandle(pump_messages_event, channel_->peer_pid(),
-                                 &pump_messages_event_for_renderer,
-                                 SYNCHRONIZE | EVENT_MODIFY_STATE, 0);
-  DCHECK(pump_messages_event_for_renderer);
-  Send(new PluginHostMsg_SetWindowlessData(
-      route_id_, pump_messages_event_for_renderer, dummy_activation_window));
-}
-#endif
-
 void WebPluginProxy::Invalidate() {
   gfx::Rect rect(0, 0,
                  delegate_->GetRect().width(),
@@ -475,17 +462,4 @@
   return channel_->incognito();
 }
 
-#if defined(OS_WIN) && !defined(USE_AURA)
-void WebPluginProxy::UpdateIMEStatus() {
-  // Retrieve the IME status from a plugin and send it to a renderer process
-  // when the plugin has updated it.
-  int input_type;
-  gfx::Rect caret_rect;
-  if (!delegate_->GetIMEStatus(&input_type, &caret_rect))
-    return;
-
-  Send(new PluginHostMsg_NotifyIMEStatus(route_id_, input_type, caret_rect));
-}
-#endif
-
 }  // namespace content
diff --git a/content/plugin/webplugin_proxy.h b/content/plugin/webplugin_proxy.h
index 37030563..a3386a74 100644
--- a/content/plugin/webplugin_proxy.h
+++ b/content/plugin/webplugin_proxy.h
@@ -72,10 +72,6 @@
   void DidStartLoading() override;
   void DidStopLoading() override;
   bool IsOffTheRecord() override;
-#if defined(OS_WIN)
-  void SetWindowlessData(HANDLE pump_messages_event,
-                         gfx::NativeViewId dummy_activation_window) override;
-#endif
 #if defined(OS_MACOSX)
   void FocusChanged(bool focused) override;
   void StartIme() override;
@@ -107,14 +103,6 @@
   // Callback from the renderer to let us know that a paint occurred.
   void DidPaint();
 
-#if defined(OS_WIN) && !defined(USE_AURA)
-  // Retrieves the IME status from a windowless plugin and sends it to a
-  // renderer process. A renderer process will convert the coordinates from
-  // local to the window coordinates and send the converted coordinates to a
-  // browser process.
-  void UpdateIMEStatus();
-#endif
-
  private:
   class SharedTransportDIB : public base::RefCounted<SharedTransportDIB> {
    public:
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDialog.java b/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDialog.java
index f14b93a..09ace74 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDialog.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDialog.java
@@ -43,6 +43,7 @@
         AlertDialog.Builder b = new AlertDialog.Builder(windowContext)
                 .setView(listView)
                 .setCancelable(true);
+        setInverseBackgroundForced(b);
 
         if (multiple) {
             b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@@ -93,6 +94,14 @@
         });
     }
 
+    @SuppressWarnings("deprecation")
+    private static void setInverseBackgroundForced(AlertDialog.Builder builder) {
+        // This is needed for pre-Holo themes (e.g. android:Theme.Black), which can be used in
+        // WebView. See http://crbug.com/596626. This can be removed if/when this class starts
+        // using android.support.v7.app.AlertDialog.
+        builder.setInverseBackgroundForced(true);
+    }
+
     private int getSelectDialogLayout(boolean isMultiChoice) {
         int resourceId;
         TypedArray styledAttributes = mListBoxPopup.getContext().obtainStyledAttributes(
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/MediaSessionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/MediaSessionTest.java
index fc673b04..13ef0b3b 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/MediaSessionTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/MediaSessionTest.java
@@ -10,6 +10,7 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
@@ -230,6 +231,8 @@
         mAudioFocusChangeListener.waitForFocusStateChange(AudioManager.AUDIOFOCUS_LOSS);
     }
 
+    // TODO(zqzhang): Investigate why this test fails after switching to .ogg from .mp3
+    @DisabledTest
     @SmallTest
     @Feature({"MediaSession"})
     public void testShortAudioStopsIfLostFocus() throws Exception {
diff --git a/content/public/browser/android/synchronous_compositor.cc b/content/public/browser/android/synchronous_compositor.cc
new file mode 100644
index 0000000..4e52b613
--- /dev/null
+++ b/content/public/browser/android/synchronous_compositor.cc
@@ -0,0 +1,27 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/android/synchronous_compositor.h"
+
+#include <utility>
+
+#include "cc/output/compositor_frame.h"
+
+namespace content {
+
+SynchronousCompositor::Frame::Frame() : output_surface_id(0u) {}
+
+SynchronousCompositor::Frame::~Frame() {}
+
+SynchronousCompositor::Frame::Frame(Frame&& rhs)
+    : output_surface_id(rhs.output_surface_id), frame(std::move(rhs.frame)) {}
+
+SynchronousCompositor::Frame& SynchronousCompositor::Frame::operator=(
+    Frame&& rhs) {
+  output_surface_id = rhs.output_surface_id;
+  frame = std::move(rhs.frame);
+  return *this;
+}
+
+}  // namespace content
diff --git a/content/public/browser/android/synchronous_compositor.h b/content/public/browser/android/synchronous_compositor.h
index e0d09d8..431e1e1c 100644
--- a/content/public/browser/android/synchronous_compositor.h
+++ b/content/public/browser/android/synchronous_compositor.h
@@ -47,9 +47,24 @@
   static void SetGpuService(
       scoped_refptr<gpu::InProcessCommandBuffer::Service> service);
 
+  struct Frame {
+    Frame();
+    ~Frame();
+
+    // Movable type.
+    Frame(Frame&& rhs);
+    Frame& operator=(Frame&& rhs);
+
+    uint32_t output_surface_id;
+    scoped_ptr<cc::CompositorFrame> frame;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(Frame);
+  };
+
   // "On demand" hardware draw. The content is first clipped to |damage_area|,
   // then transformed through |transform|, and finally clipped to |view_size|.
-  virtual scoped_ptr<cc::CompositorFrame> DemandDrawHw(
+  virtual Frame DemandDrawHw(
       const gfx::Size& surface_size,
       const gfx::Transform& transform,
       const gfx::Rect& viewport,
@@ -59,7 +74,8 @@
 
   // For delegated rendering, return resources from parent compositor to this.
   // Note that all resources must be returned before ReleaseHwDraw.
-  virtual void ReturnResources(const cc::CompositorFrameAck& frame_ack) = 0;
+  virtual void ReturnResources(uint32_t output_surface_id,
+                               const cc::CompositorFrameAck& frame_ack) = 0;
 
   // "On demand" SW draw, into the supplied canvas (observing the transform
   // and clip set there-in).
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 38e1a913..7d523d8 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -69,6 +69,10 @@
 const base::Feature kWebFontsIntervention{"WebFontsIntervention",
                                           base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Controls whether the WebUSB API is enabled:
+// https://wicg.github.io/webusb
+const base::Feature kWebUsb{"WebUSB", base::FEATURE_ENABLED_BY_DEFAULT};
+
 #if defined(OS_ANDROID)
 // Use IME's own thread instead of using main UI thread. It also means that
 // we will not use replica editor and do a round trip to renderer to synchronize
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 8fbbf42..b894afca 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -28,6 +28,7 @@
 CONTENT_EXPORT extern const base::Feature kTokenBinding;
 CONTENT_EXPORT extern const base::Feature kUpdateRendererPriorityOnStartup;
 CONTENT_EXPORT extern const base::Feature kWebFontsIntervention;
+CONTENT_EXPORT extern const base::Feature kWebUsb;
 
 #if defined(OS_ANDROID)
 CONTENT_EXPORT extern const base::Feature kImeThread;
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index b5c05cd9..d602fece 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -107,6 +107,8 @@
 
   // Creates a replacement plugin that is shown when the plugin at |file_path|
   // couldn't be loaded. This allows the embedder to show a custom placeholder.
+  // This may return nullptr. However, if it does return a WebPlugin, it must
+  // never fail to initialize.
   virtual blink::WebPlugin* CreatePluginReplacement(
       RenderFrame* render_frame,
       const base::FilePath& plugin_path);
diff --git a/content/public/test/test_synchronous_compositor_android.cc b/content/public/test/test_synchronous_compositor_android.cc
index 9eff3ff..609cdf4 100644
--- a/content/public/test/test_synchronous_compositor_android.cc
+++ b/content/public/test/test_synchronous_compositor_android.cc
@@ -27,7 +27,7 @@
   }
 }
 
-scoped_ptr<cc::CompositorFrame> TestSynchronousCompositor::DemandDrawHw(
+SynchronousCompositor::Frame TestSynchronousCompositor::DemandDrawHw(
     const gfx::Size& surface_size,
     const gfx::Transform& transform,
     const gfx::Rect& viewport,
@@ -37,14 +37,35 @@
   return std::move(hardware_frame_);
 }
 
+void TestSynchronousCompositor::ReturnResources(
+    uint32_t output_surface_id,
+    const cc::CompositorFrameAck& frame_ack) {
+  ReturnedResources returned_resources;
+  returned_resources.output_surface_id = output_surface_id;
+  returned_resources.resources = frame_ack.resources;
+  frame_ack_array_.push_back(returned_resources);
+}
+
+void TestSynchronousCompositor::SwapReturnedResources(FrameAckArray* array) {
+  DCHECK(array);
+  frame_ack_array_.swap(*array);
+}
+
 bool TestSynchronousCompositor::DemandDrawSw(SkCanvas* canvas) {
   DCHECK(canvas);
   return true;
 }
 
 void TestSynchronousCompositor::SetHardwareFrame(
+    uint32_t output_surface_id,
     scoped_ptr<cc::CompositorFrame> frame) {
-  hardware_frame_ = std::move(frame);
+  hardware_frame_.output_surface_id = output_surface_id;
+  hardware_frame_.frame = std::move(frame);
 }
 
+TestSynchronousCompositor::ReturnedResources::ReturnedResources()
+    : output_surface_id(0u) {}
+
+TestSynchronousCompositor::ReturnedResources::~ReturnedResources() {}
+
 }  // namespace content
diff --git a/content/public/test/test_synchronous_compositor_android.h b/content/public/test/test_synchronous_compositor_android.h
index b9f0c85..613eda66 100644
--- a/content/public/test/test_synchronous_compositor_android.h
+++ b/content/public/test/test_synchronous_compositor_android.h
@@ -7,8 +7,11 @@
 
 #include <stddef.h>
 
+#include <vector>
+
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
+#include "cc/output/compositor_frame_ack.h"
 #include "content/public/browser/android/synchronous_compositor.h"
 #include "content/public/browser/android/synchronous_compositor_client.h"
 
@@ -22,14 +25,15 @@
   void SetClient(SynchronousCompositorClient* client);
 
   // SynchronousCompositor overrides.
-  scoped_ptr<cc::CompositorFrame> DemandDrawHw(
+  SynchronousCompositor::Frame DemandDrawHw(
       const gfx::Size& surface_size,
       const gfx::Transform& transform,
       const gfx::Rect& viewport,
       const gfx::Rect& clip,
       const gfx::Rect& viewport_rect_for_tile_priority,
       const gfx::Transform& transform_for_tile_priority) override;
-  void ReturnResources(const cc::CompositorFrameAck& frame_ack) override {}
+  void ReturnResources(uint32_t output_surface_id,
+                       const cc::CompositorFrameAck& frame_ack) override;
   bool DemandDrawSw(SkCanvas* canvas) override;
   void SetMemoryPolicy(size_t bytes_limit) override {}
   void DidChangeRootLayerScrollOffset(
@@ -37,11 +41,23 @@
   void SetIsActive(bool is_active) override {}
   void OnComputeScroll(base::TimeTicks animate_time) override {}
 
-  void SetHardwareFrame(scoped_ptr<cc::CompositorFrame> frame);
+  void SetHardwareFrame(uint32_t output_surface_id,
+                        scoped_ptr<cc::CompositorFrame> frame);
+
+  struct ReturnedResources {
+    ReturnedResources();
+    ~ReturnedResources();
+
+    uint32_t output_surface_id;
+    cc::ReturnedResourceArray resources;
+  };
+  using FrameAckArray = std::vector<ReturnedResources>;
+  void SwapReturnedResources(FrameAckArray* array);
 
  private:
   SynchronousCompositorClient* client_;
-  scoped_ptr<cc::CompositorFrame> hardware_frame_;
+  SynchronousCompositor::Frame hardware_frame_;
+  FrameAckArray frame_ack_array_;
 
   DISALLOW_COPY_AND_ASSIGN(TestSynchronousCompositor);
 };
diff --git a/content/renderer/android/synchronous_compositor_factory.h b/content/renderer/android/synchronous_compositor_factory.h
index 18ada90..91185ffb 100644
--- a/content/renderer/android/synchronous_compositor_factory.h
+++ b/content/renderer/android/synchronous_compositor_factory.h
@@ -50,6 +50,7 @@
   GetCompositorTaskRunner() = 0;
   virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface(
       int routing_id,
+      uint32_t output_surface_id,
       const scoped_refptr<FrameSwapMessageQueue>& frame_swap_message_queue,
       const scoped_refptr<cc::ContextProvider>& onscreen_context,
       const scoped_refptr<cc::ContextProvider>& worker_context) = 0;
diff --git a/content/renderer/android/synchronous_compositor_output_surface.cc b/content/renderer/android/synchronous_compositor_output_surface.cc
index 23f67d51..5609735 100644
--- a/content/renderer/android/synchronous_compositor_output_surface.cc
+++ b/content/renderer/android/synchronous_compositor_output_surface.cc
@@ -64,6 +64,7 @@
     const scoped_refptr<cc::ContextProvider>& context_provider,
     const scoped_refptr<cc::ContextProvider>& worker_context_provider,
     int routing_id,
+    uint32_t output_surface_id,
     SynchronousCompositorRegistry* registry,
     scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue)
     : cc::OutputSurface(
@@ -71,6 +72,7 @@
           worker_context_provider,
           scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareDevice(this))),
       routing_id_(routing_id),
+      output_surface_id_(output_surface_id),
       registry_(registry),
       registered_(false),
       sync_client_(nullptr),
@@ -133,7 +135,7 @@
   DCHECK(CalledOnValidThread());
   DCHECK(sync_client_);
   if (!fallback_tick_running_)
-    sync_client_->SwapBuffers(frame);
+    sync_client_->SwapBuffers(output_surface_id_, frame);
   client_->DidSwapBuffers();
   did_swap_ = true;
 }
@@ -227,8 +229,10 @@
 }
 
 void SynchronousCompositorOutputSurface::ReturnResources(
+    uint32_t output_surface_id,
     const cc::CompositorFrameAck& frame_ack) {
-  ReclaimResources(&frame_ack);
+  if (output_surface_id_ == output_surface_id)
+    ReclaimResources(&frame_ack);
 }
 
 void SynchronousCompositorOutputSurface::SetMemoryPolicy(size_t bytes_limit) {
diff --git a/content/renderer/android/synchronous_compositor_output_surface.h b/content/renderer/android/synchronous_compositor_output_surface.h
index 7fd8127..d373146 100644
--- a/content/renderer/android/synchronous_compositor_output_surface.h
+++ b/content/renderer/android/synchronous_compositor_output_surface.h
@@ -40,7 +40,8 @@
 class SynchronousCompositorOutputSurfaceClient {
  public:
   virtual void Invalidate() = 0;
-  virtual void SwapBuffers(cc::CompositorFrame* frame) = 0;
+  virtual void SwapBuffers(uint32_t output_surface_id,
+                           cc::CompositorFrame* frame) = 0;
 
  protected:
   virtual ~SynchronousCompositorOutputSurfaceClient() {}
@@ -61,6 +62,7 @@
       const scoped_refptr<cc::ContextProvider>& context_provider,
       const scoped_refptr<cc::ContextProvider>& worker_context_provider,
       int routing_id,
+      uint32_t output_surface_id,
       SynchronousCompositorRegistry* registry,
       scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue);
   ~SynchronousCompositorOutputSurface() override;
@@ -84,7 +86,8 @@
                     const gfx::Rect& clip,
                     const gfx::Rect& viewport_rect_for_tile_priority,
                     const gfx::Transform& transform_for_tile_priority);
-  void ReturnResources(const cc::CompositorFrameAck& frame_ack);
+  void ReturnResources(uint32_t output_surface_id,
+                       const cc::CompositorFrameAck& frame_ack);
   void DemandDrawSw(SkCanvas* canvas);
   void SetMemoryPolicy(size_t bytes_limit);
   void SetTreeActivationCallback(const base::Closure& callback);
@@ -108,6 +111,7 @@
   void FallbackTickFired();
 
   const int routing_id_;
+  const uint32_t output_surface_id_;
   SynchronousCompositorRegistry* const registry_;  // unowned
   bool registered_;
 
diff --git a/content/renderer/android/synchronous_compositor_proxy.cc b/content/renderer/android/synchronous_compositor_proxy.cc
index b9859497..820b577c 100644
--- a/content/renderer/android/synchronous_compositor_proxy.cc
+++ b/content/renderer/android/synchronous_compositor_proxy.cc
@@ -218,30 +218,30 @@
   if (inside_receive_) {
     // Did not swap.
     cc::CompositorFrame empty_frame;
-    SendDemandDrawHwReply(&empty_frame, reply_message);
+    SendDemandDrawHwReply(&empty_frame, 0u, reply_message);
     inside_receive_ = false;
   } else {
     DeliverMessages();
   }
 }
 
-void SynchronousCompositorProxy::SwapBuffersHw(cc::CompositorFrame* frame) {
+void SynchronousCompositorProxy::SwapBuffersHw(uint32_t output_surface_id,
+                                               cc::CompositorFrame* frame) {
   DCHECK(inside_receive_);
   DCHECK(hardware_draw_reply_);
   DCHECK(frame);
-  SendDemandDrawHwReply(frame, hardware_draw_reply_);
+  SendDemandDrawHwReply(frame, output_surface_id, hardware_draw_reply_);
   inside_receive_ = false;
 }
 
 void SynchronousCompositorProxy::SendDemandDrawHwReply(
     cc::CompositorFrame* frame,
+    uint32_t output_surface_id,
     IPC::Message* reply_message) {
   SyncCompositorCommonRendererParams common_renderer_params;
   PopulateCommonParams(&common_renderer_params);
-  // Not using WriteParams because cc::CompositorFrame is not copy-able.
-  IPC::ParamTraits<SyncCompositorCommonRendererParams>::Write(
-      reply_message, common_renderer_params);
-  IPC::ParamTraits<cc::CompositorFrame>::Write(reply_message, *frame);
+  SyncCompositorMsg_DemandDrawHw::WriteReplyParams(
+      reply_message, common_renderer_params, output_surface_id, *frame);
   Send(reply_message);
 }
 
@@ -358,19 +358,17 @@
     IPC::Message* reply_message) {
   SyncCompositorCommonRendererParams common_renderer_params;
   PopulateCommonParams(&common_renderer_params);
-  // Not using WriteParams because cc::CompositorFrame is not copy-able.
-  IPC::ParamTraits<bool>::Write(reply_message, success);
-  IPC::ParamTraits<SyncCompositorCommonRendererParams>::Write(
-      reply_message, common_renderer_params);
-  IPC::ParamTraits<cc::CompositorFrame>::Write(reply_message, *frame);
+  SyncCompositorMsg_DemandDrawSw::WriteReplyParams(
+      reply_message, success, common_renderer_params, *frame);
   Send(reply_message);
 }
 
-void SynchronousCompositorProxy::SwapBuffers(cc::CompositorFrame* frame) {
+void SynchronousCompositorProxy::SwapBuffers(uint32_t output_surface_id,
+                                             cc::CompositorFrame* frame) {
   DCHECK(hardware_draw_reply_ || software_draw_reply_);
   DCHECK(!(hardware_draw_reply_ && software_draw_reply_));
   if (hardware_draw_reply_) {
-    SwapBuffersHw(frame);
+    SwapBuffersHw(output_surface_id, frame);
   } else if (software_draw_reply_) {
     SwapBuffersSw(frame);
   }
@@ -409,7 +407,9 @@
   begin_frame_source_->SetBeginFrameSourcePaused(
       common_params.begin_frame_source_paused);
   if (!common_params.ack.resources.empty()) {
-    output_surface_->ReturnResources(common_params.ack);
+    output_surface_->ReturnResources(
+        common_params.output_surface_id_for_returned_resources,
+        common_params.ack);
   }
 }
 
diff --git a/content/renderer/android/synchronous_compositor_proxy.h b/content/renderer/android/synchronous_compositor_proxy.h
index 534e7db6..a07e7d8 100644
--- a/content/renderer/android/synchronous_compositor_proxy.h
+++ b/content/renderer/android/synchronous_compositor_proxy.h
@@ -72,7 +72,8 @@
 
   // SynchronousCompositorOutputSurfaceClient overrides.
   void Invalidate() override;
-  void SwapBuffers(cc::CompositorFrame* frame) override;
+  void SwapBuffers(uint32_t output_surface_id,
+                   cc::CompositorFrame* frame) override;
 
   void OnMessageReceived(const IPC::Message& message);
   bool Send(IPC::Message* message);
@@ -109,8 +110,9 @@
                     const SyncCompositorDemandDrawSwParams& params,
                     IPC::Message* reply_message);
 
-  void SwapBuffersHw(cc::CompositorFrame* frame);
+  void SwapBuffersHw(uint32_t output_surface_id, cc::CompositorFrame* frame);
   void SendDemandDrawHwReply(cc::CompositorFrame* frame,
+                             uint32_t output_surface_id,
                              IPC::Message* reply_message);
   void DoDemandDrawSw(const SyncCompositorDemandDrawSwParams& params);
   void SwapBuffersSw(cc::CompositorFrame* frame);
diff --git a/content/renderer/dom_storage/local_storage_cached_area.cc b/content/renderer/dom_storage/local_storage_cached_area.cc
index 2b55bf7..da09a783 100644
--- a/content/renderer/dom_storage/local_storage_cached_area.cc
+++ b/content/renderer/dom_storage/local_storage_cached_area.cc
@@ -41,7 +41,7 @@
     const url::Origin& origin,
     StoragePartitionService* storage_partition_service,
     LocalStorageCachedAreas* cached_areas)
-    : loaded_(false), origin_(origin), binding_(this),
+    : origin_(origin), binding_(this),
       cached_areas_(cached_areas) {
   storage_partition_service->OpenLocalStorage(
       origin_, mojo::GetProxy(&leveldb_));
@@ -113,7 +113,6 @@
 
   Reset();
   map_ = new DOMStorageMap(kPerStorageAreaQuota);
-  binding_.Close();
 
   leveldb_->DeleteAll(binding_.CreateInterfacePtrAndBind(),
                       PackSource(page_url, storage_area_id),
@@ -226,10 +225,9 @@
 }
 
 void LocalStorageCachedArea::EnsureLoaded() {
-  if (loaded_)
+  if (map_)
     return;
 
-  loaded_ = true;
   base::TimeTicks before = base::TimeTicks::Now();
   leveldb::DatabaseError status = leveldb::DatabaseError::OK;
   mojo::Array<content::KeyValuePtr> data;
@@ -293,6 +291,7 @@
 }
 
 void LocalStorageCachedArea::Reset() {
+  binding_.Close();
   map_ = NULL;
   ignore_key_mutations_.clear();
 }
diff --git a/content/renderer/dom_storage/local_storage_cached_area.h b/content/renderer/dom_storage/local_storage_cached_area.h
index b17e299..ee6c0cd6 100644
--- a/content/renderer/dom_storage/local_storage_cached_area.h
+++ b/content/renderer/dom_storage/local_storage_cached_area.h
@@ -82,7 +82,6 @@
   // Resets the object back to its newly constructed state.
   void Reset();
 
-  bool loaded_;
   url::Origin origin_;
   scoped_refptr<DOMStorageMap> map_;
   std::map<base::string16, int> ignore_key_mutations_;
diff --git a/content/renderer/media/audio_track_recorder.cc b/content/renderer/media/audio_track_recorder.cc
index 2664d535..4140bd7 100644
--- a/content/renderer/media/audio_track_recorder.cc
+++ b/content/renderer/media/audio_track_recorder.cc
@@ -109,9 +109,10 @@
   void EncodeAudio(scoped_ptr<media::AudioBus> audio_bus,
                    const base::TimeTicks& capture_time);
 
+  void set_paused(bool paused) { paused_ = paused; }
+
  private:
   friend class base::RefCountedThreadSafe<AudioEncoder>;
-
   ~AudioEncoder() override;
 
   bool is_initialized() const { return !!opus_encoder_; }
@@ -142,6 +143,9 @@
   // Buffer for passing AudioBus data to OpusEncoder.
   scoped_ptr<float[]> buffer_;
 
+  // While |paused_|, AudioBuses are not encoded.
+  bool paused_;
+
   OpusEncoder* opus_encoder_;
 
   DISALLOW_COPY_AND_ASSIGN(AudioEncoder);
@@ -152,6 +156,7 @@
     int32_t bits_per_second)
     : on_encoded_audio_cb_(on_encoded_audio_cb),
       bits_per_second_(bits_per_second),
+      paused_(false),
       opus_encoder_(nullptr) {
   // AudioEncoder is constructed on the thread that ATR lives on, but should
   // operate only on the encoder thread after that. Reset
@@ -241,7 +246,7 @@
   DCHECK(!capture_time.is_null());
   DCHECK(converter_);
 
-  if (!is_initialized())
+  if (!is_initialized() || paused_)
     return;
   // TODO(mcasas): Consider using a std::deque<scoped_ptr<AudioBus>> instead of
   // an AudioFifo, to avoid copying data needlessly since we know the sizes of
@@ -278,7 +283,7 @@
 
 void AudioTrackRecorder::AudioEncoder::DestroyExistingOpusEncoder() {
   // We don't DCHECK that we're on the encoder thread here, as this could be
-  // called from the dtor (main thread) or from OnSetForamt() (render thread);
+  // called from the dtor (main thread) or from OnSetFormat() (encoder thread).
   if (opus_encoder_) {
     opus_encoder_destroy(opus_encoder_);
     opus_encoder_ = nullptr;
@@ -336,4 +341,18 @@
                             base::Passed(&audio_data), capture_time));
 }
 
+void AudioTrackRecorder::Pause() {
+  DCHECK(main_render_thread_checker_.CalledOnValidThread());
+  DCHECK(encoder_);
+  encoder_thread_.task_runner()->PostTask(
+      FROM_HERE, base::Bind(&AudioEncoder::set_paused, encoder_, true));
+}
+
+void AudioTrackRecorder::Resume() {
+  DCHECK(main_render_thread_checker_.CalledOnValidThread());
+  DCHECK(encoder_);
+  encoder_thread_.task_runner()->PostTask(
+      FROM_HERE, base::Bind(&AudioEncoder::set_paused, encoder_, false));
+}
+
 }  // namespace content
diff --git a/content/renderer/media/audio_track_recorder.h b/content/renderer/media/audio_track_recorder.h
index 7f7c1f9..608cfcaf 100644
--- a/content/renderer/media/audio_track_recorder.h
+++ b/content/renderer/media/audio_track_recorder.h
@@ -47,6 +47,9 @@
   void OnData(const media::AudioBus& audio_bus,
               base::TimeTicks capture_time) override;
 
+  void Pause();
+  void Resume();
+
  private:
   // Forward declaration of nested class for handling encoding.
   // See the implementation file for details.
diff --git a/content/renderer/media/audio_track_recorder_unittest.cc b/content/renderer/media/audio_track_recorder_unittest.cc
index 885ac03..c30ba99 100644
--- a/content/renderer/media/audio_track_recorder_unittest.cc
+++ b/content/renderer/media/audio_track_recorder_unittest.cc
@@ -27,6 +27,7 @@
 using ::testing::SaveArg;
 using ::testing::TestWithParam;
 using ::testing::ValuesIn;
+using base::TimeTicks;
 
 namespace {
 
@@ -168,11 +169,11 @@
   MOCK_METHOD3(DoOnEncodedAudio,
                void(const media::AudioParameters& params,
                     std::string encoded_data,
-                    base::TimeTicks timestamp));
+                    TimeTicks timestamp));
 
   void OnEncodedAudio(const media::AudioParameters& params,
                       scoped_ptr<std::string> encoded_data,
-                      base::TimeTicks timestamp) {
+                      TimeTicks timestamp) {
     EXPECT_TRUE(!encoded_data->empty());
     // Decode |encoded_data| and check we get the expected number of frames
     // per buffer.
@@ -236,31 +237,23 @@
   // TODO(ajose): consider adding WillOnce(SaveArg...) and inspecting, as done
   // in VTR unittests. http://crbug.com/548856
   EXPECT_CALL(*this, DoOnEncodedAudio(_, _, _)).Times(1);
-  audio_track_recorder_->OnData(*GetFirstSourceAudioBus(),
-                                base::TimeTicks::Now());
-  for (int i = 0; i < kRatioInputToOutputFrames - 1; ++i) {
-    audio_track_recorder_->OnData(*GetFirstSourceAudioBus(),
-                                  base::TimeTicks::Now());
-  }
+  audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
+  for (int i = 0; i < kRatioInputToOutputFrames - 1; ++i)
+    audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
 
   EXPECT_CALL(*this, DoOnEncodedAudio(_, _, _))
       .Times(1)
       // Only reset the decoder once we've heard back:
       .WillOnce(RunClosure(base::Bind(&AudioTrackRecorderTest::ResetDecoder,
                                       base::Unretained(this), second_params_)));
-  audio_track_recorder_->OnData(*GetFirstSourceAudioBus(),
-                                base::TimeTicks::Now());
-  for (int i = 0; i < kRatioInputToOutputFrames - 1; ++i) {
-    audio_track_recorder_->OnData(*GetFirstSourceAudioBus(),
-                                  base::TimeTicks::Now());
-  }
+  audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
+  for (int i = 0; i < kRatioInputToOutputFrames - 1; ++i)
+    audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
 
   // If the amount of samples/10ms buffer is not an integer (e.g. 22050Hz) we
   // need an extra OnData() to account for the round-off error.
-  if (GetParam().sample_rate % 100) {
-    audio_track_recorder_->OnData(*GetFirstSourceAudioBus(),
-                                  base::TimeTicks::Now());
-  }
+  if (GetParam().sample_rate % 100)
+    audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
 
   // Give ATR new audio parameters.
   audio_track_recorder_->OnSetFormat(second_params_);
@@ -269,17 +262,42 @@
   EXPECT_CALL(*this, DoOnEncodedAudio(_, _, _))
       .Times(1)
       .WillOnce(RunClosure(quit_closure));
-  audio_track_recorder_->OnData(*GetSecondSourceAudioBus(),
-                                base::TimeTicks::Now());
-  for (int i = 0; i < kRatioInputToOutputFrames - 1; ++i) {
-    audio_track_recorder_->OnData(*GetSecondSourceAudioBus(),
-                                  base::TimeTicks::Now());
-  }
+  audio_track_recorder_->OnData(*GetSecondSourceAudioBus(), TimeTicks::Now());
+  for (int i = 0; i < kRatioInputToOutputFrames - 1; ++i)
+    audio_track_recorder_->OnData(*GetSecondSourceAudioBus(), TimeTicks::Now());
+
+  run_loop.Run();
+  Mock::VerifyAndClearExpectations(this);
+}
+
+TEST_P(AudioTrackRecorderTest, PauseResume) {
+  InSequence s;
+  base::RunLoop run_loop;
+  base::Closure quit_closure = run_loop.QuitClosure();
+
+  // Give ATR initial audio parameters.
+  audio_track_recorder_->OnSetFormat(first_params_);
+
+  audio_track_recorder_->Pause();
+  EXPECT_CALL(*this, DoOnEncodedAudio(_, _, _)).Times(0);
+  audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
+  for (int i = 0; i < kRatioInputToOutputFrames - 1; ++i)
+    audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
+
+  audio_track_recorder_->Resume();
+  EXPECT_CALL(*this, DoOnEncodedAudio(_, _, _))
+      .Times(1)
+      .WillOnce(RunClosure(quit_closure));
+  audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
+  for (int i = 0; i < kRatioInputToOutputFrames - 1; ++i)
+    audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
+
+  if (GetParam().sample_rate % 100)
+    audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
 
   run_loop.Run();
   Mock::VerifyAndClearExpectations(this);
 }
 
 INSTANTIATE_TEST_CASE_P(, AudioTrackRecorderTest, ValuesIn(kATRTestParams));
-
 }  // namespace content
diff --git a/content/renderer/media/media_recorder_handler.cc b/content/renderer/media/media_recorder_handler.cc
index f20c6c40..a6e641c6 100644
--- a/content/renderer/media/media_recorder_handler.cc
+++ b/content/renderer/media/media_recorder_handler.cc
@@ -24,6 +24,7 @@
 #include "media/base/video_frame.h"
 #include "media/muxers/webm_muxer.h"
 #include "third_party/WebKit/public/platform/WebMediaRecorderHandlerClient.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 
 using base::TimeDelta;
@@ -134,11 +135,15 @@
     return false;
   }
 
-  const bool use_video_tracks =
-      !video_tracks.isEmpty() && video_tracks[0].isEnabled();
-  const bool use_audio_tracks =
-      !audio_tracks.isEmpty() && MediaStreamAudioTrack::From(audio_tracks[0])
-       && audio_tracks[0].isEnabled();
+  const bool use_video_tracks = !video_tracks.isEmpty() &&
+                                video_tracks[0].isEnabled() &&
+                                video_tracks[0].source().getReadyState() ==
+                                    blink::WebMediaStreamSource::ReadyStateLive;
+  const bool use_audio_tracks = !audio_tracks.isEmpty() &&
+                                MediaStreamAudioTrack::From(audio_tracks[0]) &&
+                                audio_tracks[0].isEnabled() &&
+                                audio_tracks[0].source().getReadyState() ==
+                                    blink::WebMediaStreamSource::ReadyStateLive;
 
   webm_muxer_.reset(new media::WebmMuxer(
       use_vp9_ ? media::kCodecVP9 : media::kCodecVP8, use_video_tracks,
@@ -202,6 +207,8 @@
   recording_ = false;
   for (const auto& video_recorder : video_recorders_)
     video_recorder->Pause();
+  for (const auto& audio_recorder : audio_recorders_)
+    audio_recorder->Pause();
 }
 
 void MediaRecorderHandler::resume() {
@@ -210,6 +217,8 @@
   recording_ = true;
   for (const auto& video_recorder : video_recorders_)
     video_recorder->Resume();
+  for (const auto& audio_recorder : audio_recorders_)
+    audio_recorder->Resume();
 }
 
 void MediaRecorderHandler::OnEncodedVideo(
diff --git a/content/renderer/npapi/webplugin_delegate_proxy.cc b/content/renderer/npapi/webplugin_delegate_proxy.cc
index 2e80b85..d69fd40 100644
--- a/content/renderer/npapi/webplugin_delegate_proxy.cc
+++ b/content/renderer/npapi/webplugin_delegate_proxy.cc
@@ -108,8 +108,6 @@
       uses_shared_bitmaps_(true),
 #if defined(OS_MACOSX)
       uses_compositor_(false),
-#elif defined(OS_WIN)
-      dummy_activation_window_(NULL),
 #endif
       mime_type_(mime_type),
       instance_id_(MSG_ROUTING_NONE),
@@ -132,20 +130,12 @@
 WebPluginDelegateProxy::SharedBitmap::~SharedBitmap() {}
 
 void WebPluginDelegateProxy::PluginDestroyed() {
-#if defined(OS_MACOSX) || defined(OS_WIN)
+#if defined(OS_MACOSX)
   // Ensure that the renderer doesn't think the plugin still has focus.
   if (render_view_)
     render_view_->PluginFocusChanged(false, instance_id_);
 #endif
 
-#if defined(OS_WIN)
-  if (dummy_activation_window_ && render_view_) {
-    render_view_->Send(new ViewHostMsg_WindowlessPluginDummyWindowDestroyed(
-        render_view_->GetRoutingID(), dummy_activation_window_));
-  }
-  dummy_activation_window_ = NULL;
-#endif
-
   if (render_view_.get())
     render_view_->UnregisterPluginDelegate(this);
 
@@ -304,10 +294,6 @@
     IPC_MESSAGE_HANDLER(PluginHostMsg_CancelDocumentLoad, OnCancelDocumentLoad)
     IPC_MESSAGE_HANDLER(PluginHostMsg_DidStartLoading, OnDidStartLoading)
     IPC_MESSAGE_HANDLER(PluginHostMsg_DidStopLoading, OnDidStopLoading)
-#if defined(OS_WIN)
-    IPC_MESSAGE_HANDLER(PluginHostMsg_SetWindowlessData, OnSetWindowlessData)
-    IPC_MESSAGE_HANDLER(PluginHostMsg_NotifyIMEStatus, OnNotifyIMEStatus)
-#endif
 #if defined(OS_MACOSX)
     IPC_MESSAGE_HANDLER(PluginHostMsg_FocusChanged,
                         OnFocusChanged);
@@ -335,7 +321,7 @@
         info_.path, channel_host_->peer_pid());
   }
 
-#if defined(OS_MACOSX) || defined(OS_WIN)
+#if defined(OS_MACOSX)
   // Ensure that the renderer doesn't think the plugin still has focus.
   if (render_view_)
     render_view_->PluginFocusChanged(false, instance_id_);
@@ -591,10 +577,6 @@
 
 void WebPluginDelegateProxy::SetFocus(bool focused) {
   Send(new PluginMsg_SetFocus(instance_id_, focused));
-#if defined(OS_WIN)
-  if (render_view_)
-    render_view_->PluginFocusChanged(focused, instance_id_);
-#endif
 }
 
 bool WebPluginDelegateProxy::HandleInputEvent(
@@ -602,14 +584,7 @@
     WebCursor::CursorInfo* cursor_info) {
   bool handled = false;
   WebCursor cursor;
-  // A windowless plugin can enter a modal loop in the context of a
-  // NPP_HandleEvent call, in which case we need to pump messages to
-  // the plugin. We pass of the corresponding event handle to the
-  // plugin process, which is set if the plugin does enter a modal loop.
-  IPC::SyncMessage* message = new PluginMsg_HandleInputEvent(
-      instance_id_, &event, &handled, &cursor);
-  message->set_pump_messages_event(modal_loop_pump_messages_event_.get());
-  Send(message);
+  Send(new PluginMsg_HandleInputEvent(instance_id_, &event, &handled, &cursor));
   return handled;
 }
 
@@ -626,35 +601,6 @@
   Send(msg);
 }
 
-#if defined(OS_WIN)
-void WebPluginDelegateProxy::ImeCompositionUpdated(
-    const base::string16& text,
-    const std::vector<int>& clauses,
-    const std::vector<int>& target,
-    int cursor_position,
-    int plugin_id) {
-  // Dispatch the raw IME data if this plugin is the focused one.
-  if (instance_id_ != plugin_id)
-    return;
-
-  IPC::Message* msg = new PluginMsg_ImeCompositionUpdated(instance_id_,
-      text, clauses, target, cursor_position);
-  msg->set_unblock(true);
-  Send(msg);
-}
-
-void WebPluginDelegateProxy::ImeCompositionCompleted(const base::string16& text,
-                                                     int plugin_id) {
-  // Dispatch the IME text if this plugin is the focused one.
-  if (instance_id_ != plugin_id)
-    return;
-
-  IPC::Message* msg = new PluginMsg_ImeCompositionCompleted(instance_id_, text);
-  msg->set_unblock(true);
-  Send(msg);
-}
-#endif
-
 #if defined(OS_MACOSX)
 void WebPluginDelegateProxy::SetWindowFocus(bool window_has_focus) {
   IPC::Message* msg = new PluginMsg_SetWindowFocus(instance_id_,
@@ -706,50 +652,6 @@
 }
 #endif  // OS_MACOSX
 
-#if defined(OS_WIN)
-void WebPluginDelegateProxy::OnSetWindowlessData(
-      HANDLE modal_loop_pump_messages_event_handle,
-      gfx::NativeViewId dummy_activation_window) {
-  DCHECK(!modal_loop_pump_messages_event_.get());
-  DCHECK(!dummy_activation_window_);
-  base::win::ScopedHandle modal_loop_pump_messages_event(
-      modal_loop_pump_messages_event_handle);
-
-  dummy_activation_window_ = dummy_activation_window;
-  render_view_->Send(new ViewHostMsg_WindowlessPluginDummyWindowCreated(
-      render_view_->GetRoutingID(), dummy_activation_window_));
-
-  // Bug 25583: this can be null because some "virus scanners" block the
-  // DuplicateHandle call in the plugin process.
-  if (!modal_loop_pump_messages_event.IsValid())
-    return;
-
-  modal_loop_pump_messages_event_.reset(
-      new base::WaitableEvent(std::move(modal_loop_pump_messages_event)));
-}
-
-void WebPluginDelegateProxy::OnNotifyIMEStatus(int input_type,
-                                               const gfx::Rect& caret_rect) {
-  if (!render_view_)
-    return;
-
-  ViewHostMsg_TextInputState_Params params;
-  params.type = static_cast<ui::TextInputType>(input_type);
-  params.mode = ui::TEXT_INPUT_MODE_DEFAULT;
-  params.can_compose_inline = true;
-  render_view_->Send(new ViewHostMsg_TextInputStateChanged(
-      render_view_->GetRoutingID(), params));
-
-  ViewHostMsg_SelectionBounds_Params bounds_params;
-  bounds_params.anchor_rect = bounds_params.focus_rect = caret_rect;
-  bounds_params.anchor_dir = bounds_params.focus_dir =
-      blink::WebTextDirectionLeftToRight;
-  bounds_params.is_anchor_first = true;
-  render_view_->Send(new ViewHostMsg_SelectionBoundsChanged(
-      render_view_->GetRoutingID(), bounds_params));
-}
-#endif
-
 void WebPluginDelegateProxy::OnInvalidateRect(const gfx::Rect& rect) {
   if (!plugin_)
     return;
diff --git a/content/renderer/npapi/webplugin_delegate_proxy.h b/content/renderer/npapi/webplugin_delegate_proxy.h
index 9e3643ed..d980de8 100644
--- a/content/renderer/npapi/webplugin_delegate_proxy.h
+++ b/content/renderer/npapi/webplugin_delegate_proxy.h
@@ -80,19 +80,6 @@
   // Informs the plugin that its containing content view has gained or lost
   // first responder status.
   virtual void SetContentAreaFocus(bool has_focus);
-#if defined(OS_WIN)
-  // Informs the plugin that plugin IME has updated its status.
-  virtual void ImeCompositionUpdated(
-      const base::string16& text,
-      const std::vector<int>& clauses,
-      const std::vector<int>& target,
-      int cursor_position,
-      int plugin_id);
-  // Informs the plugin that plugin IME has completed.
-  // If |text| is empty, composition was cancelled.
-  virtual void ImeCompositionCompleted(const base::string16& text,
-                                       int plugin_id);
-#endif
 #if defined(OS_MACOSX)
   // Informs the plugin that its enclosing window has gained or lost focus.
   virtual void SetWindowFocus(bool window_has_focus);
@@ -156,11 +143,6 @@
                                              uint32_t surface_id);
   void OnAcceleratedPluginSwappedIOSurface();
 #endif
-#if defined(OS_WIN)
-  void OnSetWindowlessData(HANDLE modal_loop_pump_messages_event_handle,
-                           gfx::NativeViewId dummy_activation_window);
-  void OnNotifyIMEStatus(const int input_mode, const gfx::Rect& caret_rect);
-#endif
   // Helper function that sends the UpdateGeometry message.
   void SendUpdateGeometry(bool bitmaps_changed);
 
@@ -226,9 +208,6 @@
   bool uses_shared_bitmaps_;
 #if defined(OS_MACOSX)
   bool uses_compositor_;
-#elif defined(OS_WIN)
-  // Used for windowless plugins so that keyboard activation works.
-  gfx::NativeViewId dummy_activation_window_;
 #endif
   scoped_refptr<PluginChannelHost> channel_host_;
   std::string mime_type_;
@@ -243,10 +222,6 @@
   // Dummy NPP used to uniquely identify this plugin.
   scoped_ptr<NPP_t> npp_;
 
-  // Event passed in by the plugin process and is used to decide if messages
-  // need to be pumped in the NPP_HandleEvent sync call.
-  scoped_ptr<base::WaitableEvent> modal_loop_pump_messages_event_;
-
   // Bitmap for crashed plugin
   SkBitmap* sad_plugin_;
 
diff --git a/content/renderer/npapi/webplugin_impl.cc b/content/renderer/npapi/webplugin_impl.cc
index 12ce8966..e57ba46 100644
--- a/content/renderer/npapi/webplugin_impl.cc
+++ b/content/renderer/npapi/webplugin_impl.cc
@@ -122,14 +122,19 @@
       return false;
     }
 
-    // Disable scripting by this plugin before replacing it with the new
-    // one. This plugin also needs destroying, so use destroy(), which will
-    // implicitly disable scripting while un-setting the container.
+    // The replacement plugin, if it exists, must never fail to initialize.
+    container->setPlugin(replacement_plugin);
+    CHECK(replacement_plugin->initialize(container));
+
+    DCHECK(container->plugin() == replacement_plugin);
+    DCHECK(replacement_plugin->container() == container);
+
+    // Since the container now owns the replacement plugin instead of this
+    // object, we must schedule ourselves for deletion. This also implicitly
+    // disables scripting while un-setting the container.
     destroy();
 
-    // Inform the container of the replacement plugin, then initialize it.
-    container->setPlugin(replacement_plugin);
-    return replacement_plugin->initialize(container);
+    return true;
   }
 
   delegate_ = plugin_delegate;
diff --git a/content/renderer/npapi/webplugin_impl.h b/content/renderer/npapi/webplugin_impl.h
index 3e695e6..8d54cc3b 100644
--- a/content/renderer/npapi/webplugin_impl.h
+++ b/content/renderer/npapi/webplugin_impl.h
@@ -110,12 +110,6 @@
   void DidStartLoading() override;
   void DidStopLoading() override;
   bool IsOffTheRecord() override;
-#if defined(OS_WIN)
-  void SetWindowlessData(HANDLE pump_messages_event,
-                         gfx::NativeViewId dummy_activation_window) override {}
-  void ReparentPluginWindow(HWND window, HWND parent) { }
-  void ReportExecutableMemory(size_t size) { }
-#endif
 #if defined(OS_MACOSX)
   WebPluginAcceleratedSurface* GetAcceleratedSurface(
       gfx::GpuPreference gpu_preference) override;
diff --git a/content/renderer/pepper/pepper_webplugin_impl.cc b/content/renderer/pepper/pepper_webplugin_impl.cc
index 7c4e04d..622bfbe 100644
--- a/content/renderer/pepper/pepper_webplugin_impl.cc
+++ b/content/renderer/pepper/pepper_webplugin_impl.cc
@@ -129,17 +129,17 @@
     if (!replacement_plugin)
       return false;
 
-    // Since we are setting the container to own the replacement plugin, we must
-    // schedule ourselves for deletion.
-    destroy();
+    // The replacement plugin, if it exists, must never fail to initialize.
     container->setPlugin(replacement_plugin);
-    if (!replacement_plugin->initialize(container)) {
-      CHECK(replacement_plugin->container() == nullptr);
-      return false;
-    }
+    CHECK(replacement_plugin->initialize(container));
 
-    CHECK(container->plugin() == replacement_plugin);
-    CHECK(replacement_plugin->container() == container);
+    DCHECK(container->plugin() == replacement_plugin);
+    DCHECK(replacement_plugin->container() == container);
+
+    // Since the container now owns the replacement plugin instead of this
+    // object, we must schedule ourselves for deletion.
+    destroy();
+
     return true;
   }
 
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index a46a7ed..c8a00e6 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -74,7 +74,7 @@
 #include "content/common/frame_messages.h"
 #include "content/common/gpu/client/context_provider_command_buffer.h"
 #include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
 #include "content/common/render_frame_setup.mojom.h"
 #include "content/common/render_process_messages.h"
 #include "content/common/resource_messages.h"
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index fc6734c..cf98faf 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -26,6 +26,7 @@
 #include "content/common/content_export.h"
 #include "content/common/frame_replication_state.h"
 #include "content/common/gpu/client/gpu_channel_host.h"
+#include "content/common/gpu_process_launch_causes.h"
 #include "content/common/storage_partition_service.mojom.h"
 #include "content/public/renderer/render_thread.h"
 #include "content/renderer/gpu/compositor_dependencies.h"
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index e5052e83..a88549a 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -638,9 +638,6 @@
 #if defined(OS_ANDROID)
       expected_content_intent_id_(0),
 #endif
-#if defined(OS_WIN)
-      focused_plugin_id_(-1),
-#endif
 #if defined(ENABLE_PLUGINS)
       focused_pepper_plugin_(NULL),
       pepper_last_mouse_event_target_(NULL),
@@ -1210,15 +1207,6 @@
   plugin_delegates_.erase(delegate);
 }
 
-#if defined(OS_WIN)
-void RenderViewImpl::PluginFocusChanged(bool focused, int plugin_id) {
-  if (focused)
-    focused_plugin_id_ = plugin_id;
-  else
-    focused_plugin_id_ = -1;
-}
-#endif
-
 #if defined(OS_MACOSX)
 void RenderViewImpl::PluginFocusChanged(bool focused, int plugin_id) {
   Send(new ViewHostMsg_PluginFocusChanged(GetRoutingID(), focused, plugin_id));
@@ -2926,32 +2914,6 @@
         text, underlines, selection_start, selection_end);
     return;
   }
-
-#if defined(OS_WIN)
-  // When a plugin has focus, we create platform-specific IME data used by
-  // our IME emulator and send it directly to the focused plugin, i.e. we
-  // bypass WebKit. (WebPluginDelegate dispatches this IME data only when its
-  // instance ID is the same one as the specified ID.)
-  if (focused_plugin_id_ >= 0) {
-    std::vector<int> clauses;
-    std::vector<int> target;
-    for (size_t i = 0; i < underlines.size(); ++i) {
-      clauses.push_back(underlines[i].startOffset);
-      clauses.push_back(underlines[i].endOffset);
-      if (underlines[i].thick) {
-        target.clear();
-        target.push_back(underlines[i].startOffset);
-        target.push_back(underlines[i].endOffset);
-      }
-    }
-    std::set<WebPluginDelegateProxy*>::iterator it;
-    for (it = plugin_delegates_.begin(); it != plugin_delegates_.end(); ++it) {
-      (*it)->ImeCompositionUpdated(text, clauses, target, selection_end,
-                                   focused_plugin_id_);
-    }
-    return;
-  }
-#endif  // OS_WIN
 #endif  // ENABLE_PLUGINS
   if (replacement_range.IsValid() && webview()) {
     // Select the text in |replacement_range|, it will then be replaced by
@@ -2980,20 +2942,6 @@
         text, replacement_range, keep_selection);
     return;
   }
-#if defined(OS_WIN)
-  // Same as OnImeSetComposition(), we send the text from IMEs directly to
-  // plugins. When we send IME text directly to plugins, we should not send
-  // it to WebKit to prevent WebKit from controlling IMEs.
-  // TODO(thakis): Honor |replacement_range| for plugins?
-  if (focused_plugin_id_ >= 0) {
-    std::set<WebPluginDelegateProxy*>::iterator it;
-    for (it = plugin_delegates_.begin();
-          it != plugin_delegates_.end(); ++it) {
-      (*it)->ImeCompositionCompleted(text, focused_plugin_id_);
-    }
-    return;
-  }
-#endif  // OS_WIN
 #endif  // ENABLE_PLUGINS
   if (replacement_range.IsValid() && webview()) {
     // Select the text in |replacement_range|, it will then be replaced by
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index d508b9f..b8df750 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -258,12 +258,10 @@
     pepper_last_mouse_event_target_ = plugin;
   }
 
-#if defined(OS_MACOSX) || defined(OS_WIN)
+#if defined(OS_MACOSX)
   // Informs the render view that the given plugin has gained or lost focus.
   void PluginFocusChanged(bool focused, int plugin_id);
-#endif
 
-#if defined(OS_MACOSX)
   // Starts plugin IME.
   void StartPluginIme();
 #endif
@@ -942,11 +940,6 @@
   // location or tab focus and visibily. These are non-owning references.
   std::set<WebPluginDelegateProxy*> plugin_delegates_;
 
-#if defined(OS_WIN)
-  // The ID of the focused NPAPI plugin.
-  int focused_plugin_id_;
-#endif
-
 #if defined(ENABLE_PLUGINS)
   typedef std::set<PepperPluginInstanceImpl*> PepperPluginSet;
   PepperPluginSet active_pepper_instances_;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index a4b9d63..c173264 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -33,7 +33,7 @@
 #include "content/common/content_switches_internal.h"
 #include "content/common/gpu/client/context_provider_command_buffer.h"
 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
 #include "content/common/input/synthetic_gesture_packet.h"
 #include "content/common/input/web_input_event_traits.h"
 #include "content/common/input_messages.h"
@@ -752,14 +752,16 @@
 #if defined(OS_ANDROID)
     if (SynchronousCompositorFactory* factory =
             SynchronousCompositorFactory::GetInstance()) {
+      uint32_t output_surface_id = next_output_surface_id_++;
       return factory->CreateOutputSurface(
-          routing_id(), frame_swap_message_queue_, context_provider,
-          worker_context_provider);
+          routing_id(), output_surface_id, frame_swap_message_queue_,
+          context_provider, worker_context_provider);
     } else if (RenderThreadImpl::current()->sync_compositor_message_filter()) {
+      uint32_t output_surface_id = next_output_surface_id_++;
       return make_scoped_ptr(new SynchronousCompositorOutputSurface(
           context_provider, worker_context_provider, routing_id(),
-          content::RenderThreadImpl::current()
-              ->sync_compositor_message_filter(),
+          output_surface_id, content::RenderThreadImpl::current()
+                                 ->sync_compositor_message_filter(),
           frame_swap_message_queue_));
     }
 #endif
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 9409b902..bc4fdfbd 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -45,7 +45,7 @@
 #include "content/common/gpu/client/context_provider_command_buffer.h"
 #include "content/common/gpu/client/gpu_channel_host.h"
 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
 #include "content/common/mime_registry_messages.h"
 #include "content/common/render_process_messages.h"
 #include "content/public/common/content_switches.h"
@@ -447,6 +447,12 @@
   return WebFileSystemImpl::ThreadSpecificInstance(default_task_runner_);
 }
 
+WebString RendererBlinkPlatformImpl::fileSystemCreateOriginIdentifier(
+    const blink::WebSecurityOrigin& origin) {
+  return WebString::fromUTF8(storage::GetIdentifierFromOrigin(
+      WebSecurityOriginToGURL(origin)));
+}
+
 //------------------------------------------------------------------------------
 
 WebMimeRegistry::SupportsType
@@ -607,9 +613,12 @@
 }
 
 long long RendererBlinkPlatformImpl::databaseGetSpaceAvailableForOrigin(
-    const WebString& origin_identifier) {
-  return DatabaseUtil::DatabaseGetSpaceAvailable(origin_identifier,
-                                                 sync_message_filter_.get());
+    const blink::WebSecurityOrigin& origin) {
+  // TODO(jsbell): Pass url::Origin over IPC instead of database
+  // identifier/GURL. https://crbug.com/591482
+  return DatabaseUtil::DatabaseGetSpaceAvailable(WebString::fromUTF8(
+      storage::GetIdentifierFromOrigin(WebSecurityOriginToGURL(origin))),
+      sync_message_filter_.get());
 }
 
 bool RendererBlinkPlatformImpl::databaseSetFileSize(
@@ -618,6 +627,12 @@
       vfs_file_name, size, sync_message_filter_.get());
 }
 
+WebString RendererBlinkPlatformImpl::databaseCreateOriginIdentifier(
+    const blink::WebSecurityOrigin& origin) {
+  return WebString::fromUTF8(storage::GetIdentifierFromOrigin(
+      WebSecurityOriginToGURL(origin)));
+}
+
 bool RendererBlinkPlatformImpl::canAccelerate2dCanvas() {
   RenderThreadImpl* thread = RenderThreadImpl::current();
   GpuChannelHost* host = thread->EstablishGpuChannelSync(
@@ -944,22 +959,7 @@
 
 //------------------------------------------------------------------------------
 
-blink::WebGraphicsContext3D*
-RendererBlinkPlatformImpl::createOffscreenGraphicsContext3D(
-    const blink::WebGraphicsContext3D::Attributes& attributes) {
-  return createOffscreenGraphicsContext3D(attributes, NULL);
-}
-
-blink::WebGraphicsContext3D*
-RendererBlinkPlatformImpl::createOffscreenGraphicsContext3D(
-    const blink::WebGraphicsContext3D::Attributes& attributes,
-    blink::WebGraphicsContext3D* share_context) {
-  blink::WebGraphicsContext3D::WebGraphicsInfo gl_info;
-  return createOffscreenGraphicsContext3D(attributes, share_context, &gl_info);
-}
-
 static void Collect3DContextInformationOnFailure(
-    blink::WebGraphicsContext3D* share_context,
     blink::WebGraphicsContext3D::WebGraphicsInfo* gl_info,
     GpuChannelHost* host) {
   DCHECK(gl_info);
@@ -997,44 +997,43 @@
   }
 }
 
-blink::WebGraphicsContext3D*
-RendererBlinkPlatformImpl::createOffscreenGraphicsContext3D(
+blink::WebGraphicsContext3DProvider*
+RendererBlinkPlatformImpl::createOffscreenGraphicsContext3DProvider(
     const blink::WebGraphicsContext3D::Attributes& attributes,
-    blink::WebGraphicsContext3D* share_context,
+    blink::WebGraphicsContext3DProvider* share_provider,
     blink::WebGraphicsContext3D::WebGraphicsInfo* gl_info) {
   DCHECK(gl_info);
   if (!RenderThreadImpl::current()) {
     std::string error_message("Failed to run in Current RenderThreadImpl");
     gl_info->errorMessage = WebString::fromUTF8(error_message);
-    return NULL;
+    return nullptr;
   }
 
   scoped_refptr<GpuChannelHost> gpu_channel_host(
       RenderThreadImpl::current()->EstablishGpuChannelSync(
           CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
 
+  WebGraphicsContext3DCommandBufferImpl* share_context =
+      share_provider ? static_cast<WebGraphicsContext3DCommandBufferImpl*>(
+                           share_provider->context3d())
+                     : nullptr;
   WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
   bool lose_context_when_out_of_memory = false;
   scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
       WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
-          gpu_channel_host.get(),
-          attributes,
-          lose_context_when_out_of_memory,
-          blink::WebStringToGURL(attributes.topDocumentURL),
-          limits,
-          static_cast<WebGraphicsContext3DCommandBufferImpl*>(share_context)));
-
-  // Most likely the GPU process exited and the attempt to reconnect to it
-  // failed. Need to try to restore the context again later.
-  if (!context || !context->InitializeOnCurrentThread() ||
-      gl_info->testFailContext) {
+          gpu_channel_host.get(), attributes, lose_context_when_out_of_memory,
+          blink::WebStringToGURL(attributes.topDocumentURL), limits,
+          share_context));
+  scoped_refptr<ContextProviderCommandBuffer> provider =
+      ContextProviderCommandBuffer::Create(std::move(context),
+                                           RENDERER_MAINTHREAD_CONTEXT);
+  if (!provider || !provider->BindToCurrentThread()) {
     // Collect Graphicsinfo if there is a context failure or it is failed
     // purposefully in case of layout tests.
-    Collect3DContextInformationOnFailure(share_context, gl_info,
-                                         gpu_channel_host.get());
-      return NULL;
+    Collect3DContextInformationOnFailure(gl_info, gpu_channel_host.get());
+    return nullptr;
   }
-  return context.release();
+  return new WebGraphicsContext3DProviderImpl(std::move(provider));
 }
 
 //------------------------------------------------------------------------------
@@ -1043,9 +1042,9 @@
 RendererBlinkPlatformImpl::createSharedOffscreenGraphicsContext3DProvider() {
   scoped_refptr<cc_blink::ContextProviderWebContext> provider =
       RenderThreadImpl::current()->SharedMainThreadContextProvider();
-  if (!provider.get())
-    return NULL;
-  return new WebGraphicsContext3DProviderImpl(provider);
+  if (!provider)
+    return nullptr;
+  return new WebGraphicsContext3DProviderImpl(std::move(provider));
 }
 
 //------------------------------------------------------------------------------
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
index 6fc81555d..5893735 100644
--- a/content/renderer/renderer_blink_platform_impl.h
+++ b/content/renderer/renderer_blink_platform_impl.h
@@ -106,9 +106,12 @@
       const blink::WebString& vfs_file_name) override;
   long long databaseGetFileSize(const blink::WebString& vfs_file_name) override;
   long long databaseGetSpaceAvailableForOrigin(
-      const blink::WebString& origin_identifier) override;
+      const blink::WebSecurityOrigin& origin) override;
   bool databaseSetFileSize(const blink::WebString& vfs_file_name,
                            long long size) override;
+  blink::WebString databaseCreateOriginIdentifier(
+      const blink::WebSecurityOrigin& origin) override;
+
   blink::WebString signedPublicKeyAndChallengeString(
       unsigned key_size_index,
       const blink::WebString& challenge,
@@ -123,6 +126,9 @@
   blink::WebServiceWorkerCacheStorage* cacheStorage(
       const blink::WebSecurityOrigin& security_origin) override;
   blink::WebFileSystem* fileSystem() override;
+  blink::WebString fileSystemCreateOriginIdentifier(
+      const blink::WebSecurityOrigin& origin) override;
+
   bool canAccelerate2dCanvas() override;
   bool isThreadedCompositingEnabled() override;
   bool isThreadedAnimationEnabled() override;
@@ -162,14 +168,9 @@
   void createHTMLVideoElementCapturer(
       blink::WebMediaStream* web_media_stream,
       blink::WebMediaPlayer* web_media_player) override;
-  blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D(
-      const blink::WebGraphicsContext3D::Attributes& attributes) override;
-  blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D(
+  blink::WebGraphicsContext3DProvider* createOffscreenGraphicsContext3DProvider(
       const blink::WebGraphicsContext3D::Attributes& attributes,
-      blink::WebGraphicsContext3D* share_context) override;
-  blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D(
-      const blink::WebGraphicsContext3D::Attributes& attributes,
-      blink::WebGraphicsContext3D* share_context,
+      blink::WebGraphicsContext3DProvider* share_provider,
       blink::WebGraphicsContext3D::WebGraphicsInfo* gl_info) override;
   blink::WebGraphicsContext3DProvider*
   createSharedOffscreenGraphicsContext3DProvider() override;
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn
index 9ceb8eb..6ce50f8 100644
--- a/content/shell/BUILD.gn
+++ b/content/shell/BUILD.gn
@@ -143,6 +143,8 @@
     "browser/shell_web_contents_view_delegate_creator.h",
     "browser/shell_web_contents_view_delegate_mac.mm",
     "browser/shell_web_contents_view_delegate_win.cc",
+    "common/layout_test/layout_test_content_client.cc",
+    "common/layout_test/layout_test_content_client.h",
     "common/layout_test/layout_test_messages.cc",
     "common/layout_test/layout_test_messages.h",
     "common/layout_test/layout_test_switches.cc",
diff --git a/content/shell/app/shell_main_delegate.cc b/content/shell/app/shell_main_delegate.cc
index 5a4c73f..0401ad7f 100644
--- a/content/shell/app/shell_main_delegate.cc
+++ b/content/shell/app/shell_main_delegate.cc
@@ -26,7 +26,9 @@
 #include "content/shell/browser/layout_test/layout_test_content_browser_client.h"
 #include "content/shell/browser/shell_browser_main.h"
 #include "content/shell/browser/shell_content_browser_client.h"
+#include "content/shell/common/layout_test/layout_test_content_client.h"
 #include "content/shell/common/layout_test/layout_test_switches.h"
+#include "content/shell/common/shell_content_client.h"
 #include "content/shell/common/shell_switches.h"
 #include "content/shell/renderer/layout_test/layout_test_content_renderer_client.h"
 #include "content/shell/renderer/shell_content_renderer_client.h"
@@ -211,7 +213,13 @@
       return true;
     }
   }
-  SetContentClient(&content_client_);
+
+  content_client_.reset(base::CommandLine::ForCurrentProcess()->HasSwitch(
+                            switches::kRunLayoutTest)
+                            ? new LayoutTestContentClient
+                            : new ShellContentClient);
+  SetContentClient(content_client_.get());
+
   return false;
 }
 
diff --git a/content/shell/app/shell_main_delegate.h b/content/shell/app/shell_main_delegate.h
index 6b351e4f..59cf53c 100644
--- a/content/shell/app/shell_main_delegate.h
+++ b/content/shell/app/shell_main_delegate.h
@@ -10,9 +10,9 @@
 #include "base/memory/scoped_ptr.h"
 #include "build/build_config.h"
 #include "content/public/app/content_main_delegate.h"
-#include "content/shell/common/shell_content_client.h"
 
 namespace content {
+class ContentClient;
 class ShellContentBrowserClient;
 class ShellContentRendererClient;
 class ShellContentUtilityClient;
@@ -44,7 +44,7 @@
   scoped_ptr<ShellContentBrowserClient> browser_client_;
   scoped_ptr<ShellContentRendererClient> renderer_client_;
   scoped_ptr<ShellContentUtilityClient> utility_client_;
-  ShellContentClient content_client_;
+  scoped_ptr<ContentClient> content_client_;
 
 #if defined(OS_ANDROID)
   scoped_ptr<BrowserMainRunner> browser_runner_;
diff --git a/content/shell/common/layout_test/layout_test_content_client.cc b/content/shell/common/layout_test/layout_test_content_client.cc
new file mode 100644
index 0000000..8c7a533
--- /dev/null
+++ b/content/shell/common/layout_test/layout_test_content_client.cc
@@ -0,0 +1,24 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/shell/common/layout_test/layout_test_content_client.h"
+
+#include "content/shell/common/shell_messages.h"
+
+namespace content {
+
+bool LayoutTestContentClient::CanSendWhileSwappedOut(
+    const IPC::Message* message) {
+  switch (message->type()) {
+    // Used in layout tests; handled in BlinkTestController.
+    case ShellViewHostMsg_PrintMessage::ID:
+    case ShellViewHostMsg_LayoutDumpFlagsChanged::ID:
+      return true;
+
+    default:
+      return false;
+  }
+}
+
+}  // namespace content
diff --git a/content/shell/common/layout_test/layout_test_content_client.h b/content/shell/common/layout_test/layout_test_content_client.h
new file mode 100644
index 0000000..2f2b4b9
--- /dev/null
+++ b/content/shell/common/layout_test/layout_test_content_client.h
@@ -0,0 +1,24 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_SHELL_COMMON_LAYOUT_TEST_LAYOUT_TEST_CONTENT_CLIENT_H_
+#define CONTENT_SHELL_COMMON_LAYOUT_TEST_LAYOUT_TEST_CONTENT_CLIENT_H_
+
+#include "base/macros.h"
+#include "content/shell/common/shell_content_client.h"
+
+namespace content {
+
+class LayoutTestContentClient : public ShellContentClient {
+ public:
+  LayoutTestContentClient() {}
+  bool CanSendWhileSwappedOut(const IPC::Message* message) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LayoutTestContentClient);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_SHELL_COMMON_LAYOUT_TEST_LAYOUT_TEST_CONTENT_CLIENT_H_
diff --git a/content/test/data/android/media/audio-1second.mp3 b/content/test/data/android/media/audio-1second.mp3
deleted file mode 100644
index 8f03918..0000000
--- a/content/test/data/android/media/audio-1second.mp3
+++ /dev/null
Binary files differ
diff --git a/content/test/data/android/media/audio-2seconds.mp3 b/content/test/data/android/media/audio-2seconds.mp3
deleted file mode 100644
index 8f03918..0000000
--- a/content/test/data/android/media/audio-2seconds.mp3
+++ /dev/null
Binary files differ
diff --git a/content/test/data/android/media/audio-6seconds.mp3 b/content/test/data/android/media/audio-6seconds.mp3
deleted file mode 100644
index 3f0adb8..0000000
--- a/content/test/data/android/media/audio-6seconds.mp3
+++ /dev/null
Binary files differ
diff --git a/content/test/data/android/media/media-session.html b/content/test/data/android/media/media-session.html
index e1c3b0d..2c291619 100644
--- a/content/test/data/android/media/media-session.html
+++ b/content/test/data/android/media/media-session.html
@@ -6,28 +6,25 @@
 </head>
 <body>
   <audio id='very-short-audio' controls>
-    <source src='audio-1second.mp3'>
     <source src='audio-1second.ogg'>
   </audio>
   <audio id='short-audio' controls>
-    <source src='audio-2seconds.mp3'>
     <source src='audio-2seconds.ogg'>
   </audio>
   <audio id='long-audio' controls>
-    <source src='audio-6seconds.mp3'>
     <source src='audio-6seconds.ogg'>
   </audio>
   <video id='very-short-video' controls>
-    <source src='video-1second.mp4'>
+    <source src='video-1second.webm'>
   </video>
   <video id='short-video' controls>
-    <source src='video-2seconds.mp4'>
+    <source src='video-2seconds.webm'>
   </video>
   <video id='long-video' controls>
-    <source src='video-6seconds.mp4'>
+    <source src='video-6seconds.webm'>
   </video>
   <video id='long-video-silent' controls>
-    <source src='video-6seconds-silent.mp4'>
+    <source src='video-6seconds-silent.webm'>
   </video>
 </body>
 </html>
diff --git a/content/test/data/android/media/video-1second.mp4 b/content/test/data/android/media/video-1second.mp4
deleted file mode 100644
index d8f89587..0000000
--- a/content/test/data/android/media/video-1second.mp4
+++ /dev/null
Binary files differ
diff --git a/content/test/data/android/media/video-1second.webm b/content/test/data/android/media/video-1second.webm
new file mode 100644
index 0000000..0c0c0493
--- /dev/null
+++ b/content/test/data/android/media/video-1second.webm
Binary files differ
diff --git a/content/test/data/android/media/video-2seconds.mp4 b/content/test/data/android/media/video-2seconds.mp4
deleted file mode 100644
index ec0c507e..0000000
--- a/content/test/data/android/media/video-2seconds.mp4
+++ /dev/null
Binary files differ
diff --git a/content/test/data/android/media/video-2seconds.webm b/content/test/data/android/media/video-2seconds.webm
new file mode 100644
index 0000000..830c3ac3
--- /dev/null
+++ b/content/test/data/android/media/video-2seconds.webm
Binary files differ
diff --git a/content/test/data/android/media/video-6seconds-silent.mp4 b/content/test/data/android/media/video-6seconds-silent.mp4
deleted file mode 100644
index 693ae31..0000000
--- a/content/test/data/android/media/video-6seconds-silent.mp4
+++ /dev/null
Binary files differ
diff --git a/content/test/data/android/media/video-6seconds-silent.webm b/content/test/data/android/media/video-6seconds-silent.webm
new file mode 100644
index 0000000..880968d
--- /dev/null
+++ b/content/test/data/android/media/video-6seconds-silent.webm
Binary files differ
diff --git a/content/test/data/android/media/video-6seconds.mp4 b/content/test/data/android/media/video-6seconds.mp4
deleted file mode 100644
index d278c8a..0000000
--- a/content/test/data/android/media/video-6seconds.mp4
+++ /dev/null
Binary files differ
diff --git a/content/test/data/android/media/video-6seconds.webm b/content/test/data/android/media/video-6seconds.webm
new file mode 100644
index 0000000..40634b1
--- /dev/null
+++ b/content/test/data/android/media/video-6seconds.webm
Binary files differ
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 4f43eb0..3d1c8a6 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -399,6 +399,8 @@
         ['linux', 'amd'], bug=483282)
     self.Fail('conformance2/reading/read-pixels-from-fbo-test.html',
         ['linux', 'amd'], bug=483282)
+    self.Fail('conformance2/reading/read-pixels-pack-parameters.html',
+        ['linux', 'amd'], bug=483282)
     self.Fail('conformance2/reading/read-pixels-into-pixel-pack-buffer.html',
         ['linux', 'amd'], bug=483282)
     self.Fail('conformance2/textures/misc/tex-mipmap-levels.html',
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc
index bb5999e..761ae47 100644
--- a/content/test/test_render_view_host.cc
+++ b/content/test/test_render_view_host.cc
@@ -205,11 +205,6 @@
 void TestRenderWidgetHostView::SetParentNativeViewAccessible(
     gfx::NativeViewAccessible accessible_parent) {
 }
-
-gfx::NativeViewId TestRenderWidgetHostView::GetParentForWindowlessPlugin()
-    const {
-  return 0;
-}
 #endif
 
 TestRenderViewHost::TestRenderViewHost(SiteInstance* instance,
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h
index 5dbcd3e..1291ab4 100644
--- a/content/test/test_render_view_host.h
+++ b/content/test/test_render_view_host.h
@@ -138,7 +138,6 @@
 #if defined(OS_WIN)
   void SetParentNativeViewAccessible(
       gfx::NativeViewAccessible accessible_parent) override;
-  gfx::NativeViewId GetParentForWindowlessPlugin() const override;
 #endif
 
   bool is_showing() const { return is_showing_; }
diff --git a/device/bluetooth/bluetooth_adapter.h b/device/bluetooth/bluetooth_adapter.h
index 5dcf12f5..80bd176 100644
--- a/device/bluetooth/bluetooth_adapter.h
+++ b/device/bluetooth/bluetooth_adapter.h
@@ -202,6 +202,7 @@
       DiscoverySessionCallback;
   typedef std::vector<BluetoothDevice*> DeviceList;
   typedef std::vector<const BluetoothDevice*> ConstDeviceList;
+  typedef std::vector<BluetoothUUID> UUIDList;
   typedef base::Callback<void(scoped_refptr<BluetoothSocket>)>
       CreateServiceCallback;
   typedef base::Callback<void(const std::string& message)>
@@ -328,6 +329,11 @@
   virtual BluetoothDevice* GetDevice(const std::string& address);
   virtual const BluetoothDevice* GetDevice(const std::string& address) const;
 
+  // Returns a list of UUIDs for services registered on this adapter.
+  // This may include UUIDs from standard profiles (e.g. A2DP) as well
+  // as those created by CreateRfcommService and CreateL2capService.
+  virtual UUIDList GetUUIDs() const = 0;
+
   // Possible priorities for AddPairingDelegate(), low is intended for
   // permanent UI and high is intended for interactive UI or applications.
   enum PairingDelegatePriority {
diff --git a/device/bluetooth/bluetooth_adapter_android.cc b/device/bluetooth/bluetooth_adapter_android.cc
index fc19a812..b3891a47 100644
--- a/device/bluetooth/bluetooth_adapter_android.cc
+++ b/device/bluetooth/bluetooth_adapter_android.cc
@@ -102,6 +102,11 @@
                                                    j_adapter_.obj());
 }
 
+BluetoothAdapter::UUIDList BluetoothAdapterAndroid::GetUUIDs() const {
+  NOTIMPLEMENTED();
+  return UUIDList();
+}
+
 void BluetoothAdapterAndroid::CreateRfcommService(
     const BluetoothUUID& uuid,
     const ServiceOptions& options,
diff --git a/device/bluetooth/bluetooth_adapter_android.h b/device/bluetooth/bluetooth_adapter_android.h
index 8ebb49ce..66df14f3e 100644
--- a/device/bluetooth/bluetooth_adapter_android.h
+++ b/device/bluetooth/bluetooth_adapter_android.h
@@ -64,6 +64,7 @@
                        const base::Closure& callback,
                        const ErrorCallback& error_callback) override;
   bool IsDiscovering() const override;
+  UUIDList GetUUIDs() const override;
   void CreateRfcommService(
       const BluetoothUUID& uuid,
       const ServiceOptions& options,
diff --git a/device/bluetooth/bluetooth_adapter_bluez.cc b/device/bluetooth/bluetooth_adapter_bluez.cc
index 4424b02..91345fc 100644
--- a/device/bluetooth/bluetooth_adapter_bluez.cc
+++ b/device/bluetooth/bluetooth_adapter_bluez.cc
@@ -328,6 +328,18 @@
   return properties->discovering.value();
 }
 
+BluetoothAdapterBlueZ::UUIDList BluetoothAdapterBlueZ::GetUUIDs() const {
+  bluez::BluetoothAdapterClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothAdapterClient()
+          ->GetProperties(object_path_);
+  DCHECK(properties);
+
+  std::vector<std::string> uuids = properties->uuids.value();
+
+  return UUIDList(uuids.begin(), uuids.end());
+}
+
 void BluetoothAdapterBlueZ::CreateRfcommService(
     const BluetoothUUID& uuid,
     const ServiceOptions& options,
diff --git a/device/bluetooth/bluetooth_adapter_bluez.h b/device/bluetooth/bluetooth_adapter_bluez.h
index 3d402d4f..de52c89 100644
--- a/device/bluetooth/bluetooth_adapter_bluez.h
+++ b/device/bluetooth/bluetooth_adapter_bluez.h
@@ -79,6 +79,7 @@
 
   // BluetoothAdapter:
   void Shutdown() override;
+  UUIDList GetUUIDs() const override;
   std::string GetAddress() const override;
   std::string GetName() const override;
   void SetName(const std::string& name,
diff --git a/device/bluetooth/bluetooth_adapter_mac.h b/device/bluetooth/bluetooth_adapter_mac.h
index 7bd221d..b632741 100644
--- a/device/bluetooth/bluetooth_adapter_mac.h
+++ b/device/bluetooth/bluetooth_adapter_mac.h
@@ -65,6 +65,7 @@
                        const base::Closure& callback,
                        const ErrorCallback& error_callback) override;
   bool IsDiscovering() const override;
+  UUIDList GetUUIDs() const override;
   void CreateRfcommService(
       const BluetoothUUID& uuid,
       const ServiceOptions& options,
diff --git a/device/bluetooth/bluetooth_adapter_mac.mm b/device/bluetooth/bluetooth_adapter_mac.mm
index 2c431a4..78c9ee9 100644
--- a/device/bluetooth/bluetooth_adapter_mac.mm
+++ b/device/bluetooth/bluetooth_adapter_mac.mm
@@ -165,6 +165,11 @@
   return is_discovering;
 }
 
+BluetoothAdapter::UUIDList BluetoothAdapterMac::GetUUIDs() const {
+  NOTIMPLEMENTED();
+  return UUIDList();
+}
+
 void BluetoothAdapterMac::CreateRfcommService(
     const BluetoothUUID& uuid,
     const ServiceOptions& options,
diff --git a/device/bluetooth/bluetooth_adapter_unittest.cc b/device/bluetooth/bluetooth_adapter_unittest.cc
index 55bffb7..feba430 100644
--- a/device/bluetooth/bluetooth_adapter_unittest.cc
+++ b/device/bluetooth/bluetooth_adapter_unittest.cc
@@ -70,6 +70,9 @@
 
   void StartDiscoverySession(const DiscoverySessionCallback& callback,
                              const ErrorCallback& error_callback) override {}
+
+  UUIDList GetUUIDs() const override { return UUIDList(); }
+
   void CreateRfcommService(
       const BluetoothUUID& uuid,
       const ServiceOptions& options,
diff --git a/device/bluetooth/bluetooth_adapter_win.cc b/device/bluetooth/bluetooth_adapter_win.cc
index c946091..33e1501 100644
--- a/device/bluetooth/bluetooth_adapter_win.cc
+++ b/device/bluetooth/bluetooth_adapter_win.cc
@@ -158,6 +158,11 @@
   MaybePostStartDiscoveryTask();
 }
 
+BluetoothAdapter::UUIDList BluetoothAdapterWin::GetUUIDs() const {
+  NOTIMPLEMENTED();
+  return UUIDList();
+}
+
 void BluetoothAdapterWin::CreateRfcommService(
     const BluetoothUUID& uuid,
     const ServiceOptions& options,
diff --git a/device/bluetooth/bluetooth_adapter_win.h b/device/bluetooth/bluetooth_adapter_win.h
index bb8f16b..8781c66 100644
--- a/device/bluetooth/bluetooth_adapter_win.h
+++ b/device/bluetooth/bluetooth_adapter_win.h
@@ -59,6 +59,7 @@
                        const base::Closure& callback,
                        const ErrorCallback& error_callback) override;
   bool IsDiscovering() const override;
+  UUIDList GetUUIDs() const override;
   void CreateRfcommService(
       const BluetoothUUID& uuid,
       const ServiceOptions& options,
diff --git a/device/bluetooth/bluetooth_bluez_unittest.cc b/device/bluetooth/bluetooth_bluez_unittest.cc
index 5186bdc..780a0be 100644
--- a/device/bluetooth/bluetooth_bluez_unittest.cc
+++ b/device/bluetooth/bluetooth_bluez_unittest.cc
@@ -170,6 +170,11 @@
 
 class BluetoothBlueZTest : public testing::Test {
  public:
+  static const char kGapUuid[];
+  static const char kGattUuid[];
+  static const char kPnpUuid[];
+  static const char kHeadsetUuid[];
+
   void SetUp() override {
     scoped_ptr<bluez::BluezDBusManagerSetter> dbus_setter =
         bluez::BluezDBusManager::GetSetterForTesting();
@@ -373,6 +378,14 @@
     }
   }
 };
+const char BluetoothBlueZTest::kGapUuid[] =
+    "00001800-0000-1000-8000-00805f9b34fb";
+const char BluetoothBlueZTest::kGattUuid[] =
+    "00001801-0000-1000-8000-00805f9b34fb";
+const char BluetoothBlueZTest::kPnpUuid[] =
+    "00001200-0000-1000-8000-00805f9b34fb";
+const char BluetoothBlueZTest::kHeadsetUuid[] =
+    "00001112-0000-1000-8000-00805f9b34fb";
 
 TEST_F(BluetoothBlueZTest, AlreadyPresent) {
   GetAdapter();
@@ -612,6 +625,28 @@
   EXPECT_EQ("", adapter_->GetName());
 }
 
+TEST_F(BluetoothBlueZTest, GetUUIDs) {
+  std::vector<std::string> adapterUuids;
+  GetAdapter();
+
+  adapterUuids.push_back(kGapUuid);
+  adapterUuids.push_back(kGattUuid);
+  adapterUuids.push_back(kPnpUuid);
+  adapterUuids.push_back(kHeadsetUuid);
+
+  fake_bluetooth_adapter_client_->SetUUIDs(adapterUuids);
+
+  BluetoothAdapter::UUIDList uuids = adapter_->GetUUIDs();
+
+  ASSERT_EQ(4U, uuids.size());
+  // Check that the UUIDs match those from above - in order, GAP, GATT, PnP, and
+  // headset.
+  EXPECT_EQ(uuids[0], BluetoothUUID("1800"));
+  EXPECT_EQ(uuids[1], BluetoothUUID("1801"));
+  EXPECT_EQ(uuids[2], BluetoothUUID("1200"));
+  EXPECT_EQ(uuids[3], BluetoothUUID("1112"));
+}
+
 TEST_F(BluetoothBlueZTest, BecomeDiscoverable) {
   GetAdapter();
   ASSERT_FALSE(adapter_->IsDiscoverable());
diff --git a/device/bluetooth/dbus/fake_bluetooth_adapter_client.cc b/device/bluetooth/dbus/fake_bluetooth_adapter_client.cc
index f928768..9083b6b 100644
--- a/device/bluetooth/dbus/fake_bluetooth_adapter_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_adapter_client.cc
@@ -269,6 +269,16 @@
   }
 }
 
+void FakeBluetoothAdapterClient::SetUUIDs(
+    const std::vector<std::string>& uuids) {
+  properties_->uuids.ReplaceValue(uuids);
+}
+
+void FakeBluetoothAdapterClient::SetSecondUUIDs(
+    const std::vector<std::string>& uuids) {
+  second_properties_->uuids.ReplaceValue(uuids);
+}
+
 void FakeBluetoothAdapterClient::OnPropertyChanged(
     const std::string& property_name) {
   if (property_name == properties_->powered.name() &&
diff --git a/device/bluetooth/dbus/fake_bluetooth_adapter_client.h b/device/bluetooth/dbus/fake_bluetooth_adapter_client.h
index 0dced89c..702bf230 100644
--- a/device/bluetooth/dbus/fake_bluetooth_adapter_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_adapter_client.h
@@ -5,6 +5,7 @@
 #ifndef DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_ADAPTER_CLIENT_H_
 #define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_ADAPTER_CLIENT_H_
 
+#include <string>
 #include <vector>
 
 #include "base/bind.h"
@@ -72,6 +73,10 @@
   void SetVisible(bool visible);
   void SetSecondVisible(bool visible);
 
+  // Set adapter UUIDs
+  void SetUUIDs(const std::vector<std::string>& uuids);
+  void SetSecondUUIDs(const std::vector<std::string>& uuids);
+
   // Object path, name and addresses of the adapters we emulate.
   static const char kAdapterPath[];
   static const char kAdapterName[];
diff --git a/device/bluetooth/test/mock_bluetooth_adapter.h b/device/bluetooth/test/mock_bluetooth_adapter.h
index 1bdb2153..e4cef59 100644
--- a/device/bluetooth/test/mock_bluetooth_adapter.h
+++ b/device/bluetooth/test/mock_bluetooth_adapter.h
@@ -76,6 +76,7 @@
   MOCK_METHOD1(GetDevice, BluetoothDevice*(const std::string& address));
   MOCK_CONST_METHOD1(GetDevice,
                      const BluetoothDevice*(const std::string& address));
+  MOCK_CONST_METHOD0(GetUUIDs, UUIDList());
   MOCK_METHOD2(AddPairingDelegate,
                void(BluetoothDevice::PairingDelegate* pairing_delegate,
                     enum PairingDelegatePriority priority));
diff --git a/extensions/extensions.gypi b/extensions/extensions.gypi
index e1c30bf..4ecff0d 100644
--- a/extensions/extensions.gypi
+++ b/extensions/extensions.gypi
@@ -1038,6 +1038,8 @@
     'extensions_renderer_sources_wifi_display': [
       'renderer/api/display_source/wifi_display/wifi_display_elementary_stream_descriptor.cc',
       'renderer/api/display_source/wifi_display/wifi_display_elementary_stream_descriptor.h',
+      'renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.cc',
+      'renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.h',
       'renderer/api/display_source/wifi_display/wifi_display_elementary_stream_packetizer.cc',
       'renderer/api/display_source/wifi_display/wifi_display_elementary_stream_packetizer.h',
       'renderer/api/display_source/wifi_display/wifi_display_media_manager.cc',
@@ -1045,6 +1047,8 @@
       'renderer/api/display_source/wifi_display/wifi_display_session.cc',
       'renderer/api/display_source/wifi_display/wifi_display_session.h',
       'renderer/api/display_source/wifi_display/wifi_display_stream_packet_part.h',
+      'renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.cc',
+      'renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.h',
     ],
     'extensions_utility_sources': [
       'utility/unpacker.cc',
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.cc
new file mode 100644
index 0000000..2c84885db
--- /dev/null
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.cc
@@ -0,0 +1,46 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.h"
+
+#include <utility>
+
+namespace extensions {
+
+WiFiDisplayElementaryStreamInfo::WiFiDisplayElementaryStreamInfo(
+    ElementaryStreamType type)
+    : type_(type) {}
+
+WiFiDisplayElementaryStreamInfo::WiFiDisplayElementaryStreamInfo(
+    ElementaryStreamType type,
+    DescriptorVector descriptors)
+    : descriptors_(std::move(descriptors)), type_(type) {}
+
+WiFiDisplayElementaryStreamInfo::WiFiDisplayElementaryStreamInfo(
+    const WiFiDisplayElementaryStreamInfo&) = default;
+
+WiFiDisplayElementaryStreamInfo::WiFiDisplayElementaryStreamInfo(
+    WiFiDisplayElementaryStreamInfo&&) = default;
+
+WiFiDisplayElementaryStreamInfo::~WiFiDisplayElementaryStreamInfo() {}
+
+WiFiDisplayElementaryStreamInfo& WiFiDisplayElementaryStreamInfo::operator=(
+    WiFiDisplayElementaryStreamInfo&&) = default;
+
+void WiFiDisplayElementaryStreamInfo::AddDescriptor(
+    WiFiDisplayElementaryStreamDescriptor descriptor) {
+  descriptors_.emplace_back(std::move(descriptor));
+}
+
+const WiFiDisplayElementaryStreamDescriptor*
+WiFiDisplayElementaryStreamInfo::FindDescriptor(
+    DescriptorTag descriptor_tag) const {
+  for (const auto& descriptor : descriptors()) {
+    if (descriptor.tag() == descriptor_tag)
+      return &descriptor;
+  }
+  return nullptr;
+}
+
+}  // namespace extensions
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.h b/extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.h
new file mode 100644
index 0000000..a0e63a82
--- /dev/null
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.h
@@ -0,0 +1,58 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_RENDERER_API_DISPLAY_SOURCE_WIFI_DISPLAY_WIFI_DISPLAY_ELEMENTARY_STREAM_INFO_H_
+#define EXTENSIONS_RENDERER_API_DISPLAY_SOURCE_WIFI_DISPLAY_WIFI_DISPLAY_ELEMENTARY_STREAM_INFO_H_
+
+#include <stdint.h>
+#include <vector>
+
+#include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_descriptor.h"
+
+namespace extensions {
+
+// WiFi Display elementary stream info is a container for elementary stream
+// information and is used for passing that information to a WiFi Display
+// transport stream packetizer.
+class WiFiDisplayElementaryStreamInfo {
+ public:
+  using DescriptorVector = std::vector<WiFiDisplayElementaryStreamDescriptor>;
+  using DescriptorTag = WiFiDisplayElementaryStreamDescriptor::DescriptorTag;
+
+  enum ElementaryStreamType : uint8_t {
+    AUDIO_AAC = 0x0Fu,
+    AUDIO_AC3 = 0x81u,
+    AUDIO_LPCM = 0x83u,
+    VIDEO_H264 = 0x1Bu,
+  };
+
+  explicit WiFiDisplayElementaryStreamInfo(ElementaryStreamType type);
+  WiFiDisplayElementaryStreamInfo(ElementaryStreamType type,
+                                  DescriptorVector descriptors);
+  WiFiDisplayElementaryStreamInfo(const WiFiDisplayElementaryStreamInfo&);
+  WiFiDisplayElementaryStreamInfo(WiFiDisplayElementaryStreamInfo&&);
+  ~WiFiDisplayElementaryStreamInfo();
+
+  WiFiDisplayElementaryStreamInfo& operator=(WiFiDisplayElementaryStreamInfo&&);
+
+  const DescriptorVector& descriptors() const { return descriptors_; }
+  ElementaryStreamType type() const { return type_; }
+
+  void AddDescriptor(WiFiDisplayElementaryStreamDescriptor descriptor);
+  const WiFiDisplayElementaryStreamDescriptor* FindDescriptor(
+      DescriptorTag descriptor_tag) const;
+  template <typename Descriptor>
+  const Descriptor* FindDescriptor() const {
+    return static_cast<const Descriptor*>(
+        FindDescriptor(static_cast<DescriptorTag>(Descriptor::kTag)));
+  }
+
+ private:
+  DescriptorVector descriptors_;
+  ElementaryStreamType type_;
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_RENDERER_API_DISPLAY_SOURCE_WIFI_DISPLAY_WIFI_DISPLAY_ELEMENTARY_STREAM_INFO_H_
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_packetizer_unittest.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_packetizer_unittest.cc
index a8b769a4..4ba1969b 100644
--- a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_packetizer_unittest.cc
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_packetizer_unittest.cc
@@ -2,12 +2,37 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <list>
+
 #include "base/big_endian.h"
+#include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_descriptor.h"
+#include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.h"
 #include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_packetizer.h"
+#include "extensions/renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using PacketPart = extensions::WiFiDisplayStreamPacketPart;
+
 namespace extensions {
 
+std::ostream& operator<<(std::ostream& os, const PacketPart& part) {
+  const auto flags = os.flags();
+  os << "{" << std::hex << std::noshowbase;
+  for (const auto& item : part) {
+    if (&item != &*part.begin())
+      os << ", ";
+    os << "0x" << static_cast<unsigned>(item);
+  }
+  os.setf(flags, std::ios::basefield | std::ios::showbase);
+  return os << "}";
+}
+
+bool operator==(const PacketPart& a, const PacketPart& b) {
+  if (a.size() != b.size())
+    return false;
+  return std::equal(a.begin(), a.end(), b.begin());
+}
+
 namespace {
 
 namespace pes {
@@ -17,6 +42,108 @@
 const size_t kUnitDataAlignment = sizeof(uint32_t);
 }
 
+namespace ts {
+const uint64_t kTimeStampMask = (static_cast<uint64_t>(1u) << 33) - 1u;
+const uint64_t kTimeStampSecond = 90000u;  // 90 kHz
+const uint64_t kProgramClockReferenceSecond =
+    300u * kTimeStampSecond;  // 27 MHz
+
+// Packet header:
+const size_t kPacketHeaderSize = 4u;
+const unsigned kSyncByte = 0x47u;
+const uint32_t kSyncByteMask = 0xFF000000u;
+const uint32_t kTransportErrorIndicator = 0x00800000u;
+const uint32_t kPayloadUnitStartIndicator = 0x00400000u;
+const uint32_t kTransportPriority = 0x00200000u;
+const uint32_t kScramblingControlMask = 0x000000C0u;
+const uint32_t kAdaptationFieldFlag = 0x00000020u;
+const uint32_t kPayloadFlag = 0x00000010u;
+
+// Adaptation field:
+const unsigned kRandomAccessFlag = 0x40u;
+const unsigned kPcrFlag = 0x10u;
+}  // namespace ts
+
+namespace widi {
+const unsigned kProgramAssociationTablePacketId = 0x0000u;
+const unsigned kProgramMapTablePacketId = 0x0100u;
+const unsigned kProgramClockReferencePacketId = 0x1000u;
+const unsigned kVideoStreamPacketId = 0x1011u;
+const unsigned kFirstAudioStreamPacketId = 0x1100u;
+}  // namespace widi
+
+template <typename PacketContainer>
+class PacketCollector {
+ public:
+  PacketContainer FetchPackets() {
+    PacketContainer container;
+    container.swap(packets_);
+    return container;
+  }
+
+ protected:
+  PacketContainer packets_;
+};
+
+class FakeTransportStreamPacketizer
+    : public WiFiDisplayTransportStreamPacketizer,
+      public PacketCollector<std::list<WiFiDisplayTransportStreamPacket>> {
+ public:
+  FakeTransportStreamPacketizer(
+      const base::TimeDelta& delay_for_unit_time_stamps,
+      std::vector<WiFiDisplayElementaryStreamInfo> stream_infos)
+      : WiFiDisplayTransportStreamPacketizer(delay_for_unit_time_stamps,
+                                             std::move(stream_infos)) {}
+
+  using WiFiDisplayTransportStreamPacketizer::NormalizeUnitTimeStamps;
+
+ protected:
+  bool OnPacketizedTransportStreamPacket(
+      const WiFiDisplayTransportStreamPacket& transport_stream_packet,
+      bool flush) override {
+    // Make a copy of header bytes as they are in stack.
+    headers_.emplace_back(transport_stream_packet.header().begin(),
+                          transport_stream_packet.header().end());
+    const auto& header = headers_.back();
+    if (transport_stream_packet.payload().empty()) {
+      packets_.emplace_back(header.data(), header.size());
+    } else {
+      packets_.emplace_back(header.data(), header.size(),
+                            transport_stream_packet.payload().begin());
+    }
+    EXPECT_EQ(transport_stream_packet.header().size(),
+              packets_.back().header().size());
+    EXPECT_EQ(transport_stream_packet.payload().size(),
+              packets_.back().payload().size());
+    EXPECT_EQ(transport_stream_packet.filler().size(),
+              packets_.back().filler().size());
+    return true;
+  }
+
+ private:
+  std::vector<std::vector<uint8_t>> headers_;
+};
+
+struct ProgramClockReference {
+  enum { kInvalidBase = ~static_cast<uint64_t>(0u) };
+  uint64_t base;
+  uint16_t extension;
+};
+
+ProgramClockReference ParseProgramClockReference(const uint8_t pcr_bytes[6]) {
+  const uint8_t reserved_pcr_bits = pcr_bytes[4] & 0x7Eu;
+  EXPECT_EQ(0x7Eu, reserved_pcr_bits);
+  ProgramClockReference pcr;
+  pcr.base = pcr_bytes[0];
+  pcr.base = (pcr.base << 8) | pcr_bytes[1];
+  pcr.base = (pcr.base << 8) | pcr_bytes[2];
+  pcr.base = (pcr.base << 8) | pcr_bytes[3];
+  pcr.base = (pcr.base << 1) | ((pcr_bytes[4] & 0x80u) >> 7);
+  pcr.extension = pcr_bytes[4] & 0x01u;
+  pcr.extension = (pcr.extension << 8) | pcr_bytes[5];
+  return pcr;
+}
+
 uint64_t ParseTimeStamp(const uint8_t ts_bytes[5], uint8_t pts_dts_indicator) {
   EXPECT_EQ(pts_dts_indicator, (ts_bytes[0] & 0xF0u) >> 4);
   EXPECT_EQ(0x01u, ts_bytes[0] & 0x01u);
@@ -31,6 +158,14 @@
   return ts;
 }
 
+unsigned ParseTransportStreamPacketId(
+    const WiFiDisplayTransportStreamPacket& packet) {
+  if (packet.header().size() < ts::kPacketHeaderSize)
+    return ~0u;
+  return (((packet.header().begin()[1] & 0x001Fu) << 8) |
+          packet.header().begin()[2]);
+}
+
 class WiFiDisplayElementaryStreamUnitPacketizationTest
     : public testing::TestWithParam<
           testing::tuple<unsigned, base::TimeDelta, base::TimeDelta>> {
@@ -120,12 +255,268 @@
     EXPECT_EQ(unit_.size(), packet.unit().size());
   }
 
+  void CheckTransportStreamPacketHeader(
+      base::BigEndianReader* header_reader,
+      bool expected_payload_unit_start_indicator,
+      unsigned expected_packet_id,
+      bool* adaptation_field_flag,
+      uint8_t expected_continuity_counter) {
+    uint32_t parsed_u32;
+    EXPECT_TRUE(header_reader->ReadU32(&parsed_u32));
+    EXPECT_EQ(ts::kSyncByte << 24u, parsed_u32 & ts::kSyncByteMask);
+    EXPECT_EQ(0x0u, parsed_u32 & ts::kTransportErrorIndicator);
+    EXPECT_EQ(expected_payload_unit_start_indicator,
+              (parsed_u32 & ts::kPayloadUnitStartIndicator) != 0u);
+    EXPECT_EQ(0x0u, parsed_u32 & ts::kTransportPriority);
+    EXPECT_EQ(expected_packet_id, (parsed_u32 & 0x001FFF00) >> 8);
+    EXPECT_EQ(0x0u, parsed_u32 & ts::kScramblingControlMask);
+    if (!adaptation_field_flag) {
+      EXPECT_EQ(0x0u, parsed_u32 & ts::kAdaptationFieldFlag);
+    } else {
+      *adaptation_field_flag = (parsed_u32 & ts::kAdaptationFieldFlag) != 0u;
+    }
+    EXPECT_EQ(ts::kPayloadFlag, parsed_u32 & ts::kPayloadFlag);
+    EXPECT_EQ(expected_continuity_counter & 0xFu, parsed_u32 & 0x0000000Fu);
+  }
+
+  void CheckTransportStreamAdaptationField(
+      base::BigEndianReader* header_reader,
+      const WiFiDisplayTransportStreamPacket& packet,
+      uint8_t* adaptation_field_flags) {
+    uint8_t parsed_adaptation_field_length;
+    EXPECT_TRUE(header_reader->ReadU8(&parsed_adaptation_field_length));
+    if (parsed_adaptation_field_length > 0u) {
+      const int initial_remaining = header_reader->remaining();
+      uint8_t parsed_adaptation_field_flags;
+      EXPECT_TRUE(header_reader->ReadU8(&parsed_adaptation_field_flags));
+      if (!adaptation_field_flags) {
+        EXPECT_EQ(0x0u, parsed_adaptation_field_flags);
+      } else {
+        *adaptation_field_flags = parsed_adaptation_field_flags;
+        if (parsed_adaptation_field_flags & ts::kPcrFlag) {
+          uint8_t parsed_pcr_bytes[6];
+          EXPECT_TRUE(header_reader->ReadBytes(parsed_pcr_bytes,
+                                               sizeof(parsed_pcr_bytes)));
+          parsed_pcr_ = ParseProgramClockReference(parsed_pcr_bytes);
+        }
+      }
+      size_t remaining_stuffing_length =
+          parsed_adaptation_field_length -
+          static_cast<size_t>(initial_remaining - header_reader->remaining());
+      while (remaining_stuffing_length > 0u && header_reader->remaining() > 0) {
+        // Adaptation field stuffing byte in header_reader.
+        uint8_t parsed_stuffing_byte;
+        EXPECT_TRUE(header_reader->ReadU8(&parsed_stuffing_byte));
+        EXPECT_EQ(0xFFu, parsed_stuffing_byte);
+        --remaining_stuffing_length;
+      }
+      if (packet.payload().empty()) {
+        // Adaptation field stuffing bytes in packet.filler().
+        EXPECT_EQ(remaining_stuffing_length, packet.filler().size());
+        EXPECT_EQ(0xFFu, packet.filler().value());
+      } else {
+        EXPECT_EQ(0u, remaining_stuffing_length);
+      }
+    }
+  }
+
+  void CheckTransportStreamProgramAssociationTablePacket(
+      const WiFiDisplayTransportStreamPacket& packet) {
+    static const uint8_t kProgramAssicationTable[4u + 13u] = {
+        // Pointer:
+        0u,  // Pointer field
+        // Table header:
+        0x00u,       // Table ID (PAT)
+        0x80u |      // Section syntax indicator (0b1 for PAT)
+            0x00u |  // Private bit (0b0 for PAT)
+            0x30u |  // Reserved bits (0b11)
+            0x00u |  // Section length unused bits (0b00)
+            0u,      // Section length (10 bits)
+        13u,         //
+        // Table syntax:
+        0x00u,       // Table ID extension (transport stream ID)
+        0x01u,       //
+        0xC0u |      // Reserved bits (0b11)
+            0x00u |  // Version (0b00000)
+            0x01u,   // Current indicator (0b1)
+        0u,          // Section number
+        0u,          // Last section number
+        // Program association table specific data:
+        0x00u,      // Program number
+        0x01u,      //
+        0xE0 |      // Reserved bits (0b111)
+            0x01u,  // Program map packet ID (13 bits)
+        0x00,       //
+        // CRC:
+        0xE8u,
+        0xF9u, 0x5Eu, 0x7Du};
+
+    base::BigEndianReader header_reader(
+        reinterpret_cast<const char*>(packet.header().begin()),
+        packet.header().size());
+
+    CheckTransportStreamPacketHeader(
+        &header_reader, true, widi::kProgramAssociationTablePacketId, nullptr,
+        continuity_.program_assication_table++);
+
+    EXPECT_EQ(PacketPart(kProgramAssicationTable),
+              PacketPart(packet.header().end() - header_reader.remaining(),
+                         static_cast<size_t>(header_reader.remaining())));
+    EXPECT_TRUE(header_reader.Skip(header_reader.remaining()));
+
+    EXPECT_EQ(0, header_reader.remaining());
+    EXPECT_EQ(0u, packet.payload().size());
+  }
+
+  void CheckTransportStreamProgramMapTablePacket(
+      const WiFiDisplayTransportStreamPacket& packet,
+      const PacketPart& program_map_table) {
+    base::BigEndianReader header_reader(
+        reinterpret_cast<const char*>(packet.header().begin()),
+        packet.header().size());
+
+    CheckTransportStreamPacketHeader(&header_reader, true,
+                                     widi::kProgramMapTablePacketId, nullptr,
+                                     continuity_.program_map_table++);
+
+    EXPECT_EQ(program_map_table,
+              PacketPart(packet.header().end() - header_reader.remaining(),
+                         static_cast<size_t>(header_reader.remaining())));
+    EXPECT_TRUE(header_reader.Skip(header_reader.remaining()));
+
+    EXPECT_EQ(0, header_reader.remaining());
+    EXPECT_EQ(0u, packet.payload().size());
+  }
+
+  void CheckTransportStreamProgramClockReferencePacket(
+      const WiFiDisplayTransportStreamPacket& packet) {
+    base::BigEndianReader header_reader(
+        reinterpret_cast<const char*>(packet.header().begin()),
+        packet.header().size());
+
+    bool parsed_adaptation_field_flag;
+    CheckTransportStreamPacketHeader(
+        &header_reader, true, widi::kProgramClockReferencePacketId,
+        &parsed_adaptation_field_flag, continuity_.program_clock_reference++);
+    EXPECT_TRUE(parsed_adaptation_field_flag);
+
+    uint8_t parsed_adaptation_field_flags;
+    CheckTransportStreamAdaptationField(&header_reader, packet,
+                                        &parsed_adaptation_field_flags);
+    EXPECT_EQ(ts::kPcrFlag, parsed_adaptation_field_flags);
+
+    EXPECT_EQ(0, header_reader.remaining());
+    EXPECT_EQ(0u, packet.payload().size());
+  }
+
+  void CheckTransportStreamElementaryStreamPacket(
+      const WiFiDisplayTransportStreamPacket& packet,
+      const WiFiDisplayElementaryStreamPacket& elementary_stream_packet,
+      unsigned stream_index,
+      unsigned expected_packet_id,
+      bool expected_random_access,
+      const uint8_t** unit_data_pos) {
+    const bool first_transport_stream_packet_for_current_unit =
+        packet.payload().begin() == unit_.data();
+    const bool last_transport_stream_packet_for_current_unit =
+        packet.payload().end() == unit_.data() + unit_.size();
+    base::BigEndianReader header_reader(
+        reinterpret_cast<const char*>(packet.header().begin()),
+        packet.header().size());
+
+    bool parsed_adaptation_field_flag;
+    CheckTransportStreamPacketHeader(
+        &header_reader, first_transport_stream_packet_for_current_unit,
+        expected_packet_id, &parsed_adaptation_field_flag,
+        continuity_.elementary_streams[stream_index]++);
+
+    if (first_transport_stream_packet_for_current_unit) {
+      // Random access can only be signified by adaptation field.
+      if (expected_random_access)
+        EXPECT_TRUE(parsed_adaptation_field_flag);
+      // If there is no need for padding nor for a random access indicator,
+      // then there is no need for an adaptation field, either.
+      if (!last_transport_stream_packet_for_current_unit &&
+          !expected_random_access) {
+        EXPECT_FALSE(parsed_adaptation_field_flag);
+      }
+      if (parsed_adaptation_field_flag) {
+        uint8_t parsed_adaptation_field_flags;
+        CheckTransportStreamAdaptationField(&header_reader, packet,
+                                            &parsed_adaptation_field_flags);
+        EXPECT_EQ(expected_random_access ? ts::kRandomAccessFlag : 0u,
+                  parsed_adaptation_field_flags);
+      }
+
+      // Elementary stream header.
+      PacketPart parsed_elementary_stream_packet_header(
+          packet.header().end() - header_reader.remaining(),
+          std::min(elementary_stream_packet.header().size(),
+                   static_cast<size_t>(header_reader.remaining())));
+      EXPECT_EQ(elementary_stream_packet.header(),
+                parsed_elementary_stream_packet_header);
+      EXPECT_TRUE(
+          header_reader.Skip(parsed_elementary_stream_packet_header.size()));
+
+      // Elementary stream unit header.
+      PacketPart parsed_unit_header(
+          packet.header().end() - header_reader.remaining(),
+          std::min(elementary_stream_packet.unit_header().size(),
+                   static_cast<size_t>(header_reader.remaining())));
+      EXPECT_EQ(elementary_stream_packet.unit_header(), parsed_unit_header);
+      EXPECT_TRUE(header_reader.Skip(parsed_unit_header.size()));
+
+      // Time stamps.
+      if (parsed_elementary_stream_packet_header.size() >= 19u) {
+        uint64_t parsed_dts = ParseTimeStamp(
+            &parsed_elementary_stream_packet_header.begin()[14], 0x1u);
+        // Check that
+        //   0 <= 300 * parsed_dts - parsed_pcr_value <=
+        //       kProgramClockReferenceSecond
+        // where
+        //   parsed_pcr_value = 300 * parsed_pcr_.base + parsed_pcr_.extension
+        // but allow parsed_pcr_.base and parsed_dts to wrap around in 33 bits.
+        EXPECT_NE(ProgramClockReference::kInvalidBase, parsed_pcr_.base);
+        EXPECT_LE(
+            300u * ((parsed_dts - parsed_pcr_.base) & ts::kTimeStampMask) -
+                parsed_pcr_.extension,
+            ts::kProgramClockReferenceSecond)
+            << " DTS must be not smaller than PCR!";
+      }
+    } else {
+      // If there is no need for padding, then there is no need for
+      // an adaptation field, either.
+      if (!last_transport_stream_packet_for_current_unit)
+        EXPECT_FALSE(parsed_adaptation_field_flag);
+      if (parsed_adaptation_field_flag) {
+        CheckTransportStreamAdaptationField(&header_reader, packet, nullptr);
+      }
+    }
+    EXPECT_EQ(0, header_reader.remaining());
+
+    // Transport stream packet payload.
+    EXPECT_EQ(*unit_data_pos, packet.payload().begin());
+    if (*unit_data_pos == packet.payload().begin())
+      *unit_data_pos += packet.payload().size();
+
+    // Transport stream packet filler.
+    EXPECT_EQ(0u, packet.filler().size());
+  }
+
   enum { kVideoOnlyUnitSize = 0x8000u };  // Not exact. Be on the safe side.
 
   const std::vector<uint8_t> unit_;
   const base::TimeTicks now_;
   const base::TimeTicks dts_;
   const base::TimeTicks pts_;
+
+  struct {
+    size_t program_assication_table;
+    size_t program_map_table;
+    size_t program_clock_reference;
+    size_t elementary_streams[3];
+  } continuity_ = {0u, 0u, 0u, {0u, 0u, 0u}};
+  ProgramClockReference parsed_pcr_ = {ProgramClockReference::kInvalidBase, 0u};
 };
 
 TEST_P(WiFiDisplayElementaryStreamUnitPacketizationTest,
@@ -152,6 +543,163 @@
   }
 }
 
+TEST_P(WiFiDisplayElementaryStreamUnitPacketizationTest,
+       EncodeToTransportStreamPackets) {
+  enum { kStreamCount = 3u };
+  static const bool kBoolValues[] = {false, true};
+  static const unsigned kPacketIds[kStreamCount] = {
+      widi::kVideoStreamPacketId, widi::kFirstAudioStreamPacketId + 0u,
+      widi::kFirstAudioStreamPacketId + 1u};
+  static const uint8_t kProgramMapTable[4u + 42u] = {
+      // Pointer:
+      0u,  // Pointer field
+      // Table header:
+      0x02u,       // Table ID (PMT)
+      0x80u |      // Section syntax indicator (0b1 for PMT)
+          0x00u |  // Private bit (0b0 for PMT)
+          0x30u |  // Reserved bits (0b11)
+          0x00u |  // Section length unused bits (0b00)
+          0u,      // Section length (10 bits)
+      42u,         //
+      // Table syntax:
+      0x00u,       // Table ID extension (program number)
+      0x01u,       //
+      0xC0u |      // Reserved bits (0b11)
+          0x00u |  // Version (0b00000)
+          0x01u,   // Current indicator (0b1)
+      0u,          // Section number
+      0u,          // Last section number
+      // Program map table specific data:
+      0xE0u |      // Reserved bits (0b111)
+          0x10u,   // Program clock reference packet ID (13 bits)
+      0x00u,       //
+      0xF0u |      // Reserved bits (0b11)
+          0x00u |  // Program info length unused bits
+          0u,      // Program info length (10 bits)
+      0u,          //
+      // Elementary stream specific data:
+      0x1Bu,       // Stream type (H.264 in a packetized stream)
+      0xE0u |      // Reserved bits (0b111)
+          0x10u,   // Elementary packet ID (13 bits)
+      0x11u,       //
+      0xF0u |      // Reserved bits (0b1111)
+          0x00u |  // Elementary stream info length unused bits
+          0u,      // Elementary stream info length (10 bits)
+      10u,         //
+      0x28u,       // AVC video descriptor tag
+      4u,          // Descriptor length
+      0xA5u,
+      0xF5u, 0xBDu, 0xBFu,
+      0x2Au,  // AVC timing and HRD descriptor tag
+      2u,     // Descriptor length
+      0x7Eu, 0x1Fu,
+      // Elementary stream specific data:
+      0x83u,       // Stream type (lossless audio in a packetized stream)
+      0xE0u |      // Reserved bits (0b111)
+          0x11u,   // Elementary packet ID (13 bits)
+      0x00u,       //
+      0xF0u |      // Reserved bits (0b1111)
+          0x00u |  // Elementary stream info length unused bits
+          0u,      // Elementary stream info length (10 bits)
+      4u,          //
+      0x83u,       // LPCM audio stream descriptor tag
+      2u,          // Descriptor length
+      0x26u,
+      0x2Fu,
+      // Elementary stream specific data:
+      0x0Fu,       // Stream type (AAC in a packetized stream)
+      0xE0u |      // Reserved bits (0b111)
+          0x11u,   // Elementary packet ID (13 bits)
+      0x01u,       //
+      0xF0u |      // Reserved bits (0b1111)
+          0x00u |  // Elementary stream info length unused bits
+          0u,      // Elementary stream info length (10 bits)
+      0u,          //
+      // CRC:
+      0x4Fu,
+      0x63u, 0xABu, 0x6Eu};
+  static const uint8_t kStreamIds[] = {
+      WiFiDisplayElementaryStreamPacketizer::kFirstVideoStreamId,
+      WiFiDisplayElementaryStreamPacketizer::kPrivateStream1Id,
+      WiFiDisplayElementaryStreamPacketizer::kFirstAudioStreamId};
+
+  using ESDescriptor = WiFiDisplayElementaryStreamDescriptor;
+  std::vector<ESDescriptor> lpcm_descriptors;
+  lpcm_descriptors.emplace_back(ESDescriptor::LPCMAudioStream::Create(
+      ESDescriptor::LPCMAudioStream::SAMPLING_FREQUENCY_44_1K,
+      ESDescriptor::LPCMAudioStream::BITS_PER_SAMPLE_16, false,
+      ESDescriptor::LPCMAudioStream::NUMBER_OF_CHANNELS_STEREO));
+  std::vector<ESDescriptor> video_desciptors;
+  video_desciptors.emplace_back(ESDescriptor::AVCVideo::Create(
+      0xA5u, true, true, true, 0x15u, 0xBDu, true));
+  video_desciptors.emplace_back(ESDescriptor::AVCTimingAndHRD::Create());
+  std::vector<WiFiDisplayElementaryStreamInfo> stream_infos;
+  stream_infos.emplace_back(WiFiDisplayElementaryStreamInfo::VIDEO_H264,
+                            std::move(video_desciptors));
+  stream_infos.emplace_back(WiFiDisplayElementaryStreamInfo::AUDIO_LPCM,
+                            std::move(lpcm_descriptors));
+  stream_infos.emplace_back(WiFiDisplayElementaryStreamInfo::AUDIO_AAC);
+  WiFiDisplayElementaryStreamPacketizer elementary_stream_packetizer;
+  FakeTransportStreamPacketizer packetizer(
+      base::TimeDelta::FromMilliseconds(200), std::move(stream_infos));
+
+  size_t packet_index = 0u;
+  for (unsigned stream_index = 0; stream_index < kStreamCount; ++stream_index) {
+    const uint8_t* unit_header_data = nullptr;
+    size_t unit_header_size = 0u;
+    if (stream_index > 0u) {  // Audio stream.
+      if (unit_.size() >= kVideoOnlyUnitSize)
+        continue;
+      if (stream_index == 1u) {  // LPCM
+        unit_header_data = reinterpret_cast<const uint8_t*>("\xA0\x06\x00\x09");
+        unit_header_size = 4u;
+      }
+    }
+    for (const bool random_access : kBoolValues) {
+      EXPECT_TRUE(packetizer.EncodeElementaryStreamUnit(
+          stream_index, unit_.data(), unit_.size(), random_access, pts_, dts_,
+          true));
+      auto normalized_pts = pts_;
+      auto normalized_dts = dts_;
+      packetizer.NormalizeUnitTimeStamps(&normalized_pts, &normalized_dts);
+      WiFiDisplayElementaryStreamPacket elementary_stream_packet =
+          elementary_stream_packetizer.EncodeElementaryStreamUnit(
+              kStreamIds[stream_index], unit_header_data, unit_header_size,
+              unit_.data(), unit_.size(), normalized_pts, normalized_dts);
+
+      const uint8_t* unit_data_pos = unit_.data();
+      for (const auto& packet : packetizer.FetchPackets()) {
+        switch (ParseTransportStreamPacketId(packet)) {
+          case widi::kProgramAssociationTablePacketId:
+            if (packet_index < 4u)
+              EXPECT_EQ(0u, packet_index);
+            CheckTransportStreamProgramAssociationTablePacket(packet);
+            break;
+          case widi::kProgramMapTablePacketId:
+            if (packet_index < 4u)
+              EXPECT_EQ(1u, packet_index);
+            CheckTransportStreamProgramMapTablePacket(
+                packet, PacketPart(kProgramMapTable));
+            break;
+          case widi::kProgramClockReferencePacketId:
+            if (packet_index < 4u)
+              EXPECT_EQ(2u, packet_index);
+            CheckTransportStreamProgramClockReferencePacket(packet);
+            break;
+          default:
+            if (packet_index < 4u)
+              EXPECT_EQ(3u, packet_index);
+            CheckTransportStreamElementaryStreamPacket(
+                packet, elementary_stream_packet, stream_index,
+                kPacketIds[stream_index], random_access, &unit_data_pos);
+        }
+        ++packet_index;
+      }
+      EXPECT_EQ(unit_.data() + unit_.size(), unit_data_pos);
+    }
+  }
+}
+
 INSTANTIATE_TEST_CASE_P(
     WiFiDisplayElementaryStreamUnitPacketizationTests,
     WiFiDisplayElementaryStreamUnitPacketizationTest,
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.cc
new file mode 100644
index 0000000..eee0a52
--- /dev/null
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.cc
@@ -0,0 +1,727 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.h"
+
+#include <algorithm>
+#include <cstring>
+#include <utility>
+
+#include "base/logging.h"
+#include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_descriptor.h"
+#include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.h"
+#include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_packetizer.h"
+
+namespace extensions {
+namespace {
+
+uint32_t crc32(uint32_t crc, const uint8_t* data, size_t len) {
+  static const uint32_t table[256] = {
+      0x00000000, 0xb71dc104, 0x6e3b8209, 0xd926430d, 0xdc760413, 0x6b6bc517,
+      0xb24d861a, 0x0550471e, 0xb8ed0826, 0x0ff0c922, 0xd6d68a2f, 0x61cb4b2b,
+      0x649b0c35, 0xd386cd31, 0x0aa08e3c, 0xbdbd4f38, 0x70db114c, 0xc7c6d048,
+      0x1ee09345, 0xa9fd5241, 0xacad155f, 0x1bb0d45b, 0xc2969756, 0x758b5652,
+      0xc836196a, 0x7f2bd86e, 0xa60d9b63, 0x11105a67, 0x14401d79, 0xa35ddc7d,
+      0x7a7b9f70, 0xcd665e74, 0xe0b62398, 0x57abe29c, 0x8e8da191, 0x39906095,
+      0x3cc0278b, 0x8bdde68f, 0x52fba582, 0xe5e66486, 0x585b2bbe, 0xef46eaba,
+      0x3660a9b7, 0x817d68b3, 0x842d2fad, 0x3330eea9, 0xea16ada4, 0x5d0b6ca0,
+      0x906d32d4, 0x2770f3d0, 0xfe56b0dd, 0x494b71d9, 0x4c1b36c7, 0xfb06f7c3,
+      0x2220b4ce, 0x953d75ca, 0x28803af2, 0x9f9dfbf6, 0x46bbb8fb, 0xf1a679ff,
+      0xf4f63ee1, 0x43ebffe5, 0x9acdbce8, 0x2dd07dec, 0x77708634, 0xc06d4730,
+      0x194b043d, 0xae56c539, 0xab068227, 0x1c1b4323, 0xc53d002e, 0x7220c12a,
+      0xcf9d8e12, 0x78804f16, 0xa1a60c1b, 0x16bbcd1f, 0x13eb8a01, 0xa4f64b05,
+      0x7dd00808, 0xcacdc90c, 0x07ab9778, 0xb0b6567c, 0x69901571, 0xde8dd475,
+      0xdbdd936b, 0x6cc0526f, 0xb5e61162, 0x02fbd066, 0xbf469f5e, 0x085b5e5a,
+      0xd17d1d57, 0x6660dc53, 0x63309b4d, 0xd42d5a49, 0x0d0b1944, 0xba16d840,
+      0x97c6a5ac, 0x20db64a8, 0xf9fd27a5, 0x4ee0e6a1, 0x4bb0a1bf, 0xfcad60bb,
+      0x258b23b6, 0x9296e2b2, 0x2f2bad8a, 0x98366c8e, 0x41102f83, 0xf60dee87,
+      0xf35da999, 0x4440689d, 0x9d662b90, 0x2a7bea94, 0xe71db4e0, 0x500075e4,
+      0x892636e9, 0x3e3bf7ed, 0x3b6bb0f3, 0x8c7671f7, 0x555032fa, 0xe24df3fe,
+      0x5ff0bcc6, 0xe8ed7dc2, 0x31cb3ecf, 0x86d6ffcb, 0x8386b8d5, 0x349b79d1,
+      0xedbd3adc, 0x5aa0fbd8, 0xeee00c69, 0x59fdcd6d, 0x80db8e60, 0x37c64f64,
+      0x3296087a, 0x858bc97e, 0x5cad8a73, 0xebb04b77, 0x560d044f, 0xe110c54b,
+      0x38368646, 0x8f2b4742, 0x8a7b005c, 0x3d66c158, 0xe4408255, 0x535d4351,
+      0x9e3b1d25, 0x2926dc21, 0xf0009f2c, 0x471d5e28, 0x424d1936, 0xf550d832,
+      0x2c769b3f, 0x9b6b5a3b, 0x26d61503, 0x91cbd407, 0x48ed970a, 0xfff0560e,
+      0xfaa01110, 0x4dbdd014, 0x949b9319, 0x2386521d, 0x0e562ff1, 0xb94beef5,
+      0x606dadf8, 0xd7706cfc, 0xd2202be2, 0x653deae6, 0xbc1ba9eb, 0x0b0668ef,
+      0xb6bb27d7, 0x01a6e6d3, 0xd880a5de, 0x6f9d64da, 0x6acd23c4, 0xddd0e2c0,
+      0x04f6a1cd, 0xb3eb60c9, 0x7e8d3ebd, 0xc990ffb9, 0x10b6bcb4, 0xa7ab7db0,
+      0xa2fb3aae, 0x15e6fbaa, 0xccc0b8a7, 0x7bdd79a3, 0xc660369b, 0x717df79f,
+      0xa85bb492, 0x1f467596, 0x1a163288, 0xad0bf38c, 0x742db081, 0xc3307185,
+      0x99908a5d, 0x2e8d4b59, 0xf7ab0854, 0x40b6c950, 0x45e68e4e, 0xf2fb4f4a,
+      0x2bdd0c47, 0x9cc0cd43, 0x217d827b, 0x9660437f, 0x4f460072, 0xf85bc176,
+      0xfd0b8668, 0x4a16476c, 0x93300461, 0x242dc565, 0xe94b9b11, 0x5e565a15,
+      0x87701918, 0x306dd81c, 0x353d9f02, 0x82205e06, 0x5b061d0b, 0xec1bdc0f,
+      0x51a69337, 0xe6bb5233, 0x3f9d113e, 0x8880d03a, 0x8dd09724, 0x3acd5620,
+      0xe3eb152d, 0x54f6d429, 0x7926a9c5, 0xce3b68c1, 0x171d2bcc, 0xa000eac8,
+      0xa550add6, 0x124d6cd2, 0xcb6b2fdf, 0x7c76eedb, 0xc1cba1e3, 0x76d660e7,
+      0xaff023ea, 0x18ede2ee, 0x1dbda5f0, 0xaaa064f4, 0x738627f9, 0xc49be6fd,
+      0x09fdb889, 0xbee0798d, 0x67c63a80, 0xd0dbfb84, 0xd58bbc9a, 0x62967d9e,
+      0xbbb03e93, 0x0cadff97, 0xb110b0af, 0x060d71ab, 0xdf2b32a6, 0x6836f3a2,
+      0x6d66b4bc, 0xda7b75b8, 0x035d36b5, 0xb440f7b1};
+  for (; len; ++data, --len)
+    crc = (crc >> 8) ^ table[(crc & 0xFFu) ^ *data];
+  return crc;
+}
+
+// Code and parameters related to the Program Specific Information (PSI)
+// specification.
+namespace psi {
+
+const uint8_t kProgramAssociationTableId = 0x00u;
+const uint8_t kProgramMapTableId = 0x02u;
+
+const uint16_t kFirstProgramNumber = 0x0001u;
+
+const size_t kCrcSize = 4u;
+const size_t kProgramMapTableElementaryStreamEntryBaseSize = 5u;
+const size_t kTableHeaderSize = 3u;
+
+size_t FillInTablePointer(uint8_t* dst, size_t min_size) {
+  size_t i = 1u;
+  if (i < min_size) {
+    std::memset(&dst[i], 0xFF, min_size - i);  // Pointer filler bytes
+    i = min_size;
+  }
+  dst[0] = i - 1u;  // Pointer field
+  return i;
+}
+
+size_t FillInTableHeaderAndCrc(uint8_t* header_dst,
+                               uint8_t* crc_dst,
+                               uint8_t table_id) {
+  size_t i;
+  const uint8_t* const header_end = header_dst + kTableHeaderSize;
+  const uint8_t* const crc_end = crc_dst + kCrcSize;
+  const size_t section_length = static_cast<size_t>(crc_end - header_end);
+  DCHECK_LE(section_length, 1021u);
+
+  // Table header.
+  i = 0u;
+  header_dst[i++] = table_id;
+  header_dst[i++] =
+      (0x1u << 7) |  // Section syntax indicator (1 for PAT and PMT)
+      (0x0u << 6) |  // Private bit (0 for PAT and PMT)
+      (0x3u << 4) |  // Reserved bits (both bits on)
+      (0x0u << 2) |  // Section length unused bits (both bits off)
+      ((section_length >> 8) & 0x03u);       // Section length (10 bits)
+  header_dst[i++] = section_length & 0xFFu;  //
+  DCHECK_EQ(kTableHeaderSize, i);
+
+  // CRC.
+  uint32_t crc =
+      crc32(0xFFFFFFFFu, header_dst, static_cast<size_t>(crc_dst - header_dst));
+  i = 0u;
+  // Avoid swapping the crc by reversing write order.
+  crc_dst[i++] = crc & 0xFFu;
+  crc_dst[i++] = (crc >> 8) & 0xFFu;
+  crc_dst[i++] = (crc >> 16) & 0xFFu;
+  crc_dst[i++] = (crc >> 24) & 0xFFu;
+  DCHECK_EQ(kCrcSize, i);
+  return i;
+}
+
+size_t FillInTableSyntax(uint8_t* dst,
+                         uint16_t table_id_extension,
+                         uint8_t version_number) {
+  size_t i = 0u;
+  dst[i++] = table_id_extension >> 8;
+  dst[i++] = table_id_extension & 0xFFu;
+  dst[i++] = (0x3u << 6) |                      // Reserved bits (both bits on)
+             ((version_number & 0x1Fu) << 1) |  // Version number (5 bits)
+             (0x1u << 0);                       // Current indicator
+  dst[i++] = 0u;                                // Section number
+  dst[i++] = 0u;                                // Last section number
+  return i;
+}
+
+size_t FillInProgramAssociationTableEntry(uint8_t* dst,
+                                          uint16_t program_number,
+                                          unsigned pmt_packet_id) {
+  size_t i = 0u;
+  dst[i++] = program_number >> 8;
+  dst[i++] = program_number & 0xFFu;
+  dst[i++] = (0x7u << 5) |                    // Reserved bits (all 3 bits on)
+             ((pmt_packet_id >> 8) & 0x1Fu);  // Packet identifier (13 bits)
+  dst[i++] = pmt_packet_id & 0xFFu;           //
+  return i;
+}
+
+size_t FillInProgramMapTableData(uint8_t* dst, unsigned pcr_packet_id) {
+  size_t i = 0u;
+  dst[i++] = (0x7u << 5) |                    // Reserved bits (all 3 bits on)
+             ((pcr_packet_id >> 8) & 0x1Fu);  // Packet identifier (13 bits)
+  dst[i++] = pcr_packet_id & 0xFFu;           //
+  dst[i++] = (0xFu << 4) |                    // Reserved bits (all 4 bits on)
+             (0x0u << 2) |  // Program info length unused bits (both bits off)
+             ((0u >> 8) & 0x3u);  // Program info length (10 bits)
+  dst[i++] = 0u & 0xFFu;          //
+                                  // No program descriptors
+  return i;
+}
+
+size_t CalculateElementaryStreamInfoLength(
+    const std::vector<WiFiDisplayElementaryStreamDescriptor>& es_descriptors) {
+  size_t es_info_length = 0u;
+  for (const auto& es_descriptor : es_descriptors)
+    es_info_length += es_descriptor.size();
+  DCHECK_EQ(0u, es_info_length >> 8);
+  return es_info_length;
+}
+
+size_t FillInProgramMapTableElementaryStreamEntry(
+    uint8_t* dst,
+    uint8_t stream_type,
+    unsigned es_packet_id,
+    size_t es_info_length,
+    const std::vector<WiFiDisplayElementaryStreamDescriptor>& es_descriptors) {
+  DCHECK_EQ(CalculateElementaryStreamInfoLength(es_descriptors),
+            es_info_length);
+  DCHECK_EQ(0u, es_info_length >> 10);
+  size_t i = 0u;
+  dst[i++] = stream_type;
+  dst[i++] = (0x7u << 5) |                   // Reserved bits (all 3 bits on)
+             ((es_packet_id >> 8) & 0x1Fu);  // Packet identifier (13 bits)
+  dst[i++] = es_packet_id & 0xFFu;           //
+  dst[i++] = (0xFu << 4) |                   // Reserved bits (all 4 bits on)
+             (0x0u << 2) |  // ES info length unused bits (both bits off)
+             ((es_info_length >> 8) & 0x3u);  // ES info length (10 bits)
+  dst[i++] = es_info_length & 0xFFu;          //
+  for (const auto& es_descriptor : es_descriptors) {
+    std::memcpy(&dst[i], es_descriptor.data(), es_descriptor.size());
+    i += es_descriptor.size();
+  }
+  return i;
+}
+
+}  // namespace psi
+
+// Code and parameters related to the MPEG Transport Stream (MPEG-TS)
+// specification.
+namespace ts {
+
+const size_t kAdaptationFieldLengthSize = 1u;
+const size_t kAdaptationFieldFlagsSize = 1u;
+const size_t kPacketHeaderSize = 4u;
+const size_t kProgramClockReferenceSize = 6u;
+
+size_t FillInProgramClockReference(uint8_t* dst, const base::TimeTicks& pcr) {
+  // Convert to the number of 27 MHz ticks since some epoch.
+  const uint64_t us =
+      static_cast<uint64_t>((pcr - base::TimeTicks()).InMicroseconds());
+  const uint64_t n = 27u * us;
+  const uint64_t base = n / 300u;  // 90 kHz
+  const uint64_t extension = n % 300u;
+
+  size_t i = 0u;
+  dst[i++] = (base >> 25) & 0xFFu;       // Base (33 bits)
+  dst[i++] = (base >> 17) & 0xFFu;       //
+  dst[i++] = (base >> 9) & 0xFFu;        //
+  dst[i++] = (base >> 1) & 0xFFu;        //
+  dst[i++] = ((base & 0x01u) << 7) |     //
+             (0x3Fu << 1) |              // Reserved bits (all 6 bits on)
+             ((extension >> 8) & 0x1u);  // Extension (9 bits)
+  dst[i++] = extension & 0xFFu;          //
+  DCHECK_EQ(kProgramClockReferenceSize, i);
+  return i;
+}
+
+size_t FillInAdaptationFieldLengthFromSize(uint8_t* dst, size_t size) {
+  size_t i = 0u;
+  dst[i++] = size - 1u;
+  DCHECK_EQ(kAdaptationFieldLengthSize, i);
+  return i;
+}
+
+size_t FillInAdaptationFieldFlags(uint8_t* dst,
+                                  bool random_access_indicator,
+                                  const base::TimeTicks& pcr) {
+  size_t i = 0u;
+  dst[i++] = (0x0u << 7) |                     // Discontinuity indicator
+             (random_access_indicator << 6) |  // Random access indicator
+             (0x0u << 5) |              // Elementary stream priority indicator
+             ((!pcr.is_null()) << 4) |  // PCR flag
+             (0x0u << 3) |              // OPCR flag
+             (0x0u << 2) |              // Splicing point flag
+             (0x0u << 1) |              // Transport private data flag
+             (0x0u << 0);               // Adaptation field extension flag
+  DCHECK_EQ(kAdaptationFieldFlagsSize, i);
+  return i;
+}
+
+size_t FillInAdaptationField(uint8_t* dst,
+                             bool random_access_indicator,
+                             size_t min_size) {
+  // Reserve space for a length.
+  size_t i = kAdaptationFieldLengthSize;
+
+  if (random_access_indicator || i < min_size) {
+    const base::TimeTicks pcr;
+    i += FillInAdaptationFieldFlags(&dst[i], random_access_indicator, pcr);
+
+    if (i < min_size) {
+      std::memset(&dst[i], 0xFF, min_size - i);  // Stuffing bytes.
+      i = min_size;
+    }
+  }
+
+  // Fill in a length now that the size is known.
+  FillInAdaptationFieldLengthFromSize(dst, i);
+
+  return i;
+}
+
+size_t FillInPacketHeader(uint8_t* dst,
+                          bool payload_unit_start_indicator,
+                          unsigned packet_id,
+                          bool adaptation_field_flag,
+                          unsigned continuity_counter) {
+  size_t i = 0u;
+  dst[i++] = 0x47;  // Sync byte ('G')
+  dst[i++] =
+      (0x0u << 7) |                          // Transport error indicator
+      (payload_unit_start_indicator << 6) |  // Payload unit start indicator
+      (0x0 << 5) |                           // Transport priority
+      ((packet_id >> 8) & 0x1Fu);            // Packet identifier (13 bits)
+  dst[i++] = packet_id & 0xFFu;              //
+  dst[i++] = (0x0u << 6) |  // Scrambling control (0b00 for not)
+             (adaptation_field_flag << 5) |  // Adaptation field flag
+             (0x1u << 4) |                   // Payload flag
+             (continuity_counter & 0xFu);    // Continuity counter
+  DCHECK_EQ(kPacketHeaderSize, i);
+  return i;
+}
+
+}  // namespace ts
+
+// Code and parameters related to the WiFi Display specification.
+namespace widi {
+
+const size_t kUnitHeaderMaxSize = 4u;
+
+// Maximum interval between meta information which includes:
+//  * Program Association Table (PAT)
+//  * Program Map Table (PMT)
+//  * Program Clock Reference (PCR)
+const int kMaxMillisecondsBetweenMetaInformation = 100u;
+
+const unsigned kProgramAssociationTablePacketId = 0x0000u;
+const unsigned kProgramMapTablePacketId = 0x0100u;
+const unsigned kProgramClockReferencePacketId = 0x1000u;
+const unsigned kVideoStreamPacketId = 0x1011u;
+const unsigned kFirstAudioStreamPacketId = 0x1100u;
+
+size_t FillInUnitHeader(uint8_t* dst,
+                        const WiFiDisplayElementaryStreamInfo& stream_info) {
+  size_t i = 0u;
+
+  if (stream_info.type() == WiFiDisplayElementaryStreamInfo::AUDIO_LPCM) {
+    // Convert an LPCM audio stream descriptor to an LPCM unit header.
+    if (const auto* lpcm_descriptor =
+            stream_info.FindDescriptor<
+                WiFiDisplayElementaryStreamDescriptor::LPCMAudioStream>()) {
+      dst[i++] = 0xA0u;  // Sub stream ID (0th sub stream)
+      dst[i++] = WiFiDisplayTransportStreamPacketizer::LPCM::kFramesPerUnit;
+      dst[i++] = ((0x00u << 1) |  // Reserved (all 7 bits off)
+                  (lpcm_descriptor->emphasis_flag() << 0));
+      dst[i++] = ((lpcm_descriptor->bits_per_sample() << 6) |
+                  (lpcm_descriptor->sampling_frequency() << 3) |
+                  (lpcm_descriptor->number_of_channels() << 0));
+    }
+  }
+
+  DCHECK_LE(i, kUnitHeaderMaxSize);
+  return i;
+}
+
+}  // namespace widi
+
+}  // namespace
+
+WiFiDisplayTransportStreamPacket::WiFiDisplayTransportStreamPacket(
+    const uint8_t* header_data,
+    size_t header_size)
+    : header_(header_data, header_size),
+      payload_(header_.end(), 0u),
+      filler_(kPacketSize - header_size) {}
+
+WiFiDisplayTransportStreamPacket::WiFiDisplayTransportStreamPacket(
+    const uint8_t* header_data,
+    size_t header_size,
+    const uint8_t* payload_data)
+    : header_(header_data, header_size),
+      payload_(payload_data, kPacketSize - header_size),
+      filler_(0u) {}
+
+struct WiFiDisplayTransportStreamPacketizer::ElementaryStreamState {
+  ElementaryStreamState(WiFiDisplayElementaryStreamInfo info,
+                        uint16_t packet_id,
+                        uint8_t stream_id)
+      : info(std::move(info)),
+        info_length(
+            psi::CalculateElementaryStreamInfoLength(this->info.descriptors())),
+        packet_id(packet_id),
+        stream_id(stream_id) {}
+
+  WiFiDisplayElementaryStreamInfo info;
+  uint8_t info_length;
+  struct {
+    uint8_t continuity = 0u;
+  } counters;
+  uint16_t packet_id;
+  uint8_t stream_id;
+};
+
+WiFiDisplayTransportStreamPacketizer::WiFiDisplayTransportStreamPacketizer(
+    const base::TimeDelta& delay_for_unit_time_stamps,
+    std::vector<WiFiDisplayElementaryStreamInfo> stream_infos)
+    : delay_for_unit_time_stamps_(delay_for_unit_time_stamps) {
+  std::memset(&counters_, 0x00, sizeof(counters_));
+  if (!stream_infos.empty())
+    CHECK(SetElementaryStreams(std::move(stream_infos)));
+}
+
+WiFiDisplayTransportStreamPacketizer::~WiFiDisplayTransportStreamPacketizer() {}
+
+bool WiFiDisplayTransportStreamPacketizer::EncodeElementaryStreamUnit(
+    unsigned stream_index,
+    const uint8_t* unit_data,
+    size_t unit_size,
+    bool random_access,
+    base::TimeTicks pts,
+    base::TimeTicks dts,
+    bool flush) {
+  DCHECK(CalledOnValidThread());
+  DCHECK_LT(stream_index, stream_states_.size());
+  ElementaryStreamState& stream_state = stream_states_[stream_index];
+
+  if (program_clock_reference_.is_null() ||
+      base::TimeTicks::Now() - program_clock_reference_ >
+          base::TimeDelta::FromMilliseconds(
+              widi::kMaxMillisecondsBetweenMetaInformation) /
+              2) {
+    if (!EncodeMetaInformation(false))
+      return false;
+  }
+
+  uint8_t unit_header_data[widi::kUnitHeaderMaxSize];
+  const size_t unit_header_size =
+      widi::FillInUnitHeader(unit_header_data, stream_state.info);
+
+  UpdateDelayForUnitTimeStamps(pts, dts);
+  NormalizeUnitTimeStamps(&pts, &dts);
+
+  WiFiDisplayElementaryStreamPacketizer elementary_stream_packetizer;
+  WiFiDisplayElementaryStreamPacket elementary_stream_packet =
+      elementary_stream_packetizer.EncodeElementaryStreamUnit(
+          stream_state.stream_id, unit_header_data, unit_header_size, unit_data,
+          unit_size, pts, dts);
+
+  size_t adaptation_field_min_size = 0u;
+  uint8_t header_data[WiFiDisplayTransportStreamPacket::kPacketSize];
+  bool is_payload_unit_end;
+  bool is_payload_unit_start = true;
+  size_t remaining_unit_size = elementary_stream_packet.unit().size();
+  do {
+    // Fill in headers and an adaptation field:
+    //  * Transport stream packet header
+    //  * Transport stream adaptation field
+    //    (only for the first and/or the last packet):
+    //     - for the first packet to hold flags
+    //     - for the last packet to hold padding
+    //  * PES packet header (only for the first packet):
+    //     - PES packet header base
+    //     - Optional PES header base
+    //     - Optional PES header optional fields:
+    //        - Presentation time stamp
+    //        - Decoding time stamp
+    bool adaptation_field_flag = false;
+    size_t header_min_size;
+    if (is_payload_unit_start || is_payload_unit_end) {
+      header_min_size = ts::kPacketHeaderSize;
+      if (is_payload_unit_start) {
+        header_min_size += elementary_stream_packet.header().size() +
+                           elementary_stream_packet.unit_header().size();
+      }
+      adaptation_field_min_size =
+          std::max(
+              WiFiDisplayTransportStreamPacket::kPacketSize - header_min_size,
+              remaining_unit_size) -
+          remaining_unit_size;
+      adaptation_field_flag = adaptation_field_min_size > 0 ||
+                              (is_payload_unit_start && random_access);
+    }
+    size_t i = 0u;
+    i += ts::FillInPacketHeader(&header_data[i], is_payload_unit_start,
+                                stream_state.packet_id, adaptation_field_flag,
+                                stream_state.counters.continuity++);
+    if (is_payload_unit_start) {
+      size_t adaptation_field_size = adaptation_field_min_size;
+      if (adaptation_field_flag) {
+        adaptation_field_size = ts::FillInAdaptationField(
+            &header_data[i], random_access, adaptation_field_min_size);
+        i += adaptation_field_size;
+        DCHECK_GE(adaptation_field_size, adaptation_field_min_size);
+      }
+      std::memcpy(&header_data[i], elementary_stream_packet.header().data(),
+                  elementary_stream_packet.header().size());
+      i += elementary_stream_packet.header().size();
+      std::memcpy(&header_data[i],
+                  elementary_stream_packet.unit_header().data(),
+                  elementary_stream_packet.unit_header().size());
+      i += elementary_stream_packet.unit_header().size();
+      DCHECK_EQ(header_min_size + adaptation_field_size, i);
+    } else if (is_payload_unit_end) {
+      if (adaptation_field_flag) {
+        // Fill in an adaptation field only for padding.
+        i += ts::FillInAdaptationField(&header_data[i], false,
+                                       adaptation_field_min_size);
+      }
+      DCHECK_EQ(header_min_size + adaptation_field_min_size, i);
+    }
+
+    // Delegate the packet.
+    WiFiDisplayTransportStreamPacket packet(
+        header_data, i,
+        elementary_stream_packet.unit().end() - remaining_unit_size);
+    DCHECK_LE(packet.payload().size(), remaining_unit_size);
+    remaining_unit_size -= packet.payload().size();
+    if (!OnPacketizedTransportStreamPacket(
+            packet, flush && remaining_unit_size == 0u)) {
+      return false;
+    }
+
+    // Prepare for the next packet.
+    is_payload_unit_end =
+        remaining_unit_size <=
+        WiFiDisplayTransportStreamPacket::kPacketSize - ts::kPacketHeaderSize;
+    is_payload_unit_start = false;
+  } while (remaining_unit_size > 0u);
+
+  DCHECK_EQ(0u, remaining_unit_size);
+
+  return true;
+}
+
+bool WiFiDisplayTransportStreamPacketizer::EncodeMetaInformation(bool flush) {
+  DCHECK(CalledOnValidThread());
+
+  return (EncodeProgramAssociationTable(false) &&
+          EncodeProgramMapTables(false) && EncodeProgramClockReference(flush));
+}
+
+bool WiFiDisplayTransportStreamPacketizer::EncodeProgramAssociationTable(
+    bool flush) {
+  DCHECK(CalledOnValidThread());
+
+  const uint16_t transport_stream_id = 0x0001u;
+
+  uint8_t header_data[WiFiDisplayTransportStreamPacket::kPacketSize];
+  size_t i = 0u;
+
+  // Fill in a packet header.
+  i += ts::FillInPacketHeader(&header_data[i], true,
+                              widi::kProgramAssociationTablePacketId, false,
+                              counters_.program_association_table_continuity++);
+
+  // Fill in a minimal table pointer.
+  i += psi::FillInTablePointer(&header_data[i], 0u);
+
+  // Reserve space for a table header.
+  const size_t table_header_index = i;
+  i += psi::kTableHeaderSize;
+
+  // Fill in a table syntax.
+  const uint8_t version_number = 0u;
+  i += psi::FillInTableSyntax(&header_data[i], transport_stream_id,
+                              version_number);
+
+  // Fill in program association table data.
+  i += psi::FillInProgramAssociationTableEntry(&header_data[i],
+                                               psi::kFirstProgramNumber,
+                                               widi::kProgramMapTablePacketId);
+
+  // Fill in a table header and a CRC now that the table size is known.
+  i += psi::FillInTableHeaderAndCrc(&header_data[table_header_index],
+                                    &header_data[i],
+                                    psi::kProgramAssociationTableId);
+
+  // Delegate the packet.
+  return OnPacketizedTransportStreamPacket(
+      WiFiDisplayTransportStreamPacket(header_data, i), flush);
+}
+
+bool WiFiDisplayTransportStreamPacketizer::EncodeProgramClockReference(
+    bool flush) {
+  DCHECK(CalledOnValidThread());
+
+  program_clock_reference_ = base::TimeTicks::Now();
+
+  uint8_t header_data[ts::kPacketHeaderSize + ts::kAdaptationFieldLengthSize +
+                      ts::kAdaptationFieldFlagsSize +
+                      ts::kProgramClockReferenceSize];
+  size_t i = 0u;
+
+  // Fill in a packet header.
+  i += ts::FillInPacketHeader(&header_data[i], true,
+                              widi::kProgramClockReferencePacketId, true,
+                              counters_.program_clock_reference_continuity++);
+
+  // Fill in an adaptation field.
+  i += ts::FillInAdaptationFieldLengthFromSize(
+      &header_data[i], WiFiDisplayTransportStreamPacket::kPacketSize - i);
+  i += ts::FillInAdaptationFieldFlags(&header_data[i], false,
+                                      program_clock_reference_);
+  i += ts::FillInProgramClockReference(&header_data[i],
+                                       program_clock_reference_);
+
+  DCHECK_EQ(std::end(header_data), header_data + i);
+
+  // Delegate the packet.
+  return OnPacketizedTransportStreamPacket(
+      WiFiDisplayTransportStreamPacket(header_data, i), flush);
+}
+
+bool WiFiDisplayTransportStreamPacketizer::EncodeProgramMapTables(bool flush) {
+  DCHECK(CalledOnValidThread());
+  DCHECK(!stream_states_.empty());
+
+  const uint16_t program_number = psi::kFirstProgramNumber;
+
+  uint8_t header_data[WiFiDisplayTransportStreamPacket::kPacketSize];
+  size_t i = 0u;
+
+  // Fill in a packet header.
+  i += ts::FillInPacketHeader(&header_data[i], true,
+                              widi::kProgramMapTablePacketId, false,
+                              counters_.program_map_table_continuity++);
+
+  // Fill in a minimal table pointer.
+  i += psi::FillInTablePointer(&header_data[i], 0u);
+
+  // Reserve space for a table header.
+  const size_t table_header_index = i;
+  i += psi::kTableHeaderSize;
+
+  // Fill in a table syntax.
+  i += psi::FillInTableSyntax(&header_data[i], program_number,
+                              counters_.program_map_table_version);
+
+  // Fill in program map table data.
+  i += psi::FillInProgramMapTableData(&header_data[i],
+                                      widi::kProgramClockReferencePacketId);
+  for (const auto& stream_state : stream_states_) {
+    DCHECK_LE(i + psi::kProgramMapTableElementaryStreamEntryBaseSize +
+                  stream_state.info_length + psi::kCrcSize,
+              WiFiDisplayTransportStreamPacket::kPacketSize);
+    i += psi::FillInProgramMapTableElementaryStreamEntry(
+        &header_data[i], stream_state.info.type(), stream_state.packet_id,
+        stream_state.info_length, stream_state.info.descriptors());
+  }
+
+  // Fill in a table header and a CRC now that the table size is known.
+  i += psi::FillInTableHeaderAndCrc(&header_data[table_header_index],
+                                    &header_data[i], psi::kProgramMapTableId);
+
+  // Delegate the packet.
+  return OnPacketizedTransportStreamPacket(
+      WiFiDisplayTransportStreamPacket(header_data, i), flush);
+}
+
+void WiFiDisplayTransportStreamPacketizer::NormalizeUnitTimeStamps(
+    base::TimeTicks* pts,
+    base::TimeTicks* dts) const {
+  DCHECK(CalledOnValidThread());
+
+  // Normalize a presentation time stamp.
+  if (!pts || pts->is_null())
+    return;
+  *pts += delay_for_unit_time_stamps_;
+  DCHECK_LE(program_clock_reference_, *pts);
+
+  // Normalize a decoding time stamp.
+  if (!dts || dts->is_null())
+    return;
+  *dts += delay_for_unit_time_stamps_;
+  DCHECK_LE(program_clock_reference_, *dts);
+  DCHECK_LE(*dts, *pts);
+}
+
+bool WiFiDisplayTransportStreamPacketizer::SetElementaryStreams(
+    std::vector<WiFiDisplayElementaryStreamInfo> stream_infos) {
+  DCHECK(CalledOnValidThread());
+
+  std::vector<ElementaryStreamState> new_stream_states;
+  new_stream_states.reserve(stream_infos.size());
+
+  uint8_t audio_stream_id =
+      WiFiDisplayElementaryStreamPacketizer::kFirstAudioStreamId;
+  uint16_t audio_stream_packet_id = widi::kFirstAudioStreamPacketId;
+  uint8_t private_stream_1_id =
+      WiFiDisplayElementaryStreamPacketizer::kPrivateStream1Id;
+  uint16_t video_stream_packet_id = widi::kVideoStreamPacketId;
+
+  for (auto& stream_info : stream_infos) {
+    uint16_t packet_id;
+    uint8_t stream_id;
+
+    switch (stream_info.type()) {
+      case AUDIO_AAC:
+        packet_id = audio_stream_packet_id++;
+        stream_id = audio_stream_id++;
+        break;
+      case AUDIO_AC3:
+      case AUDIO_LPCM:
+        if (private_stream_1_id !=
+            WiFiDisplayElementaryStreamPacketizer::kPrivateStream1Id) {
+          return false;
+        }
+        packet_id = audio_stream_packet_id++;
+        stream_id = private_stream_1_id++;
+        break;
+      case VIDEO_H264:
+        if (video_stream_packet_id != widi::kVideoStreamPacketId)
+          return false;
+        packet_id = video_stream_packet_id++;
+        stream_id = WiFiDisplayElementaryStreamPacketizer::kFirstVideoStreamId;
+        break;
+    }
+
+    new_stream_states.emplace_back(std::move(stream_info), packet_id,
+                                   stream_id);
+  }
+
+  // If there are no previous states, there is no previous program map table
+  // to change, either. This ensures that the first encoded program map table
+  // has version 0.
+  if (!stream_states_.empty())
+    ++counters_.program_map_table_version;
+
+  stream_states_.swap(new_stream_states);
+
+  return true;
+}
+
+void WiFiDisplayTransportStreamPacketizer::UpdateDelayForUnitTimeStamps(
+    const base::TimeTicks& pts,
+    const base::TimeTicks& dts) {
+  DCHECK(CalledOnValidThread());
+
+  if (pts.is_null())
+    return;
+
+  const base::TimeTicks now = base::TimeTicks::Now();
+  DCHECK_LE(program_clock_reference_, now);
+
+  // Ensure that delayed time stamps are greater than or equal to now.
+  const base::TimeTicks ts_min =
+      (dts.is_null() ? pts : dts) + delay_for_unit_time_stamps_;
+  if (now > ts_min) {
+    const base::TimeDelta error = now - ts_min;
+    delay_for_unit_time_stamps_ += 2 * error;
+  }
+}
+
+}  // namespace extensions
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.h b/extensions/renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.h
new file mode 100644
index 0000000..0cdeb6a7
--- /dev/null
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.h
@@ -0,0 +1,176 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_RENDERER_API_DISPLAY_SOURCE_WIFI_DISPLAY_WIFI_DISPLAY_TRANSPORT_STREAM_PACKETIZER_H_
+#define EXTENSIONS_RENDERER_API_DISPLAY_SOURCE_WIFI_DISPLAY_WIFI_DISPLAY_TRANSPORT_STREAM_PACKETIZER_H_
+
+#include <vector>
+
+#include "base/threading/non_thread_safe.h"
+#include "base/time/time.h"
+#include "extensions/renderer/api/display_source/wifi_display/wifi_display_stream_packet_part.h"
+
+namespace extensions {
+
+class WiFiDisplayElementaryStreamInfo;
+class WiFiDisplayElementaryStreamPacket;
+
+// This class represents an MPEG Transport Stream (MPEG-TS) packet containing
+// WiFi Display elementary stream unit data or related meta information.
+class WiFiDisplayTransportStreamPacket {
+ public:
+  enum { kPacketSize = 188u };
+
+  using Part = WiFiDisplayStreamPacketPart;
+
+  // This class represents a possibly empty padding part in the end of
+  // a transport stream packet. The padding part consists of repeated bytes
+  // having the same value.
+  class PaddingPart {
+   public:
+    explicit PaddingPart(unsigned size) : size_(size) {}
+
+    unsigned size() const { return size_; }
+    uint8_t value() const { return 0xFFu; }
+
+   private:
+    const unsigned size_;
+
+    DISALLOW_COPY_AND_ASSIGN(PaddingPart);
+  };
+
+  WiFiDisplayTransportStreamPacket(const uint8_t* header_data,
+                                   size_t header_size);
+  WiFiDisplayTransportStreamPacket(const uint8_t* header_data,
+                                   size_t header_size,
+                                   const uint8_t* payload_data);
+
+  const Part& header() const { return header_; }
+  const Part& payload() const { return payload_; }
+  const PaddingPart& filler() const { return filler_; }
+
+ private:
+  const Part header_;
+  const Part payload_;
+  const PaddingPart filler_;
+
+  DISALLOW_COPY_AND_ASSIGN(WiFiDisplayTransportStreamPacket);
+};
+
+// The WiFi Display transport stream packetizer packetizes unit buffers to
+// MPEG Transport Stream (MPEG-TS) packets containing either meta information
+// or Packetized Elementary Stream (PES) packets containing unit data.
+//
+// Whenever a Transport Stream (TS) packet is fully created and thus ready for
+// further processing, a pure virtual member function
+// |OnPacketizedTransportStreamPacket| is called.
+class WiFiDisplayTransportStreamPacketizer : public base::NonThreadSafe {
+ public:
+  enum ElementaryStreamType : uint8_t {
+    AUDIO_AAC = 0x0Fu,
+    AUDIO_AC3 = 0x81u,
+    AUDIO_LPCM = 0x83u,
+    VIDEO_H264 = 0x1Bu,
+  };
+
+  // Fixed coding parameters for Linear Pulse-Code Modulation (LPCM) audio
+  // streams. See |WiFiDisplayElementaryStreamDescriptor::LPCMAudioStream| for
+  // variable ones.
+  struct LPCM {
+    enum {
+      kFramesPerUnit = 6u,
+      kChannelSamplesPerFrame = 80u,
+      kChannelSamplesPerUnit = kChannelSamplesPerFrame * kFramesPerUnit
+    };
+  };
+
+  WiFiDisplayTransportStreamPacketizer(
+      const base::TimeDelta& delay_for_unit_time_stamps,
+      std::vector<WiFiDisplayElementaryStreamInfo> stream_infos);
+  virtual ~WiFiDisplayTransportStreamPacketizer();
+
+  // Encodes one elementary stream unit buffer (such as one video frame or
+  // 2 * |LPCM::kChannelSamplesPerUnit| two-channel LPCM audio samples) into
+  // packets:
+  //  1) Encodes meta information into meta information packets (by calling
+  //     |EncodeMetaInformation|) if needed.
+  //  2) Normalizes unit time stamps (|pts| and |dts|) so that they are never
+  //     smaller than a program clock reference.
+  //  3) Encodes the elementary stream unit buffer to unit data packets.
+  // Returns false in the case of an error in which case the caller should stop
+  // encoding.
+  //
+  // In order to minimize encoding delays, |flush| should be true unless
+  // the caller is about to continue encoding immediately.
+  //
+  // Precondition: Elementary streams are configured either using a constructor
+  //               or using the |SetElementaryStreams| member function.
+  bool EncodeElementaryStreamUnit(unsigned stream_index,
+                                  const uint8_t* unit_data,
+                                  size_t unit_size,
+                                  bool random_access,
+                                  base::TimeTicks pts,
+                                  base::TimeTicks dts,
+                                  bool flush);
+
+  // Encodes meta information (program association table, program map table and
+  // program clock reference). Returns false in the case of an error in which
+  // case the caller should stop encoding.
+  //
+  // The |EncodeElementaryStreamUnit| member function calls this member function
+  // when needed, thus the caller is responsible for calling this member
+  // function explicitly only if the caller does silence suppression and does
+  // thus not encode all elementary stream units by calling
+  // the |EncodeElementaryStreamUnit| member function.
+  //
+  // In order to minimize encoding delays, |flush| should be true unless
+  // the caller is about to continue encoding immediately.
+  //
+  // Precondition: Elementary streams are configured either using a constructor
+  //               or using the |SetElementaryStreams| member function.
+  bool EncodeMetaInformation(bool flush);
+
+  bool SetElementaryStreams(
+      std::vector<WiFiDisplayElementaryStreamInfo> stream_infos);
+
+  void DetachFromThread() { base::NonThreadSafe::DetachFromThread(); }
+
+ protected:
+  bool EncodeProgramAssociationTable(bool flush);
+  bool EncodeProgramClockReference(bool flush);
+  bool EncodeProgramMapTables(bool flush);
+
+  // Normalizes unit time stamps by delaying them in order to ensure that unit
+  // time stamps are never smaller than a program clock reference.
+  // Precondition: The |UpdateDelayForUnitTimeStamps| member function is called.
+  void NormalizeUnitTimeStamps(base::TimeTicks* pts,
+                               base::TimeTicks* dts) const;
+  // Update unit time stamp delay in order to ensure that normalized unit time
+  // stamps are never smaller than a program clock reference.
+  void UpdateDelayForUnitTimeStamps(const base::TimeTicks& pts,
+                                    const base::TimeTicks& dts);
+
+  // Called whenever a Transport Stream (TS) packet is fully created and thus
+  // ready for further processing.
+  virtual bool OnPacketizedTransportStreamPacket(
+      const WiFiDisplayTransportStreamPacket& transport_stream_packet,
+      bool flush) = 0;
+
+ private:
+  struct ElementaryStreamState;
+
+  struct {
+    uint8_t program_association_table_continuity;
+    uint8_t program_map_table_continuity;
+    uint8_t program_map_table_version;
+    uint8_t program_clock_reference_continuity;
+  } counters_;
+  base::TimeDelta delay_for_unit_time_stamps_;
+  base::TimeTicks program_clock_reference_;
+  std::vector<ElementaryStreamState> stream_states_;
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_RENDERER_API_DISPLAY_SOURCE_WIFI_DISPLAY_WIFI_DISPLAY_TRANSPORT_STREAM_PACKETIZER_H_
diff --git a/gpu/blink/webgraphicscontext3d_impl.cc b/gpu/blink/webgraphicscontext3d_impl.cc
index da34cb5..7a9a620 100644
--- a/gpu/blink/webgraphicscontext3d_impl.cc
+++ b/gpu/blink/webgraphicscontext3d_impl.cc
@@ -62,124 +62,6 @@
   graphics_context_->OnErrorMessage(msg, id);
 }
 
-// Helper macros to reduce the amount of code.
-
-#define DELEGATE_TO_GL(name, glname)                                    \
-void WebGraphicsContext3DImpl::name() {                                 \
-  gl_->glname();                                                        \
-}
-
-#define DELEGATE_TO_GL_R(name, glname, rt)                              \
-rt WebGraphicsContext3DImpl::name() {                                   \
-  return gl_->glname();                                                 \
-}
-
-#define DELEGATE_TO_GL_1(name, glname, t1)                              \
-void WebGraphicsContext3DImpl::name(t1 a1) {                            \
-  gl_->glname(a1);                                                      \
-}
-
-#define DELEGATE_TO_GL_1R(name, glname, t1, rt)                         \
-rt WebGraphicsContext3DImpl::name(t1 a1) {                              \
-  return gl_->glname(a1);                                               \
-}
-
-#define DELEGATE_TO_GL_1RB(name, glname, t1, rt)                        \
-rt WebGraphicsContext3DImpl::name(t1 a1) {                              \
-  return gl_->glname(a1) ? true : false;                                \
-}
-
-#define DELEGATE_TO_GL_2(name, glname, t1, t2)                          \
-void WebGraphicsContext3DImpl::name(t1 a1, t2 a2) {                     \
-  gl_->glname(a1, a2);                                                  \
-}
-
-#define DELEGATE_TO_GL_2R(name, glname, t1, t2, rt)                     \
-rt WebGraphicsContext3DImpl::name(t1 a1, t2 a2) {                       \
-  return gl_->glname(a1, a2);                                           \
-}
-
-#define DELEGATE_TO_GL_3(name, glname, t1, t2, t3)                      \
-void WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3) {              \
-  gl_->glname(a1, a2, a3);                                              \
-}
-
-#define DELEGATE_TO_GL_3R(name, glname, t1, t2, t3, rt)                 \
-rt WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3) {                \
-  return gl_->glname(a1, a2, a3);                                       \
-}
-
-#define DELEGATE_TO_GL_4(name, glname, t1, t2, t3, t4)                  \
-void WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4) {       \
-  gl_->glname(a1, a2, a3, a4);                                          \
-}
-
-#define DELEGATE_TO_GL_4R(name, glname, t1, t2, t3, t4, rt)             \
-rt WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4) {         \
-  return gl_->glname(a1, a2, a3, a4);                                   \
-}
-
-#define DELEGATE_TO_GL_5(name, glname, t1, t2, t3, t4, t5)              \
-void WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) {\
-                                                                        \
-  gl_->glname(a1, a2, a3, a4, a5);                                      \
-}
-
-#define DELEGATE_TO_GL_6(name, glname, t1, t2, t3, t4, t5, t6)          \
-void WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5,  \
-                                    t6 a6) {                            \
-  gl_->glname(a1, a2, a3, a4, a5, a6);                                  \
-}
-
-#define DELEGATE_TO_GL_7(name, glname, t1, t2, t3, t4, t5, t6, t7)      \
-void WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5,  \
-                                    t6 a6, t7 a7) {                     \
-  gl_->glname(a1, a2, a3, a4, a5, a6, a7);                              \
-}
-
-#define DELEGATE_TO_GL_8(name, glname, t1, t2, t3, t4, t5, t6, t7, t8)  \
-void WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5,  \
-                                    t6 a6, t7 a7, t8 a8) {              \
-  gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8);                          \
-}
-
-#define DELEGATE_TO_GL_9(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, t9) \
-void WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5,  \
-                                    t6 a6, t7 a7, t8 a8, t9 a9) {       \
-  gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9);                      \
-}
-
-#define DELEGATE_TO_GL_9R(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, \
-                          t9, rt)                                       \
-rt WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5,    \
-                                    t6 a6, t7 a7, t8 a8, t9 a9) {       \
-  return gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9);               \
-}
-
-#define DELEGATE_TO_GL_10(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, \
-                          t9, t10)                                      \
-void WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5,  \
-                                    t6 a6, t7 a7, t8 a8, t9 a9,         \
-                                    t10 a10) {                          \
-  gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);                 \
-}
-
-#define DELEGATE_TO_GL_11(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, \
-                          t9, t10, t11)                                 \
-void WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5,  \
-                                    t6 a6, t7 a7, t8 a8, t9 a9, t10 a10,\
-                                    t11 a11) {                          \
-  gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);            \
-}
-
-#define DELEGATE_TO_GL_12(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, \
-                          t9, t10, t11, t12)                            \
-void WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5,  \
-                                    t6 a6, t7 a7, t8 a8, t9 a9, t10 a10,\
-                                    t11 a11, t12 a12) {                 \
-  gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);       \
-}
-
 WebGraphicsContext3DImpl::WebGraphicsContext3DImpl()
     : initialized_(false),
       initialize_failed_(false),
@@ -191,12 +73,6 @@
 
 }
 
-blink::WebString WebGraphicsContext3DImpl::
-    getRequestableExtensionsCHROMIUM() {
-  return blink::WebString::fromUTF8(
-      gl_->GetRequestableExtensionsCHROMIUM());
-}
-
 bool WebGraphicsContext3DImpl::getActiveAttrib(
     WebGLId program, WGC3Duint index, ActiveInfo& info) {
   GLint max_name_length = -1;
@@ -318,60 +194,6 @@
   return res;
 }
 
-blink::WebString WebGraphicsContext3DImpl::getString(
-    WGC3Denum name) {
-  return blink::WebString::fromUTF8(
-      reinterpret_cast<const char*>(gl_->GetString(name)));
-}
-
-void WebGraphicsContext3DImpl::shaderSource(
-    WebGLId shader, const WGC3Dchar* string) {
-  GLint length = strlen(string);
-  gl_->ShaderSource(shader, 1, &string, &length);
-}
-
-WebGLId WebGraphicsContext3DImpl::createBuffer() {
-  GLuint o;
-  gl_->GenBuffers(1, &o);
-  return o;
-}
-
-WebGLId WebGraphicsContext3DImpl::createFramebuffer() {
-  GLuint o = 0;
-  gl_->GenFramebuffers(1, &o);
-  return o;
-}
-
-WebGLId WebGraphicsContext3DImpl::createRenderbuffer() {
-  GLuint o;
-  gl_->GenRenderbuffers(1, &o);
-  return o;
-}
-
-WebGLId WebGraphicsContext3DImpl::createTexture() {
-  GLuint o;
-  gl_->GenTextures(1, &o);
-  return o;
-}
-
-void WebGraphicsContext3DImpl::deleteBuffer(WebGLId buffer) {
-  gl_->DeleteBuffers(1, &buffer);
-}
-
-void WebGraphicsContext3DImpl::deleteFramebuffer(
-    WebGLId framebuffer) {
-  gl_->DeleteFramebuffers(1, &framebuffer);
-}
-
-void WebGraphicsContext3DImpl::deleteRenderbuffer(
-    WebGLId renderbuffer) {
-  gl_->DeleteRenderbuffers(1, &renderbuffer);
-}
-
-void WebGraphicsContext3DImpl::deleteTexture(WebGLId texture) {
-  gl_->DeleteTextures(1, &texture);
-}
-
 void WebGraphicsContext3DImpl::setErrorMessageCallback(
     WebGraphicsContext3D::WebGraphicsErrorMessageCallback* cb) {
   error_message_callback_ = cb;
@@ -382,137 +204,6 @@
   context_lost_callback_ = cb;
 }
 
-WebGLId WebGraphicsContext3DImpl::createQueryEXT() {
-  GLuint o;
-  gl_->GenQueriesEXT(1, &o);
-  return o;
-}
-
-void WebGraphicsContext3DImpl::deleteQueryEXT(
-    WebGLId query) {
-  gl_->DeleteQueriesEXT(1, &query);
-}
-
-WebGLId WebGraphicsContext3DImpl::createValuebufferCHROMIUM() {
-  GLuint o;
-  gl_->GenValuebuffersCHROMIUM(1, &o);
-  return o;
-}
-
-void WebGraphicsContext3DImpl::deleteValuebufferCHROMIUM(WebGLId valuebuffer) {
-  gl_->DeleteValuebuffersCHROMIUM(1, &valuebuffer);
-}
-
-void WebGraphicsContext3DImpl::pushGroupMarkerEXT(
-    const WGC3Dchar* marker) {
-  gl_->PushGroupMarkerEXT(0, marker);
-}
-
-WebGLId WebGraphicsContext3DImpl::createVertexArrayOES() {
-  GLuint array;
-  gl_->GenVertexArraysOES(1, &array);
-  return array;
-}
-
-void WebGraphicsContext3DImpl::deleteVertexArrayOES(
-    WebGLId array) {
-  gl_->DeleteVertexArraysOES(1, &array);
-}
-
-DELEGATE_TO_GL_1(beginTransformFeedback, BeginTransformFeedback, WGC3Denum)
-DELEGATE_TO_GL_3(bindBufferBase, BindBufferBase, WGC3Denum, WGC3Duint,
-                 WGC3Duint)
-DELEGATE_TO_GL_5(bindBufferRange, BindBufferRange, WGC3Denum, WGC3Duint,
-                 WGC3Duint, WGC3Dintptr, WGC3Dsizeiptr)
-DELEGATE_TO_GL_2(bindSampler, BindSampler, WGC3Duint, WebGLId)
-DELEGATE_TO_GL_2(bindTransformFeedback, BindTransformFeedback, WGC3Denum,
-                 WebGLId)
-DELEGATE_TO_GL_4(clearBufferfi, ClearBufferfi, WGC3Denum, WGC3Dint, WGC3Dfloat,
-                 WGC3Dint)
-DELEGATE_TO_GL_3(clearBufferfv, ClearBufferfv, WGC3Denum, WGC3Dint,
-                 const WGC3Dfloat *)
-DELEGATE_TO_GL_3(clearBufferiv, ClearBufferiv, WGC3Denum, WGC3Dint,
-                 const WGC3Dint *)
-DELEGATE_TO_GL_3(clearBufferuiv, ClearBufferuiv, WGC3Denum, WGC3Dint,
-                 const WGC3Duint *)
-DELEGATE_TO_GL_9(compressedTexImage3D, CompressedTexImage3D, WGC3Denum,
-                 WGC3Dint, WGC3Denum, WGC3Dsizei, WGC3Dsizei, WGC3Dsizei,
-                 WGC3Dint, WGC3Dsizei, const void *)
-DELEGATE_TO_GL_11(compressedTexSubImage3D, CompressedTexSubImage3D, WGC3Denum,
-                  WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei,
-                  WGC3Dsizei, WGC3Dsizei, WGC3Denum, WGC3Dsizei, const void *)
-DELEGATE_TO_GL_5(copyBufferSubData, CopyBufferSubData, WGC3Denum, WGC3Denum,
-                 WGC3Dintptr, WGC3Dintptr, WGC3Dsizeiptr)
-DELEGATE_TO_GL_9(copyTexSubImage3D, CopyTexSubImage3D, WGC3Denum, WGC3Dint,
-                 WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei,
-                 WGC3Dsizei)
-WebGLId WebGraphicsContext3DImpl::createSampler() {
-  GLuint sampler;
-  gl_->GenSamplers(1, &sampler);
-  return sampler;
-}
-WebGLId WebGraphicsContext3DImpl::createTransformFeedback() {
-  GLuint tf;
-  gl_->GenTransformFeedbacks(1, &tf);
-  return tf;
-}
-void WebGraphicsContext3DImpl::deleteSampler(WebGLId sampler) {
-  gl_->DeleteSamplers(1, &sampler);
-}
-void WebGraphicsContext3DImpl::deleteTransformFeedback(WebGLId tf) {
-  gl_->DeleteTransformFeedbacks(1, &tf);
-}
-DELEGATE_TO_GL(endTransformFeedback, EndTransformFeedback)
-DELEGATE_TO_GL_5(getActiveUniformBlockName, GetActiveUniformBlockName,
-                 WGC3Duint, WGC3Duint, WGC3Dsizei, WGC3Dsizei *, WGC3Dchar *)
-DELEGATE_TO_GL_4(getActiveUniformBlockiv, GetActiveUniformBlockiv, WGC3Duint,
-                 WGC3Duint, WGC3Denum, WGC3Dint *)
-DELEGATE_TO_GL_5(getActiveUniformsiv, GetActiveUniformsiv, WGC3Duint,
-                 WGC3Dsizei, const WGC3Duint *, WGC3Denum, WGC3Dint *)
-DELEGATE_TO_GL_2R(getFragDataLocation, GetFragDataLocation, WGC3Duint,
-                  const WGC3Dchar *, WGC3Dint)
-DELEGATE_TO_GL_5(getInternalformativ, GetInternalformativ, WGC3Denum, WGC3Denum,
-                 WGC3Denum, WGC3Dsizei, WGC3Dint *)
-DELEGATE_TO_GL_3(getSamplerParameterfv, GetSamplerParameterfv, WGC3Duint,
-                 WGC3Denum, WGC3Dfloat *)
-DELEGATE_TO_GL_3(getSamplerParameteriv, GetSamplerParameteriv, WGC3Duint,
-                 WGC3Denum, WGC3Dint *)
-DELEGATE_TO_GL_7(getTransformFeedbackVarying, GetTransformFeedbackVarying,
-                 WGC3Duint, WGC3Duint, WGC3Dsizei, WGC3Dsizei *, WGC3Dsizei *,
-                 WGC3Denum *, WGC3Dchar *)
-DELEGATE_TO_GL_2R(getUniformBlockIndex, GetUniformBlockIndex, WGC3Duint,
-                  const WGC3Dchar *, WGC3Duint)
-DELEGATE_TO_GL_4(getUniformIndices, GetUniformIndices, WGC3Duint, WGC3Dsizei,
-                 const WGC3Dchar *const*, WGC3Duint *)
-DELEGATE_TO_GL_3(getUniformuiv, GetUniformuiv, WGC3Duint, WGC3Dint,
-                 WGC3Duint *)
-DELEGATE_TO_GL_3(invalidateFramebuffer, InvalidateFramebuffer, WGC3Denum,
-                 WGC3Dsizei, const WGC3Denum *)
-DELEGATE_TO_GL_7(invalidateSubFramebuffer, InvalidateSubFramebuffer, WGC3Denum,
-                 WGC3Dsizei, const WGC3Denum *, WGC3Dint, WGC3Dint, WGC3Dsizei,
-                 WGC3Dsizei)
-DELEGATE_TO_GL_1R(isSampler, IsSampler, WebGLId, WGC3Dboolean)
-DELEGATE_TO_GL_1R(isTransformFeedback, IsTransformFeedback, WGC3Duint,
-                  WGC3Dboolean)
-DELEGATE_TO_GL_4R(mapBufferRange, MapBufferRange, WGC3Denum, WGC3Dintptr,
-                  WGC3Dsizeiptr, WGC3Dbitfield, void*);
-DELEGATE_TO_GL(pauseTransformFeedback, PauseTransformFeedback)
-//DELEGATE_TO_GL_3(programParameteri, ProgramParameteri, WGC3Duint, WGC3Denum,
-//                 WGC3Dint)
-DELEGATE_TO_GL_1(readBuffer, ReadBuffer, WGC3Denum)
-DELEGATE_TO_GL(resumeTransformFeedback, ResumeTransformFeedback)
-DELEGATE_TO_GL_3(samplerParameterf, SamplerParameterf, WGC3Duint, WGC3Denum,
-                 WGC3Dfloat)
-DELEGATE_TO_GL_3(samplerParameterfv, SamplerParameterfv, WGC3Duint, WGC3Denum,
-                 const WGC3Dfloat *)
-DELEGATE_TO_GL_3(samplerParameteri, SamplerParameteri, WGC3Duint, WGC3Denum,
-                 WGC3Dint)
-DELEGATE_TO_GL_3(samplerParameteriv, SamplerParameteriv, WGC3Duint, WGC3Denum,
-                 const WGC3Dint *)
-DELEGATE_TO_GL_4(transformFeedbackVaryings, TransformFeedbackVaryings,
-                 WGC3Duint, WGC3Dsizei, const WGC3Dchar *const*, WGC3Denum)
-DELEGATE_TO_GL_1R(unmapBuffer, UnmapBuffer, WGC3Denum, WGC3Dboolean);
-
 ::gpu::gles2::GLES2Interface* WebGraphicsContext3DImpl::getGLES2Interface() {
   return gl_;
 }
diff --git a/gpu/blink/webgraphicscontext3d_impl.h b/gpu/blink/webgraphicscontext3d_impl.h
index 733a5e8f..db08260 100644
--- a/gpu/blink/webgraphicscontext3d_impl.h
+++ b/gpu/blink/webgraphicscontext3d_impl.h
@@ -47,22 +47,6 @@
   blink::WebString getProgramInfoLog(blink::WebGLId program) override;
   blink::WebString getShaderInfoLog(blink::WebGLId shader) override;
   blink::WebString getShaderSource(blink::WebGLId shader) override;
-  blink::WebString getString(blink::WGC3Denum name) override;
-
-  void shaderSource(blink::WebGLId shader,
-                    const blink::WGC3Dchar* string) override;
-
-  blink::WebGLId createBuffer() override;
-  blink::WebGLId createFramebuffer() override;
-  blink::WebGLId createRenderbuffer() override;
-  blink::WebGLId createTexture() override;
-
-  void deleteBuffer(blink::WebGLId) override;
-  void deleteFramebuffer(blink::WebGLId) override;
-  void deleteRenderbuffer(blink::WebGLId) override;
-  void deleteTexture(blink::WebGLId) override;
-
-  blink::WebString getRequestableExtensionsCHROMIUM() override;
 
   blink::WebString getTranslatedShaderSourceANGLE(
       blink::WebGLId shader) override;
@@ -73,168 +57,6 @@
   void setErrorMessageCallback(
       WebGraphicsContext3D::WebGraphicsErrorMessageCallback* callback) override;
 
-  blink::WebGLId createQueryEXT() override;
-  void deleteQueryEXT(blink::WebGLId query) override;
-
-  blink::WebGLId createValuebufferCHROMIUM() override;
-  void deleteValuebufferCHROMIUM(blink::WebGLId) override;
-
-  void pushGroupMarkerEXT(const blink::WGC3Dchar* marker) override;
-
-  // GL_OES_vertex_array_object
-  blink::WebGLId createVertexArrayOES() override;
-  void deleteVertexArrayOES(blink::WebGLId array) override;
-
-  // OpenGL ES 3.0 functions not represented by pre-existing extensions
-  void beginTransformFeedback(blink::WGC3Denum primitiveMode) override;
-  void bindBufferBase(blink::WGC3Denum target,
-                      blink::WGC3Duint index,
-                      blink::WGC3Duint buffer) override;
-  void bindBufferRange(blink::WGC3Denum target,
-                       blink::WGC3Duint index,
-                       blink::WGC3Duint buffer,
-                       blink::WGC3Dintptr offset,
-                       blink::WGC3Dsizeiptr size) override;
-  void bindSampler(blink::WGC3Duint unit, blink::WebGLId sampler) override;
-  void bindTransformFeedback(blink::WGC3Denum target,
-                             blink::WebGLId transformfeedback) override;
-  void clearBufferfi(blink::WGC3Denum buffer,
-                     blink::WGC3Dint drawbuffer,
-                     blink::WGC3Dfloat depth,
-                     blink::WGC3Dint stencil) override;
-  void clearBufferfv(blink::WGC3Denum buffer,
-                     blink::WGC3Dint drawbuffer,
-                     const blink::WGC3Dfloat* value) override;
-  void clearBufferiv(blink::WGC3Denum buffer,
-                     blink::WGC3Dint drawbuffer,
-                     const blink::WGC3Dint* value) override;
-  void clearBufferuiv(blink::WGC3Denum buffer,
-                      blink::WGC3Dint drawbuffer,
-                      const blink::WGC3Duint* value) override;
-  void compressedTexImage3D(blink::WGC3Denum target,
-                            blink::WGC3Dint level,
-                            blink::WGC3Denum internalformat,
-                            blink::WGC3Dsizei width,
-                            blink::WGC3Dsizei height,
-                            blink::WGC3Dsizei depth,
-                            blink::WGC3Dint border,
-                            blink::WGC3Dsizei imageSize,
-                            const void *data) override;
-  void compressedTexSubImage3D(blink::WGC3Denum target,
-                               blink::WGC3Dint level,
-                               blink::WGC3Dint xoffset,
-                               blink::WGC3Dint yoffset,
-                               blink::WGC3Dint zoffset,
-                               blink::WGC3Dsizei width,
-                               blink::WGC3Dsizei height,
-                               blink::WGC3Dsizei depth,
-                               blink::WGC3Denum format,
-                               blink::WGC3Dsizei imageSize,
-                               const void *data) override;
-  void copyBufferSubData(blink::WGC3Denum readTarget,
-                         blink::WGC3Denum writeTarget,
-                         blink::WGC3Dintptr readOffset,
-                         blink::WGC3Dintptr writeOffset,
-                         blink::WGC3Dsizeiptr size) override;
-  void copyTexSubImage3D(blink::WGC3Denum target,
-                         blink::WGC3Dint level,
-                         blink::WGC3Dint xoffset,
-                         blink::WGC3Dint yoffset,
-                         blink::WGC3Dint zoffset,
-                         blink::WGC3Dint x,
-                         blink::WGC3Dint y,
-                         blink::WGC3Dsizei width,
-                         blink::WGC3Dsizei height) override;
-  blink::WebGLId createSampler() override;
-  blink::WebGLId createTransformFeedback() override;
-  void deleteSampler(blink::WebGLId sampler) override;
-  void deleteTransformFeedback(blink::WebGLId transformfeedback) override;
-  void endTransformFeedback(void) override;
-  void getActiveUniformBlockName(blink::WGC3Duint program,
-                                 blink::WGC3Duint uniformBlockIndex,
-                                 blink::WGC3Dsizei bufSize,
-                                 blink::WGC3Dsizei* length,
-                                 blink::WGC3Dchar* uniformBlockName) override;
-  void getActiveUniformBlockiv(blink::WGC3Duint program,
-                               blink::WGC3Duint uniformBlockIndex,
-                               blink::WGC3Denum pname,
-                               blink::WGC3Dint* params) override;
-  void getActiveUniformsiv(blink::WGC3Duint program,
-                           blink::WGC3Dsizei uniformCount,
-                           const blink::WGC3Duint *uniformIndices,
-                           blink::WGC3Denum pname,
-                           blink::WGC3Dint *params) override;
-  blink::WGC3Dint getFragDataLocation(blink::WGC3Duint program,
-                                      const blink::WGC3Dchar* name) override;
-  void getInternalformativ(blink::WGC3Denum target,
-                           blink::WGC3Denum internalformat,
-                           blink::WGC3Denum pname,
-                           blink::WGC3Dsizei bufSize,
-                           blink::WGC3Dint* params) override;
-  void getSamplerParameterfv(blink::WGC3Duint sampler,
-                             blink::WGC3Denum pname,
-                             blink::WGC3Dfloat* params) override;
-  void getSamplerParameteriv(blink::WGC3Duint sampler,
-                             blink::WGC3Denum pname,
-                             blink::WGC3Dint* params) override;
-  void getTransformFeedbackVarying(blink::WGC3Duint program,
-                                   blink::WGC3Duint index,
-                                   blink::WGC3Dsizei bufSize,
-                                   blink::WGC3Dsizei *length,
-                                   blink::WGC3Dsizei *size,
-                                   blink::WGC3Denum *type,
-                                   blink::WGC3Dchar *name) override;
-  blink::WGC3Duint getUniformBlockIndex(
-      blink::WGC3Duint program,
-      const blink::WGC3Dchar* uniformBlockName) override;
-  void getUniformIndices(blink::WGC3Duint program,
-                         blink::WGC3Dsizei uniformCount,
-                         const blink::WGC3Dchar *const*uniformNames,
-                         blink::WGC3Duint *uniformIndices) override;
-  void getUniformuiv(blink::WGC3Duint program,
-                     blink::WGC3Dint location,
-                     blink::WGC3Duint *params) override;
-  void invalidateFramebuffer(blink::WGC3Denum target,
-                             blink::WGC3Dsizei numAttachments,
-                             const blink::WGC3Denum* attachments) override;
-  void invalidateSubFramebuffer(blink::WGC3Denum target,
-                                blink::WGC3Dsizei numAttachments,
-                                const blink::WGC3Denum* attachments,
-                                blink::WGC3Dint x,
-                                blink::WGC3Dint y,
-                                blink::WGC3Dsizei width,
-                                blink::WGC3Dsizei height) override;
-  blink::WGC3Dboolean isSampler(blink::WebGLId sampler) override;
-  blink::WGC3Dboolean isTransformFeedback(blink::WGC3Duint id) override;
-  void* mapBufferRange(blink::WGC3Denum target,
-                       blink::WGC3Dintptr offset,
-                       blink::WGC3Dsizeiptr length,
-                       blink::WGC3Dbitfield access) override;
-  void pauseTransformFeedback(void) override;
-  //void programParameteri(blink::WGC3Duint program,
-  //                       blink::WGC3Denum pname,
-  //                       blink::WGC3Dint value) override;
-  void readBuffer(blink::WGC3Denum src) override;
-  void resumeTransformFeedback(void) override;
-  void samplerParameterf(blink::WGC3Duint sampler,
-                         blink::WGC3Denum pname,
-                         blink::WGC3Dfloat param) override;
-  void samplerParameterfv(blink::WGC3Duint sampler,
-                          blink::WGC3Denum pname,
-                          const blink::WGC3Dfloat* param) override;
-  void samplerParameteri(blink::WGC3Duint sampler,
-                         blink::WGC3Denum pname,
-                         blink::WGC3Dint param) override;
-  void samplerParameteriv(blink::WGC3Duint sampler,
-                          blink::WGC3Denum pname,
-                          const blink::WGC3Dint* param) override;
-  void transformFeedbackVaryings(
-      blink::WGC3Duint program,
-      blink::WGC3Dsizei count,
-      const blink::WGC3Dchar* const* varyings,
-      blink::WGC3Denum bufferMode) override;
-  blink::WGC3Dboolean unmapBuffer(blink::WGC3Denum target) override;
-
   // WebGraphicsContext3D implementation.
   ::gpu::gles2::GLES2Interface* getGLES2Interface() override;
 
diff --git a/gpu/command_buffer/service/buffer_manager.cc b/gpu/command_buffer/service/buffer_manager.cc
index c6f38806..914d9b0 100644
--- a/gpu/command_buffer/service/buffer_manager.cc
+++ b/gpu/command_buffer/service/buffer_manager.cc
@@ -199,17 +199,13 @@
 }
 
 template <typename T>
-GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count,
-    GLuint primitive_restart_index) {
+GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count) {
   GLuint max_value = 0;
   const T* element =
       reinterpret_cast<const T*>(static_cast<const int8_t*>(data) + offset);
   const T* end = element + count;
   for (; element < end; ++element) {
     if (*element > max_value) {
-      if (*element == primitive_restart_index) {
-        continue;
-      }
       max_value = *element;
     }
   }
@@ -217,53 +213,13 @@
 }
 
 bool Buffer::GetMaxValueForRange(
-    GLuint offset, GLsizei count, GLenum type, bool primitive_restart_enabled,
-    GLuint* max_value) {
-  GLuint primitive_restart_index = 0;
-  if (primitive_restart_enabled) {
-    switch (type) {
-      case GL_UNSIGNED_BYTE:
-        primitive_restart_index = 0xFF;
-        break;
-      case GL_UNSIGNED_SHORT:
-        primitive_restart_index = 0xFFFF;
-        break;
-      case GL_UNSIGNED_INT:
-        primitive_restart_index = 0xFFFFFFFF;
-        break;
-      default:
-        NOTREACHED();  // should never get here by validation.
-        break;
-    }
-  }
-
-  Range range(offset, count, type, primitive_restart_enabled);
+    GLuint offset, GLsizei count, GLenum type, GLuint* max_value) {
+  Range range(offset, count, type);
   RangeToMaxValueMap::iterator it = range_set_.find(range);
   if (it != range_set_.end()) {
     *max_value = it->second;
     return true;
   }
-  // Optimization. If:
-  //  - primitive restart is enabled
-  //  - we don't have an entry in the range set for these parameters
-  //    for the situation when primitive restart is enabled
-  //  - we do have an entry in the range set for these parameters for
-  //    the situation when primitive restart is disabled
-  //  - this entry is less than the primitive restart index
-  // Then we can repurpose this entry for the situation when primitive
-  // restart is enabled. Otherwise, we need to compute the max index
-  // from scratch.
-  if (primitive_restart_enabled) {
-    Range disabled_range(offset, count, type, false);
-    RangeToMaxValueMap::iterator it = range_set_.find(disabled_range);
-    if (it != range_set_.end() && it->second < primitive_restart_index) {
-      // This reuses the max value for the case where primitive
-      // restart is enabled.
-      range_set_.insert(std::make_pair(range, it->second));
-      *max_value = it->second;
-      return true;
-    }
-  }
 
   uint32_t size;
   if (!SafeMultiplyUint32(
@@ -287,24 +243,21 @@
   GLuint max_v = 0;
   switch (type) {
     case GL_UNSIGNED_BYTE:
-      max_v = GetMaxValue<uint8_t>(shadow_.get(), offset, count,
-          primitive_restart_index);
+      max_v = GetMaxValue<uint8_t>(shadow_.get(), offset, count);
       break;
     case GL_UNSIGNED_SHORT:
       // Check we are not accessing an odd byte for a 2 byte value.
       if ((offset & 1) != 0) {
         return false;
       }
-      max_v = GetMaxValue<uint16_t>(shadow_.get(), offset, count,
-          primitive_restart_index);
+      max_v = GetMaxValue<uint16_t>(shadow_.get(), offset, count);
       break;
     case GL_UNSIGNED_INT:
       // Check we are not accessing a non aligned address for a 4 byte value.
       if ((offset & 3) != 0) {
         return false;
       }
-      max_v = GetMaxValue<uint32_t>(shadow_.get(), offset, count,
-          primitive_restart_index);
+      max_v = GetMaxValue<uint32_t>(shadow_.get(), offset, count);
       break;
     default:
       NOTREACHED();  // should never get here by validation.
diff --git a/gpu/command_buffer/service/buffer_manager.h b/gpu/command_buffer/service/buffer_manager.h
index 5e2c60c..33df8186 100644
--- a/gpu/command_buffer/service/buffer_manager.h
+++ b/gpu/command_buffer/service/buffer_manager.h
@@ -63,7 +63,7 @@
   // offset is in bytes.
   // count is in elements of type.
   bool GetMaxValueForRange(GLuint offset, GLsizei count, GLenum type,
-                           bool primitive_restart_enabled, GLuint* max_value);
+                           GLuint* max_value);
 
   // Returns a pointer to shadowed data.
   const void* GetRange(GLintptr offset, GLsizeiptr size) const;
@@ -101,12 +101,10 @@
   // Represents a range in a buffer.
   class Range {
    public:
-    Range(GLuint offset, GLsizei count, GLenum type,
-          bool primitive_restart_enabled)
+    Range(GLuint offset, GLsizei count, GLenum type)
         : offset_(offset),
           count_(count),
-          type_(type),
-          primitive_restart_enabled_(primitive_restart_enabled) {
+          type_(type) {
     }
 
     // A less functor provided for std::map so it can find ranges.
@@ -118,10 +116,7 @@
         if (lhs.count_ != rhs.count_) {
           return lhs.count_ < rhs.count_;
         }
-        if (lhs.type_ != rhs.type_) {
-          return lhs.type_ < rhs.type_;
-        }
-        return lhs.primitive_restart_enabled_ < rhs.primitive_restart_enabled_;
+        return lhs.type_ < rhs.type_;
       }
     };
 
@@ -129,7 +124,6 @@
     GLuint offset_;
     GLsizei count_;
     GLenum type_;
-    bool primitive_restart_enabled_;
   };
 
   ~Buffer();
diff --git a/gpu/command_buffer/service/buffer_manager_unittest.cc b/gpu/command_buffer/service/buffer_manager_unittest.cc
index 45e08c8..4c6707a 100644
--- a/gpu/command_buffer/service/buffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/buffer_manager_unittest.cc
@@ -74,158 +74,6 @@
     return success;
   }
 
-  void RunGetMaxValueForRangeUint8Test(bool enable_primitive_restart)
-  {
-    const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
-    const GLuint kClientBufferId = 1;
-    const GLuint kServiceBufferId = 11;
-    const uint8_t data[] = {10, 9, 8, 7, 6, 0xFFu, 4, 3, 2, 1};
-    const uint8_t new_data[] = {100, 120, 110};
-    manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
-    Buffer* buffer = manager_->GetBuffer(kClientBufferId);
-    ASSERT_TRUE(buffer != NULL);
-    manager_->SetTarget(buffer, kTarget);
-    DoBufferData(
-        buffer, kTarget, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR);
-    EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 0, sizeof(data), data));
-    GLuint max_value;
-    // Check entire range succeeds.
-    EXPECT_TRUE(buffer->GetMaxValueForRange(
-        0, 10, GL_UNSIGNED_BYTE, enable_primitive_restart, &max_value));
-    if (enable_primitive_restart) {
-      EXPECT_EQ(10u, max_value);
-    } else {
-      EXPECT_EQ(0xFFu, max_value);
-    }
-    // Check sub range succeeds.
-    EXPECT_TRUE(buffer->GetMaxValueForRange(
-        4, 3, GL_UNSIGNED_BYTE, enable_primitive_restart, &max_value));
-    if (enable_primitive_restart) {
-      EXPECT_EQ(6u, max_value);
-    } else {
-      EXPECT_EQ(0xFFu, max_value);
-    }
-    // Check changing sub range succeeds.
-    EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 4, sizeof(new_data),
-                                new_data));
-    EXPECT_TRUE(buffer->GetMaxValueForRange(
-        4, 3, GL_UNSIGNED_BYTE, enable_primitive_restart, &max_value));
-    EXPECT_EQ(120u, max_value);
-    max_value = 0;
-    EXPECT_TRUE(buffer->GetMaxValueForRange(
-        0, 10, GL_UNSIGNED_BYTE, enable_primitive_restart, &max_value));
-    EXPECT_EQ(120u, max_value);
-    // Check out of range fails.
-    EXPECT_FALSE(buffer->GetMaxValueForRange(
-        0, 11, GL_UNSIGNED_BYTE, enable_primitive_restart, &max_value));
-    EXPECT_FALSE(buffer->GetMaxValueForRange(
-        10, 1, GL_UNSIGNED_BYTE, enable_primitive_restart, &max_value));
-  }
-
-  void RunGetMaxValueForRangeUint16Test(bool enable_primitive_restart) {
-    const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
-    const GLuint kClientBufferId = 1;
-    const GLuint kServiceBufferId = 11;
-    const uint16_t data[] = {10, 9, 8, 7, 6, 0xFFFF, 4, 3, 2, 1};
-    const uint16_t new_data[] = {100, 120, 110};
-    manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
-    Buffer* buffer = manager_->GetBuffer(kClientBufferId);
-    ASSERT_TRUE(buffer != NULL);
-    manager_->SetTarget(buffer, kTarget);
-    DoBufferData(
-        buffer, kTarget, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR);
-    EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 0, sizeof(data), data));
-    GLuint max_value;
-    // Check entire range succeeds.
-    EXPECT_TRUE(buffer->GetMaxValueForRange(
-        0, 10, GL_UNSIGNED_SHORT, enable_primitive_restart, &max_value));
-    if (enable_primitive_restart) {
-      EXPECT_EQ(10u, max_value);
-    } else {
-      EXPECT_EQ(0xFFFFu, max_value);
-    }
-    // Check odd offset fails for GL_UNSIGNED_SHORT.
-    EXPECT_FALSE(buffer->GetMaxValueForRange(
-        1, 10, GL_UNSIGNED_SHORT, enable_primitive_restart, &max_value));
-    // Check sub range succeeds.
-    EXPECT_TRUE(buffer->GetMaxValueForRange(
-        8, 3, GL_UNSIGNED_SHORT, enable_primitive_restart, &max_value));
-    if (enable_primitive_restart) {
-      EXPECT_EQ(6u, max_value);
-    } else {
-      EXPECT_EQ(0xFFFFu, max_value);
-    }
-    // Check changing sub range succeeds.
-    EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 8, sizeof(new_data),
-                                new_data));
-    EXPECT_TRUE(buffer->GetMaxValueForRange(
-        8, 3, GL_UNSIGNED_SHORT, enable_primitive_restart, &max_value));
-    EXPECT_EQ(120u, max_value);
-    max_value = 0;
-    EXPECT_TRUE(buffer->GetMaxValueForRange(
-        0, 10, GL_UNSIGNED_SHORT, enable_primitive_restart, &max_value));
-    EXPECT_EQ(120u, max_value);
-    // Check out of range fails.
-    EXPECT_FALSE(buffer->GetMaxValueForRange(
-        0, 11, GL_UNSIGNED_SHORT, enable_primitive_restart, &max_value));
-    EXPECT_FALSE(buffer->GetMaxValueForRange(
-        20, 1, GL_UNSIGNED_SHORT, enable_primitive_restart, &max_value));
-  }
-
-  void RunGetMaxValueForRangeUint32Test(bool enable_primitive_restart) {
-    const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
-    const GLuint kClientBufferId = 1;
-    const GLuint kServiceBufferId = 11;
-    const uint32_t data[] = {10, 9, 8, 7, 6, 0xFFFFFFFFu, 4, 3, 2, 1};
-    const uint32_t new_data[] = {100, 120, 110};
-    manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
-    Buffer* buffer = manager_->GetBuffer(kClientBufferId);
-    ASSERT_TRUE(buffer != NULL);
-    manager_->SetTarget(buffer, kTarget);
-    DoBufferData(
-        buffer, kTarget, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR);
-    EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 0, sizeof(data), data));
-    GLuint max_value;
-    // Check entire range succeeds.
-    EXPECT_TRUE(buffer->GetMaxValueForRange(
-        0, 10, GL_UNSIGNED_INT, enable_primitive_restart, &max_value));
-    if (enable_primitive_restart) {
-      EXPECT_EQ(10u, max_value);
-    } else {
-      EXPECT_EQ(0xFFFFFFFFu, max_value);
-    }
-    // Check non aligned offsets fails for GL_UNSIGNED_INT.
-    EXPECT_FALSE(buffer->GetMaxValueForRange(
-        1, 10, GL_UNSIGNED_INT, enable_primitive_restart, &max_value));
-    EXPECT_FALSE(buffer->GetMaxValueForRange(
-        2, 10, GL_UNSIGNED_INT, enable_primitive_restart, &max_value));
-    EXPECT_FALSE(buffer->GetMaxValueForRange(
-        3, 10, GL_UNSIGNED_INT, enable_primitive_restart, &max_value));
-    // Check sub range succeeds.
-    EXPECT_TRUE(buffer->GetMaxValueForRange(
-        16, 3, GL_UNSIGNED_INT, enable_primitive_restart, &max_value));
-    if (enable_primitive_restart) {
-      EXPECT_EQ(6u, max_value);
-    } else {
-      EXPECT_EQ(0xFFFFFFFFu, max_value);
-    }
-    // Check changing sub range succeeds.
-    EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 16, sizeof(new_data),
-                                new_data));
-    EXPECT_TRUE(buffer->GetMaxValueForRange(
-        16, 3, GL_UNSIGNED_INT, enable_primitive_restart, &max_value));
-    EXPECT_EQ(120u, max_value);
-    max_value = 0;
-    EXPECT_TRUE(buffer->GetMaxValueForRange(
-        0, 10, GL_UNSIGNED_INT, enable_primitive_restart, &max_value));
-    EXPECT_EQ(120u, max_value);
-    // Check out of range fails.
-    EXPECT_FALSE(buffer->GetMaxValueForRange(
-        0, 11, GL_UNSIGNED_INT, enable_primitive_restart, &max_value));
-    EXPECT_FALSE(buffer->GetMaxValueForRange(
-        40, 1, GL_UNSIGNED_INT, enable_primitive_restart, &max_value));
-  }
-
   scoped_ptr<BufferManager> manager_;
   scoped_ptr<MockErrorState> error_state_;
 };
@@ -395,27 +243,124 @@
 }
 
 TEST_F(BufferManagerTest, GetMaxValueForRangeUint8) {
-  RunGetMaxValueForRangeUint8Test(false);
-}
-
-TEST_F(BufferManagerTest, GetMaxValueForRangeUint8PrimitiveRestart) {
-  RunGetMaxValueForRangeUint8Test(true);
+  const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
+  const GLuint kClientBufferId = 1;
+  const GLuint kServiceBufferId = 11;
+  const uint8_t data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
+  const uint8_t new_data[] = {100, 120, 110};
+  manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
+  Buffer* buffer = manager_->GetBuffer(kClientBufferId);
+  ASSERT_TRUE(buffer != NULL);
+  manager_->SetTarget(buffer, kTarget);
+  DoBufferData(
+      buffer, kTarget, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR);
+  EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 0, sizeof(data), data));
+  GLuint max_value;
+  // Check entire range succeeds.
+  EXPECT_TRUE(buffer->GetMaxValueForRange(
+      0, 10, GL_UNSIGNED_BYTE, &max_value));
+  EXPECT_EQ(10u, max_value);
+  // Check sub range succeeds.
+  EXPECT_TRUE(buffer->GetMaxValueForRange(
+      4, 3, GL_UNSIGNED_BYTE, &max_value));
+  EXPECT_EQ(6u, max_value);
+  // Check changing sub range succeeds.
+  EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 4, sizeof(new_data), new_data));
+  EXPECT_TRUE(buffer->GetMaxValueForRange(
+      4, 3, GL_UNSIGNED_BYTE, &max_value));
+  EXPECT_EQ(120u, max_value);
+  max_value = 0;
+  EXPECT_TRUE(buffer->GetMaxValueForRange(
+      0, 10, GL_UNSIGNED_BYTE, &max_value));
+  EXPECT_EQ(120u, max_value);
+  // Check out of range fails.
+  EXPECT_FALSE(buffer->GetMaxValueForRange(
+      0, 11, GL_UNSIGNED_BYTE, &max_value));
+  EXPECT_FALSE(buffer->GetMaxValueForRange(
+      10, 1, GL_UNSIGNED_BYTE, &max_value));
 }
 
 TEST_F(BufferManagerTest, GetMaxValueForRangeUint16) {
-  RunGetMaxValueForRangeUint16Test(false);
-}
-
-TEST_F(BufferManagerTest, GetMaxValueForRangeUint16PrimitiveRestart) {
-  RunGetMaxValueForRangeUint16Test(true);
+  const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
+  const GLuint kClientBufferId = 1;
+  const GLuint kServiceBufferId = 11;
+  const uint16_t data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
+  const uint16_t new_data[] = {100, 120, 110};
+  manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
+  Buffer* buffer = manager_->GetBuffer(kClientBufferId);
+  ASSERT_TRUE(buffer != NULL);
+  manager_->SetTarget(buffer, kTarget);
+  DoBufferData(
+      buffer, kTarget, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR);
+  EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 0, sizeof(data), data));
+  GLuint max_value;
+  // Check entire range succeeds.
+  EXPECT_TRUE(buffer->GetMaxValueForRange(
+      0, 10, GL_UNSIGNED_SHORT, &max_value));
+  EXPECT_EQ(10u, max_value);
+  // Check odd offset fails for GL_UNSIGNED_SHORT.
+  EXPECT_FALSE(buffer->GetMaxValueForRange(
+      1, 10, GL_UNSIGNED_SHORT, &max_value));
+  // Check sub range succeeds.
+  EXPECT_TRUE(buffer->GetMaxValueForRange(
+      8, 3, GL_UNSIGNED_SHORT, &max_value));
+  EXPECT_EQ(6u, max_value);
+  // Check changing sub range succeeds.
+  EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 8, sizeof(new_data), new_data));
+  EXPECT_TRUE(buffer->GetMaxValueForRange(
+      8, 3, GL_UNSIGNED_SHORT, &max_value));
+  EXPECT_EQ(120u, max_value);
+  max_value = 0;
+  EXPECT_TRUE(buffer->GetMaxValueForRange(
+      0, 10, GL_UNSIGNED_SHORT, &max_value));
+  EXPECT_EQ(120u, max_value);
+  // Check out of range fails.
+  EXPECT_FALSE(buffer->GetMaxValueForRange(
+      0, 11, GL_UNSIGNED_SHORT, &max_value));
+  EXPECT_FALSE(buffer->GetMaxValueForRange(
+      20, 1, GL_UNSIGNED_SHORT, &max_value));
 }
 
 TEST_F(BufferManagerTest, GetMaxValueForRangeUint32) {
-  RunGetMaxValueForRangeUint32Test(false);
-}
-
-TEST_F(BufferManagerTest, GetMaxValueForRangeUint32PrimitiveRestart) {
-  RunGetMaxValueForRangeUint32Test(true);
+  const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
+  const GLuint kClientBufferId = 1;
+  const GLuint kServiceBufferId = 11;
+  const uint32_t data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
+  const uint32_t new_data[] = {100, 120, 110};
+  manager_->CreateBuffer(kClientBufferId, kServiceBufferId);
+  Buffer* buffer = manager_->GetBuffer(kClientBufferId);
+  ASSERT_TRUE(buffer != NULL);
+  manager_->SetTarget(buffer, kTarget);
+  DoBufferData(
+      buffer, kTarget, sizeof(data), GL_STATIC_DRAW, NULL, GL_NO_ERROR);
+  EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 0, sizeof(data), data));
+  GLuint max_value;
+  // Check entire range succeeds.
+  EXPECT_TRUE(
+      buffer->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT, &max_value));
+  EXPECT_EQ(10u, max_value);
+  // Check non aligned offsets fails for GL_UNSIGNED_INT.
+  EXPECT_FALSE(
+      buffer->GetMaxValueForRange(1, 10, GL_UNSIGNED_INT, &max_value));
+  EXPECT_FALSE(
+      buffer->GetMaxValueForRange(2, 10, GL_UNSIGNED_INT, &max_value));
+  EXPECT_FALSE(
+      buffer->GetMaxValueForRange(3, 10, GL_UNSIGNED_INT, &max_value));
+  // Check sub range succeeds.
+  EXPECT_TRUE(buffer->GetMaxValueForRange(16, 3, GL_UNSIGNED_INT, &max_value));
+  EXPECT_EQ(6u, max_value);
+  // Check changing sub range succeeds.
+  EXPECT_TRUE(DoBufferSubData(buffer, kTarget, 16, sizeof(new_data), new_data));
+  EXPECT_TRUE(buffer->GetMaxValueForRange(16, 3, GL_UNSIGNED_INT, &max_value));
+  EXPECT_EQ(120u, max_value);
+  max_value = 0;
+  EXPECT_TRUE(buffer->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT, &max_value));
+  EXPECT_EQ(120u, max_value);
+  // Check out of range fails.
+  EXPECT_FALSE(
+      buffer->GetMaxValueForRange(0, 11, GL_UNSIGNED_INT, &max_value));
+  EXPECT_FALSE(
+      buffer->GetMaxValueForRange(40, 1, GL_UNSIGNED_INT, &max_value));
 }
 
 TEST_F(BufferManagerTest, UseDeletedBuffer) {
@@ -475,7 +420,7 @@
   DoBufferData(
       buffer, kTarget, sizeof(data1), GL_STATIC_DRAW, data1, GL_NO_ERROR);
   EXPECT_TRUE(
-      buffer->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT, false, &max_value));
+      buffer->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT, &max_value));
   EXPECT_EQ(10u, max_value);
   // Check that any cached values are invalidated if the buffer is reloaded
   // with the same amount of data (but different content)
@@ -483,7 +428,7 @@
   DoBufferData(
       buffer, kTarget, sizeof(data2), GL_STATIC_DRAW, data2, GL_NO_ERROR);
   EXPECT_TRUE(
-      buffer->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT, false, &max_value));
+      buffer->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT, &max_value));
   EXPECT_EQ(20u, max_value);
   // Check that any cached values are invalidated if the buffer is reloaded
   // with entirely different content.
@@ -491,7 +436,7 @@
   DoBufferData(
       buffer, kTarget, sizeof(data3), GL_STATIC_DRAW, data3, GL_NO_ERROR);
   EXPECT_TRUE(
-      buffer->GetMaxValueForRange(0, 3, GL_UNSIGNED_INT, false, &max_value));
+      buffer->GetMaxValueForRange(0, 3, GL_UNSIGNED_INT, &max_value));
   EXPECT_EQ(30u, max_value);
 }
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 92accd66f..7ecd8d5f 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -8343,9 +8343,7 @@
       state_.vertex_attrib_manager->element_array_buffer();
 
   if (!element_array_buffer->GetMaxValueForRange(
-          offset, count, type,
-          state_.enable_flags.primitive_restart_fixed_index,
-          &max_vertex_accessed)) {
+      offset, count, type, &max_vertex_accessed)) {
     LOCAL_SET_GL_ERROR(
         GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
     return error::kNoError;
@@ -8442,18 +8440,8 @@
     LOCAL_SET_GL_ERROR(
         GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
   } else {
-    // The max value is used here to emulate client-side vertex
-    // arrays, by uploading enough vertices into buffer objects to
-    // cover the DrawElements call. Baking the primitive restart bit
-    // into this result isn't strictly correct in all cases; the
-    // client side code should pass down the bit and decide how to use
-    // the result. However, the only caller makes the draw call
-    // immediately afterward, so the state won't change between this
-    // query and the draw call.
     if (!buffer->GetMaxValueForRange(
-            offset, count, type,
-            state_.enable_flags.primitive_restart_fixed_index,
-            &max_vertex_accessed)) {
+        offset, count, type, &max_vertex_accessed)) {
       // TODO(gman): Should this be a GL error or a command buffer error?
       LOCAL_SET_GL_ERROR(
           GL_INVALID_OPERATION,
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg
index f9935672..091b991 100644
--- a/infra/config/cq.cfg
+++ b/infra/config/cq.cfg
@@ -83,7 +83,10 @@
       builders { name: "win_chromium_compile_dbg_ng" }
       builders { name: "win_chromium_rel_ng" }
       builders { name: "win_chromium_x64_rel_ng" }
-      builders { name: "win_clang_x64_dbg" }
+      builders {
+        name: "win_clang_x64_dbg"
+        experiment_percentage: 100
+      }
     }
   }
 
diff --git a/ios/chrome/browser/safe_browsing/safe_browsing_service.cc b/ios/chrome/browser/safe_browsing/safe_browsing_service.cc
index 37244926..e2bbe92a 100644
--- a/ios/chrome/browser/safe_browsing/safe_browsing_service.cc
+++ b/ios/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -342,9 +342,10 @@
 void SafeBrowsingService::Start() {
   DCHECK_CURRENTLY_ON(web::WebThread::UI);
 
-  web::WebThread::PostTask(web::WebThread::IO, FROM_HERE,
-                           base::Bind(&SafeBrowsingService::StartOnIOThread,
-                                      this, url_request_context_getter_));
+  web::WebThread::PostTask(
+      web::WebThread::IO, FROM_HERE,
+      base::Bind(&SafeBrowsingService::StartOnIOThread, this,
+                 base::RetainedRef(url_request_context_getter_)));
 }
 
 void SafeBrowsingService::Stop(bool shutdown) {
diff --git a/ios/chrome/browser/web_resource/web_resource_util.cc b/ios/chrome/browser/web_resource/web_resource_util.cc
index e11dedb..cceb553 100644
--- a/ios/chrome/browser/web_resource/web_resource_util.cc
+++ b/ios/chrome/browser/web_resource/web_resource_util.cc
@@ -65,9 +65,10 @@
     const WebResourceService::SuccessCallback& success_callback,
     const WebResourceService::ErrorCallback& error_callback) {
   web::WebThread::PostBlockingPoolTask(
-      FROM_HERE, base::Bind(&ParseJSONOnBackgroundThread,
-                            base::ThreadTaskRunnerHandle::Get(), data,
-                            success_callback, error_callback));
+      FROM_HERE,
+      base::Bind(&ParseJSONOnBackgroundThread,
+                 base::RetainedRef(base::ThreadTaskRunnerHandle::Get()), data,
+                 success_callback, error_callback));
 }
 
 }  // namespace
diff --git a/ios/web/net/request_tracker_impl.mm b/ios/web/net/request_tracker_impl.mm
index 4fc43227..b33c0f6 100644
--- a/ios/web/net/request_tracker_impl.mm
+++ b/ios/web/net/request_tracker_impl.mm
@@ -517,8 +517,8 @@
   scoped_refptr<net::HttpResponseHeaders> headers(request->response_headers());
   web::WebThread::PostTask(
       web::WebThread::UI, FROM_HERE,
-      base::Bind(&RequestTrackerImpl::NotifyResponseHeaders, this, headers,
-                 request->url()));
+      base::Bind(&RequestTrackerImpl::NotifyResponseHeaders, this,
+                 base::RetainedRef(headers), request->url()));
 }
 
 void RequestTrackerImpl::CaptureExpectedLength(const net::URLRequest* request,
@@ -626,7 +626,8 @@
     web::WebThread::PostTask(
         web::WebThread::UI, FROM_HERE,
         base::Bind(&RequestTrackerImpl::NotifyCertificateUsed, this,
-                   ssl_info.cert, host, ssl_info.cert_status));
+                   base::RetainedRef(ssl_info.cert), host,
+                   ssl_info.cert_status));
   }
   should_continue.Run(true);
 }
@@ -1149,7 +1150,7 @@
       web::WebThread::PostTask(
           web::WebThread::UI, FROM_HERE,
           base::Bind(&RequestTrackerImpl::NotifyCertificateUsed, this,
-                     counts->ssl_info.cert, host,
+                     base::RetainedRef(counts->ssl_info.cert), host,
                      counts->ssl_info.cert_status));
     }
     if (counts == splitPosition)
diff --git a/ios/web/web_state/ui/crw_web_controller.h b/ios/web/web_state/ui/crw_web_controller.h
index 5eef87fa..fd9bf7ac 100644
--- a/ios/web/web_state/ui/crw_web_controller.h
+++ b/ios/web/web_state/ui/crw_web_controller.h
@@ -30,15 +30,6 @@
   PAGE_LOADED = 2
 };
 
-// Policy for web page dialog handling.
-enum PageDialogOpenPolicy {
-  // Default policy. Dialogs are allowed, clients are not notified on display.
-  DIALOG_POLICY_ALLOW = 0,
-  // Dialogs are not allowed, client are notified when dialog did block with
-  // -[WebDelegate webControllerDidSuppressDialog:] delegate method call.
-  DIALOG_POLICY_SUPPRESS
-};
-
 // The accessibility identifier of the top-level container view.
 extern NSString* const kContainerViewID;
 
@@ -240,12 +231,6 @@
 // visible only briefly (e.g., tablet side swipe).
 - (void)setOverlayPreviewMode:(BOOL)overlayPreviewMode;
 
-// Sets policy for web page dialog handling. Controls dialog suppression and
-// notifying the WebDelegate.
-// TODO(crbug.com/595463): remove this method, once embedder uses
-// |setSuppressDialogs|.
-- (void)setPageDialogOpenPolicy:(web::PageDialogOpenPolicy)policy;
-
 // Records the state (scroll position, form values, whatever can be harvested)
 // from the current page into the current session entry.
 - (void)recordStateInHistory;
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 12bf6cc2..43caea72 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -3188,18 +3188,6 @@
   }
 }
 
-- (void)setPageDialogOpenPolicy:(web::PageDialogOpenPolicy)policy {
-  switch (policy) {
-    case web::DIALOG_POLICY_ALLOW:
-      self.shouldSuppressDialogs = NO;
-      return;
-    case web::DIALOG_POLICY_SUPPRESS:
-      self.shouldSuppressDialogs = YES;
-      return;
-  }
-  NOTREACHED();
-}
-
 #pragma mark -
 #pragma mark Session Information
 
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm
index 31c33f7..dc9e823 100644
--- a/ios/web/web_state/ui/crw_web_controller_unittest.mm
+++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -521,7 +521,7 @@
 // Tests that window.alert dialog is suppressed for DIALOG_POLICY_SUPPRESS.
 TEST_F(CRWWebControllerPageDialogOpenPolicyTest, SuppressAlert) {
   [[web_delegate_mock() expect] webControllerDidSuppressDialog:webController_];
-  [webController_ setPageDialogOpenPolicy:web::DIALOG_POLICY_SUPPRESS];
+  [webController_ setShouldSuppressDialogs:YES];
   EvaluateJavaScriptAsString(@"alert('test')");
 };
 
@@ -542,14 +542,14 @@
               completion_handler();
             }];
 
-  [webController_ setPageDialogOpenPolicy:web::DIALOG_POLICY_ALLOW];
+  [webController_ setShouldSuppressDialogs:NO];
   EvaluateJavaScriptAsString(@"alert('test')");
 };
 
 // Tests that window.confirm dialog is suppressed for DIALOG_POLICY_SUPPRESS.
 TEST_F(CRWWebControllerPageDialogOpenPolicyTest, SuppressConfirm) {
   [[web_delegate_mock() expect] webControllerDidSuppressDialog:webController_];
-  [webController_ setPageDialogOpenPolicy:web::DIALOG_POLICY_SUPPRESS];
+  [webController_ setShouldSuppressDialogs:YES];
   EXPECT_NSEQ(@"false", EvaluateJavaScriptAsString(@"confirm('test')"));
 };
 
@@ -572,7 +572,7 @@
               callable_block(YES);
             }];
 
-  [webController_ setPageDialogOpenPolicy:web::DIALOG_POLICY_ALLOW];
+  [webController_ setShouldSuppressDialogs:NO];
   EXPECT_NSEQ(@"true", EvaluateJavaScriptAsString(@"confirm('test')"));
 }
 
@@ -595,14 +595,14 @@
               callable_block(NO);
             }];
 
-  [webController_ setPageDialogOpenPolicy:web::DIALOG_POLICY_ALLOW];
+  [webController_ setShouldSuppressDialogs:NO];
   EXPECT_NSEQ(@"false", EvaluateJavaScriptAsString(@"confirm('test')"));
 }
 
 // Tests that window.prompt dialog is suppressed for DIALOG_POLICY_SUPPRESS.
 TEST_F(CRWWebControllerPageDialogOpenPolicyTest, SuppressPrompt) {
   [[web_delegate_mock() expect] webControllerDidSuppressDialog:webController_];
-  [webController_ setPageDialogOpenPolicy:web::DIALOG_POLICY_SUPPRESS];
+  [webController_ setShouldSuppressDialogs:YES];
   EXPECT_NSEQ(@"", EvaluateJavaScriptAsString(@"prompt('Yes?', 'No')"));
 }
 
@@ -626,21 +626,21 @@
               callable_block(@"Maybe");
             }];
 
-  [webController_ setPageDialogOpenPolicy:web::DIALOG_POLICY_ALLOW];
+  [webController_ setShouldSuppressDialogs:NO];
   EXPECT_NSEQ(@"Maybe", EvaluateJavaScriptAsString(@"prompt('Yes?', 'No')"));
 }
 
 // Tests that geolocation dialog is suppressed for DIALOG_POLICY_SUPPRESS.
 TEST_F(CRWWebControllerPageDialogOpenPolicyTest, SuppressGeolocation) {
   [[web_delegate_mock() expect] webControllerDidSuppressDialog:webController_];
-  [webController_ setPageDialogOpenPolicy:web::DIALOG_POLICY_SUPPRESS];
+  [webController_ setShouldSuppressDialogs:YES];
   EvaluateJavaScriptAsString(@"navigator.geolocation.getCurrentPosition()");
 }
 
 // Tests that window.open is suppressed for DIALOG_POLICY_SUPPRESS.
 TEST_F(CRWWebControllerPageDialogOpenPolicyTest, SuppressWindowOpen) {
   [[web_delegate_mock() expect] webControllerDidSuppressDialog:webController_];
-  [webController_ setPageDialogOpenPolicy:web::DIALOG_POLICY_SUPPRESS];
+  [webController_ setShouldSuppressDialogs:YES];
   EvaluateJavaScriptAsString(@"window.open('')");
 }
 
diff --git a/ios/web/webui/url_data_manager_ios_backend.mm b/ios/web/webui/url_data_manager_ios_backend.mm
index 29c2e3f..ce3e279 100644
--- a/ios/web/webui/url_data_manager_ios_backend.mm
+++ b/ios/web/webui/url_data_manager_ios_backend.mm
@@ -461,9 +461,8 @@
   base::MessageLoop* target_message_loop =
       web::WebThread::UnsafeGetMessageLoopForThread(web::WebThread::UI);
   target_message_loop->PostTask(
-      FROM_HERE,
-      base::Bind(&GetMimeTypeOnUI, scoped_refptr<URLDataSourceIOSImpl>(source),
-                 path, job->weak_factory_.GetWeakPtr()));
+      FROM_HERE, base::Bind(&GetMimeTypeOnUI, base::RetainedRef(source), path,
+                            job->weak_factory_.GetWeakPtr()));
 
   target_message_loop->PostTask(
       FROM_HERE, base::Bind(&URLDataManagerIOSBackend::CallStartRequest,
diff --git a/ipc/mojo/ipc_channel_mojo.cc b/ipc/mojo/ipc_channel_mojo.cc
index a0dabad..db79c11 100644
--- a/ipc/mojo/ipc_channel_mojo.cc
+++ b/ipc/mojo/ipc_channel_mojo.cc
@@ -223,7 +223,11 @@
 ChannelMojo::ChannelMojo(mojo::ScopedMessagePipeHandle handle,
                          Mode mode,
                          Listener* listener)
-    : listener_(listener), waiting_connect_(true), weak_factory_(this) {
+    : task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      pipe_(handle.get()),
+      listener_(listener),
+      waiting_connect_(true),
+      weak_factory_(this) {
   // Create MojoBootstrap after all members are set as it touches
   // ChannelMojo from a different thread.
   bootstrap_ = MojoBootstrap::Create(std::move(handle), mode, this);
@@ -234,15 +238,27 @@
 }
 
 bool ChannelMojo::Connect() {
+  base::AutoLock lock(lock_);
   DCHECK(!message_reader_);
   bootstrap_->Connect();
   return true;
 }
 
 void ChannelMojo::Close() {
-  message_reader_.reset();
-  // We might Close() before we Connect().
-  waiting_connect_ = false;
+  scoped_ptr<internal::MessagePipeReader, ReaderDeleter> reader;
+  {
+    base::AutoLock lock(lock_);
+    if (!message_reader_)
+      return;
+    // The reader's destructor may re-enter Close, so we swap it out first to
+    // avoid deadlock when freeing it below.
+    std::swap(message_reader_, reader);
+
+    // We might Close() before we Connect().
+    waiting_connect_ = false;
+  }
+
+  reader.reset();
 }
 
 // MojoBootstrap::Delegate implementation
@@ -264,39 +280,49 @@
   mojom::ChannelAssociatedPtr sender_ptr;
   sender_ptr.Bind(std::move(sender));
   scoped_ptr<internal::MessagePipeReader, ChannelMojo::ReaderDeleter> reader(
-      new internal::MessagePipeReader(std::move(sender_ptr),
+      new internal::MessagePipeReader(pipe_, std::move(sender_ptr),
                                       std::move(receiver), peer_pid, this));
 
-  for (size_t i = 0; i < pending_messages_.size(); ++i) {
-    bool sent = reader->Send(std::move(pending_messages_[i]));
-    if (!sent) {
-      // OnChannelError() is notified by OnPipeError().
+  bool connected = true;
+  {
+    base::AutoLock lock(lock_);
+    for (size_t i = 0; i < pending_messages_.size(); ++i) {
+      if (!reader->Send(std::move(pending_messages_[i]))) {
+        LOG(ERROR) << "Failed to flush pending messages";
+        pending_messages_.clear();
+        connected = false;
+        break;
+      }
+    }
+
+    if (connected) {
+      // We set |message_reader_| here and won't get any |pending_messages_|
+      // hereafter. Although we might have some if there is an error, we don't
+      // care. They cannot be sent anyway.
+      message_reader_ = std::move(reader);
       pending_messages_.clear();
-      LOG(ERROR) << "Failed to flush pending messages";
-      return;
+      waiting_connect_ = false;
     }
   }
 
-  // We set |message_reader_| here and won't get any |pending_messages_|
-  // hereafter. Although we might have some if there is an error, we don't
-  // care. They cannot be sent anyway.
-  message_reader_ = std::move(reader);
-  pending_messages_.clear();
-  waiting_connect_ = false;
-
-  listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID()));
+  if (connected)
+    listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID()));
+  else
+    OnPipeError();
 }
 
-void ChannelMojo::OnPipeClosed(internal::MessagePipeReader* reader) {
-  Close();
+void ChannelMojo::OnPipeError() {
+  if (task_runner_->RunsTasksOnCurrentThread()) {
+    listener_->OnChannelError();
+  } else {
+    task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&ChannelMojo::OnPipeError, weak_factory_.GetWeakPtr()));
+  }
 }
 
-void ChannelMojo::OnPipeError(internal::MessagePipeReader* reader) {
-  listener_->OnChannelError();
-}
-
-
 bool ChannelMojo::Send(Message* message) {
+  base::AutoLock lock(lock_);
   if (!message_reader_) {
     pending_messages_.push_back(make_scoped_ptr(message));
     // Counts as OK before the connection is established, but it's an
@@ -304,10 +330,20 @@
     return waiting_connect_;
   }
 
-  return message_reader_->Send(make_scoped_ptr(message));
+  if (!message_reader_->Send(make_scoped_ptr(message))) {
+    OnPipeError();
+    return false;
+  }
+
+  return true;
+}
+
+bool ChannelMojo::IsSendThreadSafe() const {
+  return true;
 }
 
 base::ProcessId ChannelMojo::GetPeerPID() const {
+  base::AutoLock lock(lock_);
   if (!message_reader_)
     return base::kNullProcessId;
 
diff --git a/ipc/mojo/ipc_channel_mojo.h b/ipc/mojo/ipc_channel_mojo.h
index 8c5de24d4..5968d84e 100644
--- a/ipc/mojo/ipc_channel_mojo.h
+++ b/ipc/mojo/ipc_channel_mojo.h
@@ -10,9 +10,12 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/task_runner.h"
 #include "build/build_config.h"
 #include "ipc/ipc_channel.h"
 #include "ipc/ipc_channel_factory.h"
@@ -58,6 +61,7 @@
   bool Connect() override;
   void Close() override;
   bool Send(Message* message) override;
+  bool IsSendThreadSafe() const override;
   base::ProcessId GetPeerPID() const override;
   base::ProcessId GetSelfPID() const override;
 
@@ -83,8 +87,7 @@
 
   // MessagePipeReader::Delegate
   void OnMessageReceived(const Message& message) override;
-  void OnPipeClosed(internal::MessagePipeReader* reader) override;
-  void OnPipeError(internal::MessagePipeReader* reader) override;
+  void OnPipeError() override;
 
  private:
   ChannelMojo(mojo::ScopedMessagePipeHandle handle,
@@ -100,9 +103,15 @@
   // notifications invoked by them.
   typedef internal::MessagePipeReader::DelayedDeleter ReaderDeleter;
 
+  // A TaskRunner which runs tasks on the ChannelMojo's owning thread.
+  scoped_refptr<base::TaskRunner> task_runner_;
+
+  const mojo::MessagePipeHandle pipe_;
   scoped_ptr<MojoBootstrap> bootstrap_;
   Listener* listener_;
 
+  // Guards access to the fields below.
+  mutable base::Lock lock_;
   scoped_ptr<internal::MessagePipeReader, ReaderDeleter> message_reader_;
   std::vector<scoped_ptr<Message>> pending_messages_;
   bool waiting_connect_;
diff --git a/ipc/mojo/ipc_message_pipe_reader.cc b/ipc/mojo/ipc_message_pipe_reader.cc
index 495a3a5..b657bfdc 100644
--- a/ipc/mojo/ipc_message_pipe_reader.cc
+++ b/ipc/mojo/ipc_message_pipe_reader.cc
@@ -5,20 +5,54 @@
 #include "ipc/mojo/ipc_message_pipe_reader.h"
 
 #include <stdint.h>
+
 #include <utility>
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/thread_task_runner_handle.h"
 #include "ipc/mojo/ipc_channel_mojo.h"
+#include "mojo/public/cpp/bindings/message.h"
 
 namespace IPC {
 namespace internal {
 
+namespace {
+
+// Used by Send() to capture a serialized Channel::Receive message.
+class MessageSerializer : public mojo::MessageReceiverWithResponder {
+ public:
+  MessageSerializer() {}
+  ~MessageSerializer() override {}
+
+  mojo::Message* message() { return &message_; }
+
+ private:
+  // mojo::MessageReceiverWithResponder
+  bool Accept(mojo::Message* message) override {
+    message->MoveTo(&message_);
+    return true;
+  }
+
+  bool AcceptWithResponder(mojo::Message* message,
+                           mojo::MessageReceiver* responder) override {
+    NOTREACHED();
+    return false;
+  }
+
+  mojo::Message message_;
+
+  DISALLOW_COPY_AND_ASSIGN(MessageSerializer);
+};
+
+}  // namespace
+
 MessagePipeReader::MessagePipeReader(
+    mojo::MessagePipeHandle pipe,
     mojom::ChannelAssociatedPtr sender,
     mojo::AssociatedInterfaceRequest<mojom::Channel> receiver,
     base::ProcessId peer_pid,
@@ -26,7 +60,9 @@
     : delegate_(delegate),
       peer_pid_(peer_pid),
       sender_(std::move(sender)),
-      binding_(this, std::move(receiver)) {
+      binding_(this, std::move(receiver)),
+      sender_interface_id_(sender_.interface_id()),
+      sender_pipe_(pipe) {
   sender_.set_connection_error_handler(
       base::Bind(&MessagePipeReader::OnPipeError, base::Unretained(this),
                  MOJO_RESULT_FAILED_PRECONDITION));
@@ -45,12 +81,6 @@
   sender_.reset();
   if (binding_.is_bound())
     binding_.Close();
-  OnPipeClosed();
-}
-
-void MessagePipeReader::CloseWithError(MojoResult error) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  OnPipeError(error);
 }
 
 bool MessagePipeReader::Send(scoped_ptr<Message> message) {
@@ -61,17 +91,35 @@
   mojo::Array<mojom::SerializedHandlePtr> handles(nullptr);
   MojoResult result = MOJO_RESULT_OK;
   result = ChannelMojo::ReadFromMessageAttachmentSet(message.get(), &handles);
-  if (result != MOJO_RESULT_OK) {
-    CloseWithError(result);
+  if (result != MOJO_RESULT_OK)
     return false;
-  }
+
   mojo::Array<uint8_t> data(message->size());
   std::copy(reinterpret_cast<const uint8_t*>(message->data()),
             reinterpret_cast<const uint8_t*>(message->data()) + message->size(),
             &data[0]);
-  sender_->Receive(std::move(data), std::move(handles));
+
+  MessageSerializer serializer;
+  mojom::ChannelProxy proxy(&serializer);
+  proxy.Receive(std::move(data), std::move(handles));
+  mojo::Message* mojo_message = serializer.message();
+
+  size_t num_handles = mojo_message->handles()->size();
+  DCHECK_LE(num_handles, std::numeric_limits<uint32_t>::max());
+
+  mojo_message->set_interface_id(sender_interface_id_);
+  result = mojo::WriteMessageRaw(
+      sender_pipe_, mojo_message->data(), mojo_message->data_num_bytes(),
+      reinterpret_cast<const MojoHandle*>(mojo_message->handles()->data()),
+      static_cast<uint32_t>(num_handles), MOJO_WRITE_MESSAGE_FLAG_NONE);
+
+  // If the write was successful, the handles have been transferred and they
+  // should not be closed when the message is destroyed.
+  if (result == MOJO_RESULT_OK)
+    mojo_message->mutable_handles()->clear();
+
   DVLOG(4) << "Send " << message->type() << ": " << message->size();
-  return true;
+  return result == MOJO_RESULT_OK;
 }
 
 void MessagePipeReader::Receive(
@@ -86,29 +134,21 @@
   MojoResult write_result =
       ChannelMojo::WriteToMessageAttachmentSet(std::move(handles), &message);
   if (write_result != MOJO_RESULT_OK) {
-    CloseWithError(write_result);
+    OnPipeError(write_result);
     return;
   }
 
   TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
-                         "MessagePipeReader::OnMessageReceived",
+                         "MessagePipeReader::Receive",
                          message.flags(),
                          TRACE_EVENT_FLAG_FLOW_IN);
   delegate_->OnMessageReceived(message);
 }
 
-void MessagePipeReader::OnPipeClosed() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  if (!delegate_)
-    return;
-  delegate_->OnPipeClosed(this);
-  delegate_ = nullptr;
-}
-
 void MessagePipeReader::OnPipeError(MojoResult error) {
   DCHECK(thread_checker_.CalledOnValidThread());
   if (delegate_)
-    delegate_->OnPipeError(this);
+    delegate_->OnPipeError();
   Close();
 }
 
diff --git a/ipc/mojo/ipc_message_pipe_reader.h b/ipc/mojo/ipc_message_pipe_reader.h
index 3989c25..d2ba9de 100644
--- a/ipc/mojo/ipc_message_pipe_reader.h
+++ b/ipc/mojo/ipc_message_pipe_reader.h
@@ -19,6 +19,7 @@
 #include "ipc/mojo/ipc.mojom.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "mojo/public/cpp/system/core.h"
+#include "mojo/public/cpp/system/message_pipe.h"
 
 namespace IPC {
 namespace internal {
@@ -46,8 +47,7 @@
   class Delegate {
    public:
     virtual void OnMessageReceived(const Message& message) = 0;
-    virtual void OnPipeClosed(MessagePipeReader* reader) = 0;
-    virtual void OnPipeError(MessagePipeReader* reader) = 0;
+    virtual void OnPipeError() = 0;
   };
 
   // Delay the object deletion using the current message loop.
@@ -65,11 +65,18 @@
     void operator()(MessagePipeReader* ptr) const;
   };
 
-  // Both parameters must be non-null.
-  // Build a reader that reads messages from |receive_handle| and lets
+  // Builds a reader that reads messages from |receive_handle| and lets
   // |delegate| know.
+  //
+  // |pipe| is the message pipe handle corresponding to the channel's master
+  // interface. This is the message pipe underlying both |sender| and
+  // |receiver|.
+  //
+  // Both |sender| and |receiver| must be non-null.
+  //
   // Note that MessagePipeReader doesn't delete |delegate|.
-  MessagePipeReader(mojom::ChannelAssociatedPtr sender,
+  MessagePipeReader(mojo::MessagePipeHandle pipe,
+                    mojom::ChannelAssociatedPtr sender,
                     mojo::AssociatedInterfaceRequest<mojom::Channel> receiver,
                     base::ProcessId peer_pid,
                     Delegate* delegate);
@@ -77,12 +84,12 @@
 
   // Close and destroy the MessagePipe.
   void Close();
-  // Close the mesage pipe with notifying the client with the error.
-  void CloseWithError(MojoResult error);
 
   // Return true if the MessagePipe is alive.
   bool IsValid() { return sender_; }
 
+  // Sends an IPC::Message to the other end of the pipe. Safe to call from any
+  // thread.
   bool Send(scoped_ptr<Message> message);
 
   base::ProcessId GetPeerPid() const { return peer_pid_; }
@@ -92,6 +99,7 @@
   void OnPipeError(MojoResult error);
 
  private:
+  // mojom::Channel:
   void Receive(mojo::Array<uint8_t> data,
                mojo::Array<mojom::SerializedHandlePtr> handles) override;
 
@@ -100,6 +108,12 @@
   base::ProcessId peer_pid_;
   mojom::ChannelAssociatedPtr sender_;
   mojo::AssociatedBinding<mojom::Channel> binding_;
+
+  // Raw message pipe handle and interface ID we use to send legacy IPC messages
+  // over the associated pipe.
+  const uint32_t sender_interface_id_;
+  const mojo::MessagePipeHandle sender_pipe_;
+
   base::ThreadChecker thread_checker_;
 
   DISALLOW_COPY_AND_ASSIGN(MessagePipeReader);
diff --git a/mash/BUILD.gn b/mash/BUILD.gn
index f2abd8fb..8d82d0a 100644
--- a/mash/BUILD.gn
+++ b/mash/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//mojo/public/mojo_application_manifest.gni")
 import("//testing/test.gni")
 
 # Target that builders build.
@@ -9,7 +10,7 @@
   testonly = true
 
   deps = [
-    ":tests",
+    ":mash_unittests",
     "//components/leveldb",
     "//mash/example",
     "//mash/init",
@@ -20,22 +21,23 @@
   ]
 }
 
-group("tests") {
-  testonly = true
-
-  deps = [
-    ":mash_unittests",
-    "//mash/wm:tests",
-  ]
-}
-
 test("mash_unittests") {
   deps = [
     "//base",
-    "//base/test:run_all_unittests",
     "//base/test:test_config",
     "//base/test:test_support",
     "//mash/wm:unittests",
     "//mojo/platform_handle:platform_handle_impl",
+    "//mojo/shell/background:main",
+    "//mojo/shell/public/cpp/test:run_all_shelltests",
   ]
+  data_deps = [
+    ":unittests_manifest",
+  ]
+}
+
+mojo_application_manifest("unittests_manifest") {
+  type = "exe"
+  application_name = "mash_unittests"
+  source = "unittests_manifest.json"
 }
diff --git a/mash/browser_driver/browser_driver_application_delegate.cc b/mash/browser_driver/browser_driver_application_delegate.cc
index d30225e..cc6bbdc 100644
--- a/mash/browser_driver/browser_driver_application_delegate.cc
+++ b/mash/browser_driver/browser_driver_application_delegate.cc
@@ -67,10 +67,10 @@
   return true;
 }
 
-void BrowserDriverApplicationDelegate::ShellConnectionLost() {
+bool BrowserDriverApplicationDelegate::ShellConnectionLost() {
   // Prevent the code in AddAccelerators() from keeping this app alive.
   binding_.set_connection_error_handler(base::Bind(&DoNothing));
-  base::MessageLoop::current()->QuitWhenIdle();
+  return true;
 }
 
 void BrowserDriverApplicationDelegate::OnAccelerator(
diff --git a/mash/browser_driver/browser_driver_application_delegate.h b/mash/browser_driver/browser_driver_application_delegate.h
index f517a763..0c05779 100644
--- a/mash/browser_driver/browser_driver_application_delegate.h
+++ b/mash/browser_driver/browser_driver_application_delegate.h
@@ -31,7 +31,7 @@
   void Initialize(mojo::Connector* connector, const mojo::Identity& identity,
                   uint32_t id) override;
   bool AcceptConnection(mojo::Connection* connection) override;
-  void ShellConnectionLost() override;
+  bool ShellConnectionLost() override;
 
   // mus::mojom::AcceleratorHandler:
   void OnAccelerator(uint32_t id, mus::mojom::EventPtr event) override;
diff --git a/mash/example/window_type_launcher/window_type_launcher.cc b/mash/example/window_type_launcher/window_type_launcher.cc
index 2628f034..0547e84 100644
--- a/mash/example/window_type_launcher/window_type_launcher.cc
+++ b/mash/example/window_type_launcher/window_type_launcher.cc
@@ -384,6 +384,7 @@
   widget->Show();
 }
 
-void WindowTypeLauncher::ShellConnectionLost() {
+bool WindowTypeLauncher::ShellConnectionLost() {
   base::MessageLoop::current()->QuitWhenIdle();
+  return false;
 }
diff --git a/mash/example/window_type_launcher/window_type_launcher.h b/mash/example/window_type_launcher/window_type_launcher.h
index 4d5a2669..fd05874 100644
--- a/mash/example/window_type_launcher/window_type_launcher.h
+++ b/mash/example/window_type_launcher/window_type_launcher.h
@@ -22,7 +22,7 @@
   // mojo::ShellClient:
   void Initialize(mojo::Connector* connector, const mojo::Identity& identity,
                   uint32_t id) override;
-  void ShellConnectionLost() override;
+  bool ShellConnectionLost() override;
 
   scoped_ptr<views::AuraInit> aura_init_;
 
diff --git a/mash/quick_launch/quick_launch_application.cc b/mash/quick_launch/quick_launch_application.cc
index 0f505a89..2b2764b8 100644
--- a/mash/quick_launch/quick_launch_application.cc
+++ b/mash/quick_launch/quick_launch_application.cc
@@ -106,9 +106,5 @@
   return true;
 }
 
-void QuickLaunchApplication::ShellConnectionLost() {
-  base::MessageLoop::current()->QuitWhenIdle();
-}
-
 }  // namespace quick_launch
 }  // namespace mash
diff --git a/mash/quick_launch/quick_launch_application.h b/mash/quick_launch/quick_launch_application.h
index 93d72b29..130a1dd 100644
--- a/mash/quick_launch/quick_launch_application.h
+++ b/mash/quick_launch/quick_launch_application.h
@@ -28,7 +28,6 @@
                   const mojo::Identity& identity,
                   uint32_t id) override;
   bool AcceptConnection(mojo::Connection* connection) override;
-  void ShellConnectionLost() override;
 
   mojo::TracingImpl tracing_;
   scoped_ptr<views::AuraInit> aura_init_;
diff --git a/mash/unittests_manifest.json b/mash/unittests_manifest.json
new file mode 100644
index 0000000..0f3e63e0
--- /dev/null
+++ b/mash/unittests_manifest.json
@@ -0,0 +1,5 @@
+{
+  "name": "exe:mash_unittests",
+  "display_name": "Mash Unittests",
+  "capabilities": { "*": ["*"] }
+}
diff --git a/mash/wm/BUILD.gn b/mash/wm/BUILD.gn
index 6548409c..283de71 100644
--- a/mash/wm/BUILD.gn
+++ b/mash/wm/BUILD.gn
@@ -8,13 +8,6 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 import("//tools/grit/repack.gni")
 
-group("tests") {
-  testonly = true
-  deps = [
-    ":apptests",
-  ]
-}
-
 source_set("lib") {
   sources = [
     "accelerator_registrar_impl.cc",
@@ -140,50 +133,14 @@
   ]
 }
 
-mojo_native_application("apptests") {
-  output_name = "mash_wm_apptests"
-  testonly = true
-
-  sources = [
-    "accelerator_registrar_apptest.cc",
-    "window_manager_apptest.cc",
-  ]
-
-  deps = [
-    "//base",
-    "//base/test:test_config",
-    "//components/mus/public/cpp",
-    "//components/mus/public/interfaces",
-    "//mojo/common:common_base",
-    "//mojo/converters/geometry",
-    "//mojo/converters/input_events",
-    "//mojo/shell/public/cpp:sources",
-    "//mojo/shell/public/cpp:test_support",
-    "//ui/mojo/geometry:interfaces",
-    "//ui/mojo/geometry:util",
-  ]
-
-  data_deps = [
-    ":apptest_manifest",
-    ":wm",
-  ]
-
-  if (use_x11) {
-    deps += [ "//tools/xdisplaycheck" ]
-  }
-}
-
-mojo_application_manifest("apptest_manifest") {
-  application_name = "mash_wm_apptests"
-  source = "apptest_manifest.json"
-}
-
 source_set("unittests") {
   testonly = true
 
   sources = [
+    "accelerator_registrar_unittest.cc",
     "frame/move_loop_unittest.cc",
     "layout_manager_unittest.cc",
+    "window_manager_unittest.cc",
   ]
 
   deps = [
@@ -192,12 +149,14 @@
     "//base/test:test_config",
     "//components/mus/public/cpp",
     "//components/mus/public/cpp/tests:unittest_support",
+    "//components/mus/public/interfaces",
     "//mojo/converters/geometry",
     "//mojo/converters/input_events",
     "//mojo/edk/system",
     "//mojo/gles2",
     "//mojo/platform_handle",
     "//mojo/public/cpp/system",
+    "//mojo/shell/public/cpp:shell_test_support",
     "//testing/gtest",
     "//ui/base",
     "//ui/events",
diff --git a/mash/wm/accelerator_registrar_apptest.cc b/mash/wm/accelerator_registrar_unittest.cc
similarity index 95%
rename from mash/wm/accelerator_registrar_apptest.cc
rename to mash/wm/accelerator_registrar_unittest.cc
index a16d210..fa755bc1 100644
--- a/mash/wm/accelerator_registrar_apptest.cc
+++ b/mash/wm/accelerator_registrar_unittest.cc
@@ -11,7 +11,7 @@
 #include "components/mus/public/cpp/window.h"
 #include "components/mus/public/interfaces/accelerator_registrar.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/shell/public/cpp/application_test_base.h"
+#include "mojo/shell/public/cpp/shell_test.h"
 
 using mus::mojom::AcceleratorHandler;
 using mus::mojom::AcceleratorHandlerPtr;
@@ -65,9 +65,9 @@
   DISALLOW_COPY_AND_ASSIGN(TestAcceleratorHandler);
 };
 
-class AcceleratorRegistrarTest : public mojo::test::ApplicationTestBase {
+class AcceleratorRegistrarTest : public mojo::test::ShellTest {
  public:
-  AcceleratorRegistrarTest() {}
+  AcceleratorRegistrarTest() : mojo::test::ShellTest("exe:mash_unittests") {}
   ~AcceleratorRegistrarTest() override {}
 
  protected:
diff --git a/mash/wm/apptest_manifest.json b/mash/wm/apptest_manifest.json
deleted file mode 100644
index 02cd859f..0000000
--- a/mash/wm/apptest_manifest.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "name": "mojo:mash_wm_apptests",
-  "display_name": "Desktop Window Manager Apptests",
-  "capabilities": { "*": ["*"] }
-}
diff --git a/mash/wm/window_manager_application.cc b/mash/wm/window_manager_application.cc
index 606de459..57fb884c 100644
--- a/mash/wm/window_manager_application.cc
+++ b/mash/wm/window_manager_application.cc
@@ -127,10 +127,6 @@
   return true;
 }
 
-void WindowManagerApplication::ShellConnectionLost() {
-  _exit(1);
-}
-
 void WindowManagerApplication::Create(
     mojo::Connection* connection,
     mojo::InterfaceRequest<mash::wm::mojom::UserWindowController> request) {
diff --git a/mash/wm/window_manager_application.h b/mash/wm/window_manager_application.h
index 5ca27256..b6cd495 100644
--- a/mash/wm/window_manager_application.h
+++ b/mash/wm/window_manager_application.h
@@ -90,7 +90,6 @@
   void Initialize(mojo::Connector* connector, const mojo::Identity& identity,
                   uint32_t id) override;
   bool AcceptConnection(mojo::Connection* connection) override;
-  void ShellConnectionLost() override;
 
   // InterfaceFactory<mash::wm::mojom::UserWindowController>:
   void Create(mojo::Connection* connection,
diff --git a/mash/wm/window_manager_apptest.cc b/mash/wm/window_manager_unittest.cc
similarity index 86%
rename from mash/wm/window_manager_apptest.cc
rename to mash/wm/window_manager_unittest.cc
index 605b825..5b9e16d 100644
--- a/mash/wm/window_manager_apptest.cc
+++ b/mash/wm/window_manager_unittest.cc
@@ -11,7 +11,7 @@
 #include "components/mus/public/cpp/window_tree_connection.h"
 #include "components/mus/public/cpp/window_tree_delegate.h"
 #include "components/mus/public/interfaces/window_tree.mojom.h"
-#include "mojo/shell/public/cpp/application_test_base.h"
+#include "mojo/shell/public/cpp/shell_test.h"
 
 namespace mash {
 namespace wm {
@@ -29,13 +29,20 @@
   DISALLOW_COPY_AND_ASSIGN(WindowTreeDelegateImpl);
 };
 
-using WindowManagerAppTest = mojo::test::ApplicationTestBase;
+class WindowManagerTest : public mojo::test::ShellTest {
+ public:
+  WindowManagerTest() : mojo::test::ShellTest("exe:mash_unittests") {}
+  ~WindowManagerTest() override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WindowManagerTest);
+};
 
 void OnEmbed(bool success) {
   ASSERT_TRUE(success);
 }
 
-TEST_F(WindowManagerAppTest, OpenWindow) {
+TEST_F(WindowManagerTest, OpenWindow) {
   WindowTreeDelegateImpl window_tree_delegate;
 
   // Bring up the the desktop_wm.
diff --git a/media/base/android/BUILD.gn b/media/base/android/BUILD.gn
index b9db10a8..be0e3d8 100644
--- a/media/base/android/BUILD.gn
+++ b/media/base/android/BUILD.gn
@@ -37,6 +37,8 @@
     "media_decoder_job.h",
     "media_drm_bridge.cc",
     "media_drm_bridge.h",
+    "media_drm_bridge_cdm_context.cc",
+    "media_drm_bridge_cdm_context.h",
     "media_drm_bridge_delegate.cc",
     "media_drm_bridge_delegate.h",
     "media_jni_registrar.cc",
diff --git a/media/base/android/media_drm_bridge.cc b/media/base/android/media_drm_bridge.cc
index a5975f3..2b1a83ff 100644
--- a/media/base/android/media_drm_bridge.cc
+++ b/media/base/android/media_drm_bridge.cc
@@ -465,6 +465,12 @@
   promise->reject(NOT_SUPPORTED_ERROR, 0, "RemoveSession() is not supported.");
 }
 
+CdmContext* MediaDrmBridge::GetCdmContext() {
+  DVLOG(2) << __FUNCTION__;
+
+  return &media_drm_bridge_cdm_context_;
+}
+
 void MediaDrmBridge::DeleteOnCorrectThread() const {
   DVLOG(1) << __FUNCTION__;
 
@@ -761,6 +767,7 @@
       session_keys_change_cb_(session_keys_change_cb),
       session_expiration_update_cb_(session_expiration_update_cb),
       task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      media_drm_bridge_cdm_context_(this),
       weak_factory_(this) {
   DVLOG(1) << __FUNCTION__;
 
diff --git a/media/base/android/media_drm_bridge.h b/media/base/android/media_drm_bridge.h
index d5408c1c..0a74fcd 100644
--- a/media/base/android/media_drm_bridge.h
+++ b/media/base/android/media_drm_bridge.h
@@ -15,6 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "media/base/android/media_drm_bridge_cdm_context.h"
 #include "media/base/android/provision_fetcher.h"
 #include "media/base/cdm_promise_adapter.h"
 #include "media/base/media_export.h"
@@ -114,6 +115,7 @@
                     scoped_ptr<media::SimpleCdmPromise> promise) override;
   void RemoveSession(const std::string& session_id,
                      scoped_ptr<media::SimpleCdmPromise> promise) override;
+  CdmContext* GetCdmContext() override;
   void DeleteOnCorrectThread() const override;
 
   // PlayerTracker implementation. Can be called on any thread.
@@ -326,6 +328,8 @@
   // Default task runner.
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 
+  MediaDrmBridgeCdmContext media_drm_bridge_cdm_context_;
+
   // NOTE: Weak pointers must be invalidated before all other member variables.
   base::WeakPtrFactory<MediaDrmBridge> weak_factory_;
 
diff --git a/media/base/android/media_drm_bridge_cdm_context.cc b/media/base/android/media_drm_bridge_cdm_context.cc
new file mode 100644
index 0000000..f9c9fa4
--- /dev/null
+++ b/media/base/android/media_drm_bridge_cdm_context.cc
@@ -0,0 +1,42 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/android/media_drm_bridge_cdm_context.h"
+
+#include "media/base/android/media_drm_bridge.h"
+
+namespace media {
+
+MediaDrmBridgeCdmContext::MediaDrmBridgeCdmContext(
+    MediaDrmBridge* media_drm_bridge)
+    : media_drm_bridge_(media_drm_bridge) {
+  DCHECK(media_drm_bridge_);
+}
+
+MediaDrmBridgeCdmContext::~MediaDrmBridgeCdmContext() {}
+
+Decryptor* MediaDrmBridgeCdmContext::GetDecryptor() {
+  return nullptr;
+}
+
+int MediaDrmBridgeCdmContext::GetCdmId() const {
+  return kInvalidCdmId;
+}
+
+int MediaDrmBridgeCdmContext::RegisterPlayer(
+    const base::Closure& new_key_cb,
+    const base::Closure& cdm_unset_cb) {
+  return media_drm_bridge_->RegisterPlayer(new_key_cb, cdm_unset_cb);
+}
+
+void MediaDrmBridgeCdmContext::UnregisterPlayer(int registration_id) {
+  media_drm_bridge_->UnregisterPlayer(registration_id);
+}
+
+void MediaDrmBridgeCdmContext::SetMediaCryptoReadyCB(
+    const MediaCryptoReadyCB& media_crypto_ready_cb) {
+  media_drm_bridge_->SetMediaCryptoReadyCB(media_crypto_ready_cb);
+}
+
+}  // namespace media
diff --git a/media/base/android/media_drm_bridge_cdm_context.h b/media/base/android/media_drm_bridge_cdm_context.h
new file mode 100644
index 0000000..3251ea8
--- /dev/null
+++ b/media/base/android/media_drm_bridge_cdm_context.h
@@ -0,0 +1,73 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_ANDROID_MEDIA_DRM_BRIDGE_CDM_CONTEXT_H_
+#define MEDIA_BASE_ANDROID_MEDIA_DRM_BRIDGE_CDM_CONTEXT_H_
+
+#include <jni.h>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/callback.h"
+#include "base/macros.h"
+#include "media/base/cdm_context.h"
+#include "media/base/media_export.h"
+#include "media/base/player_tracker.h"
+
+namespace media {
+
+class MediaDrmBridge;
+
+// The CdmContext implementation for MediaDrmBridge. MediaDrmBridge supports
+// neither Decryptor nor CDM ID, but uses MediaCrypto to connect to MediaCodec.
+// MediaCodec-based decoders should cast the given CdmContext to this class to
+// access APIs defined in this class.
+//
+// Methods can be called on any thread. The registered callbacks will be fired
+// on the thread |media_drm_bridge_| is running on. The caller should make sure
+// that the callbacks are posted to the correct thread.
+//
+// TODO(xhwang): Remove PlayerTracker interface.
+class MEDIA_EXPORT MediaDrmBridgeCdmContext : public CdmContext,
+                                              public PlayerTracker {
+ public:
+  using JavaObjectPtr = scoped_ptr<base::android::ScopedJavaGlobalRef<jobject>>;
+
+  // Notification called when MediaCrypto object is ready.
+  // Parameters:
+  // |media_crypto| - reference to MediaCrypto object
+  // |needs_protected_surface| - true if protected surface is required
+  using MediaCryptoReadyCB = base::Callback<void(JavaObjectPtr media_crypto,
+                                                 bool needs_protected_surface)>;
+
+  // The |media_drm_bridge| owns |this| and is guaranteed to outlive |this|.
+  explicit MediaDrmBridgeCdmContext(MediaDrmBridge* media_drm_bridge);
+
+  ~MediaDrmBridgeCdmContext() final;
+
+  // CdmContext implementation.
+  Decryptor* GetDecryptor() final;
+  int GetCdmId() const final;
+
+  // PlayerTracker implementation.
+  // Methods can be called on any thread. The registered callbacks will be fired
+  // on |task_runner_|. The caller should make sure that the callbacks are
+  // posted to the correct thread.
+  //
+  // Note: RegisterPlayer() must be called before SetMediaCryptoReadyCB() to
+  // avoid missing any new key notifications.
+  int RegisterPlayer(const base::Closure& new_key_cb,
+                     const base::Closure& cdm_unset_cb) final;
+  void UnregisterPlayer(int registration_id) final;
+
+  void SetMediaCryptoReadyCB(const MediaCryptoReadyCB& media_crypto_ready_cb);
+
+ private:
+  MediaDrmBridge* const media_drm_bridge_;
+
+  DISALLOW_COPY_AND_ASSIGN(MediaDrmBridgeCdmContext);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_ANDROID_MEDIA_DRM_BRIDGE_CDM_CONTEXT_H_
diff --git a/media/base/cdm_context.h b/media/base/cdm_context.h
index 82e088d..d41281e 100644
--- a/media/base/cdm_context.h
+++ b/media/base/cdm_context.h
@@ -13,9 +13,9 @@
 
 class Decryptor;
 
-// An interface representing the context that a media pipeline needs from a
+// An interface representing the context that a media player needs from a
 // content decryption module (CDM) to decrypt (and decode) encrypted buffers.
-// Only used for implementing SetCdm().
+// This is used to pass the CDM to the media player (e.g. SetCdm()).
 class MEDIA_EXPORT CdmContext {
  public:
   // Indicates an invalid CDM ID. See GetCdmId() for details.
@@ -24,15 +24,14 @@
   virtual ~CdmContext();
 
   // Gets the Decryptor object associated with the CDM. Returns nullptr if the
-  // CDM does not support a Decryptor. Must not return nullptr if GetCdmId()
-  // returns kInvalidCdmId. The returned object is only guaranteed to be valid
-  // during the CDM's lifetime.
+  // CDM does not support a Decryptor (i.e. platform-based CDMs where decryption
+  // occurs implicitly along with decoding). The returned object is only
+  // guaranteed to be valid during the CDM's lifetime.
   virtual Decryptor* GetDecryptor() = 0;
 
-  // Returns an ID that identifies a CDM, or kInvalidCdmId. The interpretation
-  // is implementation-specific; current implementations use the ID to locate a
-  // remote CDM in a different process. The return value will not be
-  // kInvalidCdmId if GetDecryptor() returns nullptr.
+  // Returns an ID that can be used to find a remote CDM, in which case this CDM
+  // serves as a proxy to the remote one. Returns kInvalidCdmId when remote CDM
+  // is not supported (e.g. this CDM is a local CDM).
   virtual int GetCdmId() const = 0;
 
  protected:
diff --git a/media/base/media_keys.h b/media/base/media_keys.h
index cb21b56..13c210c 100644
--- a/media/base/media_keys.h
+++ b/media/base/media_keys.h
@@ -144,11 +144,11 @@
   virtual void RemoveSession(const std::string& session_id,
                              scoped_ptr<SimpleCdmPromise> promise) = 0;
 
-  // Returns the CdmContext associated with |this| if Decryptor or CDM ID is
-  // supported. The returned CdmContext is owned by |this|. Caller needs to make
-  // sure it is not used after |this| is destructed.
-  // Returns null if no Decryptor nor CDM ID is supported. Instead the media
-  // player may use the CDM via some platform specific method.
+  // Returns the CdmContext associated with |this|. The returned CdmContext is
+  // owned by |this| and the caller needs to make sure it is not used after
+  // |this| is destructed.
+  // Returns null if CdmContext is not supported. Instead the media player may
+  // use the CDM via some platform specific method.
   // By default this method returns null.
   // TODO(xhwang): Convert all SetCdm() implementations to use CdmContext so
   // that this function should never return nullptr.
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index bbab083..1d1bff56 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -883,6 +883,8 @@
 void WebMediaPlayerImpl::OnPipelineSuspended() {
 #if defined(OS_ANDROID)
   if (isRemote()) {
+    if (delegate_)
+      delegate_->PlayerGone(delegate_id_);
     scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
     if (frame) {
       compositor_->PaintFrameUsingOldRenderingPath(frame);
diff --git a/media/filters/pipeline_controller.cc b/media/filters/pipeline_controller.cc
index f42a98f0..1d5e951 100644
--- a/media/filters/pipeline_controller.cc
+++ b/media/filters/pipeline_controller.cc
@@ -192,8 +192,8 @@
 
     // Tell |demuxer_| to expect our resume.
     DCHECK(!waiting_for_seek_);
-    demuxer_->StartWaitingForSeek(seek_time_);
     waiting_for_seek_ = true;
+    demuxer_->StartWaitingForSeek(seek_time_);
 
     pending_resume_ = false;
     state_ = State::RESUMING;
@@ -204,7 +204,7 @@
     return;
   }
 
-  // When we have pending operations, abort the current seek.
+  // If we have pending operations, and a seek is ongoing, abort it.
   if ((pending_seek_ || pending_suspend_) && waiting_for_seek_) {
     // If there is no pending seek, return the current seek to pending status.
     if (!pending_seek_) {
diff --git a/media/media.gyp b/media/media.gyp
index 17578a2..4d826dc 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -1838,6 +1838,8 @@
             'base/android/media_decoder_job.h',
             'base/android/media_drm_bridge.cc',
             'base/android/media_drm_bridge.h',
+            'base/android/media_drm_bridge_cdm_context.cc',
+            'base/android/media_drm_bridge_cdm_context.h',
             'base/android/media_drm_bridge_delegate.cc',
             'base/android/media_drm_bridge_delegate.h',
             'base/android/media_jni_registrar.cc',
diff --git a/media/mojo/services/mojo_audio_decoder.cc b/media/mojo/services/mojo_audio_decoder.cc
index 0e9ea511..9a070bb 100644
--- a/media/mojo/services/mojo_audio_decoder.cc
+++ b/media/mojo/services/mojo_audio_decoder.cc
@@ -21,7 +21,7 @@
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     interfaces::AudioDecoderPtr remote_decoder)
     : task_runner_(task_runner),
-      remote_decoder_(std::move(remote_decoder)),
+      remote_decoder_info_(remote_decoder.PassInterface()),
       binding_(this),
       has_connection_error_(false),
       needs_bitstream_conversion_(false) {
@@ -43,6 +43,9 @@
   DVLOG(1) << __FUNCTION__;
   DCHECK(task_runner_->BelongsToCurrentThread());
 
+  // Bind |remote_decoder_| to the |task_runner_|.
+  remote_decoder_.Bind(std::move(remote_decoder_info_));
+
   // Fail immediately if the stream is encrypted but |cdm_context| is invalid.
   int cdm_id = (config.is_encrypted() && cdm_context)
                    ? cdm_context->GetCdmId()
diff --git a/media/mojo/services/mojo_audio_decoder.h b/media/mojo/services/mojo_audio_decoder.h
index 3f0d58fa..ae6097d 100644
--- a/media/mojo/services/mojo_audio_decoder.h
+++ b/media/mojo/services/mojo_audio_decoder.h
@@ -63,6 +63,12 @@
 
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 
+  // This class is constructed on one thread and used exclusively on another
+  // thread. This member is used to safely pass the AudioDecoderPtr from one
+  // thread to another. It is set in the constructor and is consumed in
+  // Initialize().
+  interfaces::AudioDecoderPtrInfo remote_decoder_info_;
+
   interfaces::AudioDecoderPtr remote_decoder_;
 
   // DataPipe for serializing the data section of DecoderBuffer.
diff --git a/media/mojo/services/mojo_renderer_impl.cc b/media/mojo/services/mojo_renderer_impl.cc
index ee4c908..e5a9433f 100644
--- a/media/mojo/services/mojo_renderer_impl.cc
+++ b/media/mojo/services/mojo_renderer_impl.cc
@@ -19,7 +19,7 @@
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
     interfaces::RendererPtr remote_renderer)
     : task_runner_(task_runner),
-      remote_renderer_(std::move(remote_renderer)),
+      remote_renderer_info_(remote_renderer.PassInterface()),
       binding_(this) {
   DVLOG(1) << __FUNCTION__;
 }
@@ -43,6 +43,9 @@
   DCHECK(task_runner_->BelongsToCurrentThread());
   DCHECK(demuxer_stream_provider);
 
+  // Bind |remote_renderer_| to the |task_runner_|.
+  remote_renderer_.Bind(std::move(remote_renderer_info_));
+
   // If connection error has happened, fail immediately.
   if (remote_renderer_.encountered_error()) {
     task_runner_->PostTask(
diff --git a/media/mojo/services/mojo_renderer_impl.h b/media/mojo/services/mojo_renderer_impl.h
index 85c47aa..9a7bb0f9 100644
--- a/media/mojo/services/mojo_renderer_impl.h
+++ b/media/mojo/services/mojo_renderer_impl.h
@@ -30,13 +30,6 @@
 // |task_runner|*. That means all Renderer and RendererClient methods will be
 // called/dispached on the |task_runner|. The only exception is GetMediaTime(),
 // which can be called on any thread.
-//
-// * Threading details:
-// mojo::GetProxy() doesn't bind an InterfacePtr to a thread. Then when
-// InterfacePtr::operator->() or InterfacePtr::get() is called for the first
-// time, e.g. to call remote_renderer->Initialize(), the InterfacePtr is bound
-// the thread where the call is made.
-
 class MojoRendererImpl : public Renderer, public interfaces::RendererClient {
  public:
   MojoRendererImpl(
@@ -84,7 +77,12 @@
   // lifetime of |this|.
   DemuxerStreamProvider* demuxer_stream_provider_;
 
-  // Remote Renderer, bound to |task_runner_|.
+  // This class is constructed on one thread and used exclusively on another
+  // thread. This member is used to safely pass the RendererPtr from one thread
+  // to another. It is set in the constructor and is consumed in Initialize().
+  interfaces::RendererPtrInfo remote_renderer_info_;
+
+  // Remote Renderer, bound to |task_runner_| during Initialize().
   interfaces::RendererPtr remote_renderer_;
 
   // Binding for RendererClient, bound to the |task_runner_|.
diff --git a/mojo/mojo_shell.gyp b/mojo/mojo_shell.gyp
index 9f4c80b..26144ab 100644
--- a/mojo/mojo_shell.gyp
+++ b/mojo/mojo_shell.gyp
@@ -7,8 +7,6 @@
     'target_name': 'mojo_shell_lib',
     'type': 'static_library',
     'sources': [
-      'services/catalog/builder.cc',
-      'services/catalog/builder.h',
       'services/catalog/catalog.cc',
       'services/catalog/catalog.h',
       'services/catalog/entry.cc',
diff --git a/mojo/public/cpp/bindings/associated_interface_ptr.h b/mojo/public/cpp/bindings/associated_interface_ptr.h
index d3a848a..48caad6 100644
--- a/mojo/public/cpp/bindings/associated_interface_ptr.h
+++ b/mojo/public/cpp/bindings/associated_interface_ptr.h
@@ -79,6 +79,9 @@
   // Returns the version number of the interface that the remote side supports.
   uint32_t version() const { return internal_state_.version(); }
 
+  // Returns the internal interface ID of this associated interface.
+  uint32_t interface_id() const { return internal_state_.interface_id(); }
+
   // Queries the max version that the remote side supports. On completion, the
   // result will be returned as the input of |callback|. The version number of
   // this object will also be updated.
diff --git a/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h b/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h
index f792884..1b9e35c5 100644
--- a/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h
+++ b/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h
@@ -19,6 +19,7 @@
 #include "mojo/public/cpp/bindings/lib/interface_id.h"
 #include "mojo/public/cpp/bindings/lib/multiplex_router.h"
 #include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h"
+#include "mojo/public/cpp/system/message_pipe.h"
 
 namespace mojo {
 namespace internal {
@@ -40,6 +41,11 @@
 
   uint32_t version() const { return version_; }
 
+  uint32_t interface_id() const {
+    DCHECK(is_bound());
+    return endpoint_client_->interface_id();
+  }
+
   void QueryVersion(const Callback<void(uint32_t)>& callback) {
     // It is safe to capture |this| because the callback won't be run after this
     // object goes away.
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
index 58bc8856..8094ad0 100644
--- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
+++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
@@ -149,6 +149,11 @@
   return associated_group_.get();
 }
 
+uint32_t InterfaceEndpointClient::interface_id() const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  return handle_.id();
+}
+
 ScopedInterfaceEndpointHandle InterfaceEndpointClient::PassHandle() {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!has_pending_responders());
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.h b/mojo/public/cpp/bindings/lib/interface_endpoint_client.h
index 12ecbcc8..548ca38 100644
--- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.h
+++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.h
@@ -60,6 +60,7 @@
 
   MultiplexRouter* router() const { return handle_.router(); }
   AssociatedGroup* associated_group();
+  uint32_t interface_id() const;
 
   // After this call the object is in an invalid state and shouldn't be reused.
   ScopedInterfaceEndpointHandle PassHandle();
diff --git a/mojo/services/catalog/BUILD.gn b/mojo/services/catalog/BUILD.gn
index d81fde3..efeee6b 100644
--- a/mojo/services/catalog/BUILD.gn
+++ b/mojo/services/catalog/BUILD.gn
@@ -15,8 +15,6 @@
 
 source_set("lib") {
   sources = [
-    "builder.cc",
-    "builder.h",
     "catalog.cc",
     "catalog.h",
     "entry.cc",
@@ -48,7 +46,7 @@
 source_set("unittests") {
   testonly = true
   sources = [
-    "builder_unittest.cc",
+    "entry_unittest.cc",
   ]
   deps = [
     ":lib",
diff --git a/mojo/services/catalog/builder.cc b/mojo/services/catalog/builder.cc
deleted file mode 100644
index 9d7d5b7..0000000
--- a/mojo/services/catalog/builder.cc
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/services/catalog/builder.h"
-
-#include "base/values.h"
-#include "mojo/services/catalog/store.h"
-#include "mojo/shell/public/cpp/capabilities.h"
-#include "mojo/shell/public/cpp/names.h"
-
-// TODO(beng): this code should do better error handling instead of CHECKing so
-// much.
-
-namespace catalog {
-
-mojo::CapabilitySpec BuildCapabilitiesV0(
-    const base::DictionaryValue& value) {
-  mojo::CapabilitySpec capabilities;
-  base::DictionaryValue::Iterator it(value);
-  for (; !it.IsAtEnd(); it.Advance()) {
-    const base::ListValue* values = nullptr;
-    CHECK(it.value().GetAsList(&values));
-    mojo::CapabilityRequest spec;
-    for (auto i = values->begin(); i != values->end(); ++i) {
-      mojo::Interface interface_name;
-      const base::Value* v = *i;
-      CHECK(v->GetAsString(&interface_name));
-      spec.interfaces.insert(interface_name);
-    }
-    capabilities.required[it.key()] = spec;
-  }
-  return capabilities;
-}
-
-void ReadStringSet(const base::ListValue& list_value,
-                   std::set<std::string>* string_set) {
-  DCHECK(string_set);
-  for (auto i = list_value.begin(); i != list_value.end(); ++i) {
-    std::string value;
-    const base::Value* value_value = *i;
-    CHECK(value_value->GetAsString(&value));
-    string_set->insert(value);
-  }
-}
-
-void ReadStringSetFromValue(const base::Value& value,
-                            std::set<std::string>* string_set) {
-  const base::ListValue* list_value = nullptr;
-  CHECK(value.GetAsList(&list_value));
-  ReadStringSet(*list_value, string_set);
-}
-
-void ReadStringSetFromDictionary(const base::DictionaryValue& dictionary,
-                                 const std::string& key,
-                                 std::set<std::string>* string_set) {
-  const base::ListValue* list_value = nullptr;
-  if (dictionary.HasKey(key))
-    CHECK(dictionary.GetList(key, &list_value));
-  if (list_value)
-    ReadStringSet(*list_value, string_set);
-}
-
-mojo::CapabilitySpec BuildCapabilitiesV1(
-    const base::DictionaryValue& value) {
-  mojo::CapabilitySpec capabilities;
-
-  const base::DictionaryValue* provided_value = nullptr;
-  if (value.HasKey(Store::kCapabilities_ProvidedKey)) {
-    CHECK(value.GetDictionary(Store::kCapabilities_ProvidedKey,
-                              &provided_value));
-  }
-  if (provided_value) {
-    mojo::CapabilityRequest provided;
-    base::DictionaryValue::Iterator it(*provided_value);
-    for(; !it.IsAtEnd(); it.Advance()) {
-      mojo::Interfaces interfaces;
-      ReadStringSetFromValue(it.value(), &interfaces);
-      capabilities.provided[it.key()] = interfaces;
-    }
-  }
-
-  const base::DictionaryValue* required_value = nullptr;
-  if (value.HasKey(Store::kCapabilities_RequiredKey)) {
-    CHECK(value.GetDictionary(Store::kCapabilities_RequiredKey,
-                              &required_value));
-  }
-  if (required_value) {
-    base::DictionaryValue::Iterator it(*required_value);
-    for (; !it.IsAtEnd(); it.Advance()) {
-      mojo::CapabilityRequest spec;
-      const base::DictionaryValue* entry_value = nullptr;
-      CHECK(it.value().GetAsDictionary(&entry_value));
-      ReadStringSetFromDictionary(
-          *entry_value, Store::kCapabilities_ClassesKey, &spec.classes);
-      ReadStringSetFromDictionary(
-          *entry_value, Store::kCapabilities_InterfacesKey, &spec.interfaces);
-      capabilities.required[it.key()] = spec;
-    }
-  }
-  return capabilities;
-}
-
-Entry BuildEntry(const base::DictionaryValue& value) {
-  Entry entry;
-  int manifest_version = 0;
-  if (value.HasKey(Store::kManifestVersionKey))
-    CHECK(value.GetInteger(Store::kManifestVersionKey, &manifest_version));
-  std::string name_string;
-  CHECK(value.GetString(Store::kNameKey, &name_string));
-  CHECK(mojo::IsValidName(name_string)) << "Invalid Name: " << name_string;
-  entry.name = name_string;
-  if (value.HasKey(Store::kQualifierKey)) {
-    CHECK(value.GetString(Store::kQualifierKey, &entry.qualifier));
-  } else {
-    entry.qualifier = mojo::GetNamePath(name_string);
-  }
-  CHECK(value.GetString(Store::kDisplayNameKey, &entry.display_name));
-  const base::DictionaryValue* capabilities = nullptr;
-  CHECK(value.GetDictionary(Store::kCapabilitiesKey, &capabilities));
-  if (manifest_version == 0)
-    entry.capabilities = BuildCapabilitiesV0(*capabilities);
-  else
-    entry.capabilities = BuildCapabilitiesV1(*capabilities);
-  return entry;
-}
-
-scoped_ptr<base::DictionaryValue> SerializeEntry(const Entry& entry) {
-  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue);
-  value->SetInteger(Store::kManifestVersionKey, 1);
-  value->SetString(Store::kNameKey, entry.name);
-  value->SetString(Store::kDisplayNameKey, entry.display_name);
-  value->SetString(Store::kQualifierKey, entry.qualifier);
-  scoped_ptr<base::DictionaryValue> spec(new base::DictionaryValue);
-
-  scoped_ptr<base::DictionaryValue> provided(new base::DictionaryValue);
-  for (const auto& i : entry.capabilities.provided) {
-    scoped_ptr<base::ListValue> interfaces(new base::ListValue);
-    for (const auto& interface_name : i.second)
-      interfaces->AppendString(interface_name);
-    provided->Set(i.first, std::move(interfaces));
-  }
-  spec->Set(Store::kCapabilities_ProvidedKey, std::move(provided));
-
-  scoped_ptr<base::DictionaryValue> required(new base::DictionaryValue);
-  for (const auto& i : entry.capabilities.required) {
-    scoped_ptr<base::DictionaryValue> request(new base::DictionaryValue);
-    scoped_ptr<base::ListValue> classes(new base::ListValue);
-    for (const auto& class_name : i.second.classes)
-      classes->AppendString(class_name);
-    request->Set(Store::kCapabilities_ClassesKey, std::move(classes));
-    scoped_ptr<base::ListValue> interfaces(new base::ListValue);
-    for (const auto& interface_name : i.second.interfaces)
-      interfaces->AppendString(interface_name);
-    request->Set(Store::kCapabilities_InterfacesKey, std::move(interfaces));
-    required->Set(i.first, std::move(request));
-  }
-  spec->Set(Store::kCapabilities_RequiredKey, std::move(required));
-
-  value->Set(Store::kCapabilitiesKey, std::move(spec));
-  return value;
-}
-
-}  // namespace catalog
diff --git a/mojo/services/catalog/builder.h b/mojo/services/catalog/builder.h
deleted file mode 100644
index 71eebf10..0000000
--- a/mojo/services/catalog/builder.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_SERVICES_CATALOG_BUILDER_H_
-#define MOJO_SERVICES_CATALOG_BUILDER_H_
-
-#include "mojo/services/catalog/entry.h"
-
-namespace base {
-class DictionaryValue;
-}
-
-namespace catalog {
-
-Entry BuildEntry(const base::DictionaryValue& value);
-
-scoped_ptr<base::DictionaryValue> SerializeEntry(const Entry& entry);
-
-}  // namespace catalog
-
-#endif  // MOJO_SERVICES_CATALOG_BUILDER_H_
diff --git a/mojo/services/catalog/builder_unittest.cc b/mojo/services/catalog/builder_unittest.cc
deleted file mode 100644
index 1705be8..0000000
--- a/mojo/services/catalog/builder_unittest.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/services/catalog/builder.h"
-
-#include "base/files/file_path.h"
-#include "base/json/json_file_value_serializer.h"
-#include "base/macros.h"
-#include "base/path_service.h"
-#include "base/values.h"
-#include "mojo/shell/public/cpp/capabilities.h"
-#include "mojo/shell/public/cpp/names.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace catalog {
-
-class BuilderTest : public testing::Test {
- public:
-  BuilderTest() {}
-  ~BuilderTest() override {}
-
- protected:
-  scoped_ptr<base::Value> ReadEntry(const std::string& manifest, Entry* entry) {
-    DCHECK(entry);
-    scoped_ptr<base::Value> value = ReadManifest(manifest);
-    base::DictionaryValue* dictionary = nullptr;
-    CHECK(value->GetAsDictionary(&dictionary));
-    *entry = BuildEntry(*dictionary);
-    return value;
-  }
-
-  scoped_ptr<base::Value> ReadManifest(const std::string& manifest) {
-    base::FilePath manifest_path;
-    PathService::Get(base::DIR_SOURCE_ROOT, &manifest_path);
-    manifest_path = manifest_path.AppendASCII(
-        "mojo/services/catalog/data/" + manifest);
-
-    JSONFileValueDeserializer deserializer(manifest_path);
-    int error = 0;
-    std::string message;
-    // TODO(beng): probably want to do more detailed error checking. This should
-    //             be done when figuring out if to unblock connection
-    //             completion.
-    return deserializer.Deserialize(&error, &message);
-  }
-
- private:
-  void SetUp() override {}
-  void TearDown() override {}
-
-  DISALLOW_COPY_AND_ASSIGN(BuilderTest);
-};
-
-TEST_F(BuilderTest, Simple) {
-  Entry entry;
-  ReadEntry("simple", &entry);
-
-  EXPECT_EQ("mojo:foo", entry.name);
-  EXPECT_EQ(mojo::GetNamePath(entry.name), entry.qualifier);
-  EXPECT_EQ("Foo", entry.display_name);
-}
-
-TEST_F(BuilderTest, Instance) {
-  Entry entry;
-  ReadEntry("instance", &entry);
-
-  EXPECT_EQ("mojo:foo", entry.name);
-  EXPECT_EQ("bar", entry.qualifier);
-  EXPECT_EQ("Foo", entry.display_name);
-}
-
-TEST_F(BuilderTest, Capabilities) {
-  Entry entry;
-  ReadEntry("capabilities", &entry);
-
-  EXPECT_EQ("mojo:foo", entry.name);
-  EXPECT_EQ("bar", entry.qualifier);
-  EXPECT_EQ("Foo", entry.display_name);
-  mojo::CapabilitySpec spec;
-  mojo::CapabilityRequest request;
-  request.interfaces.insert("mojo::Bar");
-  spec.required["mojo:bar"] = request;
-  EXPECT_EQ(spec, entry.capabilities);
-}
-
-TEST_F(BuilderTest, Serialization) {
-  Entry entry;
-  scoped_ptr<base::Value> value = ReadEntry("serialization", &entry);
-
-  scoped_ptr<base::DictionaryValue> serialized(SerializeEntry(entry));
-
-  // We can't just compare values, since during deserialization some of the
-  // lists get converted to std::sets, which are sorted, so Value::Equals will
-  // fail.
-  Entry reconstituted = BuildEntry(*serialized.get());
-  EXPECT_EQ(entry, reconstituted);
-}
-
-TEST_F(BuilderTest, Malformed) {
-  scoped_ptr<base::Value> value = ReadManifest("malformed");
-  EXPECT_FALSE(value.get());
-}
-
-
-}  // namespace catalog
diff --git a/mojo/services/catalog/catalog.cc b/mojo/services/catalog/catalog.cc
index d02e1fe..0bbb9d4 100644
--- a/mojo/services/catalog/catalog.cc
+++ b/mojo/services/catalog/catalog.cc
@@ -9,7 +9,6 @@
 #include "base/strings/string_split.h"
 #include "base/task_runner_util.h"
 #include "mojo/common/url_type_converters.h"
-#include "mojo/services/catalog/builder.h"
 #include "mojo/services/catalog/entry.h"
 #include "mojo/services/catalog/store.h"
 #include "mojo/shell/public/cpp/names.h"
@@ -120,8 +119,8 @@
       continue;
     const Entry& entry = catalog_[name];
     mojom::CatalogEntryPtr entry_ptr(mojom::CatalogEntry::New());
-    entry_ptr->display_name = entry.display_name;
-    entries[entry.name] = std::move(entry_ptr);
+    entry_ptr->display_name = entry.display_name();
+    entries[entry.name()] = std::move(entry_ptr);
   }
   callback.Run(std::move(entries));
 }
@@ -153,7 +152,8 @@
   }
 
   mojo::shell::mojom::CapabilitySpecPtr capabilities_ptr =
-      mojo::shell::mojom::CapabilitySpec::From(entry_iter->second.capabilities);
+      mojo::shell::mojom::CapabilitySpec::From(
+          entry_iter->second.capabilities());
 
   callback.Run(resolved_name, qualifier, std::move(capabilities_ptr),
                file_url.spec());
@@ -193,24 +193,29 @@
     const base::DictionaryValue* dictionary = nullptr;
     const base::Value* v = *it;
     CHECK(v->GetAsDictionary(&dictionary));
-    const Entry entry = BuildEntry(*dictionary);
-    catalog_[entry.name] = entry;
+    scoped_ptr<Entry> entry = Entry::Deserialize(*dictionary);
+    if (entry.get())
+      catalog_[entry->name()] = *entry;
   }
 }
 
 void Catalog::SerializeCatalog() {
   scoped_ptr<base::ListValue> catalog(new base::ListValue);
   for (const auto& entry : catalog_)
-    catalog->Append(SerializeEntry(entry.second));
+    catalog->Append(entry.second.Serialize());
   if (store_)
     store_->UpdateStore(std::move(catalog));
 }
 
-const Entry& Catalog::DeserializeApplication(
+scoped_ptr<Entry> Catalog::DeserializeApplication(
     const base::DictionaryValue* dictionary) {
-  Entry entry = BuildEntry(*dictionary);
-  if (catalog_.find(entry.name) == catalog_.end()) {
-    catalog_[entry.name] = entry;
+  scoped_ptr<Entry> entry = Entry::Deserialize(*dictionary);
+  if (!entry)
+    return entry;
+
+  // TODO(beng): move raw dictionary analysis into Deserialize().
+  if (catalog_.find(entry->name()) == catalog_.end()) {
+    catalog_[entry->name()] = *entry;
 
     if (dictionary->HasKey("applications")) {
       const base::ListValue* applications = nullptr;
@@ -218,14 +223,16 @@
       for (size_t i = 0; i < applications->GetSize(); ++i) {
         const base::DictionaryValue* child_value = nullptr;
         applications->GetDictionary(i, &child_value);
-        const Entry& child = DeserializeApplication(child_value);
-        mojo_name_aliases_[child.name] =
-            std::make_pair(entry.name, child.qualifier);
+        scoped_ptr<Entry> child = DeserializeApplication(child_value);
+        if (child) {
+          mojo_name_aliases_[child->name()] =
+              std::make_pair(entry->name(), child->qualifier());
+        }
       }
     }
-    qualifiers_[entry.name] = entry.qualifier;
+    qualifiers_[entry->name()] = entry->qualifier();
   }
-  return catalog_[entry.name];
+  return entry;
 }
 
 GURL Catalog::GetManifestURL(const std::string& name) {
@@ -262,10 +269,10 @@
     DeserializeApplication(dictionary);
   } else {
     Entry entry;
-    entry.name = name;
-    entry.display_name = name;
-    catalog_[entry.name] = entry;
-    qualifiers_[entry.name] = mojo::GetNamePath(name);
+    entry.set_name(name);
+    entry.set_display_name(name);
+    catalog_[entry.name()] = entry;
+    qualifiers_[entry.name()] = mojo::GetNamePath(name);
   }
   SerializeCatalog();
 
diff --git a/mojo/services/catalog/catalog.h b/mojo/services/catalog/catalog.h
index dd0e53a7..e4bc6a54 100644
--- a/mojo/services/catalog/catalog.h
+++ b/mojo/services/catalog/catalog.h
@@ -76,7 +76,8 @@
   void SerializeCatalog();
 
   // Construct a catalog entry from |dictionary|.
-  const Entry& DeserializeApplication(const base::DictionaryValue* dictionary);
+  scoped_ptr<Entry> DeserializeApplication(
+      const base::DictionaryValue* dictionary);
 
   GURL GetManifestURL(const std::string& name);
 
diff --git a/mojo/services/catalog/entry.cc b/mojo/services/catalog/entry.cc
index 9aec915e..528eee49 100644
--- a/mojo/services/catalog/entry.cc
+++ b/mojo/services/catalog/entry.cc
@@ -4,16 +4,188 @@
 
 #include "mojo/services/catalog/entry.h"
 
+#include "base/values.h"
+#include "mojo/services/catalog/store.h"
+#include "mojo/shell/public/cpp/names.h"
+
 namespace catalog {
+namespace {
+
+mojo::CapabilitySpec BuildCapabilitiesV0(
+    const base::DictionaryValue& value) {
+  mojo::CapabilitySpec capabilities;
+  base::DictionaryValue::Iterator it(value);
+  for (; !it.IsAtEnd(); it.Advance()) {
+    const base::ListValue* values = nullptr;
+    CHECK(it.value().GetAsList(&values));
+    mojo::CapabilityRequest spec;
+    for (auto i = values->begin(); i != values->end(); ++i) {
+      mojo::Interface interface_name;
+      const base::Value* v = *i;
+      CHECK(v->GetAsString(&interface_name));
+      spec.interfaces.insert(interface_name);
+    }
+    capabilities.required[it.key()] = spec;
+  }
+  return capabilities;
+}
+
+void ReadStringSet(const base::ListValue& list_value,
+                   std::set<std::string>* string_set) {
+  DCHECK(string_set);
+  for (auto i = list_value.begin(); i != list_value.end(); ++i) {
+    std::string value;
+    const base::Value* value_value = *i;
+    CHECK(value_value->GetAsString(&value));
+    string_set->insert(value);
+  }
+}
+
+void ReadStringSetFromValue(const base::Value& value,
+                            std::set<std::string>* string_set) {
+  const base::ListValue* list_value = nullptr;
+  CHECK(value.GetAsList(&list_value));
+  ReadStringSet(*list_value, string_set);
+}
+
+void ReadStringSetFromDictionary(const base::DictionaryValue& dictionary,
+                                 const std::string& key,
+                                 std::set<std::string>* string_set) {
+  const base::ListValue* list_value = nullptr;
+  if (dictionary.HasKey(key))
+    CHECK(dictionary.GetList(key, &list_value));
+  if (list_value)
+    ReadStringSet(*list_value, string_set);
+}
+
+mojo::CapabilitySpec BuildCapabilitiesV1(
+    const base::DictionaryValue& value) {
+  mojo::CapabilitySpec capabilities;
+
+  const base::DictionaryValue* provided_value = nullptr;
+  if (value.HasKey(Store::kCapabilities_ProvidedKey)) {
+    CHECK(value.GetDictionary(Store::kCapabilities_ProvidedKey,
+                              &provided_value));
+  }
+  if (provided_value) {
+    mojo::CapabilityRequest provided;
+    base::DictionaryValue::Iterator it(*provided_value);
+    for(; !it.IsAtEnd(); it.Advance()) {
+      mojo::Interfaces interfaces;
+      ReadStringSetFromValue(it.value(), &interfaces);
+      capabilities.provided[it.key()] = interfaces;
+    }
+  }
+
+  const base::DictionaryValue* required_value = nullptr;
+  if (value.HasKey(Store::kCapabilities_RequiredKey)) {
+    CHECK(value.GetDictionary(Store::kCapabilities_RequiredKey,
+                              &required_value));
+  }
+  if (required_value) {
+    base::DictionaryValue::Iterator it(*required_value);
+    for (; !it.IsAtEnd(); it.Advance()) {
+      mojo::CapabilityRequest spec;
+      const base::DictionaryValue* entry_value = nullptr;
+      CHECK(it.value().GetAsDictionary(&entry_value));
+      ReadStringSetFromDictionary(
+          *entry_value, Store::kCapabilities_ClassesKey, &spec.classes);
+      ReadStringSetFromDictionary(
+          *entry_value, Store::kCapabilities_InterfacesKey, &spec.interfaces);
+      capabilities.required[it.key()] = spec;
+    }
+  }
+  return capabilities;
+}
+
+}  // namespace
 
 Entry::Entry() {}
 Entry::Entry(const Entry& other) = default;
 Entry::~Entry() {}
 
+scoped_ptr<base::DictionaryValue> Entry::Serialize() const {
+  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue);
+  value->SetInteger(Store::kManifestVersionKey, 1);
+  value->SetString(Store::kNameKey, name_);
+  value->SetString(Store::kDisplayNameKey, display_name_);
+  value->SetString(Store::kQualifierKey, qualifier_);
+  scoped_ptr<base::DictionaryValue> spec(new base::DictionaryValue);
+
+  scoped_ptr<base::DictionaryValue> provided(new base::DictionaryValue);
+  for (const auto& i : capabilities_.provided) {
+    scoped_ptr<base::ListValue> interfaces(new base::ListValue);
+    for (const auto& interface_name : i.second)
+      interfaces->AppendString(interface_name);
+    provided->Set(i.first, std::move(interfaces));
+  }
+  spec->Set(Store::kCapabilities_ProvidedKey, std::move(provided));
+
+  scoped_ptr<base::DictionaryValue> required(new base::DictionaryValue);
+  for (const auto& i : capabilities_.required) {
+    scoped_ptr<base::DictionaryValue> request(new base::DictionaryValue);
+    scoped_ptr<base::ListValue> classes(new base::ListValue);
+    for (const auto& class_name : i.second.classes)
+      classes->AppendString(class_name);
+    request->Set(Store::kCapabilities_ClassesKey, std::move(classes));
+    scoped_ptr<base::ListValue> interfaces(new base::ListValue);
+    for (const auto& interface_name : i.second.interfaces)
+      interfaces->AppendString(interface_name);
+    request->Set(Store::kCapabilities_InterfacesKey, std::move(interfaces));
+    required->Set(i.first, std::move(request));
+  }
+  spec->Set(Store::kCapabilities_RequiredKey, std::move(required));
+
+  value->Set(Store::kCapabilitiesKey, std::move(spec));
+  return value;
+}
+
+// static
+scoped_ptr<Entry> Entry::Deserialize(const base::DictionaryValue& value) {
+  scoped_ptr<Entry> entry(new Entry);
+  int manifest_version = 0;
+  if (value.HasKey(Store::kManifestVersionKey))
+    CHECK(value.GetInteger(Store::kManifestVersionKey, &manifest_version));
+  std::string name_string;
+  if (!value.GetString(Store::kNameKey, &name_string)) {
+    LOG(ERROR) << "Entry::Deserialize: dictionary has no name key";
+    return nullptr;
+  }
+  if (!mojo::IsValidName(name_string)) {
+    LOG(WARNING) << "Entry::Deserialize: " << name_string << " is not a valid "
+                 << "Mojo name";
+    return nullptr;
+  }
+  entry->set_name(name_string);
+  if (value.HasKey(Store::kQualifierKey)) {
+    std::string qualifier;
+    CHECK(value.GetString(Store::kQualifierKey, &qualifier));
+    entry->set_qualifier(qualifier);
+  } else {
+    entry->set_qualifier(mojo::GetNamePath(name_string));
+  }
+  std::string display_name;
+  if (!value.GetString(Store::kDisplayNameKey, &display_name)) {
+    LOG(WARNING) << "Entry::Deserialize: dictionary has no display_name key";
+    return nullptr;
+  }
+  entry->set_display_name(display_name);
+  const base::DictionaryValue* capabilities = nullptr;
+  if (!value.GetDictionary(Store::kCapabilitiesKey, &capabilities)) {
+    LOG(WARNING) << "Entry::Description: dictionary has no capabilities key";
+    return nullptr;
+  }
+  if (manifest_version == 0)
+    entry->set_capabilities(BuildCapabilitiesV0(*capabilities));
+  else
+    entry->set_capabilities(BuildCapabilitiesV1(*capabilities));
+  return entry;
+}
+
 bool Entry::operator==(const Entry& other) const {
-  return other.name == name && other.qualifier == qualifier &&
-         other.display_name == display_name &&
-         other.capabilities == capabilities;
+  return other.name_ == name_ && other.qualifier_ == qualifier_ &&
+         other.display_name_ == display_name_ &&
+         other.capabilities_ == capabilities_;
 }
 
 }  // catalog
diff --git a/mojo/services/catalog/entry.h b/mojo/services/catalog/entry.h
index 4b7ffa8..ac5ace5 100644
--- a/mojo/services/catalog/entry.h
+++ b/mojo/services/catalog/entry.h
@@ -7,22 +7,45 @@
 
 #include <string>
 
+#include "base/memory/scoped_ptr.h"
 #include "mojo/shell/public/cpp/capabilities.h"
 
+namespace base {
+class DictionaryValue;
+}
+
 namespace catalog {
 
 // Static information about an application package known to the Catalog.
-struct Entry {
+class Entry {
+ public:
   Entry();
-  Entry(const Entry& other);
+  explicit Entry(const Entry& other);
   ~Entry();
 
+  scoped_ptr<base::DictionaryValue> Serialize() const;
+  static scoped_ptr<Entry> Deserialize(const base::DictionaryValue& value);
+
   bool operator==(const Entry& other) const;
 
-  std::string name;
-  std::string qualifier;
-  std::string display_name;
-  mojo::CapabilitySpec capabilities;
+  const std::string& name() const { return name_; }
+  void set_name(const std::string& name) { name_ = name; }
+  const std::string& qualifier() const { return qualifier_; }
+  void set_qualifier(const std::string& qualifier) { qualifier_ = qualifier; }
+  const std::string& display_name() const { return display_name_; }
+  void set_display_name(const std::string& display_name) {
+    display_name_ = display_name;
+  }
+  const mojo::CapabilitySpec& capabilities() const { return capabilities_; }
+  void set_capabilities(const mojo::CapabilitySpec& capabilities) {
+    capabilities_ = capabilities;
+  }
+
+ private:
+  std::string name_;
+  std::string qualifier_;
+  std::string display_name_;
+  mojo::CapabilitySpec capabilities_;
 };
 
 }  // namespace catalog
diff --git a/mojo/services/catalog/entry_unittest.cc b/mojo/services/catalog/entry_unittest.cc
new file mode 100644
index 0000000..c59e3c2
--- /dev/null
+++ b/mojo/services/catalog/entry_unittest.cc
@@ -0,0 +1,102 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/services/catalog/entry.h"
+
+#include "base/files/file_path.h"
+#include "base/json/json_file_value_serializer.h"
+#include "base/macros.h"
+#include "base/path_service.h"
+#include "base/values.h"
+#include "mojo/shell/public/cpp/capabilities.h"
+#include "mojo/shell/public/cpp/names.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace catalog {
+
+class EntryTest : public testing::Test {
+ public:
+  EntryTest() {}
+  ~EntryTest() override {}
+
+ protected:
+  scoped_ptr<Entry> ReadEntry(const std::string& manifest,
+                              scoped_ptr<base::Value>* out_value) {
+    scoped_ptr<base::Value> value = ReadManifest(manifest);
+    base::DictionaryValue* dictionary = nullptr;
+    CHECK(value->GetAsDictionary(&dictionary));
+    if (out_value)
+      *out_value = std::move(value);
+    return Entry::Deserialize(*dictionary);
+  }
+
+  scoped_ptr<base::Value> ReadManifest(const std::string& manifest) {
+    base::FilePath manifest_path;
+    PathService::Get(base::DIR_SOURCE_ROOT, &manifest_path);
+    manifest_path = manifest_path.AppendASCII(
+        "mojo/services/catalog/data/" + manifest);
+
+    JSONFileValueDeserializer deserializer(manifest_path);
+    int error = 0;
+    std::string message;
+    // TODO(beng): probably want to do more detailed error checking. This should
+    //             be done when figuring out if to unblock connection
+    //             completion.
+    return deserializer.Deserialize(&error, &message);
+  }
+
+ private:
+  void SetUp() override {}
+  void TearDown() override {}
+
+  DISALLOW_COPY_AND_ASSIGN(EntryTest);
+};
+
+TEST_F(EntryTest, Simple) {
+  scoped_ptr<Entry> entry = ReadEntry("simple", nullptr);
+  EXPECT_EQ("mojo:foo", entry->name());
+  EXPECT_EQ(mojo::GetNamePath(entry->name()), entry->qualifier());
+  EXPECT_EQ("Foo", entry->display_name());
+}
+
+TEST_F(EntryTest, Instance) {
+  scoped_ptr<Entry> entry = ReadEntry("instance", nullptr);
+  EXPECT_EQ("mojo:foo", entry->name());
+  EXPECT_EQ("bar", entry->qualifier());
+  EXPECT_EQ("Foo", entry->display_name());
+}
+
+TEST_F(EntryTest, Capabilities) {
+  scoped_ptr<Entry> entry = ReadEntry("capabilities", nullptr);
+
+  EXPECT_EQ("mojo:foo", entry->name());
+  EXPECT_EQ("bar", entry->qualifier());
+  EXPECT_EQ("Foo", entry->display_name());
+  mojo::CapabilitySpec spec;
+  mojo::CapabilityRequest request;
+  request.interfaces.insert("mojo::Bar");
+  spec.required["mojo:bar"] = request;
+  EXPECT_EQ(spec, entry->capabilities());
+}
+
+TEST_F(EntryTest, Serialization) {
+  scoped_ptr<base::Value> value;
+  scoped_ptr<Entry> entry = ReadEntry("serialization", &value);
+
+  scoped_ptr<base::DictionaryValue> serialized(entry->Serialize());
+
+  // We can't just compare values, since during deserialization some of the
+  // lists get converted to std::sets, which are sorted, so Value::Equals will
+  // fail.
+  scoped_ptr<Entry> reconstituted = Entry::Deserialize(*serialized.get());
+  EXPECT_EQ(*entry, *reconstituted);
+}
+
+TEST_F(EntryTest, Malformed) {
+  scoped_ptr<base::Value> value = ReadManifest("malformed");
+  EXPECT_FALSE(value.get());
+}
+
+
+}  // namespace catalog
diff --git a/mojo/services/network/network_service_delegate.cc b/mojo/services/network/network_service_delegate.cc
index 1970928..b257331 100644
--- a/mojo/services/network/network_service_delegate.cc
+++ b/mojo/services/network/network_service_delegate.cc
@@ -78,10 +78,6 @@
   return true;
 }
 
-void NetworkServiceDelegate::ShellConnectionLost() {
-  base::MessageLoop::current()->QuitWhenIdle();
-}
-
 void NetworkServiceDelegate::Create(Connection* connection,
                                     InterfaceRequest<NetworkService> request) {
   new NetworkServiceImpl(ref_factory_.CreateRef(), std::move(request));
diff --git a/mojo/services/network/network_service_delegate.h b/mojo/services/network/network_service_delegate.h
index 8997097..70989395 100644
--- a/mojo/services/network/network_service_delegate.h
+++ b/mojo/services/network/network_service_delegate.h
@@ -38,7 +38,6 @@
   void Initialize(Connector* connector, const Identity& identity,
                   uint32_t id) override;
   bool AcceptConnection(Connection* connection) override;
-  void ShellConnectionLost() override;
 
   // InterfaceFactory<NetworkService> implementation.
   void Create(Connection* connection,
diff --git a/mojo/services/tracing/tracing_app.cc b/mojo/services/tracing/tracing_app.cc
index 65b44219..d921a6d9 100644
--- a/mojo/services/tracing/tracing_app.cc
+++ b/mojo/services/tracing/tracing_app.cc
@@ -42,8 +42,12 @@
   return true;
 }
 
-void TracingApp::ShellConnectionLost() {
+bool TracingApp::ShellConnectionLost() {
+  // TODO(beng): This is only required because TracingApp isn't run by
+  // ApplicationRunner - instead it's launched automatically by the standalone
+  // shell. It shouldn't be.
   base::MessageLoop::current()->QuitWhenIdle();
+  return false;
 }
 
 void TracingApp::Create(mojo::Connection* connection,
diff --git a/mojo/services/tracing/tracing_app.h b/mojo/services/tracing/tracing_app.h
index 17f4132..eb5934a 100644
--- a/mojo/services/tracing/tracing_app.h
+++ b/mojo/services/tracing/tracing_app.h
@@ -34,7 +34,7 @@
  private:
   // mojo::ShellClient implementation.
   bool AcceptConnection(mojo::Connection* connection) override;
-  void ShellConnectionLost() override;
+  bool ShellConnectionLost() override;
 
   // mojo::InterfaceFactory<TraceCollector> implementation.
   void Create(mojo::Connection* connection,
diff --git a/mojo/shell/background/tests/test_service.cc b/mojo/shell/background/tests/test_service.cc
index d030a81..e69640d 100644
--- a/mojo/shell/background/tests/test_service.cc
+++ b/mojo/shell/background/tests/test_service.cc
@@ -25,8 +25,8 @@
     connection->AddInterface(this);
     return true;
   }
-  void ShellConnectionLost() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+  bool ShellConnectionLost() override {
+    return true;
   }
 
   // InterfaceFactory<mojom::TestService>:
diff --git a/mojo/shell/public/cpp/lib/application_runner.cc b/mojo/shell/public/cpp/lib/application_runner.cc
index 5253053..201aa62 100644
--- a/mojo/shell/public/cpp/lib/application_runner.cc
+++ b/mojo/shell/public/cpp/lib/application_runner.cc
@@ -5,10 +5,12 @@
 #include "mojo/shell/public/cpp/application_runner.h"
 
 #include "base/at_exit.h"
+#include "base/bind.h"
 #include "base/command_line.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/process/launch.h"
+#include "base/run_loop.h"
 #include "mojo/shell/public/cpp/shell_client.h"
 #include "mojo/shell/public/cpp/shell_connection.h"
 
@@ -54,7 +56,9 @@
         client_.get(),
         MakeRequest<shell::mojom::ShellClient>(MakeScopedHandle(
             MessagePipeHandle(shell_client_request_handle)))));
-    loop->Run();
+    base::RunLoop run_loop;
+    connection_->set_connection_lost_closure(run_loop.QuitClosure());
+    run_loop.Run();
     // It's very common for the client to cache the app and terminate on errors.
     // If we don't delete the client before the app we run the risk of the
     // client having a stale reference to the app and trying to use it.
diff --git a/mojo/shell/public/cpp/lib/shell_client.cc b/mojo/shell/public/cpp/lib/shell_client.cc
index c41999b..3ca8cd7 100644
--- a/mojo/shell/public/cpp/lib/shell_client.cc
+++ b/mojo/shell/public/cpp/lib/shell_client.cc
@@ -17,6 +17,6 @@
   return false;
 }
 
-void ShellClient::ShellConnectionLost() {}
+bool ShellClient::ShellConnectionLost() { return true; }
 
 }  // namespace mojo
diff --git a/mojo/shell/public/cpp/lib/shell_connection.cc b/mojo/shell/public/cpp/lib/shell_connection.cc
index d1cba7ea..62ae598 100644
--- a/mojo/shell/public/cpp/lib/shell_connection.cc
+++ b/mojo/shell/public/cpp/lib/shell_connection.cc
@@ -86,7 +86,8 @@
   // Note that the ShellClient doesn't technically have to quit now, it may live
   // on to service existing connections. All existing Connectors however are
   // invalid.
-  client_->ShellConnectionLost();
+  if (client_->ShellConnectionLost() && !connection_lost_closure_.is_null())
+    connection_lost_closure_.Run();
   // We don't reset the connector as clients may have taken a raw pointer to it.
   // Connect() will return nullptr if they try to connect to anything.
 }
diff --git a/mojo/shell/public/cpp/shell_client.h b/mojo/shell/public/cpp/shell_client.h
index d6fca12..aff1aac4 100644
--- a/mojo/shell/public/cpp/shell_client.h
+++ b/mojo/shell/public/cpp/shell_client.h
@@ -43,8 +43,13 @@
 
   // Called when ShellConnection's ShellClient binding (i.e. the pipe the
   // Mojo Shell has to talk to us over) is closed. A shell client may use this
-  // as a signal to terminate.
-  virtual void ShellConnectionLost();
+  // as a signal to terminate. Return true from this method to tell the
+  // ShellConnection to run its connection lost closure if it has one, false to
+  // prevent it from being run. The default implementation returns true.
+  // When used in conjunction with ApplicationRunner, returning true here quits
+  // the message loop created by ApplicationRunner, which results in the app
+  // quitting.
+  virtual bool ShellConnectionLost();
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ShellClient);
diff --git a/mojo/shell/public/cpp/shell_connection.h b/mojo/shell/public/cpp/shell_connection.h
index a05f6f13..3e00cd3 100644
--- a/mojo/shell/public/cpp/shell_connection.h
+++ b/mojo/shell/public/cpp/shell_connection.h
@@ -61,7 +61,12 @@
   // TODO(rockot): Remove this once we get rid of app tests.
   void SetAppTestConnectorForTesting(shell::mojom::ConnectorPtr connector);
 
- private:
+  // Specify a function to be called when the connection to the shell is lost.
+  void set_connection_lost_closure(const base::Closure& closure) {
+    connection_lost_closure_ = closure;
+  }
+
+private:
   // shell::mojom::ShellClient:
   void Initialize(shell::mojom::IdentityPtr identity,
                   uint32_t id,
@@ -90,6 +95,8 @@
   Binding<shell::mojom::ShellClient> binding_;
   scoped_ptr<Connector> connector_;
 
+  base::Closure connection_lost_closure_;
+
   DISALLOW_COPY_AND_ASSIGN(ShellConnection);
 };
 
diff --git a/mojo/shell/tests/connect/connect_test_app.cc b/mojo/shell/tests/connect/connect_test_app.cc
index 342e14d7..4180763 100644
--- a/mojo/shell/tests/connect/connect_test_app.cc
+++ b/mojo/shell/tests/connect/connect_test_app.cc
@@ -79,12 +79,6 @@
 
     return true;
   }
-  void ShellConnectionLost() override {
-    if (base::MessageLoop::current() &&
-        base::MessageLoop::current()->is_running()) {
-      base::MessageLoop::current()->QuitWhenIdle();
-    }
-  }
 
   // InterfaceFactory<test::mojom::ConnectTestService>:
   void Create(Connection* connection,
diff --git a/mojo/shell/tests/connect/connect_test_driver.cc b/mojo/shell/tests/connect/connect_test_driver.cc
index ace64df5..b1bdce4c 100644
--- a/mojo/shell/tests/connect/connect_test_driver.cc
+++ b/mojo/shell/tests/connect/connect_test_driver.cc
@@ -37,8 +37,9 @@
     connection->AddInterface<ClientProcessTest>(this);
     return true;
   }
-  void ShellConnectionLost() override {
-    // TODO: This should exit cleanly.
+  bool ShellConnectionLost() override {
+    // TODO(rockot): http://crbug.com/596621. Should be able to remove this
+    // override entirely.
     _exit(1);
   }
 
diff --git a/mojo/shell/tests/connect/connect_test_package.cc b/mojo/shell/tests/connect/connect_test_package.cc
index c5a1a07..1458e65 100644
--- a/mojo/shell/tests/connect/connect_test_package.cc
+++ b/mojo/shell/tests/connect/connect_test_package.cc
@@ -184,12 +184,6 @@
     connection->AddInterface<test::mojom::ConnectTestService>(this);
     return true;
   }
-  void ShellConnectionLost() override {
-    if (base::MessageLoop::current() &&
-        base::MessageLoop::current()->is_running()) {
-      base::MessageLoop::current()->QuitWhenIdle();
-    }
-  }
 
   // InterfaceFactory<mojom::ShellClientFactory>:
   void Create(Connection* connection,
diff --git a/mojo/shell/tests/lifecycle/app_client.cc b/mojo/shell/tests/lifecycle/app_client.cc
index a2400ec..657d967 100644
--- a/mojo/shell/tests/lifecycle/app_client.cc
+++ b/mojo/shell/tests/lifecycle/app_client.cc
@@ -20,10 +20,6 @@
   return true;
 }
 
-void AppClient::ShellConnectionLost() {
-  GracefulQuit();
-}
-
 void AppClient::Create(mojo::Connection* connection,
                        LifecycleControlRequest request) {
   bindings_.AddBinding(this, std::move(request));
diff --git a/mojo/shell/tests/lifecycle/app_client.h b/mojo/shell/tests/lifecycle/app_client.h
index d389f20..5a7d5e6 100644
--- a/mojo/shell/tests/lifecycle/app_client.h
+++ b/mojo/shell/tests/lifecycle/app_client.h
@@ -37,7 +37,6 @@
 
   // ShellClient:
   bool AcceptConnection(Connection* connection) override;
-  void ShellConnectionLost() override;
 
   // InterfaceFactory<LifecycleControl>:
   void Create(Connection* connection, LifecycleControlRequest request) override;
diff --git a/mojo/tools/data/apptests b/mojo/tools/data/apptests
index a3a4940..8e6ceef 100644
--- a/mojo/tools/data/apptests
+++ b/mojo/tools/data/apptests
@@ -35,12 +35,6 @@
 if config.target_os != config.OS_ANDROID:
   tests += [
     {
-      'test': 'mojo:mash_wm_apptests',
-      'type': 'gtest_isolated',
-      'args': ['--use-x11-test-config',
-               '--override-use-gl-with-osmesa-for-tests']
-    },
-    {
       'test': 'mojo:media_apptests',
       'type': 'gtest_isolated',
     },
diff --git a/native_client_sdk/src/gonacl_appengine/src/smoothlife/build.sh b/native_client_sdk/src/gonacl_appengine/src/smoothlife/build.sh
index 84c33b7..25952c0 100755
--- a/native_client_sdk/src/gonacl_appengine/src/smoothlife/build.sh
+++ b/native_client_sdk/src/gonacl_appengine/src/smoothlife/build.sh
@@ -12,7 +12,7 @@
 OUT_DIR=out
 SMOOTHLIFE_URL=https://github.com/binji/smoothnacl
 SMOOTHLIFE_DIR=${OUT_DIR}/smoothlife
-SMOOTHLIFE_SHA=e81cf2b00290add556dcdc8aa84506ca007bc853
+SMOOTHLIFE_SHA=3c9c7418437ae5ad66b697d8f731b12b9a8916ed
 
 if [ -z "${NACL_SDK_ROOT:-}" ]; then
   echo "-------------------------------------------------------------------"
@@ -67,8 +67,10 @@
 
 pushd ${SMOOTHLIFE_DIR}
 
-Banner Updating submodules
-LogExecute git submodule update --init
+Banner Updating webports
+pushd third_party/webports
+LogExecute gclient sync
+popd
 
 Banner Building FFTW
 LogExecute make ports TOOLCHAIN=pnacl CONFIG=Release
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 309430b1..b6390a79 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1911,6 +1911,7 @@
     ":net_fuzzer_test_support",
     "//net",
   ]
+  dict = "http/http_chunked_decoder_fuzzer.dict"
 }
 
 fuzzer_test("net_quic_crypto_framer_parse_message_fuzzer") {
diff --git a/net/base/ip_address.cc b/net/base/ip_address.cc
index 7ae68bf4..26c8cc5 100644
--- a/net/base/ip_address.cc
+++ b/net/base/ip_address.cc
@@ -30,6 +30,27 @@
   ip_address_.push_back(b3);
 }
 
+IPAddress::IPAddress(uint8_t b0,
+                     uint8_t b1,
+                     uint8_t b2,
+                     uint8_t b3,
+                     uint8_t b4,
+                     uint8_t b5,
+                     uint8_t b6,
+                     uint8_t b7,
+                     uint8_t b8,
+                     uint8_t b9,
+                     uint8_t b10,
+                     uint8_t b11,
+                     uint8_t b12,
+                     uint8_t b13,
+                     uint8_t b14,
+                     uint8_t b15) {
+  const uint8_t address[] = {b0, b1, b2,  b3,  b4,  b5,  b6,  b7,
+                             b8, b9, b10, b11, b12, b13, b14, b15};
+  ip_address_ = std::vector<uint8_t>(std::begin(address), std::end(address));
+}
+
 IPAddress::~IPAddress() {}
 
 bool IPAddress::IsIPv4() const {
diff --git a/net/base/ip_address.h b/net/base/ip_address.h
index 91ce071..1897ebcc 100644
--- a/net/base/ip_address.h
+++ b/net/base/ip_address.h
@@ -40,10 +40,29 @@
   // parameter. The input is expected to be in network byte order.
   IPAddress(const uint8_t* address, size_t address_len);
 
-  // Initializes |ip_address_| from the 4 bX bytes. The bytes are expected to be
-  // in network byte order.
+  // Initializes |ip_address_| from the 4 bX bytes to form an IPv4 address.
+  // The bytes are expected to be in network byte order.
   IPAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3);
 
+  // Initializes |ip_address_| from the 16 bX bytes to form an IPv6 address.
+  // The bytes are expected to be in network byte order.
+  IPAddress(uint8_t b0,
+            uint8_t b1,
+            uint8_t b2,
+            uint8_t b3,
+            uint8_t b4,
+            uint8_t b5,
+            uint8_t b6,
+            uint8_t b7,
+            uint8_t b8,
+            uint8_t b9,
+            uint8_t b10,
+            uint8_t b11,
+            uint8_t b12,
+            uint8_t b13,
+            uint8_t b14,
+            uint8_t b15);
+
   ~IPAddress();
 
   // Returns true if the IP has |kIPv4AddressSize| elements.
diff --git a/net/base/ip_address_unittest.cc b/net/base/ip_address_unittest.cc
index 3ebcb72..d386e49d 100644
--- a/net/base/ip_address_unittest.cc
+++ b/net/base/ip_address_unittest.cc
@@ -24,6 +24,20 @@
   return out;
 }
 
+TEST(IPAddressTest, ConstructIPv4) {
+  EXPECT_EQ("127.0.0.1", IPAddress::IPv4Localhost().ToString());
+
+  IPAddress ipv4_ctor(192, 168, 1, 1);
+  EXPECT_EQ("192.168.1.1", ipv4_ctor.ToString());
+}
+
+TEST(IPAddressTest, ConstructIPv6) {
+  EXPECT_EQ("::1", IPAddress::IPv6Localhost().ToString());
+
+  IPAddress ipv6_ctor(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+  EXPECT_EQ("102:304:506:708:90a:b0c:d0e:f10", ipv6_ctor.ToString());
+}
+
 TEST(IPAddressTest, IsIPVersion) {
   uint8_t addr1[4] = {192, 168, 0, 1};
   IPAddress ip_address1(addr1);
diff --git a/net/cert/cert_database_android.cc b/net/cert/cert_database_android.cc
index d9b0dfcd..89a1a44a 100644
--- a/net/cert/cert_database_android.cc
+++ b/net/cert/cert_database_android.cc
@@ -48,8 +48,7 @@
 }
 
 void CertDatabase::OnAndroidKeyChainChanged() {
-  observer_list_->Notify(FROM_HERE, &Observer::OnCACertChanged,
-                         scoped_refptr<X509Certificate>());
+  observer_list_->Notify(FROM_HERE, &Observer::OnCACertChanged, nullptr);
 }
 
 }  // namespace net
diff --git a/net/cert/internal/name_constraints.cc b/net/cert/internal/name_constraints.cc
index 2077d20..9141a02dd 100644
--- a/net/cert/internal/name_constraints.cc
+++ b/net/cert/internal/name_constraints.cc
@@ -192,12 +192,12 @@
       // version 4, as specified in [RFC791], the octet string MUST contain
       // exactly four octets.  For IP version 6, as specified in [RFC2460],
       // the octet string MUST contain exactly sixteen octets.
-      if ((value.Length() != kIPv4AddressSize &&
-           value.Length() != kIPv6AddressSize)) {
+      if ((value.Length() != IPAddress::kIPv4AddressSize &&
+           value.Length() != IPAddress::kIPv6AddressSize)) {
         return false;
       }
-      subtrees->ip_addresses.push_back(std::vector<uint8_t>(
-          value.UnsafeData(), value.UnsafeData() + value.Length()));
+      subtrees->ip_addresses.push_back(
+          IPAddress(value.UnsafeData(), value.Length()));
     } else {
       DCHECK_EQ(ip_address_type, IP_ADDRESS_AND_NETMASK);
       // RFC 5280 section 4.2.1.10:
@@ -210,19 +210,18 @@
       // constraint for "class C" subnet 192.0.2.0 is represented as the
       // octets C0 00 02 00 FF FF FF 00, representing the CIDR notation
       // 192.0.2.0/24 (mask 255.255.255.0).
-      if (value.Length() != kIPv4AddressSize * 2 &&
-          value.Length() != kIPv6AddressSize * 2) {
+      if (value.Length() != IPAddress::kIPv4AddressSize * 2 &&
+          value.Length() != IPAddress::kIPv6AddressSize * 2) {
         return false;
       }
-      const std::vector<uint8_t> mask(value.UnsafeData() + value.Length() / 2,
-                                      value.UnsafeData() + value.Length());
+      const IPAddress mask(value.UnsafeData() + value.Length() / 2,
+                           value.Length() / 2);
       const unsigned mask_prefix_length = MaskPrefixLength(mask);
-      if (!IsSuffixZero(mask, mask_prefix_length))
+      if (!IsSuffixZero(mask.bytes(), mask_prefix_length))
         return false;
-      subtrees->ip_address_ranges.push_back(std::make_pair(
-          std::vector<uint8_t>(value.UnsafeData(),
-                               value.UnsafeData() + value.Length() / 2),
-          mask_prefix_length));
+      subtrees->ip_address_ranges.push_back(
+          std::make_pair(IPAddress(value.UnsafeData(), value.Length() / 2),
+                         mask_prefix_length));
     }
   } else if (tag == der::ContextSpecificPrimitive(8)) {
     // registeredID                    [8]     OBJECT IDENTIFIER }
@@ -524,9 +523,9 @@
   return false;
 }
 
-bool NameConstraints::IsPermittedIP(const IPAddressNumber& ip) const {
+bool NameConstraints::IsPermittedIP(const IPAddress& ip) const {
   for (const auto& excluded_ip : excluded_subtrees_.ip_address_ranges) {
-    if (IPNumberMatchesPrefix(ip, excluded_ip.first, excluded_ip.second))
+    if (IPAddressMatchesPrefix(ip, excluded_ip.first, excluded_ip.second))
       return false;
   }
 
@@ -536,7 +535,7 @@
     return true;
 
   for (const auto& permitted_ip : permitted_subtrees_.ip_address_ranges) {
-    if (IPNumberMatchesPrefix(ip, permitted_ip.first, permitted_ip.second))
+    if (IPAddressMatchesPrefix(ip, permitted_ip.first, permitted_ip.second))
       return true;
   }
 
diff --git a/net/cert/internal/name_constraints.h b/net/cert/internal/name_constraints.h
index 07b98a3..35ff913 100644
--- a/net/cert/internal/name_constraints.h
+++ b/net/cert/internal/name_constraints.h
@@ -11,7 +11,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
 
 namespace net {
 
@@ -59,11 +59,11 @@
 
   // iPAddresses as sequences of octets in network byte order. This will be
   // populated if the GeneralNames represents a Subject Alternative Name.
-  std::vector<std::vector<uint8_t>> ip_addresses;
+  std::vector<IPAddress> ip_addresses;
 
   // iPAddress ranges, as <IP, prefix length> pairs. This will be populated
   // if the GeneralNames represents a Name Constraints.
-  std::vector<std::pair<std::vector<uint8_t>, unsigned>> ip_address_ranges;
+  std::vector<std::pair<IPAddress, unsigned>> ip_address_ranges;
 
   // Which name types were present, as a bitfield of GeneralNameTypes.
   // Includes both the supported and unsupported types (although unsupported
@@ -111,7 +111,7 @@
   bool IsPermittedDirectoryName(const der::Input& name_rdn_sequence) const;
 
   // Returns true if the iPAddress |ip| is permitted.
-  bool IsPermittedIP(const IPAddressNumber& ip) const;
+  bool IsPermittedIP(const IPAddress& ip) const;
 
   // Returns a bitfield of GeneralNameTypes of all the types constrained by this
   // NameConstraints. Name types that aren't supported will only be present if
diff --git a/net/cert/internal/name_constraints_unittest.cc b/net/cert/internal/name_constraints_unittest.cc
index 879986e0..693597da 100644
--- a/net/cert/internal/name_constraints_unittest.cc
+++ b/net/cert/internal/name_constraints_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "net/cert/internal/name_constraints.h"
 
+#include "net/base/ip_address.h"
 #include "net/cert/internal/test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -409,142 +410,95 @@
   ASSERT_TRUE(name_constraints);
 
   // IPv4 tests:
-  {
-    // Not in any permitted range.
-    const uint8_t ip4[] = {192, 169, 0, 1};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    // Within the permitted 192.168.0.0/255.255.0.0 range.
-    const uint8_t ip4[] = {192, 168, 0, 1};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    // Within the permitted 192.168.0.0/255.255.0.0 range, however the
-    // excluded 192.168.5.0/255.255.255.0 takes priority.
-    const uint8_t ip4[] = {192, 168, 5, 1};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    // Within the permitted 192.168.0.0/255.255.0.0 range as well as the
-    // permitted 192.168.5.32/255.255.255.224 range, however the excluded
-    // 192.168.5.0/255.255.255.0 still takes priority.
-    const uint8_t ip4[] = {192, 168, 5, 33};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    // Not in any permitted range. (Just outside the
-    // 192.167.5.32/255.255.255.224 range.)
-    const uint8_t ip4[] = {192, 167, 5, 31};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    // Within the permitted 192.167.5.32/255.255.255.224 range.
-    const uint8_t ip4[] = {192, 167, 5, 32};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    // Within the permitted 192.167.5.32/255.255.255.224 range.
-    const uint8_t ip4[] = {192, 167, 5, 63};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    // Not in any permitted range. (Just outside the
-    // 192.167.5.32/255.255.255.224 range.)
-    const uint8_t ip4[] = {192, 167, 5, 64};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    // Not in any permitted range, and also inside the extraneous excluded
-    // 192.166.5.32/255.255.255.224 range.
-    const uint8_t ip4[] = {192, 166, 5, 32};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
+
+  // Not in any permitted range.
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 169, 0, 1)));
+
+  // Within the permitted 192.168.0.0/255.255.0.0 range.
+  EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 168, 0, 1)));
+
+  // Within the permitted 192.168.0.0/255.255.0.0 range, however the
+  // excluded 192.168.5.0/255.255.255.0 takes priority.
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 5, 1)));
+
+  // Within the permitted 192.168.0.0/255.255.0.0 range as well as the
+  // permitted 192.168.5.32/255.255.255.224 range, however the excluded
+  // 192.168.5.0/255.255.255.0 still takes priority.
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 5, 33)));
+
+  // Not in any permitted range. (Just outside the
+  // 192.167.5.32/255.255.255.224 range.)
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 167, 5, 31)));
+
+  // Within the permitted 192.167.5.32/255.255.255.224 range.
+  EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 167, 5, 32)));
+
+  // Within the permitted 192.167.5.32/255.255.255.224 range.
+  EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 167, 5, 63)));
+
+  // Not in any permitted range. (Just outside the
+  // 192.167.5.32/255.255.255.224 range.)
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 167, 5, 64)));
+
+  // Not in any permitted range, and also inside the extraneous excluded
+  // 192.166.5.32/255.255.255.224 range.
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 166, 5, 32)));
 
   // IPv6 tests:
-  {
-    // Not in any permitted range.
-    const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip6, ip6 + arraysize(ip6))));
-  }
-  {
-    // Within the permitted
-    // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range.
-    const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 0, 1};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip6, ip6 + arraysize(ip6))));
-  }
-  {
-    // Within the permitted
-    // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range, however
-    // the excluded
-    // 102:304:506:708:90a:b0c:500:0/ffff:ffff:ffff:ffff:ffff:ffff:ff00:0 takes
-    // priority.
-    const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 0, 0, 1};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip6, ip6 + arraysize(ip6))));
-  }
-  {
-    // Within the permitted
-    // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range as well
-    // as the permitted
-    // 102:304:506:708:90a:b0c:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0,
-    // however the excluded
-    // 102:304:506:708:90a:b0c:500:0/ffff:ffff:ffff:ffff:ffff:ffff:ff00:0 takes
-    // priority.
-    const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 33, 0, 1};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip6, ip6 + arraysize(ip6))));
-  }
-  {
-    // Not in any permitted range. (Just outside the
-    // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0
-    // range.)
-    const uint8_t ip6[] = {1, 2,  3,  4,  5, 6,  7,   8,
-                           9, 10, 11, 11, 5, 31, 255, 255};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip6, ip6 + arraysize(ip6))));
-  }
-  {
-    // Within the permitted
-    // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
-    const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 32, 0, 0};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip6, ip6 + arraysize(ip6))));
-  }
-  {
-    // Within the permitted
-    // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
-    const uint8_t ip6[] = {1, 2,  3,  4,  5, 6,  7,   8,
-                           9, 10, 11, 11, 5, 63, 255, 255};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip6, ip6 + arraysize(ip6))));
-  }
-  {
-    // Not in any permitted range. (Just outside the
-    // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0
-    // range.)
-    const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 64, 0, 0};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip6, ip6 + arraysize(ip6))));
-  }
-  {
-    // Not in any permitted range, and also inside the extraneous excluded
-    // 102:304:506:708:90a:b0a:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
-    const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 10, 5, 33, 0, 1};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip6, ip6 + arraysize(ip6))));
-  }
+
+  // Not in any permitted range.
+  EXPECT_FALSE(name_constraints->IsPermittedIP(
+      IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1)));
+
+  // Within the permitted
+  // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range.
+  EXPECT_TRUE(name_constraints->IsPermittedIP(
+      IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 0, 1)));
+
+  // Within the permitted
+  // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range, however
+  // the excluded
+  // 102:304:506:708:90a:b0c:500:0/ffff:ffff:ffff:ffff:ffff:ffff:ff00:0 takes
+  // priority.
+  EXPECT_FALSE(name_constraints->IsPermittedIP(
+      IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 0, 0, 1)));
+
+  // Within the permitted
+  // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range as well
+  // as the permitted
+  // 102:304:506:708:90a:b0c:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0,
+  // however the excluded
+  // 102:304:506:708:90a:b0c:500:0/ffff:ffff:ffff:ffff:ffff:ffff:ff00:0 takes
+  // priority.
+  EXPECT_FALSE(name_constraints->IsPermittedIP(
+      IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 33, 0, 1)));
+
+  // Not in any permitted range. (Just outside the
+  // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0
+  // range.)
+  EXPECT_FALSE(name_constraints->IsPermittedIP(
+      IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 31, 255, 255)));
+
+  // Within the permitted
+  // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
+  EXPECT_TRUE(name_constraints->IsPermittedIP(
+      IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 32, 0, 0)));
+
+  // Within the permitted
+  // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
+  EXPECT_TRUE(name_constraints->IsPermittedIP(
+      IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 63, 255, 255)));
+
+  // Not in any permitted range. (Just outside the
+  // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0
+  // range.)
+  EXPECT_FALSE(name_constraints->IsPermittedIP(
+      IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 64, 0, 0)));
+
+  // Not in any permitted range, and also inside the extraneous excluded
+  // 102:304:506:708:90a:b0a:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
+  EXPECT_FALSE(name_constraints->IsPermittedIP(
+      IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 10, 5, 33, 0, 1)));
 
   EXPECT_EQ(GENERAL_NAME_IP_ADDRESS, name_constraints->ConstrainedNameTypes());
 
@@ -572,21 +526,10 @@
 
   // Only 192.168.5.0/255.255.255.0 is excluded, and since permitted is empty,
   // any iPAddress outside that is allowed.
-  {
-    const uint8_t ip4[] = {192, 168, 0, 1};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {192, 168, 5, 1};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip6, ip6 + arraysize(ip6))));
-  }
+  EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 168, 0, 1)));
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 5, 1)));
+  EXPECT_TRUE(name_constraints->IsPermittedIP(
+      IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1)));
 }
 
 TEST_P(ParseNameConstraints, IPAdressesExcludeAll) {
@@ -600,26 +543,12 @@
   // 192.168.0.0/255.255.0.0 and
   // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: are permitted,
   // but since 0.0.0.0/0 and ::/0 are excluded nothing is permitted.
-  {
-    const uint8_t ip4[] = {192, 168, 0, 1};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {1, 1, 1, 1};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip6[] = {2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip6, ip6 + arraysize(ip6))));
-  }
-  {
-    const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip6, ip6 + arraysize(ip6))));
-  }
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 0, 1)));
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(1, 1, 1, 1)));
+  EXPECT_FALSE(name_constraints->IsPermittedIP(
+      IPAddress(2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)));
+  EXPECT_FALSE(name_constraints->IsPermittedIP(
+      IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1)));
 }
 
 TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitSingleHost) {
@@ -630,36 +559,12 @@
       NameConstraints::CreateFromDer(der::Input(&a), is_critical()));
   ASSERT_TRUE(name_constraints);
 
-  {
-    const uint8_t ip4[] = {0, 0, 0, 0};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {192, 168, 1, 1};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {192, 168, 1, 2};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {192, 168, 1, 3};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {192, 168, 1, 4};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {255, 255, 255, 255};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress::IPv4AllZeros()));
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 1)));
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 2)));
+  EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 3)));
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 4)));
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(255, 255, 255, 255)));
 }
 
 TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitPrefixLen31) {
@@ -670,41 +575,13 @@
       NameConstraints::CreateFromDer(der::Input(&a), is_critical()));
   ASSERT_TRUE(name_constraints);
 
-  {
-    const uint8_t ip4[] = {0, 0, 0, 0};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {192, 168, 1, 1};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {192, 168, 1, 2};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {192, 168, 1, 3};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {192, 168, 1, 4};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {192, 168, 1, 5};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {255, 255, 255, 255};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress::IPv4AllZeros()));
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 1)));
+  EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 2)));
+  EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 3)));
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 4)));
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 5)));
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress(255, 255, 255, 255)));
 }
 
 TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitPrefixLen1) {
@@ -715,26 +592,12 @@
       NameConstraints::CreateFromDer(der::Input(&a), is_critical()));
   ASSERT_TRUE(name_constraints);
 
-  {
-    const uint8_t ip4[] = {0, 0, 0, 0};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {0x7F, 0xFF, 0xFF, 0xFF};
-    EXPECT_FALSE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {0x80, 0, 0, 0};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {0xFF, 0xFF, 0xFF, 0xFF};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
+  EXPECT_FALSE(name_constraints->IsPermittedIP(IPAddress::IPv4AllZeros()));
+  EXPECT_FALSE(
+      name_constraints->IsPermittedIP(IPAddress(0x7F, 0xFF, 0xFF, 0xFF)));
+  EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(0x80, 0, 0, 0)));
+  EXPECT_TRUE(
+      name_constraints->IsPermittedIP(IPAddress(0xFF, 0xFF, 0xFF, 0xFF)));
 }
 
 TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitAll) {
@@ -745,21 +608,9 @@
       NameConstraints::CreateFromDer(der::Input(&a), is_critical()));
   ASSERT_TRUE(name_constraints);
 
-  {
-    const uint8_t ip4[] = {0, 0, 0, 0};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {192, 168, 1, 1};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
-  {
-    const uint8_t ip4[] = {255, 255, 255, 255};
-    EXPECT_TRUE(name_constraints->IsPermittedIP(
-        IPAddressNumber(ip4, ip4 + arraysize(ip4))));
-  }
+  EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress::IPv4AllZeros()));
+  EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(192, 168, 1, 1)));
+  EXPECT_TRUE(name_constraints->IsPermittedIP(IPAddress(255, 255, 255, 255)));
 }
 
 TEST_P(ParseNameConstraints, IPAdressesFailOnInvalidAddr) {
diff --git a/content/gpu/content_gpu_message_generator.h b/net/data/proxy_resolver_v8_tracing_unittest/alert_url.js
similarity index 62%
copy from content/gpu/content_gpu_message_generator.h
copy to net/data/proxy_resolver_v8_tracing_unittest/alert_url.js
index 55af4ce..3cc14c94 100644
--- a/content/gpu/content_gpu_message_generator.h
+++ b/net/data/proxy_resolver_v8_tracing_unittest/alert_url.js
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Multiply-included file, hence no include guard.
-
-#include "content/gpu/gpu_host_messages.h"
+function FindProxyForURL(url, host) {
+  alert(url);
+  return "PROXY foobar:99";
+}
diff --git a/net/data/proxy_resolver_v8_tracing_unittest/dns_depending_on_url.js b/net/data/proxy_resolver_v8_tracing_unittest/dns_depending_on_url.js
new file mode 100644
index 0000000..ac661107
--- /dev/null
+++ b/net/data/proxy_resolver_v8_tracing_unittest/dns_depending_on_url.js
@@ -0,0 +1,17 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This proxy script has different DNS dependencies based on whether the URL
+// contains "UseMyIpAddress". The final proxy list however is the same.
+function FindProxyForURL(url, host) {
+  if (url.indexOf("UseMyIpAddress") == -1) {
+    if (!myIpAddress())
+      return null;
+  } else {
+    if (!dnsResolve(host))
+      return null;
+  }
+
+  return "PROXY foopy:47";
+}
diff --git a/net/data/proxy_resolver_v8_tracing_unittest/error_depending_on_url.js b/net/data/proxy_resolver_v8_tracing_unittest/error_depending_on_url.js
new file mode 100644
index 0000000..42256ebc
--- /dev/null
+++ b/net/data/proxy_resolver_v8_tracing_unittest/error_depending_on_url.js
@@ -0,0 +1,13 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This proxy script throws an error if the URL does not contain the substring
+// "DontThrowError".
+function FindProxyForURL(url, host) {
+  if (url.indexOf("DontThrowError") == -1) {
+    ErrorUndefinedFunction();
+    return -1;
+  }
+  return "PROXY foopy:42";
+}
diff --git a/net/data/proxy_resolver_v8_tracing_unittest/return_url_as_proxy.js b/net/data/proxy_resolver_v8_tracing_unittest/return_url_as_proxy.js
new file mode 100644
index 0000000..fad3c85
--- /dev/null
+++ b/net/data/proxy_resolver_v8_tracing_unittest/return_url_as_proxy.js
@@ -0,0 +1,16 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This proxy script returns a proxy list that encodes the URL that was passed
+// in.
+
+function convertUrlToHostname(url) {
+  // Turn the URL into something that resembles a hostname.
+  var result = encodeURIComponent(url);
+  return result.replace(/%/g, "x");
+}
+
+function FindProxyForURL(url, host) {
+  return "PROXY " + convertUrlToHostname(url) + ":99";
+}
diff --git a/net/http/http_chunked_decoder_fuzzer.cc b/net/http/http_chunked_decoder_fuzzer.cc
index 1d716e93..91506579 100644
--- a/net/http/http_chunked_decoder_fuzzer.cc
+++ b/net/http/http_chunked_decoder_fuzzer.cc
@@ -5,6 +5,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <algorithm>
 #include <vector>
 
 #include "net/http/http_chunked_decoder.h"
@@ -12,9 +13,33 @@
 // Entry point for LibFuzzer.
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   const char* data_ptr = reinterpret_cast<const char*>(data);
-  std::vector<char> buffer(data_ptr, data_ptr + size);
   net::HttpChunkedDecoder decoder;
-  decoder.FilterBuf(buffer.data(), buffer.size());
+
+  // Feed data to decoder.FilterBuf() by blocks of "random" size.
+  size_t block_size = 0;
+  for (size_t offset = 0; offset < size; offset += block_size) {
+    // Since there is no input for block_size values, but it should be strictly
+    // determined, let's calculate these values using a couple of data bytes.
+    uint8_t temp_block_size = data[offset] ^ data[size - offset - 1];
+
+    // Let temp_block_size be in range from 0 to 0x3F (0b00111111).
+    temp_block_size &= 0x3F;
+
+    // XOR with previous block size to get different values for different data.
+    block_size ^= temp_block_size;
+
+    // Prevent infinite loop if block_size == 0.
+    block_size = std::max(block_size, static_cast<size_t>(1));
+
+    // Prevent out-of-bounds access.
+    block_size = std::min(block_size, size - offset);
+
+    // Create new buffer with current block of data and feed it to the decoder.
+    std::vector<char> buffer(data_ptr + offset, data_ptr + offset + block_size);
+    int result = decoder.FilterBuf(buffer.data(), buffer.size());
+    if (result < 0)
+      return 0;
+  }
 
   return 0;
 }
diff --git a/net/http/http_chunked_decoder_fuzzer.dict b/net/http/http_chunked_decoder_fuzzer.dict
new file mode 100644
index 0000000..f8552c9c
--- /dev/null
+++ b/net/http/http_chunked_decoder_fuzzer.dict
@@ -0,0 +1,34 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"0"
+"1"
+"2"
+"3"
+"4"
+"5"
+"6"
+"7"
+"8"
+"9"
+"\x0a"
+"\x0d"
+"0x"
+"a"
+"b"
+"c"
+"d"
+"e"
+"f"
+"A"
+"B"
+"C"
+"D"
+"E"
+"F"
+"+"
+"-"
+"="
+":"
+";"
diff --git a/net/proxy/proxy_config_service_linux.cc b/net/proxy/proxy_config_service_linux.cc
index 314bf71b..17747d9 100644
--- a/net/proxy/proxy_config_service_linux.cc
+++ b/net/proxy/proxy_config_service_linux.cc
@@ -41,7 +41,7 @@
 #include "url/url_canon.h"
 
 #if defined(USE_GIO)
-#include "library_loaders/libgio.h"
+#include "library_loaders/libgio.h"  // nogncheck
 #endif  // defined(USE_GIO)
 
 namespace net {
diff --git a/net/proxy/proxy_resolver_v8_tracing.cc b/net/proxy/proxy_resolver_v8_tracing.cc
index dd2fe40..a9fdeeb7 100644
--- a/net/proxy/proxy_resolver_v8_tracing.cc
+++ b/net/proxy/proxy_resolver_v8_tracing.cc
@@ -9,8 +9,10 @@
 #include <utility>
 #include <vector>
 
+#include "base/auto_reset.h"
 #include "base/bind.h"
 #include "base/macros.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/cancellation_flag.h"
@@ -25,6 +27,7 @@
 #include "net/proxy/proxy_info.h"
 #include "net/proxy/proxy_resolver_error_observer.h"
 #include "net/proxy/proxy_resolver_v8.h"
+#include "url/url_canon.h"
 
 // The intent of this class is explained in the design document:
 // https://docs.google.com/a/chromium.org/document/d/16Ij5OcVnR3s0MH4Z5XkhI9VTPoMJdaBn9rKreAmGOdE/edit
@@ -59,6 +62,24 @@
 // hit this. (In fact normal scripts should not even have alerts() or errors).
 const size_t kMaxAlertsAndErrorsBytes = 2048;
 
+// Strips path information from the URL and replaces it with a
+// recognizable placeholder.
+// TODO(eroman): Remove when done gathering data for crbug.com/593759
+GURL StripUrlForBug593759(const GURL& url) {
+  GURL::Replacements replacements;
+  replacements.SetPathStr("PathIsHiddenForCrbug593759");
+  replacements.ClearQuery();
+  replacements.ClearRef();
+  return url.ReplaceComponents(replacements);
+}
+
+// TODO(eroman): Remove when done gathering data for crbug.com/593759
+void LogHistogramForBug593759(PacResultForStrippedUrl value) {
+  UMA_HISTOGRAM_ENUMERATION(
+      kHistogramPacResultForStrippedUrl, static_cast<int>(value),
+      static_cast<int>(PacResultForStrippedUrl::MAX_VALUE));
+}
+
 // The Job class is responsible for executing GetProxyForURL() and
 // creating ProxyResolverV8 instances, since both of these operations share
 // similar code.
@@ -149,6 +170,9 @@
   void ExecuteNonBlocking();
   int ExecuteProxyResolver();
 
+  // TODO(eroman): Remove when done gathering data for crbug.com/593759
+  void LogMetricsForBug593759(int original_error);
+
   // Implementation of ProxyResolverv8::JSBindings
   bool ResolveDns(const std::string& host,
                   ResolveDnsOperation op,
@@ -275,6 +299,9 @@
   // Whether the current execution needs to be restarted in blocking mode.
   bool should_restart_with_blocking_dns_;
 
+  // TODO(eroman): Remove when done gathering data for crbug.com/593759
+  bool dont_start_dns_ = false;
+
   // ---------------------------------------------------------------------------
   // State for pending DNS request.
   // ---------------------------------------------------------------------------
@@ -533,6 +560,9 @@
 
   int result = ExecuteProxyResolver();
 
+  // TODO(eroman): Remove when done gathering data for crbug.com/593759
+  LogMetricsForBug593759(result);
+
   if (should_restart_with_blocking_dns_) {
     DCHECK(!blocking_dns_);
     DCHECK(abandoned_);
@@ -572,6 +602,110 @@
   return result;
 }
 
+// Gathers data on how often PAC scripts execute differently depending
+// on the URL path and parameters.
+//
+// TODO(eroman): Remove when done gathering data for crbug.com/593759
+void Job::LogMetricsForBug593759(int original_error) {
+  CheckIsOnWorkerThread();
+
+  DCHECK(!blocking_dns_);
+
+  if (operation_ != GET_PROXY_FOR_URL || !url_.SchemeIsCryptographic()) {
+    // Only interested in FindProxyForURL() invocations for cryptographic URL
+    // schemes (https:// and wss://).
+    return;
+  }
+
+  if (should_restart_with_blocking_dns_) {
+    // The current instrumentation is limited to non-blocking DNS mode, for
+    // simplicity. Fallback to blocking mode is possible for unusual PAC
+    // scripts (non-deterministic, or relies on global state).
+    LogHistogramForBug593759(
+        PacResultForStrippedUrl::SKIPPED_FALLBACK_BLOCKING_DNS);
+    return;
+  }
+
+  if (abandoned_) {
+    // If the FindProxyForURL() attempt was abandoned, it was either cancelled
+    // or it encountered a missing DNS dependency. In the latter case the job
+    // will be re-started once the DNS has been resolved, so just wait until
+    // then.
+    return;
+  }
+
+  if (original_error != OK) {
+    // Only run the extra diagnostics for successful invocations of
+    // FindProxyForURL(). In other words, the instrumentation will
+    // not check whether the script succeeds when using a stripped
+    // path after having already failed on the original URL. A script error
+    // means the PAC script is already broken, so this would just skew the data.
+    return;
+  }
+
+  // Save some state variables to compare the original run against the new run
+  // using a stripped URL.
+  auto original_num_dns = num_dns_;
+  auto original_alerts_and_errors_byte_cost_ = alerts_and_errors_byte_cost_;
+  auto original_results = results_.ToPacString();
+
+  // Reset state variables used by ExecuteProxyResolver().
+  //
+  // This is a bit messy, but it keeps the diagnostics code local
+  // to LogMetricsForBug593759() without having to refactor the existing
+  // code.
+  //
+  // The intent is that after returning from this function all of the
+  // internal state is re-set to reflect the original completion of
+  // ExecuteProxyResolver(), not the second diagnostic one.
+  //
+  // Any global modifications made to the script state however are
+  // not undone, since creating a new script context just for this
+  // test would be expensive.
+  //
+  // Lastly, DNS resolution is disabled before calling
+  // ExecuteProxyResolver(), so only previously cached results can be
+  // used.
+  base::AutoReset<GURL> reset_url(&url_, StripUrlForBug593759(url_));
+  base::AutoReset<int> reset_num_dns(&num_dns_, 0);
+  base::AutoReset<std::vector<AlertOrError>> reset_alerts_and_errors(
+      &alerts_and_errors_, std::vector<AlertOrError>());
+  base::AutoReset<size_t> reset_alerts_and_errors_byte_cost(
+      &alerts_and_errors_byte_cost_, 0);
+  base::AutoReset<bool> reset_should_restart_with_blocking_dns(
+      &should_restart_with_blocking_dns_, false);
+  base::AutoReset<ProxyInfo> reset_results(&results_, ProxyInfo());
+  base::AutoReset<bool> reset_dont_start_dns(&dont_start_dns_, true);
+  base::AutoReset<bool> reset_abandoned(&abandoned_, false);
+
+  // Re-run FindProxyForURL().
+  auto result = ExecuteProxyResolver();
+
+  // Log the result of having run FindProxyForURL() with the modified
+  // URL to an UMA histogram.
+  if (should_restart_with_blocking_dns_) {
+    LogHistogramForBug593759(
+        PacResultForStrippedUrl::FAIL_FALLBACK_BLOCKING_DNS);
+  } else if (abandoned_) {
+    LogHistogramForBug593759(PacResultForStrippedUrl::FAIL_ABANDONED);
+  } else if (result != OK) {
+    LogHistogramForBug593759(PacResultForStrippedUrl::FAIL_ERROR);
+  } else if (original_results != results_.ToPacString()) {
+    LogHistogramForBug593759(
+        PacResultForStrippedUrl::FAIL_DIFFERENT_PROXY_LIST);
+  } else if (original_alerts_and_errors_byte_cost_ !=
+             alerts_and_errors_byte_cost_) {
+    // Here alerts_and_errors_byte_cost_ is being used as a cheap (albeit
+    // imprecise) fingerprint for the calls that were made to alert().
+    LogHistogramForBug593759(PacResultForStrippedUrl::SUCCESS_DIFFERENT_ALERTS);
+  } else if (original_num_dns != num_dns_) {
+    LogHistogramForBug593759(
+        PacResultForStrippedUrl::SUCCESS_DIFFERENT_NUM_DNS);
+  } else {
+    LogHistogramForBug593759(PacResultForStrippedUrl::SUCCESS);
+  }
+}
+
 bool Job::ResolveDns(const std::string& host,
                      ResolveDnsOperation op,
                      std::string* output,
@@ -646,6 +780,12 @@
     return rv;
   }
 
+  // TODO(eroman): Remove when done gathering data for crbug.com/593759
+  if (dont_start_dns_) {
+    abandoned_ = true;
+    return false;
+  }
+
   if (num_dns_ <= last_num_dns_) {
     // The sequence of DNS operations is different from last time!
     ScheduleRestartWithBlockingDns();
@@ -1099,4 +1239,6 @@
   return make_scoped_ptr(new ProxyResolverV8TracingFactoryImpl());
 }
 
+const char kHistogramPacResultForStrippedUrl[] = "Net.PacResultForStrippedUrl";
+
 }  // namespace net
diff --git a/net/proxy/proxy_resolver_v8_tracing.h b/net/proxy/proxy_resolver_v8_tracing.h
index f5f66cf7..4ca3c82 100644
--- a/net/proxy/proxy_resolver_v8_tracing.h
+++ b/net/proxy/proxy_resolver_v8_tracing.h
@@ -89,6 +89,55 @@
   DISALLOW_COPY_AND_ASSIGN(ProxyResolverV8TracingFactory);
 };
 
+// This enum is used by an UMA histogram, so the values shouldn't be reordered
+// or renumbered.
+//
+// TODO(eroman): Remove when done gathering data for crbug.com/593759
+enum class PacResultForStrippedUrl {
+  // Did NOT measure the impact of running FindProxyForURL() with a modified
+  // URL path, because the original URL could not complete using the
+  // non-blocking DNS mode.
+  SKIPPED_FALLBACK_BLOCKING_DNS = 0,
+
+  // The result of running FindProxyForURL() with a modified URL path appears
+  // to be indistinguishable. (Although there may have been sideffects to the
+  // script state that won't manifest until later invocations).
+  SUCCESS = 1,
+
+  // Calling FindProxyForURL() with a modified URL path returned the same proxy
+  // list, but had measurable sideffects in calls to alert().
+  SUCCESS_DIFFERENT_ALERTS = 2,
+
+  // Calling FindProxyForURL() with a modified URL path returned the same proxy
+  // list, but invoked a different sequence of DNS resolutions. This would
+  // require a rather unusual script to trigger.
+  SUCCESS_DIFFERENT_NUM_DNS = 3,
+
+  // Calling FindProxyForURL() with a modified URL path resulted in a different
+  // set of DNS dependencies.
+  FAIL_ABANDONED = 4,
+
+  // Calling FindProxyForURL() with a modified URL path caused a different
+  // execution flow. Whereas with the original URL it succeeded with
+  // non-blocking DNS, this attempt requires fallback to blocking DNS (and was
+  // not attempted).
+  FAIL_FALLBACK_BLOCKING_DNS = 5,
+
+  // Calling FindProxyForURL() with a modified URL path caused a script error.
+  FAIL_ERROR = 6,
+
+  // Calling FindProxyForURL() with a modified URL path returned a different
+  // proxy list.
+  FAIL_DIFFERENT_PROXY_LIST = 7,
+
+  MAX_VALUE,
+};
+
+// TODO(eroman): Remove when done gathering data for crbug.com/593759
+//
+// This histogram name is exported only for the sake of unit-tests.
+extern NET_EXPORT_PRIVATE const char kHistogramPacResultForStrippedUrl[];
+
 }  // namespace net
 
 #endif  // NET_PROXY_PROXY_RESOLVER_V8_TRACING_H_
diff --git a/net/proxy/proxy_resolver_v8_tracing_unittest.cc b/net/proxy/proxy_resolver_v8_tracing_unittest.cc
index 888dd18..4d2b296 100644
--- a/net/proxy/proxy_resolver_v8_tracing_unittest.cc
+++ b/net/proxy/proxy_resolver_v8_tracing_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/test/histogram_tester.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_checker.h"
 #include "base/values.h"
@@ -37,6 +38,23 @@
     // spilling into the next test's execution.
     base::RunLoop().RunUntilIdle();
   }
+
+ protected:
+  // TODO(eroman): Remove when done gathering data for crbug.com/593759
+  void ExpectHistogramBucketCount(PacResultForStrippedUrl bucket,
+                                  size_t expected_total) {
+    histograms_.ExpectUniqueSample(kHistogramPacResultForStrippedUrl,
+                                   static_cast<int>(bucket), expected_total);
+  }
+
+  // TODO(eroman): Remove when done gathering data for crbug.com/593759
+  void ExpectHistogramTotal(size_t expected_total) {
+    histograms_.ExpectTotalCount(kHistogramPacResultForStrippedUrl,
+                                 expected_total);
+  }
+
+ private:
+  base::HistogramTester histograms_;
 };
 
 scoped_refptr<ProxyResolverScriptData> LoadScriptData(const char* filename) {
@@ -160,12 +178,15 @@
   TestCompletionCallback callback;
   ProxyInfo proxy_info;
 
-  resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+  resolver->GetProxyForURL(GURL("https://foo/"), &proxy_info,
                            callback.callback(), NULL,
                            mock_bindings.CreateBindings());
 
   EXPECT_EQ(OK, callback.WaitForResult());
 
+  ExpectHistogramBucketCount(PacResultForStrippedUrl::SUCCESS, 1);
+  ExpectHistogramTotal(1);
+
   EXPECT_EQ("foo:99", proxy_info.proxy_server().ToURI());
 
   EXPECT_EQ(0u, host_resolver.num_resolve());
@@ -175,6 +196,36 @@
   EXPECT_TRUE(mock_bindings.GetErrors().empty());
 }
 
+TEST_F(ProxyResolverV8TracingTest, AlertUrl) {
+  MockCachingHostResolver host_resolver;
+  MockBindings mock_bindings(&host_resolver);
+
+  scoped_ptr<ProxyResolverV8Tracing> resolver =
+      CreateResolver(mock_bindings.CreateBindings(), "alert_url.js");
+
+  TestCompletionCallback callback;
+  ProxyInfo proxy_info;
+
+  resolver->GetProxyForURL(GURL("https://foo/path"), &proxy_info,
+                           callback.callback(), NULL,
+                           mock_bindings.CreateBindings());
+
+  EXPECT_EQ(OK, callback.WaitForResult());
+
+  ExpectHistogramBucketCount(PacResultForStrippedUrl::SUCCESS_DIFFERENT_ALERTS,
+                             1);
+  ExpectHistogramTotal(1);
+
+  EXPECT_EQ("foobar:99", proxy_info.proxy_server().ToURI());
+
+  EXPECT_EQ(0u, host_resolver.num_resolve());
+
+  // There was 1 alerts and no errors.
+  EXPECT_EQ(1u, mock_bindings.GetAlerts().size());
+  EXPECT_EQ("https://foo/path", mock_bindings.GetAlerts()[0]);
+  EXPECT_TRUE(mock_bindings.GetErrors().empty());
+}
+
 TEST_F(ProxyResolverV8TracingTest, JavascriptError) {
   MockCachingHostResolver host_resolver;
   MockBindings mock_bindings(&host_resolver);
@@ -185,12 +236,14 @@
   TestCompletionCallback callback;
   ProxyInfo proxy_info;
 
-  resolver->GetProxyForURL(GURL("http://throw-an-error/"), &proxy_info,
+  resolver->GetProxyForURL(GURL("https://throw-an-error/"), &proxy_info,
                            callback.callback(), NULL,
                            mock_bindings.CreateBindings());
 
   EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, callback.WaitForResult());
 
+  ExpectHistogramTotal(0);
+
   EXPECT_EQ(0u, host_resolver.num_resolve());
 
   // Check the output -- there was 1 alert and 1 javascript error.
@@ -212,12 +265,16 @@
   TestCompletionCallback callback;
   ProxyInfo proxy_info;
 
-  resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+  resolver->GetProxyForURL(GURL("https://foo/"), &proxy_info,
                            callback.callback(), NULL,
                            mock_bindings.CreateBindings());
 
   EXPECT_EQ(OK, callback.WaitForResult());
 
+  ExpectHistogramBucketCount(
+      PacResultForStrippedUrl::SKIPPED_FALLBACK_BLOCKING_DNS, 1);
+  ExpectHistogramTotal(1);
+
   // Iteration1 does a DNS resolve
   // Iteration2 exceeds the alert buffer
   // Iteration3 runs in blocking mode and completes
@@ -248,12 +305,16 @@
   TestCompletionCallback callback;
   ProxyInfo proxy_info;
 
-  resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+  resolver->GetProxyForURL(GURL("https://foo/"), &proxy_info,
                            callback.callback(), NULL,
                            mock_bindings.CreateBindings());
 
   EXPECT_EQ(OK, callback.WaitForResult());
 
+  ExpectHistogramBucketCount(
+      PacResultForStrippedUrl::SKIPPED_FALLBACK_BLOCKING_DNS, 1);
+  ExpectHistogramTotal(1);
+
   EXPECT_EQ("foo:3", proxy_info.proxy_server().ToURI());
 
   EXPECT_EQ(1u, host_resolver.num_resolve());
@@ -294,12 +355,15 @@
   TestCompletionCallback callback;
   ProxyInfo proxy_info;
 
-  resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+  resolver->GetProxyForURL(GURL("https://foo/"), &proxy_info,
                            callback.callback(), NULL,
                            mock_bindings.CreateBindings());
 
   EXPECT_EQ(OK, callback.WaitForResult());
 
+  ExpectHistogramBucketCount(PacResultForStrippedUrl::SUCCESS, 1);
+  ExpectHistogramTotal(1);
+
   // The test does 13 DNS resolution, however only 7 of them are unique.
   EXPECT_EQ(7u, host_resolver.num_resolve());
 
@@ -346,12 +410,18 @@
   TestCompletionCallback callback2;
   ProxyInfo proxy_info;
 
-  resolver->GetProxyForURL(GURL("http://foopy/req1"), &proxy_info,
+  resolver->GetProxyForURL(GURL("https://foopy/req1"), &proxy_info,
                            callback1.callback(), NULL,
                            mock_bindings.CreateBindings());
 
   EXPECT_EQ(OK, callback1.WaitForResult());
 
+  // This fails because executing FindProxyForURL() PAC script modifies global
+  // state each time, changing the result that is returned.
+  ExpectHistogramBucketCount(PacResultForStrippedUrl::FAIL_DIFFERENT_PROXY_LIST,
+                             1);
+  ExpectHistogramTotal(1);
+
   // The test does 2 DNS resolutions.
   EXPECT_EQ(2u, host_resolver.num_resolve());
 
@@ -364,10 +434,19 @@
 
   EXPECT_EQ(OK, callback2.WaitForResult());
 
+  // The histograms are unchanged because the second invocation is for an
+  // http:// URL.
+  ExpectHistogramBucketCount(PacResultForStrippedUrl::FAIL_DIFFERENT_PROXY_LIST,
+                             1);
+  ExpectHistogramTotal(1);
+
   EXPECT_EQ(4u, host_resolver.num_resolve());
 
   // This time no restarts were required, so g_iteration incremented by 1.
-  EXPECT_EQ("166.155.144.11:4", proxy_info.proxy_server().ToURI());
+  // TODO(eroman): Additionally the counter was incremented once by the
+  // diagnostics code that ran FindProxyForURL() with a stripped URL
+  // (should really be :4 and not :5).
+  EXPECT_EQ("166.155.144.11:5", proxy_info.proxy_server().ToURI());
 
   // There were no alerts or errors.
   EXPECT_TRUE(mock_bindings.GetAlerts().empty());
@@ -391,11 +470,15 @@
   TestCompletionCallback callback;
   ProxyInfo proxy_info;
 
-  resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+  resolver->GetProxyForURL(GURL("https://foo/"), &proxy_info,
                            callback.callback(), NULL,
                            mock_bindings.CreateBindings());
   EXPECT_EQ(OK, callback.WaitForResult());
 
+  ExpectHistogramBucketCount(
+      PacResultForStrippedUrl::SKIPPED_FALLBACK_BLOCKING_DNS, 1);
+  ExpectHistogramTotal(1);
+
   // The script itself only does 2 DNS resolves per execution, however it
   // constructs the hostname using a global counter which changes on each
   // invocation.
@@ -430,11 +513,15 @@
   TestCompletionCallback callback;
   ProxyInfo proxy_info;
 
-  resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+  resolver->GetProxyForURL(GURL("https://foo/"), &proxy_info,
                            callback.callback(), NULL,
                            mock_bindings.CreateBindings());
   EXPECT_EQ(OK, callback.WaitForResult());
 
+  ExpectHistogramBucketCount(
+      PacResultForStrippedUrl::SKIPPED_FALLBACK_BLOCKING_DNS, 1);
+  ExpectHistogramTotal(1);
+
   EXPECT_EQ(3u, host_resolver.num_resolve());
 
   EXPECT_EQ("166.155.144.44:100", proxy_info.proxy_server().ToURI());
@@ -466,6 +553,9 @@
                            mock_bindings.CreateBindings());
   EXPECT_EQ(OK, callback.WaitForResult());
 
+  // Was not called because this is an http:// URL.
+  ExpectHistogramTotal(0);
+
   EXPECT_EQ(20u, host_resolver.num_resolve());
 
   EXPECT_EQ(
@@ -506,6 +596,9 @@
                            mock_bindings.CreateBindings());
   EXPECT_EQ(OK, callback.WaitForResult());
 
+  // Was not called because this is an http:// URL.
+  ExpectHistogramTotal(0);
+
   EXPECT_EQ(20u, host_resolver.num_resolve());
 
   EXPECT_EQ("null21:34", proxy_info.proxy_server().ToURI());
@@ -518,6 +611,94 @@
   EXPECT_EQ("iteration: 21", mock_bindings.GetAlerts()[0]);
 }
 
+TEST_F(ProxyResolverV8TracingTest, DifferentResultBasedOnUrl) {
+  MockCachingHostResolver host_resolver;
+  MockBindings mock_bindings(&host_resolver);
+
+  scoped_ptr<ProxyResolverV8Tracing> resolver =
+      CreateResolver(mock_bindings.CreateBindings(), "return_url_as_proxy.js");
+
+  TestCompletionCallback callback;
+  ProxyInfo proxy_info;
+
+  resolver->GetProxyForURL(GURL("https://foo/path1"), &proxy_info,
+                           callback.callback(), NULL,
+                           mock_bindings.CreateBindings());
+
+  EXPECT_EQ(OK, callback.WaitForResult());
+
+  ExpectHistogramTotal(1);
+  ExpectHistogramBucketCount(PacResultForStrippedUrl::FAIL_DIFFERENT_PROXY_LIST,
+                             1);
+
+  EXPECT_EQ("httpsx3Ax2Fx2Ffoox2Fpath1:99", proxy_info.proxy_server().ToURI());
+
+  EXPECT_EQ(0u, host_resolver.num_resolve());
+
+  // There were no alerts or errors.
+  EXPECT_TRUE(mock_bindings.GetAlerts().empty());
+  EXPECT_TRUE(mock_bindings.GetErrors().empty());
+}
+
+TEST_F(ProxyResolverV8TracingTest, ErrorDependingOnUrl) {
+  MockCachingHostResolver host_resolver;
+  MockBindings mock_bindings(&host_resolver);
+
+  scoped_ptr<ProxyResolverV8Tracing> resolver = CreateResolver(
+      mock_bindings.CreateBindings(), "error_depending_on_url.js");
+
+  TestCompletionCallback callback;
+  ProxyInfo proxy_info;
+
+  resolver->GetProxyForURL(GURL("https://foo/DontThrowError"), &proxy_info,
+                           callback.callback(), NULL,
+                           mock_bindings.CreateBindings());
+
+  EXPECT_EQ(OK, callback.WaitForResult());
+
+  ExpectHistogramTotal(1);
+  ExpectHistogramBucketCount(PacResultForStrippedUrl::FAIL_ERROR, 1);
+
+  EXPECT_EQ("foopy:42", proxy_info.proxy_server().ToURI());
+
+  EXPECT_EQ(0u, host_resolver.num_resolve());
+
+  // There were no alerts or errors.
+  EXPECT_TRUE(mock_bindings.GetAlerts().empty());
+  EXPECT_TRUE(mock_bindings.GetErrors().empty());
+}
+
+TEST_F(ProxyResolverV8TracingTest, DnsDependingOnUrl) {
+  MockCachingHostResolver host_resolver;
+  MockBindings mock_bindings(&host_resolver);
+
+  host_resolver.rules()->AddRule("host", "166.155.144.55");
+
+  // Catch-all that will be used for myIpAddress().
+  host_resolver.rules()->AddRule("*", "133.122.100.200");
+
+  scoped_ptr<ProxyResolverV8Tracing> resolver =
+      CreateResolver(mock_bindings.CreateBindings(), "dns_depending_on_url.js");
+
+  TestCompletionCallback callback;
+  ProxyInfo proxy_info;
+
+  resolver->GetProxyForURL(GURL("https://foo/UseMyIpAddress"), &proxy_info,
+                           callback.callback(), NULL,
+                           mock_bindings.CreateBindings());
+
+  EXPECT_EQ(OK, callback.WaitForResult());
+
+  ExpectHistogramBucketCount(PacResultForStrippedUrl::FAIL_ABANDONED, 1);
+  ExpectHistogramTotal(1);
+
+  EXPECT_EQ("foopy:47", proxy_info.proxy_server().ToURI());
+
+  // No errors.
+  EXPECT_TRUE(mock_bindings.GetErrors().empty());
+  ASSERT_EQ(0u, mock_bindings.GetAlerts().size());
+}
+
 void DnsDuringInitHelper(bool synchronous_host_resolver) {
   MockCachingHostResolver host_resolver;
   MockBindings mock_bindings(&host_resolver);
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index 027b46ed..e3d0a36 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -969,9 +969,8 @@
 
     nss_waiting_read_ = true;
     bool posted = nss_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(IgnoreResult(&Core::Read), this, make_scoped_refptr(buf),
-                   buf_len, callback));
+        FROM_HERE, base::Bind(IgnoreResult(&Core::Read), this,
+                              base::RetainedRef(buf), buf_len, callback));
     if (!posted) {
       nss_is_closed_ = true;
       nss_waiting_read_ = false;
@@ -1026,9 +1025,8 @@
 
     nss_waiting_write_ = true;
     bool posted = nss_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(IgnoreResult(&Core::Write), this, make_scoped_refptr(buf),
-                   buf_len, callback));
+        FROM_HERE, base::Bind(IgnoreResult(&Core::Write), this,
+                              base::RetainedRef(buf), buf_len, callback));
     if (!posted) {
       nss_is_closed_ = true;
       nss_waiting_write_ = false;
@@ -1536,11 +1534,10 @@
     pending_read_nss_error_ = 0;
 
     if (rv == 0) {
-      PostOrRunCallback(
-          FROM_HERE,
-          base::Bind(&LogByteTransferEvent, weak_net_log_,
-                     NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
-                     scoped_refptr<IOBuffer>(user_read_buf_)));
+      PostOrRunCallback(FROM_HERE,
+                        base::Bind(&LogByteTransferEvent, weak_net_log_,
+                                   NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
+                                   base::RetainedRef(user_read_buf_)));
     } else {
       PostOrRunCallback(
           FROM_HERE,
@@ -1621,11 +1618,10 @@
   DCHECK_NE(ERR_IO_PENDING, pending_read_result_);
 
   if (rv >= 0) {
-    PostOrRunCallback(
-        FROM_HERE,
-        base::Bind(&LogByteTransferEvent, weak_net_log_,
-                   NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
-                   scoped_refptr<IOBuffer>(user_read_buf_)));
+    PostOrRunCallback(FROM_HERE,
+                      base::Bind(&LogByteTransferEvent, weak_net_log_,
+                                 NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
+                                 base::RetainedRef(user_read_buf_)));
   } else if (rv != ERR_IO_PENDING) {
     PostOrRunCallback(
         FROM_HERE,
@@ -1654,11 +1650,10 @@
         base::Bind(&Core::OnNSSBufferUpdated, this, new_amount_in_read_buffer));
   }
   if (rv >= 0) {
-    PostOrRunCallback(
-        FROM_HERE,
-        base::Bind(&LogByteTransferEvent, weak_net_log_,
-                   NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv,
-                   scoped_refptr<IOBuffer>(user_write_buf_)));
+    PostOrRunCallback(FROM_HERE,
+                      base::Bind(&LogByteTransferEvent, weak_net_log_,
+                                 NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv,
+                                 base::RetainedRef(user_write_buf_)));
     return rv;
   }
   PRErrorCode prerr = PR_GetError();
@@ -1725,9 +1720,8 @@
       rv = DoBufferRecv(read_buffer.get(), nb);
     } else {
       bool posted = network_task_runner_->PostTask(
-          FROM_HERE,
-          base::Bind(IgnoreResult(&Core::DoBufferRecv), this, read_buffer,
-                     nb));
+          FROM_HERE, base::Bind(IgnoreResult(&Core::DoBufferRecv), this,
+                                base::RetainedRef(read_buffer), nb));
       rv = posted ? ERR_IO_PENDING : ERR_ABORTED;
     }
 
@@ -1775,9 +1769,8 @@
       rv = DoBufferSend(send_buffer.get(), len);
     } else {
       bool posted = network_task_runner_->PostTask(
-          FROM_HERE,
-          base::Bind(IgnoreResult(&Core::DoBufferSend), this, send_buffer,
-                     len));
+          FROM_HERE, base::Bind(IgnoreResult(&Core::DoBufferSend), this,
+                                base::RetainedRef(send_buffer), len));
       rv = posted ? ERR_IO_PENDING : ERR_ABORTED;
     }
 
@@ -1983,7 +1976,7 @@
     // own a reference to the certificate.
     NetLog::ParametersCallback net_log_callback =
         base::Bind(&NetLogX509CertificateCallback,
-                   nss_handshake_state_.server_cert);
+                   base::RetainedRef(nss_handshake_state_.server_cert));
     PostOrRunCallback(
         FROM_HERE,
         base::Bind(&AddLogEventWithCallback, weak_net_log_,
@@ -2164,12 +2157,12 @@
   int rv = transport_->socket()->Read(
       read_buffer, len,
       base::Bind(&Core::BufferRecvComplete, base::Unretained(this),
-                 scoped_refptr<IOBuffer>(read_buffer)));
+                 base::RetainedRef(read_buffer)));
 
   if (!OnNSSTaskRunner() && rv != ERR_IO_PENDING) {
-    nss_task_runner_->PostTask(
-        FROM_HERE, base::Bind(&Core::BufferRecvComplete, this,
-                              scoped_refptr<IOBuffer>(read_buffer), rv));
+    nss_task_runner_->PostTask(FROM_HERE,
+                               base::Bind(&Core::BufferRecvComplete, this,
+                                          base::RetainedRef(read_buffer), rv));
     return rv;
   }
 
@@ -2306,7 +2299,7 @@
 
     nss_task_runner_->PostTask(
         FROM_HERE, base::Bind(&Core::BufferRecvComplete, this,
-                              scoped_refptr<IOBuffer>(read_buffer), result));
+                              base::RetainedRef(read_buffer), result));
     return;
   }
 
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 6946575f..add9ed154 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -66,9 +66,10 @@
          method == "TRACE";
 }
 
-void LogChannelIDAndCookieStores(const net::URLRequestContext* context,
+void LogChannelIDAndCookieStores(const GURL& url,
+                                 const net::URLRequestContext* context,
                                  const net::SSLInfo& ssl_info) {
-  if (!ssl_info.channel_id_sent)
+  if (url.host() != "accounts.google.com" || !ssl_info.channel_id_sent)
     return;
   // This enum is used for an UMA histogram - don't reuse or renumber entries.
   enum {
@@ -1016,7 +1017,7 @@
         return;
       }
     }
-    LogChannelIDAndCookieStores(request_->context(),
+    LogChannelIDAndCookieStores(request_->url(), request_->context(),
                                 transaction_->GetResponseInfo()->ssl_info);
 
     SaveCookiesAndNotifyHeadersComplete(OK);
diff --git a/ppapi/generators/idl_thunk.py b/ppapi/generators/idl_thunk.py
index 5df8e6b..75117d2d9 100755
--- a/ppapi/generators/idl_thunk.py
+++ b/ppapi/generators/idl_thunk.py
@@ -455,6 +455,7 @@
         filenode.GetProperty('DATETIME'))
     out.Write('// %s %s\n\n' % (from_text, modified_text))
 
+    meta.AddBuiltinInclude('stdint.h')
     if meta.BuiltinIncludes():
       for include in sorted(meta.BuiltinIncludes()):
         out.Write('#include <%s>\n' % include)
diff --git a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
index cbe04ba..e80c35c 100644
--- a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
+++ b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015 The Chromium Authors. All rights reserved.
+/* Copyright (c) 2016 The Chromium Authors. All rights reserved.
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
@@ -10,6 +10,7 @@
 #include "ppapi/c/dev/ppb_audio_input_dev.h"
 #include "ppapi/c/dev/ppb_device_ref_dev.h"
 #include "ppapi/c/dev/ppb_file_chooser_dev.h"
+#include "ppapi/c/dev/ppb_font_dev.h"
 #include "ppapi/c/dev/ppb_ime_input_event_dev.h"
 #include "ppapi/c/dev/ppb_printing_dev.h"
 #include "ppapi/c/dev/ppb_truetype_font_dev.h"
@@ -156,6 +157,7 @@
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_DeviceRef_Dev_0_1;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_FileChooser_Dev_0_5;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_FileChooser_Dev_0_6;
+static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Font_Dev_0_6;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_IMEInputEvent_Dev_0_1;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_IMEInputEvent_Dev_0_2;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Printing_Dev_0_7;
@@ -2733,6 +2735,50 @@
 
 /* End wrapper methods for PPB_FileChooser_Dev_0_6 */
 
+/* Begin wrapper methods for PPB_Font_Dev_0_6 */
+
+static void Pnacl_M14_PPB_Font_Dev_GetFontFamilies(struct PP_Var* _struct_result, PP_Instance instance) {
+  const struct PPB_Font_Dev_0_6 *iface = Pnacl_WrapperInfo_PPB_Font_Dev_0_6.real_iface;
+  *_struct_result = iface->GetFontFamilies(instance);
+}
+
+static PP_Resource Pnacl_M14_PPB_Font_Dev_Create(PP_Instance instance, const struct PP_FontDescription_Dev* description) {
+  const struct PPB_Font_Dev_0_6 *iface = Pnacl_WrapperInfo_PPB_Font_Dev_0_6.real_iface;
+  return iface->Create(instance, description);
+}
+
+static PP_Bool Pnacl_M14_PPB_Font_Dev_IsFont(PP_Resource resource) {
+  const struct PPB_Font_Dev_0_6 *iface = Pnacl_WrapperInfo_PPB_Font_Dev_0_6.real_iface;
+  return iface->IsFont(resource);
+}
+
+static PP_Bool Pnacl_M14_PPB_Font_Dev_Describe(PP_Resource font, struct PP_FontDescription_Dev* description, struct PP_FontMetrics_Dev* metrics) {
+  const struct PPB_Font_Dev_0_6 *iface = Pnacl_WrapperInfo_PPB_Font_Dev_0_6.real_iface;
+  return iface->Describe(font, description, metrics);
+}
+
+static PP_Bool Pnacl_M14_PPB_Font_Dev_DrawTextAt(PP_Resource font, PP_Resource image_data, const struct PP_TextRun_Dev* text, const struct PP_Point* position, uint32_t color, const struct PP_Rect* clip, PP_Bool image_data_is_opaque) {
+  const struct PPB_Font_Dev_0_6 *iface = Pnacl_WrapperInfo_PPB_Font_Dev_0_6.real_iface;
+  return iface->DrawTextAt(font, image_data, text, position, color, clip, image_data_is_opaque);
+}
+
+static int32_t Pnacl_M14_PPB_Font_Dev_MeasureText(PP_Resource font, const struct PP_TextRun_Dev* text) {
+  const struct PPB_Font_Dev_0_6 *iface = Pnacl_WrapperInfo_PPB_Font_Dev_0_6.real_iface;
+  return iface->MeasureText(font, text);
+}
+
+static uint32_t Pnacl_M14_PPB_Font_Dev_CharacterOffsetForPixel(PP_Resource font, const struct PP_TextRun_Dev* text, int32_t pixel_position) {
+  const struct PPB_Font_Dev_0_6 *iface = Pnacl_WrapperInfo_PPB_Font_Dev_0_6.real_iface;
+  return iface->CharacterOffsetForPixel(font, text, pixel_position);
+}
+
+static int32_t Pnacl_M14_PPB_Font_Dev_PixelOffsetForCharacter(PP_Resource font, const struct PP_TextRun_Dev* text, uint32_t char_offset) {
+  const struct PPB_Font_Dev_0_6 *iface = Pnacl_WrapperInfo_PPB_Font_Dev_0_6.real_iface;
+  return iface->PixelOffsetForCharacter(font, text, char_offset);
+}
+
+/* End wrapper methods for PPB_Font_Dev_0_6 */
+
 /* Begin wrapper methods for PPB_IMEInputEvent_Dev_0_1 */
 
 static PP_Bool Pnacl_M16_PPB_IMEInputEvent_Dev_IsIMEInputEvent(PP_Resource resource) {
@@ -3684,6 +3730,8 @@
 
 /* Not generating wrapper methods for PPB_Flash_FontFile_0_1 */
 
+/* Not generating wrapper methods for PPB_Flash_FontFile_0_2 */
+
 /* Not generating wrapper methods for PPB_FlashFullscreen_0_1 */
 
 /* Not generating wrapper methods for PPB_FlashFullscreen_1_0 */
@@ -5324,6 +5372,17 @@
     .Show = (int32_t (*)(PP_Resource chooser, struct PP_ArrayOutput output, struct PP_CompletionCallback callback))&Pnacl_M19_PPB_FileChooser_Dev_Show
 };
 
+static const struct PPB_Font_Dev_0_6 Pnacl_Wrappers_PPB_Font_Dev_0_6 = {
+    .GetFontFamilies = (struct PP_Var (*)(PP_Instance instance))&Pnacl_M14_PPB_Font_Dev_GetFontFamilies,
+    .Create = (PP_Resource (*)(PP_Instance instance, const struct PP_FontDescription_Dev* description))&Pnacl_M14_PPB_Font_Dev_Create,
+    .IsFont = (PP_Bool (*)(PP_Resource resource))&Pnacl_M14_PPB_Font_Dev_IsFont,
+    .Describe = (PP_Bool (*)(PP_Resource font, struct PP_FontDescription_Dev* description, struct PP_FontMetrics_Dev* metrics))&Pnacl_M14_PPB_Font_Dev_Describe,
+    .DrawTextAt = (PP_Bool (*)(PP_Resource font, PP_Resource image_data, const struct PP_TextRun_Dev* text, const struct PP_Point* position, uint32_t color, const struct PP_Rect* clip, PP_Bool image_data_is_opaque))&Pnacl_M14_PPB_Font_Dev_DrawTextAt,
+    .MeasureText = (int32_t (*)(PP_Resource font, const struct PP_TextRun_Dev* text))&Pnacl_M14_PPB_Font_Dev_MeasureText,
+    .CharacterOffsetForPixel = (uint32_t (*)(PP_Resource font, const struct PP_TextRun_Dev* text, int32_t pixel_position))&Pnacl_M14_PPB_Font_Dev_CharacterOffsetForPixel,
+    .PixelOffsetForCharacter = (int32_t (*)(PP_Resource font, const struct PP_TextRun_Dev* text, uint32_t char_offset))&Pnacl_M14_PPB_Font_Dev_PixelOffsetForCharacter
+};
+
 static const struct PPB_IMEInputEvent_Dev_0_1 Pnacl_Wrappers_PPB_IMEInputEvent_Dev_0_1 = {
     .IsIMEInputEvent = (PP_Bool (*)(PP_Resource resource))&Pnacl_M16_PPB_IMEInputEvent_Dev_IsIMEInputEvent,
     .GetText = (struct PP_Var (*)(PP_Resource ime_event))&Pnacl_M16_PPB_IMEInputEvent_Dev_GetText,
@@ -5591,6 +5650,8 @@
 
 /* Not generating wrapper interface for PPB_Flash_FontFile_0_1 */
 
+/* Not generating wrapper interface for PPB_Flash_FontFile_0_2 */
+
 /* Not generating wrapper interface for PPB_FlashFullscreen_0_1 */
 
 /* Not generating wrapper interface for PPB_FlashFullscreen_1_0 */
@@ -6217,6 +6278,12 @@
   .real_iface = NULL
 };
 
+static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Font_Dev_0_6 = {
+  .iface_macro = PPB_FONT_DEV_INTERFACE_0_6,
+  .wrapped_iface = (const void *) &Pnacl_Wrappers_PPB_Font_Dev_0_6,
+  .real_iface = NULL
+};
+
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_IMEInputEvent_Dev_0_1 = {
   .iface_macro = PPB_IME_INPUT_EVENT_DEV_INTERFACE_0_1,
   .wrapped_iface = (const void *) &Pnacl_Wrappers_PPB_IMEInputEvent_Dev_0_1,
@@ -6568,6 +6635,7 @@
   &Pnacl_WrapperInfo_PPB_DeviceRef_Dev_0_1,
   &Pnacl_WrapperInfo_PPB_FileChooser_Dev_0_5,
   &Pnacl_WrapperInfo_PPB_FileChooser_Dev_0_6,
+  &Pnacl_WrapperInfo_PPB_Font_Dev_0_6,
   &Pnacl_WrapperInfo_PPB_IMEInputEvent_Dev_0_1,
   &Pnacl_WrapperInfo_PPB_IMEInputEvent_Dev_0_2,
   &Pnacl_WrapperInfo_PPB_Printing_Dev_0_7,
diff --git a/ppapi/thunk/ppb_audio_buffer_thunk.cc b/ppapi/thunk/ppb_audio_buffer_thunk.cc
index 75e0f80..1d84d3b 100644
--- a/ppapi/thunk/ppb_audio_buffer_thunk.cc
+++ b/ppapi/thunk/ppb_audio_buffer_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_audio_buffer.idl modified Thu May 15 17:11:43 2014.
+// From ppb_audio_buffer.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -88,15 +88,10 @@
   return enter.object()->GetDataBufferSize();
 }
 
-const PPB_AudioBuffer_0_1 g_ppb_audiobuffer_thunk_0_1 = {&IsAudioBuffer,
-                                                         &GetTimestamp,
-                                                         &SetTimestamp,
-                                                         &GetSampleRate,
-                                                         &GetSampleSize,
-                                                         &GetNumberOfChannels,
-                                                         &GetNumberOfSamples,
-                                                         &GetDataBuffer,
-                                                         &GetDataBufferSize};
+const PPB_AudioBuffer_0_1 g_ppb_audiobuffer_thunk_0_1 = {
+    &IsAudioBuffer,      &GetTimestamp,  &SetTimestamp,
+    &GetSampleRate,      &GetSampleSize, &GetNumberOfChannels,
+    &GetNumberOfSamples, &GetDataBuffer, &GetDataBufferSize};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_audio_encoder_thunk.cc b/ppapi/thunk/ppb_audio_encoder_thunk.cc
index f8355bb8..89d4b8c4 100644
--- a/ppapi/thunk/ppb_audio_encoder_thunk.cc
+++ b/ppapi/thunk/ppb_audio_encoder_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_audio_encoder.idl modified Mon Sep  7 10:17:53 2015.
+// From ppb_audio_encoder.idl modified Wed Jan 27 17:39:22 2016.
 
 #include <stdint.h>
 
@@ -56,13 +56,9 @@
   EnterResource<PPB_AudioEncoder_API> enter(audio_encoder, callback, true);
   if (enter.failed())
     return enter.retval();
-  return enter.SetResult(enter.object()->Initialize(channels,
-                                                    input_sample_rate,
-                                                    input_sample_size,
-                                                    output_profile,
-                                                    initial_bitrate,
-                                                    acceleration,
-                                                    enter.callback()));
+  return enter.SetResult(enter.object()->Initialize(
+      channels, input_sample_rate, input_sample_size, output_profile,
+      initial_bitrate, acceleration, enter.callback()));
 }
 
 int32_t GetNumberOfSamples(PP_Resource audio_encoder) {
diff --git a/ppapi/thunk/ppb_camera_capabilities_private_thunk.cc b/ppapi/thunk/ppb_camera_capabilities_private_thunk.cc
index 3bfdd4c..7f76c5b 100644
--- a/ppapi/thunk/ppb_camera_capabilities_private_thunk.cc
+++ b/ppapi/thunk/ppb_camera_capabilities_private_thunk.cc
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From private/ppb_camera_capabilities_private.idl modified Thu Feb 19 09:06:18
-// 2015.
+// From private/ppb_camera_capabilities_private.idl modified Wed Jan 27 17:10:16
+// 2016.
 
 #include <stdint.h>
 
@@ -38,8 +38,7 @@
 
 const PPB_CameraCapabilities_Private_0_1
     g_ppb_cameracapabilities_private_thunk_0_1 = {
-        &IsCameraCapabilities,
-        &GetSupportedVideoCaptureFormats};
+        &IsCameraCapabilities, &GetSupportedVideoCaptureFormats};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_camera_device_private_thunk.cc b/ppapi/thunk/ppb_camera_device_private_thunk.cc
index 207d92f..b33df8be 100644
--- a/ppapi/thunk/ppb_camera_device_private_thunk.cc
+++ b/ppapi/thunk/ppb_camera_device_private_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From private/ppb_camera_device_private.idl modified Wed Feb 18 16:44:52 2015.
+// From private/ppb_camera_device_private.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -62,8 +62,8 @@
       enter.object()->GetCameraCapabilities(capabilities, enter.callback()));
 }
 
-const PPB_CameraDevice_Private_0_1 g_ppb_cameradevice_private_thunk_0_1 =
-    {&Create, &IsCameraDevice, &Open, &Close, &GetCameraCapabilities};
+const PPB_CameraDevice_Private_0_1 g_ppb_cameradevice_private_thunk_0_1 = {
+    &Create, &IsCameraDevice, &Open, &Close, &GetCameraCapabilities};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_compositor_layer_thunk.cc b/ppapi/thunk/ppb_compositor_layer_thunk.cc
index 32d966c..29645403 100644
--- a/ppapi/thunk/ppb_compositor_layer_thunk.cc
+++ b/ppapi/thunk/ppb_compositor_layer_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_compositor_layer.idl modified Thu Jan 29 16:28:15 2015.
+// From ppb_compositor_layer.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -126,28 +126,18 @@
 }
 
 const PPB_CompositorLayer_0_1 g_ppb_compositorlayer_thunk_0_1 = {
-    &IsCompositorLayer,
-    &SetColor,
-    &SetTexture_0_1,
-    &SetImage,
-    &SetClipRect,
-    &SetTransform,
-    &SetOpacity,
-    &SetBlendMode,
-    &SetSourceRect,
-    &SetPremultipliedAlpha};
+    &IsCompositorLayer, &SetColor,
+    &SetTexture_0_1,    &SetImage,
+    &SetClipRect,       &SetTransform,
+    &SetOpacity,        &SetBlendMode,
+    &SetSourceRect,     &SetPremultipliedAlpha};
 
 const PPB_CompositorLayer_0_2 g_ppb_compositorlayer_thunk_0_2 = {
-    &IsCompositorLayer,
-    &SetColor,
-    &SetTexture,
-    &SetImage,
-    &SetClipRect,
-    &SetTransform,
-    &SetOpacity,
-    &SetBlendMode,
-    &SetSourceRect,
-    &SetPremultipliedAlpha};
+    &IsCompositorLayer, &SetColor,
+    &SetTexture,        &SetImage,
+    &SetClipRect,       &SetTransform,
+    &SetOpacity,        &SetBlendMode,
+    &SetSourceRect,     &SetPremultipliedAlpha};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_compositor_thunk.cc b/ppapi/thunk/ppb_compositor_thunk.cc
index b640787..f1593c3 100644
--- a/ppapi/thunk/ppb_compositor_thunk.cc
+++ b/ppapi/thunk/ppb_compositor_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_compositor.idl modified Thu Sep 18 11:36:39 2014.
+// From ppb_compositor.idl modified Wed Jan 27 17:39:22 2016.
 
 #include <stdint.h>
 
@@ -57,11 +57,8 @@
   return enter.object()->ResetLayers();
 }
 
-const PPB_Compositor_0_1 g_ppb_compositor_thunk_0_1 = {&IsCompositor,
-                                                       &Create,
-                                                       &AddLayer,
-                                                       &CommitLayers,
-                                                       &ResetLayers};
+const PPB_Compositor_0_1 g_ppb_compositor_thunk_0_1 = {
+    &IsCompositor, &Create, &AddLayer, &CommitLayers, &ResetLayers};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_console_thunk.cc b/ppapi/thunk/ppb_console_thunk.cc
index 3bde49a..5c9d5f86 100644
--- a/ppapi/thunk/ppb_console_thunk.cc
+++ b/ppapi/thunk/ppb_console_thunk.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_console.idl modified Mon May  6 10:11:29 2013.
+// From ppb_console.idl modified Wed Jan 27 17:10:16 2016.
+
+#include <stdint.h>
 
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/ppb_console.h"
diff --git a/ppapi/thunk/ppb_device_ref_dev_thunk.cc b/ppapi/thunk/ppb_device_ref_dev_thunk.cc
index 25a5bb4..fc357d5 100644
--- a/ppapi/thunk/ppb_device_ref_dev_thunk.cc
+++ b/ppapi/thunk/ppb_device_ref_dev_thunk.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From dev/ppb_device_ref_dev.idl modified Mon May  6 10:11:29 2013.
+// From dev/ppb_device_ref_dev.idl modified Wed Jan 27 17:10:16 2016.
+
+#include <stdint.h>
 
 #include "ppapi/c/dev/ppb_device_ref_dev.h"
 #include "ppapi/c/pp_errors.h"
@@ -38,9 +40,8 @@
   return enter.object()->GetName();
 }
 
-const PPB_DeviceRef_Dev_0_1 g_ppb_deviceref_dev_thunk_0_1 = {&IsDeviceRef,
-                                                             &GetType,
-                                                             &GetName};
+const PPB_DeviceRef_Dev_0_1 g_ppb_deviceref_dev_thunk_0_1 = {
+    &IsDeviceRef, &GetType, &GetName};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_display_color_profile_private_thunk.cc b/ppapi/thunk/ppb_display_color_profile_private_thunk.cc
index 96f398e..51c5d76 100644
--- a/ppapi/thunk/ppb_display_color_profile_private_thunk.cc
+++ b/ppapi/thunk/ppb_display_color_profile_private_thunk.cc
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From private/ppb_display_color_profile_private.idl modified Mon Apr  7
-// 08:56:43 2014.
+// From private/ppb_display_color_profile_private.idl modified Wed Jan 27
+// 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -61,9 +61,7 @@
 
 const PPB_DisplayColorProfile_Private_0_1
     g_ppb_displaycolorprofile_private_thunk_0_1 = {
-        &Create,
-        &IsDisplayColorProfile,
-        &GetColorProfile,
+        &Create, &IsDisplayColorProfile, &GetColorProfile,
         &RegisterColorProfileChangeCallback};
 
 }  // namespace
diff --git a/ppapi/thunk/ppb_file_chooser_dev_thunk.cc b/ppapi/thunk/ppb_file_chooser_dev_thunk.cc
index 88594df..8880de9 100644
--- a/ppapi/thunk/ppb_file_chooser_dev_thunk.cc
+++ b/ppapi/thunk/ppb_file_chooser_dev_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From dev/ppb_file_chooser_dev.idl modified Fri Feb  7 08:29:41 2014.
+// From dev/ppb_file_chooser_dev.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -61,12 +61,11 @@
   return enter.SetResult(enter.object()->Show(output, enter.callback()));
 }
 
-const PPB_FileChooser_Dev_0_5 g_ppb_filechooser_dev_thunk_0_5 =
-    {&Create, &IsFileChooser, &Show_0_5, &GetNextChosenFile};
+const PPB_FileChooser_Dev_0_5 g_ppb_filechooser_dev_thunk_0_5 = {
+    &Create, &IsFileChooser, &Show_0_5, &GetNextChosenFile};
 
-const PPB_FileChooser_Dev_0_6 g_ppb_filechooser_dev_thunk_0_6 = {&Create,
-                                                                 &IsFileChooser,
-                                                                 &Show};
+const PPB_FileChooser_Dev_0_6 g_ppb_filechooser_dev_thunk_0_6 = {
+    &Create, &IsFileChooser, &Show};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_file_io_thunk.cc b/ppapi/thunk/ppb_file_io_thunk.cc
index 6c23a2f..99b8d3f1 100644
--- a/ppapi/thunk/ppb_file_io_thunk.cc
+++ b/ppapi/thunk/ppb_file_io_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_file_io.idl modified Mon Nov 11 16:02:07 2013.
+// From ppb_file_io.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -132,28 +132,13 @@
                                                      output, enter.callback()));
 }
 
-const PPB_FileIO_1_0 g_ppb_fileio_thunk_1_0 = {&Create,
-                                               &IsFileIO,
-                                               &Open,
-                                               &Query,
-                                               &Touch,
-                                               &Read,
-                                               &Write,
-                                               &SetLength,
-                                               &Flush,
-                                               &Close};
+const PPB_FileIO_1_0 g_ppb_fileio_thunk_1_0 = {
+    &Create, &IsFileIO, &Open,      &Query, &Touch,
+    &Read,   &Write,    &SetLength, &Flush, &Close};
 
-const PPB_FileIO_1_1 g_ppb_fileio_thunk_1_1 = {&Create,
-                                               &IsFileIO,
-                                               &Open,
-                                               &Query,
-                                               &Touch,
-                                               &Read,
-                                               &Write,
-                                               &SetLength,
-                                               &Flush,
-                                               &Close,
-                                               &ReadToArray};
+const PPB_FileIO_1_1 g_ppb_fileio_thunk_1_1 = {
+    &Create, &IsFileIO,  &Open,  &Query, &Touch,      &Read,
+    &Write,  &SetLength, &Flush, &Close, &ReadToArray};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_file_system_thunk.cc b/ppapi/thunk/ppb_file_system_thunk.cc
index e8b5ff0..45709ca 100644
--- a/ppapi/thunk/ppb_file_system_thunk.cc
+++ b/ppapi/thunk/ppb_file_system_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_file_system.idl modified Wed May 15 13:57:07 2013.
+// From ppb_file_system.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -51,10 +51,8 @@
   return enter.object()->GetType();
 }
 
-const PPB_FileSystem_1_0 g_ppb_filesystem_thunk_1_0 = {&Create,
-                                                       &IsFileSystem,
-                                                       &Open,
-                                                       &GetType};
+const PPB_FileSystem_1_0 g_ppb_filesystem_thunk_1_0 = {&Create, &IsFileSystem,
+                                                       &Open, &GetType};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_find_private_thunk.cc b/ppapi/thunk/ppb_find_private_thunk.cc
index 0766b84f..b2a6893 100644
--- a/ppapi/thunk/ppb_find_private_thunk.cc
+++ b/ppapi/thunk/ppb_find_private_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From private/ppb_find_private.idl modified Mon Apr  7 08:56:43 2014.
+// From private/ppb_find_private.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -54,10 +54,8 @@
 }
 
 const PPB_Find_Private_0_3 g_ppb_find_private_thunk_0_3 = {
-    &SetPluginToHandleFindRequests,
-    &NumberOfFindResultsChanged,
-    &SelectedFindResultChanged,
-    &SetTickmarks};
+    &SetPluginToHandleFindRequests, &NumberOfFindResultsChanged,
+    &SelectedFindResultChanged, &SetTickmarks};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_flash_drm_thunk.cc b/ppapi/thunk/ppb_flash_drm_thunk.cc
index d80e3b8c1..8fe71b4d 100644
--- a/ppapi/thunk/ppb_flash_drm_thunk.cc
+++ b/ppapi/thunk/ppb_flash_drm_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From private/ppb_flash_drm.idl modified Mon Apr  7 08:56:43 2014.
+// From private/ppb_flash_drm.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -67,16 +67,11 @@
       enter.object()->MonitorIsExternal(is_external, enter.callback()));
 }
 
-const PPB_Flash_DRM_1_0 g_ppb_flash_drm_thunk_1_0 = {&Create,
-                                                     &GetDeviceID,
-                                                     &GetHmonitor,
-                                                     &GetVoucherFile};
+const PPB_Flash_DRM_1_0 g_ppb_flash_drm_thunk_1_0 = {
+    &Create, &GetDeviceID, &GetHmonitor, &GetVoucherFile};
 
-const PPB_Flash_DRM_1_1 g_ppb_flash_drm_thunk_1_1 = {&Create,
-                                                     &GetDeviceID,
-                                                     &GetHmonitor,
-                                                     &GetVoucherFile,
-                                                     &MonitorIsExternal};
+const PPB_Flash_DRM_1_1 g_ppb_flash_drm_thunk_1_1 = {
+    &Create, &GetDeviceID, &GetHmonitor, &GetVoucherFile, &MonitorIsExternal};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_flash_font_file_thunk.cc b/ppapi/thunk/ppb_flash_font_file_thunk.cc
index dc7d304..1c70a54 100644
--- a/ppapi/thunk/ppb_flash_font_file_thunk.cc
+++ b/ppapi/thunk/ppb_flash_font_file_thunk.cc
@@ -4,6 +4,8 @@
 
 // From private/ppb_flash_font_file.idl modified Wed Mar  9 12:48:51 2016.
 
+#include <stdint.h>
+
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/private/ppb_flash_font_file.h"
 #include "ppapi/shared_impl/ppb_flash_font_file_shared.h"
diff --git a/ppapi/thunk/ppb_fullscreen_thunk.cc b/ppapi/thunk/ppb_fullscreen_thunk.cc
index 3704847c1..af0f3afe 100644
--- a/ppapi/thunk/ppb_fullscreen_thunk.cc
+++ b/ppapi/thunk/ppb_fullscreen_thunk.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_fullscreen.idl modified Wed May 15 13:57:07 2013.
+// From ppb_fullscreen.idl modified Wed Jan 27 17:10:16 2016.
+
+#include <stdint.h>
 
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/ppb_fullscreen.h"
@@ -39,9 +41,8 @@
   return enter.functions()->GetScreenSize(instance, size);
 }
 
-const PPB_Fullscreen_1_0 g_ppb_fullscreen_thunk_1_0 = {&IsFullscreen,
-                                                       &SetFullscreen,
-                                                       &GetScreenSize};
+const PPB_Fullscreen_1_0 g_ppb_fullscreen_thunk_1_0 = {
+    &IsFullscreen, &SetFullscreen, &GetScreenSize};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_gamepad_thunk.cc b/ppapi/thunk/ppb_gamepad_thunk.cc
index e7f4a60..354eb31 100644
--- a/ppapi/thunk/ppb_gamepad_thunk.cc
+++ b/ppapi/thunk/ppb_gamepad_thunk.cc
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_gamepad.idl modified Tue May  7 14:43:00 2013.
+// From ppb_gamepad.idl modified Wed Jan 27 17:10:16 2016.
 
+#include <stdint.h>
 #include <string.h>
 
 #include "ppapi/c/pp_errors.h"
diff --git a/ppapi/thunk/ppb_graphics_2d_thunk.cc b/ppapi/thunk/ppb_graphics_2d_thunk.cc
index 7ecbb35..527b0aa8 100644
--- a/ppapi/thunk/ppb_graphics_2d_thunk.cc
+++ b/ppapi/thunk/ppb_graphics_2d_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_graphics_2d.idl modified Wed May 15 13:57:07 2013.
+// From ppb_graphics_2d.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 #include <string.h>
@@ -102,23 +102,13 @@
   return enter.object()->GetScale();
 }
 
-const PPB_Graphics2D_1_0 g_ppb_graphics2d_thunk_1_0 = {&Create,
-                                                       &IsGraphics2D,
-                                                       &Describe,
-                                                       &PaintImageData,
-                                                       &Scroll,
-                                                       &ReplaceContents,
-                                                       &Flush};
+const PPB_Graphics2D_1_0 g_ppb_graphics2d_thunk_1_0 = {
+    &Create, &IsGraphics2D,    &Describe, &PaintImageData,
+    &Scroll, &ReplaceContents, &Flush};
 
-const PPB_Graphics2D_1_1 g_ppb_graphics2d_thunk_1_1 = {&Create,
-                                                       &IsGraphics2D,
-                                                       &Describe,
-                                                       &PaintImageData,
-                                                       &Scroll,
-                                                       &ReplaceContents,
-                                                       &Flush,
-                                                       &SetScale,
-                                                       &GetScale};
+const PPB_Graphics2D_1_1 g_ppb_graphics2d_thunk_1_1 = {
+    &Create,          &IsGraphics2D, &Describe, &PaintImageData, &Scroll,
+    &ReplaceContents, &Flush,        &SetScale, &GetScale};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_graphics_3d_thunk.cc b/ppapi/thunk/ppb_graphics_3d_thunk.cc
index eced397..d0babbb 100644
--- a/ppapi/thunk/ppb_graphics_3d_thunk.cc
+++ b/ppapi/thunk/ppb_graphics_3d_thunk.cc
@@ -4,6 +4,8 @@
 
 // From ppb_graphics_3d.idl modified Wed Jan 27 17:10:16 2016.
 
+#include <stdint.h>
+
 #include "ppapi/c/pp_completion_callback.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/ppb_graphics_3d.h"
diff --git a/ppapi/thunk/ppb_host_resolver_thunk.cc b/ppapi/thunk/ppb_host_resolver_thunk.cc
index 08e2aa2..81896c4 100644
--- a/ppapi/thunk/ppb_host_resolver_thunk.cc
+++ b/ppapi/thunk/ppb_host_resolver_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_host_resolver.idl modified Mon Jun 24 15:10:54 2013.
+// From ppb_host_resolver.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -70,12 +70,9 @@
   return enter.object()->GetNetAddress(index);
 }
 
-const PPB_HostResolver_1_0 g_ppb_hostresolver_thunk_1_0 = {&Create,
-                                                           &IsHostResolver,
-                                                           &Resolve,
-                                                           &GetCanonicalName,
-                                                           &GetNetAddressCount,
-                                                           &GetNetAddress};
+const PPB_HostResolver_1_0 g_ppb_hostresolver_thunk_1_0 = {
+    &Create,           &IsHostResolver,     &Resolve,
+    &GetCanonicalName, &GetNetAddressCount, &GetNetAddress};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_image_data_thunk.cc b/ppapi/thunk/ppb_image_data_thunk.cc
index 343372c..52ca75d3 100644
--- a/ppapi/thunk/ppb_image_data_thunk.cc
+++ b/ppapi/thunk/ppb_image_data_thunk.cc
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_image_data.idl modified Tue May  7 14:43:00 2013.
+// From ppb_image_data.idl modified Wed Jan 27 17:10:16 2016.
 
+#include <stdint.h>
 #include <string.h>
 
 #include "ppapi/c/pp_errors.h"
diff --git a/ppapi/thunk/ppb_instance_private_thunk.cc b/ppapi/thunk/ppb_instance_private_thunk.cc
index 9e576fe..5a2a7e3 100644
--- a/ppapi/thunk/ppb_instance_private_thunk.cc
+++ b/ppapi/thunk/ppb_instance_private_thunk.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From private/ppb_instance_private.idl modified Fri Jul 26 09:45:14 2013.
+// From private/ppb_instance_private.idl modified Wed Jan 27 17:10:16 2016.
+
+#include <stdint.h>
 
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/private/ppb_instance_private.h"
@@ -42,9 +44,7 @@
 }
 
 const PPB_Instance_Private_0_1 g_ppb_instance_private_thunk_0_1 = {
-    &GetWindowObject,
-    &GetOwnerElementObject,
-    &ExecuteScript};
+    &GetWindowObject, &GetOwnerElementObject, &ExecuteScript};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_instance_thunk.cc b/ppapi/thunk/ppb_instance_thunk.cc
index 6de5db0d..02dd1dd 100644
--- a/ppapi/thunk/ppb_instance_thunk.cc
+++ b/ppapi/thunk/ppb_instance_thunk.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_instance.idl modified Mon May  6 10:11:29 2013.
+// From ppb_instance.idl modified Wed Jan 27 17:10:16 2016.
+
+#include <stdint.h>
 
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/ppb_instance.h"
diff --git a/ppapi/thunk/ppb_media_stream_video_track_thunk.cc b/ppapi/thunk/ppb_media_stream_video_track_thunk.cc
index 2d640c2..d8c8cea 100644
--- a/ppapi/thunk/ppb_media_stream_video_track_thunk.cc
+++ b/ppapi/thunk/ppb_media_stream_video_track_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_media_stream_video_track.idl modified Thu Sep 18 11:36:39 2014.
+// From ppb_media_stream_video_track.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -129,16 +129,11 @@
     &Close};
 
 const PPB_MediaStreamVideoTrack_1_0 g_ppb_mediastreamvideotrack_thunk_1_0 = {
-    &Create,
-    &IsMediaStreamVideoTrack,
-    &Configure,
-    &GetAttrib,
-    &GetId,
-    &HasEnded,
-    &GetFrame,
-    &RecycleFrame,
-    &Close,
-    &GetEmptyFrame,
+    &Create,    &IsMediaStreamVideoTrack,
+    &Configure, &GetAttrib,
+    &GetId,     &HasEnded,
+    &GetFrame,  &RecycleFrame,
+    &Close,     &GetEmptyFrame,
     &PutFrame};
 
 }  // namespace
diff --git a/ppapi/thunk/ppb_messaging_thunk.cc b/ppapi/thunk/ppb_messaging_thunk.cc
index a8b3c1a..40f749e 100644
--- a/ppapi/thunk/ppb_messaging_thunk.cc
+++ b/ppapi/thunk/ppb_messaging_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_messaging.idl modified Tue Mar 24 16:53:47 2015.
+// From ppb_messaging.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -47,9 +47,8 @@
 
 const PPB_Messaging_1_0 g_ppb_messaging_thunk_1_0 = {&PostMessage};
 
-const PPB_Messaging_1_2 g_ppb_messaging_thunk_1_2 = {&PostMessage,
-                                                     &RegisterMessageHandler,
-                                                     &UnregisterMessageHandler};
+const PPB_Messaging_1_2 g_ppb_messaging_thunk_1_2 = {
+    &PostMessage, &RegisterMessageHandler, &UnregisterMessageHandler};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_mouse_cursor_thunk.cc b/ppapi/thunk/ppb_mouse_cursor_thunk.cc
index 463693f..e667ac12 100644
--- a/ppapi/thunk/ppb_mouse_cursor_thunk.cc
+++ b/ppapi/thunk/ppb_mouse_cursor_thunk.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_mouse_cursor.idl modified Mon May  6 10:11:29 2013.
+// From ppb_mouse_cursor.idl modified Wed Jan 27 17:10:16 2016.
+
+#include <stdint.h>
 
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/ppb_mouse_cursor.h"
diff --git a/ppapi/thunk/ppb_network_list_thunk.cc b/ppapi/thunk/ppb_network_list_thunk.cc
index 42df315..ee7ec39 100644
--- a/ppapi/thunk/ppb_network_list_thunk.cc
+++ b/ppapi/thunk/ppb_network_list_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_network_list.idl modified Fri Nov  1 16:12:12 2013.
+// From ppb_network_list.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -82,14 +82,9 @@
   return enter.object()->GetMTU(index);
 }
 
-const PPB_NetworkList_1_0 g_ppb_networklist_thunk_1_0 = {&IsNetworkList,
-                                                         &GetCount,
-                                                         &GetName,
-                                                         &GetType,
-                                                         &GetState,
-                                                         &GetIpAddresses,
-                                                         &GetDisplayName,
-                                                         &GetMTU};
+const PPB_NetworkList_1_0 g_ppb_networklist_thunk_1_0 = {
+    &IsNetworkList, &GetCount,       &GetName,        &GetType,
+    &GetState,      &GetIpAddresses, &GetDisplayName, &GetMTU};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_network_monitor_thunk.cc b/ppapi/thunk/ppb_network_monitor_thunk.cc
index 7d37ac50..b84b406 100644
--- a/ppapi/thunk/ppb_network_monitor_thunk.cc
+++ b/ppapi/thunk/ppb_network_monitor_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_network_monitor.idl modified Fri Nov  1 16:12:12 2013.
+// From ppb_network_monitor.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -45,9 +45,7 @@
 }
 
 const PPB_NetworkMonitor_1_0 g_ppb_networkmonitor_thunk_1_0 = {
-    &Create,
-    &UpdateNetworkList,
-    &IsNetworkMonitor};
+    &Create, &UpdateNetworkList, &IsNetworkMonitor};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_output_protection_private_thunk.cc b/ppapi/thunk/ppb_output_protection_private_thunk.cc
index c92885ac..8cd0a0c 100644
--- a/ppapi/thunk/ppb_output_protection_private_thunk.cc
+++ b/ppapi/thunk/ppb_output_protection_private_thunk.cc
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From private/ppb_output_protection_private.idl modified Fri Nov  1 16:12:12
-// 2013.
+// From private/ppb_output_protection_private.idl modified Wed Jan 27 17:10:16
+// 2016.
 
 #include <stdint.h>
 
@@ -58,10 +58,8 @@
 }
 
 const PPB_OutputProtection_Private_0_1
-    g_ppb_outputprotection_private_thunk_0_1 = {&Create,
-                                                &IsOutputProtection,
-                                                &QueryStatus,
-                                                &EnableProtection};
+    g_ppb_outputprotection_private_thunk_0_1 = {
+        &Create, &IsOutputProtection, &QueryStatus, &EnableProtection};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_platform_verification_private_thunk.cc b/ppapi/thunk/ppb_platform_verification_private_thunk.cc
index d751cd3..786ef6e 100644
--- a/ppapi/thunk/ppb_platform_verification_private_thunk.cc
+++ b/ppapi/thunk/ppb_platform_verification_private_thunk.cc
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From private/ppb_platform_verification_private.idl modified Fri Nov  1
-// 16:12:12 2013.
+// From private/ppb_platform_verification_private.idl modified Wed Jan 27
+// 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -51,9 +51,8 @@
 }
 
 const PPB_PlatformVerification_Private_0_2
-    g_ppb_platformverification_private_thunk_0_2 = {&Create,
-                                                    &IsPlatformVerification,
-                                                    &ChallengePlatform};
+    g_ppb_platformverification_private_thunk_0_2 = {
+        &Create, &IsPlatformVerification, &ChallengePlatform};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_printing_dev_thunk.cc b/ppapi/thunk/ppb_printing_dev_thunk.cc
index 88bca985..2b70b99 100644
--- a/ppapi/thunk/ppb_printing_dev_thunk.cc
+++ b/ppapi/thunk/ppb_printing_dev_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From dev/ppb_printing_dev.idl modified Tue May  7 14:43:00 2013.
+// From dev/ppb_printing_dev.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -39,8 +39,7 @@
 }
 
 const PPB_Printing_Dev_0_7 g_ppb_printing_dev_thunk_0_7 = {
-    &Create,
-    &GetDefaultPrintSettings};
+    &Create, &GetDefaultPrintSettings};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_truetype_font_dev_thunk.cc b/ppapi/thunk/ppb_truetype_font_dev_thunk.cc
index 8437c75..a568e64 100644
--- a/ppapi/thunk/ppb_truetype_font_dev_thunk.cc
+++ b/ppapi/thunk/ppb_truetype_font_dev_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From dev/ppb_truetype_font_dev.idl modified Fri Nov  1 16:12:12 2013.
+// From dev/ppb_truetype_font_dev.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -94,13 +94,8 @@
 }
 
 const PPB_TrueTypeFont_Dev_0_1 g_ppb_truetypefont_dev_thunk_0_1 = {
-    &GetFontFamilies,
-    &GetFontsInFamily,
-    &Create,
-    &IsTrueTypeFont,
-    &Describe,
-    &GetTableTags,
-    &GetTable};
+    &GetFontFamilies, &GetFontsInFamily, &Create,  &IsTrueTypeFont,
+    &Describe,        &GetTableTags,     &GetTable};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_udp_socket_thunk.cc b/ppapi/thunk/ppb_udp_socket_thunk.cc
index 3df936e..1c35bad2 100644
--- a/ppapi/thunk/ppb_udp_socket_thunk.cc
+++ b/ppapi/thunk/ppb_udp_socket_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_udp_socket.idl modified Fri Mar 13 17:49:57 2015.
+// From ppb_udp_socket.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -141,34 +141,17 @@
   return enter.SetResult(enter.object()->LeaveGroup(group, enter.callback()));
 }
 
-const PPB_UDPSocket_1_0 g_ppb_udpsocket_thunk_1_0 = {&Create,
-                                                     &IsUDPSocket,
-                                                     &Bind,
-                                                     &GetBoundAddress,
-                                                     &RecvFrom,
-                                                     &SendTo,
-                                                     &Close,
-                                                     &SetOption_1_0};
+const PPB_UDPSocket_1_0 g_ppb_udpsocket_thunk_1_0 = {
+    &Create,   &IsUDPSocket, &Bind,  &GetBoundAddress,
+    &RecvFrom, &SendTo,      &Close, &SetOption_1_0};
 
-const PPB_UDPSocket_1_1 g_ppb_udpsocket_thunk_1_1 = {&Create,
-                                                     &IsUDPSocket,
-                                                     &Bind,
-                                                     &GetBoundAddress,
-                                                     &RecvFrom,
-                                                     &SendTo,
-                                                     &Close,
-                                                     &SetOption_1_1};
+const PPB_UDPSocket_1_1 g_ppb_udpsocket_thunk_1_1 = {
+    &Create,   &IsUDPSocket, &Bind,  &GetBoundAddress,
+    &RecvFrom, &SendTo,      &Close, &SetOption_1_1};
 
-const PPB_UDPSocket_1_2 g_ppb_udpsocket_thunk_1_2 = {&Create,
-                                                     &IsUDPSocket,
-                                                     &Bind,
-                                                     &GetBoundAddress,
-                                                     &RecvFrom,
-                                                     &SendTo,
-                                                     &Close,
-                                                     &SetOption,
-                                                     &JoinGroup,
-                                                     &LeaveGroup};
+const PPB_UDPSocket_1_2 g_ppb_udpsocket_thunk_1_2 = {
+    &Create, &IsUDPSocket, &Bind,      &GetBoundAddress, &RecvFrom,
+    &SendTo, &Close,       &SetOption, &JoinGroup,       &LeaveGroup};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_uma_private_thunk.cc b/ppapi/thunk/ppb_uma_private_thunk.cc
index 0e1a0b92..517b945b 100644
--- a/ppapi/thunk/ppb_uma_private_thunk.cc
+++ b/ppapi/thunk/ppb_uma_private_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From private/ppb_uma_private.idl modified Mon Apr  7 08:56:43 2014.
+// From private/ppb_uma_private.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -70,9 +70,7 @@
 }
 
 const PPB_UMA_Private_0_3 g_ppb_uma_private_thunk_0_3 = {
-    &HistogramCustomTimes,
-    &HistogramCustomCounts,
-    &HistogramEnumeration,
+    &HistogramCustomTimes, &HistogramCustomCounts, &HistogramEnumeration,
     &IsCrashReportingEnabled};
 
 }  // namespace
diff --git a/ppapi/thunk/ppb_url_loader_trusted_thunk.cc b/ppapi/thunk/ppb_url_loader_trusted_thunk.cc
index 264eed6..7d48a03b 100644
--- a/ppapi/thunk/ppb_url_loader_trusted_thunk.cc
+++ b/ppapi/thunk/ppb_url_loader_trusted_thunk.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From trusted/ppb_url_loader_trusted.idl modified Tue May  7 14:43:00 2013.
+// From trusted/ppb_url_loader_trusted.idl modified Wed Jan 27 17:10:16 2016.
+
+#include <stdint.h>
 
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/trusted/ppb_url_loader_trusted.h"
@@ -34,8 +36,7 @@
 }
 
 const PPB_URLLoaderTrusted_0_3 g_ppb_urlloadertrusted_thunk_0_3 = {
-    &GrantUniversalAccess,
-    &RegisterStatusCallback};
+    &GrantUniversalAccess, &RegisterStatusCallback};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_url_request_info_thunk.cc b/ppapi/thunk/ppb_url_request_info_thunk.cc
index 3ec617f..24e1041a 100644
--- a/ppapi/thunk/ppb_url_request_info_thunk.cc
+++ b/ppapi/thunk/ppb_url_request_info_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_url_request_info.idl modified Mon May  6 10:11:29 2013.
+// From ppb_url_request_info.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -64,10 +64,7 @@
 }
 
 const PPB_URLRequestInfo_1_0 g_ppb_urlrequestinfo_thunk_1_0 = {
-    &Create,
-    &IsURLRequestInfo,
-    &SetProperty,
-    &AppendDataToBody,
+    &Create, &IsURLRequestInfo, &SetProperty, &AppendDataToBody,
     &AppendFileToBody};
 
 }  // namespace
diff --git a/ppapi/thunk/ppb_url_response_info_thunk.cc b/ppapi/thunk/ppb_url_response_info_thunk.cc
index c61eba7..9b90f0a 100644
--- a/ppapi/thunk/ppb_url_response_info_thunk.cc
+++ b/ppapi/thunk/ppb_url_response_info_thunk.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_url_response_info.idl modified Tue May  7 14:43:00 2013.
+// From ppb_url_response_info.idl modified Wed Jan 27 17:10:16 2016.
+
+#include <stdint.h>
 
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/ppb_url_response_info.h"
@@ -40,9 +42,7 @@
 }
 
 const PPB_URLResponseInfo_1_0 g_ppb_urlresponseinfo_thunk_1_0 = {
-    &IsURLResponseInfo,
-    &GetProperty,
-    &GetBodyAsFileRef};
+    &IsURLResponseInfo, &GetProperty, &GetBodyAsFileRef};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_video_frame_thunk.cc b/ppapi/thunk/ppb_video_frame_thunk.cc
index 96e023a2..c980f8a 100644
--- a/ppapi/thunk/ppb_video_frame_thunk.cc
+++ b/ppapi/thunk/ppb_video_frame_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_video_frame.idl modified Mon Apr  7 08:56:43 2014.
+// From ppb_video_frame.idl modified Wed Jan 27 17:10:16 2016.
 
 #include <stdint.h>
 
@@ -72,13 +72,9 @@
   return enter.object()->GetDataBufferSize();
 }
 
-const PPB_VideoFrame_0_1 g_ppb_videoframe_thunk_0_1 = {&IsVideoFrame,
-                                                       &GetTimestamp,
-                                                       &SetTimestamp,
-                                                       &GetFormat,
-                                                       &GetSize,
-                                                       &GetDataBuffer,
-                                                       &GetDataBufferSize};
+const PPB_VideoFrame_0_1 g_ppb_videoframe_thunk_0_1 = {
+    &IsVideoFrame, &GetTimestamp,  &SetTimestamp,     &GetFormat,
+    &GetSize,      &GetDataBuffer, &GetDataBufferSize};
 
 }  // namespace
 
diff --git a/ppapi/thunk/ppb_view_dev_thunk.cc b/ppapi/thunk/ppb_view_dev_thunk.cc
index 0a2ef27..2dd83b4 100644
--- a/ppapi/thunk/ppb_view_dev_thunk.cc
+++ b/ppapi/thunk/ppb_view_dev_thunk.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From dev/ppb_view_dev.idl modified Mon May  6 10:11:29 2013.
+// From dev/ppb_view_dev.idl modified Wed Jan 27 17:10:16 2016.
+
+#include <stdint.h>
 
 #include "ppapi/c/dev/ppb_view_dev.h"
 #include "ppapi/c/pp_errors.h"
diff --git a/ppapi/thunk/ppb_view_thunk.cc b/ppapi/thunk/ppb_view_thunk.cc
index 980c768..6e069fc 100644
--- a/ppapi/thunk/ppb_view_thunk.cc
+++ b/ppapi/thunk/ppb_view_thunk.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_view.idl modified Wed Nov  5 14:29:15 2014.
+// From ppb_view.idl modified Wed Jan 27 17:10:16 2016.
+
+#include <stdint.h>
 
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/ppb_view.h"
@@ -86,31 +88,17 @@
   return enter.object()->GetScrollOffset(offset);
 }
 
-const PPB_View_1_0 g_ppb_view_thunk_1_0 = {&IsView,
-                                           &GetRect,
-                                           &IsFullscreen,
-                                           &IsVisible,
-                                           &IsPageVisible,
-                                           &GetClipRect};
+const PPB_View_1_0 g_ppb_view_thunk_1_0 = {
+    &IsView, &GetRect, &IsFullscreen, &IsVisible, &IsPageVisible, &GetClipRect};
 
-const PPB_View_1_1 g_ppb_view_thunk_1_1 = {&IsView,
-                                           &GetRect,
-                                           &IsFullscreen,
-                                           &IsVisible,
-                                           &IsPageVisible,
-                                           &GetClipRect,
-                                           &GetDeviceScale,
-                                           &GetCSSScale};
+const PPB_View_1_1 g_ppb_view_thunk_1_1 = {
+    &IsView,        &GetRect,     &IsFullscreen,   &IsVisible,
+    &IsPageVisible, &GetClipRect, &GetDeviceScale, &GetCSSScale};
 
-const PPB_View_1_2 g_ppb_view_thunk_1_2 = {&IsView,
-                                           &GetRect,
-                                           &IsFullscreen,
-                                           &IsVisible,
-                                           &IsPageVisible,
-                                           &GetClipRect,
-                                           &GetDeviceScale,
-                                           &GetCSSScale,
-                                           &GetScrollOffset};
+const PPB_View_1_2 g_ppb_view_thunk_1_2 = {
+    &IsView,         &GetRect,       &IsFullscreen,
+    &IsVisible,      &IsPageVisible, &GetClipRect,
+    &GetDeviceScale, &GetCSSScale,   &GetScrollOffset};
 
 }  // namespace
 
diff --git a/remoting/base/BUILD.gn b/remoting/base/BUILD.gn
index 97dc3aa..23dcad1 100644
--- a/remoting/base/BUILD.gn
+++ b/remoting/base/BUILD.gn
@@ -66,7 +66,7 @@
     "rate_counter_unittest.cc",
     "rsa_key_pair_unittest.cc",
     "run_all_unittests.cc",
-    "running_average_unittest.cc",
+    "running_samples_unittest.cc",
     "test_rsa_key_pair.h",
     "typed_buffer_unittest.cc",
     "util_unittest.cc",
diff --git a/remoting/base/running_average.cc b/remoting/base/running_average.cc
deleted file mode 100644
index 5e24c0d..0000000
--- a/remoting/base/running_average.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "remoting/base/running_average.h"
-
-#include "base/logging.h"
-
-namespace remoting {
-
-RunningAverage::RunningAverage(int window_size)
-    : window_size_(window_size),
-      sum_(0) {
-  DCHECK_GT(window_size, 0);
-}
-
-RunningAverage::~RunningAverage() {}
-
-void RunningAverage::Record(int64_t value) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  data_points_.push_back(value);
-  sum_ += value;
-
-  if (data_points_.size() > window_size_) {
-    sum_ -= data_points_[0];
-    data_points_.pop_front();
-  }
-}
-
-double RunningAverage::Average() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  if (data_points_.empty())
-    return 0;
-  return static_cast<double>(sum_) / data_points_.size();
-}
-
-}  // namespace remoting
diff --git a/remoting/base/running_average.h b/remoting/base/running_average.h
deleted file mode 100644
index e41234e5..0000000
--- a/remoting/base/running_average.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef REMOTING_BASE_RUNNING_AVERAGE_H_
-#define REMOTING_BASE_RUNNING_AVERAGE_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <deque>
-
-#include "base/macros.h"
-#include "base/threading/thread_checker.h"
-
-namespace remoting {
-
-// Calculates the average of the most recent N recorded samples.
-// This is typically used to smooth out random variation in point samples
-// over bandwidth, frame rate, etc.
-class RunningAverage {
- public:
-  // Constructs a helper to average over the |window_size| most recent samples.
-  explicit RunningAverage(int window_size);
-  virtual ~RunningAverage();
-
-  // Records a point sample.
-  void Record(int64_t value);
-
-  // Returns the average over up to |window_size| of the most recent samples.
-  double Average();
-
- private:
-  // Stores the desired window size, as size_t to avoid casting when comparing
-  // with the size of |data_points_|.
-  const size_t window_size_;
-
-  // Stores the |window_size| most recently recorded samples.
-  std::deque<int64_t> data_points_;
-
-  // Holds the sum of the samples in |data_points_|.
-  int64_t sum_;
-
-  base::ThreadChecker thread_checker_;
-
-  DISALLOW_COPY_AND_ASSIGN(RunningAverage);
-};
-
-}  // namespace remoting
-
-#endif  // REMOTING_BASE_RUNNING_AVERAGE_H_
diff --git a/remoting/base/running_average_unittest.cc b/remoting/base/running_average_unittest.cc
deleted file mode 100644
index e731573..0000000
--- a/remoting/base/running_average_unittest.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "remoting/base/running_average.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace remoting {
-
-static const int64_t kTestValues[] = { 10, 20, 30, 10, 25, 16, 15 };
-
-// Average across a single element, i.e. just return the most recent.
-TEST(RunningAverageTest, OneElementWindow) {
-  RunningAverage running_average(1);
-  EXPECT_EQ(0, running_average.Average());
-
-  for (size_t i = 0; i < arraysize(kTestValues); ++i) {
-    running_average.Record(kTestValues[i]);
-    EXPECT_EQ(static_cast<double>(kTestValues[i]), running_average.Average());
-  }
-}
-
-// Average the two most recent elements.
-TEST(RunningAverageTest, TwoElementWindow) {
-  RunningAverage running_average(2);
-  EXPECT_EQ(0, running_average.Average());
-
-  for (size_t i = 0; i < arraysize(kTestValues); ++i) {
-    running_average.Record(kTestValues[i]);
-
-    double expected = kTestValues[i];
-    if (i > 0)
-      expected = (expected + kTestValues[i-1]) / 2;
-
-    EXPECT_EQ(expected, running_average.Average());
-  }
-}
-
-// Average across all the elements if the window size exceeds the element count.
-TEST(RunningAverageTest, LongWindow) {
-  RunningAverage running_average(arraysize(kTestValues) + 1);
-  EXPECT_EQ(0, running_average.Average());
-
-  for (size_t i = 0; i < arraysize(kTestValues); ++i) {
-    running_average.Record(kTestValues[i]);
-
-    double expected = 0.0;
-    for (size_t j = 0; j <= i; ++j)
-      expected += kTestValues[j];
-    expected /= i + 1;
-
-    EXPECT_EQ(expected, running_average.Average());
-  }
-}
-
-}  // namespace remoting
diff --git a/remoting/base/running_samples.cc b/remoting/base/running_samples.cc
new file mode 100644
index 0000000..d76a1a6
--- /dev/null
+++ b/remoting/base/running_samples.cc
@@ -0,0 +1,49 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/base/running_samples.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+
+namespace remoting {
+
+RunningSamples::RunningSamples(int window_size)
+    : window_size_(window_size) {
+  DCHECK_GT(window_size, 0);
+}
+
+RunningSamples::~RunningSamples() {}
+
+void RunningSamples::Record(int64_t value) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  data_points_.push_back(value);
+  sum_ += value;
+
+  if (data_points_.size() > window_size_) {
+    sum_ -= data_points_[0];
+    data_points_.pop_front();
+  }
+}
+
+double RunningSamples::Average() const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  if (data_points_.empty())
+    return 0;
+  return static_cast<double>(sum_) / data_points_.size();
+}
+
+int64_t RunningSamples::Max() const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  if (data_points_.empty())
+    return 0;
+
+  return *std::max_element(data_points_.begin(), data_points_.end());
+}
+
+}  // namespace remoting
diff --git a/remoting/base/running_samples.h b/remoting/base/running_samples.h
new file mode 100644
index 0000000..3f5078d
--- /dev/null
+++ b/remoting/base/running_samples.h
@@ -0,0 +1,57 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_BASE_RUNNING_SAMPLES_H_
+#define REMOTING_BASE_RUNNING_SAMPLES_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <deque>
+
+#include "base/macros.h"
+#include "base/threading/thread_checker.h"
+
+namespace remoting {
+
+// Calculates the maximum or average of the most recent N recorded samples.
+// This is typically used to smooth out random variation in point samples
+// over bandwidth, frame rate, etc.
+class RunningSamples {
+ public:
+  // Constructs a running sample helper that stores |window_size| most
+  // recent samples.
+  explicit RunningSamples(int window_size);
+  virtual ~RunningSamples();
+
+  // Records a point sample.
+  void Record(int64_t value);
+
+  // Returns the average over up to |window_size| of the most recent samples.
+  // 0 if no sample available
+  double Average() const;
+
+  // Returns the max over up to |window_size| of the most recent samples.
+  // 0 if no sample available
+  int64_t Max() const;
+
+ private:
+  // Stores the desired window size, as size_t to avoid casting when comparing
+  // with the size of |data_points_|.
+  const size_t window_size_;
+
+  // Stores the |window_size| most recently recorded samples.
+  std::deque<int64_t> data_points_;
+
+  // Holds the sum of the samples in |data_points_|.
+  int64_t sum_ = 0;
+
+  base::ThreadChecker thread_checker_;
+
+  DISALLOW_COPY_AND_ASSIGN(RunningSamples);
+};
+
+}  // namespace remoting
+
+#endif  // REMOTING_BASE_RUNNING_SAMPLES_H_
diff --git a/remoting/base/running_samples_unittest.cc b/remoting/base/running_samples_unittest.cc
new file mode 100644
index 0000000..2c2c7f5
--- /dev/null
+++ b/remoting/base/running_samples_unittest.cc
@@ -0,0 +1,92 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "remoting/base/running_samples.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace remoting {
+
+typedef void (*TestFunction)(size_t i, RunningSamples& samples);
+
+static const int64_t kTestValues[] = { 10, 20, 30, 10, 25, 16, 15 };
+
+// Test framework that verifies average() and max() at beginning, iterates
+// through all elements and meanwhile calls your own test function
+static void TestFramework(int windowSize, TestFunction testFn) {
+  RunningSamples samples(windowSize);
+  EXPECT_EQ(0, samples.Average());
+  EXPECT_EQ(0, samples.Max());
+
+  for (size_t i = 0; i < arraysize(kTestValues); ++i) {
+    samples.Record(kTestValues[i]);
+    testFn(i, samples);
+  }
+}
+
+// Average across a single element, i.e. just return the most recent.
+TEST(RunningSamplesTest, AverageOneElementWindow) {
+  TestFramework(1, [](size_t i, RunningSamples& samples) {
+    EXPECT_EQ(static_cast<double>(kTestValues[i]), samples.Average());
+  });
+}
+
+// Average the two most recent elements.
+TEST(RunningSamplesTest, AverageTwoElementWindow) {
+  TestFramework(2, [](size_t i, RunningSamples& samples) {
+    double expected = kTestValues[i];
+    if (i > 0)
+      expected = (expected + kTestValues[i-1]) / 2;
+
+    EXPECT_EQ(expected, samples.Average());
+  });
+}
+
+// Average across all the elements if the window size exceeds the element count.
+TEST(RunningSamplesTest, AverageLongWindow) {
+  TestFramework(arraysize(kTestValues) + 1,
+      [](size_t i, RunningSamples& samples) {
+    double expected = 0.0;
+    for (size_t j = 0; j <= i; ++j)
+      expected += kTestValues[j];
+    expected /= i + 1;
+
+    EXPECT_EQ(expected, samples.Average());
+  });
+}
+
+// Max of a single element, i.e. just return the most recent.
+TEST(RunningSamplesTest, MaxOneElementWindow) {
+  TestFramework(1, [](size_t i, RunningSamples& samples) {
+    EXPECT_EQ(static_cast<double>(kTestValues[i]), samples.Max());
+  });
+}
+
+// Max of the two most recent elements.
+TEST(RunningSamplesTest, MaxTwoElementWindow) {
+  TestFramework(2, [](size_t i, RunningSamples& samples) {
+    double expected = kTestValues[i];
+    if (i > 0)
+      expected = expected > kTestValues[i-1] ? expected : kTestValues[i-1];
+
+    EXPECT_EQ(expected, samples.Max());
+  });
+}
+
+// Max of all the elements if the window size exceeds the element count.
+TEST(RunningSamplesTest, MaxLongWindow) {
+  TestFramework(arraysize(kTestValues) + 1,
+      [](size_t i, RunningSamples& samples) {
+    int64_t expected = -1;
+    for (size_t j = 0; j <= i; ++j)
+      expected = expected > kTestValues[j] ? expected : kTestValues[j];
+
+    EXPECT_EQ(expected, samples.Max());
+  });
+}
+
+}  // namespace remoting
\ No newline at end of file
diff --git a/remoting/client/BUILD.gn b/remoting/client/BUILD.gn
index 88cb608..c4e0a40 100644
--- a/remoting/client/BUILD.gn
+++ b/remoting/client/BUILD.gn
@@ -32,6 +32,11 @@
       "client_status_logger.cc",
       "server_log_entry_client.cc",
     ]
+  } else {
+    sources += rebase_path(
+            remoting_srcs_gypi_values.remoting_client_standalone_sources,
+            ".",
+            "//remoting")
   }
 }
 
@@ -43,6 +48,7 @@
   set_sources_assignment_filter([])
   sources = [
     "audio_player_unittest.cc",
+    "chromoting_client_runtime_unittest.cc",
     "client_status_logger_unittest.cc",
     "empty_cursor_filter_unittest.cc",
     "key_event_mapper_unittest.cc",
diff --git a/remoting/client/chromoting_client_runtime.cc b/remoting/client/chromoting_client_runtime.cc
new file mode 100644
index 0000000..db486f61
--- /dev/null
+++ b/remoting/client/chromoting_client_runtime.cc
@@ -0,0 +1,55 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/client/chromoting_client_runtime.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "remoting/base/url_request_context_getter.h"
+
+namespace remoting {
+
+scoped_ptr<ChromotingClientRuntime> ChromotingClientRuntime::Create(
+    base::MessageLoopForUI* ui_loop) {
+  DCHECK(ui_loop);
+
+  // |ui_loop_| runs on the main thread, so |ui_task_runner_| will run on the
+  // main thread.  We can not kill the main thread when the message loop becomes
+  // idle so the callback function does nothing (as opposed to the typical
+  // base::MessageLoop::QuitClosure())
+  scoped_refptr<AutoThreadTaskRunner> ui_task_runner = new AutoThreadTaskRunner(
+      ui_loop->task_runner(), base::Bind(&base::DoNothing));
+
+  scoped_refptr<AutoThreadTaskRunner> display_task_runner =
+      AutoThread::Create("native_disp", ui_task_runner);
+  scoped_refptr<AutoThreadTaskRunner> network_task_runner =
+      AutoThread::CreateWithType("native_net", ui_task_runner,
+                                 base::MessageLoop::TYPE_IO);
+  scoped_refptr<AutoThreadTaskRunner> file_task_runner =
+      AutoThread::CreateWithType("native_file", ui_task_runner,
+                                 base::MessageLoop::TYPE_IO);
+  scoped_refptr<net::URLRequestContextGetter> url_requester =
+      new URLRequestContextGetter(network_task_runner, file_task_runner);
+
+  return make_scoped_ptr(new ChromotingClientRuntime(
+      ui_task_runner, display_task_runner, network_task_runner,
+      file_task_runner, url_requester));
+}
+
+ChromotingClientRuntime::ChromotingClientRuntime(
+    scoped_refptr<AutoThreadTaskRunner> ui_task_runner,
+    scoped_refptr<AutoThreadTaskRunner> display_task_runner,
+    scoped_refptr<AutoThreadTaskRunner> network_task_runner,
+    scoped_refptr<AutoThreadTaskRunner> file_task_runner,
+    scoped_refptr<net::URLRequestContextGetter> url_requester)
+    : ui_task_runner_(ui_task_runner),
+      display_task_runner_(display_task_runner),
+      network_task_runner_(network_task_runner),
+      file_task_runner_(file_task_runner),
+      url_requester_(url_requester) {}
+
+ChromotingClientRuntime::~ChromotingClientRuntime() {}
+
+}  // namespace remoting
diff --git a/remoting/client/chromoting_client_runtime.h b/remoting/client/chromoting_client_runtime.h
new file mode 100644
index 0000000..b9c45b6
--- /dev/null
+++ b/remoting/client/chromoting_client_runtime.h
@@ -0,0 +1,89 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_CLIENT_CHROMOTING_CLIENT_RUNTIME_H_
+#define REMOTING_CLIENT_CHROMOTING_CLIENT_RUNTIME_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "remoting/base/auto_thread.h"
+
+namespace base {
+class MessageLoopForUI;
+}  // namespace base
+
+// Houses the global resources on which the Chromoting components run
+// (e.g. message loops and task runners).
+namespace remoting {
+
+class ChromotingClientRuntime {
+ public:
+  // Caller to create is responsible for creating and attaching a new ui thread
+  // for use. Example:
+  //
+  // On Android, the UI thread is managed by Java, so we need to attach and
+  // start a special type of message loop to allow Chromium code to run tasks.
+  //
+  //  base::MessageLoopForUI *ui_loop = new base::MessageLoopForUI();
+  //  ui_loop_->Start();
+  //  scoped_ptr<ChromotingClientRuntime> runtime =
+  //    ChromotingClientRuntime::Create(ui_loop);
+  //
+  // On iOS we created a new message loop and now attach it.
+  //
+  //  base::MessageLoopForUI *ui_loop = new base::MessageLoopForUI();
+  //  ui_loop_->Attach();
+  //  scoped_ptr<ChromotingClientRuntime> runtime =
+  //    ChromotingClientRuntime::Create(ui_loop);
+  //
+  static scoped_ptr<ChromotingClientRuntime> Create(
+      base::MessageLoopForUI* ui_loop);
+
+  ~ChromotingClientRuntime();
+
+  scoped_refptr<AutoThreadTaskRunner> network_task_runner() {
+    return network_task_runner_;
+  }
+
+  scoped_refptr<AutoThreadTaskRunner> ui_task_runner() {
+    return ui_task_runner_;
+  }
+
+  scoped_refptr<AutoThreadTaskRunner> display_task_runner() {
+    return display_task_runner_;
+  }
+
+  scoped_refptr<AutoThreadTaskRunner> file_task_runner() {
+    return file_task_runner_;
+  }
+
+  scoped_refptr<net::URLRequestContextGetter> url_requester() {
+    return url_requester_;
+  }
+
+ private:
+  ChromotingClientRuntime();
+  ChromotingClientRuntime(
+      scoped_refptr<AutoThreadTaskRunner> ui_task_runner,
+      scoped_refptr<AutoThreadTaskRunner> display_task_runner,
+      scoped_refptr<AutoThreadTaskRunner> network_task_runner,
+      scoped_refptr<AutoThreadTaskRunner> file_task_runner,
+      scoped_refptr<net::URLRequestContextGetter> url_requester);
+
+  // References to native threads.
+  scoped_refptr<AutoThreadTaskRunner> ui_task_runner_;
+
+  scoped_refptr<AutoThreadTaskRunner> display_task_runner_;
+  scoped_refptr<AutoThreadTaskRunner> network_task_runner_;
+  scoped_refptr<AutoThreadTaskRunner> file_task_runner_;
+
+  scoped_refptr<net::URLRequestContextGetter> url_requester_;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromotingClientRuntime);
+};
+
+}  // namespace remoting
+
+#endif  // REMOTING_CLIENT_CHROMOTING_CLIENT_RUNTIME_H_
diff --git a/remoting/client/chromoting_client_runtime_unittest.cc b/remoting/client/chromoting_client_runtime_unittest.cc
new file mode 100644
index 0000000..39f240fe1
--- /dev/null
+++ b/remoting/client/chromoting_client_runtime_unittest.cc
@@ -0,0 +1,37 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "remoting/base/auto_thread_task_runner.h"
+#include "remoting/client/chromoting_client_runtime.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace remoting {
+
+#if defined(OS_IOS) || defined(OS_ANDROID)
+
+// A simple test that starts and stop the runtime. This tests the runtime
+// operates properly and all threads and message loops are valid.
+TEST(ChromotingClientRuntimeTest, StartAndStop) {
+  scoped_ptr<base::MessageLoopForUI> ui_loop;
+  ui_loop.reset(new base::MessageLoopForUI());
+#if defined(OS_IOS)
+  ui_loop->Attach();
+#endif
+
+  scoped_ptr<ChromotingClientRuntime> runtime =
+      ChromotingClientRuntime::Create(ui_loop.get());
+
+  ASSERT_TRUE(runtime);
+  EXPECT_TRUE(runtime->network_task_runner().get());
+  EXPECT_TRUE(runtime->ui_task_runner().get());
+  EXPECT_TRUE(runtime->display_task_runner().get());
+  EXPECT_TRUE(runtime->file_task_runner().get());
+  EXPECT_TRUE(runtime->url_requester().get());
+}
+
+#endif
+
+}  // namespace remoting
diff --git a/remoting/client/jni/chromoting_jni_instance.cc b/remoting/client/jni/chromoting_jni_instance.cc
index 7d8b7f8..1fd5b1c 100644
--- a/remoting/client/jni/chromoting_jni_instance.cc
+++ b/remoting/client/jni/chromoting_jni_instance.cc
@@ -484,12 +484,20 @@
 
   __android_log_print(
       ANDROID_LOG_INFO, "stats",
-      "Bandwidth:%.0f FrameRate:%.1f Capture:%.1f Encode:%.1f "
-      "Decode:%.1f Render:%.1f Latency:%.0f",
+      "Bandwidth:%.0f FrameRate:%.1f; "
+      "(Avg, Max) Capture:%.1f, %lld Encode:%.1f, %lld Decode:%.1f, %lld "
+      "Render:%.1f, %lld RTL:%.0f, %lld",
       perf_tracker_->video_bandwidth(), perf_tracker_->video_frame_rate(),
-      perf_tracker_->video_capture_ms(), perf_tracker_->video_encode_ms(),
-      perf_tracker_->video_decode_ms(), perf_tracker_->video_paint_ms(),
-      perf_tracker_->round_trip_ms());
+      perf_tracker_->video_capture_ms().Average(),
+      perf_tracker_->video_capture_ms().Max(),
+      perf_tracker_->video_encode_ms().Average(),
+      perf_tracker_->video_encode_ms().Max(),
+      perf_tracker_->video_decode_ms().Average(),
+      perf_tracker_->video_decode_ms().Max(),
+      perf_tracker_->video_paint_ms().Average(),
+      perf_tracker_->video_paint_ms().Max(),
+      perf_tracker_->round_trip_ms().Average(),
+      perf_tracker_->round_trip_ms().Max());
 
   client_status_logger_->LogStatistics(perf_tracker_.get());
 
diff --git a/remoting/client/jni/chromoting_jni_runtime.cc b/remoting/client/jni/chromoting_jni_runtime.cc
index 6e91a5e..443e0b6 100644
--- a/remoting/client/jni/chromoting_jni_runtime.cc
+++ b/remoting/client/jni/chromoting_jni_runtime.cc
@@ -186,42 +186,41 @@
 }
 
 ChromotingJniRuntime::ChromotingJniRuntime() {
-  // On Android, the UI thread is managed by Java, so we need to attach and
-  // start a special type of message loop to allow Chromium code to run tasks.
-  ui_loop_.reset(new base::MessageLoopForUI());
-  ui_loop_->Start();
+  // Grab or create the threads.
+  // TODO(nicholss) We could runtime this as a constructor argument when jni
+  // runtime is not no longer a singleton.
 
-  // TODO(solb) Stop pretending to control the managed UI thread's lifetime.
-  ui_task_runner_ = new AutoThreadTaskRunner(
-      ui_loop_->task_runner(), base::MessageLoop::QuitWhenIdleClosure());
-  network_task_runner_ = AutoThread::CreateWithType("native_net",
-                                                    ui_task_runner_,
-                                                    base::MessageLoop::TYPE_IO);
-  display_task_runner_ = AutoThread::Create("native_disp",
-                                            ui_task_runner_);
+  if (!base::MessageLoop::current()) {
+    VLOG(1) << "Starting main message loop";
+    // On Android, the UI thread is managed by Java, so we need to attach and
+    // start a special type of message loop to allow Chromium code to run tasks.
+    ui_loop_.reset(new base::MessageLoopForUI());
+    ui_loop_->Start();
+  } else {
+    VLOG(1) << "Using existing main message loop";
+    ui_loop_.reset(base::MessageLoopForUI::current());
+  }
 
-  url_requester_ =
-      new URLRequestContextGetter(network_task_runner_, network_task_runner_);
+  // Pass the main ui loop already attached to be used for creating threads.
+  runtime_ = ChromotingClientRuntime::Create(ui_loop_.get());
 }
 
 ChromotingJniRuntime::~ChromotingJniRuntime() {
   // The singleton should only ever be destroyed on the main thread.
-  DCHECK(ui_task_runner_->BelongsToCurrentThread());
+  DCHECK(ui_task_runner()->BelongsToCurrentThread());
 
   // The session must be shut down first, since it depends on our other
   // components' still being alive.
   DisconnectFromHost();
 
   base::WaitableEvent done_event(false, false);
-  network_task_runner_->PostTask(FROM_HERE, base::Bind(
-      &ChromotingJniRuntime::DetachFromVmAndSignal,
-      base::Unretained(this),
-      &done_event));
+  network_task_runner()->PostTask(
+      FROM_HERE, base::Bind(&ChromotingJniRuntime::DetachFromVmAndSignal,
+                            base::Unretained(this), &done_event));
   done_event.Wait();
-  display_task_runner_->PostTask(FROM_HERE, base::Bind(
-      &ChromotingJniRuntime::DetachFromVmAndSignal,
-      base::Unretained(this),
-      &done_event));
+  display_task_runner()->PostTask(
+      FROM_HERE, base::Bind(&ChromotingJniRuntime::DetachFromVmAndSignal,
+                            base::Unretained(this), &done_event));
   done_event.Wait();
   base::android::LibraryLoaderExitHook();
   base::android::DetachFromVM();
@@ -236,7 +235,7 @@
                                          const std::string& pairing_secret,
                                          const std::string& capabilities,
                                          const std::string& flags) {
-  DCHECK(ui_task_runner_->BelongsToCurrentThread());
+  DCHECK(ui_task_runner()->BelongsToCurrentThread());
   DCHECK(!session_.get());
   session_ = new ChromotingJniInstance(this, username, auth_token, host_jid,
                                        host_id, host_pubkey, pairing_id,
@@ -244,7 +243,7 @@
 }
 
 void ChromotingJniRuntime::DisconnectFromHost() {
-  DCHECK(ui_task_runner_->BelongsToCurrentThread());
+  DCHECK(ui_task_runner()->BelongsToCurrentThread());
   if (session_.get()) {
     session_->Disconnect();
     session_ = nullptr;
@@ -254,14 +253,14 @@
 void ChromotingJniRuntime::OnConnectionState(
     protocol::ConnectionToHost::State state,
     protocol::ErrorCode error) {
-  DCHECK(ui_task_runner_->BelongsToCurrentThread());
+  DCHECK(ui_task_runner()->BelongsToCurrentThread());
 
   JNIEnv* env = base::android::AttachCurrentThread();
   Java_JniInterface_onConnectionState(env, state, error);
 }
 
 void ChromotingJniRuntime::DisplayAuthenticationPrompt(bool pairing_supported) {
-  DCHECK(ui_task_runner_->BelongsToCurrentThread());
+  DCHECK(ui_task_runner()->BelongsToCurrentThread());
 
   JNIEnv* env = base::android::AttachCurrentThread();
   Java_JniInterface_displayAuthenticationPrompt(env, pairing_supported);
@@ -270,7 +269,7 @@
 void ChromotingJniRuntime::CommitPairingCredentials(const std::string& host,
                                                     const std::string& id,
                                                     const std::string& secret) {
-  DCHECK(ui_task_runner_->BelongsToCurrentThread());
+  DCHECK(ui_task_runner()->BelongsToCurrentThread());
 
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jstring> j_host = ConvertUTF8ToJavaString(env, host);
@@ -284,7 +283,7 @@
 void ChromotingJniRuntime::FetchThirdPartyToken(const std::string& token_url,
                                                 const std::string& client_id,
                                                 const std::string& scope) {
-  DCHECK(ui_task_runner_->BelongsToCurrentThread());
+  DCHECK(ui_task_runner()->BelongsToCurrentThread());
   JNIEnv* env = base::android::AttachCurrentThread();
 
   ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, token_url);
@@ -297,7 +296,7 @@
 }
 
 void ChromotingJniRuntime::SetCapabilities(const std::string& capabilities) {
-  DCHECK(ui_task_runner_->BelongsToCurrentThread());
+  DCHECK(ui_task_runner()->BelongsToCurrentThread());
   JNIEnv* env = base::android::AttachCurrentThread();
 
   ScopedJavaLocalRef<jstring> j_cap =
@@ -308,7 +307,7 @@
 
 void ChromotingJniRuntime::HandleExtensionMessage(const std::string& type,
                                                   const std::string& message) {
-  DCHECK(ui_task_runner_->BelongsToCurrentThread());
+  DCHECK(ui_task_runner()->BelongsToCurrentThread());
   JNIEnv* env = base::android::AttachCurrentThread();
 
   ScopedJavaLocalRef<jstring> j_type = ConvertUTF8ToJavaString(env, type);
@@ -324,7 +323,7 @@
 }
 
 void ChromotingJniRuntime::UpdateFrameBitmap(jobject bitmap) {
-  DCHECK(display_task_runner_->BelongsToCurrentThread());
+  DCHECK(display_task_runner()->BelongsToCurrentThread());
 
   JNIEnv* env = base::android::AttachCurrentThread();
   Java_JniInterface_setVideoFrame(env, bitmap);
@@ -332,7 +331,7 @@
 
 void ChromotingJniRuntime::UpdateCursorShape(
     const protocol::CursorShapeInfo& cursor_shape) {
-  DCHECK(display_task_runner_->BelongsToCurrentThread());
+  DCHECK(display_task_runner()->BelongsToCurrentThread());
 
   // const_cast<> is safe as long as the Java updateCursorShape() method copies
   // the data out of the buffer without mutating it, and doesn't keep any
@@ -354,7 +353,7 @@
 }
 
 void ChromotingJniRuntime::RedrawCanvas() {
-  DCHECK(display_task_runner_->BelongsToCurrentThread());
+  DCHECK(display_task_runner()->BelongsToCurrentThread());
 
   JNIEnv* env = base::android::AttachCurrentThread();
   Java_JniInterface_redrawGraphicsInternal(env);
diff --git a/remoting/client/jni/chromoting_jni_runtime.h b/remoting/client/jni/chromoting_jni_runtime.h
index b6128c1e..8dedfcb 100644
--- a/remoting/client/jni/chromoting_jni_runtime.h
+++ b/remoting/client/jni/chromoting_jni_runtime.h
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "remoting/base/auto_thread.h"
+#include "remoting/client/chromoting_client_runtime.h"
 #include "remoting/client/jni/chromoting_jni_instance.h"
 #include "remoting/protocol/connection_to_host.h"
 
@@ -34,19 +35,19 @@
   static ChromotingJniRuntime* GetInstance();
 
   scoped_refptr<AutoThreadTaskRunner> ui_task_runner() {
-    return ui_task_runner_;
+    return runtime_->ui_task_runner();
   }
 
   scoped_refptr<AutoThreadTaskRunner> network_task_runner() {
-    return network_task_runner_;
+    return runtime_->network_task_runner();
   }
 
   scoped_refptr<AutoThreadTaskRunner> display_task_runner() {
-    return display_task_runner_;
+    return runtime_->display_task_runner();
   }
 
   scoped_refptr<net::URLRequestContextGetter> url_requester() {
-    return url_requester_;
+    return runtime_->url_requester();
   }
 
   // Initiates a connection with the specified host. Only call when a host
@@ -126,15 +127,13 @@
   // Detaches JVM from the current thread, then signals. Doesn't own |waiter|.
   void DetachFromVmAndSignal(base::WaitableEvent* waiter);
 
-  // Chromium code's connection to the Java message loop.
+  // Chromium code's connection to the app message loop. Once created the
+  // MessageLoop will live for the life of the program.
   scoped_ptr<base::MessageLoopForUI> ui_loop_;
 
-  // References to native threads.
-  scoped_refptr<AutoThreadTaskRunner> ui_task_runner_;
-  scoped_refptr<AutoThreadTaskRunner> network_task_runner_;
-  scoped_refptr<AutoThreadTaskRunner> display_task_runner_;
-
-  scoped_refptr<net::URLRequestContextGetter> url_requester_;
+  // Contains threads.
+  //
+  scoped_ptr<ChromotingClientRuntime> runtime_;
 
   // Contains all connection-specific state.
   scoped_refptr<ChromotingJniInstance> session_;
diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc
index e0ca0d5..a7c56018 100644
--- a/remoting/client/plugin/chromoting_instance.cc
+++ b/remoting/client/plugin/chromoting_instance.cc
@@ -1034,11 +1034,16 @@
   scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
   data->SetDouble("videoBandwidth", perf_tracker_.video_bandwidth());
   data->SetDouble("videoFrameRate", perf_tracker_.video_frame_rate());
-  data->SetDouble("captureLatency", perf_tracker_.video_capture_ms());
-  data->SetDouble("encodeLatency", perf_tracker_.video_encode_ms());
-  data->SetDouble("decodeLatency", perf_tracker_.video_decode_ms());
-  data->SetDouble("renderLatency", perf_tracker_.video_paint_ms());
-  data->SetDouble("roundtripLatency", perf_tracker_.round_trip_ms());
+  data->SetDouble("captureLatency", perf_tracker_.video_capture_ms().Average());
+  data->SetDouble("maxCaptureLatency", perf_tracker_.video_capture_ms().Max());
+  data->SetDouble("encodeLatency", perf_tracker_.video_encode_ms().Average());
+  data->SetDouble("maxEncodeLatency", perf_tracker_.video_encode_ms().Max());
+  data->SetDouble("decodeLatency", perf_tracker_.video_decode_ms().Average());
+  data->SetDouble("maxDecodeLatency", perf_tracker_.video_decode_ms().Max());
+  data->SetDouble("renderLatency", perf_tracker_.video_paint_ms().Average());
+  data->SetDouble("maxRenderLatency", perf_tracker_.video_paint_ms().Max());
+  data->SetDouble("roundtripLatency", perf_tracker_.round_trip_ms().Average());
+  data->SetDouble("maxRoundtripLatency", perf_tracker_.round_trip_ms().Max());
   PostLegacyJsonMessage("onPerfStats", std::move(data));
 }
 
diff --git a/remoting/client/server_log_entry_client.cc b/remoting/client/server_log_entry_client.cc
index 0686159..290165f 100644
--- a/remoting/client/server_log_entry_client.cc
+++ b/remoting/client/server_log_entry_client.cc
@@ -117,15 +117,15 @@
   entry->Set("video-bandwidth",
              StringPrintf("%.2f", perf_tracker->video_bandwidth()));
   entry->Set("capture-latency",
-             StringPrintf("%.2f", perf_tracker->video_capture_ms()));
+             StringPrintf("%.2f", perf_tracker->video_capture_ms().Average()));
   entry->Set("encode-latency",
-             StringPrintf("%.2f", perf_tracker->video_encode_ms()));
+             StringPrintf("%.2f", perf_tracker->video_encode_ms().Average()));
   entry->Set("decode-latency",
-             StringPrintf("%.2f", perf_tracker->video_decode_ms()));
+             StringPrintf("%.2f", perf_tracker->video_decode_ms().Average()));
   entry->Set("render-latency",
-             StringPrintf("%.2f", perf_tracker->video_frame_rate()));
+             StringPrintf("%.2f", perf_tracker->video_paint_ms().Average()));
   entry->Set("roundtrip-latency",
-             StringPrintf("%.2f", perf_tracker->round_trip_ms()));
+             StringPrintf("%.2f", perf_tracker->round_trip_ms().Average()));
 
   return entry;
 }
diff --git a/remoting/protocol/capture_scheduler.h b/remoting/protocol/capture_scheduler.h
index 54e2229d..3f4369ae 100644
--- a/remoting/protocol/capture_scheduler.h
+++ b/remoting/protocol/capture_scheduler.h
@@ -13,7 +13,7 @@
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "remoting/base/running_average.h"
+#include "remoting/base/running_samples.h"
 #include "remoting/protocol/video_feedback_stub.h"
 
 namespace remoting {
@@ -88,8 +88,8 @@
 
   int num_of_processors_;
 
-  RunningAverage capture_time_;
-  RunningAverage encode_time_;
+  RunningSamples capture_time_;
+  RunningSamples encode_time_;
 
   // Number of frames pending encoding.
   int num_encoding_frames_;
diff --git a/remoting/protocol/performance_tracker.h b/remoting/protocol/performance_tracker.h
index 3e5bf2c..c31ca91 100644
--- a/remoting/protocol/performance_tracker.h
+++ b/remoting/protocol/performance_tracker.h
@@ -13,7 +13,7 @@
 #include "base/macros.h"
 #include "base/timer/timer.h"
 #include "remoting/base/rate_counter.h"
-#include "remoting/base/running_average.h"
+#include "remoting/base/running_samples.h"
 
 namespace remoting {
 
@@ -49,11 +49,11 @@
   double video_bandwidth() { return video_bandwidth_.Rate(); }
   double video_frame_rate() { return video_frame_rate_.Rate(); }
   double video_packet_rate() { return video_packet_rate_.Rate(); }
-  double video_capture_ms() { return video_capture_ms_.Average(); }
-  double video_encode_ms() { return video_encode_ms_.Average(); }
-  double video_decode_ms() { return video_decode_ms_.Average(); }
-  double video_paint_ms() { return video_paint_ms_.Average(); }
-  double round_trip_ms() { return round_trip_ms_.Average(); }
+  const RunningSamples& video_capture_ms() { return video_capture_ms_; }
+  const RunningSamples& video_encode_ms() { return video_encode_ms_; }
+  const RunningSamples& video_decode_ms() { return video_decode_ms_; }
+  const RunningSamples& video_paint_ms() { return video_paint_ms_; }
+  const RunningSamples& round_trip_ms() { return round_trip_ms_; }
 
   // Record stats for a video-packet.
   void RecordVideoPacketStats(const VideoPacket& packet);
@@ -113,11 +113,11 @@
   // The following running-averages are uploaded to UMA per video packet and
   // also used for display to users, averaged over the N most recent samples.
   // N = kLatencySampleSize.
-  RunningAverage video_capture_ms_;
-  RunningAverage video_encode_ms_;
-  RunningAverage video_decode_ms_;
-  RunningAverage video_paint_ms_;
-  RunningAverage round_trip_ms_;
+  RunningSamples video_capture_ms_;
+  RunningSamples video_encode_ms_;
+  RunningSamples video_decode_ms_;
+  RunningSamples video_paint_ms_;
+  RunningSamples round_trip_ms_;
 
   // Used to update UMA stats, if set.
   UpdateUmaCustomHistogramCallback uma_custom_counts_updater_;
diff --git a/remoting/remoting_client.gypi b/remoting/remoting_client.gypi
index e0edbde..91628825 100644
--- a/remoting/remoting_client.gypi
+++ b/remoting/remoting_client.gypi
@@ -20,6 +20,7 @@
       ],
       'sources': [
         '<@(remoting_client_sources)',
+        '<@(remoting_client_standalone_sources)',
       ],
       'conditions': [
         ['buildtype!="Official"', {
diff --git a/remoting/remoting_srcs.gypi b/remoting/remoting_srcs.gypi
index 7bc06823..4ab56405 100644
--- a/remoting/remoting_srcs.gypi
+++ b/remoting/remoting_srcs.gypi
@@ -25,8 +25,8 @@
       'base/rate_counter.h',
       'base/rsa_key_pair.cc',
       'base/rsa_key_pair.h',
-      'base/running_average.cc',
-      'base/running_average.h',
+      'base/running_samples.cc',
+      'base/running_samples.h',
       'base/scoped_sc_handle_win.h',
       'base/service_urls.cc',
       'base/service_urls.h',
@@ -299,6 +299,11 @@
       'client/touch_input_scaler.h',
     ],
 
+    'remoting_client_standalone_sources': [
+      'client/chromoting_client_runtime.cc',
+      'client/chromoting_client_runtime.h',
+    ],
+
     'remoting_client_plugin_sources': [
       'client/plugin/chromoting_instance.cc',
       'client/plugin/chromoting_instance.h',
diff --git a/remoting/remoting_test.gypi b/remoting/remoting_test.gypi
index 19b904cd..5f193e9 100644
--- a/remoting/remoting_test.gypi
+++ b/remoting/remoting_test.gypi
@@ -232,11 +232,12 @@
         'base/rate_counter_unittest.cc',
         'base/rsa_key_pair_unittest.cc',
         'base/run_all_unittests.cc',
-        'base/running_average_unittest.cc',
+        'base/running_samples_unittest.cc',
         'base/test_rsa_key_pair.h',
         'base/typed_buffer_unittest.cc',
         'base/util_unittest.cc',
         'client/audio_player_unittest.cc',
+        'client/chromoting_client_runtime_unittest.cc',
         'client/client_status_logger_unittest.cc',
         'client/empty_cursor_filter_unittest.cc',
         'client/key_event_mapper_unittest.cc',
diff --git a/remoting/webapp/base/js/chromoting_event.js b/remoting/webapp/base/js/chromoting_event.js
index 476f879c..0f6fedd 100644
--- a/remoting/webapp/base/js/chromoting_event.js
+++ b/remoting/webapp/base/js/chromoting_event.js
@@ -79,6 +79,16 @@
   this.render_latency;
   /** @type {number} */
   this.roundtrip_latency;
+  /** @type {number} */
+  this.max_capture_latency;
+  /** @type {number} */
+  this.max_encode_latency;
+  /** @type {number} */
+  this.max_decode_latency;
+  /** @type {number} */
+  this.max_render_latency;
+  /** @type {number} */
+  this.max_roundtrip_latency;
   /** @type {remoting.ChromotingEvent.Mode} */
   this.mode;
   /** @type {remoting.ChromotingEvent.SignalStrategyType} */
diff --git a/remoting/webapp/base/js/connection_stats.js b/remoting/webapp/base/js/connection_stats.js
index d08a527..61d5680 100644
--- a/remoting/webapp/base/js/connection_stats.js
+++ b/remoting/webapp/base/js/connection_stats.js
@@ -123,23 +123,36 @@
   /**
    * @param {number} value
    * @param {string} units
+   * @param {number} digits
    * @return {string} Formatted number.
    */
-  function formatStatNumber(value, units) {
+  function formatStatNumber(value, units, digits) {
     if (value != undefined) {
-      return value.toFixed(2) + ' ' + units;
+      return value.toFixed(digits) + ' ' + units;
     } else {
       return "n/a";
     }
   }
 
+  /**
+   * @param {string} type
+   * @param {number} avg
+   * @param {number} max
+   * @return {string} "type: avg, max; " e.g. "RTT: 8.0, 13; "
+   */
+  function formatStat(type, avg, max) {
+    return type + ': ' + avg.toFixed(1) + ', ' + max + '; ';
+  }
+
   var statistics = document.getElementById('statistics');
   this.statsElement_.innerText = (
-      'Bandwidth: ' + formatStatNumber(videoBandwidth, units) +
-      ', Frame Rate: ' + formatStatNumber(stats.videoFrameRate, 'fps') +
-      ', Capture: ' + formatStatNumber(stats.captureLatency, 'ms') +
-      ', Encode: ' + formatStatNumber(stats.encodeLatency, 'ms') +
-      ', Decode: ' + formatStatNumber(stats.decodeLatency, 'ms') +
-      ', Render: ' + formatStatNumber(stats.renderLatency, 'ms') +
-      ', Latency: ' + formatStatNumber(stats.roundtripLatency, 'ms'));
+      '(avg, max in ms) ' +
+      formatStat('Capture', stats.captureLatency, stats.maxCaptureLatency) +
+      formatStat('Encode', stats.encodeLatency, stats.maxEncodeLatency) +
+      formatStat('Decode', stats.decodeLatency, stats.maxDecodeLatency) +
+      formatStat('Render', stats.renderLatency, stats.maxRenderLatency) +
+      formatStat('RTT', stats.roundtripLatency, stats.maxRoundtripLatency) +
+      'Bandwidth: ' + formatStatNumber(videoBandwidth, units, 2) + '; ' +
+      'Frame Rate: ' + formatStatNumber(stats.videoFrameRate, 'fps', 1)
+    );
 };
diff --git a/remoting/webapp/base/js/session_logger.js b/remoting/webapp/base/js/session_logger.js
index 6f26c9a..4e4eba9 100644
--- a/remoting/webapp/base/js/session_logger.js
+++ b/remoting/webapp/base/js/session_logger.js
@@ -291,6 +291,11 @@
     entry.decode_latency = perfStats.decodeLatency;
     entry.render_latency = perfStats.renderLatency;
     entry.roundtrip_latency = perfStats.roundtripLatency;
+    entry.max_capture_latency = perfStats.maxCaptureLatency;
+    entry.max_encode_latency = perfStats.maxEncodeLatency;
+    entry.max_decode_latency = perfStats.maxDecodeLatency;
+    entry.max_render_latency = perfStats.maxRenderLatency;
+    entry.max_roundtrip_latency = perfStats.maxRoundtripLatency;
     return entry;
   }
   return null;
diff --git a/remoting/webapp/base/js/stats_accumulator.js b/remoting/webapp/base/js/stats_accumulator.js
index e0edd49..e8bda09f 100644
--- a/remoting/webapp/base/js/stats_accumulator.js
+++ b/remoting/webapp/base/js/stats_accumulator.js
@@ -94,6 +94,26 @@
 };
 
 /**
+ * Finds the max of the values for a given key.
+ *
+ * @param {string} key
+ * @return {number} the max of the values for that key
+ */
+remoting.StatsAccumulator.prototype.calcMax = function(key) {
+  /**
+   * @param {Array<number>} values
+   * @return {number}
+   */
+  var calcMax = function(values) {
+    if (!values || !values.length) {
+      return 0;
+    }
+    return Math.max.apply(null, values);
+  };
+  return this.map(key, calcMax);
+};
+
+/**
  * Applies a given map to the list of values for a given key.
  *
  * @param {string} key
@@ -131,10 +151,15 @@
   var stats = new remoting.ClientSession.PerfStats();
   stats.videoBandwidth = this.calcMean('videoBandwidth');
   stats.captureLatency = this.calcMean('captureLatency');
+  stats.maxCaptureLatency = this.calcMax('maxCaptureLatency');
   stats.encodeLatency = this.calcMean('encodeLatency');
+  stats.maxEncodeLatency = this.calcMax('maxEncodeLatency');
   stats.decodeLatency = this.calcMean('decodeLatency');
+  stats.maxDecodeLatency = this.calcMax('maxDecodeLatency');
   stats.renderLatency = this.calcMean('renderLatency');
+  stats.maxRenderLatency = this.calcMax('maxRenderLatency');
   stats.roundtripLatency = this.calcMean('roundtripLatency');
+  stats.maxRoundtripLatency = this.calcMax('maxRoundtripLatency');
 
   for (var key in stats) {
     if (stats[key] !== 0) {
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 570f94a..cdbefdb 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -441,6 +441,9 @@
 crbug.com/580355 virtual/spv2/fast/block/margin-collapse/block-inside-inline/020.html [ Pass ]
 crbug.com/580355 virtual/spv2/fast/block/positioning/height-change.html [ Pass ]
 crbug.com/580355 virtual/spv2/fast/block/positioning/relayout-on-position-change.html [ Pass ]
+crbug.com/596780 virtual/spv2/compositing/framesets/composited-frame-alignment.html [ Pass ]
+crbug.com/596780 virtual/spv2/compositing/geometry/outline-change.html [ Pass ]
+crbug.com/596780 virtual/spv2/compositing/squashing/incorrect-clip-after-remove-compositing.html [ Pass ]
 
 crbug.com/563667 virtual/spv2/fast/overflow/007.html [ Failure ]
 crbug.com/537409 virtual/spv2/fast/overflow [ Pass ]
@@ -461,6 +464,8 @@
 crbug.com/589265 virtual/spv2/fast/overflow/overflow-text-hit-testing.html [ Failure ]
 crbug.com/589265 virtual/spv2/fast/overflow/overflow-with-local-background-attachment.html [ Failure ]
 crbug.com/589265 virtual/spv2/fast/overflow/scrollbar-position-update.html [ Failure ]
+crbug.com/589265 virtual/spv2/compositing/geometry/root-layer-update.html [ Failure ]
+
 # Implement scrollbars in FramePainter for SPv2
 crbug.com/589279 virtual/spv2/fast/overflow/006.html [ Failure ]
 crbug.com/589279 virtual/spv2/fast/overflow/hidden-viewport-x.html [ Failure ]
@@ -483,6 +488,17 @@
 crbug.com/587970 virtual/spv2/compositing/plugins/webplugin-alpha.html [ Pass ]
 crbug.com/587970 virtual/spv2/compositing/plugins/webplugin-no-alpha.html [ Pass ]
 
+# These failures have been manually verified to be only paint invalidation text differences.
+crbug.com/596780 virtual/spv2/compositing/geometry/bounds-clipped-composited-child.html [ Failure ]
+crbug.com/596780 virtual/spv2/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html [ Failure ]
+crbug.com/596780 virtual/spv2/compositing/geometry/bounds-ignores-hidden-dynamic.html [ Failure ]
+crbug.com/596780 virtual/spv2/compositing/rtl/rtl-iframe-absolute-overflow.html [ Failure ]
+crbug.com/596780 virtual/spv2/compositing/rtl/rtl-iframe-absolute.html [ Failure ]
+crbug.com/596780 virtual/spv2/compositing/rtl/rtl-iframe-fixed-overflow.html [ Failure ]
+crbug.com/596780 virtual/spv2/compositing/rtl/rtl-iframe-fixed.html [ Failure ]
+crbug.com/596780 virtual/spv2/compositing/rtl/rtl-iframe-relative.html [ Failure ]
+crbug.com/596780 virtual/spv2/compositing/visibility/layer-visible-content.html [ Failure ]
+
 # In imported/web-platform-tests/html/, we prefer checking in failure
 # expectation files. The following tests with [ Failure ] don't have failure
 # expectation files because they contain local path names.
@@ -575,10 +591,7 @@
 crbug.com/318978 [ Linux ] plugins/embed-prefers-plugins-for-images.html [ Skip ]
 crbug.com/318978 [ Linux ] plugins/form-value.html [ Skip ]
 crbug.com/318978 [ Linux ] plugins/fullscreen-plugins-dont-reload.html [ Skip ]
-crbug.com/318978 [ Linux ] plugins/instance-available-before-stylesheets-loaded-object.html [ Skip ]
-crbug.com/318978 [ Linux ] plugins/instance-available-before-stylesheets-loaded.html [ Skip ]
 crbug.com/318978 [ Linux ] plugins/no-mime-with-valid-extension.html [ Skip ]
-crbug.com/318978 [ Linux ] plugins/open-and-close-window-with-plugin.html [ Skip ]
 crbug.com/318978 [ Linux ] plugins/override-node-method.html [ Skip ]
 crbug.com/318978 [ Linux ] plugins/plugin-destroyed-enumerate.html [ Skip ]
 crbug.com/318978 [ Linux ] plugins/plugin-remove-subframe.html [ Skip ]
@@ -902,9 +915,6 @@
 crbug.com/305346 virtual/pointerevent/fast/events/mouseover-mouseout.html [ Failure Pass ]
 crbug.com/305346 virtual/trustedeventsdefaultaction/fast/events/mouseover-mouseout.html [ Failure Pass ]
 
-# Disabled until the test plugin is fixed.
-crbug.com/363099 [ Win ] plugins/open-and-close-window-with-plugin.html [ Failure ]
-
 crbug.com/425345 [ Mac ] fast/text/line-break-after-question-mark.html [ Failure ]
 
 crbug.com/574283 [ Mac ] virtual/threaded/fast/scroll-behavior/smooth-scroll/mousewheel-scroll-interrupted.html [ Skip ]
@@ -1300,7 +1310,7 @@
 
 crbug.com/320139 fast/repaint/block-layout-inline-children-replaced.html [ Pass Failure ]
 
-crbug.com/596486 [ Linux Debug ] inspector/elements/edit/edit-dom-actions.html [ Timeout Pass ]
+crbug.com/596486 [ Debug ] inspector/elements/edit/edit-dom-actions.html [ Timeout Pass ]
 
 crbug.com/575766 http/tests/inspector/resource-tree/resource-tree-frame-add.html [ Timeout Pass ]
 crbug.com/581468 http/tests/inspector/resource-tree/resource-tree-non-unique-url.html [ Pass Failure ]
@@ -1332,8 +1342,6 @@
 
 crbug.com/577380 [ Linux Debug ] http/tests/serviceworker/chromium/registration-stress.html [ Failure ]
 
-crbug.com/577746 [ Linux Debug ] compositing/iframes/iframe-in-composited-layer.html [ Pass Failure ]
-
 crbug.com/581038 fast/text/first-letter-bad-line-boxes-crash.html [ Crash Pass ]
 
 crbug.com/587136 [ Linux Debug ] http/tests/security/xss-DENIED-cross-origin-stack-overflow.html [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/compositing/iframes/iframe-in-composited-layer.html b/third_party/WebKit/LayoutTests/compositing/iframes/iframe-in-composited-layer.html
index 06ee898..e711777 100644
--- a/third_party/WebKit/LayoutTests/compositing/iframes/iframe-in-composited-layer.html
+++ b/third_party/WebKit/LayoutTests/compositing/iframes/iframe-in-composited-layer.html
@@ -3,8 +3,19 @@
     <i><a href="https://bugs.webkit.org/show_bug.cgi?id=38427">https://bugs.webkit.org/show_bug.cgi?id=38427</a>
     <rdar://problem/7932072> Iframes in composited layers don&rsquo;t repaint correctly (affects Yahoo! Mail with Flash Player 10.1)</i>.
 <-->
+<script>
+    if (window.testRunner)
+        testRunner.waitUntilDone();
+
+    function runTest() {
+        document.getElementById("frame").contentWindow.scrollTo(600, 600);
+        if (window.testRunner)
+            testRunner.notifyDone();
+    }
+</script>
+
 <div style="transform: translateZ(0); width: 400px; height: 400px; background-color: lightyellow;">
-    <iframe id="frame" style="width: 380px; height: 380px; border: solid; margin: 7px" src="data:text/html,
+    <iframe id="frame"  onload="runTest()" style="width: 380px; height: 380px; border: solid; margin: 7px" src="data:text/html,
         <html style='height: 900px; width: 900px; position: relative;'>
             <body>
                 <div style='position: absolute; width: 100px; height: 100px; background-color: red; left: 0; top: 0;'></div>
@@ -13,13 +24,3 @@
         </html>
     "></iframe>
 </div>
-<script>
-    if (window.testRunner)
-        testRunner.waitUntilDone();
-
-    setTimeout(function() {
-        document.getElementById("frame").contentWindow.scrollTo(600, 600);
-        if (window.testRunner)
-            testRunner.notifyDone();
-    }, 200);
-</script>
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-empty-font-family-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-empty-font-family-expected.txt
new file mode 100644
index 0000000..053e4fa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-empty-font-family-expected.txt
@@ -0,0 +1,12 @@
+Font attributes. The font-family should list the empty string:
+
+font-family: "";
+font-kerning: auto;
+font-size: 16px;
+font-size-adjust: none;
+font-stretch: normal;
+font-style: normal;
+font-variant: normal;
+font-variant-ligatures: normal;
+font-weight: normal;
+
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-empty-font-family.html b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-empty-font-family.html
new file mode 100644
index 0000000..3e0376e3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-empty-font-family.html
@@ -0,0 +1,21 @@
+<script>
+function test()
+{
+    if (window.testRunner)
+        testRunner.dumpAsText();
+    var style = document.defaultView.getComputedStyle(document.body, "");
+    var text = "";
+    for (var i = 0; i != style.length; ++i) {
+        var name = style.item(i);
+        if (!name.match(/^font/))
+            continue;
+        var value = style.getPropertyValue(name);
+        text += name + ": " + value + ";\n";
+    }
+    document.getElementById("exposed").textContent = text;
+}
+</script>
+<body onload="test()" style="font-family: ''">
+<p>Font attributes. The font-family should list the empty string:</p>
+<p id="exposed" style="white-space: pre"></p>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLDialogElement/inert-node-is-unfocusable.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLDialogElement/inert-node-is-unfocusable.html
index 631e6d4..9e2e6b4 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLDialogElement/inert-node-is-unfocusable.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLDialogElement/inert-node-is-unfocusable.html
@@ -17,7 +17,7 @@
     </select>
     <div id="contenteditable-div" contenteditable>I'm editable</div>
     <span id="tabindex-span" tabindex="0">I'm tabindexed.</div>
-    <embed id="embed" type="application/x-webkit-test-netscape" width=100 height=100></embed>
+    <embed id="embed" type="application/x-blink-test-plugin" width=100 height=100></embed>
     <a id="anchor" href="">Link</a>
 </div>
 <script>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/text/text-set-selection-crash.html b/third_party/WebKit/LayoutTests/fast/forms/text/text-set-selection-crash.html
index b4615c3..c098336 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/text/text-set-selection-crash.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/text/text-set-selection-crash.html
@@ -1,6 +1,6 @@
 <body>
 <script src="../../../resources/js-test.js"></script>
-<applet code=""><input><embed type="application/x-webkit-test-netscape" width="200"></embed></applet>
+<applet code=""><input><embed type="application/x-blink-test-plugin" width="200"></embed></applet>
 <script>
 description('There was a bug that HTMLTextFormControlElement::setSelectionRange crashed. This test requires ASAN or something.');
 jsTestIsAsync = true;
diff --git a/third_party/WebKit/LayoutTests/fast/layers/clip-rects-transformed-2.html b/third_party/WebKit/LayoutTests/fast/layers/clip-rects-transformed-2.html
index f6116b2e3..54a594f 100644
--- a/third_party/WebKit/LayoutTests/fast/layers/clip-rects-transformed-2.html
+++ b/third_party/WebKit/LayoutTests/fast/layers/clip-rects-transformed-2.html
@@ -13,6 +13,6 @@
 <div style="transform: translateZ(0); position: absolute;"></div>
 <div style="opacity: 0.9">
     <div style="position: absolute;">
-        <embed type="application/x-webkit-test-netscape">
+        <embed type="application/x-blink-test-plugin">
     </div>
 </div>
diff --git a/third_party/WebKit/LayoutTests/fast/layers/clip-rects-transformed.html b/third_party/WebKit/LayoutTests/fast/layers/clip-rects-transformed.html
index a7e858bd..a1d51cda 100644
--- a/third_party/WebKit/LayoutTests/fast/layers/clip-rects-transformed.html
+++ b/third_party/WebKit/LayoutTests/fast/layers/clip-rects-transformed.html
@@ -12,6 +12,6 @@
 </p>
 <div style="transform: translateX(100px);">
     <div style="position: absolute; overflow: hidden;">
-        <embed type="application/x-webkit-test-netscape">
+        <embed type="application/x-blink-test-plugin">
     </div>
 </div>
diff --git a/third_party/WebKit/LayoutTests/fast/loader/reload-zero-byte-plugin-expected.txt b/third_party/WebKit/LayoutTests/fast/loader/reload-zero-byte-plugin-expected.txt
index dbb973a..db2202d 100644
--- a/third_party/WebKit/LayoutTests/fast/loader/reload-zero-byte-plugin-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/loader/reload-zero-byte-plugin-expected.txt
@@ -1 +1,3 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
+CONSOLE MESSAGE: Blink Test Plugin: initializing
 This test passes if it doesn't crash. To run manually, please disable your popup blocker.
diff --git a/third_party/WebKit/LayoutTests/fast/loader/reload-zero-byte-plugin.html b/third_party/WebKit/LayoutTests/fast/loader/reload-zero-byte-plugin.html
index d305fe5..37f8f87f 100644
--- a/third_party/WebKit/LayoutTests/fast/loader/reload-zero-byte-plugin.html
+++ b/third_party/WebKit/LayoutTests/fast/loader/reload-zero-byte-plugin.html
@@ -6,7 +6,7 @@
     testRunner.setCloseRemainingWindowsWhenComplete(true);
 }
 
-var win = window.open('data:application/x-webkit-test-netscape,');
+var win = window.open('data:application/x-blink-test-plugin,');
 setTimeout(function() {
     win.location.reload();
     setTimeout(function() {
diff --git a/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-embed-expected.txt b/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-embed-expected.txt
index cca205b..80dfe3c 100644
--- a/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-embed-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-embed-expected.txt
@@ -1,3 +1,7 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
+CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(true)
+CONSOLE MESSAGE: Blink Test Plugin: MouseDown at (5,5)
+CONSOLE MESSAGE: Blink Test Plugin: MouseUp at (5,5)
 
 This test requires DumpRenderTree. Click the orange border, a focus ring should not appear. 
 EMBED Event: focus PASS
diff --git a/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-embed.html b/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-embed.html
index acccf8f1..fda5729 100644
--- a/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-embed.html
+++ b/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-embed.html
@@ -3,7 +3,7 @@
   #test { border: 20px solid orange; background-color: blue }
 </style>
 
-<embed id="test" tabIndex="1" type="application/x-webkit-test-netscape" windowedPlugin="false"><br>
+<embed id="test" tabIndex="1" type="application/x-blink-test-plugin"><br>
 This test requires DumpRenderTree. Click the orange border, a focus ring should not appear.
 
 <script src="resources/focus-test.js"></script>
diff --git a/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-object-expected.txt b/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-object-expected.txt
index 7c4a35c4..ae8f70c 100644
--- a/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-object-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-object-expected.txt
@@ -1,3 +1,7 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
+CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(true)
+CONSOLE MESSAGE: Blink Test Plugin: MouseDown at (5,5)
+CONSOLE MESSAGE: Blink Test Plugin: MouseUp at (5,5)
 
 This test requires DumpRenderTree. Click the orange border, a focus ring should not appear. 
 OBJECT Event: focus PASS
diff --git a/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-object.html b/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-object.html
index 2bd13d0..c95005bc 100644
--- a/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-object.html
+++ b/third_party/WebKit/LayoutTests/fast/replaced/no-focus-ring-object.html
@@ -3,8 +3,7 @@
   #test { border: 20px solid orange; background-color: blue }
 </style>
 
-<object id="test" tabIndex="1" type="application/x-webkit-test-netscape">
-  <param name="windowedPlugin" value="false">
+<object id="test" tabIndex="1" type="application/x-blink-test-plugin">
 </object><br>
 This test requires DumpRenderTree. Click the orange border, a focus ring should not appear.
 
diff --git a/third_party/WebKit/LayoutTests/fast/replaced/object-with-non-empty-classid-triggers-fallback.html b/third_party/WebKit/LayoutTests/fast/replaced/object-with-non-empty-classid-triggers-fallback.html
index d06f8bfe..98c861d 100644
--- a/third_party/WebKit/LayoutTests/fast/replaced/object-with-non-empty-classid-triggers-fallback.html
+++ b/third_party/WebKit/LayoutTests/fast/replaced/object-with-non-empty-classid-triggers-fallback.html
@@ -7,7 +7,7 @@
     object with classid attribute but no type attribute renders fallback: PASS
 </object>
 <br>
-<object id="obj" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" type=application/x-webkit-test-netscape">
+<object id="obj" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" type=application/x-blink-test-plugin">
     object with classid and type attributes renders fallback: PASS
 </object>
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/register-link-element.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/register-link-element.html
new file mode 100644
index 0000000..0792ded0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/register-link-element.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharness-helpers.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="resources/test-helpers.js"></script>
+<script src="resources/registration-tests.js"></script>
+<body>
+<script>
+
+function registerUsingLink(script, options) {
+  var scope = options.scope;
+  var link = document.createElement('link');
+  link.setAttribute('rel', 'serviceworker');
+  link.setAttribute('href', script);
+  link.setAttribute('scope', scope);
+  document.getElementsByTagName('head')[0].appendChild(link);
+  return new Promise(function(resolve, reject) {
+        link.onload = resolve;
+        link.onerror = reject;
+      })
+    .then(() => navigator.serviceWorker.getRegistration(scope));
+}
+
+registration_tests(registerUsingLink, false);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/registration.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/registration.html
index 7c03bba..6ad5aec 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/registration.html
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/registration.html
@@ -4,383 +4,7 @@
 <script src="../resources/testharness-helpers.js"></script>
 <script src="../resources/testharnessreport.js"></script>
 <script src="resources/test-helpers.js"></script>
+<script src="resources/registration-tests.js"></script>
 <script>
-
-promise_test(function(t) {
-    var script = 'resources/registration-worker.js';
-    var scope = 'resources/registration/normal';
-    return navigator.serviceWorker.register(script, {scope: scope})
-      .then(function(registration) {
-          assert_true(registration instanceof ServiceWorkerRegistration,
-                      'Successfully registered.');
-          service_worker_unregister_and_done(t, scope);
-        })
-  }, 'Registering normal scope');
-
-promise_test(function(t) {
-    var script = 'resources/registration-worker.js';
-    var scope = 'resources/registration/scope-with-fragment#ref';
-    return navigator.serviceWorker.register(script, {scope: scope})
-      .then(function(registration) {
-          assert_true(
-            registration instanceof ServiceWorkerRegistration,
-            'Successfully registered.');
-          assert_equals(
-            registration.scope,
-            normalizeURL('resources/registration/scope-with-fragment'),
-            'A fragment should be removed from scope')
-          service_worker_unregister_and_done(t, scope);
-        })
-  }, 'Registering scope with fragment');
-
-promise_test(function(t) {
-    var script = 'resources/registration-worker.js';
-    var scope = 'resources/';
-    return navigator.serviceWorker.register(script, {scope: scope})
-      .then(function(registration) {
-          assert_true(registration instanceof ServiceWorkerRegistration,
-                      'Successfully registered.');
-          service_worker_unregister_and_done(t, scope);
-        })
-  }, 'Registering same scope as the script directory');
-
-promise_test(function(t) {
-    var script = 'resources/registration-worker.js';
-    var scope = 'resources';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'SecurityError',
-        'Registering same scope as the script directory without the last ' +
-            'slash should fail with SecurityError.');
-  }, 'Registering same scope as the script directory without the last slash');
-
-promise_test(function(t) {
-    var script = 'resources/registration-worker.js';
-    var scope = 'different-directory/';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'SecurityError',
-        'Registration scope outside the script directory should fail ' +
-            'with SecurityError.');
-  }, 'Registration scope outside the script directory');
-
-promise_test(function(t) {
-    var script = 'resources/registration-worker.js';
-    var scope = 'http://example.com/';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'SecurityError',
-        'Registration scope outside domain should fail with SecurityError.');
-  }, 'Registering scope outside domain');
-
-promise_test(function(t) {
-    var script = 'http://example.com/worker.js';
-    var scope = 'http://example.com/scope/';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'SecurityError',
-        'Registration script outside domain should fail with SecurityError.');
-  }, 'Registering script outside domain');
-
-promise_test(function(t) {
-    var script = 'resources/no-such-worker.js';
-    var scope = 'resources/scope/no-such-worker';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'NetworkError',
-        'Registration of non-existent script should fail.');
-  }, 'Registering non-existent script');
-
-promise_test(function(t) {
-    var script = 'resources/invalid-chunked-encoding.php';
-    var scope = 'resources/scope/invalid-chunked-encoding/';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'NetworkError',
-        'Registration of invalid chunked encoding script should fail.');
-  }, 'Registering invalid chunked encoding script');
-
-promise_test(function(t) {
-    var script = 'resources/invalid-chunked-encoding-with-flush.php';
-    var scope = 'resources/scope/invalid-chunked-encoding-with-flush/';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'NetworkError',
-        'Registration of invalid chunked encoding script should fail.');
-  }, 'Registering invalid chunked encoding script with flush');
-
-promise_test(function(t) {
-    var script = 'resources/mime-type-worker.php';
-    var scope = 'resources/scope/no-mime-type-worker/';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'SecurityError',
-        'Registration of no MIME type script should fail.');
-  }, 'Registering script with no MIME type');
-
-promise_test(function(t) {
-    var script = 'resources/mime-type-worker.php?mime=text/plain';
-    var scope = 'resources/scope/bad-mime-type-worker/';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'SecurityError',
-        'Registration of plain text script should fail.');
-  }, 'Registering script with bad MIME type');
-
-promise_test(function(t) {
-    var script = 'resources/redirect.php?Redirect=' +
-                  encodeURIComponent('/resources/registration-worker.js');
-    var scope = 'resources/scope/redirect/';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'SecurityError',
-        'Registration of redirected script should fail.');
-  }, 'Registering redirected script');
-
-promise_test(function(t) {
-    var script = 'resources/malformed-worker.php?parse-error';
-    var scope = 'resources/scope/parse-error';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'AbortError',
-        'Registration of script including parse error should fail.');
-  }, 'Registering script including parse error');
-
-promise_test(function(t) {
-    var script = 'resources/malformed-worker.php?undefined-error';
-    var scope = 'resources/scope/undefined-error';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'AbortError',
-        'Registration of script including undefined error should fail.');
-  }, 'Registering script including undefined error');
-
-promise_test(function(t) {
-    var script = 'resources/malformed-worker.php?uncaught-exception';
-    var scope = 'resources/scope/uncaught-exception';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'AbortError',
-        'Registration of script including uncaught exception should fail.');
-  }, 'Registering script including uncaught exception');
-
-promise_test(function(t) {
-    var script = 'resources/malformed-worker.php?caught-exception';
-    var scope = 'resources/scope/caught-exception';
-    return navigator.serviceWorker.register(script, {scope: scope})
-        .then(function(registration) {
-            assert_true(registration instanceof ServiceWorkerRegistration,
-                        'Successfully registered.');
-            service_worker_unregister_and_done(t, scope);
-          })
-  }, 'Registering script including caught exception');
-
-promise_test(function(t) {
-    var script = 'resources/malformed-worker.php?import-malformed-script';
-    var scope = 'resources/scope/import-malformed-script';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'AbortError',
-        'Registration of script importing malformed script should fail.');
-  }, 'Registering script importing malformed script');
-
-promise_test(function(t) {
-    var script = 'resources/malformed-worker.php?import-no-such-script';
-    var scope = 'resources/scope/import-no-such-script';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'AbortError',
-        'Registration of script importing non-existent script should fail.');
-  }, 'Registering script importing non-existent script');
-
-promise_test(function(t) {
-    // URL-encoded full-width 'scope'.
-    var name = '%ef%bd%93%ef%bd%83%ef%bd%8f%ef%bd%90%ef%bd%85';
-    var script = 'resources/empty-worker.js';
-    var scope = 'resources/' + name + '/escaped-multibyte-character-scope';
-    return navigator.serviceWorker.register(script, {scope: scope})
-      .then(function(registration) {
-          assert_equals(
-            registration.scope,
-            normalizeURL(scope),
-            'URL-encoded multibyte characters should be available.');
-          service_worker_unregister_and_done(t, scope);
-        });
-  }, 'Scope including URL-encoded multibyte characters');
-
-promise_test(function(t) {
-    // Non-URL-encoded full-width "scope".
-    var name = String.fromCodePoint(0xff53, 0xff43, 0xff4f, 0xff50, 0xff45);
-    var script = 'resources/empty-worker.js';
-    var scope = 'resources/' + name  + '/non-escaped-multibyte-character-scope';
-    return navigator.serviceWorker.register(script, {scope: scope})
-      .then(function(registration) {
-          assert_equals(
-            registration.scope,
-            normalizeURL(scope),
-            'Non-URL-encoded multibyte characters should be available.');
-          service_worker_unregister_and_done(t, scope);
-        });
-  }, 'Scope including non-escaped multibyte characters');
-
-promise_test(function(t) {
-    var script = 'resources%2fempty-worker.js';
-    var scope = 'resources/scope/encoded-slash-in-script-url';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        new TypeError,
-        'URL-encoded slash in the script URL should be rejected.');
-  }, 'Script URL including URL-encoded slash');
-
-promise_test(function(t) {
-    var script = 'resources%2Fempty-worker.js';
-    var scope = 'resources/scope/encoded-slash-in-script-url';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        new TypeError,
-        'URL-encoded slash in the script URL should be rejected.');
-  }, 'Script URL including uppercase URL-encoded slash');
-
-promise_test(function(t) {
-    var script = 'resources/empty-worker.js';
-    var scope = 'resources/scope%2fencoded-slash-in-scope';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        new TypeError,
-        'URL-encoded slash in the scope should be rejected.');
-  }, 'Scope including URL-encoded slash');
-
-promise_test(function(t) {
-    var script = 'resources%5cempty-worker.js';
-    var scope = 'resources/scope/encoded-slash-in-script-url';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        new TypeError,
-        'URL-encoded backslash in the script URL should be rejected.');
-  }, 'Script URL including URL-encoded backslash');
-
-promise_test(function(t) {
-    var script = 'resources%5Cempty-worker.js';
-    var scope = 'resources/scope/encoded-slash-in-script-url';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        new TypeError,
-        'URL-encoded backslash in the script URL should be rejected.');
-  }, 'Script URL including uppercase URL-encoded backslash');
-
-promise_test(function(t) {
-    var script = 'resources/empty-worker.js';
-    var scope = 'resources/scope%5cencoded-slash-in-scope';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        new TypeError,
-        'URL-encoded backslash in the scope should be rejected.');
-  }, 'Scope including URL-encoded backslash');
-
-promise_test(function(t) {
-    var script = 'resources/././empty-worker.js';
-    var scope = 'resources/scope/parent-reference-in-script-url';
-    return navigator.serviceWorker.register(script, {scope: scope})
-      .then(function(registration) {
-          assert_equals(
-            registration.installing.scriptURL,
-            normalizeURL('resources/empty-worker.js'),
-            'Script URL including self-reference should be normalized.');
-          service_worker_unregister_and_done(t, scope);
-        });
-  }, 'Script URL including self-reference');
-
-promise_test(function(t) {
-    var script = 'resources/empty-worker.js';
-    var scope = 'resources/././scope/self-reference-in-scope';
-    return navigator.serviceWorker.register(script, {scope: scope})
-      .then(function(registration) {
-          assert_equals(
-            registration.scope,
-            normalizeURL('resources/scope/self-reference-in-scope'),
-            'Scope including self-reference should be normalized.');
-          service_worker_unregister_and_done(t, scope);
-        });
-  }, 'Scope including self-reference');
-
-promise_test(function(t) {
-    var script = 'resources/../resources/empty-worker.js';
-    var scope = 'resources/scope/parent-reference-in-script-url';
-    return navigator.serviceWorker.register(script, {scope: scope})
-      .then(function(registration) {
-          assert_equals(
-            registration.installing.scriptURL,
-            normalizeURL('resources/empty-worker.js'),
-            'Script URL including parent-reference should be normalized.');
-          service_worker_unregister_and_done(t, scope);
-        });
-  }, 'Script URL including parent-reference');
-
-promise_test(function(t) {
-    var script = 'resources/empty-worker.js';
-    var scope = 'resources/../resources/scope/parent-reference-in-scope';
-    return navigator.serviceWorker.register(script, {scope: scope})
-      .then(function(registration) {
-          assert_equals(
-            registration.scope,
-            normalizeURL('resources/scope/parent-reference-in-scope'),
-            'Scope including parent-reference should be normalized.');
-          service_worker_unregister_and_done(t, scope);
-        });
-  }, 'Scope including parent-reference');
-
-promise_test(function(t) {
-    var script = 'resources/empty-worker.js';
-    var scope = 'resources/../scope/parent-reference-in-scope';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'SecurityError',
-        'Scope not under the script directory should be rejected.');
-  }, 'Scope including parent-reference and not under the script directory');
-
-promise_test(function(t) {
-    var script = 'resources////empty-worker.js';
-    var scope = 'resources/scope/consecutive-slashes-in-script-url';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'SecurityError',
-        'Consecutive slashes in the script url should not be unified.');
-  }, 'Script URL including consecutive slashes');
-
-promise_test(function(t) {
-    var script = 'resources/empty-worker.js';
-    var scope = 'resources/scope////consecutive-slashes-in-scope';
-    return navigator.serviceWorker.register(script, {scope: scope})
-      .then(function(registration) {
-          // Although consecutive slashes in the scope are not unified, the
-          // scope is under the script directory and registration should
-          // succeed.
-          assert_equals(
-            registration.scope,
-            normalizeURL(scope),
-            'Should successfully be registered.');
-          service_worker_unregister_and_done(t, scope);
-        })
-  }, 'Scope including consecutive slashes');
-
-promise_test(function(t) {
-    var script = 'filesystem:' + normalizeURL('resources/empty-worker.js');
-    var scope = 'resources/scope/filesystem-script-url';
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'SecurityError',
-        'Registering a script which has same-origin filesystem: URL should ' +
-            'fail with SecurityError.');
-  }, 'Script URL is same-origin filesystem: URL');
-
-promise_test(function(t) {
-    var script = 'resources/empty-worker.js';
-    var scope = 'filesystem:' + normalizeURL('resources/scope/filesystem-scope-url');
-    return assert_promise_rejects(
-        navigator.serviceWorker.register(script, {scope: scope}),
-        'SecurityError',
-        'Registering with the scope that has same-origin filesystem: URL ' +
-            'should fail with SecurityError.');
-  }, 'Scope URL is same-origin filesystem: URL');
-
+registration_tests((script, options) => navigator.serviceWorker.register(script, options), true);
 </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/registration-tests.js b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/registration-tests.js
new file mode 100644
index 0000000..09e1b5e8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/registration-tests.js
@@ -0,0 +1,397 @@
+function registration_tests(register_method, check_error_types) {
+  // The navigator.serviceWorker.register() method guarantees that the newly
+  // installing worker is available as registration.installing when its promise
+  // resolves. However these tests are also used to test installation using a
+  // <link> element where it is possible for the installing worker to have
+  // already become the waiting or active worker. So This method is used to get
+  // the newest worker when these tests need access to the ServiceWorker itself.
+  function get_newest_worker(registration) {
+    if (registration.installing)
+      return registration.installing;
+    if (registration.waiting)
+      return registration.waiting;
+    if (registration.active)
+      return registration.active;
+  }
+
+  promise_test(function(t) {
+      var script = 'resources/registration-worker.js';
+      var scope = 'resources/registration/normal';
+      return register_method(script, {scope: scope})
+        .then(function(registration) {
+            assert_equals(registration.constructor.name,
+                          'ServiceWorkerRegistration',
+                          'Successfully registered.');
+            service_worker_unregister_and_done(t, scope);
+          })
+    }, 'Registering normal scope');
+
+  promise_test(function(t) {
+      var script = 'resources/registration-worker.js';
+      var scope = 'resources/registration/scope-with-fragment#ref';
+      return register_method(script, {scope: scope})
+        .then(function(registration) {
+            assert_equals(registration.constructor.name,
+                          'ServiceWorkerRegistration',
+                          'Successfully registered.');
+            assert_equals(
+              registration.scope,
+              normalizeURL('resources/registration/scope-with-fragment'),
+              'A fragment should be removed from scope')
+            service_worker_unregister_and_done(t, scope);
+          })
+    }, 'Registering scope with fragment');
+
+  promise_test(function(t) {
+      var script = 'resources/registration-worker.js';
+      var scope = 'resources/';
+      return register_method(script, {scope: scope})
+        .then(function(registration) {
+            assert_equals(registration.constructor.name,
+                          'ServiceWorkerRegistration',
+                          'Successfully registered.');
+            service_worker_unregister_and_done(t, scope);
+          })
+    }, 'Registering same scope as the script directory');
+
+  promise_test(function(t) {
+      var script = 'resources/registration-worker.js';
+      var scope = 'resources';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'SecurityError' : null,
+          'Registering same scope as the script directory without the last ' +
+              'slash should fail with SecurityError.');
+    }, 'Registering same scope as the script directory without the last slash');
+
+  promise_test(function(t) {
+      var script = 'resources/registration-worker.js';
+      var scope = 'different-directory/';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'SecurityError' : null,
+          'Registration scope outside the script directory should fail ' +
+              'with SecurityError.');
+    }, 'Registration scope outside the script directory');
+
+  promise_test(function(t) {
+      var script = 'resources/registration-worker.js';
+      var scope = 'http://example.com/';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'SecurityError' : null,
+          'Registration scope outside domain should fail with SecurityError.');
+    }, 'Registering scope outside domain');
+
+  promise_test(function(t) {
+      var script = 'http://example.com/worker.js';
+      var scope = 'http://example.com/scope/';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'SecurityError' : null,
+          'Registration script outside domain should fail with SecurityError.');
+    }, 'Registering script outside domain');
+
+  promise_test(function(t) {
+      var script = 'resources/no-such-worker.js';
+      var scope = 'resources/scope/no-such-worker';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'NetworkError' : null,
+          navigator.serviceWorker.register(script, {scope: scope}),
+          'Registration of non-existent script should fail.');
+    }, 'Registering non-existent script');
+
+  promise_test(function(t) {
+      var script = 'resources/invalid-chunked-encoding.php';
+      var scope = 'resources/scope/invalid-chunked-encoding/';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'NetworkError' : null,
+          'Registration of invalid chunked encoding script should fail.');
+    }, 'Registering invalid chunked encoding script');
+
+  promise_test(function(t) {
+      var script = 'resources/invalid-chunked-encoding-with-flush.php';
+      var scope = 'resources/scope/invalid-chunked-encoding-with-flush/';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'NetworkError' : null,
+          'Registration of invalid chunked encoding script should fail.');
+    }, 'Registering invalid chunked encoding script with flush');
+
+  promise_test(function(t) {
+      var script = 'resources/mime-type-worker.php';
+      var scope = 'resources/scope/no-mime-type-worker/';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'SecurityError' : null,
+          'Registration of no MIME type script should fail.');
+    }, 'Registering script with no MIME type');
+
+  promise_test(function(t) {
+      var script = 'resources/mime-type-worker.php?mime=text/plain';
+      var scope = 'resources/scope/bad-mime-type-worker/';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'SecurityError' : null,
+          'Registration of plain text script should fail.');
+    }, 'Registering script with bad MIME type');
+
+  promise_test(function(t) {
+      var script = 'resources/redirect.php?Redirect=' +
+                    encodeURIComponent('/resources/registration-worker.js');
+      var scope = 'resources/scope/redirect/';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'SecurityError' : null,
+          'Registration of redirected script should fail.');
+    }, 'Registering redirected script');
+
+  promise_test(function(t) {
+      var script = 'resources/malformed-worker.php?parse-error';
+      var scope = 'resources/scope/parse-error';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'AbortError' : null,
+          'Registration of script including parse error should fail.');
+    }, 'Registering script including parse error');
+
+  promise_test(function(t) {
+      var script = 'resources/malformed-worker.php?undefined-error';
+      var scope = 'resources/scope/undefined-error';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'AbortError' : null,
+          'Registration of script including undefined error should fail.');
+    }, 'Registering script including undefined error');
+
+  promise_test(function(t) {
+      var script = 'resources/malformed-worker.php?uncaught-exception';
+      var scope = 'resources/scope/uncaught-exception';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'AbortError' : null,
+          'Registration of script including uncaught exception should fail.');
+    }, 'Registering script including uncaught exception');
+
+  promise_test(function(t) {
+      var script = 'resources/malformed-worker.php?caught-exception';
+      var scope = 'resources/scope/caught-exception';
+      return register_method(script, {scope: scope})
+          .then(function(registration) {
+              assert_equals(registration.constructor.name,
+                            'ServiceWorkerRegistration',
+                            'Successfully registered.');
+              service_worker_unregister_and_done(t, scope);
+            })
+    }, 'Registering script including caught exception');
+
+  promise_test(function(t) {
+      var script = 'resources/malformed-worker.php?import-malformed-script';
+      var scope = 'resources/scope/import-malformed-script';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'AbortError' : null,
+          'Registration of script importing malformed script should fail.');
+    }, 'Registering script importing malformed script');
+
+  promise_test(function(t) {
+      var script = 'resources/malformed-worker.php?import-no-such-script';
+      var scope = 'resources/scope/import-no-such-script';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'AbortError' : null,
+          'Registration of script importing non-existent script should fail.');
+    }, 'Registering script importing non-existent script');
+
+  promise_test(function(t) {
+      // URL-encoded full-width 'scope'.
+      var name = '%ef%bd%93%ef%bd%83%ef%bd%8f%ef%bd%90%ef%bd%85';
+      var script = 'resources/empty-worker.js';
+      var scope = 'resources/' + name + '/escaped-multibyte-character-scope';
+      return register_method(script, {scope: scope})
+        .then(function(registration) {
+            assert_equals(
+              registration.scope,
+              normalizeURL(scope),
+              'URL-encoded multibyte characters should be available.');
+            service_worker_unregister_and_done(t, scope);
+          });
+    }, 'Scope including URL-encoded multibyte characters');
+
+  promise_test(function(t) {
+      // Non-URL-encoded full-width "scope".
+      var name = String.fromCodePoint(0xff53, 0xff43, 0xff4f, 0xff50, 0xff45);
+      var script = 'resources/empty-worker.js';
+      var scope = 'resources/' + name  + '/non-escaped-multibyte-character-scope';
+      return register_method(script, {scope: scope})
+        .then(function(registration) {
+            assert_equals(
+              registration.scope,
+              normalizeURL(scope),
+              'Non-URL-encoded multibyte characters should be available.');
+            service_worker_unregister_and_done(t, scope);
+          });
+    }, 'Scope including non-escaped multibyte characters');
+
+  promise_test(function(t) {
+      var script = 'resources%2fempty-worker.js';
+      var scope = 'resources/scope/encoded-slash-in-script-url';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? new TypeError : null,
+          'URL-encoded slash in the script URL should be rejected.');
+    }, 'Script URL including URL-encoded slash');
+
+  promise_test(function(t) {
+      var script = 'resources%2Fempty-worker.js';
+      var scope = 'resources/scope/encoded-slash-in-script-url';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? new TypeError : null,
+          'URL-encoded slash in the script URL should be rejected.');
+    }, 'Script URL including uppercase URL-encoded slash');
+
+  promise_test(function(t) {
+      var script = 'resources/empty-worker.js';
+      var scope = 'resources/scope%2fencoded-slash-in-scope';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? new TypeError : null,
+          'URL-encoded slash in the scope should be rejected.');
+    }, 'Scope including URL-encoded slash');
+
+  promise_test(function(t) {
+      var script = 'resources%5cempty-worker.js';
+      var scope = 'resources/scope/encoded-slash-in-script-url';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? new TypeError : null,
+          'URL-encoded backslash in the script URL should be rejected.');
+    }, 'Script URL including URL-encoded backslash');
+
+  promise_test(function(t) {
+      var script = 'resources%5Cempty-worker.js';
+      var scope = 'resources/scope/encoded-slash-in-script-url';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? new TypeError : null,
+          'URL-encoded backslash in the script URL should be rejected.');
+    }, 'Script URL including uppercase URL-encoded backslash');
+
+  promise_test(function(t) {
+      var script = 'resources/empty-worker.js';
+      var scope = 'resources/scope%5cencoded-slash-in-scope';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? new TypeError : null,
+          'URL-encoded backslash in the scope should be rejected.');
+    }, 'Scope including URL-encoded backslash');
+
+  promise_test(function(t) {
+      var script = 'resources/././empty-worker.js';
+      var scope = 'resources/scope/parent-reference-in-script-url';
+      return register_method(script, {scope: scope})
+        .then(function(registration) {
+            assert_equals(
+              get_newest_worker(registration).scriptURL,
+              normalizeURL('resources/empty-worker.js'),
+              'Script URL including self-reference should be normalized.');
+            service_worker_unregister_and_done(t, scope);
+          });
+    }, 'Script URL including self-reference');
+
+  promise_test(function(t) {
+      var script = 'resources/empty-worker.js';
+      var scope = 'resources/././scope/self-reference-in-scope';
+      return register_method(script, {scope: scope})
+        .then(function(registration) {
+            assert_equals(
+              registration.scope,
+              normalizeURL('resources/scope/self-reference-in-scope'),
+              'Scope including self-reference should be normalized.');
+            service_worker_unregister_and_done(t, scope);
+          });
+    }, 'Scope including self-reference');
+
+  promise_test(function(t) {
+      var script = 'resources/../resources/empty-worker.js';
+      var scope = 'resources/scope/parent-reference-in-script-url';
+      return register_method(script, {scope: scope})
+        .then(function(registration) {
+            assert_equals(
+              get_newest_worker(registration).scriptURL,
+              normalizeURL('resources/empty-worker.js'),
+              'Script URL including parent-reference should be normalized.');
+            service_worker_unregister_and_done(t, scope);
+          });
+    }, 'Script URL including parent-reference');
+
+  promise_test(function(t) {
+      var script = 'resources/empty-worker.js';
+      var scope = 'resources/../resources/scope/parent-reference-in-scope';
+      return register_method(script, {scope: scope})
+        .then(function(registration) {
+            assert_equals(
+              registration.scope,
+              normalizeURL('resources/scope/parent-reference-in-scope'),
+              'Scope including parent-reference should be normalized.');
+            service_worker_unregister_and_done(t, scope);
+          });
+    }, 'Scope including parent-reference');
+
+  promise_test(function(t) {
+      var script = 'resources/empty-worker.js';
+      var scope = 'resources/../scope/parent-reference-in-scope';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'SecurityError' : null,
+          'Scope not under the script directory should be rejected.');
+    }, 'Scope including parent-reference and not under the script directory');
+
+  promise_test(function(t) {
+      var script = 'resources////empty-worker.js';
+      var scope = 'resources/scope/consecutive-slashes-in-script-url';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'SecurityError' : null,
+          'Consecutive slashes in the script url should not be unified.');
+    }, 'Script URL including consecutive slashes');
+
+  promise_test(function(t) {
+      var script = 'resources/empty-worker.js';
+      var scope = 'resources/scope////consecutive-slashes-in-scope';
+      return register_method(script, {scope: scope})
+        .then(function(registration) {
+            // Although consecutive slashes in the scope are not unified, the
+            // scope is under the script directory and registration should
+            // succeed.
+            assert_equals(
+              registration.scope,
+              normalizeURL(scope),
+              'Should successfully be registered.');
+            service_worker_unregister_and_done(t, scope);
+          })
+    }, 'Scope including consecutive slashes');
+
+  promise_test(function(t) {
+      var script = 'filesystem:' + normalizeURL('resources/empty-worker.js');
+      var scope = 'resources/scope/filesystem-script-url';
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'SecurityError' : null,
+          'Registering a script which has same-origin filesystem: URL should ' +
+              'fail with SecurityError.');
+    }, 'Script URL is same-origin filesystem: URL');
+
+  promise_test(function(t) {
+      var script = 'resources/empty-worker.js';
+      var scope = 'filesystem:' + normalizeURL('resources/scope/filesystem-scope-url');
+      return assert_promise_rejects(
+          register_method(script, {scope: scope}),
+          check_error_types ? 'SecurityError' : null,
+          'Registering with the scope that has same-origin filesystem: URL ' +
+              'should fail with SecurityError.');
+    }, 'Scope URL is same-origin filesystem: URL');
+}
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/import.html b/third_party/WebKit/LayoutTests/http/tests/worklet/import.html
index 3e44c5ff..2b99c5c 100644
--- a/third_party/WebKit/LayoutTests/http/tests/worklet/import.html
+++ b/third_party/WebKit/LayoutTests/http/tests/worklet/import.html
@@ -8,7 +8,7 @@
 <script>
     promise_test(function() {
 
-        return renderWorklet.import('resources/empty-worklet-script.js').then(function(undefined_arg) {
+        return paintWorklet.import('resources/empty-worklet-script.js').then(function(undefined_arg) {
             assert_equals(undefined_arg, undefined, 'Promise should resolve with no arguments.');
         }).catch(function(error) {
             assert_unreached('unexpected rejection: ' + error);
@@ -18,7 +18,7 @@
 
     promise_test(function() {
 
-        return renderWorklet.import('resources/throwing-worklet-script.js').then(function(undefined_arg) {
+        return paintWorklet.import('resources/throwing-worklet-script.js').then(function(undefined_arg) {
             assert_equals(undefined_arg, undefined, 'Promise should resolve with no arguments.');
         }).catch(function(error) {
             assert_unreached('unexpected rejection: ' + error);
@@ -28,7 +28,7 @@
 
     promise_test(function() {
 
-        return renderWorklet.import('non-existant-worklet-script.js').then(function() {
+        return paintWorklet.import('non-existant-worklet-script.js').then(function() {
             assert_unreached('import should fail.');
         }).catch(function(error) {
             assert_equals(error.name, 'NetworkError', 'error should be a NetworkError.');
@@ -38,7 +38,7 @@
 
     promise_test(function() {
 
-        return renderWorklet.import('http://invalid:123$').then(function() {
+        return paintWorklet.import('http://invalid:123$').then(function() {
             assert_unreached('import should fail.');
         }).catch(function(error) {
             assert_equals(error.name, 'SyntaxError', 'error should be a SyntaxError.');
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-dirRTL-anchorEnd-expected.txt b/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-dirRTL-anchorEnd-expected.txt
deleted file mode 100644
index 8b07337..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-dirRTL-anchorEnd-expected.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutSVGRoot {svg} at (0,0) size 800x600
-    LayoutSVGContainer {g} at (280,183) size 415x213
-      LayoutSVGText {text} at (230,151) size 187x12 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 187x12
-          chunk 1 (end anchor) text run 1 at (230.00,160.00) startOffset 0 endOffset 42 width 186.60: "Making the world wide web truly world wide"
-      LayoutSVGText {text} at (230,186) size 149x12 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 149x12
-          chunk 1 (end anchor) text run 1 at (230.00,195.00) startOffset 0 endOffset 31 width 148.80 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (230,226) size 119x12 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 119x12
-          chunk 1 (end anchor) text run 1 at (230.00,235.00) startOffset 0 endOffset 38 width 118.80 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
-      LayoutSVGImage {image} at (280,183) size 214x44
-    LayoutSVGContainer {g} at (16,556) size 77x14
-      LayoutSVGText {text} at (10,334) size 46x8 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 46x8
-          chunk 1 text run 1 at (10.00,340.00) startOffset 0 endOffset 16 width 45.60: "$Revision: 1.4 $"
-    LayoutSVGRect {rect} at (0,0) size 800x600 [stroke={[type=SOLID] [color=#000000]}] [x=1.00] [y=1.00] [width=478.00] [height=358.00]
-    LayoutSVGContainer {g} at (0,0) size 800x38
-      LayoutSVGRect {rect} at (0,0) size 800x36 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#FF0000]}] [x=1.00] [y=1.00] [width=478.00] [height=20.00]
-      LayoutSVGText {text} at (206,-1) size 68x24 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 67x23
-          chunk 1 (middle anchor) text run 1 at (206.70,18.00) startOffset 0 endOffset 5 width 66.60: "DRAFT"
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-dirRTL-anchorMiddle-expected.txt b/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-dirRTL-anchorMiddle-expected.txt
deleted file mode 100644
index 3dad8d2d..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-dirRTL-anchorMiddle-expected.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutSVGRoot {svg} at (0,0) size 800x600
-    LayoutSVGContainer {g} at (227,183) size 312x213
-      LayoutSVGText {text} at (136,151) size 188x12 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 187x12
-          chunk 1 (middle anchor) text run 1 at (136.70,160.00) startOffset 0 endOffset 42 width 186.60: "Making the world wide web truly world wide"
-      LayoutSVGText {text} at (155,186) size 150x12 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 149x12
-          chunk 1 (middle anchor) text run 1 at (155.60,195.00) startOffset 0 endOffset 31 width 148.80 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (170,226) size 120x12 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 119x12
-          chunk 1 (middle anchor) text run 1 at (170.60,235.00) startOffset 0 endOffset 38 width 118.80 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
-      LayoutSVGImage {image} at (280,183) size 214x44
-    LayoutSVGContainer {g} at (16,556) size 77x14
-      LayoutSVGText {text} at (10,334) size 46x8 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 46x8
-          chunk 1 text run 1 at (10.00,340.00) startOffset 0 endOffset 16 width 45.60: "$Revision: 1.4 $"
-    LayoutSVGRect {rect} at (0,0) size 800x600 [stroke={[type=SOLID] [color=#000000]}] [x=1.00] [y=1.00] [width=478.00] [height=358.00]
-    LayoutSVGContainer {g} at (0,0) size 800x38
-      LayoutSVGRect {rect} at (0,0) size 800x36 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#FF0000]}] [x=1.00] [y=1.00] [width=478.00] [height=20.00]
-      LayoutSVGText {text} at (206,-1) size 68x24 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 67x23
-          chunk 1 (middle anchor) text run 1 at (206.70,18.00) startOffset 0 endOffset 5 width 66.60: "DRAFT"
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-dirRTL-anchorStart-expected.txt b/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-dirRTL-anchorStart-expected.txt
deleted file mode 100644
index a89fcd1..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-dirRTL-anchorStart-expected.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutSVGRoot {svg} at (0,0) size 800x600
-    LayoutSVGContainer {g} at (72,183) size 422x213
-      LayoutSVGText {text} at (43,151) size 187x12 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 187x12
-          chunk 1 text run 1 at (43.40,160.00) startOffset 0 endOffset 42 width 186.60: "Making the world wide web truly world wide"
-      LayoutSVGText {text} at (81,186) size 149x12 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 149x12
-          chunk 1 text run 1 at (81.20,195.00) startOffset 0 endOffset 31 width 148.80 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (111,226) size 119x12 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 119x12
-          chunk 1 text run 1 at (111.20,235.00) startOffset 0 endOffset 38 width 118.80 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
-      LayoutSVGImage {image} at (280,183) size 214x44
-    LayoutSVGContainer {g} at (16,556) size 77x14
-      LayoutSVGText {text} at (10,334) size 46x8 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 46x8
-          chunk 1 text run 1 at (10.00,340.00) startOffset 0 endOffset 16 width 45.60: "$Revision: 1.4 $"
-    LayoutSVGRect {rect} at (0,0) size 800x600 [stroke={[type=SOLID] [color=#000000]}] [x=1.00] [y=1.00] [width=478.00] [height=358.00]
-    LayoutSVGContainer {g} at (0,0) size 800x38
-      LayoutSVGRect {rect} at (0,0) size 800x36 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#FF0000]}] [x=1.00] [y=1.00] [width=478.00] [height=20.00]
-      LayoutSVGText {text} at (206,-1) size 68x24 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 67x23
-          chunk 1 (middle anchor) text run 1 at (206.70,18.00) startOffset 0 endOffset 5 width 66.60: "DRAFT"
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorEnd-expected.txt b/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorEnd-expected.txt
deleted file mode 100644
index a8c01a0..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorEnd-expected.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutSVGRoot {svg} at (0,0) size 800x600
-    LayoutSVGContainer {g} at (280,183) size 415x213
-      LayoutSVGContainer {g} at (383,251) size 312x145
-        LayoutSVGText {text} at (230,151) size 187x12 contains 1 chunk(s)
-          LayoutSVGInlineText {#text} at (0,0) size 187x12
-            chunk 1 (end anchor) text run 1 at (230.00,160.00) startOffset 0 endOffset 42 width 186.60: "Making the world wide web truly world wide"
-        LayoutSVGText {text} at (230,186) size 149x12 contains 1 chunk(s)
-          LayoutSVGInlineText {#text} at (0,0) size 149x12
-            chunk 1 (end anchor) text run 1 at (230.00,195.00) startOffset 0 endOffset 31 width 148.80 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-        LayoutSVGText {text} at (230,226) size 119x12 contains 1 chunk(s)
-          LayoutSVGInlineText {#text} at (0,0) size 119x12
-            chunk 1 (end anchor) text run 1 at (230.00,235.00) startOffset 0 endOffset 38 width 118.80 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
-      LayoutSVGImage {image} at (280,183) size 214x44
-    LayoutSVGContainer {g} at (16,556) size 77x14
-      LayoutSVGText {text} at (10,334) size 46x8 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 46x8
-          chunk 1 text run 1 at (10.00,340.00) startOffset 0 endOffset 16 width 45.60: "$Revision: 1.4 $"
-    LayoutSVGRect {rect} at (0,0) size 800x600 [stroke={[type=SOLID] [color=#000000]}] [x=1.00] [y=1.00] [width=478.00] [height=358.00]
-    LayoutSVGContainer {g} at (0,0) size 800x38
-      LayoutSVGRect {rect} at (0,0) size 800x36 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#FF0000]}] [x=1.00] [y=1.00] [width=478.00] [height=20.00]
-      LayoutSVGText {text} at (206,-1) size 68x24 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 67x23
-          chunk 1 (middle anchor) text run 1 at (206.70,18.00) startOffset 0 endOffset 5 width 66.60: "DRAFT"
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorMiddle-expected.txt b/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorMiddle-expected.txt
deleted file mode 100644
index 41ed049..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorMiddle-expected.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutSVGRoot {svg} at (0,0) size 800x600
-    LayoutSVGContainer {g} at (227,183) size 312x213
-      LayoutSVGContainer {g} at (227,251) size 312x145
-        LayoutSVGText {text} at (136,151) size 188x12 contains 1 chunk(s)
-          LayoutSVGInlineText {#text} at (0,0) size 187x12
-            chunk 1 (middle anchor) text run 1 at (136.70,160.00) startOffset 0 endOffset 42 width 186.60: "Making the world wide web truly world wide"
-        LayoutSVGText {text} at (155,186) size 150x12 contains 1 chunk(s)
-          LayoutSVGInlineText {#text} at (0,0) size 149x12
-            chunk 1 (middle anchor) text run 1 at (155.60,195.00) startOffset 0 endOffset 31 width 148.80 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-        LayoutSVGText {text} at (170,226) size 120x12 contains 1 chunk(s)
-          LayoutSVGInlineText {#text} at (0,0) size 119x12
-            chunk 1 (middle anchor) text run 1 at (170.60,235.00) startOffset 0 endOffset 38 width 118.80 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
-      LayoutSVGImage {image} at (280,183) size 214x44
-    LayoutSVGContainer {g} at (16,556) size 77x14
-      LayoutSVGText {text} at (10,334) size 46x8 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 46x8
-          chunk 1 text run 1 at (10.00,340.00) startOffset 0 endOffset 16 width 45.60: "$Revision: 1.4 $"
-    LayoutSVGRect {rect} at (0,0) size 800x600 [stroke={[type=SOLID] [color=#000000]}] [x=1.00] [y=1.00] [width=478.00] [height=358.00]
-    LayoutSVGContainer {g} at (0,0) size 800x38
-      LayoutSVGRect {rect} at (0,0) size 800x36 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#FF0000]}] [x=1.00] [y=1.00] [width=478.00] [height=20.00]
-      LayoutSVGText {text} at (206,-1) size 68x24 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 67x23
-          chunk 1 (middle anchor) text run 1 at (206.70,18.00) startOffset 0 endOffset 5 width 66.60: "DRAFT"
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorStart-expected.txt b/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorStart-expected.txt
deleted file mode 100644
index a25995f..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorStart-expected.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutSVGRoot {svg} at (0,0) size 800x600
-    LayoutSVGContainer {g} at (72,183) size 422x213
-      LayoutSVGContainer {g} at (72,251) size 312x145
-        LayoutSVGText {text} at (43,151) size 187x12 contains 1 chunk(s)
-          LayoutSVGInlineText {#text} at (0,0) size 187x12
-            chunk 1 text run 1 at (43.40,160.00) startOffset 0 endOffset 42 width 186.60: "Making the world wide web truly world wide"
-        LayoutSVGText {text} at (81,186) size 149x12 contains 1 chunk(s)
-          LayoutSVGInlineText {#text} at (0,0) size 149x12
-            chunk 1 text run 1 at (81.20,195.00) startOffset 0 endOffset 31 width 148.80 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-        LayoutSVGText {text} at (111,226) size 119x12 contains 1 chunk(s)
-          LayoutSVGInlineText {#text} at (0,0) size 119x12
-            chunk 1 text run 1 at (111.20,235.00) startOffset 0 endOffset 38 width 118.80 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
-      LayoutSVGImage {image} at (280,183) size 214x44
-    LayoutSVGContainer {g} at (16,556) size 77x14
-      LayoutSVGText {text} at (10,334) size 46x8 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 46x8
-          chunk 1 text run 1 at (10.00,340.00) startOffset 0 endOffset 16 width 45.60: "$Revision: 1.4 $"
-    LayoutSVGRect {rect} at (0,0) size 800x600 [stroke={[type=SOLID] [color=#000000]}] [x=1.00] [y=1.00] [width=478.00] [height=358.00]
-    LayoutSVGContainer {g} at (0,0) size 800x38
-      LayoutSVGRect {rect} at (0,0) size 800x36 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#FF0000]}] [x=1.00] [y=1.00] [width=478.00] [height=20.00]
-      LayoutSVGText {text} at (206,-1) size 68x24 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 67x23
-          chunk 1 (middle anchor) text run 1 at (206.70,18.00) startOffset 0 endOffset 5 width 66.60: "DRAFT"
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/tspan-dirLTR-ubEmbed-in-rtl-context-expected.txt b/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/tspan-dirLTR-ubEmbed-in-rtl-context-expected.txt
deleted file mode 100644
index c87b9e6..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-I18N/tspan-dirLTR-ubEmbed-in-rtl-context-expected.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutSVGRoot {svg} at (0,0) size 800x600
-    LayoutSVGContainer {g} at (33,222) size 651x143
-      LayoutSVGText {text} at (92,133) size 276x22 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (192,0) size 83x21
-          chunk 1 (middle anchor) text run 1 at (284.83,150.00) startOffset 0 endOffset 14 width 82.80 RTL: "\x{646}\x{634}\x{627}\x{637} \x{627}\x{644}\x{62A}\x{62F}\x{648}\x{64A}\x{644} \""
-        LayoutSVGTSpan {tspan} at (0,0) size 181x21
-          LayoutSVGInlineText {#text} at (12,0) size 181x21
-            chunk 1 (middle anchor) text run 1 at (104.37,150.00) startOffset 0 endOffset 16 width 145.66: "dirLTR ubEmbed, "
-            chunk 1 (middle anchor) text run 1 at (250.03,150.00) startOffset 0 endOffset 6 width 34.80 RTL: "\x{627}\x{62E}\x{62A}\x{628}\x{627}\x{631}"
-        LayoutSVGInlineText {#text} at (0,0) size 12x21
-          chunk 1 (middle anchor) text run 1 at (92.37,150.00) startOffset 0 endOffset 2 width 12.00 RTL: "\"!"
-      LayoutSVGText {text} at (20,171) size 85x12 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 85x12
-          chunk 1 text run 1 at (20.00,180.00) startOffset 0 endOffset 18 width 84.60: "Reference graphic:"
-      LayoutSVGImage {image} at (100,300) size 584x65
-    LayoutSVGContainer {g} at (16,556) size 77x14
-      LayoutSVGText {text} at (10,334) size 46x8 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 46x8
-          chunk 1 text run 1 at (10.00,340.00) startOffset 0 endOffset 16 width 45.60: "$Revision: 1.7 $"
-    LayoutSVGRect {rect} at (0,0) size 800x600 [stroke={[type=SOLID] [color=#000000]}] [x=1.00] [y=1.00] [width=478.00] [height=358.00]
-    LayoutSVGContainer {g} at (0,0) size 800x38
-      LayoutSVGRect {rect} at (0,0) size 800x36 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#FF0000]}] [x=1.00] [y=1.00] [width=478.00] [height=20.00]
-      LayoutSVGText {text} at (206,-1) size 68x24 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 67x23
-          chunk 1 (middle anchor) text run 1 at (206.70,18.00) startOffset 0 endOffset 5 width 66.60: "DRAFT"
diff --git a/third_party/WebKit/LayoutTests/platform/linux/plugins/plugin-javascript-access-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/plugins/plugin-javascript-access-expected.txt
index b367deb4..d0eedab 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/plugins/plugin-javascript-access-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/plugins/plugin-javascript-access-expected.txt
@@ -1 +1,32 @@
-FAILURE! (Failed to find netscape test plugin)
+Name: Blink Test Plugin
+
+Description: Interesting description.
+
+Filename: libblink_test_plugin.so
+
+Mime Types:
+
+Type: application/x-blink-test-plugin
+
+Description: Interesting description.
+
+Suffixes:
+
+
+Plugin.item() works.
+
+Plugin.namedItem() works.
+
+PluginArray.item() works.
+
+PluginArray.namedItem() works.
+
+Type: application/x-blink-test-plugin
+
+Description: Interesting description.
+
+Suffixes:
+
+MimeTypeArray.item() works.
+
+MimeTypeArray.namedItem() works.
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-dirRTL-anchorEnd-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-dirRTL-anchorEnd-expected.txt
index 65e1239..8b07337 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-dirRTL-anchorEnd-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-dirRTL-anchorEnd-expected.txt
@@ -2,9 +2,9 @@
   LayoutView at (0,0) size 800x600
 layer at (0,0) size 800x600
   LayoutSVGRoot {svg} at (0,0) size 800x600
-    LayoutSVGContainer {g} at (280,183) size 416x213
-      LayoutSVGText {text} at (230,151) size 188x12 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 188x12
+    LayoutSVGContainer {g} at (280,183) size 415x213
+      LayoutSVGText {text} at (230,151) size 187x12 contains 1 chunk(s)
+        LayoutSVGInlineText {#text} at (0,0) size 187x12
           chunk 1 (end anchor) text run 1 at (230.00,160.00) startOffset 0 endOffset 42 width 186.60: "Making the world wide web truly world wide"
       LayoutSVGText {text} at (230,186) size 149x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 149x12
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-dirRTL-anchorMiddle-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-dirRTL-anchorMiddle-expected.txt
index dbef47fe..3dad8d2d 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-dirRTL-anchorMiddle-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-dirRTL-anchorMiddle-expected.txt
@@ -2,9 +2,9 @@
   LayoutView at (0,0) size 800x600
 layer at (0,0) size 800x600
   LayoutSVGRoot {svg} at (0,0) size 800x600
-    LayoutSVGContainer {g} at (227,183) size 313x213
+    LayoutSVGContainer {g} at (227,183) size 312x213
       LayoutSVGText {text} at (136,151) size 188x12 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 188x12
+        LayoutSVGInlineText {#text} at (0,0) size 187x12
           chunk 1 (middle anchor) text run 1 at (136.70,160.00) startOffset 0 endOffset 42 width 186.60: "Making the world wide web truly world wide"
       LayoutSVGText {text} at (155,186) size 150x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 149x12
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-dirRTL-anchorStart-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-dirRTL-anchorStart-expected.txt
index 4b1074e..a89fcd1 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-dirRTL-anchorStart-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-dirRTL-anchorStart-expected.txt
@@ -3,8 +3,8 @@
 layer at (0,0) size 800x600
   LayoutSVGRoot {svg} at (0,0) size 800x600
     LayoutSVGContainer {g} at (72,183) size 422x213
-      LayoutSVGText {text} at (43,151) size 188x12 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 188x12
+      LayoutSVGText {text} at (43,151) size 187x12 contains 1 chunk(s)
+        LayoutSVGInlineText {#text} at (0,0) size 187x12
           chunk 1 text run 1 at (43.40,160.00) startOffset 0 endOffset 42 width 186.60: "Making the world wide web truly world wide"
       LayoutSVGText {text} at (81,186) size 149x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 149x12
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorEnd-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorEnd-expected.txt
index 799f678..a8c01a0 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorEnd-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorEnd-expected.txt
@@ -2,10 +2,10 @@
   LayoutView at (0,0) size 800x600
 layer at (0,0) size 800x600
   LayoutSVGRoot {svg} at (0,0) size 800x600
-    LayoutSVGContainer {g} at (280,183) size 416x213
-      LayoutSVGContainer {g} at (383,251) size 313x145
-        LayoutSVGText {text} at (230,151) size 188x12 contains 1 chunk(s)
-          LayoutSVGInlineText {#text} at (0,0) size 188x12
+    LayoutSVGContainer {g} at (280,183) size 415x213
+      LayoutSVGContainer {g} at (383,251) size 312x145
+        LayoutSVGText {text} at (230,151) size 187x12 contains 1 chunk(s)
+          LayoutSVGInlineText {#text} at (0,0) size 187x12
             chunk 1 (end anchor) text run 1 at (230.00,160.00) startOffset 0 endOffset 42 width 186.60: "Making the world wide web truly world wide"
         LayoutSVGText {text} at (230,186) size 149x12 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 149x12
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorMiddle-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorMiddle-expected.txt
index 20640cf..41ed049 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorMiddle-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorMiddle-expected.txt
@@ -2,10 +2,10 @@
   LayoutView at (0,0) size 800x600
 layer at (0,0) size 800x600
   LayoutSVGRoot {svg} at (0,0) size 800x600
-    LayoutSVGContainer {g} at (227,183) size 313x213
-      LayoutSVGContainer {g} at (227,251) size 313x145
+    LayoutSVGContainer {g} at (227,183) size 312x213
+      LayoutSVGContainer {g} at (227,251) size 312x145
         LayoutSVGText {text} at (136,151) size 188x12 contains 1 chunk(s)
-          LayoutSVGInlineText {#text} at (0,0) size 188x12
+          LayoutSVGInlineText {#text} at (0,0) size 187x12
             chunk 1 (middle anchor) text run 1 at (136.70,160.00) startOffset 0 endOffset 42 width 186.60: "Making the world wide web truly world wide"
         LayoutSVGText {text} at (155,186) size 150x12 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 149x12
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorStart-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorStart-expected.txt
index 615ecaa..a25995f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorStart-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/text-anchor-inherited-dirRTL-anchorStart-expected.txt
@@ -3,9 +3,9 @@
 layer at (0,0) size 800x600
   LayoutSVGRoot {svg} at (0,0) size 800x600
     LayoutSVGContainer {g} at (72,183) size 422x213
-      LayoutSVGContainer {g} at (72,251) size 313x145
-        LayoutSVGText {text} at (43,151) size 188x12 contains 1 chunk(s)
-          LayoutSVGInlineText {#text} at (0,0) size 188x12
+      LayoutSVGContainer {g} at (72,251) size 312x145
+        LayoutSVGText {text} at (43,151) size 187x12 contains 1 chunk(s)
+          LayoutSVGInlineText {#text} at (0,0) size 187x12
             chunk 1 text run 1 at (43.40,160.00) startOffset 0 endOffset 42 width 186.60: "Making the world wide web truly world wide"
         LayoutSVGText {text} at (81,186) size 149x12 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 149x12
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/tspan-dirLTR-ubEmbed-in-rtl-context-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/tspan-dirLTR-ubEmbed-in-rtl-context-expected.txt
index 39ad1cc..c87b9e6 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/tspan-dirLTR-ubEmbed-in-rtl-context-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-I18N/tspan-dirLTR-ubEmbed-in-rtl-context-expected.txt
@@ -6,8 +6,8 @@
       LayoutSVGText {text} at (92,133) size 276x22 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (192,0) size 83x21
           chunk 1 (middle anchor) text run 1 at (284.83,150.00) startOffset 0 endOffset 14 width 82.80 RTL: "\x{646}\x{634}\x{627}\x{637} \x{627}\x{644}\x{62A}\x{62F}\x{648}\x{64A}\x{644} \""
-        LayoutSVGTSpan {tspan} at (0,0) size 182x21
-          LayoutSVGInlineText {#text} at (12,0) size 182x21
+        LayoutSVGTSpan {tspan} at (0,0) size 181x21
+          LayoutSVGInlineText {#text} at (12,0) size 181x21
             chunk 1 (middle anchor) text run 1 at (104.37,150.00) startOffset 0 endOffset 16 width 145.66: "dirLTR ubEmbed, "
             chunk 1 (middle anchor) text run 1 at (250.03,150.00) startOffset 0 endOffset 6 width 34.80 RTL: "\x{627}\x{62E}\x{62A}\x{628}\x{627}\x{631}"
         LayoutSVGInlineText {#text} at (0,0) size 12x21
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-intro-05-t-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-intro-05-t-expected.txt
index e2f17da..b2e3af98 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-intro-05-t-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-intro-05-t-expected.txt
@@ -2,15 +2,15 @@
   LayoutView at (0,0) size 800x600
 layer at (0,0) size 800x600
   LayoutSVGRoot {svg} at (0,0) size 800x600
-    LayoutSVGContainer {g} at (71,80) size 696x332
-      LayoutSVGText {text} at (113,48) size 347x40 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 347x40
+    LayoutSVGContainer {g} at (71,80) size 698x332
+      LayoutSVGText {text} at (113,48) size 349x40 contains 1 chunk(s)
+        LayoutSVGInlineText {#text} at (0,0) size 348x40
           chunk 1 (end anchor) text run 1 at (113.20,80.00) startOffset 0 endOffset 37 width 346.80 RTL: "\x{644}\x{645}\x{627}\x{630}\x{627} \x{644}\x{627} \x{64A}\x{62A}\x{643}\x{644}\x{645}\x{648}\x{646} \x{627}\x{644}\x{644}\x{651}\x{63A}\x{629} \x{627}\x{644}\x{639}\x{631}\x{628}\x{64A}\x{629} \x{641}\x{62D}\x{633}\x{628}\x{61F}"
-      LayoutSVGText {text} at (43,122) size 417x47 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 417x47
+      LayoutSVGText {text} at (43,122) size 419x47 contains 1 chunk(s)
+        LayoutSVGInlineText {#text} at (0,0) size 419x47
           chunk 1 (end anchor) text run 1 at (43.00,160.00) startOffset 0 endOffset 37 width 417.00 RTL: "\x{644}\x{645}\x{627}\x{630}\x{627} \x{644}\x{627} \x{64A}\x{62A}\x{643}\x{644}\x{645}\x{648}\x{646} \x{627}\x{644}\x{644}\x{651}\x{63A}\x{629} \x{627}\x{644}\x{639}\x{631}\x{628}\x{64A}\x{629} \x{641}\x{62D}\x{633}\x{628}\x{61F}"
-      LayoutSVGText {text} at (113,208) size 347x40 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 347x40
+      LayoutSVGText {text} at (113,208) size 349x40 contains 1 chunk(s)
+        LayoutSVGInlineText {#text} at (0,0) size 348x40
           chunk 1 (end anchor) text run 1 at (113.20,240.00) startOffset 0 endOffset 37 width 346.80 RTL: "\x{644}\x{645}\x{627}\x{630}\x{627} \x{644}\x{627} \x{64A}\x{62A}\x{643}\x{644}\x{645}\x{648}\x{646} \x{627}\x{644}\x{644}\x{651}\x{63A}\x{629} \x{627}\x{644}\x{639}\x{631}\x{628}\x{64A}\x{629} \x{641}\x{62D}\x{633}\x{628}\x{61F}"
     LayoutSVGText {text} at (10,304) size 266x46 contains 1 chunk(s)
       LayoutSVGInlineText {#text} at (0,0) size 266x46
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/combining-character-queries-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/combining-character-queries-expected.txt
index 05d135a1..6c87d3cc 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/combining-character-queries-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/combining-character-queries-expected.txt
@@ -479,16 +479,16 @@
               chunk 1 text run 1 at (82.04,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}"
               chunk 1 text run 1 at (82.04,125.00) startOffset 0 endOffset 1 width 17.96: "a"
               chunk 1 text run 1 at (100.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}"
-          LayoutSVGText {text} at (200,94) size 50x40 contains 1 chunk(s)
-            LayoutSVGInlineText {#text} at (0,0) size 50x40
+          LayoutSVGText {text} at (201,94) size 49x40 contains 1 chunk(s)
+            LayoutSVGInlineText {#text} at (0,0) size 49x40
               chunk 1 text run 1 at (201.43,125.00) startOffset 0 endOffset 3 width 15.53: "c\x{30C}\x{30C}"
               chunk 1 text run 1 at (216.97,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}"
               chunk 1 text run 1 at (216.97,125.00) startOffset 0 endOffset 2 width 17.50: "b\x{30C}"
               chunk 1 text run 1 at (234.47,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}"
               chunk 1 text run 1 at (234.47,125.00) startOffset 0 endOffset 1 width 15.53: "a"
               chunk 1 text run 1 at (250.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}"
-          LayoutSVGText {text} at (328,93) size 72x40 contains 1 chunk(s)
-            LayoutSVGInlineText {#text} at (0,0) size 72x40
+          LayoutSVGText {text} at (343,93) size 57x40 contains 1 chunk(s)
+            LayoutSVGInlineText {#text} at (0,0) size 57x40
               chunk 1 text run 1 at (343.57,125.00) startOffset 0 endOffset 3 width 17.50: "c\x{30C}\x{30C}"
               chunk 1 text run 1 at (361.07,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}"
               chunk 1 text run 1 at (361.07,125.00) startOffset 0 endOffset 2 width 19.47: "b\x{30C}"
diff --git a/third_party/WebKit/LayoutTests/platform/mac/plugins/overlay-scrollbar-mouse-capture-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/plugins/overlay-scrollbar-mouse-capture-expected.txt
index 58eb151..dd4e5a87 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/plugins/overlay-scrollbar-mouse-capture-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/plugins/overlay-scrollbar-mouse-capture-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
 
 This tests whether scrolling still works correctly when an overlay scrollbar is over a plugin. The plugin should still receive mouse down/up events when clicking an overlay scrollbar. Scrolling should still work correctly too. However mouse capture should not be started on the plugin as this would interfere with events going to the scrollbar.
 
diff --git a/third_party/WebKit/LayoutTests/platform/mac/plugins/plugin-javascript-access-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/plugins/plugin-javascript-access-expected.txt
index 37a327a..a02b7bb0 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/plugins/plugin-javascript-access-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/plugins/plugin-javascript-access-expected.txt
@@ -1,27 +1,16 @@
-Name: WebKit Test PlugIn
+Name: Blink Test Plugin
 
-Description: Simple Netscape plug-in that handles test content for WebKit
+Description: Interesting description.
 
-Filename: test_netscape_plugin.plugin
+Filename: blink_test_plugin.plugin
 
 Mime Types:
 
-Type: application/x-webkit-test-netscape
+Type: application/x-blink-test-plugin
 
-Description: test netscape content
+Description: Interesting description.
 
-Suffixes: testnetscape
-
-
-Plugin.item() works.
-
-Plugin.namedItem() works.
-
-Type: image/png
-
-Description: PNG image
-
-Suffixes: png
+Suffixes:
 
 
 Plugin.item() works.
@@ -32,11 +21,11 @@
 
 PluginArray.namedItem() works.
 
-Type: application/x-webkit-test-netscape
+Type: application/x-blink-test-plugin
 
-Description: test netscape content
+Description: Interesting description.
 
-Suffixes: testnetscape
+Suffixes:
 
 MimeTypeArray.item() works.
 
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirLTR-anchorEnd-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirLTR-anchorEnd-expected.txt
index d489521..4f9c5be 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirLTR-anchorEnd-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirLTR-anchorEnd-expected.txt
@@ -9,7 +9,7 @@
       LayoutSVGText {text} at (83,186) size 147x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 147x12
           chunk 1 (end anchor) text run 1 at (83.13,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (115,222) size 115x16 contains 1 chunk(s)
+      LayoutSVGText {text} at (115,223) size 116x15 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 115x15
           chunk 1 (end anchor) text run 1 at (115.82,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirLTR-anchorMiddle-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirLTR-anchorMiddle-expected.txt
index 2086d8d..2d9c763 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirLTR-anchorMiddle-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirLTR-anchorMiddle-expected.txt
@@ -9,7 +9,7 @@
       LayoutSVGText {text} at (156,186) size 148x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 147x12
           chunk 1 (middle anchor) text run 1 at (156.57,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (172,222) size 116x16 contains 1 chunk(s)
+      LayoutSVGText {text} at (172,223) size 116x15 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 115x15
           chunk 1 (middle anchor) text run 1 at (172.91,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirLTR-anchorStart-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirLTR-anchorStart-expected.txt
index 9a5cc70..f31070f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirLTR-anchorStart-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirLTR-anchorStart-expected.txt
@@ -9,7 +9,7 @@
       LayoutSVGText {text} at (230,186) size 147x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 147x12
           chunk 1 text run 1 at (230.00,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (230,222) size 115x16 contains 1 chunk(s)
+      LayoutSVGText {text} at (230,223) size 115x15 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 115x15
           chunk 1 text run 1 at (230.00,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirNone-anchorEnd-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirNone-anchorEnd-expected.txt
index d489521..4f9c5be 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirNone-anchorEnd-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirNone-anchorEnd-expected.txt
@@ -9,7 +9,7 @@
       LayoutSVGText {text} at (83,186) size 147x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 147x12
           chunk 1 (end anchor) text run 1 at (83.13,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (115,222) size 115x16 contains 1 chunk(s)
+      LayoutSVGText {text} at (115,223) size 116x15 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 115x15
           chunk 1 (end anchor) text run 1 at (115.82,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirNone-anchorMiddle-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirNone-anchorMiddle-expected.txt
index 2086d8d..2d9c763 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirNone-anchorMiddle-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirNone-anchorMiddle-expected.txt
@@ -9,7 +9,7 @@
       LayoutSVGText {text} at (156,186) size 148x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 147x12
           chunk 1 (middle anchor) text run 1 at (156.57,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (172,222) size 116x16 contains 1 chunk(s)
+      LayoutSVGText {text} at (172,223) size 116x15 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 115x15
           chunk 1 (middle anchor) text run 1 at (172.91,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirNone-anchorStart-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirNone-anchorStart-expected.txt
index 9a5cc70..f31070f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirNone-anchorStart-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-dirNone-anchorStart-expected.txt
@@ -9,7 +9,7 @@
       LayoutSVGText {text} at (230,186) size 147x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 147x12
           chunk 1 text run 1 at (230.00,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (230,222) size 115x16 contains 1 chunk(s)
+      LayoutSVGText {text} at (230,223) size 115x15 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 115x15
           chunk 1 text run 1 at (230.00,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorEnd-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorEnd-expected.txt
index 4553c6b..de2b355 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorEnd-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorEnd-expected.txt
@@ -10,7 +10,7 @@
         LayoutSVGText {text} at (83,186) size 147x12 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 147x12
             chunk 1 (end anchor) text run 1 at (83.13,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-        LayoutSVGText {text} at (115,222) size 115x16 contains 1 chunk(s)
+        LayoutSVGText {text} at (115,223) size 116x15 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 115x15
             chunk 1 (end anchor) text run 1 at (115.82,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorMiddle-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorMiddle-expected.txt
index d592bc3..4c6485e2 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorMiddle-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorMiddle-expected.txt
@@ -10,7 +10,7 @@
         LayoutSVGText {text} at (156,186) size 148x12 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 147x12
             chunk 1 (middle anchor) text run 1 at (156.57,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-        LayoutSVGText {text} at (172,222) size 116x16 contains 1 chunk(s)
+        LayoutSVGText {text} at (172,223) size 116x15 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 115x15
             chunk 1 (middle anchor) text run 1 at (172.91,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorStart-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorStart-expected.txt
index 528035c9..f57c2c3 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorStart-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorStart-expected.txt
@@ -10,7 +10,7 @@
         LayoutSVGText {text} at (230,186) size 147x12 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 147x12
             chunk 1 text run 1 at (230.00,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-        LayoutSVGText {text} at (230,222) size 115x16 contains 1 chunk(s)
+        LayoutSVGText {text} at (230,223) size 115x15 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 115x15
             chunk 1 text run 1 at (230.00,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-no-markup-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-no-markup-expected.txt
index 9a5cc70..f31070f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-no-markup-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/text-anchor-no-markup-expected.txt
@@ -9,7 +9,7 @@
       LayoutSVGText {text} at (230,186) size 147x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 147x12
           chunk 1 text run 1 at (230.00,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (230,222) size 115x16 contains 1 chunk(s)
+      LayoutSVGText {text} at (230,223) size 115x15 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 115x15
           chunk 1 text run 1 at (230.00,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/tspan-direction-ltr-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/tspan-direction-ltr-expected.txt
index 6e4825a..c6caaba0 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/tspan-direction-ltr-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-I18N/tspan-direction-ltr-expected.txt
@@ -6,8 +6,8 @@
       LayoutSVGText {text} at (89,133) size 282x21 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (11,0) size 147x20
           chunk 1 (middle anchor) text run 1 at (100.89,150.00) startOffset 0 endOffset 16 width 146.12: "dirLTR ubEmbed \""
-        LayoutSVGTSpan {tspan} at (0,0) size 124x20
-          LayoutSVGInlineText {#text} at (157,0) size 124x20
+        LayoutSVGTSpan {tspan} at (0,0) size 125x20
+          LayoutSVGInlineText {#text} at (156,0) size 125x20
             chunk 1 (middle anchor) text run 1 at (247.01,150.00) startOffset 0 endOffset 12 width 72.76 RTL: "\x{646}\x{634}\x{627}\x{637} \x{627}\x{644}\x{62A}\x{62F}\x{648}\x{64A}\x{644}"
             chunk 1 (middle anchor) text run 1 at (319.76,150.00) startOffset 0 endOffset 5 width 50.74: "\x{60C} W3C"
         LayoutSVGInlineText {#text} at (0,0) size 12x20
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/bidi-text-query-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/text/bidi-text-query-expected.txt
index f5edb0b8..8059ad4 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/bidi-text-query-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/bidi-text-query-expected.txt
@@ -7,9 +7,9 @@
         LayoutSVGTSpan {tspan} at (0,0) size 127x20
           LayoutSVGInlineText {#text} at (0,0) size 127x20
             chunk 1 text run 1 at (10.00,50.00) startOffset 0 endOffset 17 width 126.54 LTR override: "\x{646}\x{634}\x{627}\x{637} \x{627}\x{644}\x{62A}\x{62F}\x{648}\x{64A}\x{644}\x{60C} W3C"
-      LayoutSVGText {text} at (10,63) size 124x21 contains 1 chunk(s)
-        LayoutSVGTSpan {tspan} at (0,0) size 124x20
-          LayoutSVGInlineText {#text} at (0,0) size 124x20
+      LayoutSVGText {text} at (9,63) size 125x21 contains 1 chunk(s)
+        LayoutSVGTSpan {tspan} at (0,0) size 125x20
+          LayoutSVGInlineText {#text} at (0,0) size 125x20
             chunk 1 text run 1 at (10.00,80.00) startOffset 0 endOffset 12 width 72.76 RTL: "\x{646}\x{634}\x{627}\x{637} \x{627}\x{644}\x{62A}\x{62F}\x{648}\x{64A}\x{644}"
             chunk 1 text run 1 at (82.76,80.00) startOffset 0 endOffset 5 width 50.74: "\x{60C} W3C"
       LayoutSVGText {text} at (9,93) size 125x21 contains 1 chunk(s)
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/combining-character-queries-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/text/combining-character-queries-expected.txt
index 5a1ee7a..d9ad34a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/combining-character-queries-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/combining-character-queries-expected.txt
@@ -471,24 +471,24 @@
           LayoutSVGText {text} at (350,16) size 58x42 contains 1 chunk(s)
             LayoutSVGInlineText {#text} at (0,0) size 58x42
               chunk 1 text run 1 at (350.00,50.00) startOffset 0 endOffset 6 width 57.51: "ab\x{30C}c\x{30C}\x{30C}"
-          LayoutSVGText {text} at (51,79) size 50x62 contains 1 chunk(s)
-            LayoutSVGInlineText {#text} at (0,6) size 49x62
+          LayoutSVGText {text} at (51,86) size 50x55 contains 1 chunk(s)
+            LayoutSVGInlineText {#text} at (0,0) size 49x55
               chunk 1 text run 1 at (51.67,125.00) startOffset 0 endOffset 3 width 13.40: "c\x{30C}\x{30C}"
               chunk 1 text run 1 at (65.07,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}"
               chunk 1 text run 1 at (65.07,125.00) startOffset 0 endOffset 2 width 16.97: "b\x{30C}"
               chunk 1 text run 1 at (82.04,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}"
               chunk 1 text run 1 at (82.04,125.00) startOffset 0 endOffset 1 width 17.96: "a"
               chunk 1 text run 1 at (100.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}"
-          LayoutSVGText {text} at (200,90) size 50x44 contains 1 chunk(s)
-            LayoutSVGInlineText {#text} at (0,0) size 50x44
+          LayoutSVGText {text} at (201,94) size 49x40 contains 1 chunk(s)
+            LayoutSVGInlineText {#text} at (0,0) size 49x40
               chunk 1 text run 1 at (201.43,125.00) startOffset 0 endOffset 3 width 15.53: "c\x{30C}\x{30C}"
               chunk 1 text run 1 at (216.97,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}"
               chunk 1 text run 1 at (216.97,125.00) startOffset 0 endOffset 2 width 17.50: "b\x{30C}"
               chunk 1 text run 1 at (234.47,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}"
               chunk 1 text run 1 at (234.47,125.00) startOffset 0 endOffset 1 width 15.53: "a"
               chunk 1 text run 1 at (250.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}"
-          LayoutSVGText {text} at (327,91) size 73x42 contains 1 chunk(s)
-            LayoutSVGInlineText {#text} at (0,0) size 73x42
+          LayoutSVGText {text} at (342,93) size 58x40 contains 1 chunk(s)
+            LayoutSVGInlineText {#text} at (0,0) size 58x40
               chunk 1 text run 1 at (342.15,125.00) startOffset 0 endOffset 3 width 18.58: "c\x{30C}\x{30C}"
               chunk 1 text run 1 at (360.73,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}"
               chunk 1 text run 1 at (360.73,125.00) startOffset 0 endOffset 2 width 19.81: "b\x{30C}"
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-intro-05-t-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-intro-05-t-expected.txt
index 74bdf7d9..7e88028 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-intro-05-t-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-intro-05-t-expected.txt
@@ -2,15 +2,15 @@
   LayoutView at (0,0) size 800x600
 layer at (0,0) size 800x600
   LayoutSVGRoot {svg} at (0,0) size 800x600
-    LayoutSVGContainer {g} at (30,87) size 737x330
-      LayoutSVGText {text} at (91,52) size 369x38 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 369x38
+    LayoutSVGContainer {g} at (31,87) size 736x326
+      LayoutSVGText {text} at (92,52) size 368x36 contains 1 chunk(s)
+        LayoutSVGInlineText {#text} at (0,0) size 368x36
           chunk 1 (end anchor) text run 1 at (92.27,80.00) startOffset 0 endOffset 37 width 367.73 RTL: "\x{644}\x{645}\x{627}\x{630}\x{627} \x{644}\x{627} \x{64A}\x{62A}\x{643}\x{644}\x{645}\x{648}\x{646} \x{627}\x{644}\x{644}\x{651}\x{63A}\x{629} \x{627}\x{644}\x{639}\x{631}\x{628}\x{64A}\x{629} \x{641}\x{62D}\x{633}\x{628}\x{61F}"
-      LayoutSVGText {text} at (18,127) size 442x45 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 442x45
+      LayoutSVGText {text} at (18,127) size 442x42 contains 1 chunk(s)
+        LayoutSVGInlineText {#text} at (0,0) size 442x42
           chunk 1 (end anchor) text run 1 at (18.72,160.00) startOffset 0 endOffset 37 width 441.28 RTL: "\x{644}\x{645}\x{627}\x{630}\x{627} \x{644}\x{627} \x{64A}\x{62A}\x{643}\x{644}\x{645}\x{648}\x{646} \x{627}\x{644}\x{644}\x{651}\x{63A}\x{629} \x{627}\x{644}\x{639}\x{631}\x{628}\x{64A}\x{629} \x{641}\x{62D}\x{633}\x{628}\x{61F}"
-      LayoutSVGText {text} at (91,212) size 369x38 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (0,0) size 369x38
+      LayoutSVGText {text} at (92,212) size 368x36 contains 1 chunk(s)
+        LayoutSVGInlineText {#text} at (0,0) size 368x36
           chunk 1 (end anchor) text run 1 at (92.27,240.00) startOffset 0 endOffset 37 width 367.73 RTL: "\x{644}\x{645}\x{627}\x{630}\x{627} \x{644}\x{627} \x{64A}\x{62A}\x{643}\x{644}\x{645}\x{648}\x{646} \x{627}\x{644}\x{644}\x{651}\x{63A}\x{629} \x{627}\x{644}\x{639}\x{631}\x{628}\x{64A}\x{629} \x{641}\x{62D}\x{633}\x{628}\x{61F}"
     LayoutSVGText {text} at (10,304) size 264x47 contains 1 chunk(s)
       LayoutSVGInlineText {#text} at (0,0) size 264x47
diff --git a/third_party/WebKit/LayoutTests/platform/win/plugins/plugin-javascript-access-expected.txt b/third_party/WebKit/LayoutTests/platform/win/plugins/plugin-javascript-access-expected.txt
index 121fe35..d63212d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/plugins/plugin-javascript-access-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/plugins/plugin-javascript-access-expected.txt
@@ -1,27 +1,16 @@
-Name: WebKit Test PlugIn
+Name: Blink Test Plugin
 
-Description: Simple Netscape plug-in that handles test content for WebKit
+Description: Interesting description.
 
-Filename: np_test_netscape_plugin.dll
+Filename: blink_test_plugin.dll
 
 Mime Types:
 
-Type: application/x-webkit-test-netscape
+Type: application/x-blink-test-plugin
 
-Description: test netscape content
+Description: Interesting description.
 
-Suffixes: testnetscape
-
-
-Plugin.item() works.
-
-Plugin.namedItem() works.
-
-Type: image/png
-
-Description: PNG image
-
-Suffixes: png
+Suffixes:
 
 
 Plugin.item() works.
@@ -32,11 +21,11 @@
 
 PluginArray.namedItem() works.
 
-Type: application/x-webkit-test-netscape
+Type: application/x-blink-test-plugin
 
-Description: test netscape content
+Description: Interesting description.
 
-Suffixes: testnetscape
+Suffixes:
 
 MimeTypeArray.item() works.
 
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/W3C-I18N/tspan-direction-ltr-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/W3C-I18N/tspan-direction-ltr-expected.txt
index 7d43180..7c3ff141 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/W3C-I18N/tspan-direction-ltr-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/W3C-I18N/tspan-direction-ltr-expected.txt
@@ -6,8 +6,8 @@
       LayoutSVGText {text} at (89,133) size 282x21 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (11,0) size 147x20
           chunk 1 (middle anchor) text run 1 at (100.89,150.00) startOffset 0 endOffset 16 width 146.12: "dirLTR ubEmbed \""
-        LayoutSVGTSpan {tspan} at (0,0) size 124x20
-          LayoutSVGInlineText {#text} at (157,0) size 124x20
+        LayoutSVGTSpan {tspan} at (0,0) size 125x20
+          LayoutSVGInlineText {#text} at (156,0) size 125x20
             chunk 1 (middle anchor) text run 1 at (247.01,150.00) startOffset 0 endOffset 12 width 72.76 RTL: "\x{646}\x{634}\x{627}\x{637} \x{627}\x{644}\x{62A}\x{62F}\x{648}\x{64A}\x{644}"
             chunk 1 (middle anchor) text run 1 at (319.76,150.00) startOffset 0 endOffset 5 width 50.74: "\x{60C} W3C"
         LayoutSVGInlineText {#text} at (0,0) size 12x20
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/bidi-text-query-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/text/bidi-text-query-expected.txt
index 711a894..47f6a62 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/text/bidi-text-query-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/bidi-text-query-expected.txt
@@ -7,9 +7,9 @@
         LayoutSVGTSpan {tspan} at (0,0) size 127x20
           LayoutSVGInlineText {#text} at (0,0) size 127x20
             chunk 1 text run 1 at (10.00,50.00) startOffset 0 endOffset 17 width 126.54 LTR override: "\x{646}\x{634}\x{627}\x{637} \x{627}\x{644}\x{62A}\x{62F}\x{648}\x{64A}\x{644}\x{60C} W3C"
-      LayoutSVGText {text} at (10,63) size 124x21 contains 1 chunk(s)
-        LayoutSVGTSpan {tspan} at (0,0) size 124x20
-          LayoutSVGInlineText {#text} at (0,0) size 124x20
+      LayoutSVGText {text} at (9,63) size 125x21 contains 1 chunk(s)
+        LayoutSVGTSpan {tspan} at (0,0) size 125x20
+          LayoutSVGInlineText {#text} at (0,0) size 125x20
             chunk 1 text run 1 at (10.00,80.00) startOffset 0 endOffset 12 width 72.76 RTL: "\x{646}\x{634}\x{627}\x{637} \x{627}\x{644}\x{62A}\x{62F}\x{648}\x{64A}\x{644}"
             chunk 1 text run 1 at (82.76,80.00) startOffset 0 endOffset 5 width 50.74: "\x{60C} W3C"
       LayoutSVGText {text} at (9,93) size 125x21 contains 1 chunk(s)
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirLTR-anchorEnd-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirLTR-anchorEnd-expected.txt
index 0f7a124..d8c9f08 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirLTR-anchorEnd-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirLTR-anchorEnd-expected.txt
@@ -9,7 +9,7 @@
       LayoutSVGText {text} at (83,186) size 147x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 147x12
           chunk 1 (end anchor) text run 1 at (83.13,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (115,222) size 115x16 contains 1 chunk(s)
+      LayoutSVGText {text} at (115,223) size 116x15 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 115x15
           chunk 1 (end anchor) text run 1 at (115.82,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirLTR-anchorMiddle-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirLTR-anchorMiddle-expected.txt
index 40f5297..c41b146 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirLTR-anchorMiddle-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirLTR-anchorMiddle-expected.txt
@@ -9,7 +9,7 @@
       LayoutSVGText {text} at (156,186) size 148x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 147x12
           chunk 1 (middle anchor) text run 1 at (156.57,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (172,222) size 116x16 contains 1 chunk(s)
+      LayoutSVGText {text} at (172,223) size 116x15 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 115x15
           chunk 1 (middle anchor) text run 1 at (172.91,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirLTR-anchorStart-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirLTR-anchorStart-expected.txt
index 95096ae..dd91788 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirLTR-anchorStart-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirLTR-anchorStart-expected.txt
@@ -9,7 +9,7 @@
       LayoutSVGText {text} at (230,186) size 147x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 147x12
           chunk 1 text run 1 at (230.00,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (230,222) size 115x16 contains 1 chunk(s)
+      LayoutSVGText {text} at (230,223) size 115x15 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 115x15
           chunk 1 text run 1 at (230.00,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirNone-anchorEnd-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirNone-anchorEnd-expected.txt
index 0f7a124..d8c9f08 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirNone-anchorEnd-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirNone-anchorEnd-expected.txt
@@ -9,7 +9,7 @@
       LayoutSVGText {text} at (83,186) size 147x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 147x12
           chunk 1 (end anchor) text run 1 at (83.13,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (115,222) size 115x16 contains 1 chunk(s)
+      LayoutSVGText {text} at (115,223) size 116x15 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 115x15
           chunk 1 (end anchor) text run 1 at (115.82,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirNone-anchorMiddle-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirNone-anchorMiddle-expected.txt
index 40f5297..c41b146 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirNone-anchorMiddle-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirNone-anchorMiddle-expected.txt
@@ -9,7 +9,7 @@
       LayoutSVGText {text} at (156,186) size 148x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 147x12
           chunk 1 (middle anchor) text run 1 at (156.57,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (172,222) size 116x16 contains 1 chunk(s)
+      LayoutSVGText {text} at (172,223) size 116x15 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 115x15
           chunk 1 (middle anchor) text run 1 at (172.91,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirNone-anchorStart-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirNone-anchorStart-expected.txt
index 95096ae..dd91788 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirNone-anchorStart-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-dirNone-anchorStart-expected.txt
@@ -9,7 +9,7 @@
       LayoutSVGText {text} at (230,186) size 147x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 147x12
           chunk 1 text run 1 at (230.00,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (230,222) size 115x16 contains 1 chunk(s)
+      LayoutSVGText {text} at (230,223) size 115x15 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 115x15
           chunk 1 text run 1 at (230.00,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorEnd-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorEnd-expected.txt
index 82edf26..ce61cab2 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorEnd-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorEnd-expected.txt
@@ -10,7 +10,7 @@
         LayoutSVGText {text} at (83,186) size 147x12 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 147x12
             chunk 1 (end anchor) text run 1 at (83.13,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-        LayoutSVGText {text} at (115,222) size 115x16 contains 1 chunk(s)
+        LayoutSVGText {text} at (115,223) size 116x15 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 115x15
             chunk 1 (end anchor) text run 1 at (115.82,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorMiddle-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorMiddle-expected.txt
index 8938759..dad315a69 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorMiddle-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorMiddle-expected.txt
@@ -10,7 +10,7 @@
         LayoutSVGText {text} at (156,186) size 148x12 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 147x12
             chunk 1 (middle anchor) text run 1 at (156.57,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-        LayoutSVGText {text} at (172,222) size 116x16 contains 1 chunk(s)
+        LayoutSVGText {text} at (172,223) size 116x15 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 115x15
             chunk 1 (middle anchor) text run 1 at (172.91,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorStart-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorStart-expected.txt
index ba14aba..f7e6fb5b 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorStart-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-inherited-dirLTR-anchorStart-expected.txt
@@ -10,7 +10,7 @@
         LayoutSVGText {text} at (230,186) size 147x12 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 147x12
             chunk 1 text run 1 at (230.00,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-        LayoutSVGText {text} at (230,222) size 115x16 contains 1 chunk(s)
+        LayoutSVGText {text} at (230,223) size 115x15 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 115x15
             chunk 1 text run 1 at (230.00,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-no-markup-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-no-markup-expected.txt
index 95096ae..dd91788 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-no-markup-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win7/svg/W3C-I18N/text-anchor-no-markup-expected.txt
@@ -9,7 +9,7 @@
       LayoutSVGText {text} at (230,186) size 147x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 147x12
           chunk 1 text run 1 at (230.00,195.00) startOffset 0 endOffset 31 width 146.87 RTL: "\x{5DC}\x{5D9}\x{5E6}\x{5D5}\x{5E8} \x{5DE}\x{5D4}\x{5E8}\x{5E9}\x{5EA} \x{5E8}\x{5E9}\x{5EA} \x{5DB}\x{5DC}\x{5DC} \x{5E2}\x{5D5}\x{5DC}\x{5DE}\x{5D9}\x{5EA} \x{5D1}\x{5D0}\x{5DE}\x{5EA}"
-      LayoutSVGText {text} at (230,222) size 115x16 contains 1 chunk(s)
+      LayoutSVGText {text} at (230,223) size 115x15 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 115x15
           chunk 1 text run 1 at (230.00,235.00) startOffset 0 endOffset 38 width 114.18 RTL: "\x{62C}\x{639}\x{644} \x{634}\x{628}\x{643}\x{629} \x{627}\x{644}\x{648}\x{64A}\x{628} \x{627}\x{644}\x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{639}\x{627}\x{644}\x{645}\x{64A}\x{651}\x{629} \x{62D}\x{642}\x{64B}\x{651}\x{627}"
       LayoutSVGImage {image} at (280,183) size 214x44
diff --git a/third_party/WebKit/LayoutTests/plugins/change-widget-and-click-crash-expected.txt b/third_party/WebKit/LayoutTests/plugins/change-widget-and-click-crash-expected.txt
index 7ef22e9..f7a66c6 100644
--- a/third_party/WebKit/LayoutTests/plugins/change-widget-and-click-crash-expected.txt
+++ b/third_party/WebKit/LayoutTests/plugins/change-widget-and-click-crash-expected.txt
@@ -1 +1,2 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
 PASS
diff --git a/third_party/WebKit/LayoutTests/plugins/change-widget-and-click-crash.html b/third_party/WebKit/LayoutTests/plugins/change-widget-and-click-crash.html
index eaaf536d8..f439623 100644
--- a/third_party/WebKit/LayoutTests/plugins/change-widget-and-click-crash.html
+++ b/third_party/WebKit/LayoutTests/plugins/change-widget-and-click-crash.html
@@ -28,7 +28,7 @@
 }
 </script>
 <body onload="load()">
-    <object id="x" data="x" border="1" type="application/x-webkit-test-netscape">
+    <object id="x" data="x" border="1" type="application/x-blink-test-plugin">
         <param name="wmode" value="transparent">
     </object>
 </body>
diff --git a/third_party/WebKit/LayoutTests/plugins/instance-available-before-stylesheets-loaded-object.html b/third_party/WebKit/LayoutTests/plugins/instance-available-before-stylesheets-loaded-object.html
index 5f827f991..9a140b1 100644
--- a/third_party/WebKit/LayoutTests/plugins/instance-available-before-stylesheets-loaded-object.html
+++ b/third_party/WebKit/LayoutTests/plugins/instance-available-before-stylesheets-loaded-object.html
@@ -1,5 +1,5 @@
 <link rel="stylesheet" href="data:text/css,">
-<object id="plugin" type="application/x-webkit-test-netscape" width=100 height=100></object>
+<object id="plugin" type="application/x-blink-deprecated-test-plugin" width=100 height=100></object>
 <p id="result">
 </p>
 <script>
@@ -8,7 +8,7 @@
 
     var plugIn = document.getElementById("plugin");
 
-    document.getElementById("result").innerText = ("eventLoggingEnabled" in plugIn)
+    document.getElementById("result").innerText = ("testPassTestObject" in plugIn)
         ? "PASS: Plugin instance available while waiting for style sheets to load"
         : "FAIL: Plugin not instantiated on property access while waiting for style sheets to load";
 
diff --git a/third_party/WebKit/LayoutTests/plugins/instance-available-before-stylesheets-loaded.html b/third_party/WebKit/LayoutTests/plugins/instance-available-before-stylesheets-loaded.html
index 4694241..1e4880e 100644
--- a/third_party/WebKit/LayoutTests/plugins/instance-available-before-stylesheets-loaded.html
+++ b/third_party/WebKit/LayoutTests/plugins/instance-available-before-stylesheets-loaded.html
@@ -1,5 +1,5 @@
 <link rel="stylesheet" href="data:text/css,">
-<embed id="plugin" type="application/x-webkit-test-netscape" width=100 height=100></embed>
+<embed id="plugin" type="application/x-blink-deprecated-test-plugin" width=100 height=100></embed>
 <p id="result">
 </p>
 <script>
@@ -8,7 +8,7 @@
 
     var plugIn = document.getElementById("plugin");
 
-    document.getElementById("result").innerText = ("eventLoggingEnabled" in plugIn)
+    document.getElementById("result").innerText = ("testPassTestObject" in plugIn)
         ? "PASS: Plugin instance available while waiting for style sheets to load"
         : "FAIL: Plugin not instantiated on property access while waiting for style sheets to load";
 
diff --git a/third_party/WebKit/LayoutTests/plugins/missing-plugin-expected.txt b/third_party/WebKit/LayoutTests/plugins/missing-plugin-expected.txt
index 464dcd6..9773b39 100644
--- a/third_party/WebKit/LayoutTests/plugins/missing-plugin-expected.txt
+++ b/third_party/WebKit/LayoutTests/plugins/missing-plugin-expected.txt
@@ -1,2 +1,3 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
  
 This tests that a missing plugin does not cause an assertion failure. Bug 41900
diff --git a/third_party/WebKit/LayoutTests/plugins/missing-plugin.html b/third_party/WebKit/LayoutTests/plugins/missing-plugin.html
index 761ef38..85725d6a 100644
--- a/third_party/WebKit/LayoutTests/plugins/missing-plugin.html
+++ b/third_party/WebKit/LayoutTests/plugins/missing-plugin.html
@@ -6,7 +6,7 @@
 </script>
 </head>
 <body>
-<embed type="application/x-webkit-test-netscape"></embed>
+<embed type="application/x-blink-test-plugin"></embed>
 <embed type="application/x-non-existent"></embed>
 <p>
     This tests that a missing plugin does not cause an assertion failure.
diff --git a/third_party/WebKit/LayoutTests/plugins/mouse-capture-inside-shadow-expected.txt b/third_party/WebKit/LayoutTests/plugins/mouse-capture-inside-shadow-expected.txt
index 0aa2e65e..3d25c66 100644
--- a/third_party/WebKit/LayoutTests/plugins/mouse-capture-inside-shadow-expected.txt
+++ b/third_party/WebKit/LayoutTests/plugins/mouse-capture-inside-shadow-expected.txt
@@ -1,3 +1,7 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
+CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(true)
+CONSOLE MESSAGE: Blink Test Plugin: MouseDown at (12,12)
+CONSOLE MESSAGE: Blink Test Plugin: MouseUp at (212,112)
 This tests that mousedown captures the mouse correctly for a plugin object and continues to send events even if the mouse moves outside of the bounds of the plugin. On a successful run, plugin will see mousedown, followed by a mousemove, followed by a mouseup.
 Console
 plugin.mousedown
diff --git a/third_party/WebKit/LayoutTests/plugins/mouse-capture-inside-shadow.html b/third_party/WebKit/LayoutTests/plugins/mouse-capture-inside-shadow.html
index 8ce9731..60345f6 100644
--- a/third_party/WebKit/LayoutTests/plugins/mouse-capture-inside-shadow.html
+++ b/third_party/WebKit/LayoutTests/plugins/mouse-capture-inside-shadow.html
@@ -15,7 +15,7 @@
     var div = document.getElementById('container');
 
     var plugin = document.createElement('object');
-    plugin.type = 'application/x-webkit-test-netscape';
+    plugin.type = 'application/x-blink-test-plugin';
     // Plugin takes up the full available space inside the ShadowRoot.
     plugin.style.width = '100%';
     plugin.style.height = '100%';
diff --git a/third_party/WebKit/LayoutTests/plugins/mouse-click-iframe-to-plugin.html b/third_party/WebKit/LayoutTests/plugins/mouse-click-iframe-to-plugin.html
index 58e388eae..c88fb55 100644
--- a/third_party/WebKit/LayoutTests/plugins/mouse-click-iframe-to-plugin.html
+++ b/third_party/WebKit/LayoutTests/plugins/mouse-click-iframe-to-plugin.html
@@ -23,7 +23,7 @@
 </script>
 </head>
 <body onload="runTest();">
-<embed type="application/x-webkit-test-netscape" width="100" height="100"></embed><br>
+<embed type="application/x-blink-test-plugin" width="100" height="100"></embed><br>
 <iframe id="frame" width="640"></iframe>
 <div id="output">FAILED</div>
 </body>
diff --git a/third_party/WebKit/LayoutTests/plugins/open-and-close-window-with-plugin-expected.txt b/third_party/WebKit/LayoutTests/plugins/open-and-close-window-with-plugin-expected.txt
index 3497cbd..f9bb2f7 100644
--- a/third_party/WebKit/LayoutTests/plugins/open-and-close-window-with-plugin-expected.txt
+++ b/third_party/WebKit/LayoutTests/plugins/open-and-close-window-with-plugin-expected.txt
@@ -1,2 +1 @@
-PLUGIN: NPP_Destroy
 This tests that opening a window with a WebView that contains a plugin, and then closing the window without calling -[WebView close] does not leak the window or the web view.
diff --git a/third_party/WebKit/LayoutTests/plugins/overlay-scrollbar-mouse-capture-expected.txt b/third_party/WebKit/LayoutTests/plugins/overlay-scrollbar-mouse-capture-expected.txt
index 9dd8f48..015fae7 100644
--- a/third_party/WebKit/LayoutTests/plugins/overlay-scrollbar-mouse-capture-expected.txt
+++ b/third_party/WebKit/LayoutTests/plugins/overlay-scrollbar-mouse-capture-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
 
 This tests whether scrolling still works correctly when an overlay scrollbar is over a plugin. The plugin should still receive mouse down/up events when clicking an overlay scrollbar. Scrolling should still work correctly too. However mouse capture should not be started on the plugin as this would interfere with events going to the scrollbar.
 
diff --git a/third_party/WebKit/LayoutTests/plugins/overlay-scrollbar-mouse-capture.html b/third_party/WebKit/LayoutTests/plugins/overlay-scrollbar-mouse-capture.html
index cacdd09..10730e7 100644
--- a/third_party/WebKit/LayoutTests/plugins/overlay-scrollbar-mouse-capture.html
+++ b/third_party/WebKit/LayoutTests/plugins/overlay-scrollbar-mouse-capture.html
@@ -52,7 +52,7 @@
 
         var d = document.getElementById('container');
         var plugin = document.createElement('object');
-        plugin.type = 'application/x-webkit-test-netscape';
+        plugin.type = 'application/x-blink-test-plugin';
         plugin.width = window.innerWidth * 2;
         plugin.height = window.innerHeight * 2;
         plugin.addEventListener('mousedown', function(e) {
diff --git a/third_party/WebKit/LayoutTests/plugins/plugin-javascript-access.html b/third_party/WebKit/LayoutTests/plugins/plugin-javascript-access.html
index e83fc66..b304238 100644
--- a/third_party/WebKit/LayoutTests/plugins/plugin-javascript-access.html
+++ b/third_party/WebKit/LayoutTests/plugins/plugin-javascript-access.html
@@ -15,8 +15,8 @@
 for (var i = 0; i < navigator.plugins.length; i++) {
     var plugin = navigator.plugins[i];
 
-    // We can only guarantee that the Test PlugIn is installed.
-    if (plugin.name != "WebKit Test PlugIn")
+    // We can only guarantee that the Test Plugin is installed.
+    if (plugin.name != "Blink Test Plugin")
         continue;
     else
         foundTestPlugin = true;
@@ -62,7 +62,7 @@
     var mimeType = navigator.mimeTypes[i];
 
     // We can only guarantee that the Test PlugIn is installed.
-    if (mimeType.type != "application/x-webkit-test-netscape")
+    if (mimeType.type != "application/x-blink-test-plugin")
         continue;
 
     document.writeln("<p>Type: " + mimeType.type + "<\/p>");
@@ -83,7 +83,7 @@
 }
 
 if (!foundTestPlugin)
-    document.writeln("<p>FAILURE!  (Failed to find netscape test plugin)<\/p>");
+    document.writeln("<p>FAILURE!  (Failed to find blink test plugin)<\/p>");
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/plugins/renderless-plugin-creation-doesnt-crash-without-frame.html b/third_party/WebKit/LayoutTests/plugins/renderless-plugin-creation-doesnt-crash-without-frame.html
index 4a004cde..424dec0 100644
--- a/third_party/WebKit/LayoutTests/plugins/renderless-plugin-creation-doesnt-crash-without-frame.html
+++ b/third_party/WebKit/LayoutTests/plugins/renderless-plugin-creation-doesnt-crash-without-frame.html
@@ -11,7 +11,7 @@
 
   newDoc = document.implementation.createDocument("http://www.w3.org/2000/svg", null);
   newDoc.adoptNode(embedElement);
-  embedElement.setAttribute("type", "application/x-webkit-test-netscape");
+  embedElement.setAttribute("type", "application/x-blink-test-plugin");
 }
 
 document.addEventListener("DOMContentLoaded", init, false);
diff --git a/third_party/WebKit/LayoutTests/plugins/resources/mouse-move-over-plugin-in-frame.html b/third_party/WebKit/LayoutTests/plugins/resources/mouse-move-over-plugin-in-frame.html
index c1d6dabe..bc627cd9 100644
--- a/third_party/WebKit/LayoutTests/plugins/resources/mouse-move-over-plugin-in-frame.html
+++ b/third_party/WebKit/LayoutTests/plugins/resources/mouse-move-over-plugin-in-frame.html
@@ -1 +1 @@
-<object name="plugin" type="application/x-webkit-test-netscape"></object>
\ No newline at end of file
+<object name="plugin" type="application/x-blink-test-plugin"></object>
diff --git a/third_party/WebKit/LayoutTests/plugins/resources/open-and-close-window-with-plugin.html b/third_party/WebKit/LayoutTests/plugins/resources/open-and-close-window-with-plugin.html
index 785c4dbe..ee21dda6 100644
--- a/third_party/WebKit/LayoutTests/plugins/resources/open-and-close-window-with-plugin.html
+++ b/third_party/WebKit/LayoutTests/plugins/resources/open-and-close-window-with-plugin.html
@@ -1,7 +1,6 @@
 <script>
 function runTest() {
     var plugin = document.getElementById('testPlugin');
-    plugin.logDestroy = true;
 
     window.opener.setTimeout('setTimeout("testRunner.notifyDone()",50)', 0);
     window.close();
@@ -10,6 +9,6 @@
 </script>
 
 <body onload="runTest()">
-<embed id="testPlugin" type="application/x-webkit-test-netscape" width="200" height="200"></embed>
+<embed id="testPlugin" type="application/x-blink-deprecated-test-plugin" width="200" height="200"></embed>
 
 </body>
diff --git a/third_party/WebKit/LayoutTests/plugins/sequential-focus-expected.txt b/third_party/WebKit/LayoutTests/plugins/sequential-focus-expected.txt
index 02bcfb5..3db37182 100644
--- a/third_party/WebKit/LayoutTests/plugins/sequential-focus-expected.txt
+++ b/third_party/WebKit/LayoutTests/plugins/sequential-focus-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
 Test if sequential focus navigation works well with OBJECT in IFRAME.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/WebKit/LayoutTests/plugins/sequential-focus.html b/third_party/WebKit/LayoutTests/plugins/sequential-focus.html
index 6d8015e..97412b8 100644
--- a/third_party/WebKit/LayoutTests/plugins/sequential-focus.html
+++ b/third_party/WebKit/LayoutTests/plugins/sequential-focus.html
@@ -3,7 +3,7 @@
 <script src="../resources/js-test.js"></script>
 
 <input id="input-pre">
-<iframe srcdoc="<object type='application/x-webkit-test-netscape'></object>"></iframe>
+<iframe srcdoc="<object type='application/x-blink-test-plugin'></object>"></iframe>
 <input id="input-post">
 
 <script>
diff --git a/third_party/WebKit/LayoutTests/svg/text/invalid-non-bmp-characters.html b/third_party/WebKit/LayoutTests/svg/text/invalid-non-bmp-characters.html
new file mode 100644
index 0000000..0021de1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/text/invalid-non-bmp-characters.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<svg id="svg" height="0" font-size="100">
+    <text id="text">
+        <!-- invalid non-bmp character followed by a valid character -->
+        <tspan>&#x90012;a</tspan>
+        <!-- many invalid non-bmp characters followed by a valid character -->
+        <tspan>&#x90012;&#x90012;&#x90012;&#x90012;a&#x90012;&#x90012;&#x90012;&#x90012;a</tspan>
+        <!-- alternating valid and invalid non-bmp characters -->
+        <tspan>&#128514;&#x90012;&#128514;&#x90012;&#128514;&#x90012;</tspan>
+        <!-- invalid non-bmp characters in rtl -->
+        <tspan direction="rtl">نشاط&#128514;نشاط&#x90012;&#x90012;ن&#x90012;شاط&#128514;نش&#x90012;اط&#x90012;ا</tspan>
+    </text>
+</svg>
+<script>
+test(function() {
+  text.getComputedTextLength();
+  svg.parentElement.removeChild(svg);
+}, 'Text runs with invalid non-bmp characters should not crash.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/usb/disconnect-when-hidden-or-closed.html b/third_party/WebKit/LayoutTests/usb/disconnect-when-hidden-or-closed.html
new file mode 100644
index 0000000..b897726
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/usb/disconnect-when-hidden-or-closed.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../resources/mojo-helpers.js"></script>
+<script src="resources/fake-devices.js"></script>
+<script src="resources/usb-helpers.js"></script>
+<script>
+'use strict';
+
+const visibilityError =
+    'Connection is only allowed while the page is visible. This is a ' +
+    'temporary measure until we are able to effectively communicate to the ' +
+    'user that the page is connected to a device.';
+
+usb_test(usb => {
+  usb.mockDeviceManager.addMockDevice(usb.fakeDevices[0]);
+  testRunner.setPageVisibility('visible');
+  return navigator.usb.getDevices().then(devices => {
+    assert_equals(devices.length, 1);
+    let device = devices[0];
+    testRunner.setPageVisibility('hidden');
+    return assertRejectsWithError(
+        device.open(), 'SecurityError', visibilityError).then(() => {
+      assert_false(device.opened);
+    });
+  });
+}, 'device connection is disallowed while the tab is hidden');
+
+usb_test(usb => {
+  usb.mockDeviceManager.addMockDevice(usb.fakeDevices[0]);
+  testRunner.setPageVisibility('visible');
+  return navigator.usb.getDevices().then(devices => {
+    assert_equals(devices.length, 1);
+    let device = devices[0];
+    let promise = assertRejectsWithError(
+        device.open(), 'SecurityError', visibilityError);
+    testRunner.setPageVisibility('hidden');
+    return promise.then(() => {
+      assert_false(device.opened);
+    });
+  });
+}, 'device connection is disallowed when it finishes while the tab is hidden');
+
+usb_test(usb => {
+  usb.mockDeviceManager.addMockDevice(usb.fakeDevices[0]);
+  testRunner.setPageVisibility('visible');
+  return navigator.usb.getDevices().then(devices => {
+    assert_equals(devices.length, 1);
+    let device = devices[0];
+    return device.open().then(() => {
+      testRunner.setPageVisibility('hidden');
+      return assertRejectsWithError(
+          device.selectConfiguration(1), 'SecurityError', visibilityError);
+    }).then(() => {
+      assert_false(device.opened);
+    });
+  });
+}, 'device connection is closed when tab becomes hidden');
+
+usb_test(usb => {
+  usb.mockDeviceManager.addMockDevice(usb.fakeDevices[0]);
+  testRunner.setPageVisibility('visible');
+  return navigator.usb.getDevices().then(devices => {
+    assert_equals(devices.length, 1);
+    let device = devices[0];
+    return device.open().then(() => {
+      testRunner.setPageVisibility('hidden');
+      return assertRejectsWithError(
+          device.selectConfiguration(0), 'SecurityError', visibilityError);
+    }).then(() => {
+      assert_false(device.opened);
+      testRunner.setPageVisibility('visible');
+      return device.open()
+          .then(() => device.selectConfiguration(1))
+          .then(() => device.close());
+    });
+  });
+}, 'device can be reopened when the page is visible');
+</script>
diff --git a/third_party/WebKit/LayoutTests/usb/resources/usb-helpers.js b/third_party/WebKit/LayoutTests/usb/resources/usb-helpers.js
index faf30ac..ccceef54 100644
--- a/third_party/WebKit/LayoutTests/usb/resources/usb-helpers.js
+++ b/third_party/WebKit/LayoutTests/usb/resources/usb-helpers.js
@@ -1,5 +1,15 @@
 'use strict';
 
+function assertRejectsWithError(promise, name, message) {
+  return promise.then(() => {
+    assert_unreached('expected promise to reject with ' + name);
+  }, error => {
+    assert_equals(error.name, name);
+    if (message !== undefined)
+      assert_equals(error.message, message);
+  });
+}
+
 // TODO(reillyg): Remove when jyasskin upstreams this to testharness.js:
 // https://crbug.com/509058.
 function callWithKeyDown(functionCalledOnKeyPress) {
diff --git a/third_party/WebKit/LayoutTests/usb/usbDevice.html b/third_party/WebKit/LayoutTests/usb/usbDevice.html
index 3fefee2..e611148 100644
--- a/third_party/WebKit/LayoutTests/usb/usbDevice.html
+++ b/third_party/WebKit/LayoutTests/usb/usbDevice.html
@@ -7,16 +7,6 @@
 <script>
 'use strict';
 
-function assertRejectsWithError(promise, name, message) {
-  return promise.then(() => {
-    assert_unreached('expected promise to reject with ' + name);
-  }, error => {
-    assert_equals(error.name, name);
-    if (message !== undefined)
-      assert_equals(error.message, message);
-  });
-}
-
 function assertRejectsWithNotFoundError(promise) {
   return assertRejectsWithError(promise, 'NotFoundError');
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
index c5f3c985..a6a915cf 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -3464,6 +3464,7 @@
     method constructor
 interface OfflineAudioContext : AudioContext
     attribute @@toStringTag
+    getter length
     getter oncomplete
     method constructor
     method resume
@@ -6253,6 +6254,7 @@
     setter onremovetrack
 interface webkitOfflineAudioContext : AudioContext
     attribute @@toStringTag
+    getter length
     getter oncomplete
     method constructor
     method resume
diff --git a/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-constructor-expected.txt b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-constructor-expected.txt
index 2469ed9..dcb80873 100644
--- a/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-constructor-expected.txt
+++ b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-constructor-expected.txt
@@ -4,17 +4,27 @@
 
 
 PASS new OfflineAudioContext(1, 0, 44100) threw exception SyntaxError: Failed to construct 'OfflineAudioContext': number of frames cannot be zero..
-PASS new OfflineAudioContext(2, 512, 3000) did not throw exception.
-PASS new OfflineAudioContext(2, 512, 192000) did not throw exception.
-PASS new OfflineAudioContext(2, 512, 8000) did not throw exception.
-PASS new OfflineAudioContext(2, 512, 11025) did not throw exception.
-PASS new OfflineAudioContext(2, 512, 22050) did not throw exception.
-PASS new OfflineAudioContext(2, 512, 44100) did not throw exception.
-PASS new OfflineAudioContext(2, 512, 48000) did not throw exception.
-PASS new OfflineAudioContext(2, 512, 88200) did not throw exception.
-PASS new OfflineAudioContext(2, 512, 96000) did not throw exception.
-PASS new OfflineAudioContext(1, 0, NaN) threw exception TypeError: Failed to construct 'OfflineAudioContext': The provided float value is non-finite..
-PASS new OfflineAudioContext(1, 0, Infinite) threw exception ReferenceError: Infinite is not defined.
+PASS context = new OfflineAudioContext(2, 512, 3000) did not throw exception.
+PASS context.length is 512
+PASS context = new OfflineAudioContext(2, 1024, 192000) did not throw exception.
+PASS context.length is 1024
+PASS context = new OfflineAudioContext(2, 2048, 8000) did not throw exception.
+PASS context.length is 2048
+PASS context = new OfflineAudioContext(2, 4096, 11025) did not throw exception.
+PASS context.length is 4096
+PASS context = new OfflineAudioContext(2, 512, 22050) did not throw exception.
+PASS context.length is 512
+PASS context = new OfflineAudioContext(2, 512, 44100) did not throw exception.
+PASS context.length is 512
+PASS context = new OfflineAudioContext(2, 512, 48000) did not throw exception.
+PASS context.length is 512
+PASS context = new OfflineAudioContext(2, 512, 88200) did not throw exception.
+PASS context.length is 512
+PASS context.length = 99 did not throw exception.
+PASS context.length is 512
+PASS context = new OfflineAudioContext(2, 512, 96000) did not throw exception.
+PASS context = new OfflineAudioContext(1, 0, NaN) threw exception TypeError: Failed to construct 'OfflineAudioContext': The provided float value is non-finite..
+PASS context = new OfflineAudioContext(1, 0, Infinite) threw exception ReferenceError: Infinite is not defined.
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-constructor.html b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-constructor.html
index e8e941f4..3e3aa27 100644
--- a/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-constructor.html
+++ b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-constructor.html
@@ -8,21 +8,33 @@
 <script>
 description("Tests the OfflineAudioContext constructor");
 
+var context;      
 // Make sure we don't crash when giving 0 as number of frames.
 shouldThrow("new OfflineAudioContext(1, 0, 44100)");
 // Make sure we don't throw exceptions for supported ranges of sample rates for an OfflineAudioContext.
-shouldNotThrow("new OfflineAudioContext(2, 512, 3000)");
-shouldNotThrow("new OfflineAudioContext(2, 512, 192000)");
-shouldNotThrow("new OfflineAudioContext(2, 512, 8000)");
-shouldNotThrow("new OfflineAudioContext(2, 512, 11025)");
-shouldNotThrow("new OfflineAudioContext(2, 512, 22050)");
-shouldNotThrow("new OfflineAudioContext(2, 512, 44100)");
-shouldNotThrow("new OfflineAudioContext(2, 512, 48000)");
-shouldNotThrow("new OfflineAudioContext(2, 512, 88200)");
-shouldNotThrow("new OfflineAudioContext(2, 512, 96000)");
+shouldNotThrow("context = new OfflineAudioContext(2, 512, 3000)");
+shouldBeEqualToNumber("context.length", 512);      
+shouldNotThrow("context = new OfflineAudioContext(2, 1024, 192000)");
+shouldBeEqualToNumber("context.length", 1024);      
+shouldNotThrow("context = new OfflineAudioContext(2, 2048, 8000)");
+shouldBeEqualToNumber("context.length", 2048);      
+shouldNotThrow("context = new OfflineAudioContext(2, 4096, 11025)");
+shouldBeEqualToNumber("context.length", 4096);      
+shouldNotThrow("context = new OfflineAudioContext(2, 512, 22050)");
+shouldBeEqualToNumber("context.length", 512);      
+shouldNotThrow("context = new OfflineAudioContext(2, 512, 44100)");
+shouldBeEqualToNumber("context.length", 512);      
+shouldNotThrow("context = new OfflineAudioContext(2, 512, 48000)");
+shouldBeEqualToNumber("context.length", 512);      
+shouldNotThrow("context = new OfflineAudioContext(2, 512, 88200)");
+shouldBeEqualToNumber("context.length", 512);
+// Make sure length is read-only.
+shouldNotThrow("context.length = 99");
+shouldBeEqualToNumber("context.length", 512);
+shouldNotThrow("context = new OfflineAudioContext(2, 512, 96000)");
 // Make sure we throw exceptions for non-finite sample rates.
-shouldThrow("new OfflineAudioContext(1, 0, NaN)");
-shouldThrow("new OfflineAudioContext(1, 0, Infinite)");
+shouldThrow("context = new OfflineAudioContext(1, 0, NaN)");
+shouldThrow("context = new OfflineAudioContext(1, 0, Infinite)");
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
index 22452fb..12a2329 100644
--- a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
@@ -675,6 +675,7 @@
     property rel
     property relList
     property rev
+    property scope
     property sheet
     property sizes
     property target
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index e3e1459..b6f1283 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -2526,6 +2526,7 @@
     getter rel
     getter relList
     getter rev
+    getter scope
     getter sheet
     getter sizes
     getter target
@@ -2542,6 +2543,7 @@
     setter rel
     setter relList
     setter rev
+    setter scope
     setter sizes
     setter target
     setter type
@@ -3986,6 +3988,7 @@
     method constructor
 interface OfflineAudioContext : AudioContext
     attribute @@toStringTag
+    getter length
     getter oncomplete
     method constructor
     method resume
@@ -7246,6 +7249,7 @@
     setter onremovetrack
 interface webkitOfflineAudioContext : AudioContext
     attribute @@toStringTag
+    getter length
     getter oncomplete
     method constructor
     method resume
@@ -7514,11 +7518,11 @@
     attribute outerWidth
     attribute pageXOffset
     attribute pageYOffset
+    attribute paintWorklet
     attribute parent
     attribute performance
     attribute personalbar
     attribute propertyNamesInGlobal
-    attribute renderWorklet
     attribute screen
     attribute screenLeft
     attribute screenTop
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_utilities.py b/third_party/WebKit/Source/bindings/scripts/v8_utilities.py
index 7a54d49..cb167a69 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_utilities.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_utilities.py
@@ -231,6 +231,7 @@
 EXPOSED_EXECUTION_CONTEXT_METHOD = {
     'CompositorWorker': 'isCompositorWorkerGlobalScope',
     'DedicatedWorker': 'isDedicatedWorkerGlobalScope',
+    'PaintWorklet': 'isPaintWorkletGlobalScope',
     'ServiceWorker': 'isServiceWorkerGlobalScope',
     'SharedWorker': 'isSharedWorkerGlobalScope',
     'Window': 'isDocument',
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi
index 749000f..bbcb4931 100644
--- a/third_party/WebKit/Source/core/core.gypi
+++ b/third_party/WebKit/Source/core/core.gypi
@@ -527,6 +527,7 @@
             'layout/api/LineLayoutItem.h',
             'layout/api/LineLayoutListMarker.h',
             'layout/api/LineLayoutRubyRun.h',
+            'layout/api/LineLayoutRubyText.h',
             'layout/api/LineLayoutSVGInline.h',
             'layout/api/LineLayoutSVGInlineText.h',
             'layout/api/LineLayoutSVGTextPath.h',
diff --git a/third_party/WebKit/Source/core/css/CSSRule.cpp b/third_party/WebKit/Source/core/css/CSSRule.cpp
index 3bd73b4b..25a78dac 100644
--- a/third_party/WebKit/Source/core/css/CSSRule.cpp
+++ b/third_party/WebKit/Source/core/css/CSSRule.cpp
@@ -24,7 +24,6 @@
 #include "core/css/CSSStyleSheet.h"
 #include "core/css/StyleRule.h"
 #include "core/css/StyleSheetContents.h"
-#include "platform/NotImplemented.h"
 
 namespace blink {
 
@@ -36,11 +35,6 @@
 
 static_assert(sizeof(CSSRule) == sizeof(SameSizeAsCSSRule), "CSSRule should stay small");
 
-void CSSRule::setCSSText(const String&)
-{
-    notImplemented();
-}
-
 const CSSParserContext& CSSRule::parserContext() const
 {
     CSSStyleSheet* styleSheet = parentStyleSheet();
diff --git a/third_party/WebKit/Source/core/css/CSSRule.h b/third_party/WebKit/Source/core/css/CSSRule.h
index e5b85e9..8b15c31 100644
--- a/third_party/WebKit/Source/core/css/CSSRule.h
+++ b/third_party/WebKit/Source/core/css/CSSRule.h
@@ -85,8 +85,8 @@
 
     CSSRule* parentRule() const { return m_parentIsRule ? m_parentRule : nullptr; }
 
-    // NOTE: Just calls notImplemented().
-    void setCSSText(const String&);
+    // The CSSOM spec states that "setting the cssText attribute must do nothing."
+    void setCSSText(const String&) { }
 
 protected:
     CSSRule(CSSStyleSheet* parent)
diff --git a/third_party/WebKit/Source/core/css/CSSValuePool.cpp b/third_party/WebKit/Source/core/css/CSSValuePool.cpp
index 3babf7f7..8d7b22f 100644
--- a/third_party/WebKit/Source/core/css/CSSValuePool.cpp
+++ b/third_party/WebKit/Source/core/css/CSSValuePool.cpp
@@ -128,6 +128,8 @@
 
 PassRefPtrWillBeRawPtr<CSSFontFamilyValue> CSSValuePool::createFontFamilyValue(const String& familyName)
 {
+    if (familyName.isNull())
+        return CSSFontFamilyValue::create(familyName);
     RefPtrWillBeMember<CSSFontFamilyValue>& value = m_fontFamilyValueCache.add(familyName, nullptr).storedValue->value;
     if (!value)
         value = CSSFontFamilyValue::create(familyName);
diff --git a/third_party/WebKit/Source/core/css/MediaValues.cpp b/third_party/WebKit/Source/core/css/MediaValues.cpp
index aeb7f69..f7393f8 100644
--- a/third_party/WebKit/Source/core/css/MediaValues.cpp
+++ b/third_party/WebKit/Source/core/css/MediaValues.cpp
@@ -15,7 +15,7 @@
 #include "core/frame/Settings.h"
 #include "core/html/imports/HTMLImportsController.h"
 #include "core/layout/LayoutObject.h"
-#include "core/layout/LayoutView.h"
+#include "core/layout/api/LayoutViewItem.h"
 #include "core/layout/compositing/PaintLayerCompositor.h"
 #include "core/page/ChromeClient.h"
 #include "core/page/Page.h"
@@ -121,10 +121,10 @@
 
 bool MediaValues::calculateThreeDEnabled(LocalFrame* frame)
 {
-    ASSERT(frame && frame->contentLayoutObject() && frame->contentLayoutObject()->compositor());
+    ASSERT(frame && frame->contentLayoutObject() && LayoutViewItem(frame->contentLayoutObject()).compositor());
     bool threeDEnabled = false;
-    if (LayoutView* view = frame->contentLayoutObject())
-        threeDEnabled = view->compositor()->hasAcceleratedCompositing();
+    if (LayoutViewItem view = LayoutViewItem(frame->contentLayoutObject()))
+        threeDEnabled = view.compositor()->hasAcceleratedCompositing();
     return threeDEnabled;
 }
 
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index 030266cf..c0049bd 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -3063,6 +3063,45 @@
     return values.release();
 }
 
+static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeGridBreadth(CSSParserTokenRange& range, CSSParserMode cssParserMode, TrackSizeRestriction restriction = AllowAll)
+{
+    if (restriction == AllowAll) {
+        const CSSParserToken& token = range.peek();
+        if (identMatches<CSSValueMinContent, CSSValueMaxContent, CSSValueAuto>(token.id()))
+            return consumeIdent(range);
+        if (token.type() == DimensionToken && token.unitType() == CSSPrimitiveValue::UnitType::Fraction) {
+            if (range.peek().numericValue() < 0)
+                return nullptr;
+            return cssValuePool().createValue(range.consumeIncludingWhitespace().numericValue(), CSSPrimitiveValue::UnitType::Fraction);
+        }
+    }
+    return consumeLengthOrPercent(range, cssParserMode, ValueRangeNonNegative, UnitlessQuirk::Allow);
+}
+
+static PassRefPtrWillBeRawPtr<CSSValue> consumeGridTrackSize(CSSParserTokenRange& range, CSSParserMode cssParserMode, TrackSizeRestriction restriction = AllowAll)
+{
+    const CSSParserToken& token = range.peek();
+    if (restriction == AllowAll && identMatches<CSSValueAuto>(token.id()))
+        return consumeIdent(range);
+
+    if (token.functionId() == CSSValueMinmax) {
+        CSSParserTokenRange rangeCopy = range;
+        CSSParserTokenRange args = consumeFunction(rangeCopy);
+        RefPtrWillBeRawPtr<CSSPrimitiveValue> minTrackBreadth = consumeGridBreadth(args, cssParserMode, restriction);
+        if (!minTrackBreadth || !consumeCommaIncludingWhitespace(args))
+            return nullptr;
+        RefPtrWillBeRawPtr<CSSPrimitiveValue> maxTrackBreadth = consumeGridBreadth(args, cssParserMode);
+        if (!maxTrackBreadth || !args.atEnd())
+            return nullptr;
+        range = rangeCopy;
+        RefPtrWillBeRawPtr<CSSFunctionValue> result = CSSFunctionValue::create(CSSValueMinmax);
+        result->append(minTrackBreadth.release());
+        result->append(maxTrackBreadth.release());
+        return result.release();
+    }
+    return consumeGridBreadth(range, cssParserMode, restriction);
+}
+
 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSPropertyID unresolvedProperty)
 {
     CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty);
@@ -3431,6 +3470,10 @@
     case CSSPropertyGridRowStart:
         ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
         return consumeGridLine(m_range);
+    case CSSPropertyGridAutoColumns:
+    case CSSPropertyGridAutoRows:
+        ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
+        return consumeGridTrackSize(m_range, m_context.mode());
     default:
         CSSParserValueList valueList(m_range);
         if (valueList.size()) {
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
index 7abc6ca2..f8dc56b7 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
@@ -43,6 +43,9 @@
 class CSSValueList;
 class StylePropertyShorthand;
 
+// TODO(rob.buis) to move to cpp file once legacy parser is removed.
+enum TrackSizeRestriction { FixedSizeOnly, AllowAll };
+
 // Inputs: PropertyID, isImportant bool, CSSParserValueList.
 // Outputs: Vector of CSSProperties
 
@@ -112,7 +115,6 @@
 
     bool consumeColumns(bool important);
 
-    enum TrackSizeRestriction { FixedSizeOnly, AllowAll };
     bool consumeGridItemPositionShorthand(CSSPropertyID, bool important);
     PassRefPtrWillBeRawPtr<CSSValue> parseGridTemplateColumns(bool important);
     bool parseGridTemplateRowsAndAreasAndColumns(bool important);
diff --git a/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp
index 60e82cc1..4745767 100644
--- a/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp
@@ -264,11 +264,6 @@
         ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
         parsedValue = parseGridAutoFlow(*m_valueList);
         break;
-    case CSSPropertyGridAutoColumns:
-    case CSSPropertyGridAutoRows:
-        ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
-        parsedValue = parseGridTrackSize(*m_valueList);
-        break;
 
     case CSSPropertyGridTemplateColumns:
     case CSSPropertyGridTemplateRows:
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index e94d3c0..0787418b 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -468,8 +468,7 @@
         m_fetcher = m_frame->loader().documentLoader()->fetcher();
         FrameFetchContext::provideDocumentToContext(m_fetcher->context(), this);
     } else if (m_importsController) {
-        m_fetcher = FrameFetchContext::createContextAndFetcher(nullptr);
-        FrameFetchContext::provideDocumentToContext(m_fetcher->context(), this);
+        m_fetcher = FrameFetchContext::createContextAndFetcher(nullptr, this);
     } else {
         m_fetcher = ResourceFetcher::create(nullptr);
     }
diff --git a/third_party/WebKit/Source/core/dom/ExecutionContext.h b/third_party/WebKit/Source/core/dom/ExecutionContext.h
index 9932d1dc..b41e9b9 100644
--- a/third_party/WebKit/Source/core/dom/ExecutionContext.h
+++ b/third_party/WebKit/Source/core/dom/ExecutionContext.h
@@ -79,6 +79,7 @@
     virtual bool isSharedWorkerGlobalScope() const { return false; }
     virtual bool isServiceWorkerGlobalScope() const { return false; }
     virtual bool isCompositorWorkerGlobalScope() const { return false; }
+    virtual bool isPaintWorkletGlobalScope() const { return false; }
     virtual bool isJSExecutionForbidden() const { return false; }
 
     virtual bool isContextThread() const { return true; }
diff --git a/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.cpp b/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.cpp
index 015d0f3..5f1bf13 100644
--- a/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.cpp
@@ -46,11 +46,11 @@
 
 PassRefPtrWillBeRawPtr<CSSStyleSheetResource> CSSStyleSheetResource::createForTest(const ResourceRequest& request, const String& charset)
 {
-    return adoptRefWillBeNoop(new CSSStyleSheetResource(request, charset));
+    return adoptRefWillBeNoop(new CSSStyleSheetResource(request, ResourceLoaderOptions(), charset));
 }
 
-CSSStyleSheetResource::CSSStyleSheetResource(const ResourceRequest& resourceRequest, const String& charset)
-    : StyleSheetResource(resourceRequest, CSSStyleSheet, "text/css", charset)
+CSSStyleSheetResource::CSSStyleSheetResource(const ResourceRequest& resourceRequest, const ResourceLoaderOptions& options, const String& charset)
+    : StyleSheetResource(resourceRequest, CSSStyleSheet, options, "text/css", charset)
 {
     DEFINE_STATIC_LOCAL(const AtomicString, acceptCSS, ("text/css,*/*;q=0.1", AtomicString::ConstructFromLiteral));
 
diff --git a/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.h b/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.h
index 9310f4d..e887fcfef 100644
--- a/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.h
+++ b/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.h
@@ -66,12 +66,12 @@
         CSSStyleSheetResourceFactory()
             : ResourceFactory(Resource::CSSStyleSheet) { }
 
-        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const String& charset) const override
+        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const ResourceLoaderOptions& options, const String& charset) const override
         {
-            return adoptRefWillBeNoop(new CSSStyleSheetResource(request, charset));
+            return adoptRefWillBeNoop(new CSSStyleSheetResource(request, options, charset));
         }
     };
-    CSSStyleSheetResource(const ResourceRequest&, const String& charset);
+    CSSStyleSheetResource(const ResourceRequest&, const ResourceLoaderOptions&, const String& charset);
 
     bool canUseSheet(MIMETypeCheck) const;
     void removedFromMemoryCache() override;
diff --git a/third_party/WebKit/Source/core/fetch/DocumentResource.cpp b/third_party/WebKit/Source/core/fetch/DocumentResource.cpp
index 191fa6e..d37c7c9 100644
--- a/third_party/WebKit/Source/core/fetch/DocumentResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/DocumentResource.cpp
@@ -37,8 +37,8 @@
     return toDocumentResource(fetcher->requestResource(request, SVGDocumentResourceFactory()));
 }
 
-DocumentResource::DocumentResource(const ResourceRequest& request, Type type)
-    : Resource(request, type)
+DocumentResource::DocumentResource(const ResourceRequest& request, Type type, const ResourceLoaderOptions& options)
+    : Resource(request, type, options)
     , m_decoder(TextResourceDecoder::create("application/xml"))
 {
     // FIXME: We'll support more types to support HTMLImports.
diff --git a/third_party/WebKit/Source/core/fetch/DocumentResource.h b/third_party/WebKit/Source/core/fetch/DocumentResource.h
index 44d0cec3..e4315e5 100644
--- a/third_party/WebKit/Source/core/fetch/DocumentResource.h
+++ b/third_party/WebKit/Source/core/fetch/DocumentResource.h
@@ -53,12 +53,12 @@
         SVGDocumentResourceFactory()
             : ResourceFactory(Resource::SVGDocument) { }
 
-        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const String& charset) const override
+        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const ResourceLoaderOptions& options, const String& charset) const override
         {
-            return adoptRefWillBeNoop(new DocumentResource(request, Resource::SVGDocument));
+            return adoptRefWillBeNoop(new DocumentResource(request, Resource::SVGDocument, options));
         }
     };
-    DocumentResource(const ResourceRequest&, Type);
+    DocumentResource(const ResourceRequest&, Type, const ResourceLoaderOptions&);
 
     bool mimeTypeAllowed() const;
     PassRefPtrWillBeRawPtr<Document> createDocument(const KURL&);
diff --git a/third_party/WebKit/Source/core/fetch/FontResource.cpp b/third_party/WebKit/Source/core/fetch/FontResource.cpp
index 51d6faa..7610e63 100644
--- a/third_party/WebKit/Source/core/fetch/FontResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/FontResource.cpp
@@ -77,8 +77,8 @@
     return toFontResource(fetcher->requestResource(request, FontResourceFactory()));
 }
 
-FontResource::FontResource(const ResourceRequest& resourceRequest)
-    : Resource(resourceRequest, Font)
+FontResource::FontResource(const ResourceRequest& resourceRequest, const ResourceLoaderOptions& options)
+    : Resource(resourceRequest, Font, options)
     , m_state(Unloaded)
     , m_corsFailed(false)
     , m_fontLoadShortLimitTimer(this, &FontResource::fontLoadShortLimitCallback)
@@ -102,11 +102,10 @@
         m_state = Unloaded;
 }
 
-void FontResource::load(ResourceFetcher*, const ResourceLoaderOptions& options)
+void FontResource::load(ResourceFetcher*)
 {
     // Don't load the file yet. Wait for an access before triggering the load.
     setLoading(true);
-    m_options = options;
     if (!m_revalidatingRequest.isNull())
         m_state = Unloaded;
 }
@@ -127,7 +126,7 @@
 {
     if (stillNeedsLoad()) {
         m_state = LoadInitiated;
-        Resource::load(dl, m_options);
+        Resource::load(dl);
         m_fontLoadShortLimitTimer.startOneShot(fontLoadWaitShortLimitSec, BLINK_FROM_HERE);
         m_fontLoadLongLimitTimer.startOneShot(fontLoadWaitLongLimitSec, BLINK_FROM_HERE);
 
diff --git a/third_party/WebKit/Source/core/fetch/FontResource.h b/third_party/WebKit/Source/core/fetch/FontResource.h
index aa92d49..9fa27cb 100644
--- a/third_party/WebKit/Source/core/fetch/FontResource.h
+++ b/third_party/WebKit/Source/core/fetch/FontResource.h
@@ -47,7 +47,7 @@
     static PassRefPtrWillBeRawPtr<FontResource> fetch(FetchRequest&, ResourceFetcher*);
     ~FontResource() override;
 
-    void load(ResourceFetcher*, const ResourceLoaderOptions&) override;
+    void load(ResourceFetcher*) override;
 
     void didAddClient(ResourceClient*) override;
 
@@ -75,12 +75,12 @@
         FontResourceFactory()
             : ResourceFactory(Resource::Font) { }
 
-        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const String& charset) const override
+        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const ResourceLoaderOptions& options, const String& charset) const override
         {
-            return adoptRefWillBeNoop(new FontResource(request));
+            return adoptRefWillBeNoop(new FontResource(request, options));
         }
     };
-    FontResource(const ResourceRequest&);
+    FontResource(const ResourceRequest&, const ResourceLoaderOptions&);
 
     void checkNotify() override;
     void fontLoadShortLimitCallback(Timer<FontResource>*);
diff --git a/third_party/WebKit/Source/core/fetch/ImageResource.cpp b/third_party/WebKit/Source/core/fetch/ImageResource.cpp
index 8e2c9bd..499d5843 100644
--- a/third_party/WebKit/Source/core/fetch/ImageResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/ImageResource.cpp
@@ -58,8 +58,8 @@
     return toImageResource(fetcher->requestResource(request, ImageResourceFactory()));
 }
 
-ImageResource::ImageResource(const ResourceRequest& resourceRequest)
-    : Resource(resourceRequest, Image)
+ImageResource::ImageResource(const ResourceRequest& resourceRequest, const ResourceLoaderOptions& options)
+    : Resource(resourceRequest, Image, options)
     , m_devicePixelRatioHeaderValue(1.0)
     , m_image(nullptr)
     , m_hasDevicePixelRatioHeaderValue(false)
@@ -69,8 +69,8 @@
     setCustomAcceptHeader();
 }
 
-ImageResource::ImageResource(blink::Image* image)
-    : Resource(ResourceRequest(""), Image)
+ImageResource::ImageResource(blink::Image* image, const ResourceLoaderOptions& options)
+    : Resource(ResourceRequest(""), Image, options)
     , m_devicePixelRatioHeaderValue(1.0)
     , m_image(image)
     , m_hasDevicePixelRatioHeaderValue(false)
@@ -81,8 +81,8 @@
     setCustomAcceptHeader();
 }
 
-ImageResource::ImageResource(const ResourceRequest& resourceRequest, blink::Image* image)
-    : Resource(resourceRequest, Image)
+ImageResource::ImageResource(const ResourceRequest& resourceRequest, blink::Image* image, const ResourceLoaderOptions& options)
+    : Resource(resourceRequest, Image, options)
     , m_image(image)
 {
     WTF_LOG(Timers, "new ImageResource(ResourceRequest, Image) %p", this);
@@ -105,10 +105,11 @@
     MultipartImageResourceParser::Client::trace(visitor);
 }
 
-void ImageResource::load(ResourceFetcher* fetcher, const ResourceLoaderOptions& options)
+void ImageResource::load(ResourceFetcher* fetcher)
 {
-    if (!fetcher || fetcher->autoLoadImages())
-        Resource::load(fetcher, options);
+    ASSERT(fetcher);
+    if (fetcher->autoLoadImages())
+        Resource::load(fetcher);
     else
         setLoading(false);
 }
@@ -455,7 +456,7 @@
     m_resourceRequest.setCachePolicy(ResourceRequestCachePolicy::ReloadBypassingCache);
     m_resourceRequest.setLoFiState(WebURLRequest::LoFiOff);
     error(Resource::LoadError);
-    load(fetcher, fetcher->defaultResourceOptions());
+    load(fetcher);
 }
 
 void ImageResource::changedInRect(const blink::Image* image, const IntRect& rect)
diff --git a/third_party/WebKit/Source/core/fetch/ImageResource.h b/third_party/WebKit/Source/core/fetch/ImageResource.h
index f5c4d9a..d4b92c4 100644
--- a/third_party/WebKit/Source/core/fetch/ImageResource.h
+++ b/third_party/WebKit/Source/core/fetch/ImageResource.h
@@ -53,18 +53,18 @@
 
     static PassRefPtrWillBeRawPtr<ImageResource> create(blink::Image* image)
     {
-        return adoptRefWillBeNoop(new ImageResource(image));
+        return adoptRefWillBeNoop(new ImageResource(image, ResourceLoaderOptions()));
     }
 
     // Exposed for testing
     static PassRefPtrWillBeRawPtr<ImageResource> create(const ResourceRequest& request, blink::Image* image)
     {
-        return adoptRefWillBeNoop(new ImageResource(request, image));
+        return adoptRefWillBeNoop(new ImageResource(request, image, ResourceLoaderOptions()));
     }
 
     ~ImageResource() override;
 
-    void load(ResourceFetcher*, const ResourceLoaderOptions&) override;
+    void load(ResourceFetcher*) override;
 
     blink::Image* getImage(); // Returns the nullImage() if the image is not available yet.
     bool hasImage() const { return m_image.get(); }
@@ -129,8 +129,8 @@
     void destroyDecodedDataForFailedRevalidation() override;
 
 private:
-    explicit ImageResource(blink::Image*);
-    ImageResource(const ResourceRequest&, blink::Image*);
+    explicit ImageResource(blink::Image*, const ResourceLoaderOptions&);
+    ImageResource(const ResourceRequest&, blink::Image*, const ResourceLoaderOptions&);
 
     enum class MultipartParsingState : uint8_t {
         WaitingForFirstPart,
@@ -143,12 +143,12 @@
         ImageResourceFactory()
             : ResourceFactory(Resource::Image) { }
 
-        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const String&) const override
+        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const ResourceLoaderOptions& options, const String&) const override
         {
-            return adoptRefWillBeNoop(new ImageResource(request));
+            return adoptRefWillBeNoop(new ImageResource(request, options));
         }
     };
-    ImageResource(const ResourceRequest&);
+    ImageResource(const ResourceRequest&, const ResourceLoaderOptions&);
 
     void clear();
 
diff --git a/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp b/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp
index 236650a..aa4596d 100644
--- a/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp
+++ b/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp
@@ -90,7 +90,7 @@
     // Emulate starting a real load, but don't expect any "real" WebURLLoaderClient callbacks.
     RefPtrWillBeRawPtr<ImageResource> cachedImage = ImageResource::create(ResourceRequest(testURL), nullptr);
     cachedImage->setIdentifier(createUniqueIdentifier());
-    cachedImage->load(fetcher, ResourceLoaderOptions());
+    cachedImage->load(fetcher);
     Platform::current()->unitTestSupport()->unregisterMockedURL(testURL);
 
     MockImageResourceClient client(cachedImage);
@@ -151,7 +151,7 @@
     RefPtrWillBeRawPtr<ImageResource> cachedImage = ImageResource::create(ResourceRequest(testURL), nullptr);
     cachedImage->setIdentifier(createUniqueIdentifier());
 
-    cachedImage->load(fetcher, ResourceLoaderOptions());
+    cachedImage->load(fetcher);
     memoryCache()->add(cachedImage.get());
 
     MockImageResourceClient client(cachedImage);
diff --git a/third_party/WebKit/Source/core/fetch/LinkFetchResource.cpp b/third_party/WebKit/Source/core/fetch/LinkFetchResource.cpp
index 2c92ed8..bc4a2af0 100644
--- a/third_party/WebKit/Source/core/fetch/LinkFetchResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/LinkFetchResource.cpp
@@ -18,8 +18,8 @@
     return fetcher->requestResource(request, LinkResourceFactory(type));
 }
 
-LinkFetchResource::LinkFetchResource(const ResourceRequest& request, Type type)
-    : Resource(request, type)
+LinkFetchResource::LinkFetchResource(const ResourceRequest& request, Type type, const ResourceLoaderOptions& options)
+    : Resource(request, type, options)
 {
 }
 
diff --git a/third_party/WebKit/Source/core/fetch/LinkFetchResource.h b/third_party/WebKit/Source/core/fetch/LinkFetchResource.h
index 62d7131..84d16fb 100644
--- a/third_party/WebKit/Source/core/fetch/LinkFetchResource.h
+++ b/third_party/WebKit/Source/core/fetch/LinkFetchResource.h
@@ -27,12 +27,12 @@
         LinkResourceFactory(Resource::Type type)
             : ResourceFactory(type) { }
 
-        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const String& charset) const override
+        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const ResourceLoaderOptions& options, const String& charset) const override
         {
-            return adoptRefWillBeNoop(new LinkFetchResource(request, type()));
+            return adoptRefWillBeNoop(new LinkFetchResource(request, type(), options));
         }
     };
-    LinkFetchResource(const ResourceRequest&, Type);
+    LinkFetchResource(const ResourceRequest&, Type, const ResourceLoaderOptions&);
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/fetch/MemoryCacheTest.cpp b/third_party/WebKit/Source/core/fetch/MemoryCacheTest.cpp
index 07a61977..d02cf52 100644
--- a/third_party/WebKit/Source/core/fetch/MemoryCacheTest.cpp
+++ b/third_party/WebKit/Source/core/fetch/MemoryCacheTest.cpp
@@ -46,7 +46,7 @@
     public:
         static RefPtrWillBeRawPtr<FakeDecodedResource> create(const ResourceRequest& request, Type type)
         {
-            return adoptRefWillBeNoop(new FakeDecodedResource(request, type));
+            return adoptRefWillBeNoop(new FakeDecodedResource(request, type, ResourceLoaderOptions()));
         }
 
         virtual void appendData(const char* data, size_t len)
@@ -56,8 +56,8 @@
         }
 
     protected:
-        FakeDecodedResource(const ResourceRequest& request, Type type)
-            : Resource(request, type)
+        FakeDecodedResource(const ResourceRequest& request, Type type, const ResourceLoaderOptions& options)
+            : Resource(request, type, options)
         {
         }
 
@@ -71,7 +71,7 @@
     public:
         static RefPtrWillBeRawPtr<FakeResource> create(const ResourceRequest& request, Type type)
         {
-            return adoptRefWillBeNoop(new FakeResource(request, type));
+            return adoptRefWillBeNoop(new FakeResource(request, type, ResourceLoaderOptions()));
         }
 
         void fakeEncodedSize(size_t size)
@@ -80,8 +80,8 @@
         }
 
     private:
-        FakeResource(const ResourceRequest& request, Type type)
-            : Resource(request, type)
+        FakeResource(const ResourceRequest& request, Type type, const ResourceLoaderOptions& options)
+            : Resource(request, type, options)
         {
         }
     };
diff --git a/third_party/WebKit/Source/core/fetch/RawResource.cpp b/third_party/WebKit/Source/core/fetch/RawResource.cpp
index 278fda7..fb1f585 100644
--- a/third_party/WebKit/Source/core/fetch/RawResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/RawResource.cpp
@@ -85,8 +85,8 @@
     return toRawResource(fetcher->requestResource(request, RawResourceFactory(Resource::Manifest)));
 }
 
-RawResource::RawResource(const ResourceRequest& resourceRequest, Type type)
-    : Resource(resourceRequest, type)
+RawResource::RawResource(const ResourceRequest& resourceRequest, Type type, const ResourceLoaderOptions& options)
+    : Resource(resourceRequest, type, options)
 {
 }
 
diff --git a/third_party/WebKit/Source/core/fetch/RawResource.h b/third_party/WebKit/Source/core/fetch/RawResource.h
index 0054cff..eb19b90 100644
--- a/third_party/WebKit/Source/core/fetch/RawResource.h
+++ b/third_party/WebKit/Source/core/fetch/RawResource.h
@@ -50,7 +50,7 @@
     // Exposed for testing
     static RefPtrWillBeRawPtr<RawResource> create(const ResourceRequest& request, Type type)
     {
-        return adoptRefWillBeNoop(new RawResource(request, type));
+        return adoptRefWillBeNoop(new RawResource(request, type, ResourceLoaderOptions()));
     }
 
     // FIXME: AssociatedURLLoader shouldn't be a DocumentThreadableLoader and therefore shouldn't
@@ -66,13 +66,13 @@
         RawResourceFactory(Resource::Type type)
             : ResourceFactory(type) { }
 
-        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const String& charset) const override
+        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const ResourceLoaderOptions& options, const String& charset) const override
         {
-            return adoptRefWillBeNoop(new RawResource(request, m_type));
+            return adoptRefWillBeNoop(new RawResource(request, m_type, options));
         }
     };
 
-    RawResource(const ResourceRequest&, Type);
+    RawResource(const ResourceRequest&, Type, const ResourceLoaderOptions&);
 
     void didAddClient(ResourceClient*) override;
     void appendData(const char*, size_t) override;
diff --git a/third_party/WebKit/Source/core/fetch/Resource.cpp b/third_party/WebKit/Source/core/fetch/Resource.cpp
index e97b8d34..84635b3 100644
--- a/third_party/WebKit/Source/core/fetch/Resource.cpp
+++ b/third_party/WebKit/Source/core/fetch/Resource.cpp
@@ -144,8 +144,9 @@
     return m_resource->encoding();
 }
 
-Resource::Resource(const ResourceRequest& request, Type type)
+Resource::Resource(const ResourceRequest& request, Type type, const ResourceLoaderOptions& options)
     : m_resourceRequest(request)
+    , m_options(options)
     , m_responseTimestamp(currentTime())
     , m_cancelTimer(this, &Resource::cancelTimerFired)
 #if !ENABLE(OILPAN)
@@ -199,10 +200,9 @@
 #endif
 }
 
-void Resource::load(ResourceFetcher* fetcher, const ResourceLoaderOptions& options)
+void Resource::load(ResourceFetcher* fetcher)
 {
     RELEASE_ASSERT(!m_loader);
-    m_options = options;
     m_loading = true;
     m_status = Pending;
 
diff --git a/third_party/WebKit/Source/core/fetch/Resource.h b/third_party/WebKit/Source/core/fetch/Resource.h
index de7f4d7..e5513fd 100644
--- a/third_party/WebKit/Source/core/fetch/Resource.h
+++ b/third_party/WebKit/Source/core/fetch/Resource.h
@@ -85,16 +85,16 @@
     };
 
     // Exposed for testing.
-    static PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, Type type)
+    static PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, Type type, const ResourceLoaderOptions& options = ResourceLoaderOptions())
     {
-        return adoptRefWillBeNoop(new Resource(request, type));
+        return adoptRefWillBeNoop(new Resource(request, type, options));
     }
     virtual ~Resource();
 
     virtual void removedFromMemoryCache();
     DECLARE_VIRTUAL_TRACE();
 
-    virtual void load(ResourceFetcher*, const ResourceLoaderOptions&);
+    virtual void load(ResourceFetcher*);
 
     virtual void setEncoding(const String&) { }
     virtual String encoding() const { return String(); }
@@ -124,7 +124,6 @@
     Type getType() const { return static_cast<Type>(m_type); }
     const ResourceLoaderOptions& options() const { return m_options; }
     ResourceLoaderOptions& mutableOptions() { return m_options; }
-    void setOptions(const ResourceLoaderOptions& options) { m_options = options; }
 
     void didChangePriority(ResourceLoadPriority, int intraPriorityValue);
     ResourcePriority priorityFromClients();
@@ -255,7 +254,7 @@
     WeakPtrWillBeRawPtr<Resource> asWeakPtr();
 
 protected:
-    Resource(const ResourceRequest&, Type);
+    Resource(const ResourceRequest&, Type, const ResourceLoaderOptions&);
 
     virtual void checkNotify();
 
@@ -373,7 +372,7 @@
 class ResourceFactory {
     STACK_ALLOCATED();
 public:
-    virtual PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest&, const String&) const = 0;
+    virtual PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest&, const ResourceLoaderOptions&, const String&) const = 0;
     Resource::Type type() const { return m_type; }
 
 protected:
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
index 515a577..a19aca0 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
@@ -194,8 +194,9 @@
     return WebURLRequest::RequestContextSubresource;
 }
 
-ResourceFetcher::ResourceFetcher(FetchContext* context)
-    : m_context(context)
+ResourceFetcher::ResourceFetcher(FetchContext* newContext)
+    : m_context(newContext)
+    , m_archive(context().isMainFrame() ? nullptr : context().archive())
     , m_resourceTimingReportTimer(this, &ResourceFetcher::resourceTimingReportTimerFired)
     , m_autoLoadImages(true)
     , m_imagesEnabled(true)
@@ -302,13 +303,13 @@
 PassRefPtrWillBeRawPtr<Resource> ResourceFetcher::resourceForStaticData(const FetchRequest& request, const ResourceFactory& factory, const SubstituteData& substituteData)
 {
     const KURL& url = request.resourceRequest().url();
-    ASSERT(url.protocolIsData() || substituteData.isValid());
+    ASSERT(url.protocolIsData() || substituteData.isValid() || m_archive);
 
     // TODO(japhet): We only send main resource data: urls through WebURLLoader for the benefit of
     // a service worker test (RenderViewImplTest.ServiceWorkerNetworkProviderSetup), which is at a
     // layer where it isn't easy to mock out a network load. It uses data: urls to emulate the
     // behavior it wants to test, which would otherwise be reserved for network loads.
-    if ((factory.type() == Resource::MainResource && !substituteData.isValid()) || factory.type() == Resource::Raw)
+    if (!m_archive && !substituteData.isValid() && (factory.type() == Resource::MainResource || factory.type() == Resource::Raw))
         return nullptr;
 
     const String cacheIdentifier = getCacheIdentifier();
@@ -326,18 +327,26 @@
         mimetype = substituteData.mimeType();
         charset = substituteData.textEncoding();
         data = substituteData.content();
-    } else {
+    } else if (url.protocolIsData()) {
         data = PassRefPtr<SharedBuffer>(Platform::current()->parseDataURL(url, mimetype, charset));
         if (!data)
             return nullptr;
+    } else {
+        ArchiveResource* archiveResource = m_archive->subresourceForURL(request.url());
+        // Fall back to the network if the archive doesn't contain the resource.
+        if (!archiveResource)
+            return nullptr;
+        mimetype = archiveResource->mimeType();
+        charset = archiveResource->textEncoding();
+        data = archiveResource->data();
     }
+
     ResourceResponse response(url, mimetype, data->size(), charset, String());
     response.setHTTPStatusCode(200);
     response.setHTTPStatusText("OK");
 
-    RefPtrWillBeRawPtr<Resource> resource = factory.create(request.resourceRequest(), request.charset());
+    RefPtrWillBeRawPtr<Resource> resource = factory.create(request.resourceRequest(), request.options(), request.charset());
     resource->setNeedsSynchronousCacheHit(substituteData.forceSynchronousLoad());
-    resource->setOptions(request.options());
     // FIXME: We should provide a body stream here.
     resource->responseReceived(response, nullptr);
     resource->setDataBufferingPolicy(BufferData);
@@ -422,7 +431,7 @@
         }
     }
 
-    bool isStaticData = request.resourceRequest().url().protocolIsData() || substituteData.isValid();
+    bool isStaticData = request.resourceRequest().url().protocolIsData() || substituteData.isValid() || m_archive;
     RefPtrWillBeRawPtr<Resource> resource(nullptr);
     if (isStaticData)
         resource = resourceForStaticData(request, factory, substituteData);
@@ -483,8 +492,7 @@
             return nullptr;
         }
 
-        if (!scheduleArchiveLoad(resource.get(), request.resourceRequest()))
-            resource->load(this, request.options());
+        resource->load(this);
 
         // For asynchronous loads that immediately fail, it's sufficient to return a
         // null Resource, as it indicates that something prevented the load from starting.
@@ -589,7 +597,7 @@
 
     WTF_LOG(ResourceLoading, "Loading Resource for '%s'.", request.resourceRequest().url().elidedString().latin1().data());
 
-    RefPtrWillBeRawPtr<Resource> resource = factory.create(request.resourceRequest(), charset);
+    RefPtrWillBeRawPtr<Resource> resource = factory.create(request.resourceRequest(), request.options(), charset);
     resource->setLinkPreload(request.isLinkPreload());
     resource->setCacheIdentifier(cacheIdentifier);
 
@@ -834,7 +842,7 @@
     for (const auto& documentResource : m_documentResources) {
         Resource* resource = documentResource.value.get();
         if (resource && resource->getType() == Resource::Image && resource->stillNeedsLoad() && !clientDefersImage(resource->url()))
-            const_cast<Resource*>(resource)->load(this, defaultResourceOptions());
+            const_cast<Resource*>(resource)->load(this);
     }
 }
 
@@ -901,29 +909,6 @@
     return m_archive ? m_archive->mainResource() : nullptr;
 }
 
-bool ResourceFetcher::scheduleArchiveLoad(Resource* resource, const ResourceRequest& request)
-{
-    if (resource->getType() == Resource::MainResource && !context().isMainFrame())
-        m_archive = context().archive();
-
-    if (!m_archive)
-        return false;
-
-    ArchiveResource* archiveResource = m_archive->subresourceForURL(request.url());
-    if (!archiveResource) {
-        resource->error(Resource::LoadError);
-        return false;
-    }
-
-    resource->setLoading(true);
-    resource->responseReceived(archiveResource->response(), nullptr);
-    SharedBuffer* data = archiveResource->data();
-    if (data)
-        resource->appendData(data->data(), data->size());
-    resource->finish();
-    return true;
-}
-
 void ResourceFetcher::didFinishLoading(Resource* resource, double finishTime, int64_t encodedDataLength)
 {
     TRACE_EVENT_ASYNC_END0("blink.net", "Resource", resource);
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
index bbc3730..54d0f8b 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
@@ -160,7 +160,6 @@
     void initializeRevalidation(const FetchRequest&, Resource*);
     PassRefPtrWillBeRawPtr<Resource> createResourceForLoading(FetchRequest&, const String& charset, const ResourceFactory&);
     void storeResourceTimingInitiatorInformation(Resource*);
-    bool scheduleArchiveLoad(Resource*, const ResourceRequest&);
 
     PassRefPtrWillBeRawPtr<Resource> resourceForStaticData(const FetchRequest&, const ResourceFactory&, const SubstituteData&);
 
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcherTest.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcherTest.cpp
index f85a42e..da6ee3c 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcherTest.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcherTest.cpp
@@ -80,9 +80,9 @@
     TestResourceFactory(Resource::Type type = Resource::Raw)
         : ResourceFactory(type) { }
 
-    PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const String& charset) const override
+    PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const ResourceLoaderOptions& options, const String& charset) const override
     {
-        return Resource::create(request, type());
+        return Resource::create(request, type(), options);
     }
 };
 
diff --git a/third_party/WebKit/Source/core/fetch/ResourceTest.cpp b/third_party/WebKit/Source/core/fetch/ResourceTest.cpp
index a91cc38..b25bb3a 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceTest.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResourceTest.cpp
@@ -27,7 +27,7 @@
 
 private:
     UnlockableResource(const ResourceRequest& request, Type type)
-        : Resource(request, type)
+        : Resource(request, type, ResourceLoaderOptions())
         {
         }
 
diff --git a/third_party/WebKit/Source/core/fetch/ScriptResource.cpp b/third_party/WebKit/Source/core/fetch/ScriptResource.cpp
index 15b6d993..504192d4 100644
--- a/third_party/WebKit/Source/core/fetch/ScriptResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/ScriptResource.cpp
@@ -46,8 +46,9 @@
     return resource.release();
 }
 
-ScriptResource::ScriptResource(const ResourceRequest& resourceRequest, const String& charset)
-    : TextResource(resourceRequest, Script, "application/javascript", charset), m_integrityDisposition(ScriptIntegrityDisposition::NotChecked)
+ScriptResource::ScriptResource(const ResourceRequest& resourceRequest, const ResourceLoaderOptions& options, const String& charset)
+    : TextResource(resourceRequest, Script, options, "application/javascript", charset)
+    , m_integrityDisposition(ScriptIntegrityDisposition::NotChecked)
 {
     DEFINE_STATIC_LOCAL(const AtomicString, acceptScript, ("*/*", AtomicString::ConstructFromLiteral));
 
diff --git a/third_party/WebKit/Source/core/fetch/ScriptResource.h b/third_party/WebKit/Source/core/fetch/ScriptResource.h
index af2d6190..c3c5c3c 100644
--- a/third_party/WebKit/Source/core/fetch/ScriptResource.h
+++ b/third_party/WebKit/Source/core/fetch/ScriptResource.h
@@ -60,7 +60,7 @@
     // Public for testing
     static PassRefPtrWillBeRawPtr<ScriptResource> create(const ResourceRequest& request, const String& charset)
     {
-        return adoptRefWillBeNoop(new ScriptResource(request, charset));
+        return adoptRefWillBeNoop(new ScriptResource(request, ResourceLoaderOptions(), charset));
     }
 
     ~ScriptResource() override;
@@ -89,13 +89,13 @@
         ScriptResourceFactory()
             : ResourceFactory(Resource::Script) { }
 
-        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const String& charset) const override
+        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const ResourceLoaderOptions& options, const String& charset) const override
         {
-            return adoptRefWillBeNoop(new ScriptResource(request, charset));
+            return adoptRefWillBeNoop(new ScriptResource(request, options, charset));
         }
     };
 
-    ScriptResource(const ResourceRequest&, const String& charset);
+    ScriptResource(const ResourceRequest&, const ResourceLoaderOptions&, const String& charset);
 
     ScriptIntegrityDisposition m_integrityDisposition;
     IntegrityMetadataSet m_integrityMetadata;
diff --git a/third_party/WebKit/Source/core/fetch/StyleSheetResource.h b/third_party/WebKit/Source/core/fetch/StyleSheetResource.h
index 7ddb13e..ee35866f 100644
--- a/third_party/WebKit/Source/core/fetch/StyleSheetResource.h
+++ b/third_party/WebKit/Source/core/fetch/StyleSheetResource.h
@@ -42,8 +42,8 @@
 public:
     using ClientType = StyleSheetResourceClient;
 
-    StyleSheetResource(const ResourceRequest& request, Type type, const String& mimeType, const String& charset)
-        : TextResource(request, type, mimeType, charset)
+    StyleSheetResource(const ResourceRequest& request, Type type, const ResourceLoaderOptions& options, const String& mimeType, const String& charset)
+        : TextResource(request, type, options, mimeType, charset)
     { }
 };
 
diff --git a/third_party/WebKit/Source/core/fetch/TextResource.cpp b/third_party/WebKit/Source/core/fetch/TextResource.cpp
index e651c6a..f4878dd3 100644
--- a/third_party/WebKit/Source/core/fetch/TextResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/TextResource.cpp
@@ -10,8 +10,8 @@
 
 namespace blink {
 
-TextResource::TextResource(const ResourceRequest& resourceRequest, Resource::Type type, const String& mimeType, const String& charset)
-    : Resource(resourceRequest, type)
+TextResource::TextResource(const ResourceRequest& resourceRequest, Resource::Type type, const ResourceLoaderOptions& options, const String& mimeType, const String& charset)
+    : Resource(resourceRequest, type, options)
     , m_decoder(TextResourceDecoder::create(mimeType, charset))
 {
 }
diff --git a/third_party/WebKit/Source/core/fetch/TextResource.h b/third_party/WebKit/Source/core/fetch/TextResource.h
index c24b261..a412f16 100644
--- a/third_party/WebKit/Source/core/fetch/TextResource.h
+++ b/third_party/WebKit/Source/core/fetch/TextResource.h
@@ -22,7 +22,7 @@
     String encoding() const override;
 
 protected:
-    TextResource(const ResourceRequest&, Type, const String& mimeType, const String& charset);
+    TextResource(const ResourceRequest&, Type, const ResourceLoaderOptions&, const String& mimeType, const String& charset);
     ~TextResource() override;
 
 private:
diff --git a/third_party/WebKit/Source/core/fetch/XSLStyleSheetResource.cpp b/third_party/WebKit/Source/core/fetch/XSLStyleSheetResource.cpp
index a4a25cbb..82f5f94d 100644
--- a/third_party/WebKit/Source/core/fetch/XSLStyleSheetResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/XSLStyleSheetResource.cpp
@@ -55,8 +55,8 @@
     return toXSLStyleSheetResource(fetcher->requestResource(request, XSLStyleSheetResourceFactory()));
 }
 
-XSLStyleSheetResource::XSLStyleSheetResource(const ResourceRequest& resourceRequest, const String& charset)
-    : StyleSheetResource(resourceRequest, XSLStyleSheet, "text/xsl", charset)
+XSLStyleSheetResource::XSLStyleSheetResource(const ResourceRequest& resourceRequest, const ResourceLoaderOptions& options, const String& charset)
+    : StyleSheetResource(resourceRequest, XSLStyleSheet, options, "text/xsl", charset)
 {
     ASSERT(RuntimeEnabledFeatures::xsltEnabled());
     DEFINE_STATIC_LOCAL(const AtomicString, acceptXSLT, ("text/xml, application/xml, application/xhtml+xml, text/xsl, application/rss+xml, application/atom+xml", AtomicString::ConstructFromLiteral));
diff --git a/third_party/WebKit/Source/core/fetch/XSLStyleSheetResource.h b/third_party/WebKit/Source/core/fetch/XSLStyleSheetResource.h
index 33687283..744abd2 100644
--- a/third_party/WebKit/Source/core/fetch/XSLStyleSheetResource.h
+++ b/third_party/WebKit/Source/core/fetch/XSLStyleSheetResource.h
@@ -48,12 +48,12 @@
         XSLStyleSheetResourceFactory()
             : ResourceFactory(Resource::XSLStyleSheet) { }
 
-        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const String& charset) const override
+        PassRefPtrWillBeRawPtr<Resource> create(const ResourceRequest& request, const ResourceLoaderOptions& options, const String& charset) const override
         {
-            return adoptRefWillBeNoop(new XSLStyleSheetResource(request, charset));
+            return adoptRefWillBeNoop(new XSLStyleSheetResource(request, options, charset));
         }
     };
-    XSLStyleSheetResource(const ResourceRequest&, const String& charset);
+    XSLStyleSheetResource(const ResourceRequest&, const ResourceLoaderOptions&, const String& charset);
 
     void checkNotify() override;
 
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
index 70e44f10..43aef5b 100644
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
@@ -135,7 +135,14 @@
     if (cropRect == srcRect) {
         if (flipY)
             return StaticBitmapImage::create(flipSkImageVertically(skiaImage->newSubset(srcRect), premultiplyAlpha ? PremultiplyAlpha : DontPremultiplyAlpha));
-        return StaticBitmapImage::create(adoptRef(skiaImage->newSubset(srcRect)));
+        SkImage* croppedSkImage = skiaImage->newSubset(srcRect);
+        if (cropRect == imgRect) {
+            // Call readPixels to trigger image decoding. Only read 1*1 subregion to be efficient.
+            SkImageInfo info = SkImageInfo::MakeN32(1, 1, premultiplyAlpha ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
+            OwnPtr<uint8_t[]> imagePixels = adoptArrayPtr(new uint8_t[info.bytesPerPixel()]);
+            croppedSkImage->readPixels(info, imagePixels.get(), info.bytesPerPixel(), 0, 0);
+        }
+        return StaticBitmapImage::create(adoptRef(croppedSkImage));
     }
 
     RefPtr<SkSurface> surface = adoptRef(SkSurface::NewRasterN32Premul(cropRect.width(), cropRect.height()));
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
index 875eea3a..8fac39c 100644
--- a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
@@ -193,6 +193,9 @@
     } else if (name == mediaAttr) {
         m_media = value.lower();
         process();
+    } else if (name == scopeAttr) {
+        m_scope = value;
+        process();
     } else if (name == disabledAttr) {
         UseCounter::count(document(), UseCounter::HTMLLinkElementDisabled);
         if (LinkStyle* link = linkStyle())
@@ -230,6 +233,9 @@
             m_link = LinkImport::create(this);
         } else if (m_relAttribute.isManifest()) {
             m_link = LinkManifest::create(this);
+        } else if (RuntimeEnabledFeatures::linkServiceWorkerEnabled() && m_relAttribute.isServiceWorker()) {
+            if (document().frame())
+                m_link = document().frame()->loader().client()->createServiceWorkerLinkResource(this);
         } else {
             OwnPtrWillBeRawPtr<LinkStyle> link = LinkStyle::create(this);
             if (fastHasAttribute(disabledAttr)) {
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.h b/third_party/WebKit/Source/core/html/HTMLLinkElement.h
index fa3643d..f6d5338c 100644
--- a/third_party/WebKit/Source/core/html/HTMLLinkElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.h
@@ -143,6 +143,7 @@
     String asValue() const { return m_as; }
     const LinkRelAttribute& relAttribute() const { return m_relAttribute; }
     DOMTokenList& relList() const { return static_cast<DOMTokenList&>(*m_relList); }
+    String scope() const { return m_scope; }
 
     const AtomicString& type() const;
 
@@ -227,6 +228,7 @@
     Vector<IntSize> m_iconSizes;
     RawPtrWillBeMember<RelList> m_relList;
     LinkRelAttribute m_relAttribute;
+    String m_scope;
 
     bool m_createdByParser;
     bool m_isInShadowTree;
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.idl b/third_party/WebKit/Source/core/html/HTMLLinkElement.idl
index 1d19a864b..55395e84 100644
--- a/third_party/WebKit/Source/core/html/HTMLLinkElement.idl
+++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.idl
@@ -52,4 +52,8 @@
     // Subresource Integrity
     // http://w3c.github.io/webappsec/specs/subresourceintegrity/#htmllinkelement-1
     [Reflect] attribute DOMString integrity;
+
+    // Service workers
+    // http://mkruisselbrink.github.io/ServiceWorker/spec/service_worker/#link-element-interface-section
+    [Reflect, RuntimeEnabled=LinkServiceWorker] attribute USVString scope;
 };
diff --git a/third_party/WebKit/Source/core/html/LinkRelAttribute.cpp b/third_party/WebKit/Source/core/html/LinkRelAttribute.cpp
index 825ea483..21b068b 100644
--- a/third_party/WebKit/Source/core/html/LinkRelAttribute.cpp
+++ b/third_party/WebKit/Source/core/html/LinkRelAttribute.cpp
@@ -47,6 +47,7 @@
     , m_isLinkNext(false)
     , m_isImport(false)
     , m_isManifest(false)
+    , m_isServiceWorker(false)
 {
     if (rel.isEmpty())
         return;
@@ -88,6 +89,8 @@
             m_iconType = TouchPrecomposedIcon;
         } else if (equalIgnoringCase(linkType, "manifest")) {
             m_isManifest = true;
+        } else if (equalIgnoringCase(linkType, "serviceworker")) {
+            m_isServiceWorker = true;
         }
         // Adding or removing a value here requires you to update RelList::supportedTokens()
     }
diff --git a/third_party/WebKit/Source/core/html/LinkRelAttribute.h b/third_party/WebKit/Source/core/html/LinkRelAttribute.h
index 5230d3a..11e7bf9 100644
--- a/third_party/WebKit/Source/core/html/LinkRelAttribute.h
+++ b/third_party/WebKit/Source/core/html/LinkRelAttribute.h
@@ -55,6 +55,7 @@
     bool isLinkNext() const { return m_isLinkNext; }
     bool isImport() const { return m_isImport; }
     bool isManifest() const { return m_isManifest; }
+    bool isServiceWorker() const { return m_isServiceWorker; }
 
 private:
     IconType m_iconType;
@@ -68,6 +69,7 @@
     bool m_isLinkNext : 1;
     bool m_isImport : 1;
     bool m_isManifest : 1;
+    bool m_isServiceWorker : 1;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/LinkResource.h b/third_party/WebKit/Source/core/html/LinkResource.h
index 7599d92..07c983c 100644
--- a/third_party/WebKit/Source/core/html/LinkResource.h
+++ b/third_party/WebKit/Source/core/html/LinkResource.h
@@ -31,6 +31,7 @@
 #ifndef LinkResource_h
 #define LinkResource_h
 
+#include "core/CoreExport.h"
 #include "core/fetch/FetchRequest.h"
 #include "platform/heap/Handle.h"
 #include "platform/weborigin/KURL.h"
@@ -41,13 +42,14 @@
 class HTMLLinkElement;
 class LocalFrame;
 
-class LinkResource : public NoBaseWillBeGarbageCollectedFinalized<LinkResource>  {
+class CORE_EXPORT LinkResource : public NoBaseWillBeGarbageCollectedFinalized<LinkResource>  {
     WTF_MAKE_NONCOPYABLE(LinkResource); USING_FAST_MALLOC_WILL_BE_REMOVED(LinkResource);
 public:
     enum LinkResourceType {
         Style,
         Import,
-        Manifest
+        Manifest,
+        Other
     };
 
     explicit LinkResource(HTMLLinkElement*);
diff --git a/third_party/WebKit/Source/core/html/RelList.cpp b/third_party/WebKit/Source/core/html/RelList.cpp
index 18a2ecda..4b726e5 100644
--- a/third_party/WebKit/Source/core/html/RelList.cpp
+++ b/third_party/WebKit/Source/core/html/RelList.cpp
@@ -5,6 +5,7 @@
 #include "core/html/RelList.h"
 
 #include "core/dom/Document.h"
+#include "platform/RuntimeEnabledFeatures.h"
 #include "wtf/HashMap.h"
 
 namespace blink {
@@ -67,6 +68,8 @@
         supportedValuesMap.add("manifest");
         supportedValuesMap.add("apple-touch-icon");
         supportedValuesMap.add("apple-touch-icon-precomposed");
+        if (RuntimeEnabledFeatures::linkServiceWorkerEnabled())
+            supportedValuesMap.add("serviceworker");
     }
 
     return supportedValuesMap;
diff --git a/third_party/WebKit/Source/core/layout/LayoutRubyText.h b/third_party/WebKit/Source/core/layout/LayoutRubyText.h
index 8841b37..292ebce85 100644
--- a/third_party/WebKit/Source/core/layout/LayoutRubyText.h
+++ b/third_party/WebKit/Source/core/layout/LayoutRubyText.h
@@ -53,6 +53,8 @@
     void adjustInlineDirectionLineBounds(unsigned expansionOpportunityCount, LayoutUnit& logicalLeft, LayoutUnit& logicalWidth) const override;
 };
 
+DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutRubyText, isRubyText());
+
 } // namespace blink
 
 #endif // LayoutRubyText_h
diff --git a/third_party/WebKit/Source/core/layout/api/LayoutViewItem.h b/third_party/WebKit/Source/core/layout/api/LayoutViewItem.h
index b288cc7..94c9edc 100644
--- a/third_party/WebKit/Source/core/layout/api/LayoutViewItem.h
+++ b/third_party/WebKit/Source/core/layout/api/LayoutViewItem.h
@@ -11,6 +11,8 @@
 
 namespace blink {
 
+class PaintLayerCompositor;
+
 class LayoutViewItem : public LayoutBlockItem {
 public:
     explicit LayoutViewItem(LayoutView* layoutView)
@@ -28,6 +30,11 @@
 
     LayoutViewItem() { }
 
+    PaintLayerCompositor* compositor()
+    {
+        return toView()->compositor();
+    }
+
     IntRect documentRect() const
     {
         return toView()->documentRect();
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutBlockFlow.h b/third_party/WebKit/Source/core/layout/api/LineLayoutBlockFlow.h
index 6ef0dee..ad2c4f6 100644
--- a/third_party/WebKit/Source/core/layout/api/LineLayoutBlockFlow.h
+++ b/third_party/WebKit/Source/core/layout/api/LineLayoutBlockFlow.h
@@ -213,6 +213,21 @@
         return toBlockFlow()->lastLineBox();
     }
 
+    InlineFlowBox* firstLineBox()
+    {
+        return toBlockFlow()->firstLineBox();
+    }
+
+    RootInlineBox* firstRootBox() const
+    {
+        return toBlockFlow()->firstRootBox();
+    }
+
+    RootInlineBox* lastRootBox() const
+    {
+        return toBlockFlow()->lastRootBox();
+    }
+
 private:
     LayoutBlockFlow* toBlockFlow() { return toLayoutBlockFlow(layoutObject()); };
     const LayoutBlockFlow* toBlockFlow() const { return toLayoutBlockFlow(layoutObject()); };
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutBox.h b/third_party/WebKit/Source/core/layout/api/LineLayoutBox.h
index db3bb838..b1954d3a 100644
--- a/third_party/WebKit/Source/core/layout/api/LineLayoutBox.h
+++ b/third_party/WebKit/Source/core/layout/api/LineLayoutBox.h
@@ -51,6 +51,11 @@
         return toBox()->logicalHeight();
     }
 
+    LayoutUnit logicalTop() const
+    {
+        return toBox()->logicalTop();
+    }
+
     LayoutUnit flipForWritingMode(LayoutUnit unit) const
     {
         return toBox()->flipForWritingMode(unit);
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutItem.h b/third_party/WebKit/Source/core/layout/api/LineLayoutItem.h
index 30fd9e12..4a87e2e5 100644
--- a/third_party/WebKit/Source/core/layout/api/LineLayoutItem.h
+++ b/third_party/WebKit/Source/core/layout/api/LineLayoutItem.h
@@ -265,6 +265,11 @@
         return m_layoutObject->isAtomicInlineLevel();
     }
 
+    bool isRubyText() const
+    {
+        return m_layoutObject->isRubyText();
+    }
+
     bool isRubyRun() const
     {
         return m_layoutObject->isRubyRun();
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutRubyRun.h b/third_party/WebKit/Source/core/layout/api/LineLayoutRubyRun.h
index d5ed629..7106de3 100644
--- a/third_party/WebKit/Source/core/layout/api/LineLayoutRubyRun.h
+++ b/third_party/WebKit/Source/core/layout/api/LineLayoutRubyRun.h
@@ -7,6 +7,7 @@
 
 #include "core/layout/LayoutRubyRun.h"
 #include "core/layout/api/LineLayoutBlockFlow.h"
+#include "core/layout/api/LineLayoutRubyText.h"
 
 namespace blink {
 
@@ -32,9 +33,9 @@
         toRubyRun()->getOverhang(firstLine, startLayoutItem.layoutObject(), endLayoutItem.layoutObject(), startOverhang, endOverhang);
     }
 
-    LayoutRubyText* rubyText() const
+    LineLayoutRubyText rubyText() const
     {
-        return toRubyRun()->rubyText();
+        return LineLayoutRubyText(toRubyRun()->rubyText());
     }
 
     LayoutRubyBase* rubyBase() const
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutRubyText.h b/third_party/WebKit/Source/core/layout/api/LineLayoutRubyText.h
new file mode 100644
index 0000000..e297e656
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/api/LineLayoutRubyText.h
@@ -0,0 +1,45 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LineLayoutRubyText_h
+#define LineLayoutRubyText_h
+
+#include "core/layout/LayoutRubyText.h"
+#include "core/layout/api/LineLayoutBlockFlow.h"
+
+namespace blink {
+
+class LineLayoutRubyText : public LineLayoutBlockFlow {
+public:
+    explicit LineLayoutRubyText(LayoutRubyText* layoutRubyText)
+        : LineLayoutBlockFlow(layoutRubyText)
+    {
+    }
+
+    explicit LineLayoutRubyText(const LineLayoutItem& item)
+        : LineLayoutBlockFlow(item)
+    {
+        ASSERT_WITH_SECURITY_IMPLICATION(!item || item.isRubyText());
+    }
+
+    explicit LineLayoutRubyText(std::nullptr_t) : LineLayoutBlockFlow(nullptr) { }
+
+    LineLayoutRubyText() { }
+
+
+private:
+    LayoutRubyText* toRubyText()
+    {
+        return toLayoutRubyText(layoutObject());
+    }
+
+    const LayoutRubyText* toRubyText() const
+    {
+        return toLayoutRubyText(layoutObject());
+    }
+};
+
+} // namespace blink
+
+#endif // LineLayoutRubyText_h
diff --git a/third_party/WebKit/Source/core/layout/line/DEPS b/third_party/WebKit/Source/core/layout/line/DEPS
index ff0ae54f..165f3863 100644
--- a/third_party/WebKit/Source/core/layout/line/DEPS
+++ b/third_party/WebKit/Source/core/layout/line/DEPS
@@ -11,7 +11,6 @@
     "!core/layout/HitTestResult.h",
     "!core/layout/LayoutBlockFlow.h",
     "!core/layout/LayoutRubyBase.h",
-    "!core/layout/LayoutRubyText.h",
     "!core/layout/OverflowModel.h",
     "!core/layout/TextRunConstructor.h",
     "!core/layout/VerticalPositionCache.h",
diff --git a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
index 26f94f3..2abd3ac4 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
+++ b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
@@ -23,12 +23,12 @@
 #include "core/dom/Document.h"
 #include "core/layout/HitTestResult.h"
 #include "core/layout/LayoutRubyBase.h"
-#include "core/layout/LayoutRubyText.h"
 #include "core/layout/api/LineLayoutBlockFlow.h"
 #include "core/layout/api/LineLayoutBox.h"
 #include "core/layout/api/LineLayoutInline.h"
 #include "core/layout/api/LineLayoutListMarker.h"
 #include "core/layout/api/LineLayoutRubyRun.h"
+#include "core/layout/api/LineLayoutRubyText.h"
 #include "core/layout/line/GlyphOverflow.h"
 #include "core/layout/line/InlineTextBox.h"
 #include "core/layout/line/RootInlineBox.h"
@@ -1144,18 +1144,18 @@
 
         if (curr->getLineLayoutItem().isAtomicInlineLevel() && curr->getLineLayoutItem().isRubyRun() && curr->getLineLayoutItem().style()->getRubyPosition() == RubyPositionBefore) {
             LineLayoutRubyRun rubyRun = LineLayoutRubyRun(curr->getLineLayoutItem());
-            LayoutRubyText* rubyText = rubyRun.rubyText();
+            LineLayoutRubyText rubyText = rubyRun.rubyText();
             if (!rubyText)
                 continue;
 
             if (!rubyRun.style()->isFlippedLinesWritingMode()) {
-                LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : LayoutUnit());
+                LayoutUnit topOfFirstRubyTextLine = rubyText.logicalTop() + (rubyText.firstRootBox() ? rubyText.firstRootBox()->lineTop() : LayoutUnit());
                 if (topOfFirstRubyTextLine >= 0)
                     continue;
                 topOfFirstRubyTextLine += curr->logicalTop();
                 result = std::max(result, allowedPosition - topOfFirstRubyTextLine);
             } else {
-                LayoutUnit bottomOfLastRubyTextLine = rubyText->logicalTop() + (rubyText->lastRootBox() ? rubyText->lastRootBox()->lineBottom() : rubyText->logicalHeight());
+                LayoutUnit bottomOfLastRubyTextLine = rubyText.logicalTop() + (rubyText.lastRootBox() ? rubyText.lastRootBox()->lineBottom() : rubyText.logicalHeight());
                 if (bottomOfLastRubyTextLine <= curr->logicalHeight())
                     continue;
                 bottomOfLastRubyTextLine += curr->logicalTop();
@@ -1192,18 +1192,18 @@
 
         if (curr->getLineLayoutItem().isAtomicInlineLevel() && curr->getLineLayoutItem().isRubyRun() && curr->getLineLayoutItem().style()->getRubyPosition() == RubyPositionAfter) {
             LineLayoutRubyRun rubyRun = LineLayoutRubyRun(curr->getLineLayoutItem());
-            LayoutRubyText* rubyText = rubyRun.rubyText();
+            LineLayoutRubyText rubyText = rubyRun.rubyText();
             if (!rubyText)
                 continue;
 
             if (rubyRun.style()->isFlippedLinesWritingMode()) {
-                LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : LayoutUnit());
+                LayoutUnit topOfFirstRubyTextLine = rubyText.logicalTop() + (rubyText.firstRootBox() ? rubyText.firstRootBox()->lineTop() : LayoutUnit());
                 if (topOfFirstRubyTextLine >= 0)
                     continue;
                 topOfFirstRubyTextLine += curr->logicalTop();
                 result = std::max(result, allowedPosition - topOfFirstRubyTextLine);
             } else {
-                LayoutUnit bottomOfLastRubyTextLine = rubyText->logicalTop() + (rubyText->lastRootBox() ? rubyText->lastRootBox()->lineBottom() : rubyText->logicalHeight());
+                LayoutUnit bottomOfLastRubyTextLine = rubyText.logicalTop() + (rubyText.lastRootBox() ? rubyText.lastRootBox()->lineBottom() : rubyText.logicalHeight());
                 if (bottomOfLastRubyTextLine <= curr->logicalHeight())
                     continue;
                 bottomOfLastRubyTextLine += curr->logicalTop();
diff --git a/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp b/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
index 41cd392..9d11f0c3 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
+++ b/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
@@ -23,10 +23,10 @@
 #include "core/layout/line/InlineTextBox.h"
 
 #include "core/layout/HitTestResult.h"
-#include "core/layout/LayoutRubyText.h"
 #include "core/layout/api/LineLayoutBR.h"
 #include "core/layout/api/LineLayoutBox.h"
 #include "core/layout/api/LineLayoutRubyRun.h"
+#include "core/layout/api/LineLayoutRubyText.h"
 #include "core/layout/line/AbstractInlineTextBox.h"
 #include "core/layout/line/EllipsisBox.h"
 #include "core/paint/InlineTextBoxPainter.h"
@@ -413,10 +413,10 @@
     if (!containingBlock.parent().isRubyRun())
         return true; // Cannot get the ruby text.
 
-    LayoutRubyText* rubyText = LineLayoutRubyRun(containingBlock.parent()).rubyText();
+    LineLayoutRubyText rubyText = LineLayoutRubyRun(containingBlock.parent()).rubyText();
 
     // The emphasis marks over are suppressed only if there is a ruby text box and it not empty.
-    return !rubyText || !rubyText->firstLineBox();
+    return !rubyText || !rubyText.firstLineBox();
 }
 
 void InlineTextBox::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit /*lineTop*/, LayoutUnit /*lineBottom*/) const
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp
index 68f4a4c0..8954380 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp
@@ -114,7 +114,7 @@
 static void computeGlyphOverflow(SVGInlineTextBox* textBox, SVGTextFragment& textFragment)
 {
     LineLayoutSVGInlineText textLineLayout = LineLayoutSVGInlineText(textBox->getLineLayoutItem());
-    TextRun run = SVGTextMetrics::constructTextRun(textLineLayout, textFragment.characterOffset, textFragment.length, textLineLayout.styleRef().direction());
+    TextRun run = textBox->constructTextRun(textLineLayout.styleRef(), textFragment);
 
     float scalingFactor = textLineLayout.scalingFactor();
     ASSERT(scalingFactor);
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGTextMetricsBuilder.cpp b/third_party/WebKit/Source/core/layout/svg/SVGTextMetricsBuilder.cpp
index 87917374..7c212e9 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGTextMetricsBuilder.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/SVGTextMetricsBuilder.cpp
@@ -161,6 +161,12 @@
         }
     }
 
+    // TODO(pdr): m_subrunRanges can be too short in the presence of invalid
+    // unicode characters (see: crbug.com/595960). This is a temporary
+    // workaround to ensure the returned index is valid for m_subrunRages.
+    if (positionInRun >= m_subrunRanges.size())
+        return 0;
+
     return positionInRun;
 }
 
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
index 8af960e6..1c68b663 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
@@ -97,7 +97,7 @@
 
 DocumentLoader::DocumentLoader(LocalFrame* frame, const ResourceRequest& req, const SubstituteData& substituteData)
     : m_frame(frame)
-    , m_fetcher(FrameFetchContext::createContextAndFetcher(this))
+    , m_fetcher(FrameFetchContext::createContextAndFetcher(this, nullptr))
     , m_originalRequest(req)
     , m_substituteData(substituteData)
     , m_request(req)
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
index 56fc09e..f040553 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -71,11 +71,12 @@
 
 namespace blink {
 
-FrameFetchContext::FrameFetchContext(DocumentLoader* loader)
-    : m_document(nullptr)
+FrameFetchContext::FrameFetchContext(DocumentLoader* loader, Document* document)
+    : m_document(document)
     , m_documentLoader(loader)
     , m_imageFetched(false)
 {
+    ASSERT(frame());
 }
 
 FrameFetchContext::~FrameFetchContext()
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.h b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
index abce8e5d..c652b30 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.h
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
@@ -51,9 +51,9 @@
 
 class CORE_EXPORT FrameFetchContext final : public FetchContext {
 public:
-    static ResourceFetcher* createContextAndFetcher(DocumentLoader* loader)
+    static ResourceFetcher* createContextAndFetcher(DocumentLoader* loader, Document* document)
     {
-        return ResourceFetcher::create(new FrameFetchContext(loader));
+        return ResourceFetcher::create(new FrameFetchContext(loader, document));
     }
 
     static void provideDocumentToContext(FetchContext& context, Document* document)
@@ -117,7 +117,7 @@
     DECLARE_VIRTUAL_TRACE();
 
 private:
-    explicit FrameFetchContext(DocumentLoader*);
+    explicit FrameFetchContext(DocumentLoader*, Document*);
     inline DocumentLoader* ensureLoaderForNotifications() const;
 
     LocalFrame* frame() const; // Can be null
diff --git a/third_party/WebKit/Source/core/loader/FrameLoaderClient.h b/third_party/WebKit/Source/core/loader/FrameLoaderClient.h
index 65f542f..870898c 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoaderClient.h
+++ b/third_party/WebKit/Source/core/loader/FrameLoaderClient.h
@@ -35,6 +35,7 @@
 #include "core/dom/IconURL.h"
 #include "core/fetch/ResourceLoaderOptions.h"
 #include "core/frame/FrameClient.h"
+#include "core/html/LinkResource.h"
 #include "core/loader/FrameLoaderTypes.h"
 #include "core/loader/NavigationPolicy.h"
 #include "platform/heap/Handle.h"
@@ -255,6 +256,7 @@
     };
     virtual void suddenTerminationDisablerChanged(bool present, SuddenTerminationDisablerType) { }
 
+    virtual PassOwnPtrWillBeRawPtr<LinkResource> createServiceWorkerLinkResource(HTMLLinkElement*) { return nullptr; }
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimationElement.cpp b/third_party/WebKit/Source/core/svg/SVGAnimationElement.cpp
index 5c9440e9..ed35d252 100644
--- a/third_party/WebKit/Source/core/svg/SVGAnimationElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGAnimationElement.cpp
@@ -447,7 +447,7 @@
     SMILTime duration = simpleDuration();
     if (!duration.isFinite())
         duration = 100.0;
-    return narrowPrecisionToFloat(bezier.solve(percent, solveEpsilon(duration.value())));
+    return narrowPrecisionToFloat(bezier.solveWithEpsilon(percent, solveEpsilon(duration.value())));
 }
 
 float SVGAnimationElement::calculatePercentFromKeyPoints(float percent) const
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index 88e6375e..7b22252a 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -76,7 +76,7 @@
 group("devtools_frontend_resources") {
   public_deps = [
     ":build_applications",
-    ":copy_compatibility_scripts",
+    ":copy_embedder_scripts",
     ":copy_emulated_devices_images",
     ":copy_inspector_images",
     ":devtools_extension_api",
@@ -85,8 +85,8 @@
   ]
 }
 
-copy("copy_compatibility_scripts") {
-  sources = gypi_values.devtools_compatibility_scripts
+copy("copy_embedder_scripts") {
+  sources = gypi_values.devtools_embedder_scripts
   outputs = [
     resources_out_dir + "{{source_file_part}}",
   ]
@@ -113,7 +113,7 @@
     ":devtools_frontend_resources",
   ]
   inputs = gypi_values.devtools_image_files + all_devtools_files
-  inputs += gypi_values.devtools_compatibility_scripts
+  inputs += gypi_values.devtools_embedder_scripts
 
   if (debug_devtools) {
     # Debug: all files are picked as-is.
@@ -181,18 +181,17 @@
     "front_end",
   ]
 
-  args =
-      rebase_path(generated_files, root_build_dir) +
-      rebase_path(generated_files, root_build_dir) +
-      rebase_path(gypi_values.devtools_compatibility_scripts, root_build_dir) +
-      static_files_args + [ "--relative_path_dirs" ] +
-      rebase_path(relative_path_dirs, root_build_dir) +
-      [
-        "--images",
-        rebase_path(images_path, root_build_dir),
-        "--output",
-        rebase_path(outfile, root_build_dir),
-      ]
+  args = rebase_path(generated_files, root_build_dir) +
+         rebase_path(generated_files, root_build_dir) +
+         rebase_path(gypi_values.devtools_embedder_scripts, root_build_dir) +
+         static_files_args + [ "--relative_path_dirs" ] +
+         rebase_path(relative_path_dirs, root_build_dir) +
+         [
+           "--images",
+           rebase_path(images_path, root_build_dir),
+           "--output",
+           rebase_path(outfile, root_build_dir),
+         ]
 }
 
 action("devtools_extension_api") {
diff --git a/third_party/WebKit/Source/devtools/devtools.gyp b/third_party/WebKit/Source/devtools/devtools.gyp
index 7e9472a..ab14a9a 100644
--- a/third_party/WebKit/Source/devtools/devtools.gyp
+++ b/third_party/WebKit/Source/devtools/devtools.gyp
@@ -57,7 +57,7 @@
                 {
                     'destination': '<(PRODUCT_DIR)/resources/inspector/',
                     'files': [
-                        '<@(devtools_compatibility_scripts)',
+                        '<@(devtools_embedder_scripts)',
                     ],
                 },
             ],
@@ -132,7 +132,7 @@
                         'inputs': [
                             '<@(_script_name)',
                             '<@(_static_files)',
-                            '<@(devtools_compatibility_scripts)',
+                            '<@(devtools_embedder_scripts)',
                             '<@(_generated_files)',
                             '<@(devtools_image_files)',
                             '<(_devtools_static_files_list)',
@@ -141,7 +141,7 @@
                             'front_end/Images',
                         ],
                         'outputs': ['<(SHARED_INTERMEDIATE_DIR)/devtools/devtools_resources.grd'],
-                        'action': ['python', '<@(_script_name)', '<@(_generated_files)', '<@(devtools_compatibility_scripts)', '--static_files_list', '<(_devtools_static_files_list)', '--relative_path_dirs', '<@(_relative_path_dirs)', '--images', '<@(_images_path)', '--output', '<@(_outputs)'],
+                        'action': ['python', '<@(_script_name)', '<@(_generated_files)', '<@(devtools_embedder_scripts)', '--static_files_list', '<(_devtools_static_files_list)', '--relative_path_dirs', '<@(_relative_path_dirs)', '--images', '<@(_images_path)', '--output', '<@(_outputs)'],
                     }],
                 },
                 {
@@ -170,7 +170,7 @@
                         'inputs': [
                             '<@(_script_name)',
                             '<@(_static_files)',
-                            '<@(devtools_compatibility_scripts)',
+                            '<@(devtools_embedder_scripts)',
                             '<@(_generated_files)',
                             '<@(devtools_image_files)',
                             '<(_devtools_static_files_list)',
@@ -180,7 +180,7 @@
                         ],
                         # Note that other files are put under /devtools directory, together with declared devtools_resources.grd
                         'outputs': ['<(SHARED_INTERMEDIATE_DIR)/devtools/devtools_resources.grd'],
-                        'action': ['python', '<@(_script_name)', '<@(_generated_files)', '<@(devtools_compatibility_scripts)', '--static_files_list', '<(_devtools_static_files_list)', '--relative_path_dirs', '<@(_relative_path_dirs)', '--images', '<@(_images_path)', '--output', '<@(_outputs)'],
+                        'action': ['python', '<@(_script_name)', '<@(_generated_files)', '<@(devtools_embedder_scripts)', '--static_files_list', '<(_devtools_static_files_list)', '--relative_path_dirs', '<@(_relative_path_dirs)', '--images', '<@(_images_path)', '--output', '<@(_outputs)'],
                     }],
                 }],
             ],
diff --git a/third_party/WebKit/Source/devtools/devtools.gypi b/third_party/WebKit/Source/devtools/devtools.gypi
index 5242a26..c5140150 100644
--- a/third_party/WebKit/Source/devtools/devtools.gypi
+++ b/third_party/WebKit/Source/devtools/devtools.gypi
@@ -48,8 +48,9 @@
             '<@(devtools_ui_js_files)',
             '<@(devtools_workspace_js_files)',
         ],
-        'devtools_compatibility_scripts': [
+        'devtools_embedder_scripts': [
             'front_end/devtools.js',
+            'front_end/Tests.js',
         ],
         'devtools_core_base_files': [
             'front_end/inspector.js',
@@ -73,7 +74,6 @@
             'front_end/common/StaticContentProvider.js',
             'front_end/common/OutputStream.js',
             'front_end/common/SegmentedRange.js',
-            'front_end/common/TestBase.js',
             'front_end/common/Text.js',
             'front_end/common/TextDictionary.js',
             'front_end/common/TextRange.js',
@@ -312,7 +312,6 @@
             'front_end/main/OverlayController.js',
             'front_end/main/RenderingOptions.js',
             'front_end/main/SimpleApp.js',
-            'front_end/main/Tests.js',
         ],
         'devtools_module_json_files': [
             'front_end/accessibility/module.json',
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Tests.js b/third_party/WebKit/Source/devtools/front_end/Tests.js
similarity index 84%
rename from third_party/WebKit/Source/devtools/front_end/main/Tests.js
rename to third_party/WebKit/Source/devtools/front_end/Tests.js
index d7cebcf0..81e0557 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/Tests.js
+++ b/third_party/WebKit/Source/devtools/front_end/Tests.js
@@ -37,25 +37,212 @@
  * FIXME: change field naming style to use trailing underscore.
  */
 
-function createTestSuite(domAutomationController)
+(function createTestSuite(window)
 {
 
 /**
  * Test suite for interactive UI tests.
  * @constructor
+ * @param {Object} domAutomationController DomAutomationController instance.
  */
-function TestSuite()
+function TestSuite(domAutomationController)
 {
-    WebInspector.TestBase.call(this, domAutomationController);
+    this.domAutomationController_ = domAutomationController;
+    this.controlTaken_ = false;
+    this.timerId_ = -1;
     this._asyncInvocationId = 0;
+}
+
+/**
+ * Reports test failure.
+ * @param {string} message Failure description.
+ */
+TestSuite.prototype.fail = function(message)
+{
+    if (this.controlTaken_)
+        this.reportFailure_(message);
+    else
+        throw message;
 };
 
-TestSuite.prototype = {
-    __proto__: WebInspector.TestBase.prototype
+
+/**
+ * Equals assertion tests that expected === actual.
+ * @param {!Object|boolean} expected Expected object.
+ * @param {!Object|boolean} actual Actual object.
+ * @param {string} opt_message User message to print if the test fails.
+ */
+TestSuite.prototype.assertEquals = function(expected, actual, opt_message)
+{
+    if (expected !== actual) {
+        var message = "Expected: '" + expected + "', but was '" + actual + "'";
+        if (opt_message)
+            message = opt_message + "(" + message + ")";
+        this.fail(message);
+    }
 };
 
 
 /**
+ * True assertion tests that value == true.
+ * @param {!Object} value Actual object.
+ * @param {string} opt_message User message to print if the test fails.
+ */
+TestSuite.prototype.assertTrue = function(value, opt_message)
+{
+    this.assertEquals(true, !!value, opt_message);
+};
+
+
+/**
+ * Takes control over execution.
+ */
+TestSuite.prototype.takeControl = function()
+{
+    this.controlTaken_ = true;
+    // Set up guard timer.
+    var self = this;
+    this.timerId_ = setTimeout(function() {
+        self.reportFailure_("Timeout exceeded: 20 sec");
+    }, 20000);
+};
+
+
+/**
+ * Releases control over execution.
+ */
+TestSuite.prototype.releaseControl = function()
+{
+    if (this.timerId_ !== -1) {
+        clearTimeout(this.timerId_);
+        this.timerId_ = -1;
+    }
+    this.controlTaken_ = false;
+    this.reportOk_();
+};
+
+
+/**
+ * Async tests use this one to report that they are completed.
+ */
+TestSuite.prototype.reportOk_ = function()
+{
+    this.domAutomationController_.send("[OK]");
+};
+
+
+/**
+ * Async tests use this one to report failures.
+ */
+TestSuite.prototype.reportFailure_ = function(error)
+{
+    if (this.timerId_ !== -1) {
+        clearTimeout(this.timerId_);
+        this.timerId_ = -1;
+    }
+    this.domAutomationController_.send("[FAILED] " + error);
+};
+
+
+/**
+ * Run specified test on a fresh instance of the test suite.
+ * @param {Array<string>} args method name followed by its parameters.
+ */
+TestSuite.prototype.dispatchOnTestSuite = function(args)
+{
+    var methodName = args.shift();
+    try {
+        this[methodName].apply(this, args);
+        if (!this.controlTaken_)
+            this.reportOk_();
+    } catch (e) {
+        this.reportFailure_(e);
+    }
+};
+
+
+/**
+ * Wrap an async method with TestSuite.{takeControl(), releaseControl()}
+ * and invoke TestSuite.reportOk_ upon completion.
+ * @param {Array<string>} args method name followed by its parameters.
+ */
+TestSuite.prototype.waitForAsync = function(var_args)
+{
+    var args = Array.prototype.slice.call(arguments);
+    this.takeControl();
+    args.push(this.releaseControl.bind(this));
+    this.dispatchOnTestSuite(args);
+};
+
+/**
+ * Overrides the method with specified name until it's called first time.
+ * @param {!Object} receiver An object whose method to override.
+ * @param {string} methodName Name of the method to override.
+ * @param {!Function} override A function that should be called right after the
+ *     overridden method returns.
+ * @param {?boolean} opt_sticky Whether restore original method after first run
+ *     or not.
+ */
+TestSuite.prototype.addSniffer = function(receiver, methodName, override, opt_sticky)
+{
+    var orig = receiver[methodName];
+    if (typeof orig !== "function")
+        this.fail("Cannot find method to override: " + methodName);
+    var test = this;
+    receiver[methodName] = function(var_args) {
+        try {
+            var result = orig.apply(this, arguments);
+        } finally {
+            if (!opt_sticky)
+                receiver[methodName] = orig;
+        }
+        // In case of exception the override won't be called.
+        try {
+            override.apply(this, arguments);
+        } catch (e) {
+            test.fail("Exception in overriden method '" + methodName + "': " + e);
+        }
+        return result;
+    };
+};
+
+/**
+ * Waits for current throttler invocations, if any.
+ * @param {!WebInspector.Throttler} throttler
+ * @param {function()} callback
+ */
+TestSuite.prototype.waitForThrottler = function(throttler, callback)
+{
+    var test = this;
+    var scheduleShouldFail = true;
+    test.addSniffer(throttler, "schedule", onSchedule);
+
+    function hasSomethingScheduled()
+    {
+        return throttler._isRunningProcess || throttler._process;
+    }
+
+    function checkState()
+    {
+        if (!hasSomethingScheduled()) {
+            scheduleShouldFail = false;
+            callback();
+            return;
+        }
+
+        test.addSniffer(throttler, "_processCompletedForTests", checkState);
+    }
+
+    function onSchedule()
+    {
+        if (scheduleShouldFail)
+            test.fail("Unexpected Throttler.schedule");
+    }
+
+    checkState();
+};
+
+/**
  * @param {string} panelName Name of the panel to show.
  */
 TestSuite.prototype.showPanel = function(panelName)
@@ -888,11 +1075,5 @@
     return evt;
 };
 
-return new TestSuite();
-
-}
-
-if (window.uiTests) {
-    WebInspector.notifications.addEventListener(WebInspector.NotificationService.Events.InspectorAgentEnabledForTests,
-        window.uiTests.testSuiteReady.bind(null, createTestSuite));
-}
+window.uiTests = new TestSuite(window.domAutomationController);
+})(window);
diff --git a/third_party/WebKit/Source/devtools/front_end/common/NotificationService.js b/third_party/WebKit/Source/devtools/front_end/common/NotificationService.js
index ea2e8c5..a6292fe2 100644
--- a/third_party/WebKit/Source/devtools/front_end/common/NotificationService.js
+++ b/third_party/WebKit/Source/devtools/front_end/common/NotificationService.js
@@ -15,7 +15,6 @@
 }
 
 WebInspector.NotificationService.Events = {
-    InspectorAgentEnabledForTests: "InspectorAgentEnabledForTests",
     SelectedNodeChanged: "SelectedNodeChanged"
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/common/TestBase.js b/third_party/WebKit/Source/devtools/front_end/common/TestBase.js
deleted file mode 100644
index 48fecf7b..0000000
--- a/third_party/WebKit/Source/devtools/front_end/common/TestBase.js
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * Test suite for interactive UI tests.
- * @constructor
- * @param {Object} domAutomationController DomAutomationController instance.
- */
-WebInspector.TestBase = function(domAutomationController)
-{
-    this.domAutomationController_ = domAutomationController;
-    this.controlTaken_ = false;
-    this.timerId_ = -1;
-};
-
-
-/**
- * Reports test failure.
- * @param {string} message Failure description.
- */
-WebInspector.TestBase.prototype.fail = function(message)
-{
-    if (this.controlTaken_)
-        this.reportFailure_(message);
-    else
-        throw message;
-};
-
-
-/**
- * Equals assertion tests that expected === actual.
- * @param {!Object|boolean} expected Expected object.
- * @param {!Object|boolean} actual Actual object.
- * @param {string} opt_message User message to print if the test fails.
- */
-WebInspector.TestBase.prototype.assertEquals = function(expected, actual, opt_message)
-{
-    if (expected !== actual) {
-        var message = "Expected: '" + expected + "', but was '" + actual + "'";
-        if (opt_message)
-            message = opt_message + "(" + message + ")";
-        this.fail(message);
-    }
-};
-
-
-/**
- * True assertion tests that value == true.
- * @param {!Object} value Actual object.
- * @param {string} opt_message User message to print if the test fails.
- */
-WebInspector.TestBase.prototype.assertTrue = function(value, opt_message)
-{
-    this.assertEquals(true, !!value, opt_message);
-};
-
-
-/**
- * Takes control over execution.
- */
-WebInspector.TestBase.prototype.takeControl = function()
-{
-    this.controlTaken_ = true;
-    // Set up guard timer.
-    var self = this;
-    this.timerId_ = setTimeout(function() {
-        self.reportFailure_("Timeout exceeded: 20 sec");
-    }, 20000);
-};
-
-
-/**
- * Releases control over execution.
- */
-WebInspector.TestBase.prototype.releaseControl = function()
-{
-    if (this.timerId_ !== -1) {
-        clearTimeout(this.timerId_);
-        this.timerId_ = -1;
-    }
-    this.controlTaken_ = false;
-    this.reportOk_();
-};
-
-
-/**
- * Async tests use this one to report that they are completed.
- */
-WebInspector.TestBase.prototype.reportOk_ = function()
-{
-    this.domAutomationController_.send("[OK]");
-};
-
-
-/**
- * Async tests use this one to report failures.
- */
-WebInspector.TestBase.prototype.reportFailure_ = function(error)
-{
-    if (this.timerId_ !== -1) {
-        clearTimeout(this.timerId_);
-        this.timerId_ = -1;
-    }
-    this.domAutomationController_.send("[FAILED] " + error);
-};
-
-
-/**
- * Run specified test on a fresh instance of the test suite.
- * @param {Array<string>} args method name followed by its parameters.
- */
-WebInspector.TestBase.prototype.dispatch = function(args)
-{
-    var methodName = args.shift();
-    try {
-        this[methodName].apply(this, args);
-        if (!this.controlTaken_)
-            this.reportOk_();
-    } catch (e) {
-        this.reportFailure_(e);
-    }
-};
-
-
-/**
- * Wrap an async method with TestBase.{takeControl(), releaseControl()}
- * and invoke TestBase.reportOk_ upon completion.
- * @param {Array<string>} args method name followed by its parameters.
- */
-WebInspector.TestBase.prototype.waitForAsync = function(var_args)
-{
-    var args = Array.prototype.slice.call(arguments);
-    this.takeControl();
-    args.push(this.releaseControl.bind(this));
-    this.dispatch(args);
-};
-
-/**
- * Overrides the method with specified name until it's called first time.
- * @param {!Object} receiver An object whose method to override.
- * @param {string} methodName Name of the method to override.
- * @param {!Function} override A function that should be called right after the
- *     overridden method returns.
- * @param {?boolean} opt_sticky Whether restore original method after first run
- *     or not.
- */
-WebInspector.TestBase.prototype.addSniffer = function(receiver, methodName, override, opt_sticky)
-{
-    var orig = receiver[methodName];
-    if (typeof orig !== "function")
-        this.fail("Cannot find method to override: " + methodName);
-    var test = this;
-    receiver[methodName] = function(var_args) {
-        try {
-            var result = orig.apply(this, arguments);
-        } finally {
-            if (!opt_sticky)
-                receiver[methodName] = orig;
-        }
-        // In case of exception the override won't be called.
-        try {
-            override.apply(this, arguments);
-        } catch (e) {
-            test.fail("Exception in overriden method '" + methodName + "': " + e);
-        }
-        return result;
-    };
-};
-
-/**
- * Waits for current throttler invocations, if any.
- * @param {!WebInspector.Throttler} throttler
- * @param {function()} callback
- */
-WebInspector.TestBase.prototype.waitForThrottler = function(throttler, callback)
-{
-    var test = this;
-    var scheduleShouldFail = true;
-    test.addSniffer(throttler, "schedule", onSchedule);
-
-    function hasSomethingScheduled()
-    {
-        return throttler._isRunningProcess || throttler._process;
-    }
-
-    function checkState()
-    {
-        if (!hasSomethingScheduled()) {
-            scheduleShouldFail = false;
-            callback();
-            return;
-        }
-
-        test.addSniffer(throttler, "_processCompletedForTests", checkState);
-    }
-
-    function onSchedule()
-    {
-        if (scheduleShouldFail)
-            test.fail("Unexpected Throttler.schedule");
-    }
-
-    checkState();
-};
diff --git a/third_party/WebKit/Source/devtools/front_end/common/module.json b/third_party/WebKit/Source/devtools/front_end/common/module.json
index fc9ec62..2b04f326 100644
--- a/third_party/WebKit/Source/devtools/front_end/common/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/common/module.json
@@ -19,15 +19,11 @@
         "StaticContentProvider.js",
         "OutputStream.js",
         "SegmentedRange.js",
-        "TestBase.js",
         "Text.js",
         "TextRange.js",
         "TextUtils.js",
         "Throttler.js",
         "UIString.js",
         "ModuleExtensionInterfaces.js"
-    ],
-    "skip_compilation": [
-        "TestBase.js"
     ]
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/devtools.js b/third_party/WebKit/Source/devtools/front_end/devtools.js
index 9da83256..d33064d 100644
--- a/third_party/WebKit/Source/devtools/front_end/devtools.js
+++ b/third_party/WebKit/Source/devtools/front_end/devtools.js
@@ -675,6 +675,14 @@
 
     /**
      * @override
+     */
+    readyForTest: function()
+    {
+        DevToolsAPI.sendMessageToEmbedder("readyForTest", [], null);
+    },
+
+    /**
+     * @override
      * @param {boolean} discoverUsbDevices
      * @param {boolean} portForwardingEnabled
      * @param {!Adb.PortForwardingConfig} portForwardingConfig
@@ -1020,35 +1028,6 @@
 else
     window.addEventListener("DOMContentLoaded", windowLoaded, false);
 
-// UITests ------------------------------------------------------------------
-
-if (window.domAutomationController) {
-    var uiTests = {};
-
-    uiTests._dispatchIfReady = function()
-    {
-        if (uiTests._testSuite && uiTests._pendingDispatchArgs) {
-            var args = uiTests._pendingDispatchArgs;
-            delete uiTests._pendingDispatchArgs;
-            uiTests._testSuite.dispatch(args);
-        }
-    }
-
-    uiTests.dispatchOnTestSuite = function(args)
-    {
-        uiTests._pendingDispatchArgs = args;
-        uiTests._dispatchIfReady();
-    };
-
-    uiTests.testSuiteReady = function(testSuiteConstructor)
-    {
-        uiTests._testSuite = testSuiteConstructor(window.domAutomationController);
-        uiTests._dispatchIfReady();
-    };
-
-    window.uiTests = uiTests;
-}
-
 })(window);
 
 if (!DOMTokenList.prototype.__originalDOMTokenListToggle) {
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
index 40ced1c..299c2fa 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -769,7 +769,7 @@
         items.push(backgroundButton);
 
         if (rule) {
-            var newRuleButton = new WebInspector.ToolbarButton(WebInspector.UIString("Insert Style Rule"), "add-toolbar-item");
+            var newRuleButton = new WebInspector.ToolbarButton(WebInspector.UIString("Insert Style Rule Below"), "add-toolbar-item");
             newRuleButton.addEventListener("click", this._onNewRuleClick.bind(this));
             items.push(newRuleButton);
         }
diff --git a/third_party/WebKit/Source/devtools/front_end/formatter_worker/CSSFormatter.js b/third_party/WebKit/Source/devtools/front_end/formatter_worker/CSSFormatter.js
index eb82550..5743e0d 100644
--- a/third_party/WebKit/Source/devtools/front_end/formatter_worker/CSSFormatter.js
+++ b/third_party/WebKit/Source/devtools/front_end/formatter_worker/CSSFormatter.js
@@ -30,14 +30,14 @@
 
 /**
  * @constructor
- * @param {!FormatterWorker.FormattedContentBuilder} builder
+ * @param {!WebInspector.FormattedContentBuilder} builder
  */
-FormatterWorker.CSSFormatter = function(builder)
+WebInspector.CSSFormatter = function(builder)
 {
     this._builder = builder;
 }
 
-FormatterWorker.CSSFormatter.prototype = {
+WebInspector.CSSFormatter.prototype = {
     /**
      * @param {string} text
      * @param {!Array.<number>} lineEndings
@@ -51,7 +51,7 @@
         this._toOffset = toOffset;
         this._lastLine = -1;
         this._state = {};
-        var tokenize = FormatterWorker.createTokenizer("text/css");
+        var tokenize = WebInspector.createTokenizer("text/css");
         tokenize(text.substring(this._fromOffset, this._toOffset), this._tokenCallback.bind(this));
     },
 
diff --git a/third_party/WebKit/Source/devtools/front_end/formatter_worker/CSSRuleParser.js b/third_party/WebKit/Source/devtools/front_end/formatter_worker/CSSRuleParser.js
index c4b4dc9..7240a11 100644
--- a/third_party/WebKit/Source/devtools/front_end/formatter_worker/CSSRuleParser.js
+++ b/third_party/WebKit/Source/devtools/front_end/formatter_worker/CSSRuleParser.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-FormatterWorker.CSSParserStates = {
+WebInspector.CSSParserStates = {
     Initial: "Initial",
     Selector: "Selector",
     Style: "Style",
@@ -11,19 +11,26 @@
     AtRule: "AtRule"
 };
 
-FormatterWorker.parseCSS = function(params)
+/**
+ * @param {string} text
+ */
+WebInspector.parseCSS = function(text)
 {
-    FormatterWorker._innerParseCSS(params.content, postMessage);
+    WebInspector._innerParseCSS(text, postMessage);
 }
 
-FormatterWorker._innerParseCSS = function(text, chunkCallback)
+/**
+ * @param {string} text
+ * @param {function(*)} chunkCallback
+ */
+WebInspector._innerParseCSS = function(text, chunkCallback)
 {
     var chunkSize = 100000; // characters per data chunk
     var lines = text.split("\n");
     var rules = [];
     var processedChunkCharacters = 0;
 
-    var state = FormatterWorker.CSSParserStates.Initial;
+    var state = WebInspector.CSSParserStates.Initial;
     var rule;
     var property;
     var UndefTokenType = {};
@@ -44,7 +51,7 @@
     {
         var tokenType = tokenTypes ? tokenTypes.split(" ").keySet() : UndefTokenType;
         switch (state) {
-        case FormatterWorker.CSSParserStates.Initial:
+        case WebInspector.CSSParserStates.Initial:
             if (tokenType["qualifier"] || tokenType["builtin"] || tokenType["tag"]) {
                 rule = {
                     selectorText: tokenValue,
@@ -52,35 +59,35 @@
                     columnNumber: column,
                     properties: [],
                 };
-                state = FormatterWorker.CSSParserStates.Selector;
+                state = WebInspector.CSSParserStates.Selector;
             } else if (tokenType["def"]) {
                 rule = {
                     atRule: tokenValue,
                     lineNumber: lineNumber,
                     columnNumber: column,
                 };
-                state = FormatterWorker.CSSParserStates.AtRule;
+                state = WebInspector.CSSParserStates.AtRule;
             }
             break;
-        case FormatterWorker.CSSParserStates.Selector:
+        case WebInspector.CSSParserStates.Selector:
             if (tokenValue === "{" && tokenType === UndefTokenType) {
                 rule.selectorText = rule.selectorText.trim();
                 rule.styleRange = createRange(lineNumber, newColumn);
-                state = FormatterWorker.CSSParserStates.Style;
+                state = WebInspector.CSSParserStates.Style;
             } else {
                 rule.selectorText += tokenValue;
             }
             break;
-        case FormatterWorker.CSSParserStates.AtRule:
+        case WebInspector.CSSParserStates.AtRule:
             if ((tokenValue === ";" || tokenValue === "{") && tokenType === UndefTokenType) {
                 rule.atRule = rule.atRule.trim();
                 rules.push(rule);
-                state = FormatterWorker.CSSParserStates.Initial;
+                state = WebInspector.CSSParserStates.Initial;
             } else {
                 rule.atRule += tokenValue;
             }
             break;
-        case FormatterWorker.CSSParserStates.Style:
+        case WebInspector.CSSParserStates.Style:
             if (tokenType["meta"] || tokenType["property"]) {
                 property = {
                     name: tokenValue,
@@ -88,12 +95,12 @@
                     range: createRange(lineNumber, column),
                     nameRange: createRange(lineNumber, column)
                 };
-                state = FormatterWorker.CSSParserStates.PropertyName;
+                state = WebInspector.CSSParserStates.PropertyName;
             } else if (tokenValue === "}" && tokenType === UndefTokenType) {
                 rule.styleRange.endLine = lineNumber;
                 rule.styleRange.endColumn = column;
                 rules.push(rule);
-                state = FormatterWorker.CSSParserStates.Initial;
+                state = WebInspector.CSSParserStates.Initial;
             } else if (tokenType["comment"]) {
                 // The |processToken| is called per-line, so no token spans more then one line.
                 // Support only a one-line comments.
@@ -102,7 +109,7 @@
                 var uncommentedText = tokenValue.substring(2, tokenValue.length - 2);
                 var fakeRule = "a{\n" + uncommentedText + "}";
                 disabledRules = [];
-                FormatterWorker._innerParseCSS(fakeRule, disabledRulesCallback);
+                WebInspector._innerParseCSS(fakeRule, disabledRulesCallback);
                 if (disabledRules.length === 1 && disabledRules[0].properties.length === 1) {
                     var disabledProperty = disabledRules[0].properties[0];
                     disabledProperty.disabled = true;
@@ -122,18 +129,18 @@
                 }
             }
             break;
-        case FormatterWorker.CSSParserStates.PropertyName:
+        case WebInspector.CSSParserStates.PropertyName:
             if (tokenValue === ":" && tokenType === UndefTokenType) {
                 property.name = property.name;
                 property.nameRange.endLine = lineNumber;
                 property.nameRange.endColumn = column;
                 property.valueRange = createRange(lineNumber, newColumn);
-                state = FormatterWorker.CSSParserStates.PropertyValue;
+                state = WebInspector.CSSParserStates.PropertyValue;
             } else if (tokenType["property"]) {
                 property.name += tokenValue;
             }
             break;
-        case FormatterWorker.CSSParserStates.PropertyValue:
+        case WebInspector.CSSParserStates.PropertyValue:
             if ((tokenValue === ";" || tokenValue === "}") && tokenType === UndefTokenType) {
                 property.value = property.value;
                 property.valueRange.endLine = lineNumber;
@@ -145,9 +152,9 @@
                     rule.styleRange.endLine = lineNumber;
                     rule.styleRange.endColumn = column;
                     rules.push(rule);
-                    state = FormatterWorker.CSSParserStates.Initial;
+                    state = WebInspector.CSSParserStates.Initial;
                 } else {
-                    state = FormatterWorker.CSSParserStates.Style;
+                    state = WebInspector.CSSParserStates.Style;
                 }
             } else if (!tokenType["comment"]) {
                 property.value += tokenValue;
@@ -163,7 +170,7 @@
             processedChunkCharacters = 0;
         }
     }
-    var tokenizer = FormatterWorker.createTokenizer("text/css");
+    var tokenizer = WebInspector.createTokenizer("text/css");
     var lineNumber;
     for (lineNumber = 0; lineNumber < lines.length; ++lineNumber) {
         var line = lines[lineNumber];
diff --git a/third_party/WebKit/Source/devtools/front_end/formatter_worker/FormattedContentBuilder.js b/third_party/WebKit/Source/devtools/front_end/formatter_worker/FormattedContentBuilder.js
index d232481f..4a5428be 100644
--- a/third_party/WebKit/Source/devtools/front_end/formatter_worker/FormattedContentBuilder.js
+++ b/third_party/WebKit/Source/devtools/front_end/formatter_worker/FormattedContentBuilder.js
@@ -6,7 +6,7 @@
  * @constructor
  * @param {string} indentString
  */
-FormatterWorker.FormattedContentBuilder = function(indentString)
+WebInspector.FormattedContentBuilder = function(indentString)
 {
     this._lastOriginalPosition = 0;
 
@@ -28,7 +28,7 @@
     this._hardSpaces = 0;
 }
 
-FormatterWorker.FormattedContentBuilder.prototype = {
+WebInspector.FormattedContentBuilder.prototype = {
     /**
      * @param {string} token
      * @param {number} startPosition
diff --git a/third_party/WebKit/Source/devtools/front_end/formatter_worker/FormatterWorker.js b/third_party/WebKit/Source/devtools/front_end/formatter_worker/FormatterWorker.js
index d63a4f9..4d22f1b 100644
--- a/third_party/WebKit/Source/devtools/front_end/formatter_worker/FormatterWorker.js
+++ b/third_party/WebKit/Source/devtools/front_end/formatter_worker/FormatterWorker.js
@@ -27,87 +27,83 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-var FormatterWorker = {
-    /**
-     * @param {string} mimeType
-     * @return {function(string, function(string, ?string, number, number):(!Object|undefined))}
-     */
-    createTokenizer: function(mimeType)
-    {
-        var mode = CodeMirror.getMode({indentUnit: 2}, mimeType);
-        var state = CodeMirror.startState(mode);
-        /**
-         * @param {string} line
-         * @param {function(string, ?string, number, number):?} callback
-         */
-        function tokenize(line, callback)
-        {
-            var stream = new CodeMirror.StringStream(line);
-            while (!stream.eol()) {
-                var style = mode.token(stream, state);
-                var value = stream.current();
-                if (callback(value, style, stream.start, stream.start + value.length) === FormatterWorker.AbortTokenization)
-                    return;
-                stream.start = stream.pos;
-            }
-        }
-        return tokenize;
-    }
-};
-
-FormatterWorker.AbortTokenization = {};
 
 /**
- * @typedef {{indentString: string, content: string, mimeType: string}}
+ * @param {string} mimeType
+ * @return {function(string, function(string, ?string, number, number):(!Object|undefined))}
  */
-var FormatterParameters;
+WebInspector.createTokenizer = function(mimeType)
+{
+    var mode = CodeMirror.getMode({indentUnit: 2}, mimeType);
+    var state = CodeMirror.startState(mode);
+    /**
+     * @param {string} line
+     * @param {function(string, ?string, number, number):?} callback
+     */
+    function tokenize(line, callback)
+    {
+        var stream = new CodeMirror.StringStream(line);
+        while (!stream.eol()) {
+            var style = mode.token(stream, state);
+            var value = stream.current();
+            if (callback(value, style, stream.start, stream.start + value.length) === WebInspector.AbortTokenization)
+                return;
+            stream.start = stream.pos;
+        }
+    }
+    return tokenize;
+}
+
+WebInspector.AbortTokenization = {};
 
 self.onmessage = function(event) {
-    var data = /** @type !{method: string, params: !FormatterParameters} */ (event.data);
-    if (!data.method)
+    var method = /** @type {string} */(event.data.method);
+    var params = /** @type !{indentString: string, content: string, mimeType: string} */ (event.data.params);
+    if (!method)
         return;
 
-    switch (data.method) {
+    switch (method) {
     case "format":
-        FormatterWorker.format(data.params);
+        WebInspector.format(params.mimeType, params.content, params.indentString);
         break;
     case "parseCSS":
-        FormatterWorker.parseCSS(data.params);
+        WebInspector.parseCSS(params.content);
         break;
     case "javaScriptOutline":
-        FormatterWorker.javaScriptOutline(data.params);
+        WebInspector.javaScriptOutline(params.content);
         break;
     default:
-        console.error("Unsupport method name: " + data.method);
+        console.error("Unsupport method name: " + method);
     }
 };
 
 /**
- * @param {!FormatterParameters} params
+ * @param {string} mimeType
+ * @param {string} text
+ * @param {string=} indentString
  */
-FormatterWorker.format = function(params)
+WebInspector.format = function(mimeType, text, indentString)
 {
     // Default to a 4-space indent.
-    var indentString = params.indentString || "    ";
+    indentString = indentString || "    ";
     var result = {};
-    var builder = new FormatterWorker.FormattedContentBuilder(indentString);
-    var text = params.content;
+    var builder = new WebInspector.FormattedContentBuilder(indentString);
     var lineEndings = text.computeLineEndings();
     try {
-        switch (params.mimeType) {
+        switch (mimeType) {
         case "text/html":
             formatMixedHTML(builder, text, lineEndings);
             break;
         case "text/css":
-            var formatter = new FormatterWorker.CSSFormatter(builder);
+            var formatter = new WebInspector.CSSFormatter(builder);
             formatter.format(text, lineEndings, 0, text.length);
             break;
         case "text/javascript":
-            var formatter = new FormatterWorker.JavaScriptFormatter(builder);
+            var formatter = new WebInspector.JavaScriptFormatter(builder);
             formatter.format(text, lineEndings, 0, text.length);
             break;
         default:
-            var formatter = new FormatterWorker.IdentityFormatter(builder);
+            var formatter = new WebInspector.IdentityFormatter(builder);
             formatter.format(text, lineEndings, 0, text.length);
         }
         result.mapping = builder.mapping();
@@ -121,16 +117,16 @@
 }
 
 /**
- * @param {!FormatterWorker.FormattedContentBuilder} builder
+ * @param {!WebInspector.FormattedContentBuilder} builder
  * @param {string} text
  * @param {!Array<number>} lineEndings
  */
 function formatMixedHTML(builder, text, lineEndings)
 {
-    var htmlFormatter = new FormatterWorker.HTMLFormatter(builder);
-    var jsFormatter = new FormatterWorker.JavaScriptFormatter(builder);
-    var cssFormatter = new FormatterWorker.CSSFormatter(builder);
-    var identityFormatter = new FormatterWorker.IdentityFormatter(builder);
+    var htmlFormatter = new WebInspector.HTMLFormatter(builder);
+    var jsFormatter = new WebInspector.JavaScriptFormatter(builder);
+    var cssFormatter = new WebInspector.CSSFormatter(builder);
+    var identityFormatter = new WebInspector.IdentityFormatter(builder);
 
     var offset = 0;
     while (offset < text.length) {
diff --git a/third_party/WebKit/Source/devtools/front_end/formatter_worker/HTMLFormatter.js b/third_party/WebKit/Source/devtools/front_end/formatter_worker/HTMLFormatter.js
index 54ca418..ab7f46a 100644
--- a/third_party/WebKit/Source/devtools/front_end/formatter_worker/HTMLFormatter.js
+++ b/third_party/WebKit/Source/devtools/front_end/formatter_worker/HTMLFormatter.js
@@ -4,9 +4,9 @@
 
 /**
  * @constructor
- * @param {!FormatterWorker.FormattedContentBuilder} builder
+ * @param {!WebInspector.FormattedContentBuilder} builder
  */
-FormatterWorker.HTMLFormatter = function(builder)
+WebInspector.HTMLFormatter = function(builder)
 {
     this._builder = builder;
 }
@@ -16,18 +16,18 @@
  * @param {string} tagName
  * @param {number} offset
  */
-FormatterWorker.HTMLFormatter.Result = function(tagName, offset)
+WebInspector.HTMLFormatter.Result = function(tagName, offset)
 {
     this.tagName = tagName;
     this.offset = offset;
 }
 
-FormatterWorker.HTMLFormatter.prototype = {
+WebInspector.HTMLFormatter.prototype = {
     /**
      * @param {string} text
      * @param {!Array<number>} lineEndings
      * @param {number} fromOffset
-     * @return {!FormatterWorker.HTMLFormatter.Result}
+     * @return {!WebInspector.HTMLFormatter.Result}
      */
     format: function(text, lineEndings, fromOffset)
     {
@@ -42,7 +42,7 @@
          * @param {number} tokenStart
          * @param {number} tokenEnd
          * @return {(!Object|undefined)}
-         * @this {FormatterWorker.HTMLFormatter}
+         * @this {WebInspector.HTMLFormatter}
          */
         function processToken(tokenValue, type, tokenStart, tokenEnd)
         {
@@ -65,15 +65,15 @@
             }
 
             if (tagName && tokenValue === ">")
-                return FormatterWorker.AbortTokenization;
+                return WebInspector.AbortTokenization;
 
             accumulatedTokenValue = accumulatedTokenValue + tokenValue.toLowerCase();
             if (accumulatedTokenValue === "<script" || accumulatedTokenValue === "<style")
                 tagName = accumulatedTokenValue.substring(1);
             accumulatedTokenValue = "";
         }
-        var tokenizer = FormatterWorker.createTokenizer("text/html");
+        var tokenizer = WebInspector.createTokenizer("text/html");
         tokenizer(content, processToken.bind(this));
-        return new FormatterWorker.HTMLFormatter.Result(tagName, lastOffset);
+        return new WebInspector.HTMLFormatter.Result(tagName, lastOffset);
     },
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/formatter_worker/IdentityFormatter.js b/third_party/WebKit/Source/devtools/front_end/formatter_worker/IdentityFormatter.js
index fa0c2d41..bafb5f2 100644
--- a/third_party/WebKit/Source/devtools/front_end/formatter_worker/IdentityFormatter.js
+++ b/third_party/WebKit/Source/devtools/front_end/formatter_worker/IdentityFormatter.js
@@ -4,14 +4,14 @@
 
 /**
  * @constructor
- * @param {!FormatterWorker.FormattedContentBuilder} builder
+ * @param {!WebInspector.FormattedContentBuilder} builder
  */
-FormatterWorker.IdentityFormatter = function(builder)
+WebInspector.IdentityFormatter = function(builder)
 {
     this._builder = builder;
 }
 
-FormatterWorker.IdentityFormatter.prototype = {
+WebInspector.IdentityFormatter.prototype = {
     /**
      * @param {string} text
      * @param {!Array<number>} lineEndings
diff --git a/third_party/WebKit/Source/devtools/front_end/formatter_worker/JavaScriptFormatter.js b/third_party/WebKit/Source/devtools/front_end/formatter_worker/JavaScriptFormatter.js
index ac3093e..7a8c611a 100644
--- a/third_party/WebKit/Source/devtools/front_end/formatter_worker/JavaScriptFormatter.js
+++ b/third_party/WebKit/Source/devtools/front_end/formatter_worker/JavaScriptFormatter.js
@@ -30,14 +30,14 @@
 
 /**
  * @constructor
- * @param {!FormatterWorker.FormattedContentBuilder} builder
+ * @param {!WebInspector.FormattedContentBuilder} builder
  */
-FormatterWorker.JavaScriptFormatter = function(builder)
+WebInspector.JavaScriptFormatter = function(builder)
 {
     this._builder = builder;
 }
 
-FormatterWorker.JavaScriptFormatter.prototype = {
+WebInspector.JavaScriptFormatter.prototype = {
     /**
      * @param {string} text
      * @param {!Array<number>} lineEndings
diff --git a/third_party/WebKit/Source/devtools/front_end/formatter_worker/JavaScriptOutline.js b/third_party/WebKit/Source/devtools/front_end/formatter_worker/JavaScriptOutline.js
index 36868df5..b709232 100644
--- a/third_party/WebKit/Source/devtools/front_end/formatter_worker/JavaScriptOutline.js
+++ b/third_party/WebKit/Source/devtools/front_end/formatter_worker/JavaScriptOutline.js
@@ -3,9 +3,9 @@
 // found in the LICENSE file.
 
 /**
- * @param {!Object} params
+ * @param {string} content
  */
-FormatterWorker.javaScriptOutline = function(params)
+WebInspector.javaScriptOutline = function(content)
 {
     var chunkSize = 100000; // characters per data chunk
     var outlineChunk = [];
@@ -16,7 +16,7 @@
     var isReadingArguments = false;
     var argumentsText = "";
     var currentFunction = null;
-    var tokenizer = new WebInspector.AcornTokenizer(params.content);
+    var tokenizer = new WebInspector.AcornTokenizer(content);
     var AT = WebInspector.AcornTokenizer;
 
     while (tokenizer.peekToken()) {
@@ -24,7 +24,7 @@
         if (AT.lineComment(token) || AT.blockComment(token))
             continue;
 
-        var tokenValue = params.content.substring(token.start, token.end);
+        var tokenValue = content.substring(token.start, token.end);
 
         if (AT.identifier(token) && previousToken && (AT.identifier(previousToken, "get") || AT.identifier(previousToken, "set"))) {
             currentFunction = {
diff --git a/third_party/WebKit/Source/devtools/front_end/host/InspectorFrontendHost.js b/third_party/WebKit/Source/devtools/front_end/host/InspectorFrontendHost.js
index 5fc21beb..35e2642e 100644
--- a/third_party/WebKit/Source/devtools/front_end/host/InspectorFrontendHost.js
+++ b/third_party/WebKit/Source/devtools/front_end/host/InspectorFrontendHost.js
@@ -383,6 +383,13 @@
 
     /**
      * @override
+     */
+    readyForTest: function()
+    {
+    },
+
+    /**
+     * @override
      * @param {boolean} discoverUsbDevices
      * @param {boolean} portForwardingEnabled
      * @param {!Adb.PortForwardingConfig} portForwardingConfig
diff --git a/third_party/WebKit/Source/devtools/front_end/host/InspectorFrontendHostAPI.js b/third_party/WebKit/Source/devtools/front_end/host/InspectorFrontendHostAPI.js
index 738c61b6..e435dda 100644
--- a/third_party/WebKit/Source/devtools/front_end/host/InspectorFrontendHostAPI.js
+++ b/third_party/WebKit/Source/devtools/front_end/host/InspectorFrontendHostAPI.js
@@ -292,6 +292,8 @@
      */
     isUnderTest: function() { },
 
+    readyForTest: function() { },
+
     /**
      * @return {boolean}
      */
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js
index f7b22fc..0442864 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/Main.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -328,7 +328,7 @@
         function inspectorAgentEnableCallback()
         {
             console.timeStamp("Main.inspectorAgentEnableCallback");
-            WebInspector.notifications.dispatchEventToListeners(WebInspector.NotificationService.Events.InspectorAgentEnabledForTests);
+            InspectorFrontendHost.readyForTest();
             // Asynchronously run the extensions.
             setTimeout(lateInitialization, 0);
         }
diff --git a/third_party/WebKit/Source/devtools/front_end/main/module.json b/third_party/WebKit/Source/devtools/front_end/main/module.json
index 3244c6a..6b1e3b9 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/main/module.json
@@ -355,14 +355,10 @@
         "FrontendWebSocketAPI.js",
         "RenderingOptions.js",
         "SimpleApp.js",
-        "Tests.js",
         "OverlayController.js",
         "Connections.js",
         "Main.js"
     ],
-    "skip_compilation": [
-        "Tests.js"
-    ],
     "resources": [
         "errorWarningCounter.css",
         "remoteDebuggingTerminatedScreen.css",
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
index 141eb0a..ddd650e 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
@@ -765,7 +765,7 @@
             for (var line of this._valueWidgets.keys())
                 toLine = Math.max(toLine, line + 1);
         }
-        if (fromLine >= toLine || toLine - fromLine > 500) {
+        if (fromLine >= toLine || toLine - fromLine > 500 || fromLine < 0 || toLine >= this.textEditor.linesCount) {
             this._clearValueWidgets();
             return;
         }
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineModel.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineModel.js
index 1f67829..243d057d 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineModel.js
@@ -1761,7 +1761,7 @@
                 }
                 for (var j = 0; j < node.positionTicks.length; ++j) {
                     var lineInfo = node.positionTicks[j];
-                    var line = lineInfo.line - 1;
+                    var line = lineInfo.line;
                     var time = lineInfo.ticks * sampleDuration;
                     fileInfo.set(line, (fileInfo.get(line) || 0) + time);
                 }
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
index b4d1109..a048529b 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
@@ -1269,14 +1269,20 @@
      */
     _setLineLevelCPUProfile: function(profile)
     {
+        var debuggerModel = WebInspector.DebuggerModel.fromTarget(WebInspector.targetManager.mainTarget());
+        if (!debuggerModel)
+            return;
         for (var fileInfo of profile.files()) {
-            var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(/** @type {string} */ (fileInfo[0]));
-            if (!uiSourceCode)
-                continue;
+            var url = /** @type {string} */ (fileInfo[0]);
+            var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(url);
             for (var lineInfo of fileInfo[1]) {
-                var line = lineInfo[0];
+                var line = lineInfo[0] - 1;
                 var time = lineInfo[1];
-                uiSourceCode.addLineDecoration(line, WebInspector.TimelineUIUtils.PerformanceLineDecorator.type, time);
+                var rawLocation = debuggerModel.createRawLocationByURL(url, line, 0);
+                if (rawLocation)
+                    new WebInspector.TimelineUIUtils.LineLevelProfilePresentation(rawLocation, time);
+                else if (uiSourceCode)
+                    uiSourceCode.addLineDecoration(line, WebInspector.TimelineUIUtils.PerformanceLineDecorator.type, time);
             }
         }
     },
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
index 8cc41a4..f9edcfb 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
@@ -2110,6 +2110,31 @@
 
 /**
  * @constructor
+ * @param {!WebInspector.DebuggerModel.Location} rawLocation
+ * @param {number} time
+ */
+WebInspector.TimelineUIUtils.LineLevelProfilePresentation = function(rawLocation, time)
+{
+    this._time = time;
+    WebInspector.debuggerWorkspaceBinding.createLiveLocation(rawLocation, this.updateLocation.bind(this));
+}
+
+WebInspector.TimelineUIUtils.LineLevelProfilePresentation.prototype = {
+    /**
+     * @param {!WebInspector.LiveLocation} liveLocation
+     */
+    updateLocation: function(liveLocation)
+    {
+        if (this._uiLocation)
+            this._uiLocation.uiSourceCode.removeLineDecoration(this._uiLocation.lineNumber, WebInspector.TimelineUIUtils.PerformanceLineDecorator.type);
+        this._uiLocation = liveLocation.uiLocation();
+        if (this._uiLocation)
+            this._uiLocation.uiSourceCode.addLineDecoration(this._uiLocation.lineNumber, WebInspector.TimelineUIUtils.PerformanceLineDecorator.type, this._time);
+    }
+}
+
+/**
+ * @constructor
  * @implements {WebInspector.UISourceCodeFrame.LineDecorator}
  */
 WebInspector.TimelineUIUtils.PerformanceLineDecorator = function()
@@ -2127,9 +2152,11 @@
     decorate: function(uiSourceCode, textEditor)
     {
         var type = WebInspector.TimelineUIUtils.PerformanceLineDecorator.type;
-        var decorations = uiSourceCode.lineDecorations(type) || [];
+        var decorations = uiSourceCode.lineDecorations(type);
         textEditor.resetGutterDecorations(type);
-        for (var decoration of decorations) {
+        if (!decorations)
+            return;
+        for (var decoration of decorations.values()) {
             var time = /** @type {number} */ (decoration.data());
             var text = WebInspector.UIString("%.1f\xa0ms", time);
             var intensity = Number.constrain(Math.log10(1 + 2 * time) / 5, 0.02, 1);
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/FlameChart.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/FlameChart.js
index 096d801..da1c28a 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/FlameChart.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/FlameChart.js
@@ -96,6 +96,8 @@
     this._windowRight = 1.0;
     this._timeWindowLeft = 0;
     this._timeWindowRight = Infinity;
+    this._rangeSelectionStart = 0;
+    this._rangeSelectionEnd = 0;
     this._barHeight = dataProvider.barHeight();
     this._paddingLeft = this._dataProvider.paddingLeft();
     var markerPadding = 2;
diff --git a/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js b/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
index 5e78d0a..e37d5c2 100644
--- a/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
+++ b/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
@@ -52,7 +52,7 @@
     this._requestContentCallback = null;
     /** @type {?Promise<?string>} */
     this._requestContentPromise = null;
-    /** @type {!Map<string, !Array<!WebInspector.UISourceCode.LineMarker>>} */
+    /** @type {!Map<string, !Map<number, !WebInspector.UISourceCode.LineMarker>>} */
     this._lineDecorations = new Map();
 
     /** @type {!Array.<!WebInspector.Revision>} */
@@ -657,27 +657,49 @@
     {
         var markers = this._lineDecorations.get(type);
         if (!markers) {
-            markers = [];
+            markers = new Map();
             this._lineDecorations.set(type, markers);
         }
         var marker = new WebInspector.UISourceCode.LineMarker(lineNumber, type, data);
-        markers.push(marker);
+        markers.set(lineNumber, marker);
         this.dispatchEventToListeners(WebInspector.UISourceCode.Events.LineDecorationAdded, marker);
     },
 
     /**
+     * @param {number} lineNumber
+     * @param {string} type
+     */
+    removeLineDecoration: function(lineNumber, type)
+    {
+        var markers = this._lineDecorations.get(type);
+        if (!markers)
+            return;
+        var marker = markers.get(lineNumber);
+        if (!marker)
+            return;
+        markers.delete(lineNumber);
+        this.dispatchEventToListeners(WebInspector.UISourceCode.Events.LineDecorationRemoved, marker);
+        if (!markers.size)
+            this._lineDecorations.delete(type);
+    },
+
+    /**
      * @param {string} type
      */
     removeAllLineDecorations: function(type)
     {
-        var markers = this._lineDecorations.get(type) || [];
-        markers.forEach(this.dispatchEventToListeners.bind(this, WebInspector.UISourceCode.Events.LineDecorationRemoved));
+        var markers = this._lineDecorations.get(type);
+        if (!markers)
+            return;
         this._lineDecorations.delete(type);
+        markers.forEach(marker => {
+            this.dispatchEventToListeners(WebInspector.UISourceCode.Events.LineDecorationRemoved, marker);
+        });
     },
 
     /**
      * @param {string} type
-     * @return {?Array<!WebInspector.UISourceCode.LineMarker>}
+     * @return {?Map<number, !WebInspector.UISourceCode.LineMarker>}
      */
     lineDecorations: function(type)
     {
diff --git a/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp b/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp
index fb30712..8fd87e2 100644
--- a/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp
+++ b/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp
@@ -8,7 +8,6 @@
 #include "platform/inspector_protocol/Dispatcher.h"
 #include "platform/inspector_protocol/TypeBuilder.h"
 #include "platform/inspector_protocol/Values.h"
-#include "platform/weborigin/DatabaseIdentifier.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/weborigin/SecurityOrigin.h"
 #include "public/platform/Platform.h"
diff --git a/third_party/WebKit/Source/modules/csspaint/DEPS b/third_party/WebKit/Source/modules/csspaint/DEPS
new file mode 100644
index 0000000..7648e43
--- /dev/null
+++ b/third_party/WebKit/Source/modules/csspaint/DEPS
@@ -0,0 +1,10 @@
+include_rules = [
+    "+third_party/WebKit/Source/bindings",
+    "+third_party/WebKit/Source/core",
+    "+third_party/WebKit/Source/platform/heap",
+    "-third_party/WebKit/Source/modules",
+    "+third_party/WebKit/Source/modules/csspaint",
+    "+third_party/WebKit/Source/modules/worklet",
+    "+third_party/WebKit/Source/platform",
+    "-third_party/WebKit/Source/web",
+]
diff --git a/third_party/WebKit/Source/modules/csspaint/OWNERS b/third_party/WebKit/Source/modules/csspaint/OWNERS
new file mode 100644
index 0000000..76ab6f5
--- /dev/null
+++ b/third_party/WebKit/Source/modules/csspaint/OWNERS
@@ -0,0 +1 @@
+ikilpatrick@chromium.org
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintWorklet.cpp b/third_party/WebKit/Source/modules/csspaint/PaintWorklet.cpp
new file mode 100644
index 0000000..c184100
--- /dev/null
+++ b/third_party/WebKit/Source/modules/csspaint/PaintWorklet.cpp
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/csspaint/PaintWorklet.h"
+
+#include "bindings/core/v8/V8Binding.h"
+#include "core/dom/ExecutionContext.h"
+#include "modules/csspaint/PaintWorkletGlobalScope.h"
+
+namespace blink {
+
+// static
+PaintWorklet* PaintWorklet::create(LocalFrame* frame, ExecutionContext* executionContext)
+{
+    PaintWorklet* worklet = new PaintWorklet(frame, executionContext);
+    worklet->suspendIfNeeded();
+    return worklet;
+}
+
+PaintWorklet::PaintWorklet(LocalFrame* frame, ExecutionContext* executionContext)
+    : Worklet(executionContext)
+    , m_paintWorkletGlobalScope(PaintWorkletGlobalScope::create(frame, executionContext->url(), executionContext->userAgent(), executionContext->getSecurityOrigin(), toIsolate(executionContext)))
+{
+}
+
+PaintWorklet::~PaintWorklet()
+{
+}
+
+DEFINE_TRACE(PaintWorklet)
+{
+    visitor->trace(m_paintWorkletGlobalScope);
+    Worklet::trace(visitor);
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintWorklet.h b/third_party/WebKit/Source/modules/csspaint/PaintWorklet.h
new file mode 100644
index 0000000..1bf6a69
--- /dev/null
+++ b/third_party/WebKit/Source/modules/csspaint/PaintWorklet.h
@@ -0,0 +1,31 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PaintWorklet_h
+#define PaintWorklet_h
+
+#include "modules/worklet/Worklet.h"
+#include "platform/heap/Handle.h"
+
+namespace blink {
+
+class PaintWorklet final : public Worklet {
+    WTF_MAKE_NONCOPYABLE(PaintWorklet);
+public:
+    static PaintWorklet* create(LocalFrame*, ExecutionContext*);
+    ~PaintWorklet() override;
+
+    WorkletGlobalScope* workletGlobalScope() const final { return m_paintWorkletGlobalScope.get(); }
+
+    DECLARE_VIRTUAL_TRACE();
+
+private:
+    PaintWorklet(LocalFrame*, ExecutionContext*);
+
+    RefPtrWillBeMember<WorkletGlobalScope> m_paintWorkletGlobalScope;
+};
+
+} // namespace blink
+
+#endif // PaintWorklet_h
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.cpp b/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.cpp
new file mode 100644
index 0000000..627f2ac
--- /dev/null
+++ b/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.cpp
@@ -0,0 +1,30 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/csspaint/PaintWorkletGlobalScope.h"
+
+#include "bindings/core/v8/WorkerOrWorkletScriptController.h"
+#include "core/inspector/MainThreadDebugger.h"
+
+namespace blink {
+
+// static
+PassRefPtrWillBeRawPtr<PaintWorkletGlobalScope> PaintWorkletGlobalScope::create(LocalFrame* frame, const KURL& url, const String& userAgent, PassRefPtr<SecurityOrigin> securityOrigin, v8::Isolate* isolate)
+{
+    RefPtrWillBeRawPtr<PaintWorkletGlobalScope> paintWorkletGlobalScope = adoptRefWillBeNoop(new PaintWorkletGlobalScope(frame, url, userAgent, securityOrigin, isolate));
+    paintWorkletGlobalScope->scriptController()->initializeContextIfNeeded();
+    MainThreadDebugger::contextCreated(paintWorkletGlobalScope->scriptController()->getScriptState(), paintWorkletGlobalScope->frame(), paintWorkletGlobalScope->getSecurityOrigin());
+    return paintWorkletGlobalScope.release();
+}
+
+PaintWorkletGlobalScope::PaintWorkletGlobalScope(LocalFrame* frame, const KURL& url, const String& userAgent, PassRefPtr<SecurityOrigin> securityOrigin, v8::Isolate* isolate)
+    : WorkletGlobalScope(frame, url, userAgent, securityOrigin, isolate)
+{
+}
+
+PaintWorkletGlobalScope::~PaintWorkletGlobalScope()
+{
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.h b/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.h
new file mode 100644
index 0000000..fb48bccd
--- /dev/null
+++ b/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.h
@@ -0,0 +1,31 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PaintWorkletGlobalScope_h
+#define PaintWorkletGlobalScope_h
+
+#include "bindings/core/v8/ScriptValue.h"
+#include "core/dom/ExecutionContext.h"
+#include "modules/worklet/WorkletGlobalScope.h"
+
+namespace blink {
+
+class PaintWorkletGlobalScope : public WorkletGlobalScope {
+    DEFINE_WRAPPERTYPEINFO();
+public:
+    static PassRefPtrWillBeRawPtr<PaintWorkletGlobalScope> create(LocalFrame*, const KURL&, const String& userAgent, PassRefPtr<SecurityOrigin>, v8::Isolate*);
+    ~PaintWorkletGlobalScope() override;
+
+    bool isPaintWorkletGlobalScope() const final { return true; }
+    void registerPaint(const String&, ScriptValue) { }
+
+private:
+    PaintWorkletGlobalScope(LocalFrame*, const KURL&, const String& userAgent, PassRefPtr<SecurityOrigin>, v8::Isolate*);
+};
+
+DEFINE_TYPE_CASTS(PaintWorkletGlobalScope, ExecutionContext, context, context->isPaintWorkletGlobalScope(), context.isPaintWorkletGlobalScope());
+
+} // namespace blink
+
+#endif // PaintWorkletGlobalScope_h
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.idl b/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.idl
new file mode 100644
index 0000000..ee716fa
--- /dev/null
+++ b/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.idl
@@ -0,0 +1,14 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://drafts.css-houdini.org/css-paint-api/#paintworkletglobalscope
+
+[
+    Exposed=PaintWorklet,
+    Global=(Worklet,PaintWorklet),
+    RuntimeEnabled=CSSPaintAPI,
+    WillBeGarbageCollected,
+] interface PaintWorkletGlobalScope : WorkletGlobalScope {
+    void registerPaint(DOMString name, Function paintCtor);
+};
diff --git a/third_party/WebKit/Source/modules/csspaint/WindowPaintWorklet.cpp b/third_party/WebKit/Source/modules/csspaint/WindowPaintWorklet.cpp
new file mode 100644
index 0000000..3e11656
--- /dev/null
+++ b/third_party/WebKit/Source/modules/csspaint/WindowPaintWorklet.cpp
@@ -0,0 +1,56 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/csspaint/WindowPaintWorklet.h"
+
+#include "core/frame/LocalDOMWindow.h"
+#include "core/frame/LocalFrame.h"
+#include "modules/csspaint/PaintWorklet.h"
+
+namespace blink {
+
+WindowPaintWorklet::WindowPaintWorklet(LocalDOMWindow& window)
+    : DOMWindowProperty(window.frame())
+{
+}
+
+DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(WindowPaintWorklet);
+
+const char* WindowPaintWorklet::supplementName()
+{
+    return "WindowPaintWorklet";
+}
+
+// static
+WindowPaintWorklet& WindowPaintWorklet::from(LocalDOMWindow& window)
+{
+    WindowPaintWorklet* supplement = static_cast<WindowPaintWorklet*>(WillBeHeapSupplement<LocalDOMWindow>::from(window, supplementName()));
+    if (!supplement) {
+        supplement = new WindowPaintWorklet(window);
+        provideTo(window, supplementName(), adoptPtrWillBeNoop(supplement));
+    }
+    return *supplement;
+}
+
+// static
+Worklet* WindowPaintWorklet::paintWorklet(ExecutionContext* executionContext, DOMWindow& window)
+{
+    return from(toLocalDOMWindow(window)).paintWorklet(executionContext);
+}
+
+PaintWorklet* WindowPaintWorklet::paintWorklet(ExecutionContext* executionContext) const
+{
+    if (!m_paintWorklet && frame())
+        m_paintWorklet = PaintWorklet::create(frame(), executionContext);
+    return m_paintWorklet.get();
+}
+
+DEFINE_TRACE(WindowPaintWorklet)
+{
+    visitor->trace(m_paintWorklet);
+    WillBeHeapSupplement<LocalDOMWindow>::trace(visitor);
+    DOMWindowProperty::trace(visitor);
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/modules/csspaint/WindowPaintWorklet.h b/third_party/WebKit/Source/modules/csspaint/WindowPaintWorklet.h
new file mode 100644
index 0000000..c69127a2
--- /dev/null
+++ b/third_party/WebKit/Source/modules/csspaint/WindowPaintWorklet.h
@@ -0,0 +1,39 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WindowPaintWorklet_h
+#define WindowPaintWorklet_h
+
+#include "core/frame/DOMWindowProperty.h"
+#include "platform/Supplementable.h"
+#include "platform/heap/Handle.h"
+
+namespace blink {
+
+class DOMWindow;
+class ExecutionContext;
+class PaintWorklet;
+class Worklet;
+
+class WindowPaintWorklet final : public NoBaseWillBeGarbageCollected<WindowPaintWorklet>, public WillBeHeapSupplement<LocalDOMWindow>, public DOMWindowProperty {
+    WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(WindowPaintWorklet);
+    DECLARE_EMPTY_VIRTUAL_DESTRUCTOR_WILL_BE_REMOVED(WindowPaintWorklet);
+    USING_FAST_MALLOC_WILL_BE_REMOVED(WindowPaintWorklet);
+public:
+    static WindowPaintWorklet& from(LocalDOMWindow&);
+    static Worklet* paintWorklet(ExecutionContext*, DOMWindow&);
+    PaintWorklet* paintWorklet(ExecutionContext*) const;
+
+    DECLARE_TRACE();
+
+private:
+    explicit WindowPaintWorklet(LocalDOMWindow&);
+    static const char* supplementName();
+
+    mutable PersistentWillBeMember<PaintWorklet> m_paintWorklet;
+};
+
+} // namespace blink
+
+#endif // WindowPaintWorklet_h
diff --git a/third_party/WebKit/Source/modules/csspaint/WindowPaintWorklet.idl b/third_party/WebKit/Source/modules/csspaint/WindowPaintWorklet.idl
new file mode 100644
index 0000000..d6ebafd
--- /dev/null
+++ b/third_party/WebKit/Source/modules/csspaint/WindowPaintWorklet.idl
@@ -0,0 +1,9 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+    RuntimeEnabled=CSSPaintAPI,
+] partial interface Window {
+    [CallWith=ExecutionContext] readonly attribute Worklet paintWorklet;
+};
diff --git a/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.cpp b/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.cpp
index 08b7cbf0..8fa8758a 100644
--- a/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.cpp
+++ b/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.cpp
@@ -41,10 +41,11 @@
 #include "modules/filesystem/FileWriterCallback.h"
 #include "modules/filesystem/MetadataCallback.h"
 #include "platform/FileMetadata.h"
-#include "platform/weborigin/DatabaseIdentifier.h"
 #include "platform/weborigin/SecurityOrigin.h"
+#include "public/platform/Platform.h"
 #include "public/platform/WebFileSystem.h"
 #include "public/platform/WebFileSystemCallbacks.h"
+#include "public/platform/WebSecurityOrigin.h"
 #include "wtf/OwnPtr.h"
 #include "wtf/text/StringBuilder.h"
 #include "wtf/text/WTFString.h"
@@ -65,7 +66,7 @@
         return 0;
 
     StringBuilder filesystemName;
-    filesystemName.append(createDatabaseIdentifierFromSecurityOrigin(context->getSecurityOrigin()));
+    filesystemName.append(Platform::current()->fileSystemCreateOriginIdentifier(WebSecurityOrigin(context->getSecurityOrigin())));
     filesystemName.appendLiteral(":Isolated_");
     filesystemName.append(filesystemId);
 
diff --git a/third_party/WebKit/Source/modules/modules.gypi b/third_party/WebKit/Source/modules/modules.gypi
index d05414d1..a16f6a0d 100644
--- a/third_party/WebKit/Source/modules/modules.gypi
+++ b/third_party/WebKit/Source/modules/modules.gypi
@@ -42,6 +42,7 @@
       'crypto/Crypto.idl',
       'crypto/CryptoKey.idl',
       'crypto/SubtleCrypto.idl',
+      'csspaint/PaintWorkletGlobalScope.idl',
       'device_light/DeviceLightEvent.idl',
       'device_orientation/DeviceAcceleration.idl',
       'device_orientation/DeviceMotionEvent.idl',
@@ -343,6 +344,7 @@
       'credentialmanager/NavigatorCredentials.idl',
       'crypto/WindowCrypto.idl',
       'crypto/WorkerGlobalScopeCrypto.idl',
+      'csspaint/WindowPaintWorklet.idl',
       'device_light/WindowDeviceLight.idl',
       'device_orientation/WindowDeviceMotion.idl',
       'device_orientation/WindowDeviceOrientation.idl',
@@ -407,7 +409,6 @@
       'webgl/WebGLRenderingContextBase.idl',
       'webmidi/NavigatorWebMIDI.idl',
       'webusb/NavigatorUSB.idl',
-      'worklet/WindowWorklet.idl',
     ],
     # interfaces that inherit from Event
     'modules_event_idl_files': [
@@ -924,6 +925,12 @@
       'crypto/SubtleCrypto.h',
       'crypto/WorkerGlobalScopeCrypto.cpp',
       'crypto/WorkerGlobalScopeCrypto.h',
+      'csspaint/PaintWorklet.cpp',
+      'csspaint/PaintWorklet.h',
+      'csspaint/PaintWorkletGlobalScope.cpp',
+      'csspaint/PaintWorkletGlobalScope.h',
+      'csspaint/WindowPaintWorklet.cpp',
+      'csspaint/WindowPaintWorklet.h',
       'device_light/DeviceLightController.cpp',
       'device_light/DeviceLightController.h',
       'device_light/DeviceLightDispatcher.cpp',
@@ -1477,6 +1484,8 @@
       'serviceworkers/ServiceWorkerContainer.h',
       'serviceworkers/ServiceWorkerContainerClient.cpp',
       'serviceworkers/ServiceWorkerContainerClient.h',
+      'serviceworkers/ServiceWorkerLinkResource.cpp',
+      'serviceworkers/ServiceWorkerLinkResource.h',
       'serviceworkers/ServiceWorkerWindowClient.cpp',
       'serviceworkers/ServiceWorkerWindowClient.h',
       'serviceworkers/ServiceWorkerWindowClientCallback.cpp',
@@ -1909,8 +1918,6 @@
       'webusb/USBIsochronousOutTransferPacket.h',
       'webusb/USBIsochronousOutTransferResult.h',
       'webusb/USBOutTransferResult.h',
-      'worklet/DOMWindowWorklet.cpp',
-      'worklet/DOMWindowWorklet.h',
       'worklet/Worklet.cpp',
       'worklet/Worklet.h',
       'worklet/WorkletConsole.cpp',
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
index 8603e878..ef8e865 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
@@ -75,7 +75,11 @@
     {
         if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContext()->activeDOMObjectsAreStopped())
             return;
-        m_resolver->reject(ServiceWorkerError::take(m_resolver.get(), error));
+        if (error.errorType == WebServiceWorkerError::ErrorTypeType) {
+            m_resolver->reject(V8ThrowException::createTypeError(m_resolver->getScriptState()->isolate(), error.message));
+        } else {
+            m_resolver->reject(ServiceWorkerError::take(m_resolver.get(), error));
+        }
     }
 
 private:
@@ -190,6 +194,61 @@
     ContextLifecycleObserver::trace(visitor);
 }
 
+void ServiceWorkerContainer::registerServiceWorkerImpl(ExecutionContext* executionContext, const KURL& rawScriptURL, const KURL& scope, PassOwnPtr<RegistrationCallbacks> callbacks)
+{
+    if (!m_provider) {
+        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeState, "Failed to register a ServiceWorker: The document is in an invalid state."));
+        return;
+    }
+
+    RefPtr<SecurityOrigin> documentOrigin = executionContext->getSecurityOrigin();
+    String errorMessage;
+    // Restrict to secure origins: https://w3c.github.io/webappsec/specs/powerfulfeatures/#settings-privileged
+    if (!executionContext->isSecureContext(errorMessage)) {
+        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, errorMessage));
+        return;
+    }
+
+    KURL pageURL = KURL(KURL(), documentOrigin->toString());
+    if (!SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(pageURL.protocol())) {
+        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The URL protocol of the current origin ('" + documentOrigin->toString() + "') is not supported.")));
+        return;
+    }
+
+    KURL scriptURL = rawScriptURL;
+    scriptURL.removeFragmentIdentifier();
+    if (!documentOrigin->canRequest(scriptURL)) {
+        RefPtr<SecurityOrigin> scriptOrigin = SecurityOrigin::create(scriptURL);
+        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The origin of the provided scriptURL ('" + scriptOrigin->toString() + "') does not match the current origin ('" + documentOrigin->toString() + "').")));
+        return;
+    }
+    if (!SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(scriptURL.protocol())) {
+        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The URL protocol of the script ('" + scriptURL.getString() + "') is not supported.")));
+        return;
+    }
+
+    KURL patternURL = scope;
+    patternURL.removeFragmentIdentifier();
+
+    if (!documentOrigin->canRequest(patternURL)) {
+        RefPtr<SecurityOrigin> patternOrigin = SecurityOrigin::create(patternURL);
+        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The origin of the provided scope ('" + patternOrigin->toString() + "') does not match the current origin ('" + documentOrigin->toString() + "').")));
+        return;
+    }
+    if (!SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(patternURL.protocol())) {
+        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The URL protocol of the scope ('" + patternURL.getString() + "') is not supported.")));
+        return;
+    }
+
+    WebString webErrorMessage;
+    if (!m_provider->validateScopeAndScriptURL(patternURL, scriptURL, &webErrorMessage)) {
+        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeType, WebString::fromUTF8("Failed to register a ServiceWorker: " + webErrorMessage.utf8())));
+        return;
+    }
+
+    m_provider->registerServiceWorker(patternURL, scriptURL, callbacks.leakPtr());
+}
+
 ScriptPromise ServiceWorkerContainer::registerServiceWorker(ScriptState* scriptState, const String& url, const RegistrationOptions& options)
 {
     ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
@@ -205,56 +264,16 @@
     if (!executionContext)
         return ScriptPromise();
 
-    RefPtr<SecurityOrigin> documentOrigin = executionContext->getSecurityOrigin();
-    String errorMessage;
-    // Restrict to secure origins: https://w3c.github.io/webappsec/specs/powerfulfeatures/#settings-privileged
-    if (!executionContext->isSecureContext(errorMessage)) {
-        resolver->reject(DOMException::create(SecurityError, errorMessage));
-        return promise;
-    }
-
-    KURL pageURL = KURL(KURL(), documentOrigin->toString());
-    if (!SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(pageURL.protocol())) {
-        resolver->reject(DOMException::create(SecurityError, "Failed to register a ServiceWorker: The URL protocol of the current origin ('" + documentOrigin->toString() + "') is not supported."));
-        return promise;
-    }
-
     KURL scriptURL = enteredExecutionContext(scriptState->isolate())->completeURL(url);
     scriptURL.removeFragmentIdentifier();
-    if (!documentOrigin->canRequest(scriptURL)) {
-        RefPtr<SecurityOrigin> scriptOrigin = SecurityOrigin::create(scriptURL);
-        resolver->reject(DOMException::create(SecurityError, "Failed to register a ServiceWorker: The origin of the provided scriptURL ('" + scriptOrigin->toString() + "') does not match the current origin ('" + documentOrigin->toString() + "')."));
-        return promise;
-    }
-    if (!SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(scriptURL.protocol())) {
-        resolver->reject(DOMException::create(SecurityError, "Failed to register a ServiceWorker: The URL protocol of the script ('" + scriptURL.getString() + "') is not supported."));
-        return promise;
-    }
 
     KURL patternURL;
     if (options.scope().isNull())
         patternURL = KURL(scriptURL, "./");
     else
         patternURL = enteredExecutionContext(scriptState->isolate())->completeURL(options.scope());
-    patternURL.removeFragmentIdentifier();
 
-    if (!documentOrigin->canRequest(patternURL)) {
-        RefPtr<SecurityOrigin> patternOrigin = SecurityOrigin::create(patternURL);
-        resolver->reject(DOMException::create(SecurityError, "Failed to register a ServiceWorker: The origin of the provided scope ('" + patternOrigin->toString() + "') does not match the current origin ('" + documentOrigin->toString() + "')."));
-        return promise;
-    }
-    if (!SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(patternURL.protocol())) {
-        resolver->reject(DOMException::create(SecurityError, "Failed to register a ServiceWorker: The URL protocol of the scope ('" + patternURL.getString() + "') is not supported."));
-        return promise;
-    }
-
-    WebString webErrorMessage;
-    if (!m_provider->validateScopeAndScriptURL(patternURL, scriptURL, &webErrorMessage)) {
-        resolver->reject(V8ThrowException::createTypeError(scriptState->isolate(), WebString::fromUTF8("Failed to register a ServiceWorker: " + webErrorMessage.utf8())));
-        return promise;
-    }
-
-    m_provider->registerServiceWorker(patternURL, scriptURL, new RegistrationCallback(resolver));
+    registerServiceWorkerImpl(executionContext, scriptURL, patternURL, adoptPtr(new RegistrationCallback(resolver)));
 
     return promise;
 }
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.h
index 6365407..3085f51 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.h
@@ -41,6 +41,7 @@
 #include "modules/serviceworkers/ServiceWorker.h"
 #include "modules/serviceworkers/ServiceWorkerRegistration.h"
 #include "platform/heap/Handle.h"
+#include "public/platform/modules/serviceworker/WebServiceWorkerProvider.h"
 #include "public/platform/modules/serviceworker/WebServiceWorkerProviderClient.h"
 #include "wtf/Forward.h"
 
@@ -59,6 +60,8 @@
     REFCOUNTED_GARBAGE_COLLECTED_EVENT_TARGET(ServiceWorkerContainer);
     WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(ServiceWorkerContainer);
 public:
+    using RegistrationCallbacks = WebServiceWorkerProvider::WebServiceWorkerRegistrationCallbacks;
+
     static ServiceWorkerContainer* create(ExecutionContext*);
     ~ServiceWorkerContainer();
 
@@ -70,6 +73,8 @@
     ScriptPromise ready(ScriptState*);
     WebServiceWorkerProvider* provider() { return m_provider; }
 
+    void registerServiceWorkerImpl(ExecutionContext*, const KURL& scriptURL, const KURL& scope, PassOwnPtr<RegistrationCallbacks>);
+
     ScriptPromise registerServiceWorker(ScriptState*, const String& pattern, const RegistrationOptions&);
     ScriptPromise getRegistration(ScriptState*, const String& documentURL);
     ScriptPromise getRegistrations(ScriptState*);
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp
index e504adf..4a376381 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp
@@ -73,6 +73,10 @@
         return createException(AbortError, "The Service Worker operation timed out.", webError.message);
     case WebServiceWorkerError::ErrorTypeUnknown:
         return createException(UnknownError, "An unknown error occurred within Service Worker.", webError.message);
+    case WebServiceWorkerError::ErrorTypeType:
+        // ErrorTypeType should have been handled before reaching this point.
+        ASSERT_NOT_REACHED();
+        return DOMException::create(UnknownError);
     }
     ASSERT_NOT_REACHED();
     return DOMException::create(UnknownError);
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerLinkResource.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerLinkResource.cpp
new file mode 100644
index 0000000..183127b
--- /dev/null
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerLinkResource.cpp
@@ -0,0 +1,92 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/serviceworkers/ServiceWorkerLinkResource.h"
+
+#include "core/dom/Document.h"
+#include "core/frame/LocalFrame.h"
+#include "core/html/HTMLLinkElement.h"
+#include "core/loader/FrameLoaderClient.h"
+#include "modules/serviceworkers/NavigatorServiceWorker.h"
+#include "modules/serviceworkers/ServiceWorkerContainer.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebScheduler.h"
+
+namespace blink {
+
+namespace {
+
+class RegistrationCallback : public WebServiceWorkerProvider::WebServiceWorkerRegistrationCallbacks {
+public:
+    explicit RegistrationCallback(LinkLoaderClient* client) : m_client(client) {}
+    ~RegistrationCallback() override {}
+
+    void onSuccess(WebPassOwnPtr<WebServiceWorkerRegistration::Handle> handle) override
+    {
+        Platform::current()->currentThread()->scheduler()->timerTaskRunner()->postTask(BLINK_FROM_HERE, bind(&LinkLoaderClient::linkLoaded, m_client));
+    }
+
+    void onError(const WebServiceWorkerError& error) override
+    {
+        Platform::current()->currentThread()->scheduler()->timerTaskRunner()->postTask(BLINK_FROM_HERE, bind(&LinkLoaderClient::linkLoadingErrored, m_client));
+    }
+
+private:
+    WTF_MAKE_NONCOPYABLE(RegistrationCallback);
+
+    RawPtrWillBePersistent<LinkLoaderClient> m_client;
+};
+
+}
+
+PassOwnPtrWillBeRawPtr<ServiceWorkerLinkResource> ServiceWorkerLinkResource::create(HTMLLinkElement* owner)
+{
+    return adoptPtrWillBeNoop(new ServiceWorkerLinkResource(owner));
+}
+
+ServiceWorkerLinkResource::~ServiceWorkerLinkResource()
+{
+}
+
+void ServiceWorkerLinkResource::process()
+{
+    if (!m_owner || !m_owner->document().frame())
+        return;
+
+    if (!m_owner->shouldLoadLink())
+        return;
+
+    Document& document = m_owner->document();
+
+    KURL scriptURL = m_owner->href();
+
+    String scope = m_owner->scope();
+    KURL scopeURL;
+    if (scope.isNull())
+        scopeURL = KURL(scriptURL, "./");
+    else
+        scopeURL = document.completeURL(scope);
+    scopeURL.removeFragmentIdentifier();
+
+    TrackExceptionState exceptionState;
+
+    NavigatorServiceWorker::serviceWorker(&document, *document.frame()->domWindow()->navigator(), exceptionState)->registerServiceWorkerImpl(&document, scriptURL, scopeURL, adoptPtr(new RegistrationCallback(m_owner)));
+}
+
+bool ServiceWorkerLinkResource::hasLoaded() const
+{
+    return false;
+}
+
+void ServiceWorkerLinkResource::ownerRemoved()
+{
+    process();
+}
+
+ServiceWorkerLinkResource::ServiceWorkerLinkResource(HTMLLinkElement* owner)
+    : LinkResource(owner)
+{
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerLinkResource.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerLinkResource.h
new file mode 100644
index 0000000..10a8769f
--- /dev/null
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerLinkResource.h
@@ -0,0 +1,38 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ServiceWorkerLinkResource_h
+#define ServiceWorkerLinkResource_h
+
+#include "core/html/LinkResource.h"
+#include "modules/ModulesExport.h"
+#include "wtf/Allocator.h"
+#include "wtf/PassOwnPtr.h"
+#include "wtf/RefPtr.h"
+
+namespace blink {
+
+class HTMLLinkElement;
+
+class MODULES_EXPORT ServiceWorkerLinkResource final : public LinkResource {
+    USING_FAST_MALLOC_WILL_BE_REMOVED(ServiceWorkerLinkResource);
+public:
+
+    static PassOwnPtrWillBeRawPtr<ServiceWorkerLinkResource> create(HTMLLinkElement* owner);
+
+    ~ServiceWorkerLinkResource() override;
+
+    // LinkResource implementation:
+    void process() override;
+    LinkResourceType type() const override { return Other; }
+    bool hasLoaded() const override;
+    void ownerRemoved() override;
+
+private:
+    explicit ServiceWorkerLinkResource(HTMLLinkElement* owner);
+};
+
+} // namespace blink
+
+#endif // ServiceWorkerLinkResource_h
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp
index 2429c66..6aaf6de 100644
--- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp
@@ -37,7 +37,7 @@
 
 namespace blink {
 
-OfflineAudioContext* OfflineAudioContext::create(ExecutionContext* context, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionState)
+OfflineAudioContext* OfflineAudioContext::create(ExecutionContext* context, unsigned numberOfChannels, unsigned numberOfFrames, float sampleRate, ExceptionState& exceptionState)
 {
     // FIXME: add support for workers.
     if (!context || !context->isDocument()) {
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h
index 85d99d75..946e26d 100644
--- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h
+++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h
@@ -37,12 +37,14 @@
 class MODULES_EXPORT OfflineAudioContext final : public AbstractAudioContext {
     DEFINE_WRAPPERTYPEINFO();
 public:
-    static OfflineAudioContext* create(ExecutionContext*, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState&);
+    static OfflineAudioContext* create(ExecutionContext*, unsigned numberOfChannels, unsigned numberOfFrames, float sampleRate, ExceptionState&);
 
     ~OfflineAudioContext() override;
 
     DECLARE_VIRTUAL_TRACE();
 
+    unsigned length() const { return m_totalRenderFrames; }
+
     ScriptPromise startOfflineRendering(ScriptState*);
 
     ScriptPromise closeContext(ScriptState*) final;
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl
index 1f91f8f5..e0a457c3 100644
--- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl
+++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl
@@ -30,6 +30,7 @@
 ] interface OfflineAudioContext : AudioContext {
     // Offline rendering
     attribute EventHandler oncomplete;
+    readonly attribute unsigned long length;
     [CallWith=ScriptState, ImplementedAs=startOfflineRendering, MeasureAs=OfflineAudioContextStartRendering] Promise<AudioBuffer> startRendering();
     [CallWith=ScriptState, ImplementedAs=suspendContext, MeasureAs=OfflineAudioContextSuspend] Promise<void> suspend(double suspendTime);
     [CallWith=ScriptState, ImplementedAs=resumeContext, MeasureAs=OfflineAudioContextResume] Promise<void> resume();
diff --git a/third_party/WebKit/Source/modules/webdatabase/Database.cpp b/third_party/WebKit/Source/modules/webdatabase/Database.cpp
index f73374cb..1347d9a 100644
--- a/third_party/WebKit/Source/modules/webdatabase/Database.cpp
+++ b/third_party/WebKit/Source/modules/webdatabase/Database.cpp
@@ -50,9 +50,9 @@
 #include "modules/webdatabase/sqlite/SQLiteTransaction.h"
 #include "platform/Logging.h"
 #include "platform/heap/SafePoint.h"
-#include "platform/weborigin/DatabaseIdentifier.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebDatabaseObserver.h"
+#include "public/platform/WebSecurityOrigin.h"
 #include "wtf/Atomics.h"
 #include "wtf/CurrentTime.h"
 
@@ -712,7 +712,7 @@
 {
     if (Platform::current()->databaseObserver()) {
         Platform::current()->databaseObserver()->reportOpenDatabaseResult(
-            createDatabaseIdentifierFromSecurityOrigin(getSecurityOrigin()),
+            WebSecurityOrigin(getSecurityOrigin()),
             stringIdentifier(), errorSite, webSqlErrorCode, sqliteErrorCode,
             duration);
     }
@@ -722,7 +722,7 @@
 {
     if (Platform::current()->databaseObserver()) {
         Platform::current()->databaseObserver()->reportChangeVersionResult(
-            createDatabaseIdentifierFromSecurityOrigin(getSecurityOrigin()),
+            WebSecurityOrigin(getSecurityOrigin()),
             stringIdentifier(), errorSite, webSqlErrorCode, sqliteErrorCode);
     }
 }
@@ -731,7 +731,7 @@
 {
     if (Platform::current()->databaseObserver()) {
         Platform::current()->databaseObserver()->reportStartTransactionResult(
-            createDatabaseIdentifierFromSecurityOrigin(getSecurityOrigin()),
+            WebSecurityOrigin(getSecurityOrigin()),
             stringIdentifier(), errorSite, webSqlErrorCode, sqliteErrorCode);
     }
 }
@@ -740,7 +740,7 @@
 {
     if (Platform::current()->databaseObserver()) {
         Platform::current()->databaseObserver()->reportCommitTransactionResult(
-            createDatabaseIdentifierFromSecurityOrigin(getSecurityOrigin()),
+            WebSecurityOrigin(getSecurityOrigin()),
             stringIdentifier(), errorSite, webSqlErrorCode, sqliteErrorCode);
     }
 }
@@ -749,7 +749,7 @@
 {
     if (Platform::current()->databaseObserver()) {
         Platform::current()->databaseObserver()->reportExecuteStatementResult(
-            createDatabaseIdentifierFromSecurityOrigin(getSecurityOrigin()),
+            WebSecurityOrigin(getSecurityOrigin()),
             stringIdentifier(), errorSite, webSqlErrorCode, sqliteErrorCode);
     }
 }
@@ -758,7 +758,7 @@
 {
     if (Platform::current()->databaseObserver()) {
         Platform::current()->databaseObserver()->reportVacuumDatabaseResult(
-            createDatabaseIdentifierFromSecurityOrigin(getSecurityOrigin()),
+            WebSecurityOrigin(getSecurityOrigin()),
             stringIdentifier(), sqliteErrorCode);
     }
 }
diff --git a/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp b/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp
index 24f5626..434a9c5e 100644
--- a/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp
+++ b/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp
@@ -37,11 +37,11 @@
 #include "modules/webdatabase/DatabaseContext.h"
 #include "modules/webdatabase/QuotaTracker.h"
 #include "modules/webdatabase/sqlite/SQLiteFileSystem.h"
-#include "platform/weborigin/DatabaseIdentifier.h"
 #include "platform/weborigin/SecurityOrigin.h"
 #include "platform/weborigin/SecurityOriginHash.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebDatabaseObserver.h"
+#include "public/platform/WebSecurityOrigin.h"
 #include "public/platform/WebTraceLocation.h"
 #include "wtf/Assertions.h"
 #include "wtf/StdLibExtras.h"
@@ -52,7 +52,7 @@
 {
     if (Platform::current()->databaseObserver()) {
         Platform::current()->databaseObserver()->databaseClosed(
-            createDatabaseIdentifierFromSecurityOrigin(database->getSecurityOrigin()),
+            WebSecurityOrigin(database->getSecurityOrigin()),
             database->stringIdentifier());
     }
 }
@@ -79,7 +79,7 @@
 
 String DatabaseTracker::fullPathForDatabase(SecurityOrigin* origin, const String& name, bool)
 {
-    return createDatabaseIdentifierFromSecurityOrigin(origin) + "/" + name + "#";
+    return String(Platform::current()->databaseCreateOriginIdentifier(WebSecurityOrigin(origin))) + "/" + name + "#";
 }
 
 void DatabaseTracker::addOpenDatabase(Database* database)
@@ -88,11 +88,11 @@
     if (!m_openDatabaseMap)
         m_openDatabaseMap = adoptPtr(new DatabaseOriginMap);
 
-    String originIdentifier = createDatabaseIdentifierFromSecurityOrigin(database->getSecurityOrigin());
-    DatabaseNameMap* nameMap = m_openDatabaseMap->get(originIdentifier);
+    String originString = database->getSecurityOrigin()->toString();
+    DatabaseNameMap* nameMap = m_openDatabaseMap->get(originString);
     if (!nameMap) {
         nameMap = new DatabaseNameMap();
-        m_openDatabaseMap->set(originIdentifier, nameMap);
+        m_openDatabaseMap->set(originString, nameMap);
     }
 
     String name(database->stringIdentifier());
@@ -109,9 +109,9 @@
 {
     {
         MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
-        String originIdentifier = createDatabaseIdentifierFromSecurityOrigin(database->getSecurityOrigin());
+        String originString = database->getSecurityOrigin()->toString();
         ASSERT(m_openDatabaseMap);
-        DatabaseNameMap* nameMap = m_openDatabaseMap->get(originIdentifier);
+        DatabaseNameMap* nameMap = m_openDatabaseMap->get(originString);
         if (!nameMap)
             return;
 
@@ -129,7 +129,7 @@
             nameMap->remove(name);
             delete databaseSet;
             if (nameMap->isEmpty()) {
-                m_openDatabaseMap->remove(originIdentifier);
+                m_openDatabaseMap->remove(originString);
                 delete nameMap;
             }
         }
@@ -142,7 +142,7 @@
     ASSERT(database->getDatabaseContext()->getExecutionContext()->isContextThread());
     if (Platform::current()->databaseObserver()) {
         Platform::current()->databaseObserver()->databaseOpened(
-            createDatabaseIdentifierFromSecurityOrigin(database->getSecurityOrigin()),
+            WebSecurityOrigin(database->getSecurityOrigin()),
             database->stringIdentifier(),
             database->displayName(),
             database->estimatedSize());
@@ -159,43 +159,44 @@
     unsigned long long spaceAvailable = 0;
     unsigned long long databaseSize = 0;
     QuotaTracker::instance().getDatabaseSizeAndSpaceAvailableToOrigin(
-        createDatabaseIdentifierFromSecurityOrigin(database->getSecurityOrigin()),
+        database->getSecurityOrigin(),
         database->stringIdentifier(), &databaseSize, &spaceAvailable);
     return databaseSize + spaceAvailable;
 }
 
 class DatabaseTracker::CloseOneDatabaseImmediatelyTask final : public ExecutionContextTask {
 public:
-    static PassOwnPtr<CloseOneDatabaseImmediatelyTask> create(const String& originIdentifier, const String& name, Database* database)
+    static PassOwnPtr<CloseOneDatabaseImmediatelyTask> create(const String& originString, const String& name, Database* database)
     {
-        return adoptPtr(new CloseOneDatabaseImmediatelyTask(originIdentifier, name, database));
+        return adoptPtr(new CloseOneDatabaseImmediatelyTask(originString, name, database));
     }
 
     void performTask(ExecutionContext*) override
     {
-        DatabaseTracker::tracker().closeOneDatabaseImmediately(m_originIdentifier, m_name, m_database);
+        DatabaseTracker::tracker().closeOneDatabaseImmediately(m_originString, m_name, m_database);
     }
 
 private:
-    CloseOneDatabaseImmediatelyTask(const String& originIdentifier, const String& name, Database* database)
-        : m_originIdentifier(originIdentifier.isolatedCopy())
+    CloseOneDatabaseImmediatelyTask(const String& originString, const String& name, Database* database)
+        : m_originString(originString.isolatedCopy())
         , m_name(name.isolatedCopy())
         , m_database(database)
     {
     }
 
-    String m_originIdentifier;
+    String m_originString;
     String m_name;
     CrossThreadPersistent<Database> m_database;
 };
 
-void DatabaseTracker::closeDatabasesImmediately(const String& originIdentifier, const String& name)
+void DatabaseTracker::closeDatabasesImmediately(SecurityOrigin* origin, const String& name)
 {
+    String originString = origin->toString();
     MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
     if (!m_openDatabaseMap)
         return;
 
-    DatabaseNameMap* nameMap = m_openDatabaseMap->get(originIdentifier);
+    DatabaseNameMap* nameMap = m_openDatabaseMap->get(originString);
     if (!nameMap)
         return;
 
@@ -205,10 +206,10 @@
 
     // We have to call closeImmediately() on the context thread.
     for (DatabaseSet::iterator it = databaseSet->begin(); it != databaseSet->end(); ++it)
-        (*it)->getDatabaseContext()->getExecutionContext()->postTask(BLINK_FROM_HERE, CloseOneDatabaseImmediatelyTask::create(originIdentifier, name, *it));
+        (*it)->getDatabaseContext()->getExecutionContext()->postTask(BLINK_FROM_HERE, CloseOneDatabaseImmediatelyTask::create(originString, name, *it));
 }
 
-void DatabaseTracker::closeOneDatabaseImmediately(const String& originIdentifier, const String& name, Database* database)
+void DatabaseTracker::closeOneDatabaseImmediately(const String& originString, const String& name, Database* database)
 {
     // First we have to confirm the 'database' is still in our collection.
     {
@@ -216,7 +217,7 @@
         if (!m_openDatabaseMap)
             return;
 
-        DatabaseNameMap* nameMap = m_openDatabaseMap->get(originIdentifier);
+        DatabaseNameMap* nameMap = m_openDatabaseMap->get(originString);
         if (!nameMap)
             return;
 
diff --git a/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.h b/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.h
index 6e6f8d7..9b6059ee 100644
--- a/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.h
+++ b/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.h
@@ -63,7 +63,7 @@
 
     unsigned long long getMaxSizeForDatabase(const Database*);
 
-    void closeDatabasesImmediately(const String& originIdentifier, const String& name);
+    void closeDatabasesImmediately(SecurityOrigin*, const String& name);
 
     void prepareToOpenDatabase(Database*);
     void failedToOpenDatabase(Database*);
diff --git a/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.cpp b/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.cpp
index 007cb53..d9e32f3 100644
--- a/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.cpp
+++ b/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.cpp
@@ -30,7 +30,9 @@
 
 #include "modules/webdatabase/QuotaTracker.h"
 
+#include "platform/weborigin/SecurityOrigin.h"
 #include "public/platform/Platform.h"
+#include "public/platform/WebSecurityOrigin.h"
 #include "wtf/StdLibExtras.h"
 #include "wtf/Threading.h"
 
@@ -43,46 +45,46 @@
 }
 
 void QuotaTracker::getDatabaseSizeAndSpaceAvailableToOrigin(
-    const String& originIdentifier, const String& databaseName,
+    SecurityOrigin* origin, const String& databaseName,
     unsigned long long* databaseSize, unsigned long long* spaceAvailable)
 {
     // Extra scope to unlock prior to potentially calling Platform.
     {
         MutexLocker lockData(m_dataGuard);
-        ASSERT(m_databaseSizes.contains(originIdentifier));
-        HashMap<String, SizeMap>::const_iterator it = m_databaseSizes.find(originIdentifier);
+        ASSERT(m_databaseSizes.contains(origin->toString()));
+        HashMap<String, SizeMap>::const_iterator it = m_databaseSizes.find(origin->toString());
         ASSERT(it->value.contains(databaseName));
         *databaseSize = it->value.get(databaseName);
 
-        if (m_spaceAvailableToOrigins.contains(originIdentifier)) {
-            *spaceAvailable = m_spaceAvailableToOrigins.get(originIdentifier);
+        if (m_spaceAvailableToOrigins.contains(origin->toString())) {
+            *spaceAvailable = m_spaceAvailableToOrigins.get(origin->toString());
             return;
         }
     }
 
     // The embedder hasn't pushed this value to us, so we pull it as needed.
-    *spaceAvailable = Platform::current()->databaseGetSpaceAvailableForOrigin(originIdentifier);
+    *spaceAvailable = Platform::current()->databaseGetSpaceAvailableForOrigin(WebSecurityOrigin(origin));
 }
 
 void QuotaTracker::updateDatabaseSize(
-    const String& originIdentifier, const String& databaseName,
+    SecurityOrigin* origin, const String& databaseName,
     unsigned long long databaseSize)
 {
     MutexLocker lockData(m_dataGuard);
-    HashMap<String, SizeMap>::ValueType* it = m_databaseSizes.add(originIdentifier, SizeMap()).storedValue;
+    HashMap<String, SizeMap>::ValueType* it = m_databaseSizes.add(origin->toString(), SizeMap()).storedValue;
     it->value.set(databaseName, databaseSize);
 }
 
-void QuotaTracker::updateSpaceAvailableToOrigin(const String& originIdentifier, unsigned long long spaceAvailable)
+void QuotaTracker::updateSpaceAvailableToOrigin(SecurityOrigin* origin, unsigned long long spaceAvailable)
 {
     MutexLocker lockData(m_dataGuard);
-    m_spaceAvailableToOrigins.set(originIdentifier, spaceAvailable);
+    m_spaceAvailableToOrigins.set(origin->toString(), spaceAvailable);
 }
 
-void QuotaTracker::resetSpaceAvailableToOrigin(const String& originIdentifier)
+void QuotaTracker::resetSpaceAvailableToOrigin(SecurityOrigin* origin)
 {
     MutexLocker lockData(m_dataGuard);
-    m_spaceAvailableToOrigins.remove(originIdentifier);
+    m_spaceAvailableToOrigins.remove(origin->toString());
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.h b/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.h
index eb37a9d2..9c64ab23 100644
--- a/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.h
+++ b/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.h
@@ -32,7 +32,6 @@
 #define QuotaTracker_h
 
 #include "modules/ModulesExport.h"
-#include "platform/weborigin/SecurityOrigin.h"
 #include "wtf/HashMap.h"
 #include "wtf/ThreadingPrimitives.h"
 #include "wtf/text/StringHash.h"
@@ -40,6 +39,8 @@
 
 namespace blink {
 
+class SecurityOrigin;
+
 class MODULES_EXPORT QuotaTracker {
     USING_FAST_MALLOC(QuotaTracker);
     WTF_MAKE_NONCOPYABLE(QuotaTracker);
@@ -47,13 +48,13 @@
     static QuotaTracker& instance();
 
     void getDatabaseSizeAndSpaceAvailableToOrigin(
-        const String& originIdentifier, const String& databaseName,
+        SecurityOrigin*, const String& databaseName,
         unsigned long long* databaseSize, unsigned long long* spaceAvailable);
     void updateDatabaseSize(
-        const String& originIdentifier, const String& databaseName,
+        SecurityOrigin*, const String& databaseName,
         unsigned long long databaseSize);
-    void updateSpaceAvailableToOrigin(const String& originIdentifier, unsigned long long spaceAvailable);
-    void resetSpaceAvailableToOrigin(const String& originIdentifier);
+    void updateSpaceAvailableToOrigin(SecurityOrigin*, unsigned long long spaceAvailable);
+    void resetSpaceAvailableToOrigin(SecurityOrigin*);
 
 private:
     QuotaTracker() { }
diff --git a/third_party/WebKit/Source/modules/webdatabase/SQLTransactionClient.cpp b/third_party/WebKit/Source/modules/webdatabase/SQLTransactionClient.cpp
index 5670e2f6..60736f4 100644
--- a/third_party/WebKit/Source/modules/webdatabase/SQLTransactionClient.cpp
+++ b/third_party/WebKit/Source/modules/webdatabase/SQLTransactionClient.cpp
@@ -34,30 +34,38 @@
 #include "core/dom/ExecutionContext.h"
 #include "modules/webdatabase/Database.h"
 #include "modules/webdatabase/DatabaseContext.h"
-#include "platform/weborigin/DatabaseIdentifier.h"
 #include "platform/weborigin/SecurityOrigin.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebDatabaseObserver.h"
+#include "public/platform/WebSecurityOrigin.h"
 #include "public/platform/WebTraceLocation.h"
 #include "wtf/Functional.h"
 
 namespace blink {
 
-static void databaseModified(const String& originIdentifier, const String& databaseName)
+namespace {
+
+void databaseModified(const WebSecurityOrigin& origin, const String& databaseName)
 {
     if (Platform::current()->databaseObserver())
-        Platform::current()->databaseObserver()->databaseModified(originIdentifier, databaseName);
+        Platform::current()->databaseObserver()->databaseModified(origin, databaseName);
 }
 
+void databaseModifiedCrossThread(const String& originString, const String& databaseName)
+{
+    databaseModified(WebSecurityOrigin::createFromString(originString), databaseName);
+}
+
+} // namespace
+
 void SQLTransactionClient::didCommitWriteTransaction(Database* database)
 {
-    String originIdentifier = createDatabaseIdentifierFromSecurityOrigin(database->getSecurityOrigin());
     String databaseName = database->stringIdentifier();
     ExecutionContext* executionContext = database->getDatabaseContext()->getExecutionContext();
     if (!executionContext->isContextThread()) {
-        executionContext->postTask(BLINK_FROM_HERE, createCrossThreadTask(&databaseModified, originIdentifier, databaseName));
+        executionContext->postTask(BLINK_FROM_HERE, createCrossThreadTask(&databaseModifiedCrossThread, executionContext->getSecurityOrigin()->toString(), databaseName));
     } else {
-        databaseModified(originIdentifier, databaseName);
+        databaseModified(WebSecurityOrigin(executionContext->getSecurityOrigin()), databaseName);
     }
 }
 
diff --git a/third_party/WebKit/Source/modules/webgl/CHROMIUMValuebuffer.cpp b/third_party/WebKit/Source/modules/webgl/CHROMIUMValuebuffer.cpp
index bd13951..9390ee4 100644
--- a/third_party/WebKit/Source/modules/webgl/CHROMIUMValuebuffer.cpp
+++ b/third_party/WebKit/Source/modules/webgl/CHROMIUMValuebuffer.cpp
@@ -4,6 +4,7 @@
 
 #include "modules/webgl/CHROMIUMValuebuffer.h"
 
+#include "gpu/command_buffer/client/gles2_interface.h"
 #include "modules/webgl/WebGLRenderingContextBase.h"
 
 namespace blink {
@@ -23,12 +24,14 @@
     : WebGLSharedPlatform3DObject(ctx)
     , m_hasEverBeenBound(false)
 {
-    setObject(ctx->webContext()->createValuebufferCHROMIUM());
+    GLuint buffer;
+    ctx->contextGL()->GenValuebuffersCHROMIUM(1, &buffer);
+    setObject(buffer);
 }
 
 void CHROMIUMValuebuffer::deleteObjectImpl(WebGraphicsContext3D* context3d, gpu::gles2::GLES2Interface* gl)
 {
-    context3d->deleteValuebufferCHROMIUM(m_object);
+    gl->DeleteValuebuffersCHROMIUM(1, &m_object);
     m_object = 0;
 }
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp
index 888b74d..c80ee7b 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp
@@ -9,6 +9,7 @@
 #include "core/frame/Settings.h"
 #include "core/loader/FrameLoader.h"
 #include "core/loader/FrameLoaderClient.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
 #include "modules/webgl/CHROMIUMSubscribeUniform.h"
 #include "modules/webgl/EXTColorBufferFloat.h"
 #include "modules/webgl/EXTDisjointTimerQuery.h"
@@ -26,6 +27,7 @@
 #include "modules/webgl/WebGLLoseContext.h"
 #include "platform/graphics/gpu/DrawingBuffer.h"
 #include "public/platform/Platform.h"
+#include "public/platform/WebGraphicsContext3DProvider.h"
 
 namespace blink {
 
@@ -37,18 +39,19 @@
     }
 
     WebGLContextAttributes attributes = toWebGLContextAttributes(attrs);
-    OwnPtr<WebGraphicsContext3D> context(createWebGraphicsContext3D(canvas, attributes, 2));
-    if (!context)
+    OwnPtr<WebGraphicsContext3DProvider> contextProvider(createWebGraphicsContext3DProvider(canvas, attributes, 2));
+    if (!contextProvider)
         return nullptr;
-    OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get(), context->getGLES2Interface());
+    gpu::gles2::GLES2Interface* gl = contextProvider->contextGL();
+    OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(gl);
     if (!extensionsUtil)
         return nullptr;
     if (extensionsUtil->supportsExtension("GL_EXT_debug_marker")) {
-        String contextLabel(String::format("WebGL2RenderingContext-%p", context.get()));
-        context->pushGroupMarkerEXT(contextLabel.ascii().data());
+        String contextLabel(String::format("WebGL2RenderingContext-%p", contextProvider.get()));
+        gl->PushGroupMarkerEXT(0, contextLabel.ascii().data());
     }
 
-    OwnPtrWillBeRawPtr<WebGL2RenderingContext> renderingContext = adoptPtrWillBeNoop(new WebGL2RenderingContext(canvas, context.release(), attributes));
+    OwnPtrWillBeRawPtr<WebGL2RenderingContext> renderingContext = adoptPtrWillBeNoop(new WebGL2RenderingContext(canvas, contextProvider.release(), attributes));
 
     if (!renderingContext->drawingBuffer()) {
         canvas->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, "Could not create a WebGL2 context."));
@@ -66,8 +69,8 @@
     canvas->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, error));
 }
 
-WebGL2RenderingContext::WebGL2RenderingContext(HTMLCanvasElement* passedCanvas, PassOwnPtr<WebGraphicsContext3D> context, const WebGLContextAttributes& requestedAttributes)
-    : WebGL2RenderingContextBase(passedCanvas, context, requestedAttributes)
+WebGL2RenderingContext::WebGL2RenderingContext(HTMLCanvasElement* passedCanvas, PassOwnPtr<WebGraphicsContext3DProvider> contextProvider, const WebGLContextAttributes& requestedAttributes)
+    : WebGL2RenderingContextBase(passedCanvas, contextProvider, requestedAttributes)
 {
 }
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.h b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.h
index 5a27233e..c470846 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.h
@@ -38,7 +38,7 @@
     DECLARE_VIRTUAL_TRACE();
 
 protected:
-    WebGL2RenderingContext(HTMLCanvasElement* passedCanvas, PassOwnPtr<WebGraphicsContext3D>, const WebGLContextAttributes& requestedAttributes);
+    WebGL2RenderingContext(HTMLCanvasElement* passedCanvas, PassOwnPtr<WebGraphicsContext3DProvider>, const WebGLContextAttributes& requestedAttributes);
 
     PersistentWillBeMember<CHROMIUMSubscribeUniform> m_chromiumSubscribeUniform;
     PersistentWillBeMember<EXTColorBufferFloat> m_extColorBufferFloat;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
index 2424ab4..d56b52a 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
@@ -26,8 +26,13 @@
 #include "modules/webgl/WebGLVertexArrayObject.h"
 #include "platform/CheckedInt.h"
 #include "platform/NotImplemented.h"
+#include "public/platform/WebGraphicsContext3D.h"
+#include "public/platform/WebGraphicsContext3DProvider.h"
 #include "wtf/OwnPtr.h"
 #include "wtf/PassOwnPtr.h"
+#include "wtf/text/WTFString.h"
+
+using WTF::String;
 
 namespace blink {
 
@@ -111,8 +116,8 @@
     GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
 };
 
-WebGL2RenderingContextBase::WebGL2RenderingContextBase(HTMLCanvasElement* passedCanvas, PassOwnPtr<WebGraphicsContext3D> context, const WebGLContextAttributes& requestedAttributes)
-    : WebGLRenderingContextBase(passedCanvas, context, requestedAttributes)
+WebGL2RenderingContextBase::WebGL2RenderingContextBase(HTMLCanvasElement* passedCanvas, PassOwnPtr<WebGraphicsContext3DProvider> contextProvider, const WebGLContextAttributes& requestedAttributes)
+    : WebGLRenderingContextBase(passedCanvas, contextProvider, requestedAttributes)
 {
     m_supportedInternalFormatsStorage.insert(kSupportedInternalFormatsStorage, kSupportedInternalFormatsStorage + WTF_ARRAY_LENGTH(kSupportedInternalFormatsStorage));
     m_supportedInternalFormatsStorage.insert(kCompressedTextureFormatsETC2EAC, kCompressedTextureFormatsETC2EAC + WTF_ARRAY_LENGTH(kCompressedTextureFormatsETC2EAC));
@@ -213,7 +218,7 @@
     if (writeBuffer->getInitialTarget() == 0)
         writeBuffer->setInitialTarget(readBuffer->getInitialTarget());
 
-    webContext()->copyBufferSubData(readTarget, writeTarget, static_cast<GLintptr>(readOffset), static_cast<GLintptr>(writeOffset), static_cast<GLsizeiptr>(size));
+    contextGL()->CopyBufferSubData(readTarget, writeTarget, static_cast<GLintptr>(readOffset), static_cast<GLintptr>(writeOffset), static_cast<GLsizeiptr>(size));
 }
 
 void WebGL2RenderingContextBase::getBufferSubData(GLenum target, long long offset, DOMArrayBuffer* returnedData)
@@ -238,14 +243,14 @@
         return;
     }
 
-    void* mappedData = webContext()->mapBufferRange(target, static_cast<GLintptr>(offset), returnedData->byteLength(), GL_MAP_READ_BIT);
+    void* mappedData = contextGL()->MapBufferRange(target, static_cast<GLintptr>(offset), returnedData->byteLength(), GL_MAP_READ_BIT);
 
     if (!mappedData)
         return;
 
     memcpy(returnedData->data(), mappedData, returnedData->byteLength());
 
-    webContext()->unmapBuffer(target);
+    contextGL()->UnmapBuffer(target);
 }
 
 void WebGL2RenderingContextBase::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
@@ -405,14 +410,14 @@
             OwnPtr<GLint[]> values;
             GLint length = -1;
             if (!floatType) {
-                webContext()->getInternalformativ(target, internalformat, GL_NUM_SAMPLE_COUNTS, 1, &length);
+                contextGL()->GetInternalformativ(target, internalformat, GL_NUM_SAMPLE_COUNTS, 1, &length);
                 if (length <= 0)
                     return WebGLAny(scriptState, DOMInt32Array::create(0));
 
                 values = adoptArrayPtr(new GLint[length]);
                 for (GLint ii = 0; ii < length; ++ii)
                     values[ii] = 0;
-                webContext()->getInternalformativ(target, internalformat, GL_SAMPLES, length, values.get());
+                contextGL()->GetInternalformativ(target, internalformat, GL_SAMPLES, length, values.get());
             } else {
                 length = 1;
                 values = adoptArrayPtr(new GLint[1]);
@@ -490,7 +495,7 @@
     if (!checkAndTranslateAttachments("invalidateFramebuffer", target, attachments, translatedAttachments))
         return;
 
-    webContext()->invalidateFramebuffer(target, translatedAttachments.size(), translatedAttachments.data());
+    contextGL()->InvalidateFramebuffer(target, translatedAttachments.size(), translatedAttachments.data());
 }
 
 void WebGL2RenderingContextBase::invalidateSubFramebuffer(GLenum target, const Vector<GLenum>& attachments, GLint x, GLint y, GLsizei width, GLsizei height)
@@ -512,7 +517,7 @@
     if (!checkAndTranslateAttachments("invalidateSubFramebuffer", target, attachments, translatedAttachments))
         return;
 
-    webContext()->invalidateSubFramebuffer(target, translatedAttachments.size(), translatedAttachments.data(), x, y, width, height);
+    contextGL()->InvalidateSubFramebuffer(target, translatedAttachments.size(), translatedAttachments.data(), x, y, width, height);
 }
 
 void WebGL2RenderingContextBase::readBuffer(GLenum mode)
@@ -552,7 +557,7 @@
         }
         readFramebufferBinding->readBuffer(mode);
     }
-    webContext()->readBuffer(mode);
+    contextGL()->ReadBuffer(mode);
 }
 
 void WebGL2RenderingContextBase::pixelStorei(GLenum pname, GLint param)
@@ -694,7 +699,7 @@
             contextGL()->RenderbufferStorage(target, internalformat, width, height);
         } else {
             GLint maxNumberOfSamples = 0;
-            webContext()->getInternalformativ(target, internalformat, GL_SAMPLES, 1, &maxNumberOfSamples);
+            contextGL()->GetInternalformativ(target, internalformat, GL_SAMPLES, 1, &maxNumberOfSamples);
             if (samples > maxNumberOfSamples) {
                 synthesizeGLError(GL_INVALID_OPERATION, functionName, "samples out of range");
                 return;
@@ -1208,7 +1213,7 @@
         return;
     clearIfComposited();
     ScopedDrawingBufferBinder binder(drawingBuffer(), readFramebufferBinding);
-    webContext()->copyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
+    contextGL()->CopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
 }
 
 void WebGL2RenderingContextBase::compressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, DOMArrayBufferView* data)
@@ -1219,7 +1224,7 @@
         return;
     if (!validateCompressedTexFormat("compressedTexImage3D", internalformat))
         return;
-    webContext()->compressedTexImage3D(target, level, internalformat, width, height, depth, border, data->byteLength(), data->baseAddress());
+    contextGL()->CompressedTexImage3D(target, level, internalformat, width, height, depth, border, data->byteLength(), data->baseAddress());
 }
 
 void WebGL2RenderingContextBase::compressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, DOMArrayBufferView* data)
@@ -1230,7 +1235,7 @@
         return;
     if (!validateCompressedTexFormat("compressedTexSubImage3D", format))
         return;
-    webContext()->compressedTexSubImage3D(target, level, xoffset, yoffset, zoffset,
+    contextGL()->CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset,
         width, height, depth, format, data->byteLength(), data->baseAddress());
 }
 
@@ -1239,7 +1244,7 @@
     if (isContextLost() || !validateWebGLObject("getFragDataLocation", program))
         return -1;
 
-    return webContext()->getFragDataLocation(objectOrZero(program), name.utf8().data());
+    return contextGL()->GetFragDataLocation(objectOrZero(program), name.utf8().data());
 }
 
 void WebGL2RenderingContextBase::uniform1ui(const WebGLUniformLocation* location, GLuint v0)
@@ -1656,7 +1661,7 @@
     if (isContextLost() || !validateClearBuffer("clearBufferiv", buffer, value->length()))
         return;
 
-    webContext()->clearBufferiv(buffer, drawbuffer, value->data());
+    contextGL()->ClearBufferiv(buffer, drawbuffer, value->data());
 }
 
 void WebGL2RenderingContextBase::clearBufferiv(GLenum buffer, GLint drawbuffer, const Vector<GLint>& value)
@@ -1664,7 +1669,7 @@
     if (isContextLost() || !validateClearBuffer("clearBufferiv", buffer, value.size()))
         return;
 
-    webContext()->clearBufferiv(buffer, drawbuffer, value.data());
+    contextGL()->ClearBufferiv(buffer, drawbuffer, value.data());
 }
 
 void WebGL2RenderingContextBase::clearBufferuiv(GLenum buffer, GLint drawbuffer, DOMUint32Array* value)
@@ -1672,7 +1677,7 @@
     if (isContextLost() || !validateClearBuffer("clearBufferuiv", buffer, value->length()))
         return;
 
-    webContext()->clearBufferuiv(buffer, drawbuffer, value->data());
+    contextGL()->ClearBufferuiv(buffer, drawbuffer, value->data());
 }
 
 void WebGL2RenderingContextBase::clearBufferuiv(GLenum buffer, GLint drawbuffer, const Vector<GLuint>& value)
@@ -1680,7 +1685,7 @@
     if (isContextLost() || !validateClearBuffer("clearBufferuiv", buffer, value.size()))
         return;
 
-    webContext()->clearBufferuiv(buffer, drawbuffer, value.data());
+    contextGL()->ClearBufferuiv(buffer, drawbuffer, value.data());
 }
 
 void WebGL2RenderingContextBase::clearBufferfv(GLenum buffer, GLint drawbuffer, DOMFloat32Array* value)
@@ -1688,7 +1693,7 @@
     if (isContextLost() || !validateClearBuffer("clearBufferfv", buffer, value->length()))
         return;
 
-    webContext()->clearBufferfv(buffer, drawbuffer, value->data());
+    contextGL()->ClearBufferfv(buffer, drawbuffer, value->data());
 }
 
 void WebGL2RenderingContextBase::clearBufferfv(GLenum buffer, GLint drawbuffer, const Vector<GLfloat>& value)
@@ -1696,7 +1701,7 @@
     if (isContextLost() || !validateClearBuffer("clearBufferfv", buffer, value.size()))
         return;
 
-    webContext()->clearBufferfv(buffer, drawbuffer, value.data());
+    contextGL()->ClearBufferfv(buffer, drawbuffer, value.data());
 }
 
 void WebGL2RenderingContextBase::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
@@ -1704,7 +1709,7 @@
     if (isContextLost())
         return;
 
-    webContext()->clearBufferfi(buffer, drawbuffer, depth, stencil);
+    contextGL()->ClearBufferfi(buffer, drawbuffer, depth, stencil);
 }
 
 WebGLQuery* WebGL2RenderingContextBase::createQuery()
@@ -1913,7 +1918,7 @@
     for (size_t i = 0; i < m_samplerUnits.size(); ++i) {
         if (sampler == m_samplerUnits[i]) {
             m_samplerUnits[i] = nullptr;
-            webContext()->bindSampler(i, 0);
+            contextGL()->BindSampler(i, 0);
         }
     }
 
@@ -1925,7 +1930,7 @@
     if (isContextLost() || !sampler)
         return 0;
 
-    return webContext()->isSampler(sampler->object());
+    return contextGL()->IsSampler(sampler->object());
 }
 
 void WebGL2RenderingContextBase::bindSampler(GLuint unit, WebGLSampler* sampler)
@@ -1948,7 +1953,7 @@
 
     m_samplerUnits[unit] = sampler;
 
-    webContext()->bindSampler(unit, objectOrZero(sampler));
+    contextGL()->BindSampler(unit, objectOrZero(sampler));
 }
 
 void WebGL2RenderingContextBase::samplerParameter(WebGLSampler* sampler, GLenum pname, GLfloat paramf, GLint parami, bool isFloat)
@@ -2030,9 +2035,9 @@
     }
 
     if (isFloat) {
-        webContext()->samplerParameterf(objectOrZero(sampler), pname, paramf);
+        contextGL()->SamplerParameterf(objectOrZero(sampler), pname, paramf);
     } else {
-        webContext()->samplerParameteri(objectOrZero(sampler), pname, parami);
+        contextGL()->SamplerParameteri(objectOrZero(sampler), pname, parami);
     }
 }
 
@@ -2061,14 +2066,14 @@
     case GL_TEXTURE_WRAP_T:
         {
             GLint value = 0;
-            webContext()->getSamplerParameteriv(objectOrZero(sampler), pname, &value);
+            contextGL()->GetSamplerParameteriv(objectOrZero(sampler), pname, &value);
             return WebGLAny(scriptState, static_cast<unsigned>(value));
         }
     case GL_TEXTURE_MAX_LOD:
     case GL_TEXTURE_MIN_LOD:
         {
             GLfloat value = 0.f;
-            webContext()->getSamplerParameterfv(objectOrZero(sampler), pname, &value);
+            contextGL()->GetSamplerParameterfv(objectOrZero(sampler), pname, &value);
             return WebGLAny(scriptState, value);
         }
     default:
@@ -2179,7 +2184,7 @@
     if (!feedback->hasEverBeenBound())
         return 0;
 
-    return webContext()->isTransformFeedback(feedback->object());
+    return contextGL()->IsTransformFeedback(feedback->object());
 }
 
 void WebGL2RenderingContextBase::bindTransformFeedback(GLenum target, WebGLTransformFeedback* feedback)
@@ -2204,7 +2209,7 @@
 
     m_transformFeedbackBinding = feedback;
 
-    webContext()->bindTransformFeedback(target, objectOrZero(feedback));
+    contextGL()->BindTransformFeedback(target, objectOrZero(feedback));
     if (feedback)
         feedback->setTarget(target);
 }
@@ -2221,7 +2226,7 @@
         return;
     }
 
-    webContext()->beginTransformFeedback(primitiveMode);
+    contextGL()->BeginTransformFeedback(primitiveMode);
 
     // TODO(kbr): there are many more reasons BeginTransformFeedback may fail, the most
     // problematic being "if any binding point used in transform feedback mode does not
@@ -2246,7 +2251,7 @@
         return;
     }
 
-    webContext()->endTransformFeedback();
+    contextGL()->EndTransformFeedback();
 
     setTransformFeedbackPaused(false);
     setTransformFeedbackActive(false);
@@ -2281,7 +2286,7 @@
         varyingStrings.append(keepAlive.last().data());
     }
 
-    webContext()->transformFeedbackVaryings(objectOrZero(program), varyings.size(), varyingStrings.data(), bufferMode);
+    contextGL()->TransformFeedbackVaryings(objectOrZero(program), varyings.size(), varyingStrings.data(), bufferMode);
 }
 
 WebGLActiveInfo* WebGL2RenderingContextBase::getTransformFeedbackVarying(WebGLProgram* program, GLuint index)
@@ -2309,7 +2314,7 @@
     GLsizei length = 0;
     GLsizei size = 0;
     GLenum type = 0;
-    webContext()->getTransformFeedbackVarying(objectOrZero(program), index, maxNameLength, &length, &size, &type, name.get());
+    contextGL()->GetTransformFeedbackVarying(objectOrZero(program), index, maxNameLength, &length, &size, &type, name.get());
 
     if (length == 0 || size == 0 || type == 0) {
         return nullptr;
@@ -2328,7 +2333,7 @@
         return;
     }
 
-    webContext()->pauseTransformFeedback();
+    contextGL()->PauseTransformFeedback();
 
     setTransformFeedbackPaused(true);
 }
@@ -2348,7 +2353,7 @@
         return;
     }
 
-    webContext()->resumeTransformFeedback();
+    contextGL()->ResumeTransformFeedback();
 
     setTransformFeedbackPaused(false);
 }
@@ -2384,7 +2389,7 @@
         return;
     }
 
-    webContext()->bindBufferBase(target, index, objectOrZero(buffer));
+    contextGL()->BindBufferBase(target, index, objectOrZero(buffer));
 }
 
 void WebGL2RenderingContextBase::bindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer, long long offset, long long size)
@@ -2410,7 +2415,7 @@
     if (!validateAndUpdateBufferBindBaseTarget("bindBufferRange", target, index, buffer))
         return;
 
-    webContext()->bindBufferRange(target, index, objectOrZero(buffer), static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size));
+    contextGL()->BindBufferRange(target, index, objectOrZero(buffer), static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size));
 }
 
 bool WebGL2RenderingContextBase::transformFeedbackActive() const
@@ -2486,7 +2491,7 @@
     }
 
     result.resize(uniformNames.size());
-    webContext()->getUniformIndices(objectOrZero(program), uniformStrings.size(), uniformStrings.data(), result.data());
+    contextGL()->GetUniformIndices(objectOrZero(program), uniformStrings.size(), uniformStrings.data(), result.data());
     return result;
 }
 
@@ -2537,7 +2542,7 @@
     }
 
     Vector<GLint> result(size);
-    webContext()->getActiveUniformsiv(objectOrZero(program), uniformIndices.size(), uniformIndices.data(), pname, result.data());
+    contextGL()->GetActiveUniformsiv(objectOrZero(program), uniformIndices.size(), uniformIndices.data(), pname, result.data());
     switch (returnType) {
     case EnumType:
         {
@@ -2577,7 +2582,7 @@
     if (!validateString("getUniformBlockIndex", uniformBlockName))
         return 0;
 
-    return webContext()->getUniformBlockIndex(objectOrZero(program), uniformBlockName.utf8().data());
+    return contextGL()->GetUniformBlockIndex(objectOrZero(program), uniformBlockName.utf8().data());
 }
 
 bool WebGL2RenderingContextBase::validateUniformBlockIndex(const char* functionName, WebGLProgram* program, GLuint blockIndex)
@@ -2610,23 +2615,23 @@
     case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
         {
             GLint intValue = 0;
-            webContext()->getActiveUniformBlockiv(objectOrZero(program), uniformBlockIndex, pname, &intValue);
+            contextGL()->GetActiveUniformBlockiv(objectOrZero(program), uniformBlockIndex, pname, &intValue);
             return WebGLAny(scriptState, static_cast<unsigned>(intValue));
         }
     case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
         {
             GLint uniformCount = 0;
-            webContext()->getActiveUniformBlockiv(objectOrZero(program), uniformBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &uniformCount);
+            contextGL()->GetActiveUniformBlockiv(objectOrZero(program), uniformBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &uniformCount);
 
             Vector<GLint> indices(uniformCount);
-            webContext()->getActiveUniformBlockiv(objectOrZero(program), uniformBlockIndex, pname, indices.data());
+            contextGL()->GetActiveUniformBlockiv(objectOrZero(program), uniformBlockIndex, pname, indices.data());
             return WebGLAny(scriptState, DOMUint32Array::create(reinterpret_cast<GLuint*>(indices.data()), indices.size()));
         }
     case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
     case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
         {
             GLint boolValue = 0;
-            webContext()->getActiveUniformBlockiv(objectOrZero(program), uniformBlockIndex, pname, &boolValue);
+            contextGL()->GetActiveUniformBlockiv(objectOrZero(program), uniformBlockIndex, pname, &boolValue);
             return WebGLAny(scriptState, static_cast<bool>(boolValue));
         }
     default:
@@ -2653,7 +2658,7 @@
     OwnPtr<GLchar[]> name = adoptArrayPtr(new GLchar[maxNameLength]);
 
     GLsizei length = 0;
-    webContext()->getActiveUniformBlockName(objectOrZero(program), uniformBlockIndex, maxNameLength, &length, name.get());
+    contextGL()->GetActiveUniformBlockName(objectOrZero(program), uniformBlockIndex, maxNameLength, &length, name.get());
 
     return String(name.get(), length);
 }
@@ -2778,10 +2783,11 @@
     if (isContextLost())
         return ScriptValue::createNull(scriptState);
     switch (pname) {
-    case GL_SHADING_LANGUAGE_VERSION:
-        return WebGLAny(scriptState, "WebGL GLSL ES 3.00 (" + String(webContext()->getString(GL_SHADING_LANGUAGE_VERSION)) + ")");
+    case GL_SHADING_LANGUAGE_VERSION: {
+        return WebGLAny(scriptState, "WebGL GLSL ES 3.00 (" + String(contextGL()->GetString(GL_SHADING_LANGUAGE_VERSION)) + ")");
+    }
     case GL_VERSION:
-        return WebGLAny(scriptState, "WebGL 2.0 (" + String(webContext()->getString(GL_VERSION)) + ")");
+        return WebGLAny(scriptState, "WebGL 2.0 (" + String(contextGL()->GetString(GL_VERSION)) + ")");
 
     case GL_COPY_READ_BUFFER_BINDING:
         return WebGLAny(scriptState, m_boundCopyReadBuffer.get());
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h
index 736866e..7b9630f 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h
@@ -218,7 +218,7 @@
     DECLARE_VIRTUAL_TRACE();
 
 protected:
-    WebGL2RenderingContextBase(HTMLCanvasElement*, PassOwnPtr<WebGraphicsContext3D>, const WebGLContextAttributes& requestedAttributes);
+    WebGL2RenderingContextBase(HTMLCanvasElement*, PassOwnPtr<WebGraphicsContext3DProvider>, const WebGLContextAttributes& requestedAttributes);
 
     // Helper function to validate target and the attachment combination for getFramebufferAttachmentParameters.
     // Generate GL error and return false if parameters are illegal.
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLBuffer.cpp b/third_party/WebKit/Source/modules/webgl/WebGLBuffer.cpp
index a3144ee..4f8e50ef 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLBuffer.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLBuffer.cpp
@@ -25,6 +25,7 @@
 
 #include "modules/webgl/WebGLBuffer.h"
 
+#include "gpu/command_buffer/client/gles2_interface.h"
 #include "modules/webgl/WebGLRenderingContextBase.h"
 
 namespace blink {
@@ -39,7 +40,9 @@
     , m_initialTarget(0)
     , m_size(0)
 {
-    setObject(ctx->webContext()->createBuffer());
+    GLuint buffer;
+    ctx->contextGL()->GenBuffers(1, &buffer);
+    setObject(buffer);
 }
 
 WebGLBuffer::~WebGLBuffer()
@@ -50,7 +53,7 @@
 
 void WebGLBuffer::deleteObjectImpl(WebGraphicsContext3D* context3d, gpu::gles2::GLES2Interface* gl)
 {
-    context3d->deleteBuffer(m_object);
+    gl->DeleteBuffers(1, &m_object);
     m_object = 0;
 }
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLDrawBuffers.cpp b/third_party/WebKit/Source/modules/webgl/WebGLDrawBuffers.cpp
index bd921b84..4142408 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLDrawBuffers.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLDrawBuffers.cpp
@@ -101,7 +101,6 @@
 // static
 bool WebGLDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContextBase* webglContext)
 {
-    WebGraphicsContext3D* context = webglContext->webContext();
     gpu::gles2::GLES2Interface* gl = webglContext->contextGL();
     Extensions3DUtil* extensionsUtil = webglContext->extensionsUtil();
 
@@ -113,7 +112,8 @@
     if (maxDrawBuffers < 4 || maxColorAttachments < 4)
         return false;
 
-    Platform3DObject fbo = context->createFramebuffer();
+    GLuint fbo;
+    gl->GenFramebuffers(1, &fbo);
     gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
 
     const unsigned char* buffer = 0; // Chromium doesn't allow init data for depth/stencil tetxures.
@@ -122,15 +122,15 @@
         || extensionsUtil->supportsExtension("GL_ARB_depth_texture"));
     bool supportsDepthStencil = (extensionsUtil->supportsExtension("GL_EXT_packed_depth_stencil")
         || extensionsUtil->supportsExtension("GL_OES_packed_depth_stencil"));
-    Platform3DObject depthStencil = 0;
+    GLuint depthStencil = 0;
     if (supportsDepthStencil) {
-        depthStencil = context->createTexture();
+        gl->GenTextures(1, &depthStencil);
         gl->BindTexture(GL_TEXTURE_2D, depthStencil);
         gl->TexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_OES, 1, 1, 0, GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES, buffer);
     }
-    Platform3DObject depth = 0;
+    GLuint depth = 0;
     if (supportsDepth) {
-        depth = context->createTexture();
+        gl->GenTextures(1, &depth);
         gl->BindTexture(GL_TEXTURE_2D, depth);
         gl->TexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, buffer);
     }
@@ -139,7 +139,8 @@
     bool ok = true;
     GLint maxAllowedBuffers = std::min(maxDrawBuffers, maxColorAttachments);
     for (GLint i = 0; i < maxAllowedBuffers; ++i) {
-        Platform3DObject color = context->createTexture();
+        GLuint color;
+        gl->GenTextures(1, &color);
         colors.append(color);
         gl->BindTexture(GL_TEXTURE_2D, color);
         gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
@@ -169,14 +170,13 @@
     }
 
     webglContext->restoreCurrentFramebuffer();
-    context->deleteFramebuffer(fbo);
+    gl->DeleteFramebuffers(1, &fbo);
     webglContext->restoreCurrentTexture2D();
     if (supportsDepth)
-        context->deleteTexture(depth);
+        gl->DeleteTextures(1, &depth);
     if (supportsDepthStencil)
-        context->deleteTexture(depthStencil);
-    for (size_t i = 0; i < colors.size(); ++i)
-        context->deleteTexture(colors[i]);
+        gl->DeleteTextures(1, &depthStencil);
+    gl->DeleteTextures(colors.size(), colors.data());
     return ok;
 }
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp b/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp
index 86ebce7..43d538b 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp
@@ -201,11 +201,12 @@
 
 WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContextBase* ctx)
     : WebGLContextObject(ctx)
-    , m_object(ctx->webContext()->createFramebuffer())
+    , m_object(0)
     , m_destructionInProgress(false)
     , m_hasEverBeenBound(false)
     , m_readBuffer(GL_COLOR_ATTACHMENT0)
 {
+    ctx->contextGL()->GenFramebuffers(1, &m_object);
 }
 
 WebGLFramebuffer::~WebGLFramebuffer()
@@ -367,7 +368,7 @@
             attachment.value->onDetached(context3d, gl);
     }
 
-    context3d->deleteFramebuffer(m_object);
+    gl->DeleteFramebuffers(1, &m_object);
     m_object = 0;
 }
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.h b/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.h
index 7899c9a..ff3915f 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.h
@@ -64,7 +64,7 @@
 
     static WebGLFramebuffer* create(WebGLRenderingContextBase*);
 
-    Platform3DObject object() const { return m_object; }
+    GLuint object() const { return m_object; }
 
     void setAttachmentForBoundFramebuffer(GLenum target, GLenum attachment, GLenum texTarget, WebGLTexture*, GLint level, GLint layer);
     void setAttachmentForBoundFramebuffer(GLenum target, GLenum attachment, WebGLRenderbuffer*);
@@ -114,7 +114,7 @@
     // Check if a new drawBuffers call should be issued. This is called when we add or remove an attachment.
     void drawBuffersIfNecessary(bool force);
 
-    Platform3DObject m_object;
+    GLuint m_object;
 
     typedef HeapHashMap<GLenum, Member<WebGLAttachment>> AttachmentMap;
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLQuery.cpp b/third_party/WebKit/Source/modules/webgl/WebGLQuery.cpp
index ddebb241..1657d56 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLQuery.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLQuery.cpp
@@ -31,7 +31,9 @@
     , m_queryResultAvailable(false)
     , m_queryResult(0)
 {
-    setObject(ctx->webContext()->createQueryEXT());
+    GLuint query;
+    ctx->contextGL()->GenQueriesEXT(1, &query);
+    setObject(query);
 }
 
 void WebGLQuery::setTarget(GLenum target)
@@ -43,7 +45,7 @@
 
 void WebGLQuery::deleteObjectImpl(WebGraphicsContext3D* context3d, gpu::gles2::GLES2Interface* gl)
 {
-    context3d->deleteQueryEXT(m_object);
+    gl->DeleteQueriesEXT(1, &m_object);
     m_object = 0;
 }
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderbuffer.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderbuffer.cpp
index e71d4e6..8e4d7cd 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderbuffer.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderbuffer.cpp
@@ -25,6 +25,7 @@
 
 #include "modules/webgl/WebGLRenderbuffer.h"
 
+#include "gpu/command_buffer/client/gles2_interface.h"
 #include "modules/webgl/WebGLRenderingContextBase.h"
 
 namespace blink {
@@ -47,12 +48,14 @@
     , m_height(0)
     , m_hasEverBeenBound(false)
 {
-    setObject(ctx->webContext()->createRenderbuffer());
+    GLuint rbo;
+    ctx->contextGL()->GenRenderbuffers(1, &rbo);
+    setObject(rbo);
 }
 
 void WebGLRenderbuffer::deleteObjectImpl(WebGraphicsContext3D* context3d, gpu::gles2::GLES2Interface* gl)
 {
-    context3d->deleteRenderbuffer(m_object);
+    gl->DeleteRenderbuffers(1, &m_object);
     m_object = 0;
 }
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp
index 52b6984..458669e 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp
@@ -31,6 +31,7 @@
 #include "core/layout/LayoutBox.h"
 #include "core/loader/FrameLoader.h"
 #include "core/loader/FrameLoaderClient.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
 #include "modules/webgl/ANGLEInstancedArrays.h"
 #include "modules/webgl/CHROMIUMSubscribeUniform.h"
 #include "modules/webgl/EXTBlendMinMax.h"
@@ -61,24 +62,26 @@
 #include "platform/CheckedInt.h"
 #include "platform/graphics/gpu/DrawingBuffer.h"
 #include "public/platform/Platform.h"
+#include "public/platform/WebGraphicsContext3DProvider.h"
 
 namespace blink {
 
 PassOwnPtrWillBeRawPtr<CanvasRenderingContext> WebGLRenderingContext::Factory::create(HTMLCanvasElement* canvas, const CanvasContextCreationAttributes& attrs, Document&)
 {
     WebGLContextAttributes attributes = toWebGLContextAttributes(attrs);
-    OwnPtr<WebGraphicsContext3D> context(createWebGraphicsContext3D(canvas, attributes, 1));
-    if (!context)
+    OwnPtr<WebGraphicsContext3DProvider> contextProvider(createWebGraphicsContext3DProvider(canvas, attributes, 1));
+    if (!contextProvider)
         return nullptr;
-    OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get(), context->getGLES2Interface());
+    gpu::gles2::GLES2Interface* gl = contextProvider->contextGL();
+    OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(gl);
     if (!extensionsUtil)
         return nullptr;
     if (extensionsUtil->supportsExtension("GL_EXT_debug_marker")) {
-        String contextLabel(String::format("WebGLRenderingContext-%p", context.get()));
-        context->pushGroupMarkerEXT(contextLabel.ascii().data());
+        String contextLabel(String::format("WebGLRenderingContext-%p", contextProvider.get()));
+        gl->PushGroupMarkerEXT(0, contextLabel.ascii().data());
     }
 
-    OwnPtrWillBeRawPtr<WebGLRenderingContext> renderingContext = adoptPtrWillBeNoop(new WebGLRenderingContext(canvas, context.release(), attributes));
+    OwnPtrWillBeRawPtr<WebGLRenderingContext> renderingContext = adoptPtrWillBeNoop(new WebGLRenderingContext(canvas, contextProvider.release(), attributes));
 
     if (!renderingContext->drawingBuffer()) {
         canvas->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, "Could not create a WebGL context."));
@@ -96,8 +99,8 @@
     canvas->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, error));
 }
 
-WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassOwnPtr<WebGraphicsContext3D> context, const WebGLContextAttributes& requestedAttributes)
-    : WebGLRenderingContextBase(passedCanvas, context, requestedAttributes)
+WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassOwnPtr<WebGraphicsContext3DProvider> contextProvider, const WebGLContextAttributes& requestedAttributes)
+    : WebGLRenderingContextBase(passedCanvas, contextProvider, requestedAttributes)
 {
 }
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.h b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.h
index 0f823b25..cd41c3b6 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.h
@@ -59,7 +59,7 @@
     DECLARE_VIRTUAL_TRACE();
 
 private:
-    WebGLRenderingContext(HTMLCanvasElement*, PassOwnPtr<WebGraphicsContext3D>, const WebGLContextAttributes&);
+    WebGLRenderingContext(HTMLCanvasElement*, PassOwnPtr<WebGraphicsContext3DProvider>, const WebGLContextAttributes&);
 
     // Enabled extension objects.
     PersistentWillBeMember<ANGLEInstancedArrays> m_angleInstancedArrays;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
index cc97dc8..e156684 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -94,9 +94,12 @@
 #include "platform/graphics/gpu/AcceleratedImageBufferSurface.h"
 #include "platform/graphics/gpu/DrawingBuffer.h"
 #include "public/platform/Platform.h"
+#include "public/platform/WebGraphicsContext3D.h"
+#include "public/platform/WebGraphicsContext3DProvider.h"
 #include "wtf/ArrayBufferContents.h"
 #include "wtf/PassOwnPtr.h"
 #include "wtf/text/StringBuilder.h"
+#include "wtf/text/StringUTF8Adaptor.h"
 
 namespace blink {
 
@@ -563,7 +566,7 @@
     return statusMessage;
 }
 
-PassOwnPtr<WebGraphicsContext3D> WebGLRenderingContextBase::createWebGraphicsContext3D(HTMLCanvasElement* canvas, WebGLContextAttributes attributes, unsigned webGLVersion)
+PassOwnPtr<WebGraphicsContext3DProvider> WebGLRenderingContextBase::createWebGraphicsContext3DProvider(HTMLCanvasElement* canvas, WebGLContextAttributes attributes, unsigned webGLVersion)
 {
     Document& document = canvas->document();
     LocalFrame* frame = document.frame();
@@ -583,18 +586,19 @@
     WebGraphicsContext3D::Attributes wgc3dAttributes = toWebGraphicsContext3DAttributes(attributes, document.topDocument().url().getString(), settings, webGLVersion);
     WebGraphicsContext3D::WebGraphicsInfo glInfo;
     glInfo.testFailContext = shouldFailContextCreationForTesting;
-    OwnPtr<WebGraphicsContext3D> context = adoptPtr(Platform::current()->createOffscreenGraphicsContext3D(wgc3dAttributes, 0, &glInfo));
-    if (!context || shouldFailContextCreationForTesting) {
+    OwnPtr<WebGraphicsContext3DProvider> contextProvider = adoptPtr(Platform::current()->createOffscreenGraphicsContext3DProvider(wgc3dAttributes, 0, &glInfo));
+    if (!contextProvider || shouldFailContextCreationForTesting) {
         shouldFailContextCreationForTesting = false;
         canvas->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, extractWebGLContextCreationError(glInfo)));
         return nullptr;
     }
-    if (context->getString(GL_EXTENSIONS).utf8().find("GL_OES_packed_depth_stencil") == std::string::npos) {
+    gpu::gles2::GLES2Interface* gl = contextProvider->contextGL();
+    if (!String(gl->GetString(GL_EXTENSIONS)).contains("GL_OES_packed_depth_stencil")) {
         canvas->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, "OES_packed_depth_stencil support is required."));
         return nullptr;
     }
 
-    return context.release();
+    return contextProvider.release();
 }
 
 void WebGLRenderingContextBase::forceNextWebGLContextCreationToFail()
@@ -839,7 +843,7 @@
 
 } // namespace
 
-WebGLRenderingContextBase::WebGLRenderingContextBase(HTMLCanvasElement* passedCanvas, PassOwnPtr<WebGraphicsContext3D> context, const WebGLContextAttributes& requestedAttributes)
+WebGLRenderingContextBase::WebGLRenderingContextBase(HTMLCanvasElement* passedCanvas, PassOwnPtr<WebGraphicsContext3DProvider> contextProvider, const WebGLContextAttributes& requestedAttributes)
     : CanvasRenderingContext(passedCanvas)
     , m_isHidden(false)
     , m_contextLostMode(NotLostContext)
@@ -865,16 +869,15 @@
     , m_weakPtrFactory(this)
 #endif
 {
-    ASSERT(context);
-    gpu::gles2::GLES2Interface* gl = context->getGLES2Interface();
+    ASSERT(contextProvider);
 
     m_contextGroup = WebGLContextGroup::create();
     m_contextGroup->addContext(this);
 
     m_maxViewportDims[0] = m_maxViewportDims[1] = 0;
-    gl->GetIntegerv(GL_MAX_VIEWPORT_DIMS, m_maxViewportDims);
+    contextProvider->contextGL()->GetIntegerv(GL_MAX_VIEWPORT_DIMS, m_maxViewportDims);
 
-    RefPtr<DrawingBuffer> buffer = createDrawingBuffer(context);
+    RefPtr<DrawingBuffer> buffer = createDrawingBuffer(contextProvider);
     if (!buffer) {
         m_contextLostMode = SyntheticLostContext;
         return;
@@ -896,7 +899,7 @@
     ADD_VALUES_TO_SET(m_supportedTypes, kSupportedTypesES2);
 }
 
-PassRefPtr<DrawingBuffer> WebGLRenderingContextBase::createDrawingBuffer(PassOwnPtr<WebGraphicsContext3D> context)
+PassRefPtr<DrawingBuffer> WebGLRenderingContextBase::createDrawingBuffer(PassOwnPtr<WebGraphicsContext3DProvider> contextProvider)
 {
     WebGraphicsContext3D::Attributes attrs;
     attrs.alpha = m_requestedAttributes.alpha();
@@ -905,7 +908,7 @@
     attrs.antialias = m_requestedAttributes.antialias();
     attrs.premultipliedAlpha = m_requestedAttributes.premultipliedAlpha();
     DrawingBuffer::PreserveDrawingBuffer preserve = m_requestedAttributes.preserveDrawingBuffer() ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
-    return DrawingBuffer::create(context, clampedCanvasSize(), preserve, attrs);
+    return DrawingBuffer::create(contextProvider, clampedCanvasSize(), preserve, attrs);
 }
 
 void WebGLRenderingContextBase::initializeNewContext()
@@ -996,12 +999,6 @@
     webContext()->setContextLostCallback(m_contextLostCallbackAdapter.get());
     webContext()->setErrorMessageCallback(m_errorMessageCallbackAdapter.get());
 
-    // If WebGL 2, the PRIMITIVE_RESTART_FIXED_INDEX should be always enabled.
-    // See the section <Primitive Restart is Always Enabled> in WebGL 2 spec:
-    // https://www.khronos.org/registry/webgl/specs/latest/2.0/#4.1.4
-    if (isWebGL2OrHigher())
-        contextGL()->Enable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
-
     // This ensures that the context has a valid "lastFlushID" and won't be mistakenly identified as the "least recently used" context.
     contextGL()->Flush();
 
@@ -2701,7 +2698,7 @@
     case GL_SCISSOR_TEST:
         return getBooleanParameter(scriptState, pname);
     case GL_SHADING_LANGUAGE_VERSION:
-        return WebGLAny(scriptState, "WebGL GLSL ES 1.0 (" + String(webContext()->getString(GL_SHADING_LANGUAGE_VERSION)) + ")");
+        return WebGLAny(scriptState, "WebGL GLSL ES 1.0 (" + String(contextGL()->GetString(GL_SHADING_LANGUAGE_VERSION)) + ")");
     case GL_STENCIL_BACK_FAIL:
         return getUnsignedIntParameter(scriptState, pname);
     case GL_STENCIL_BACK_FUNC:
@@ -2755,7 +2752,7 @@
     case GL_VENDOR:
         return WebGLAny(scriptState, String("WebKit"));
     case GL_VERSION:
-        return WebGLAny(scriptState, "WebGL 1.0 (" + String(webContext()->getString(GL_VERSION)) + ")");
+        return WebGLAny(scriptState, "WebGL 1.0 (" + String(contextGL()->GetString(GL_VERSION)) + ")");
     case GL_VIEWPORT:
         return getWebGLIntArrayParameter(scriptState, pname);
     case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
@@ -2765,12 +2762,12 @@
         return ScriptValue::createNull(scriptState);
     case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL:
         if (extensionEnabled(WebGLDebugRendererInfoName))
-            return WebGLAny(scriptState, webContext()->getString(GL_RENDERER));
+            return WebGLAny(scriptState, String(contextGL()->GetString(GL_RENDERER)));
         synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
         return ScriptValue::createNull(scriptState);
     case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL:
         if (extensionEnabled(WebGLDebugRendererInfoName))
-            return WebGLAny(scriptState, webContext()->getString(GL_VENDOR));
+            return WebGLAny(scriptState, String(contextGL()->GetString(GL_VENDOR)));
         synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
         return ScriptValue::createNull(scriptState);
     case GL_VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object
@@ -3717,10 +3714,16 @@
     if (isContextLost() || !validateWebGLObject("shaderSource", shader))
         return;
     String stringWithoutComments = StripComments(string).result();
+    // TODO(danakj): Make validateString reject characters > 255 (or utf16 Strings)
+    // so we don't need to use StringUTF8Adaptor.
     if (!validateString("shaderSource", stringWithoutComments))
         return;
     shader->setSource(string);
-    webContext()->shaderSource(objectOrZero(shader), stringWithoutComments.utf8().data());
+    WTF::StringUTF8Adaptor adaptor(stringWithoutComments);
+    const GLchar* shaderData = adaptor.data();
+    // TODO(danakj): Use base::saturated_cast<GLint>.
+    const GLint shaderLength = adaptor.length();
+    contextGL()->ShaderSource(objectOrZero(shader), 1, &shaderData, &shaderLength);
 }
 
 void WebGLRenderingContextBase::stencilFunc(GLenum func, GLint ref, GLuint mask)
@@ -4102,7 +4105,7 @@
         targetLevel = 0;
         targetInternalformat = GL_RGBA;
         targetType = GL_UNSIGNED_BYTE;
-        targetTexture = webContext()->createTexture();
+        contextGL()->GenTextures(1, &targetTexture);
         contextGL()->BindTexture(GL_TEXTURE_2D, targetTexture);
         contextGL()->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
         contextGL()->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -4128,7 +4131,8 @@
     }
 
     if (!possibleDirectCopy) {
-        WebGLId tmpFBO = webContext()->createFramebuffer();
+        GLuint tmpFBO;
+        contextGL()->GenFramebuffers(1, &tmpFBO);
         contextGL()->BindFramebuffer(GL_FRAMEBUFFER, tmpFBO);
         contextGL()->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, targetTexture, 0);
         contextGL()->BindTexture(texture->getTarget(), texture->object());
@@ -4137,12 +4141,12 @@
         } else if (functionType == TexSubImage2DByGPU) {
             contextGL()->CopyTexSubImage2D(target, level, xoffset, yoffset, 0, 0, canvas->width(), canvas->height());
         } else if (functionType == TexSubImage3DByGPU) {
-            webContext()->copyTexSubImage3D(target, level, xoffset, yoffset, zoffset, 0, 0, canvas->width(), canvas->height());
+            contextGL()->CopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, 0, 0, canvas->width(), canvas->height());
         }
         contextGL()->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
         restoreCurrentFramebuffer();
-        webContext()->deleteFramebuffer(tmpFBO);
-        webContext()->deleteTexture(targetTexture);
+        contextGL()->DeleteFramebuffers(1, &tmpFBO);
+        contextGL()->DeleteTextures(1, &targetTexture);
     }
 }
 
@@ -5114,10 +5118,9 @@
 Extensions3DUtil* WebGLRenderingContextBase::extensionsUtil()
 {
     if (!m_extensionsUtil) {
-        WebGraphicsContext3D* context = webContext();
         gpu::gles2::GLES2Interface* gl = contextGL();
-        m_extensionsUtil = Extensions3DUtil::create(context, gl);
-        // The only reason the ExtensionsUtil should be invalid is if the webContext is lost.
+        m_extensionsUtil = Extensions3DUtil::create(gl);
+        // The only reason the ExtensionsUtil should be invalid is if the gl context is lost.
         ASSERT(m_extensionsUtil->isValid() || gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR);
     }
     return m_extensionsUtil.get();
@@ -5987,11 +5990,12 @@
     }
 
     WebGraphicsContext3D::Attributes attributes = toWebGraphicsContext3DAttributes(m_requestedAttributes, canvas()->document().topDocument().url().getString(), settings, version());
-    OwnPtr<WebGraphicsContext3D> context = adoptPtr(Platform::current()->createOffscreenGraphicsContext3D(attributes, 0));
+    blink::WebGraphicsContext3D::WebGraphicsInfo glInfo;
+    OwnPtr<WebGraphicsContext3DProvider> contextProvider = adoptPtr(Platform::current()->createOffscreenGraphicsContext3DProvider(attributes, 0, &glInfo));
     RefPtr<DrawingBuffer> buffer;
-    if (context) {
+    if (contextProvider) {
         // Construct a new drawing buffer with the new WebGraphicsContext3D.
-        buffer = createDrawingBuffer(context.release());
+        buffer = createDrawingBuffer(contextProvider.release());
         // If DrawingBuffer::create() fails to allocate a fbo, |drawingBuffer| is set to null.
     }
     if (!buffer) {
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
index 457cea5..34afc49 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
@@ -155,7 +155,7 @@
 
     static unsigned getWebGLVersion(const CanvasRenderingContext*);
 
-    static PassOwnPtr<WebGraphicsContext3D> createWebGraphicsContext3D(HTMLCanvasElement*, WebGLContextAttributes, unsigned webGLVersion);
+    static PassOwnPtr<WebGraphicsContext3DProvider> createWebGraphicsContext3DProvider(HTMLCanvasElement*, WebGLContextAttributes, unsigned webGLVersion);
     static void forceNextWebGLContextCreationToFail();
 
     int drawingBufferWidth() const;
@@ -448,8 +448,8 @@
     friend class ScopedTexture2DRestorer;
     friend class ScopedFramebufferRestorer;
 
-    WebGLRenderingContextBase(HTMLCanvasElement*, PassOwnPtr<WebGraphicsContext3D>, const WebGLContextAttributes&);
-    PassRefPtr<DrawingBuffer> createDrawingBuffer(PassOwnPtr<WebGraphicsContext3D>);
+    WebGLRenderingContextBase(HTMLCanvasElement*, PassOwnPtr<WebGraphicsContext3DProvider>, const WebGLContextAttributes&);
+    PassRefPtr<DrawingBuffer> createDrawingBuffer(PassOwnPtr<WebGraphicsContext3DProvider>);
     void setupFlags();
 
     // CanvasRenderingContext implementation.
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLSampler.cpp b/third_party/WebKit/Source/modules/webgl/WebGLSampler.cpp
index eb4324f..2ef7eaa4 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLSampler.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLSampler.cpp
@@ -4,6 +4,7 @@
 
 #include "modules/webgl/WebGLSampler.h"
 
+#include "gpu/command_buffer/client/gles2_interface.h"
 #include "modules/webgl/WebGL2RenderingContextBase.h"
 
 namespace blink {
@@ -22,12 +23,14 @@
 WebGLSampler::WebGLSampler(WebGL2RenderingContextBase* ctx)
     : WebGLSharedPlatform3DObject(ctx)
 {
-    setObject(ctx->webContext()->createSampler());
+    GLuint sampler;
+    ctx->contextGL()->GenSamplers(1, &sampler);
+    setObject(sampler);
 }
 
 void WebGLSampler::deleteObjectImpl(WebGraphicsContext3D* context3d, gpu::gles2::GLES2Interface* gl)
 {
-    context3d->deleteSampler(m_object);
+    gl->DeleteSamplers(1, &m_object);
     m_object = 0;
 }
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLTexture.cpp b/third_party/WebKit/Source/modules/webgl/WebGLTexture.cpp
index d6ebe30..0985d33 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLTexture.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLTexture.cpp
@@ -25,6 +25,7 @@
 
 #include "modules/webgl/WebGLTexture.h"
 
+#include "gpu/command_buffer/client/gles2_interface.h"
 #include "modules/webgl/WebGLRenderingContextBase.h"
 
 namespace blink {
@@ -38,7 +39,9 @@
     : WebGLSharedPlatform3DObject(ctx)
     , m_target(0)
 {
-    setObject(ctx->webContext()->createTexture());
+    GLuint texture;
+    ctx->contextGL()->GenTextures(1, &texture);
+    setObject(texture);
 }
 
 WebGLTexture::~WebGLTexture()
@@ -59,7 +62,7 @@
 
 void WebGLTexture::deleteObjectImpl(WebGraphicsContext3D* context3d, gpu::gles2::GLES2Interface* gl)
 {
-    context3d->deleteTexture(m_object);
+    gl->DeleteTextures(1, &m_object);
     m_object = 0;
 }
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLTimerQueryEXT.cpp b/third_party/WebKit/Source/modules/webgl/WebGLTimerQueryEXT.cpp
index 5ebdd0e..8f7073d 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLTimerQueryEXT.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLTimerQueryEXT.cpp
@@ -32,7 +32,7 @@
     , m_queryResultAvailable(false)
     , m_queryResult(0)
 {
-    m_queryId = context()->webContext()->createQueryEXT();
+    context()->contextGL()->GenQueriesEXT(1, &m_queryId);
 }
 
 void WebGLTimerQueryEXT::resetCachedResult()
@@ -82,7 +82,7 @@
 
 void WebGLTimerQueryEXT::deleteObjectImpl(WebGraphicsContext3D* context3d, gpu::gles2::GLES2Interface* gl)
 {
-    context3d->deleteQueryEXT(m_queryId);
+    gl->DeleteQueriesEXT(1, &m_queryId);
     m_queryId = 0;
 }
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLTransformFeedback.cpp b/third_party/WebKit/Source/modules/webgl/WebGLTransformFeedback.cpp
index f4075ad..80cc902e 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLTransformFeedback.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLTransformFeedback.cpp
@@ -4,6 +4,7 @@
 
 #include "modules/webgl/WebGLTransformFeedback.h"
 
+#include "gpu/command_buffer/client/gles2_interface.h"
 #include "modules/webgl/WebGL2RenderingContextBase.h"
 
 namespace blink {
@@ -26,12 +27,14 @@
     , m_paused(false)
     , m_program(nullptr)
 {
-    setObject(ctx->webContext()->createTransformFeedback());
+    GLuint tf;
+    ctx->contextGL()->GenTransformFeedbacks(1, &tf);
+    setObject(tf);
 }
 
 void WebGLTransformFeedback::deleteObjectImpl(WebGraphicsContext3D* context3d, gpu::gles2::GLES2Interface* gl)
 {
-    context3d->deleteTransformFeedback(m_object);
+    gl->DeleteTransformFeedbacks(1, &m_object);
     m_object = 0;
 }
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLVertexArrayObjectBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLVertexArrayObjectBase.cpp
index 3861be1..802f062 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLVertexArrayObjectBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLVertexArrayObjectBase.cpp
@@ -4,6 +4,7 @@
 
 #include "modules/webgl/WebGLVertexArrayObjectBase.h"
 
+#include "gpu/command_buffer/client/gles2_interface.h"
 #include "modules/webgl/WebGLRenderingContextBase.h"
 
 namespace blink {
@@ -22,7 +23,7 @@
     case VaoTypeDefault:
         break;
     default:
-        m_object = context()->webContext()->createVertexArrayOES();
+        context()->contextGL()->GenVertexArraysOES(1, &m_object);
         break;
     }
 }
@@ -55,7 +56,7 @@
     case VaoTypeDefault:
         break;
     default:
-        context3d->deleteVertexArrayOES(m_object);
+        gl->DeleteVertexArraysOES(1, &m_object);
         m_object = 0;
         break;
     }
diff --git a/third_party/WebKit/Source/modules/webusb/USBDevice.cpp b/third_party/WebKit/Source/modules/webusb/USBDevice.cpp
index 48b387f..54ec6d9 100644
--- a/third_party/WebKit/Source/modules/webusb/USBDevice.cpp
+++ b/third_party/WebKit/Source/modules/webusb/USBDevice.cpp
@@ -30,6 +30,7 @@
 const char kInterfaceNotFound[] = "The interface number provided is not supported by the device in its current configuration.";
 const char kInterfaceStateChangeInProgress[] = "An operation that changes interface state is in progress.";
 const char kOpenRequired[] = "The device must be opened first.";
+const char kVisibiltyError[] = "Connection is only allowed while the page is visible. This is a temporary measure until we are able to effectively communicate to the user that the page is connected to a device.";
 
 DOMException* convertControlTransferParameters(
     WebUSBDevice::TransferDirection direction,
@@ -94,8 +95,15 @@
     {
         if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContext()->activeDOMObjectsAreStopped())
             return;
+
         m_device->onDeviceOpenedOrClosed(m_desiredState);
-        m_resolver->resolve();
+        if (m_device->page()->isPageVisible()) {
+            m_resolver->resolve();
+        } else {
+            m_device->pageVisibilityChanged();
+            m_resolver->reject(DOMException::create(SecurityError, kVisibiltyError));
+            return;
+        }
     }
 
     void onError(const WebUSBError& e) override
@@ -312,6 +320,7 @@
 
 USBDevice::USBDevice(PassOwnPtr<WebUSBDevice> device, ExecutionContext* context)
     : ContextLifecycleObserver(context)
+    , PageLifecycleObserver(toDocument(context)->page())
     , m_device(device)
     , m_opened(false)
     , m_deviceStateChangeInProgress(false)
@@ -607,13 +616,24 @@
 
 void USBDevice::contextDestroyed()
 {
-    if (m_opened)
+    if (m_opened) {
         m_device->close(new WebUSBDeviceCloseCallbacks());
+        m_opened = false;
+    }
+}
+
+void USBDevice::pageVisibilityChanged()
+{
+    if (!page()->isPageVisible() && m_opened) {
+        m_device->close(new WebUSBDeviceCloseCallbacks());
+        m_opened = false;
+    }
 }
 
 DEFINE_TRACE(USBDevice)
 {
     ContextLifecycleObserver::trace(visitor);
+    PageLifecycleObserver::trace(visitor);
 }
 
 int USBDevice::findConfigurationIndex(uint8_t configurationValue) const
@@ -648,29 +668,40 @@
     return -1;
 }
 
+bool USBDevice::ensurePageVisible(ScriptPromiseResolver* resolver) const
+{
+    if (!page()->isPageVisible()) {
+        resolver->reject(DOMException::create(SecurityError, kVisibiltyError));
+        return false;
+    }
+    return true;
+}
+
 bool USBDevice::ensureNoDeviceOrInterfaceChangeInProgress(ScriptPromiseResolver* resolver) const
 {
-    if (m_deviceStateChangeInProgress) {
+    if (!ensurePageVisible(resolver))
+        return false;
+    if (m_deviceStateChangeInProgress)
         resolver->reject(DOMException::create(InvalidStateError, kDeviceStateChangeInProgress));
-    } else if (anyInterfaceChangeInProgress()) {
+    else if (anyInterfaceChangeInProgress())
         resolver->reject(DOMException::create(InvalidStateError, kInterfaceStateChangeInProgress));
-    } else {
+    else
         return true;
-    }
     return false;
 }
 
 bool USBDevice::ensureDeviceConfigured(ScriptPromiseResolver* resolver) const
 {
-    if (!m_opened) {
-        resolver->reject(DOMException::create(InvalidStateError, kOpenRequired));
-    } else if (m_deviceStateChangeInProgress) {
+    if (!ensurePageVisible(resolver))
+        return false;
+    if (m_deviceStateChangeInProgress)
         resolver->reject(DOMException::create(InvalidStateError, kDeviceStateChangeInProgress));
-    } else if (m_configurationIndex == -1) {
+    else if (!m_opened)
+        resolver->reject(DOMException::create(InvalidStateError, kOpenRequired));
+    else if (m_configurationIndex == -1)
         resolver->reject(DOMException::create(InvalidStateError, "The device must have a configuration selected."));
-    } else {
+    else
         return true;
-    }
     return false;
 }
 
@@ -679,15 +710,14 @@
     if (!ensureDeviceConfigured(resolver))
         return false;
     int interfaceIndex = findInterfaceIndex(interfaceNumber);
-    if (interfaceIndex == -1) {
+    if (interfaceIndex == -1)
         resolver->reject(DOMException::create(NotFoundError, kInterfaceNotFound));
-    } else if (m_interfaceStateChangeInProgress.get(interfaceIndex)) {
+    else if (m_interfaceStateChangeInProgress.get(interfaceIndex))
         resolver->reject(DOMException::create(InvalidStateError, kInterfaceStateChangeInProgress));
-    } else if (!m_claimedInterfaces.get(interfaceIndex)) {
+    else if (!m_claimedInterfaces.get(interfaceIndex))
         resolver->reject(DOMException::create(InvalidStateError, "The specified interface has not been claimed."));
-    } else {
+    else
         return true;
-    }
     return false;
 }
 
diff --git a/third_party/WebKit/Source/modules/webusb/USBDevice.h b/third_party/WebKit/Source/modules/webusb/USBDevice.h
index 00c879c..7f30b53 100644
--- a/third_party/WebKit/Source/modules/webusb/USBDevice.h
+++ b/third_party/WebKit/Source/modules/webusb/USBDevice.h
@@ -9,6 +9,8 @@
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/modules/v8/UnionTypesModules.h"
 #include "core/dom/ContextLifecycleObserver.h"
+#include "core/dom/Document.h"
+#include "core/page/PageLifecycleObserver.h"
 #include "platform/heap/Handle.h"
 #include "public/platform/modules/webusb/WebUSBDevice.h"
 #include "public/platform/modules/webusb/WebUSBDeviceInfo.h"
@@ -25,7 +27,8 @@
 class USBDevice
     : public GarbageCollectedFinalized<USBDevice>
     , public ContextLifecycleObserver
-    , public ScriptWrappable {
+    , public ScriptWrappable
+    , public PageLifecycleObserver {
     WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(USBDevice);
     DEFINE_WRAPPERTYPEINFO();
 public:
@@ -85,14 +88,19 @@
     ScriptPromise isochronousTransferOut(ScriptState*, uint8_t endpointNumber, const ArrayBufferOrArrayBufferView& data, Vector<unsigned> packetLengths);
     ScriptPromise reset(ScriptState*);
 
+    // ContextLifecycleObserver interface.
     void contextDestroyed() override;
 
+    // PageLifecycleObserver interface.
+    void pageVisibilityChanged() override;
+
     DECLARE_TRACE();
 
 private:
     int findConfigurationIndex(uint8_t configurationValue) const;
     int findInterfaceIndex(uint8_t interfaceNumber) const;
     int findAlternateIndex(size_t interfaceIndex, uint8_t alternateSetting) const;
+    bool ensurePageVisible(ScriptPromiseResolver*) const;
     bool ensureNoDeviceOrInterfaceChangeInProgress(ScriptPromiseResolver*) const;
     bool ensureDeviceConfigured(ScriptPromiseResolver*) const;
     bool ensureInterfaceClaimed(uint8_t interfaceNumber, ScriptPromiseResolver*) const;
diff --git a/third_party/WebKit/Source/modules/worklet/DOMWindowWorklet.cpp b/third_party/WebKit/Source/modules/worklet/DOMWindowWorklet.cpp
deleted file mode 100644
index 07a4a32d..0000000
--- a/third_party/WebKit/Source/modules/worklet/DOMWindowWorklet.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "modules/worklet/DOMWindowWorklet.h"
-
-#include "core/frame/LocalDOMWindow.h"
-#include "core/frame/LocalFrame.h"
-#include "modules/worklet/Worklet.h"
-
-namespace blink {
-
-DOMWindowWorklet::DOMWindowWorklet(LocalDOMWindow& window)
-    : DOMWindowProperty(window.frame())
-{
-}
-
-DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(DOMWindowWorklet);
-
-const char* DOMWindowWorklet::supplementName()
-{
-    return "DOMWindowWorklet";
-}
-
-// static
-DOMWindowWorklet& DOMWindowWorklet::from(LocalDOMWindow& window)
-{
-    DOMWindowWorklet* supplement = static_cast<DOMWindowWorklet*>(WillBeHeapSupplement<LocalDOMWindow>::from(window, supplementName()));
-    if (!supplement) {
-        supplement = new DOMWindowWorklet(window);
-        provideTo(window, supplementName(), adoptPtrWillBeNoop(supplement));
-    }
-    return *supplement;
-}
-
-// static
-Worklet* DOMWindowWorklet::renderWorklet(ExecutionContext* executionContext, DOMWindow& window)
-{
-    return from(toLocalDOMWindow(window)).renderWorklet(executionContext);
-}
-
-Worklet* DOMWindowWorklet::renderWorklet(ExecutionContext* executionContext) const
-{
-    if (!m_renderWorklet && frame())
-        m_renderWorklet = Worklet::create(frame(), executionContext);
-    return m_renderWorklet.get();
-}
-
-DEFINE_TRACE(DOMWindowWorklet)
-{
-    visitor->trace(m_renderWorklet);
-    WillBeHeapSupplement<LocalDOMWindow>::trace(visitor);
-    DOMWindowProperty::trace(visitor);
-}
-
-} // namespace blink
diff --git a/third_party/WebKit/Source/modules/worklet/DOMWindowWorklet.h b/third_party/WebKit/Source/modules/worklet/DOMWindowWorklet.h
deleted file mode 100644
index fe4589e..0000000
--- a/third_party/WebKit/Source/modules/worklet/DOMWindowWorklet.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef DOMWindowWorklet_h
-#define DOMWindowWorklet_h
-
-#include "core/frame/DOMWindowProperty.h"
-#include "platform/Supplementable.h"
-#include "platform/heap/Handle.h"
-
-namespace blink {
-
-class DOMWindow;
-class ExecutionContext;
-class Worklet;
-
-class DOMWindowWorklet final : public NoBaseWillBeGarbageCollected<DOMWindowWorklet>, public WillBeHeapSupplement<LocalDOMWindow>, public DOMWindowProperty {
-    WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(DOMWindowWorklet);
-    DECLARE_EMPTY_VIRTUAL_DESTRUCTOR_WILL_BE_REMOVED(DOMWindowWorklet);
-    USING_FAST_MALLOC_WILL_BE_REMOVED(DOMWindowWorklet);
-public:
-    static DOMWindowWorklet& from(LocalDOMWindow&);
-    static Worklet* renderWorklet(ExecutionContext*, DOMWindow&);
-    Worklet* renderWorklet(ExecutionContext*) const;
-
-    DECLARE_TRACE();
-
-private:
-    explicit DOMWindowWorklet(LocalDOMWindow&);
-    static const char* supplementName();
-
-    mutable PersistentWillBeMember<Worklet> m_renderWorklet;
-};
-
-} // namespace blink
-
-#endif // DOMWindowWorklet_h
diff --git a/third_party/WebKit/Source/modules/worklet/WindowWorklet.idl b/third_party/WebKit/Source/modules/worklet/WindowWorklet.idl
deleted file mode 100644
index 8b98be2..0000000
--- a/third_party/WebKit/Source/modules/worklet/WindowWorklet.idl
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-[
-    ImplementedAs=DOMWindowWorklet,
-    RuntimeEnabled=Worklet,
-] partial interface Window {
-    [CallWith=ExecutionContext] readonly attribute Worklet renderWorklet;
-};
diff --git a/third_party/WebKit/Source/modules/worklet/Worklet.cpp b/third_party/WebKit/Source/modules/worklet/Worklet.cpp
index 1b9d032..5c04f405 100644
--- a/third_party/WebKit/Source/modules/worklet/Worklet.cpp
+++ b/third_party/WebKit/Source/modules/worklet/Worklet.cpp
@@ -15,17 +15,8 @@
 
 namespace blink {
 
-// static
-Worklet* Worklet::create(LocalFrame* frame, ExecutionContext* executionContext)
-{
-    Worklet* worklet = new Worklet(frame, executionContext);
-    worklet->suspendIfNeeded();
-    return worklet;
-}
-
-Worklet::Worklet(LocalFrame* frame, ExecutionContext* executionContext)
+Worklet::Worklet(ExecutionContext* executionContext)
     : ActiveDOMObject(executionContext)
-    , m_workletGlobalScope(WorkletGlobalScope::create(frame, executionContext->url(), executionContext->userAgent(), executionContext->getSecurityOrigin(), toIsolate(executionContext)))
 {
 }
 
@@ -72,8 +63,8 @@
         // TODO(ikilpatrick): Worklets don't have the same error behaviour
         // as workers, etc. For a SyntaxError we should reject, however if
         // the script throws a normal error, resolve. For now just resolve.
-        m_workletGlobalScope->scriptController()->evaluate(ScriptSourceCode(scriptLoader->script(), scriptLoader->url()));
-        InspectorInstrumentation::scriptImported(m_workletGlobalScope.get(), scriptLoader->identifier(), scriptLoader->script());
+        workletGlobalScope()->scriptController()->evaluate(ScriptSourceCode(scriptLoader->script(), scriptLoader->url()));
+        InspectorInstrumentation::scriptImported(workletGlobalScope(), scriptLoader->identifier(), scriptLoader->script());
         resolver->resolve();
     }
 
@@ -88,7 +79,7 @@
 
 void Worklet::stop()
 {
-    m_workletGlobalScope->scriptController()->willScheduleExecutionTermination();
+    workletGlobalScope()->scriptController()->willScheduleExecutionTermination();
 
     for (auto scriptLoader : m_scriptLoaders) {
         scriptLoader->cancel();
@@ -98,7 +89,6 @@
 DEFINE_TRACE(Worklet)
 {
     visitor->trace(m_resolvers);
-    visitor->trace(m_workletGlobalScope);
     ActiveDOMObject::trace(visitor);
 }
 
diff --git a/third_party/WebKit/Source/modules/worklet/Worklet.h b/third_party/WebKit/Source/modules/worklet/Worklet.h
index 5fda297..2523d28d 100644
--- a/third_party/WebKit/Source/modules/worklet/Worklet.h
+++ b/third_party/WebKit/Source/modules/worklet/Worklet.h
@@ -19,29 +19,30 @@
 class ScriptPromiseResolver;
 class WorkerScriptLoader;
 
-class Worklet final : public GarbageCollectedFinalized<Worklet>, public ScriptWrappable, public ActiveDOMObject {
+class Worklet : public GarbageCollectedFinalized<Worklet>, public ScriptWrappable, public ActiveDOMObject {
     DEFINE_WRAPPERTYPEINFO();
     WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(Worklet);
     WTF_MAKE_NONCOPYABLE(Worklet);
 public:
-    // The ExecutionContext argument is the parent document of the Worklet. The
-    // Worklet inherits the url and userAgent, from the document.
-    static Worklet* create(LocalFrame*, ExecutionContext*);
+    virtual WorkletGlobalScope* workletGlobalScope() const = 0;
 
+    // Worklet
     ScriptPromise import(ScriptState*, const String& url);
 
     // ActiveDOMObject
     void stop() final;
 
-    DECLARE_TRACE();
+    DECLARE_VIRTUAL_TRACE();
+
+protected:
+    // The ExecutionContext argument is the parent document of the Worklet. The
+    // Worklet inherits the url and userAgent from the document.
+    explicit Worklet(ExecutionContext*);
 
 private:
-    Worklet(LocalFrame*, ExecutionContext*);
-
     void onResponse();
     void onFinished(WorkerScriptLoader*, ScriptPromiseResolver*);
 
-    RefPtrWillBeMember<WorkletGlobalScope> m_workletGlobalScope;
     Vector<RefPtr<WorkerScriptLoader>> m_scriptLoaders;
     HeapVector<Member<ScriptPromiseResolver>> m_resolvers;
 };
diff --git a/third_party/WebKit/Source/modules/worklet/WorkletGlobalScope.cpp b/third_party/WebKit/Source/modules/worklet/WorkletGlobalScope.cpp
index 95d980c..001bc9ad 100644
--- a/third_party/WebKit/Source/modules/worklet/WorkletGlobalScope.cpp
+++ b/third_party/WebKit/Source/modules/worklet/WorkletGlobalScope.cpp
@@ -12,15 +12,6 @@
 
 namespace blink {
 
-// static
-PassRefPtrWillBeRawPtr<WorkletGlobalScope> WorkletGlobalScope::create(LocalFrame* frame, const KURL& url, const String& userAgent, PassRefPtr<SecurityOrigin> securityOrigin, v8::Isolate* isolate)
-{
-    RefPtrWillBeRawPtr<WorkletGlobalScope> workletGlobalScope = adoptRefWillBeNoop(new WorkletGlobalScope(frame, url, userAgent, securityOrigin, isolate));
-    workletGlobalScope->scriptController()->initializeContextIfNeeded();
-    MainThreadDebugger::contextCreated(workletGlobalScope->scriptController()->getScriptState(), workletGlobalScope->frame(), workletGlobalScope->getSecurityOrigin());
-    return workletGlobalScope.release();
-}
-
 WorkletGlobalScope::WorkletGlobalScope(LocalFrame* frame, const KURL& url, const String& userAgent, PassRefPtr<SecurityOrigin> securityOrigin, v8::Isolate* isolate)
     : MainThreadWorkletGlobalScope(frame)
     , m_url(url)
diff --git a/third_party/WebKit/Source/modules/worklet/WorkletGlobalScope.h b/third_party/WebKit/Source/modules/worklet/WorkletGlobalScope.h
index 6b9c66f..e8eaa2f6 100644
--- a/third_party/WebKit/Source/modules/worklet/WorkletGlobalScope.h
+++ b/third_party/WebKit/Source/modules/worklet/WorkletGlobalScope.h
@@ -31,9 +31,6 @@
     using RefCounted<WorkletGlobalScope>::deref;
 #endif
 
-    // The url, userAgent and securityOrigin arguments are inherited from the
-    // parent ExecutionContext for Worklets.
-    static PassRefPtrWillBeRawPtr<WorkletGlobalScope> create(LocalFrame*, const KURL&, const String& userAgent, PassRefPtr<SecurityOrigin>, v8::Isolate*);
     ~WorkletGlobalScope() override;
 
     bool isWorkletGlobalScope() const final { return true; }
@@ -72,14 +69,17 @@
 
     DECLARE_VIRTUAL_TRACE();
 
+protected:
+    // The url, userAgent and securityOrigin arguments are inherited from the
+    // parent ExecutionContext for Worklets.
+    WorkletGlobalScope(LocalFrame*, const KURL&, const String& userAgent, PassRefPtr<SecurityOrigin>, v8::Isolate*);
+
 private:
 #if !ENABLE(OILPAN)
     void refExecutionContext() final { ref(); }
     void derefExecutionContext() final { deref(); }
 #endif
 
-    WorkletGlobalScope(LocalFrame*, const KURL&, const String& userAgent, PassRefPtr<SecurityOrigin>, v8::Isolate*);
-
     const KURL& virtualURL() const final { return m_url; }
     KURL virtualCompleteURL(const String&) const final;
 
diff --git a/third_party/WebKit/Source/modules/worklet/WorkletGlobalScope.idl b/third_party/WebKit/Source/modules/worklet/WorkletGlobalScope.idl
index de3c347..34ae3a3 100644
--- a/third_party/WebKit/Source/modules/worklet/WorkletGlobalScope.idl
+++ b/third_party/WebKit/Source/modules/worklet/WorkletGlobalScope.idl
@@ -6,7 +6,6 @@
 
 [
     Exposed=Worklet,
-    Global=Worklet,
     RuntimeEnabled=Worklet,
     WillBeGarbageCollected,
 ] interface WorkletGlobalScope {
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
index ee44457..ad686ce2 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -50,7 +50,7 @@
 CSSIndependentTransformProperties status=experimental
 CSSMaskSourceType status=experimental
 CSSOMSmoothScroll status=experimental
-CSSPaintAPI
+CSSPaintAPI status=test, depends_on=Worklet
 CSSPropertyD status=experimental
 CSSSnapSize status=experimental
 CSSStickyPosition
@@ -109,6 +109,7 @@
 LinkPreconnect status=stable
 LinkPreload status=stable
 LinkHeader status=stable
+LinkServiceWorker status=experimental
 FractionalScrollOffsets status=experimental
 MediaCapture
 MediaCaptureFromCanvas status=experimental
diff --git a/third_party/WebKit/Source/platform/animation/TimingFunction.cpp b/third_party/WebKit/Source/platform/animation/TimingFunction.cpp
index 885376a..c7feefb 100644
--- a/third_party/WebKit/Source/platform/animation/TimingFunction.cpp
+++ b/third_party/WebKit/Source/platform/animation/TimingFunction.cpp
@@ -54,7 +54,7 @@
 {
     if (!m_bezier)
         m_bezier = adoptPtr(new UnitBezier(m_x1, m_y1, m_x2, m_y2));
-    return m_bezier->solve(fraction, accuracy);
+    return m_bezier->solveWithEpsilon(fraction, accuracy);
 }
 
 // This works by taking taking the derivative of the cubic bezier, on the y
@@ -109,8 +109,8 @@
 
     // Since our input values can be out of the range 0->1 so we must also
     // consider the minimum and maximum points.
-    double solutionMin = m_bezier->solve(*minValue, std::numeric_limits<double>::epsilon());
-    double solutionMax = m_bezier->solve(*maxValue, std::numeric_limits<double>::epsilon());
+    double solutionMin = m_bezier->solveWithEpsilon(*minValue, std::numeric_limits<double>::epsilon());
+    double solutionMax = m_bezier->solveWithEpsilon(*maxValue, std::numeric_limits<double>::epsilon());
     *minValue = std::min(std::min(solutionMin, solutionMax), 0.0);
     *maxValue = std::max(std::max(solutionMin, solutionMax), 1.0);
     *minValue = std::min(std::min(*minValue, solution1), solution2);
diff --git a/third_party/WebKit/Source/platform/animation/TimingFunctionTest.cpp b/third_party/WebKit/Source/platform/animation/TimingFunctionTest.cpp
index b2ad85c..8e5bd010 100644
--- a/third_party/WebKit/Source/platform/animation/TimingFunctionTest.cpp
+++ b/third_party/WebKit/Source/platform/animation/TimingFunctionTest.cpp
@@ -451,7 +451,7 @@
     EXPECT_EQ(1, regions.at(1).end);
 
     UnitBezier bezier = UnitBezier(x1, y1, x2, y2);
-    EXPECT_FLOAT_EQ(0.5, bezier.solve(regions.at(0).end, std::numeric_limits<double>::epsilon()));
+    EXPECT_FLOAT_EQ(0.5, bezier.solveWithEpsilon(regions.at(0).end, std::numeric_limits<double>::epsilon()));
 }
 
 static void checkCubicRegions4(double x1, double y1, double x2, double y2)
@@ -473,8 +473,8 @@
     EXPECT_EQ(1, regions.at(3).end);
 
     UnitBezier bezier = UnitBezier(x1, y1, x2, y2);
-    EXPECT_FLOAT_EQ(0.5, bezier.solve(regions.at(0).end, std::numeric_limits<double>::epsilon()));
-    EXPECT_FLOAT_EQ(0.5, bezier.solve(regions.at(1).end, std::numeric_limits<double>::epsilon()));
+    EXPECT_FLOAT_EQ(0.5, bezier.solveWithEpsilon(regions.at(0).end, std::numeric_limits<double>::epsilon()));
+    EXPECT_FLOAT_EQ(0.5, bezier.solveWithEpsilon(regions.at(1).end, std::numeric_limits<double>::epsilon()));
 }
 
 TEST_F(TimingFunctionTest, StepsPartitioning)
diff --git a/third_party/WebKit/Source/platform/animation/UnitBezier.cpp b/third_party/WebKit/Source/platform/animation/UnitBezier.cpp
new file mode 100644
index 0000000..41aeac29
--- /dev/null
+++ b/third_party/WebKit/Source/platform/animation/UnitBezier.cpp
@@ -0,0 +1,113 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/animation/UnitBezier.h"
+
+namespace blink {
+
+const double UnitBezier::kBezierEpsilon = 1e-7;
+
+UnitBezier::UnitBezier(double p1x, double p1y, double p2x, double p2y)
+{
+    initCoefficients(p1x, p1y, p2x, p2y);
+    initGradients(p1x, p1y, p2x, p2y);
+    initRange(p1y, p2y);
+}
+
+void UnitBezier::initCoefficients(double p1x, double p1y, double p2x, double p2y)
+{
+    // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
+    cx = 3.0 * p1x;
+    bx = 3.0 * (p2x - p1x) - cx;
+    ax = 1.0 - cx -bx;
+
+    cy = 3.0 * p1y;
+    by = 3.0 * (p2y - p1y) - cy;
+    ay = 1.0 - cy - by;
+}
+
+void UnitBezier::initGradients(double p1x, double p1y, double p2x, double p2y)
+{
+    // End-point gradients are used to calculate timing function results
+    // outside the range [0, 1].
+    //
+    // There are three possibilities for the gradient at each end:
+    // (1) the closest control point is not horizontally coincident with regard to
+    //     (0, 0) or (1, 1). In this case the line between the end point and
+    //     the control point is tangent to the bezier at the end point.
+    // (2) the closest control point is coincident with the end point. In
+    //     this case the line between the end point and the far control
+    //     point is tangent to the bezier at the end point.
+    // (3) the closest control point is horizontally coincident with the end
+    //     point, but vertically distinct. In this case the gradient at the
+    //     end point is Infinite. However, this causes issues when
+    //     interpolating. As a result, we break down to a simple case of
+    //     0 gradient under these conditions.
+
+    if (p1x > 0)
+        m_startGradient = p1y / p1x;
+    else if (!p1y && p2x > 0)
+        m_startGradient = p2y / p2x;
+    else
+        m_startGradient = 0;
+
+    if (p2x < 1)
+        m_endGradient = (p2y - 1) / (p2x - 1);
+    else if (p2x == 1 && p1x < 1)
+        m_endGradient = (p1y - 1) / (p1x - 1);
+    else
+        m_endGradient = 0;
+}
+
+void UnitBezier::initRange(double p1y, double p2y)
+{
+    m_rangeMin = 0;
+    m_rangeMax = 1;
+    if (0 <= p1y && p1y < 1 && 0 <= p2y && p2y <= 1)
+        return;
+
+    // Represent the function's derivative in the form at^2 + bt + c
+    // as in sampleCurveDerivativeY.
+    // (Technically this is (dy/dt)*(1/3), which is suitable for finding zeros
+    // but does not actually give the slope of the curve.)
+    const double a = 3.0 * ay;
+    const double b = 2.0 * by;
+    const double c = cy;
+
+    // Check if the derivative is constant.
+    if (std::abs(a) < kBezierEpsilon && std::abs(b) < kBezierEpsilon)
+        return;
+
+    // Zeros of the function's derivative.
+    double t1 = 0;
+    double t2 = 0;
+
+    if (std::abs(a) < kBezierEpsilon) {
+        // The function's derivative is linear.
+        t1 = -c / b;
+    } else {
+        // The function's derivative is a quadratic. We find the zeros of this
+        // quadratic using the quadratic formula.
+        double discriminant = b * b - 4 * a * c;
+        if (discriminant < 0)
+            return;
+        double discriminantSqrt = sqrt(discriminant);
+        t1 = (-b + discriminantSqrt) / (2 * a);
+        t2 = (-b - discriminantSqrt) / (2 * a);
+    }
+
+    double sol1 = 0;
+    double sol2 = 0;
+
+    if (0 < t1 && t1 < 1)
+        sol1 = sampleCurveY(t1);
+
+    if (0 < t2 && t2 < 1)
+        sol2 = sampleCurveY(t2);
+
+    m_rangeMin = std::min(std::min(m_rangeMin, sol1), sol2);
+    m_rangeMax = std::max(std::max(m_rangeMax, sol1), sol2);
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/platform/animation/UnitBezier.h b/third_party/WebKit/Source/platform/animation/UnitBezier.h
index f5a5ade..dc0db72 100644
--- a/third_party/WebKit/Source/platform/animation/UnitBezier.h
+++ b/third_party/WebKit/Source/platform/animation/UnitBezier.h
@@ -29,73 +29,42 @@
 #include "platform/PlatformExport.h"
 #include "wtf/Allocator.h"
 #include "wtf/Assertions.h"
-#include <math.h>
+
+#include <algorithm>
+#include <cmath>
 
 namespace blink {
 
-struct UnitBezier {
+struct PLATFORM_EXPORT UnitBezier {
     USING_FAST_MALLOC(UnitBezier);
 public:
-    UnitBezier(double p1x, double p1y, double p2x, double p2y)
-    {
-        // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
-        cx = 3.0 * p1x;
-        bx = 3.0 * (p2x - p1x) - cx;
-        ax = 1.0 - cx -bx;
+    UnitBezier(double p1x, double p1y, double p2x, double p2y);
 
-        cy = 3.0 * p1y;
-        by = 3.0 * (p2y - p1y) - cy;
-        ay = 1.0 - cy - by;
+    static const double kBezierEpsilon;
 
-        // End-point gradients are used to calculate timing function results
-        // outside the range [0, 1].
-        //
-        // There are three possibilities for the gradient at each end:
-        // (1) the closest control point is not horizontally coincident with regard to
-        //     (0, 0) or (1, 1). In this case the line between the end point and
-        //     the control point is tangent to the bezier at the end point.
-        // (2) the closest control point is coincident with the end point. In
-        //     this case the line between the end point and the far control
-        //     point is tangent to the bezier at the end point.
-        // (3) the closest control point is horizontally coincident with the end
-        //     point, but vertically distinct. In this case the gradient at the
-        //     end point is Infinite. However, this causes issues when
-        //     interpolating. As a result, we break down to a simple case of
-        //     0 gradient under these conditions.
-
-        if (p1x > 0)
-            m_startGradient = p1y / p1x;
-        else if (!p1y && p2x > 0)
-            m_startGradient = p2y / p2x;
-        else
-            m_startGradient = 0;
-
-        if (p2x < 1)
-            m_endGradient = (p2y - 1) / (p2x - 1);
-        else if (p2x == 1 && p1x < 1)
-            m_endGradient = (p1y - 1) / (p1x - 1);
-        else
-            m_endGradient = 0;
-    }
-
-    double sampleCurveX(double t)
+    double sampleCurveX(double t) const
     {
         // `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
         return ((ax * t + bx) * t + cx) * t;
     }
 
-    double sampleCurveY(double t)
+    double sampleCurveY(double t) const
     {
         return ((ay * t + by) * t + cy) * t;
     }
 
-    double sampleCurveDerivativeX(double t)
+    double sampleCurveDerivativeX(double t) const
     {
         return (3.0 * ax * t + 2.0 * bx) * t + cx;
     }
 
+    double sampleCurveDerivativeY(double t) const
+    {
+        return (3.0 * ay * t + 2.0 * by) * t + cy;
+    }
+
     // Given an x value, find a parametric value it came from.
-    double solveCurveX(double x, double epsilon)
+    double solveCurveX(double x, double epsilon) const
     {
         ASSERT(x >= 0.0);
         ASSERT(x <= 1.0);
@@ -138,9 +107,15 @@
         return t2;
     }
 
+    // Evaluates y at the given x.
+    double solve(double x) const
+    {
+        return solveWithEpsilon(x, kBezierEpsilon);
+    }
+
     // Evaluates y at the given x. The epsilon parameter provides a hint as to the required
     // accuracy and is not guaranteed.
-    double solve(double x, double epsilon)
+    double solveWithEpsilon(double x, double epsilon) const
     {
         if (x < 0.0)
             return 0.0 + m_startGradient * x;
@@ -149,7 +124,33 @@
         return sampleCurveY(solveCurveX(x, epsilon));
     }
 
+    // Returns an approximation of dy/dx at the given x.
+    double slope(double x) const
+    {
+        return slopeWithEpsilon(x, kBezierEpsilon);
+    }
+
+    double slopeWithEpsilon(double x, double epsilon) const
+    {
+        double t = solveCurveX(x, epsilon);
+        double dx = sampleCurveDerivativeX(t);
+        double dy = sampleCurveDerivativeY(t);
+        return dy / dx;
+    }
+
+    // Sets |min| and |max| to the bezier's minimum and maximium y values in the
+    // interval [0, 1].
+    void range(double* min, double* max) const
+    {
+        *min = m_rangeMin;
+        *max = m_rangeMax;
+    }
+
 private:
+    void initCoefficients(double p1x, double p1y, double p2x, double p2y);
+    void initGradients(double p1x, double p1y, double p2x, double p2y);
+    void initRange(double p1y, double p2y);
+
     double ax;
     double bx;
     double cx;
@@ -160,6 +161,9 @@
 
     double m_startGradient;
     double m_endGradient;
+
+    double m_rangeMin;
+    double m_rangeMax;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/animation/UnitBezierTest.cpp b/third_party/WebKit/Source/platform/animation/UnitBezierTest.cpp
index 87c7899..e5172b22 100644
--- a/third_party/WebKit/Source/platform/animation/UnitBezierTest.cpp
+++ b/third_party/WebKit/Source/platform/animation/UnitBezierTest.cpp
@@ -24,6 +24,7 @@
 
 #include "platform/animation/UnitBezier.h"
 
+#include "base/memory/scoped_ptr.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
@@ -31,61 +32,161 @@
 TEST(UnitBezierTest, BasicUse)
 {
     UnitBezier bezier(0.5, 1.0, 0.5, 1.0);
-    EXPECT_EQ(0.875, bezier.solve(0.5, 0.005));
+    EXPECT_EQ(0.875, bezier.solve(0.5));
 }
 
 TEST(UnitBezierTest, Overshoot)
 {
     UnitBezier bezier(0.5, 2.0, 0.5, 2.0);
-    EXPECT_EQ(1.625, bezier.solve(0.5, 0.005));
+    EXPECT_EQ(1.625, bezier.solve(0.5));
 }
 
 TEST(UnitBezierTest, Undershoot)
 {
     UnitBezier bezier(0.5, -1.0, 0.5, -1.0);
-    EXPECT_EQ(-0.625, bezier.solve(0.5, 0.005));
+    EXPECT_EQ(-0.625, bezier.solve(0.5));
 }
 
 TEST(UnitBezierTest, InputAtEdgeOfRange)
 {
     UnitBezier bezier(0.5, 1.0, 0.5, 1.0);
-    EXPECT_EQ(0.0, bezier.solve(0.0, 0.005));
-    EXPECT_EQ(1.0, bezier.solve(1.0, 0.005));
+    EXPECT_EQ(0.0, bezier.solve(0.0));
+    EXPECT_EQ(1.0, bezier.solve(1.0));
 }
 
 TEST(UnitBezierTest, InputOutOfRange)
 {
     UnitBezier bezier(0.5, 1.0, 0.5, 1.0);
-    EXPECT_EQ(-2.0, bezier.solve(-1.0, 0.005));
-    EXPECT_EQ(1.0, bezier.solve(2.0, 0.005));
+    EXPECT_EQ(-2.0, bezier.solve(-1.0));
+    EXPECT_EQ(1.0, bezier.solve(2.0));
 }
 
 TEST(UnitBezierTest, InputOutOfRangeLargeEpsilon)
 {
     UnitBezier bezier(0.5, 1.0, 0.5, 1.0);
-    EXPECT_EQ(-2.0, bezier.solve(-1.0, 1.0));
-    EXPECT_EQ(1.0, bezier.solve(2.0, 1.0));
+    EXPECT_EQ(-2.0, bezier.solveWithEpsilon(-1.0, 1.0));
+    EXPECT_EQ(1.0, bezier.solveWithEpsilon(2.0, 1.0));
 }
 
 TEST(UnitBezierTest, InputOutOfRangeCoincidentEndpoints)
 {
     UnitBezier bezier(0.0, 0.0, 1.0, 1.0);
-    EXPECT_EQ(-1.0, bezier.solve(-1.0, 0.005));
-    EXPECT_EQ(2.0, bezier.solve(2.0, 0.005));
+    EXPECT_EQ(-1.0, bezier.solve(-1.0));
+    EXPECT_EQ(2.0, bezier.solve(2.0));
 }
 
 TEST(UnitBezierTest, InputOutOfRangeVerticalGradient)
 {
     UnitBezier bezier(0.0, 1.0, 1.0, 0.0);
-    EXPECT_EQ(0.0, bezier.solve(-1.0, 0.005));
-    EXPECT_EQ(1.0, bezier.solve(2.0, 0.005));
+    EXPECT_EQ(0.0, bezier.solve(-1.0));
+    EXPECT_EQ(1.0, bezier.solve(2.0));
 }
 
 TEST(UnitBezierTest, InputOutOfRangeDistinctEndpoints)
 {
     UnitBezier bezier(0.1, 0.2, 0.8, 0.8);
-    EXPECT_EQ(-2.0, bezier.solve(-1.0, 0.005));
-    EXPECT_EQ(2.0, bezier.solve(2.0, 0.005));
+    EXPECT_EQ(-2.0, bezier.solve(-1.0));
+    EXPECT_EQ(2.0, bezier.solve(2.0));
+}
+
+TEST(UnitBezierTest, Range)
+{
+    double epsilon = 0.00015;
+    double min, max;
+
+    // Derivative is a constant.
+    scoped_ptr<UnitBezier> bezier(
+        new UnitBezier(0.25, (1.0 / 3.0), 0.75, (2.0 / 3.0)));
+    bezier->range(&min, &max);
+    EXPECT_EQ(0, min);
+    EXPECT_EQ(1, max);
+
+    // Derivative is linear.
+    bezier.reset(new UnitBezier(0.25, -0.5, 0.75, (-1.0 / 6.0)));
+    bezier->range(&min, &max);
+    EXPECT_NEAR(min, -0.225, epsilon);
+    EXPECT_EQ(1, max);
+
+    // Derivative has no real roots.
+    bezier.reset(new UnitBezier(0.25, 0.25, 0.75, 0.5));
+    bezier->range(&min, &max);
+    EXPECT_EQ(0, min);
+    EXPECT_EQ(1, max);
+
+    // Derivative has exactly one real root.
+    bezier.reset(new UnitBezier(0.0, 1.0, 1.0, 0.0));
+    bezier->range(&min, &max);
+    EXPECT_EQ(0, min);
+    EXPECT_EQ(1, max);
+
+    // Derivative has one root < 0 and one root > 1.
+    bezier.reset(new UnitBezier(0.25, 0.1, 0.75, 0.9));
+    bezier->range(&min, &max);
+    EXPECT_EQ(0, min);
+    EXPECT_EQ(1, max);
+
+    // Derivative has two roots in [0,1].
+    bezier.reset(new UnitBezier(0.25, 2.5, 0.75, 0.5));
+    bezier->range(&min, &max);
+    EXPECT_EQ(0, min);
+    EXPECT_NEAR(max, 1.28818, epsilon);
+    bezier.reset(new UnitBezier(0.25, 0.5, 0.75, -1.5));
+    bezier->range(&min, &max);
+    EXPECT_NEAR(min, -0.28818, epsilon);
+    EXPECT_EQ(1, max);
+
+    // Derivative has one root < 0 and one root in [0,1].
+    bezier.reset(new UnitBezier(0.25, 0.1, 0.75, 1.5));
+    bezier->range(&min, &max);
+    EXPECT_EQ(0, min);
+    EXPECT_NEAR(max, 1.10755, epsilon);
+
+    // Derivative has one root in [0,1] and one root > 1.
+    bezier.reset(new UnitBezier(0.25, -0.5, 0.75, 0.9));
+    bezier->range(&min, &max);
+    EXPECT_NEAR(min, -0.10755, epsilon);
+    EXPECT_EQ(1, max);
+
+    // Derivative has two roots < 0.
+    bezier.reset(new UnitBezier(0.25, 0.3, 0.75, 0.633));
+    bezier->range(&min, &max);
+    EXPECT_EQ(0, min);
+    EXPECT_EQ(1, max);
+
+    // Derivative has two roots > 1.
+    bezier.reset(new UnitBezier(0.25, 0.367, 0.75, 0.7));
+    bezier->range(&min, &max);
+    EXPECT_EQ(0.f, min);
+    EXPECT_EQ(1.f, max);
+}
+
+TEST(UnitBezierTest, Slope)
+{
+    UnitBezier bezier(0.25, 0.0, 0.75, 1.0);
+
+    double epsilon = 0.00015;
+
+    EXPECT_NEAR(bezier.slope(0), 0, epsilon);
+    EXPECT_NEAR(bezier.slope(0.05), 0.42170, epsilon);
+    EXPECT_NEAR(bezier.slope(0.1), 0.69778, epsilon);
+    EXPECT_NEAR(bezier.slope(0.15), 0.89121, epsilon);
+    EXPECT_NEAR(bezier.slope(0.2), 1.03184, epsilon);
+    EXPECT_NEAR(bezier.slope(0.25), 1.13576, epsilon);
+    EXPECT_NEAR(bezier.slope(0.3), 1.21239, epsilon);
+    EXPECT_NEAR(bezier.slope(0.35), 1.26751, epsilon);
+    EXPECT_NEAR(bezier.slope(0.4), 1.30474, epsilon);
+    EXPECT_NEAR(bezier.slope(0.45), 1.32628, epsilon);
+    EXPECT_NEAR(bezier.slope(0.5), 1.33333, epsilon);
+    EXPECT_NEAR(bezier.slope(0.55), 1.32628, epsilon);
+    EXPECT_NEAR(bezier.slope(0.6), 1.30474, epsilon);
+    EXPECT_NEAR(bezier.slope(0.65), 1.26751, epsilon);
+    EXPECT_NEAR(bezier.slope(0.7), 1.21239, epsilon);
+    EXPECT_NEAR(bezier.slope(0.75), 1.13576, epsilon);
+    EXPECT_NEAR(bezier.slope(0.8), 1.03184, epsilon);
+    EXPECT_NEAR(bezier.slope(0.85), 0.89121, epsilon);
+    EXPECT_NEAR(bezier.slope(0.9), 0.69778, epsilon);
+    EXPECT_NEAR(bezier.slope(0.95), 0.42170, epsilon);
+    EXPECT_NEAR(bezier.slope(1), 0, epsilon);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/blink_platform.gypi b/third_party/WebKit/Source/platform/blink_platform.gypi
index a698478..af7f59c 100644
--- a/third_party/WebKit/Source/platform/blink_platform.gypi
+++ b/third_party/WebKit/Source/platform/blink_platform.gypi
@@ -176,6 +176,7 @@
       'animation/CubicBezierControlPoints.h',
       'animation/TimingFunction.cpp',
       'animation/TimingFunction.h',
+      'animation/UnitBezier.cpp',
       'animation/UnitBezier.h',
       'audio/AudioArray.h',
       'audio/AudioBus.cpp',
@@ -1096,8 +1097,6 @@
       'web_memory_dump_provider_adapter.h',
       'web_process_memory_dump_impl.cc',
       'web_process_memory_dump_impl.h',
-      'weborigin/DatabaseIdentifier.cpp',
-      'weborigin/DatabaseIdentifier.h',
       'weborigin/KURL.cpp',
       'weborigin/KURL.h',
       'weborigin/KURLHash.h',
@@ -1220,7 +1219,6 @@
       'transforms/TransformTestHelper.h',
       'transforms/TransformationMatrixTest.cpp',
       'web_process_memory_dump_impl_test.cc',
-      'weborigin/DatabaseIdentifierTest.cpp',
       'weborigin/KnownPortsTest.cpp',
       'weborigin/KURLTest.cpp',
       'weborigin/OriginAccessEntryTest.cpp',
diff --git a/third_party/WebKit/Source/platform/exported/WebSecurityOrigin.cpp b/third_party/WebKit/Source/platform/exported/WebSecurityOrigin.cpp
index b2f4456..051232f 100644
--- a/third_party/WebKit/Source/platform/exported/WebSecurityOrigin.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebSecurityOrigin.cpp
@@ -30,7 +30,6 @@
 
 #include "public/platform/WebSecurityOrigin.h"
 
-#include "platform/weborigin/DatabaseIdentifier.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/weborigin/SecurityOrigin.h"
 #include "public/platform/WebString.h"
@@ -42,11 +41,6 @@
 class WebSecurityOriginPrivate : public SecurityOrigin {
 };
 
-WebSecurityOrigin WebSecurityOrigin::createFromDatabaseIdentifier(const WebString& databaseIdentifier)
-{
-    return WebSecurityOrigin(createSecurityOriginFromDatabaseIdentifier(databaseIdentifier));
-}
-
 WebSecurityOrigin WebSecurityOrigin::createFromString(const WebString& origin)
 {
     return WebSecurityOrigin(SecurityOrigin::createFromString(origin));
@@ -135,12 +129,6 @@
     return m_private->toString();
 }
 
-WebString WebSecurityOrigin::databaseIdentifier() const
-{
-    ASSERT(m_private);
-    return createDatabaseIdentifierFromSecurityOrigin(m_private);
-}
-
 bool WebSecurityOrigin::canAccessPasswordManager() const
 {
     ASSERT(m_private);
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
index 26b0e05..ade818e8 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -252,18 +252,13 @@
         return info;
     }
 
-    WebGraphicsContext3D* webContext = context();
     gpu::gles2::GLES2Interface* gl = contextGL();
     GLuint imageId = gl->CreateGpuMemoryBufferImageCHROMIUM(m_size.width(), m_size.height(), GL_BGRA_EXT, GC3D_SCANOUT_CHROMIUM);
     if (!imageId)
         return Canvas2DLayerBridge::ImageInfo();
 
-    GLuint textureId= webContext->createTexture();
-    if (!textureId) {
-        gl->DestroyImageCHROMIUM(imageId);
-        return Canvas2DLayerBridge::ImageInfo();
-    }
-
+    GLuint textureId;
+    gl->GenTextures(1, &textureId);
     GLenum target = GC3D_TEXTURE_RECTANGLE_ARB;
     gl->BindTexture(target, textureId);
     gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, getGLFilter());
@@ -277,7 +272,6 @@
 
 void Canvas2DLayerBridge::deleteCHROMIUMImage(ImageInfo info)
 {
-    WebGraphicsContext3D* webContext = context();
     gpu::gles2::GLES2Interface* gl = contextGL();
     if (gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR)
         return;
@@ -286,7 +280,7 @@
     gl->BindTexture(target, info.m_textureId);
     gl->ReleaseTexImage2DCHROMIUM(target, info.m_imageId);
     gl->DestroyImageCHROMIUM(info.m_imageId);
-    webContext->deleteTexture(info.m_textureId);
+    gl->DeleteTextures(1, &info.m_textureId);
     gl->BindTexture(target, 0);
 
     resetSkiaTextureBinding();
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
index 6d81dc8..9b472d6 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
@@ -224,7 +224,7 @@
     // The canvas is stored in an inverted position, so the flip semantics are reversed.
     gl->CopyTextureCHROMIUM(sourceTexture, texture, internalFormat, destType, flipY ? GL_FALSE : GL_TRUE, GL_FALSE, premultiplyAlpha ? GL_FALSE : GL_TRUE);
 
-    context->deleteTexture(sourceTexture);
+    gl->DeleteTextures(1, &sourceTexture);
 
     const GLuint64 contextFenceSync = gl->InsertFenceSyncCHROMIUM();
 
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
index ca5aa84..bc5f2285 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -89,19 +89,18 @@
 
 } // namespace
 
-PassRefPtr<DrawingBuffer> DrawingBuffer::create(PassOwnPtr<WebGraphicsContext3D> context, const IntSize& size, PreserveDrawingBuffer preserve, WebGraphicsContext3D::Attributes requestedAttributes)
+PassRefPtr<DrawingBuffer> DrawingBuffer::create(PassOwnPtr<WebGraphicsContext3DProvider> contextProvider, const IntSize& size, PreserveDrawingBuffer preserve, WebGraphicsContext3D::Attributes requestedAttributes)
 {
-    ASSERT(context);
+    ASSERT(contextProvider);
 
     if (shouldFailDrawingBufferCreationForTesting) {
         shouldFailDrawingBufferCreationForTesting = false;
         return nullptr;
     }
 
-    gpu::gles2::GLES2Interface* gl = context->getGLES2Interface();
-    OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get(), gl);
+    OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(contextProvider->contextGL());
     if (!extensionsUtil->isValid()) {
-        // This might be the first time we notice that the WebGraphicsContext3D is lost.
+        // This might be the first time we notice that the GL context is lost.
         return nullptr;
     }
     ASSERT(extensionsUtil->supportsExtension("GL_OES_packed_depth_stencil"));
@@ -120,7 +119,7 @@
     if (discardFramebufferSupported)
         extensionsUtil->ensureExtensionEnabled("GL_EXT_discard_framebuffer");
 
-    RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(std::move(context), gl, extensionsUtil.release(), multisampleSupported, discardFramebufferSupported, preserve, requestedAttributes));
+    RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(std::move(contextProvider), extensionsUtil.release(), multisampleSupported, discardFramebufferSupported, preserve, requestedAttributes));
     if (!drawingBuffer->initialize(size)) {
         drawingBuffer->beginDestruction();
         return PassRefPtr<DrawingBuffer>();
@@ -133,15 +132,16 @@
     shouldFailDrawingBufferCreationForTesting = true;
 }
 
-DrawingBuffer::DrawingBuffer(PassOwnPtr<WebGraphicsContext3D> context, gpu::gles2::GLES2Interface* gl, PassOwnPtr<Extensions3DUtil> extensionsUtil, bool multisampleExtensionSupported, bool discardFramebufferSupported, PreserveDrawingBuffer preserve, WebGraphicsContext3D::Attributes requestedAttributes)
+DrawingBuffer::DrawingBuffer(PassOwnPtr<WebGraphicsContext3DProvider> contextProvider, PassOwnPtr<Extensions3DUtil> extensionsUtil, bool multisampleExtensionSupported, bool discardFramebufferSupported, PreserveDrawingBuffer preserve, WebGraphicsContext3D::Attributes requestedAttributes)
     : m_preserveDrawingBuffer(preserve)
     , m_scissorEnabled(false)
     , m_texture2DBinding(0)
     , m_drawFramebufferBinding(0)
     , m_readFramebufferBinding(0)
     , m_activeTextureUnit(GL_TEXTURE0)
-    , m_context(std::move(context))
-    , m_gl(gl)
+    , m_contextProvider(std::move(contextProvider))
+    , m_context(m_contextProvider->context3d())
+    , m_gl(m_contextProvider->contextGL())
     , m_extensionsUtil(std::move(extensionsUtil))
     , m_size(-1, -1)
     , m_requestedAttributes(requestedAttributes)
@@ -174,7 +174,7 @@
     ASSERT(m_destructionInProgress);
     ASSERT(m_textureMailboxes.isEmpty());
     m_layer.clear();
-    m_context.clear();
+    m_contextProvider.clear();
 #ifndef NDEBUG
     drawingBufferCounter().decrement();
 #endif
@@ -202,7 +202,7 @@
 
 WebGraphicsContext3D* DrawingBuffer::context()
 {
-    return m_context.get();
+    return m_context;
 }
 
 gpu::gles2::GLES2Interface* DrawingBuffer::contextGL()
@@ -276,12 +276,7 @@
 
     // No buffer available to recycle, create a new one.
     if (!frontColorBufferMailbox) {
-        TextureInfo newTexture = createTextureAndAllocateMemory(m_size);
-        // Bad things happened, abandon ship.
-        if (!newTexture.textureId)
-            return false;
-
-        frontColorBufferMailbox = createNewMailbox(newTexture);
+        frontColorBufferMailbox = createNewMailbox(createTextureAndAllocateMemory(m_size));
     }
 
     if (m_preserveDrawingBuffer == Discard) {
@@ -439,7 +434,7 @@
 
             deleteChromiumImageForTexture(&m_textureMailboxes[i]->textureInfo);
 
-            m_context->deleteTexture(m_textureMailboxes[i]->textureInfo.textureId);
+            m_gl->DeleteTextures(1, &m_textureMailboxes[i]->textureInfo.textureId);
             m_textureMailboxes.remove(i);
             return;
         }
@@ -469,7 +464,7 @@
     }
     m_sampleCount = std::min(4, maxSampleCount);
 
-    m_fbo = m_context->createFramebuffer();
+    m_gl->GenFramebuffers(1, &m_fbo);
 
     m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
     createSecondaryBuffers();
@@ -550,7 +545,7 @@
 
     gl->CopyTextureCHROMIUM(sourceTexture, texture, internalFormat, destType, flipY, unpackPremultiplyAlphaNeeded, unpackUnpremultiplyAlphaNeeded);
 
-    context->deleteTexture(sourceTexture);
+    gl->DeleteTextures(1, &sourceTexture);
 
     const GLuint64 fenceSync = gl->InsertFenceSyncCHROMIUM();
 
@@ -601,20 +596,20 @@
         deleteMailbox(m_recycledMailboxQueue.takeLast());
 
     if (m_multisampleFBO)
-        m_context->deleteFramebuffer(m_multisampleFBO);
+        m_gl->DeleteFramebuffers(1, &m_multisampleFBO);
 
     if (m_fbo)
-        m_context->deleteFramebuffer(m_fbo);
+        m_gl->DeleteFramebuffers(1, &m_fbo);
 
     if (m_multisampleColorBuffer)
-        m_context->deleteRenderbuffer(m_multisampleColorBuffer);
+        m_gl->DeleteRenderbuffers(1, &m_multisampleColorBuffer);
 
     if (m_depthStencilBuffer)
-        m_context->deleteRenderbuffer(m_depthStencilBuffer);
+        m_gl->DeleteRenderbuffers(1, &m_depthStencilBuffer);
 
     if (m_colorBuffer.textureId) {
         deleteChromiumImageForTexture(&m_colorBuffer);
-        m_context->deleteTexture(m_colorBuffer.textureId);
+        m_gl->DeleteTextures(1, &m_colorBuffer.textureId);
     }
 
     setSize(IntSize());
@@ -632,16 +627,13 @@
 
 WebGLId DrawingBuffer::createColorTexture(const TextureParameters& parameters)
 {
-    WebGLId offscreenColorTexture = m_context->createTexture();
-    if (!offscreenColorTexture)
-        return 0;
-
+    GLuint offscreenColorTexture;
+    m_gl->GenTextures(1, &offscreenColorTexture);
     m_gl->BindTexture(parameters.target, offscreenColorTexture);
     m_gl->TexParameteri(parameters.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     m_gl->TexParameteri(parameters.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     m_gl->TexParameteri(parameters.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     m_gl->TexParameteri(parameters.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
     return offscreenColorTexture;
 }
 
@@ -649,9 +641,9 @@
 {
     // create a multisample FBO
     if (m_antiAliasingMode == MSAAExplicitResolve) {
-        m_multisampleFBO = m_context->createFramebuffer();
+        m_gl->GenFramebuffers(1, &m_multisampleFBO);
         m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
-        m_multisampleColorBuffer = m_context->createRenderbuffer();
+        m_gl->GenRenderbuffers(1, &m_multisampleColorBuffer);
     }
 }
 
@@ -692,7 +684,7 @@
         return;
 
     if (!m_depthStencilBuffer)
-        m_depthStencilBuffer = m_context->createRenderbuffer();
+        m_gl->GenRenderbuffers(1, &m_depthStencilBuffer);
     m_gl->BindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer);
     if (m_antiAliasingMode == MSAAImplicitResolve)
         m_gl->RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_sampleCount, GL_DEPTH24_STENCIL8_OES, size.width(), size.height());
@@ -878,9 +870,9 @@
 
     WTF::ArrayBufferContents pixels(width * height, 4, WTF::ArrayBufferContents::NotShared, WTF::ArrayBufferContents::DontInitialize);
 
-    GLint fbo = 0;
+    GLuint fbo = 0;
     if (sourceBuffer == FrontBuffer && m_frontColorBuffer.texInfo.textureId) {
-        fbo = m_context->createFramebuffer();
+        m_gl->GenFramebuffers(1, &fbo);
         m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
         m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_frontColorBuffer.texInfo.parameters.target, m_frontColorBuffer.texInfo.textureId, 0);
     } else {
@@ -892,7 +884,7 @@
 
     if (fbo) {
         m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_frontColorBuffer.texInfo.parameters.target, 0, 0);
-        m_context->deleteFramebuffer(fbo);
+        m_gl->DeleteFramebuffers(1, &fbo);
     }
 
     restoreFramebufferBindings();
@@ -982,11 +974,6 @@
         return createDefaultTextureAndAllocateMemory(size);
 
     WebGLId textureId = createColorTexture(parameters);
-    if (!textureId) {
-        m_gl->DestroyImageCHROMIUM(imageId);
-        return createDefaultTextureAndAllocateMemory(size);
-    }
-
     m_gl->BindTexImage2DCHROMIUM(parameters.target, imageId);
 
     TextureInfo info;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
index 856619c9..137830a8 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
@@ -63,6 +63,7 @@
 class WebExternalBitmap;
 class WebExternalTextureLayer;
 class WebGraphicsContext3D;
+class WebGraphicsContext3DProvider;
 class WebLayer;
 
 // Manages a rendering target (framebuffer + attachment) for a canvas.  Can publish its rendering
@@ -75,7 +76,7 @@
         Discard
     };
 
-    static PassRefPtr<DrawingBuffer> create(PassOwnPtr<WebGraphicsContext3D>, const IntSize&, PreserveDrawingBuffer, WebGraphicsContext3D::Attributes requestedAttributes);
+    static PassRefPtr<DrawingBuffer> create(PassOwnPtr<WebGraphicsContext3DProvider>, const IntSize&, PreserveDrawingBuffer, WebGraphicsContext3D::Attributes requestedAttributes);
     static void forceNextDrawingBufferCreationToFail();
 
     ~DrawingBuffer() override;
@@ -179,8 +180,7 @@
 
 protected: // For unittests
     DrawingBuffer(
-        PassOwnPtr<WebGraphicsContext3D>,
-        gpu::gles2::GLES2Interface*,
+        PassOwnPtr<WebGraphicsContext3DProvider>,
         PassOwnPtr<Extensions3DUtil>,
         bool multisampleExtensionSupported,
         bool discardFramebufferSupported,
@@ -304,14 +304,15 @@
     Platform3DObject m_readFramebufferBinding;
     GLenum m_activeTextureUnit;
 
-    OwnPtr<WebGraphicsContext3D> m_context;
-    gpu::gles2::GLES2Interface* m_gl; // Lifetime is tied to the m_context.
+    OwnPtr<WebGraphicsContext3DProvider> m_contextProvider;
+    WebGraphicsContext3D* m_context; // Lifetime is tied to the m_contextProvider.
+    gpu::gles2::GLES2Interface* m_gl; // Lifetime is tied to the m_contextProvider.
     OwnPtr<Extensions3DUtil> m_extensionsUtil;
     IntSize m_size;
     WebGraphicsContext3D::Attributes m_requestedAttributes;
     bool m_multisampleExtensionSupported;
     bool m_discardFramebufferSupported;
-    Platform3DObject m_fbo;
+    GLuint m_fbo;
     // DrawingBuffer's output is double-buffered. m_colorBuffer is the back buffer.
     TextureInfo m_colorBuffer;
     struct FrontBufferInfo {
@@ -323,11 +324,11 @@
     OwnPtr<SameThreadClosure> m_newMailboxCallback;
 
     // This is used when the user requests either a depth or stencil buffer.
-    Platform3DObject m_depthStencilBuffer;
+    GLuint m_depthStencilBuffer;
 
     // For multisampling.
-    Platform3DObject m_multisampleFBO;
-    Platform3DObject m_multisampleColorBuffer;
+    GLuint m_multisampleFBO;
+    GLuint m_multisampleColorBuffer;
 
     // True if our contents have been modified since the last presentation of this buffer.
     bool m_contentsChanged;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
index 44fa3e3..9b6258f 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
@@ -38,6 +38,8 @@
 #include "platform/graphics/test/MockWebGraphicsContext3D.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebExternalTextureMailbox.h"
+#include "public/platform/WebGraphicsContext3D.h"
+#include "public/platform/WebGraphicsContext3DProvider.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "wtf/RefPtr.h"
@@ -168,32 +170,39 @@
         memcpy(syncToken, &fenceSync, sizeof(fenceSync));
     }
 
-    uint32_t boundTexture() const { return m_boundTexture; }
-    uint32_t boundTextureTarget() const { return m_boundTextureTarget; }
-    uint32_t mostRecentlyWaitedSyncToken() const { return m_mostRecentlyWaitedSyncToken; }
-    uint32_t currentImageId() const { return m_currentImageId; }
+    void GenTextures(GLsizei n, GLuint* textures) override
+    {
+        static GLuint id = 1;
+        for (GLsizei i = 0; i < n; ++i)
+            textures[i] = id++;
+    }
+
+    GLuint boundTexture() const { return m_boundTexture; }
+    GLuint boundTextureTarget() const { return m_boundTextureTarget; }
+    GLuint mostRecentlyWaitedSyncToken() const { return m_mostRecentlyWaitedSyncToken; }
+    GLuint currentImageId() const { return m_currentImageId; }
     IntSize mostRecentlyProducedSize() const { return m_mostRecentlyProducedSize; }
     bool allowImageChromium() const { return m_allowImageChromium; }
 
     void setAllowImageChromium(bool allow) { m_allowImageChromium = allow; }
 
 private:
-    uint32_t m_boundTexture = 0;
-    uint32_t m_boundTextureTarget = 0;
-    uint32_t m_mostRecentlyWaitedSyncToken = 0;
+    GLuint m_boundTexture = 0;
+    GLuint m_boundTextureTarget = 0;
+    GLuint m_mostRecentlyWaitedSyncToken = 0;
     WGC3Dbyte m_currentMailboxByte = 0;
     IntSize m_mostRecentlyProducedSize;
     bool m_allowImageChromium = true;
-    uint32_t m_currentImageId = 1;
-    HashMap<uint32_t, IntSize> m_textureSizes;
-    HashMap<uint32_t, IntSize> m_imageSizes;
-    HashMap<uint32_t, uint32_t> m_imageToTextureMap;
+    GLuint m_currentImageId = 1;
+    HashMap<GLuint, IntSize> m_textureSizes;
+    HashMap<GLuint, IntSize> m_imageSizes;
+    HashMap<GLuint, GLuint> m_imageToTextureMap;
 };
 
 class WebGraphicsContext3DForTests : public MockWebGraphicsContext3D {
 public:
-    WebGraphicsContext3DForTests(PassOwnPtr<GLES2InterfaceForTests> contextGL)
-        : m_contextGL(std::move(contextGL))
+    WebGraphicsContext3DForTests(GLES2InterfaceForTests* contextGL)
+        : m_contextGL(contextGL)
     {
     }
 
@@ -215,11 +224,11 @@
 
     gpu::gles2::GLES2Interface* getGLES2Interface() override
     {
-        return m_contextGL.get();
+        return m_contextGL;
     }
 
 private:
-    OwnPtr<GLES2InterfaceForTests> m_contextGL;
+    GLES2InterfaceForTests* m_contextGL;
 };
 
 static const int initialWidth = 100;
@@ -228,10 +237,10 @@
 
 class DrawingBufferForTests : public DrawingBuffer {
 public:
-    static PassRefPtr<DrawingBufferForTests> create(PassOwnPtr<WebGraphicsContext3D> context, gpu::gles2::GLES2Interface* gl, const IntSize& size, PreserveDrawingBuffer preserve)
+    static PassRefPtr<DrawingBufferForTests> create(PassOwnPtr<WebGraphicsContext3DProvider> contextProvider, const IntSize& size, PreserveDrawingBuffer preserve)
     {
-        OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get(), gl);
-        RefPtr<DrawingBufferForTests> drawingBuffer = adoptRef(new DrawingBufferForTests(context, gl, extensionsUtil.release(), preserve));
+        OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(contextProvider->contextGL());
+        RefPtr<DrawingBufferForTests> drawingBuffer = adoptRef(new DrawingBufferForTests(contextProvider, extensionsUtil.release(), preserve));
         if (!drawingBuffer->initialize(size)) {
             drawingBuffer->beginDestruction();
             return PassRefPtr<DrawingBufferForTests>();
@@ -239,8 +248,8 @@
         return drawingBuffer.release();
     }
 
-    DrawingBufferForTests(PassOwnPtr<WebGraphicsContext3D> context, gpu::gles2::GLES2Interface* gl, PassOwnPtr<Extensions3DUtil> extensionsUtil, PreserveDrawingBuffer preserve)
-        : DrawingBuffer(context, gl, extensionsUtil, false /* multisampleExtensionSupported */, false /* discardFramebufferSupported */, preserve, WebGraphicsContext3D::Attributes())
+    DrawingBufferForTests(PassOwnPtr<WebGraphicsContext3DProvider> contextProvider, PassOwnPtr<Extensions3DUtil> extensionsUtil, PreserveDrawingBuffer preserve)
+        : DrawingBuffer(contextProvider, extensionsUtil, false /* multisampleExtensionSupported */, false /* discardFramebufferSupported */, preserve, WebGraphicsContext3D::Attributes())
         , m_live(0)
     { }
 
@@ -253,16 +262,34 @@
     bool* m_live;
 };
 
+class WebGraphicsContext3DProviderForTests : public WebGraphicsContext3DProvider {
+public:
+    WebGraphicsContext3DProviderForTests(PassOwnPtr<WebGraphicsContext3D> context, PassOwnPtr<gpu::gles2::GLES2Interface> gl)
+        : m_context(std::move(context))
+        , m_gl(std::move(gl))
+    {
+    }
+
+    WebGraphicsContext3D* context3d() override { return m_context.get(); }
+    gpu::gles2::GLES2Interface* contextGL() override { return m_gl.get(); }
+    // Not used by WebGL code.
+    GrContext* grContext() override { return nullptr; }
+
+private:
+    OwnPtr<WebGraphicsContext3D> m_context;
+    OwnPtr<gpu::gles2::GLES2Interface> m_gl;
+};
+
 class DrawingBufferTest : public Test {
 protected:
     void SetUp() override
     {
         OwnPtr<GLES2InterfaceForTests> gl = adoptPtr(new GLES2InterfaceForTests);
         m_gl = gl.get();
-        OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests(gl.release()));
+        OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests(m_gl));
         m_context = context.get();
-        m_drawingBuffer = DrawingBufferForTests::create(context.release(), m_gl,
-            IntSize(initialWidth, initialHeight), DrawingBuffer::Preserve);
+        OwnPtr<WebGraphicsContext3DProviderForTests> provider = adoptPtr(new WebGraphicsContext3DProviderForTests(context.release(), gl.release()));
+        m_drawingBuffer = DrawingBufferForTests::create(provider.release(), IntSize(initialWidth, initialHeight), DrawingBuffer::Preserve);
     }
 
     WebGraphicsContext3DForTests* webContext()
@@ -488,12 +515,13 @@
     {
         OwnPtr<GLES2InterfaceForTests> gl = adoptPtr(new GLES2InterfaceForTests);
         m_gl = gl.get();
-        OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests(gl.release()));
+        OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests(m_gl));
         m_context = context.get();
+        OwnPtr<WebGraphicsContext3DProviderForTests> provider = adoptPtr(new WebGraphicsContext3DProviderForTests(context.release(), gl.release()));
         RuntimeEnabledFeatures::setWebGLImageChromiumEnabled(true);
         m_imageId0 = webContext()->nextImageIdToBeCreated();
         EXPECT_CALL(*m_gl, BindTexImage2DMock(m_imageId0)).Times(1);
-        m_drawingBuffer = DrawingBufferForTests::create(context.release(), m_gl,
+        m_drawingBuffer = DrawingBufferForTests::create(provider.release(),
             IntSize(initialWidth, initialHeight), DrawingBuffer::Preserve);
         testing::Mock::VerifyAndClearExpectations(webContext());
     }
@@ -618,44 +646,48 @@
         }
     }
 
-    uint32_t stencilAttachment() const { return m_stencilAttachment; }
-    uint32_t depthAttachment() const { return m_depthAttachment; }
-    uint32_t depthStencilAttachment() const { return m_depthStencilAttachment; }
+    const GLubyte* GetString(GLenum type) override
+    {
+        if (type == GL_EXTENSIONS)
+            return reinterpret_cast<const GLubyte*>("GL_OES_packed_depth_stencil");
+        return reinterpret_cast<const GLubyte*>("");
+    }
+
+    void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) override
+    {
+        for (GLsizei i = 0; i < n; ++i)
+            renderbuffers[i] = m_nextGenRenderbufferId++;
+    }
+
+    GLuint stencilAttachment() const { return m_stencilAttachment; }
+    GLuint depthAttachment() const { return m_depthAttachment; }
+    GLuint depthStencilAttachment() const { return m_depthStencilAttachment; }
+    size_t numAllocatedRenderBuffer() const { return m_nextGenRenderbufferId - 1; }
 
 private:
-    uint32_t m_depthAttachment = 0;
-    uint32_t m_stencilAttachment = 0;
-    uint32_t m_depthStencilAttachment = 0;
+    GLuint m_nextGenRenderbufferId = 1;
+    GLuint m_depthAttachment = 0;
+    GLuint m_stencilAttachment = 0;
+    GLuint m_depthStencilAttachment = 0;
 };
 
 class DepthStencilTrackingContext : public MockWebGraphicsContext3D {
 public:
-    DepthStencilTrackingContext() : m_nextRenderBufferId(1) {}
+    DepthStencilTrackingContext(DepthStencilTrackingGLES2Interface* gl)
+        : m_contextGL(gl)
+    {
+    }
     ~DepthStencilTrackingContext() override {}
 
-    int numAllocatedRenderBuffer() const { return m_nextRenderBufferId - 1; }
-    WebGLId stencilAttachment() const { return m_contextGL.stencilAttachment(); }
-    WebGLId depthAttachment() const { return m_contextGL.depthAttachment(); }
-    WebGLId depthStencilAttachment() const { return m_contextGL.depthStencilAttachment(); }
+    size_t numAllocatedRenderBuffer() const { return m_contextGL->numAllocatedRenderBuffer(); }
+    WebGLId stencilAttachment() const { return m_contextGL->stencilAttachment(); }
+    WebGLId depthAttachment() const { return m_contextGL->depthAttachment(); }
+    WebGLId depthStencilAttachment() const { return m_contextGL->depthStencilAttachment(); }
 
-    WebString getString(WGC3Denum type) override
-    {
-        if (type == GL_EXTENSIONS) {
-            return WebString::fromUTF8("GL_OES_packed_depth_stencil");
-        }
-        return WebString();
-    }
-
-    WebGLId createRenderbuffer() override
-    {
-        return ++m_nextRenderBufferId;
-    }
-
-    gpu::gles2::GLES2Interface* getGLES2Interface() override { return &m_contextGL; }
+    gpu::gles2::GLES2Interface* getGLES2Interface() override { return m_contextGL; }
 
 private:
-    WebGLId m_nextRenderBufferId;
-    DepthStencilTrackingGLES2Interface m_contextGL;
+    DepthStencilTrackingGLES2Interface* m_contextGL;
 };
 
 struct DepthStencilTestCase {
@@ -667,7 +699,7 @@
 
     bool requestStencil;
     bool requestDepth;
-    int expectedRenderBuffers;
+    size_t expectedRenderBuffers;
     const char* const testCaseName;
 };
 
@@ -687,14 +719,17 @@
 
     for (size_t i = 0; i < WTF_ARRAY_LENGTH(cases); i++) {
         SCOPED_TRACE(cases[i].testCaseName);
-        OwnPtr<DepthStencilTrackingContext> context = adoptPtr(new DepthStencilTrackingContext);
+        OwnPtr<DepthStencilTrackingGLES2Interface> gl = adoptPtr(new DepthStencilTrackingGLES2Interface);
+        DepthStencilTrackingGLES2Interface* trackingGL = gl.get();
+        OwnPtr<DepthStencilTrackingContext> context = adoptPtr(new DepthStencilTrackingContext(trackingGL));
         DepthStencilTrackingContext* trackingContext = context.get();
+        OwnPtr<WebGraphicsContext3DProviderForTests> provider = adoptPtr(new WebGraphicsContext3DProviderForTests(context.release(), gl.release()));
         DrawingBuffer::PreserveDrawingBuffer preserve = DrawingBuffer::Preserve;
 
         WebGraphicsContext3D::Attributes requestedAttributes;
         requestedAttributes.stencil = cases[i].requestStencil;
         requestedAttributes.depth = cases[i].requestDepth;
-        RefPtr<DrawingBuffer> drawingBuffer = DrawingBuffer::create(context.release(), IntSize(10, 10), preserve, requestedAttributes);
+        RefPtr<DrawingBuffer> drawingBuffer = DrawingBuffer::create(provider.release(), IntSize(10, 10), preserve, requestedAttributes);
 
         EXPECT_EQ(cases[i].requestDepth, drawingBuffer->getActualAttributes().depth);
         EXPECT_EQ(cases[i].requestStencil, drawingBuffer->getActualAttributes().stencil);
@@ -755,10 +790,11 @@
         OwnPtr<GLES2InterfaceForTests> gl = adoptPtr(new GLES2InterfaceForTests);
         gl->setAllowImageChromium(false);
         m_gl = gl.get();
-        OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests(gl.release()));
+        OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests(m_gl));
         m_context = context.get();
+        OwnPtr<WebGraphicsContext3DProviderForTests> provider = adoptPtr(new WebGraphicsContext3DProviderForTests(context.release(), gl.release()));
         RuntimeEnabledFeatures::setWebGLImageChromiumEnabled(true);
-        m_drawingBuffer = DrawingBufferForTests::create(context.release(), m_gl,
+        m_drawingBuffer = DrawingBufferForTests::create(provider.release(),
             IntSize(initialWidth, initialHeight), DrawingBuffer::Preserve);
     }
 
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.cpp b/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.cpp
index ce6494c..e68bc797 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.cpp
@@ -5,7 +5,8 @@
 #include "platform/graphics/gpu/Extensions3DUtil.h"
 
 #include "gpu/command_buffer/client/gles2_interface.h"
-#include "public/platform/WebGraphicsContext3D.h"
+#include "wtf/OwnPtr.h"
+#include "wtf/PassOwnPtr.h"
 #include "wtf/text/CString.h"
 #include "wtf/text/StringHash.h"
 
@@ -23,16 +24,15 @@
 
 } // anonymous namespace
 
-PassOwnPtr<Extensions3DUtil> Extensions3DUtil::create(WebGraphicsContext3D* context, gpu::gles2::GLES2Interface* gl)
+PassOwnPtr<Extensions3DUtil> Extensions3DUtil::create(gpu::gles2::GLES2Interface* gl)
 {
-    OwnPtr<Extensions3DUtil> out = adoptPtr(new Extensions3DUtil(context, gl));
+    OwnPtr<Extensions3DUtil> out = adoptPtr(new Extensions3DUtil(gl));
     out->initializeExtensions();
     return out.release();
 }
 
-Extensions3DUtil::Extensions3DUtil(WebGraphicsContext3D* context, gpu::gles2::GLES2Interface* gl)
-    : m_context(context)
-    , m_gl(gl)
+Extensions3DUtil::Extensions3DUtil(gpu::gles2::GLES2Interface* gl)
+    : m_gl(gl)
     , m_isValid(true)
 {
 }
@@ -50,10 +50,10 @@
         return;
     }
 
-    String extensionsString = m_context->getString(GL_EXTENSIONS);
+    String extensionsString(m_gl->GetString(GL_EXTENSIONS));
     splitStringHelper(extensionsString, m_enabledExtensions);
 
-    String requestableExtensionsString = m_context->getRequestableExtensionsCHROMIUM();
+    String requestableExtensionsString(m_gl->GetRequestableExtensionsCHROMIUM());
     splitStringHelper(requestableExtensionsString, m_requestableExtensions);
 }
 
@@ -84,8 +84,8 @@
 
 bool Extensions3DUtil::canUseCopyTextureCHROMIUM(GLenum destTarget, GLenum destFormat, GLenum destType, GLint level)
 {
-    // FIXME: restriction of (RGB || RGBA)/UNSIGNED_BYTE/(Level 0) should be lifted when
-    // WebGraphicsContext3D::copyTextureCHROMIUM(...) are fully functional.
+    // TODO(zmo): restriction of (RGB || RGBA)/UNSIGNED_BYTE/(Level 0) should be lifted when
+    // GLES2Interface::CopyTextureCHROMIUM(...) are fully functional.
     if (destTarget == GL_TEXTURE_2D && (destFormat == GL_RGB || destFormat == GL_RGBA)
         && destType == GL_UNSIGNED_BYTE
         && !level)
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.h b/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.h
index 0e36c32..b6f8eab 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.h
+++ b/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.h
@@ -23,14 +23,12 @@
 
 namespace blink {
 
-class WebGraphicsContext3D;
-
 class PLATFORM_EXPORT Extensions3DUtil final {
     USING_FAST_MALLOC(Extensions3DUtil);
     WTF_MAKE_NONCOPYABLE(Extensions3DUtil);
 public:
     // Creates a new Extensions3DUtil. If the passed GLES2Interface has been spontaneously lost, returns null.
-    static PassOwnPtr<Extensions3DUtil> create(WebGraphicsContext3D*, gpu::gles2::GLES2Interface*);
+    static PassOwnPtr<Extensions3DUtil> create(gpu::gles2::GLES2Interface*);
     ~Extensions3DUtil();
 
     bool isValid() { return m_isValid; }
@@ -42,10 +40,9 @@
     static bool canUseCopyTextureCHROMIUM(GLenum destTarget, GLenum destFormat, GLenum destType, GLint level);
 
 private:
-    Extensions3DUtil(WebGraphicsContext3D*, gpu::gles2::GLES2Interface*);
+    Extensions3DUtil(gpu::gles2::GLES2Interface*);
     void initializeExtensions();
 
-    WebGraphicsContext3D* m_context;
     gpu::gles2::GLES2Interface* m_gl;
     HashSet<String> m_enabledExtensions;
     HashSet<String> m_requestableExtensions;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/SharedContextRateLimiter.cpp b/third_party/WebKit/Source/platform/graphics/gpu/SharedContextRateLimiter.cpp
index 4b0dbc74..fa3cf4f 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/SharedContextRateLimiter.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/SharedContextRateLimiter.cpp
@@ -31,7 +31,7 @@
 
     gpu::gles2::GLES2Interface* gl = m_contextProvider->contextGL();
     if (gl && gl->GetGraphicsResetStatusKHR() == GL_NO_ERROR) {
-        OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(m_contextProvider->context3d(), gl);
+        OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(gl);
         // TODO(junov): when the GLES 3.0 command buffer is ready, we could use fenceSync instead
         m_canUseSyncQueries = extensionsUtil->supportsExtension("GL_CHROMIUM_sync_query");
     }
@@ -43,12 +43,12 @@
         return;
 
     gpu::gles2::GLES2Interface* gl = m_contextProvider->contextGL();
-
     if (!gl || gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR)
         return;
 
-    WebGraphicsContext3D* context = m_contextProvider->context3d();
-    m_queries.append(m_canUseSyncQueries ? context->createQueryEXT() : 0);
+    m_queries.append(0);
+    if (m_canUseSyncQueries)
+        gl->GenQueriesEXT(1, &m_queries.last());
     if (m_canUseSyncQueries) {
         gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, m_queries.last());
         gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
@@ -57,7 +57,7 @@
         if (m_canUseSyncQueries) {
             WGC3Duint result;
             gl->GetQueryObjectuivEXT(m_queries.first(), GL_QUERY_RESULT_EXT, &result);
-            context->deleteQueryEXT(m_queries.first());
+            gl->DeleteQueriesEXT(1, &m_queries.first());
             m_queries.removeFirst();
         } else {
             gl->Finish();
@@ -73,9 +73,8 @@
 
     gpu::gles2::GLES2Interface* gl = m_contextProvider->contextGL();
     if (gl && gl->GetGraphicsResetStatusKHR() == GL_NO_ERROR) {
-        WebGraphicsContext3D* context = m_contextProvider->context3d();
         while (m_queries.size() > 0) {
-            context->deleteQueryEXT(m_queries.first());
+            gl->DeleteQueriesEXT(1, &m_queries.first());
             m_queries.removeFirst();
         }
     } else {
diff --git a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp
index aef96a3..19648b8e 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp
@@ -20,6 +20,10 @@
     if (!context.getPaintController().clientCacheIsValid(client))
         return false;
 
+    // TODO(pdr): Implement subsequence caching for spv2 (crbug.com/596983).
+    if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
+        return false;
+
     context.getPaintController().createAndAppend<CachedDisplayItem>(client, DisplayItem::CachedSubsequence);
 
 #if ENABLE(ASSERT)
diff --git a/third_party/WebKit/Source/platform/graphics/test/MockWebGraphicsContext3D.h b/third_party/WebKit/Source/platform/graphics/test/MockWebGraphicsContext3D.h
index 66f8aec..f7f3c1b 100644
--- a/third_party/WebKit/Source/platform/graphics/test/MockWebGraphicsContext3D.h
+++ b/third_party/WebKit/Source/platform/graphics/test/MockWebGraphicsContext3D.h
@@ -41,8 +41,6 @@
     {
     }
 
-    virtual WebString getRequestableExtensionsCHROMIUM() { return WebString(); }
-
     virtual void blitFramebufferCHROMIUM(WGC3Dint srcX0, WGC3Dint srcY0, WGC3Dint srcX1, WGC3Dint srcY1, WGC3Dint dstX0, WGC3Dint dstY0, WGC3Dint dstX1, WGC3Dint dstY1, WGC3Dbitfield mask, WGC3Denum filter) { }
 
     virtual bool getActiveAttrib(WebGLId program, WGC3Duint index, ActiveInfo&) { return false; }
@@ -51,48 +49,6 @@
     virtual WebString getProgramInfoLog(WebGLId program) { return WebString(); }
     virtual WebString getShaderInfoLog(WebGLId shader) { return WebString(); }
     virtual WebString getShaderSource(WebGLId shader) { return WebString(); }
-    virtual WebString getString(WGC3Denum name) { return WebString(); }
-
-    virtual void shaderSource(WebGLId shader, const WGC3Dchar* string) { }
-
-    virtual void genBuffers(WGC3Dsizei count, WebGLId* ids)
-    {
-        for (int i = 0; i < count; ++i)
-            ids[i] = 1;
-    }
-    virtual void genFramebuffers(WGC3Dsizei count, WebGLId* ids)
-    {
-        for (int i = 0; i < count; ++i)
-            ids[i] = 1;
-    }
-    virtual void genRenderbuffers(WGC3Dsizei count, WebGLId* ids)
-    {
-        for (int i = 0; i < count; ++i)
-            ids[i] = 1;
-    }
-    virtual void genTextures(WGC3Dsizei count, WebGLId* ids)
-    {
-        for (int i = 0; i < count; ++i)
-            ids[i] = m_nextTextureId++;
-    }
-
-    virtual void deleteBuffers(WGC3Dsizei count, WebGLId* ids) { }
-    virtual void deleteFramebuffers(WGC3Dsizei count, WebGLId* ids) { }
-    virtual void deleteRenderbuffers(WGC3Dsizei count, WebGLId* ids) { }
-    virtual void deleteTextures(WGC3Dsizei count, WebGLId* ids) { }
-
-    virtual WebGLId createBuffer() { return 1; }
-    virtual WebGLId createFramebuffer() { return 1; }
-    virtual WebGLId createRenderbuffer() { return 1; }
-    virtual WebGLId createTexture() { return m_nextTextureId++; }
-
-    virtual void deleteBuffer(WebGLId) { }
-    virtual void deleteFramebuffer(WebGLId) { }
-    virtual void deleteRenderbuffer(WebGLId) { }
-    virtual void deleteTexture(WebGLId) { }
-
-    virtual WebGLId createQueryEXT() { return 1; }
-    virtual void deleteQueryEXT(WebGLId) { }
 
     virtual WebString getTranslatedShaderSourceANGLE(WebGLId) { return WebString(); }
 
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageFrame.cpp b/third_party/WebKit/Source/platform/image-decoders/ImageFrame.cpp
index d7e5a06b..a2a7f2a8 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ImageFrame.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/ImageFrame.cpp
@@ -98,7 +98,8 @@
     // setSize() should only be called once, it leaks memory otherwise.
     ASSERT(!width() && !height());
 
-    m_bitmap.setInfo(SkImageInfo::MakeN32Premul(newWidth, newHeight));
+    m_bitmap.setInfo(SkImageInfo::MakeN32(newWidth, newHeight,
+        m_premultiplyAlpha ? kPremul_SkAlphaType : kUnpremul_SkAlphaType));
     if (!m_bitmap.tryAllocPixels(m_allocator, 0))
         return false;
 
@@ -120,19 +121,14 @@
 {
     m_hasAlpha = alpha;
 
-    // If the frame is not fully loaded, there will be transparent pixels,
-    // so we can't tell skia we're opaque, even for image types that logically
-    // always are (e.g. jpeg).
-    if (m_status != FrameComplete)
-        alpha = true;
-    m_bitmap.setAlphaType(alpha ? kPremul_SkAlphaType : kOpaque_SkAlphaType);
+    m_bitmap.setAlphaType(computeAlphaType());
 }
 
 void ImageFrame::setStatus(Status status)
 {
     m_status = status;
     if (m_status == FrameComplete) {
-        m_bitmap.setAlphaType(m_hasAlpha ? kPremul_SkAlphaType : kOpaque_SkAlphaType);
+        m_bitmap.setAlphaType(computeAlphaType());
         // Send pending pixels changed notifications now, because we can't do this after
         // the bitmap has been marked immutable.
         notifyBitmapIfPixelsChanged();
@@ -149,4 +145,15 @@
     setHasAlpha(true);
 }
 
+SkAlphaType ImageFrame::computeAlphaType() const
+{
+    // If the frame is not fully loaded, there will be transparent pixels,
+    // so we can't tell skia we're opaque, even for image types that logically
+    // always are (e.g. jpeg).
+    if (!m_hasAlpha && m_status == FrameComplete)
+        return kOpaque_SkAlphaType;
+
+    return m_premultiplyAlpha ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageFrame.h b/third_party/WebKit/Source/platform/image-decoders/ImageFrame.h
index 655c9ef..80b8fa3 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ImageFrame.h
+++ b/third_party/WebKit/Source/platform/image-decoders/ImageFrame.h
@@ -199,6 +199,8 @@
         return m_bitmap.height();
     }
 
+    SkAlphaType computeAlphaType() const;
+
     SkBitmap m_bitmap;
     SkBitmap::Allocator* m_allocator;
     bool m_hasAlpha;
diff --git a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoderTest.cpp
index 92d0d58..9a0d7dc5 100644
--- a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoderTest.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoderTest.cpp
@@ -516,4 +516,50 @@
     EXPECT_EQ(expectedRepetitionCount, decoder->repetitionCount()); // Expected value after decode.
 }
 
+TEST(GIFImageDecoderTest, bitmapAlphaType)
+{
+    RefPtr<SharedBuffer> fullData = readFile(decodersTestingDir, "radient.gif");
+    ASSERT_TRUE(fullData.get());
+
+    // Empirically chosen truncation size:
+    //   a) large enough to produce a partial frame &&
+    //   b) small enough to not fully decode the frame
+    const size_t kTruncateSize = 800;
+    ASSERT_TRUE(kTruncateSize < fullData->size());
+    RefPtr<SharedBuffer> partialData = SharedBuffer::create(fullData->data(), kTruncateSize);
+
+    OwnPtr<ImageDecoder> premulDecoder = adoptPtr(new GIFImageDecoder(
+        ImageDecoder::AlphaPremultiplied,
+        ImageDecoder::GammaAndColorProfileApplied,
+        ImageDecoder::noDecodedImageByteLimit));
+    OwnPtr<ImageDecoder> unpremulDecoder = adoptPtr(new GIFImageDecoder(
+        ImageDecoder::AlphaNotPremultiplied,
+        ImageDecoder::GammaAndColorProfileApplied,
+        ImageDecoder::noDecodedImageByteLimit));
+
+    // Partially decoded frame => the frame alpha type is unknown and should reflect the requested format.
+    premulDecoder->setData(partialData.get(), false);
+    ASSERT_TRUE(premulDecoder->frameCount());
+    unpremulDecoder->setData(partialData.get(), false);
+    ASSERT_TRUE(unpremulDecoder->frameCount());
+    ImageFrame* premulFrame = premulDecoder->frameBufferAtIndex(0);
+    EXPECT_TRUE(premulFrame && premulFrame->getStatus() != ImageFrame::FrameComplete);
+    EXPECT_EQ(premulFrame->bitmap().alphaType(), kPremul_SkAlphaType);
+    ImageFrame* unpremulFrame = unpremulDecoder->frameBufferAtIndex(0);
+    EXPECT_TRUE(unpremulFrame && unpremulFrame->getStatus() != ImageFrame::FrameComplete);
+    EXPECT_EQ(unpremulFrame->bitmap().alphaType(), kUnpremul_SkAlphaType);
+
+    // Fully decoded frame => the frame alpha type is known (opaque).
+    premulDecoder->setData(fullData.get(), true);
+    ASSERT_TRUE(premulDecoder->frameCount());
+    unpremulDecoder->setData(fullData.get(), true);
+    ASSERT_TRUE(unpremulDecoder->frameCount());
+    premulFrame = premulDecoder->frameBufferAtIndex(0);
+    EXPECT_TRUE(premulFrame && premulFrame->getStatus() == ImageFrame::FrameComplete);
+    EXPECT_EQ(premulFrame->bitmap().alphaType(), kOpaque_SkAlphaType);
+    unpremulFrame = unpremulDecoder->frameBufferAtIndex(0);
+    EXPECT_TRUE(unpremulFrame && unpremulFrame->getStatus() == ImageFrame::FrameComplete);
+    EXPECT_EQ(unpremulFrame->bitmap().alphaType(), kOpaque_SkAlphaType);
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/mhtml/ArchiveResource.cpp b/third_party/WebKit/Source/platform/mhtml/ArchiveResource.cpp
index 3c12174..b8d521b 100644
--- a/third_party/WebKit/Source/platform/mhtml/ArchiveResource.cpp
+++ b/third_party/WebKit/Source/platform/mhtml/ArchiveResource.cpp
@@ -38,8 +38,6 @@
     const AtomicString& textEncoding)
     : m_url(url)
     , m_contentID(contentID)
-    , m_response(
-        ResourceResponse(url, mimeType, data->size(), textEncoding, String()))
     , m_data(data)
     , m_mimeType(mimeType)
     , m_textEncoding(textEncoding)
diff --git a/third_party/WebKit/Source/platform/mhtml/ArchiveResource.h b/third_party/WebKit/Source/platform/mhtml/ArchiveResource.h
index 9391dc86..b886c4f 100644
--- a/third_party/WebKit/Source/platform/mhtml/ArchiveResource.h
+++ b/third_party/WebKit/Source/platform/mhtml/ArchiveResource.h
@@ -31,7 +31,6 @@
 
 #include "platform/SharedBuffer.h"
 #include "platform/heap/Handle.h"
-#include "platform/network/ResourceResponse.h"
 #include "platform/weborigin/KURL.h"
 #include "wtf/RefCounted.h"
 #include "wtf/RefPtr.h"
@@ -51,7 +50,6 @@
 
     const KURL& url() const { return m_url; }
     const String& contentID() const { return m_contentID; }
-    const ResourceResponse& response() const { return m_response; }
     SharedBuffer* data() const { return m_data.get(); }
     const AtomicString& mimeType() const { return m_mimeType; }
     const AtomicString& textEncoding() const { return m_textEncoding; }
@@ -68,7 +66,6 @@
 
     KURL m_url;
     String m_contentID;
-    ResourceResponse m_response;
     RefPtr<SharedBuffer> m_data;
     AtomicString m_mimeType;
     AtomicString m_textEncoding;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/DebuggerScript.js b/third_party/WebKit/Source/platform/v8_inspector/DebuggerScript.js
index f4c38439..2816c37 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/DebuggerScript.js
+++ b/third_party/WebKit/Source/platform/v8_inspector/DebuggerScript.js
@@ -270,7 +270,7 @@
     var frameCount = execState.frameCount();
     if (index >= frameCount)
         return undefined;
-    return DebuggerScript._frameMirrorToJSCallFrame(execState.frame(index), undefined, false);
+    return DebuggerScript._frameMirrorToJSCallFrame(execState.frame(index), undefined);
 }
 
 DebuggerScript.stepIntoStatement = function(execState)
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp
index c37c436..0ff1a07 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp
@@ -495,7 +495,7 @@
 {
     ASSERT(enabled());
     for (int index = 0; ; ++index) {
-        OwnPtr<JavaScriptCallFrame> frame = debugger().callFrameNoScopes(index);
+        OwnPtr<JavaScriptCallFrame> frame = debugger().callFrame(index);
         if (!frame)
             break;
         if (!isCallFrameWithUnknownScriptOrBlackboxed(frame.get()))
@@ -507,7 +507,7 @@
 bool V8DebuggerAgentImpl::isTopCallFrameBlackboxed()
 {
     ASSERT(enabled());
-    return isCallFrameWithUnknownScriptOrBlackboxed(debugger().callFrameNoScopes(0).get());
+    return isCallFrameWithUnknownScriptOrBlackboxed(debugger().callFrame(0).get());
 }
 
 bool V8DebuggerAgentImpl::isCallFrameWithUnknownScriptOrBlackboxed(JavaScriptCallFrame* frame)
@@ -653,7 +653,7 @@
 
     v8::TryCatch tryCatch(m_isolate);
 
-    OwnPtr<JavaScriptCallFrame> javaScriptCallFrame = debugger().callFrameNoScopes(remoteId->frameOrdinal());
+    OwnPtr<JavaScriptCallFrame> javaScriptCallFrame = debugger().callFrame(remoteId->frameOrdinal());
     if (!javaScriptCallFrame) {
         *errorString = "Could not find call frame with given id";
         return;
@@ -907,7 +907,7 @@
     if (!assertPaused(errorString))
         return;
     // StepOver at function return point should fallback to StepInto.
-    OwnPtr<JavaScriptCallFrame> frame = debugger().callFrameNoScopes(0);
+    OwnPtr<JavaScriptCallFrame> frame = debugger().callFrame(0);
     if (frame && frame->isAtReturn()) {
         stepInto(errorString);
         return;
@@ -1010,7 +1010,7 @@
         return;
     }
 
-    OwnPtr<JavaScriptCallFrame> javaScriptCallFrame = debugger().callFrameNoScopes(remoteId->frameOrdinal());
+    OwnPtr<JavaScriptCallFrame> javaScriptCallFrame = debugger().callFrame(remoteId->frameOrdinal());
     if (!javaScriptCallFrame) {
         *errorString = "Could not find call frame with given id";
         return;
@@ -1068,7 +1068,7 @@
     if (!injectedScript->resolveCallArgument(errorString, newValueArgument.get()).ToLocal(&newValue))
         return;
 
-    OwnPtr<JavaScriptCallFrame> javaScriptCallFrame = debugger().callFrameNoScopes(remoteId->frameOrdinal());
+    OwnPtr<JavaScriptCallFrame> javaScriptCallFrame = debugger().callFrame(remoteId->frameOrdinal());
     if (!javaScriptCallFrame) {
         *errorString = "Could not find call frame with given id";
         return;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp
index f370d79..502da99 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp
@@ -516,7 +516,7 @@
     return wrapper;
 }
 
-PassOwnPtr<JavaScriptCallFrame> V8DebuggerImpl::callFrameNoScopes(int index)
+PassOwnPtr<JavaScriptCallFrame> V8DebuggerImpl::callFrame(int index)
 {
     if (!m_isolate->InContext())
         return nullptr;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h
index 35dbac3..a462e87 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h
@@ -85,7 +85,7 @@
 
     bool setScriptSource(const String16& sourceID, const String16& newContent, bool preview, ErrorString*, Maybe<protocol::Debugger::SetScriptSourceError>*, v8::Global<v8::Object>* newCallFrames, Maybe<bool>* stackChanged);
     v8::Local<v8::Object> currentCallFrames();
-    PassOwnPtr<JavaScriptCallFrame> callFrameNoScopes(int index);
+    PassOwnPtr<JavaScriptCallFrame> callFrame(int index);
     int frameCount();
 
     bool isPaused();
diff --git a/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifier.cpp b/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifier.cpp
deleted file mode 100644
index 4d15d763..0000000
--- a/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifier.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "platform/weborigin/DatabaseIdentifier.h"
-
-#include "platform/weborigin/KURL.h"
-#include "platform/weborigin/KnownPorts.h"
-#include "platform/weborigin/SchemeRegistry.h"
-#include "platform/weborigin/SecurityOriginCache.h"
-#include "platform/weborigin/SecurityPolicy.h"
-#include "wtf/HexNumber.h"
-#include "wtf/StdLibExtras.h"
-#include "wtf/text/StringBuilder.h"
-
-namespace blink {
-
-namespace {
-
-String escapeIPv6Hostname(const String& hostname)
-{
-    // Shortest IPv6 hostname would be "[::1]".
-    if (hostname.length() < 5 || hostname[0] != '[' || hostname[hostname.length() - 1] != ']')
-        return hostname;
-
-    // Should be canonicalized before it gets this far.
-    // i.e. "[::ffff:8190:3426]" not "[::FFFF:129.144.52.38]"
-    ASSERT(!hostname.contains('.'));
-    ASSERT(hostname == hostname.lower());
-
-    String copy = hostname;
-    copy.replace(':', '_');
-    return copy;
-}
-
-String unescapeIPv6Hostname(const String& hostname)
-{
-    if (hostname.length() < 5 || hostname[0] != '[' || hostname[hostname.length() - 1] != ']')
-        return hostname;
-
-    String copy = hostname;
-    copy.replace('_', ':');
-    return copy;
-}
-
-} // namespace
-
-const int maxAllowedPort = 65535;
-
-static const char separatorCharacter = '_';
-
-PassRefPtr<SecurityOrigin> createSecurityOriginFromDatabaseIdentifier(const String& databaseIdentifier)
-{
-    if (!databaseIdentifier.containsOnlyASCII())
-        return SecurityOrigin::createUnique();
-
-    // Match restrictions in storage/common/database/database_identifier.cc
-    // TODO(jsbell): Eliminate duplicate implementations.
-    if (databaseIdentifier.contains(".."))
-        return SecurityOrigin::createUnique();
-    char forbidden[] = {'\\', '/', ':', '\0'};
-    for (auto c : forbidden) {
-        if (databaseIdentifier.contains(c))
-            return SecurityOrigin::createUnique();
-    }
-
-    // Make sure there's a first separator
-    size_t separator1 = databaseIdentifier.find(separatorCharacter);
-    if (separator1 == kNotFound)
-        return SecurityOrigin::createUnique();
-
-    // Make sure there's a second separator
-    size_t separator2 = databaseIdentifier.reverseFind(separatorCharacter);
-    if (separator2 == kNotFound)
-        return SecurityOrigin::createUnique();
-
-    // Ensure there were at least 2 separator characters. Some hostnames on intranets have
-    // underscores in them, so we'll assume that any additional underscores are part of the host.
-    if (separator1 == separator2)
-        return SecurityOrigin::createUnique();
-
-    // Make sure the port section is a valid port number or doesn't exist
-    bool portOkay;
-    int port = databaseIdentifier.right(databaseIdentifier.length() - separator2 - 1).toInt(&portOkay);
-    bool portAbsent = (separator2 == databaseIdentifier.length() - 1);
-    if (!(portOkay || portAbsent))
-        return SecurityOrigin::createUnique();
-
-    if (port < 0 || port > maxAllowedPort)
-        return SecurityOrigin::createUnique();
-
-    // Split out the 3 sections of data
-    String protocol = databaseIdentifier.substring(0, separator1);
-    String host = unescapeIPv6Hostname(databaseIdentifier.substring(separator1 + 1, separator2 - separator1 - 1));
-
-    // Make sure the components match their canonical representation so we are sure we're round tripping correctly.
-    KURL url(KURL(), protocol + "://" + host + ":" + String::number(port) + "/");
-    if (!url.isValid() || url.protocol() != protocol || url.host() != host)
-        return SecurityOrigin::createUnique();
-
-    return SecurityOrigin::create(url);
-}
-
-String createDatabaseIdentifierFromSecurityOrigin(const SecurityOrigin* securityOrigin)
-{
-    String separatorString(&separatorCharacter, 1);
-    return securityOrigin->protocol() + separatorString + escapeIPv6Hostname(securityOrigin->host()) + separatorString + String::number(securityOrigin->port());
-}
-
-} // namespace blink
diff --git a/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifier.h b/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifier.h
deleted file mode 100644
index c6985a7..0000000
--- a/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifier.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DatabaseIdentifier_h
-#define DatabaseIdentifier_h
-
-#include "platform/PlatformExport.h"
-#include "platform/weborigin/SecurityOrigin.h"
-#include "wtf/text/WTFString.h"
-
-namespace blink {
-
-PLATFORM_EXPORT PassRefPtr<SecurityOrigin> createSecurityOriginFromDatabaseIdentifier(const String&);
-PLATFORM_EXPORT String createDatabaseIdentifierFromSecurityOrigin(const SecurityOrigin*);
-
-} // namespace blink
-
-#endif // DatabaseIdentifier_h
diff --git a/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifierTest.cpp b/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifierTest.cpp
deleted file mode 100644
index feeb466f..0000000
--- a/third_party/WebKit/Source/platform/weborigin/DatabaseIdentifierTest.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "platform/weborigin/DatabaseIdentifier.h"
-
-#include "platform/weborigin/KURL.h"
-#include "platform/weborigin/SecurityOrigin.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace blink {
-
-TEST(DatabaseIdentifierTest, CreateIdentifierFromSecurityOrigin)
-{
-    struct OriginTestCase {
-        String protocol;
-        String host;
-        int port;
-        String expectedIdentifier;
-    } cases[] = {
-        {"http", "google.com", 80, "http_google.com_0"},
-        {"https", "www.google.com", 443, "https_www.google.com_0"},
-        {"http", "foo_bar_baz.org", 80, "http_foo_bar_baz.org_0"},
-        {"http", "nondefaultport.net", 8001, "http_nondefaultport.net_8001"},
-        {"http", "invalidportnumber.org", 70000, "__0"},
-        {"http", "invalidportnumber.org", -5, "__0"},
-        {"http", "%E2%98%83.unicode.com", 80, "http_xn--n3h.unicode.com_0"},
-        {"http", String::fromUTF8("\xe2\x98\x83.unicode.com"), 80, "http_xn--n3h.unicode.com_0"},
-        {"http", String::fromUTF8("\xf0\x9f\x92\xa9.unicode.com"), 80, "http_xn--ls8h.unicode.com_0"},
-        {"file", "", 0, "file__0"},
-        {"data", "", 0, "__0"},
-        {"about", "blank", 0, "__0"},
-        {"non-standard", "foobar.com", 0, "non-standard__0"},
-        {"http", "[::1]", 0, "http_[__1]_0"},
-        {"http", "[3ffe:2a00:100:7031::1]", 0, "http_[3ffe_2a00_100_7031__1]_0"},
-        {"http", "[::ffff:8190:3426]", 0, "http_[__ffff_8190_3426]_0"},
-    };
-
-    for (size_t i = 0; i < WTF_ARRAY_LENGTH(cases); ++i) {
-        RefPtr<SecurityOrigin> origin = SecurityOrigin::create(cases[i].protocol, cases[i].host, cases[i].port);
-        String identifier = createDatabaseIdentifierFromSecurityOrigin(origin.get());
-        EXPECT_EQ(cases[i].expectedIdentifier, identifier) << "test case " << origin->toString();
-    }
-}
-
-// This tests the encoding of a hostname including every character in the range [\x1f, \x80].
-TEST(DatabaseIdentifierTest, CreateIdentifierAllHostChars)
-{
-    struct Case {
-        String hostname;
-        String expected;
-        bool shouldRoundTrip;
-    } cases[] = {
-        {"x\x1Fx", "__0", false},
-
-        {"x\x20x", "http_x%20x_0", false},
-        {"x\x21x", "http_x%21x_0", false},
-        {"x\x22x", "http_x%22x_0", false},
-        {"x\x23x", "http_x_0", false}, // 'x#x', the # and following are ignored.
-        {"x\x24x", "http_x%24x_0", false},
-        {"x\x25x", "__0", false},
-        {"x\x26x", "http_x%26x_0", false},
-        {"x\x27x", "http_x%27x_0", false},
-        {"x\x28x", "http_x%28x_0", false},
-        {"x\x29x", "http_x%29x_0", false},
-        {"x\x2ax", "http_x%2ax_0", false},
-        {"x\x2bx", "http_x+x_0", false},
-        {"x\x2cx", "http_x%2cx_0", false},
-        {"x\x2dx", "http_x-x_0", true},
-        {"x\x2ex", "http_x.x_0", true},
-        {"x\x2fx", "http_x_0", false}, // 'x/x', the / and following are ignored.
-
-        {"x\x30x", "http_x0x_0", true},
-        {"x\x31x", "http_x1x_0", true},
-        {"x\x32x", "http_x2x_0", true},
-        {"x\x33x", "http_x3x_0", true},
-        {"x\x34x", "http_x4x_0", true},
-        {"x\x35x", "http_x5x_0", true},
-        {"x\x36x", "http_x6x_0", true},
-        {"x\x37x", "http_x7x_0", true},
-        {"x\x38x", "http_x8x_0", true},
-        {"x\x39x", "http_x9x_0", true},
-        {"x\x3ax", "__0", false},
-        {"x\x3bx", "__0", false},
-        {"x\x3cx", "http_x%3cx_0", false},
-        {"x\x3dx", "http_x%3dx_0", false},
-        {"x\x3ex", "http_x%3ex_0", false},
-        {"x\x3fx", "http_x_0", false}, // 'x?x', the ? and following are ignored.
-
-        {"x\x40x", "http_x_0", false}, // 'x@x', the @ and following are ignored.
-        {"x\x41x", "http_xax_0", true},
-        {"x\x42x", "http_xbx_0", true},
-        {"x\x43x", "http_xcx_0", true},
-        {"x\x44x", "http_xdx_0", true},
-        {"x\x45x", "http_xex_0", true},
-        {"x\x46x", "http_xfx_0", true},
-        {"x\x47x", "http_xgx_0", true},
-        {"x\x48x", "http_xhx_0", true},
-        {"x\x49x", "http_xix_0", true},
-        {"x\x4ax", "http_xjx_0", true},
-        {"x\x4bx", "http_xkx_0", true},
-        {"x\x4cx", "http_xlx_0", true},
-        {"x\x4dx", "http_xmx_0", true},
-        {"x\x4ex", "http_xnx_0", true},
-        {"x\x4fx", "http_xox_0", true},
-
-        {"x\x50x", "http_xpx_0", true},
-        {"x\x51x", "http_xqx_0", true},
-        {"x\x52x", "http_xrx_0", true},
-        {"x\x53x", "http_xsx_0", true},
-        {"x\x54x", "http_xtx_0", true},
-        {"x\x55x", "http_xux_0", true},
-        {"x\x56x", "http_xvx_0", true},
-        {"x\x57x", "http_xwx_0", true},
-        {"x\x58x", "http_xxx_0", true},
-        {"x\x59x", "http_xyx_0", true},
-        {"x\x5ax", "http_xzx_0", true},
-        {"x\x5bx", "__0", false},
-        {"x\x5cx", "http_x_0", false}, // "x\x", the \ and following are ignored.
-        {"x\x5dx", "__0", false},
-        {"x\x5ex", "__0", false},
-        {"x\x5fx", "http_x_x_0", true},
-
-        {"x\x60x", "http_x%60x_0", false},
-        {"x\x61x", "http_xax_0", true},
-        {"x\x62x", "http_xbx_0", true},
-        {"x\x63x", "http_xcx_0", true},
-        {"x\x64x", "http_xdx_0", true},
-        {"x\x65x", "http_xex_0", true},
-        {"x\x66x", "http_xfx_0", true},
-        {"x\x67x", "http_xgx_0", true},
-        {"x\x68x", "http_xhx_0", true},
-        {"x\x69x", "http_xix_0", true},
-        {"x\x6ax", "http_xjx_0", true},
-        {"x\x6bx", "http_xkx_0", true},
-        {"x\x6cx", "http_xlx_0", true},
-        {"x\x6dx", "http_xmx_0", true},
-        {"x\x6ex", "http_xnx_0", true},
-        {"x\x6fx", "http_xox_0", true},
-
-        {"x\x70x", "http_xpx_0", true},
-        {"x\x71x", "http_xqx_0", true},
-        {"x\x72x", "http_xrx_0", true},
-        {"x\x73x", "http_xsx_0", true},
-        {"x\x74x", "http_xtx_0", true},
-        {"x\x75x", "http_xux_0", true},
-        {"x\x76x", "http_xvx_0", true},
-        {"x\x77x", "http_xwx_0", true},
-        {"x\x78x", "http_xxx_0", true},
-        {"x\x79x", "http_xyx_0", true},
-        {"x\x7ax", "http_xzx_0", true},
-        {"x\x7bx", "http_x%7bx_0", false},
-        {"x\x7cx", "http_x%7cx_0", false},
-        {"x\x7dx", "http_x%7dx_0", false},
-        {"x\x7ex", "__0", false},
-        {"x\x7fx", "__0", false},
-
-        {"x\x80x", "__0", false},
-    };
-
-    for (size_t i = 0; i < WTF_ARRAY_LENGTH(cases); ++i) {
-        RefPtr<SecurityOrigin> origin = SecurityOrigin::create("http", cases[i].hostname, 80);
-        String identifier = createDatabaseIdentifierFromSecurityOrigin(origin.get());
-        EXPECT_EQ(cases[i].expected, identifier) << "test case " << i << ": \"" << cases[i].hostname << "\"";
-        if (cases[i].shouldRoundTrip) {
-            RefPtr<SecurityOrigin> parsedOrigin = createSecurityOriginFromDatabaseIdentifier(identifier);
-            EXPECT_EQ(cases[i].hostname.lower(), parsedOrigin->host()) << "test case " << i << ": \"" << cases[i].hostname << "\"";
-        }
-    }
-
-}
-
-TEST(DatabaseIdentifierTest, CreateSecurityOriginFromIdentifier)
-{
-    struct IdentifierTestCase {
-        String identifier;
-        String expectedProtocol;
-        String expectedHost;
-        int expectedPort;
-        String expectedStringRepresentation;
-        bool expectedUnique;
-    };
-
-    IdentifierTestCase validCases[] = {
-        {"http_google.com_0", "http", "google.com", 0, "http://google.com", false},
-        {"https_google.com_0", "https", "google.com", 0, "https://google.com", false},
-        {"ftp_google.com_0", "ftp", "google.com", 0, "ftp://google.com", false},
-        {"unknown_google.com_0", "", "", 0, "null", true},
-        {"http_nondefaultport.net_8001", "http", "nondefaultport.net", 8001, "http://nondefaultport.net:8001", false},
-        {"file__0", "", "", 0, "null", true},
-        {"__0", "", "", 0, "null", true},
-        {"http_foo_bar_baz.org_0", "http", "foo_bar_baz.org", 0, "http://foo_bar_baz.org", false},
-        {"http_xn--n3h.unicode.com_0", "http", "xn--n3h.unicode.com", 0, "http://xn--n3h.unicode.com", false},
-        {"http_dot.com_0", "http", "dot.com", 0, "http://dot.com", false},
-        {"http_escaped%3Dfun.com_0", "http", "escaped%3dfun.com", 0, "http://escaped%3dfun.com", false},
-    };
-
-    for (size_t i = 0; i < WTF_ARRAY_LENGTH(validCases); ++i) {
-        RefPtr<SecurityOrigin> origin = createSecurityOriginFromDatabaseIdentifier(validCases[i].identifier);
-        EXPECT_EQ(validCases[i].expectedProtocol, origin->protocol()) << "test case " << i;
-        EXPECT_EQ(validCases[i].expectedHost, origin->host()) << "test case " << i;
-        EXPECT_EQ(validCases[i].expectedPort, origin->port()) << "test case " << i;
-        EXPECT_EQ(validCases[i].expectedStringRepresentation, origin->toString()) << "test case " << i;
-        EXPECT_EQ(validCases[i].expectedUnique, origin->isUnique()) << "test case " << i;
-    }
-
-    String bogusIdentifiers[] = {
-        "", "_", "__",
-        String("\x00", 1),
-        String("http_\x00_0", 8),
-        "ht\x7ctp_badprotocol.com_0",
-        "http_unescaped_percent_%.com_0",
-        "http_port_too_big.net_75000",
-        "http_port_too_small.net_-25",
-        "http_shouldbeescaped\x7c.com_0",
-        "http_latin1\x8a.org_8001",
-        String::fromUTF8("http_\xe2\x98\x83.unicode.com_0"),
-        "http_dot%252ecom_0",
-        "HtTp_NonCanonicalRepresenTation_0",
-        "http_non_ascii.\xa1.com_0",
-        "http_not_canonical_escape%3d_0",
-    };
-
-    for (size_t i = 0; i < WTF_ARRAY_LENGTH(bogusIdentifiers); ++i) {
-        RefPtr<SecurityOrigin> origin = createSecurityOriginFromDatabaseIdentifier(bogusIdentifiers[i]);
-        EXPECT_EQ("null", origin->toString()) << "test case " << i;
-        EXPECT_EQ(true, origin->isUnique()) << "test case " << i;
-    }
-}
-
-} // namespace blink
diff --git a/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp b/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp
index 1c199ad..72bdb4b2 100644
--- a/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp
+++ b/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp
@@ -61,6 +61,7 @@
 #include "modules/mediasession/HTMLMediaElementMediaSession.h"
 #include "modules/mediasession/MediaSession.h"
 #include "modules/serviceworkers/NavigatorServiceWorker.h"
+#include "modules/serviceworkers/ServiceWorkerLinkResource.h"
 #include "modules/storage/DOMWindowStorageController.h"
 #include "modules/vr/NavigatorVRDevice.h"
 #include "platform/Histogram.h"
@@ -1051,4 +1052,9 @@
     }
 }
 
+PassOwnPtrWillBeRawPtr<LinkResource> FrameLoaderClientImpl::createServiceWorkerLinkResource(HTMLLinkElement* owner)
+{
+    return ServiceWorkerLinkResource::create(owner);
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/web/FrameLoaderClientImpl.h b/third_party/WebKit/Source/web/FrameLoaderClientImpl.h
index 4fbff228..945494a 100644
--- a/third_party/WebKit/Source/web/FrameLoaderClientImpl.h
+++ b/third_party/WebKit/Source/web/FrameLoaderClientImpl.h
@@ -182,6 +182,8 @@
 
     void suddenTerminationDisablerChanged(bool present, SuddenTerminationDisablerType) override;
 
+    PassOwnPtrWillBeRawPtr<LinkResource> createServiceWorkerLinkResource(HTMLLinkElement*) override;
+
 private:
     explicit FrameLoaderClientImpl(WebLocalFrameImpl*);
 
diff --git a/third_party/WebKit/Source/web/WebDatabase.cpp b/third_party/WebKit/Source/web/WebDatabase.cpp
index 1158e9e..ba77144 100644
--- a/third_party/WebKit/Source/web/WebDatabase.cpp
+++ b/third_party/WebKit/Source/web/WebDatabase.cpp
@@ -33,28 +33,29 @@
 #include "modules/webdatabase/DatabaseTracker.h"
 #include "modules/webdatabase/QuotaTracker.h"
 #include "platform/weborigin/SecurityOrigin.h"
+#include "public/platform/WebSecurityOrigin.h"
 #include "public/platform/WebString.h"
 
 namespace blink {
 
-void WebDatabase::updateDatabaseSize(const WebString& originIdentifier, const WebString& name, long long size)
+void WebDatabase::updateDatabaseSize(const WebSecurityOrigin& origin, const WebString& name, long long size)
 {
-    QuotaTracker::instance().updateDatabaseSize(originIdentifier, name, size);
+    QuotaTracker::instance().updateDatabaseSize(origin.get(), name, size);
 }
 
-void WebDatabase::updateSpaceAvailable(const WebString& originIdentifier, long long spaceAvailable)
+void WebDatabase::updateSpaceAvailable(const WebSecurityOrigin& origin, long long spaceAvailable)
 {
-    QuotaTracker::instance().updateSpaceAvailableToOrigin(originIdentifier, spaceAvailable);
+    QuotaTracker::instance().updateSpaceAvailableToOrigin(origin.get(), spaceAvailable);
 }
 
-void WebDatabase::resetSpaceAvailable(const WebString& originIdentifier)
+void WebDatabase::resetSpaceAvailable(const WebSecurityOrigin& origin)
 {
-    QuotaTracker::instance().resetSpaceAvailableToOrigin(originIdentifier);
+    QuotaTracker::instance().resetSpaceAvailableToOrigin(origin.get());
 }
 
-void WebDatabase::closeDatabaseImmediately(const WebString& originIdentifier, const WebString& databaseName)
+void WebDatabase::closeDatabaseImmediately(const WebSecurityOrigin& origin, const WebString& databaseName)
 {
-    DatabaseTracker::tracker().closeDatabasesImmediately(originIdentifier, databaseName);
+    DatabaseTracker::tracker().closeDatabasesImmediately(origin.get(), databaseName);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp b/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp
index a98bbca..5595abb 100644
--- a/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp
+++ b/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp
@@ -45,6 +45,11 @@
     RuntimeEnabledFeatures::setWebBluetoothEnabled(enable);
 }
 
+void WebRuntimeFeatures::enableWebUsb(bool enable)
+{
+    RuntimeEnabledFeatures::setWebUSBEnabled(enable);
+}
+
 void WebRuntimeFeatures::enableFeatureFromString(const std::string& name, bool enable)
 {
     RuntimeEnabledFeatures::setFeatureEnabledFromString(name, enable);
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/grammar_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/grammar_unittest.py
index afc67db1..f87d604 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/grammar_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/grammar_unittest.py
@@ -28,11 +28,38 @@
 
 import unittest
 
-from webkitpy.tool.grammar import join_with_separators
+from webkitpy.tool import grammar
 
 class GrammarTest(unittest.TestCase):
 
-    def test_join_with_separators(self):
-        self.assertEqual(join_with_separators(["one"]), "one")
-        self.assertEqual(join_with_separators(["one", "two"]), "one and two")
-        self.assertEqual(join_with_separators(["one", "two", "three"]), "one, two, and three")
+    def test_join_with_separators_zero(self):
+        self.assertEqual(
+            "",
+            grammar.join_with_separators([]))
+
+    def test_join_with_separators_one(self):
+        self.assertEqual(
+            "one",
+            grammar.join_with_separators(["one"]))
+
+    def test_join_with_separators_two(self):
+        self.assertEqual(
+            "one and two",
+            grammar.join_with_separators(["one", "two"]))
+
+    def test_join_with_separators_three(self):
+        self.assertEqual(
+            "one, two, and three",
+            grammar.join_with_separators(["one", "two", "three"]))
+
+    def test_pluralize_zero(self):
+        self.assertEqual("0 tests", grammar.pluralize("test", 0))
+
+    def test_pluralize_one(self):
+        self.assertEqual("1 test", grammar.pluralize("test", 1))
+
+    def test_pluralize_two(self):
+        self.assertEqual("2 tests", grammar.pluralize("test", 2))
+
+    def test_pluralize_two_ends_with_sh(self):
+        self.assertEqual("2 crashes", grammar.pluralize("crash", 2))
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index aa5117c..dba669c 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -175,6 +175,17 @@
   ]
 }
 
+# GYP version: WebKit/public/blink.gyp:mojo_bindings_blink_mojom
+mojom("mojo_bindings_blink") {
+  sources = [
+    "platform/modules/bluetooth/web_bluetooth.mojom",
+    "platform/modules/notifications/notification.mojom",
+  ]
+  for_blink = true
+  variant = "wtf"
+}
+
+# GYP version: WebKit/public/blink.gyp:mojo_bindings_mojom
 mojom("mojo_bindings") {
   sources = [
     "platform/modules/bluetooth/web_bluetooth.mojom",
diff --git a/third_party/WebKit/public/blink.gyp b/third_party/WebKit/public/blink.gyp
index db889278..8289fd8 100644
--- a/third_party/WebKit/public/blink.gyp
+++ b/third_party/WebKit/public/blink.gyp
@@ -31,6 +31,12 @@
     'includes': [
         '../Source/build/features.gypi',
     ],
+    'variables': {
+        'blink_mojo_sources': [
+            'platform/modules/bluetooth/web_bluetooth.mojom',
+            'platform/modules/notifications/notification.mojom',
+        ],
+    },
     'targets': [
         {
             # GN version: //third_party/WebKit/public:blink
@@ -82,24 +88,36 @@
             ],
         },
         {
+            # GN version: //third_party/WebKit/public:mojo_bindings_blink
+            'target_name': 'mojo_bindings_blink_mojom',
+            'type': 'none',
+            'variables': {
+                'mojom_files': ['<@(blink_mojo_sources)'],
+                'mojom_variant': 'wtf',
+                'for_blink': 'true',
+            },
+            'includes': [
+                '../../../mojo/mojom_bindings_generator_explicit.gypi',
+            ],
+        },
+        {
+            # GN version: //third_party/WebKit/public:mojo_bindings
             'target_name': 'mojo_bindings_mojom',
             'type': 'none',
             'variables': {
-              'mojom_files': [
-                'platform/modules/bluetooth/web_bluetooth.mojom',
-                'platform/modules/notifications/notification.mojom',
-              ],
+                'mojom_files': ['<@(blink_mojo_sources)'],
             },
             'includes': [
-              '../../../mojo/mojom_bindings_generator_explicit.gypi',
+                '../../../mojo/mojom_bindings_generator_explicit.gypi',
             ],
         },
         {
             'target_name': 'mojo_bindings',
             'type': 'static_library',
             'dependencies': [
-              'mojo_bindings_mojom',
-              '../../../mojo/mojo_public.gyp:mojo_cpp_bindings',
+                'mojo_bindings_blink_mojom',
+                'mojo_bindings_mojom',
+                '../../../mojo/mojo_public.gyp:mojo_cpp_bindings',
             ],
         },
     ],
diff --git a/third_party/WebKit/public/platform/Platform.h b/third_party/WebKit/public/platform/Platform.h
index 0ecf774..8f39386 100644
--- a/third_party/WebKit/public/platform/Platform.h
+++ b/third_party/WebKit/public/platform/Platform.h
@@ -206,11 +206,13 @@
     virtual long long databaseGetFileSize(const WebString& vfsFileName) { return 0; }
 
     // Returns the space available for the given origin
-    virtual long long databaseGetSpaceAvailableForOrigin(const WebString& originIdentifier) { return 0; }
+    virtual long long databaseGetSpaceAvailableForOrigin(const WebSecurityOrigin& origin) { return 0; }
 
     // Set the size of the given database file
     virtual bool databaseSetFileSize(const WebString& vfsFileName, long long size) { return false; }
 
+    // Return a filename-friendly identifier for an origin.
+    virtual WebString databaseCreateOriginIdentifier(const WebSecurityOrigin& origin) { return WebString(); }
 
     // DOM Storage --------------------------------------------------
 
@@ -223,6 +225,8 @@
     // Must return non-null.
     virtual WebFileSystem* fileSystem() { return nullptr; }
 
+    // Return a filename-friendly identifier for an origin.
+    virtual WebString fileSystemCreateOriginIdentifier(const WebSecurityOrigin& origin) { return WebString(); }
 
     // IDN conversion ------------------------------------------------------
 
@@ -451,15 +455,16 @@
 
     // GPU ----------------------------------------------------------------
     //
-    // May return null if GPU is not supported.
-    // Returns newly allocated and initialized offscreen WebGraphicsContext3D instance.
-    // Passing an existing context to shareContext will create the new context in the same share group as the passed context.
-    virtual WebGraphicsContext3D* createOffscreenGraphicsContext3D(const WebGraphicsContext3D::Attributes&, WebGraphicsContext3D* shareContext) { return nullptr; }
-    virtual WebGraphicsContext3D* createOffscreenGraphicsContext3D(const WebGraphicsContext3D::Attributes&, WebGraphicsContext3D* shareContext, WebGraphicsContext3D::WebGraphicsInfo* glInfo) { return nullptr; }
-    virtual WebGraphicsContext3D* createOffscreenGraphicsContext3D(const WebGraphicsContext3D::Attributes&) { return nullptr; }
+    // Returns a newly allocated and initialized offscreen context provider,
+    // backed by an independent context. Returns null if the context cannot be
+    // created or initialized.
+    // Passing an existing provider to shareContext will create the new context
+    // in the same share group as the one passed.
+    virtual WebGraphicsContext3DProvider* createOffscreenGraphicsContext3DProvider(const WebGraphicsContext3D::Attributes&, WebGraphicsContext3DProvider* shareContext, WebGraphicsContext3D::WebGraphicsInfo* glInfo) { return nullptr; }
 
-    // Returns a newly allocated and initialized offscreen context provider. The provider may return a null
-    // graphics context if GPU is not supported.
+    // Returns a newly allocated and initialized offscreen context provider,
+    // backed by the process-wide shared main thread context. Returns null if
+    // the context cannot be created or initialized.
     virtual WebGraphicsContext3DProvider* createSharedOffscreenGraphicsContext3DProvider() { return nullptr; }
 
     // Returns true if the platform is capable of producing an offscreen context suitable for accelerating 2d canvas.
diff --git a/third_party/WebKit/public/platform/WebDatabaseObserver.h b/third_party/WebKit/public/platform/WebDatabaseObserver.h
index 2451423..64f7acd 100644
--- a/third_party/WebKit/public/platform/WebDatabaseObserver.h
+++ b/third_party/WebKit/public/platform/WebDatabaseObserver.h
@@ -34,43 +34,44 @@
 namespace blink {
 
 class WebString;
+class WebSecurityOrigin;
 
 class WebDatabaseObserver {
 public:
     virtual void databaseOpened(
-        const WebString& databaseIdentifier,
+        const WebSecurityOrigin&,
         const WebString& databaseName,
         const WebString& databaseDisplayName,
         unsigned long estimatedSize) = 0;
     virtual void databaseModified(
-        const WebString& databaseIdentifier,
+        const WebSecurityOrigin&,
         const WebString& databaseName) = 0;
     virtual void databaseClosed(
-        const WebString& databaseIdentifier,
+        const WebSecurityOrigin&,
         const WebString& databaseName) = 0;
     virtual void reportOpenDatabaseResult(
-        const WebString& databaseIdentifier,
+        const WebSecurityOrigin&,
         const WebString& databaseName,
         int errorSite, int webSqlErrorCode, int sqliteErrorCode,
         double callTime) { }
     virtual void reportChangeVersionResult(
-        const WebString& databaseIdentifier,
+        const WebSecurityOrigin&,
         const WebString& databaseName,
         int errorSite, int webSqlErrorCode, int sqliteErrorCode) { }
     virtual void reportStartTransactionResult(
-        const WebString& databaseIdentifier,
+        const WebSecurityOrigin&,
         const WebString& databaseName,
         int errorSite, int webSqlErrorCode, int sqliteErrorCode) { }
     virtual void reportCommitTransactionResult(
-        const WebString& databaseIdentifier,
+        const WebSecurityOrigin&,
         const WebString& databaseName,
         int errorSite, int webSqlErrorCode, int sqliteErrorCode) { }
     virtual void reportExecuteStatementResult(
-        const WebString& databaseIdentifier,
+        const WebSecurityOrigin&,
         const WebString& databaseName,
         int errorSite, int webSqlErrorCode, int sqliteErrorCode) { }
     virtual void reportVacuumDatabaseResult(
-        const WebString& databaseIdentifier,
+        const WebSecurityOrigin&,
         const WebString& databaseName,
         int sqliteErrorCode) { }
 
diff --git a/third_party/WebKit/public/platform/WebGraphicsContext3D.h b/third_party/WebKit/public/platform/WebGraphicsContext3D.h
index 91cc4ef..2f59efb1 100644
--- a/third_party/WebKit/public/platform/WebGraphicsContext3D.h
+++ b/third_party/WebKit/public/platform/WebGraphicsContext3D.h
@@ -136,9 +136,6 @@
     // This destructor needs to be public so that using classes can destroy instances if initialization fails.
     virtual ~WebGraphicsContext3D() { }
 
-    // GL_CHROMIUM_request_extension
-    virtual WebString getRequestableExtensionsCHROMIUM() = 0;
-
     // The entry points below map directly to the OpenGL ES 2.0 API.
     // See: http://www.khronos.org/registry/gles/
     // and: http://www.khronos.org/opengles/sdk/docs/man/
@@ -147,87 +144,12 @@
     virtual WebString getProgramInfoLog(WebGLId program) = 0;
     virtual WebString getShaderInfoLog(WebGLId shader) = 0;
     virtual WebString getShaderSource(WebGLId shader) = 0;
-    virtual WebString getString(WGC3Denum name) = 0;
-
-    virtual void shaderSource(WebGLId shader, const WGC3Dchar* string) = 0;
-
-    virtual WebGLId createBuffer() = 0;
-    virtual WebGLId createFramebuffer() = 0;
-    virtual WebGLId createRenderbuffer() = 0;
-    virtual WebGLId createTexture() = 0;
-
-    virtual void deleteBuffer(WebGLId) = 0;
-    virtual void deleteFramebuffer(WebGLId) = 0;
-    virtual void deleteRenderbuffer(WebGLId) = 0;
-    virtual void deleteTexture(WebGLId) = 0;
 
     virtual void setContextLostCallback(WebGraphicsContextLostCallback* callback) { }
     virtual void setErrorMessageCallback(WebGraphicsErrorMessageCallback* callback) { }
 
     virtual WebString getTranslatedShaderSourceANGLE(WebGLId shader) = 0;
 
-    // GL_EXT_occlusion_query
-    virtual WebGLId createQueryEXT() { return 0; }
-    virtual void deleteQueryEXT(WebGLId query) { }
-
-    // GL_CHROMIUM_subscribe_uniform
-    virtual WebGLId createValuebufferCHROMIUM() { return 0; }
-    virtual void deleteValuebufferCHROMIUM(WebGLId) { }
-
-    // GL_EXT_debug_marker
-    virtual void pushGroupMarkerEXT(const WGC3Dchar* marker) { }
-
-    // GL_OES_vertex_array_object
-    virtual WebGLId createVertexArrayOES() { return 0; }
-    virtual void deleteVertexArrayOES(WebGLId array) { }
-
-    // OpenGL ES 3.0 functions not represented by pre-existing extensions
-    virtual void beginTransformFeedback(WGC3Denum primitiveMode) { }
-    virtual void bindBufferBase(WGC3Denum target, WGC3Duint index, WebGLId buffer) { }
-    virtual void bindBufferRange(WGC3Denum target, WGC3Duint index, WebGLId buffer, WGC3Dintptr offset, WGC3Dsizeiptr size) { }
-    virtual void bindSampler(WGC3Duint unit, WebGLId sampler) { }
-    virtual void bindTransformFeedback(WGC3Denum target, WebGLId transformfeedback) { }
-    virtual void clearBufferfi(WGC3Denum buffer, WGC3Dint drawbuffer, WGC3Dfloat depth, WGC3Dint stencil) { }
-    virtual void clearBufferfv(WGC3Denum buffer, WGC3Dint drawbuffer, const WGC3Dfloat *value) { }
-    virtual void clearBufferiv(WGC3Denum buffer, WGC3Dint drawbuffer, const WGC3Dint *value) { }
-    virtual void clearBufferuiv(WGC3Denum buffer, WGC3Dint drawbuffer, const WGC3Duint *value) { }
-    virtual void compressedTexImage3D(WGC3Denum target, WGC3Dint level, WGC3Denum internalformat, WGC3Dsizei width, WGC3Dsizei height, WGC3Dsizei depth, WGC3Dint border, WGC3Dsizei imageSize, const void *data) { }
-    virtual void compressedTexSubImage3D(WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, WGC3Dint yoffset, WGC3Dint zoffset, WGC3Dsizei width, WGC3Dsizei height, WGC3Dsizei depth, WGC3Denum format, WGC3Dsizei imageSize, const void *data) { }
-    virtual void copyBufferSubData(WGC3Denum readTarget, WGC3Denum writeTarget, WGC3Dintptr readOffset, WGC3Dintptr writeOffset, WGC3Dsizeiptr size) { }
-    virtual void copyTexSubImage3D(WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, WGC3Dint yoffset, WGC3Dint zoffset, WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height) { }
-    virtual WebGLId createSampler() { return 0; }
-    virtual WebGLId createTransformFeedback() { return 0; }
-    virtual void deleteSampler(WebGLId sampler) { }
-    virtual void deleteTransformFeedback(WebGLId transformfeedback) { }
-    virtual void endTransformFeedback(void) { }
-    virtual void getActiveUniformBlockName(WebGLId program, WGC3Duint uniformBlockIndex, WGC3Dsizei bufSize, WGC3Dsizei *length, WGC3Dchar *uniformBlockName) { }
-    virtual void getActiveUniformBlockiv(WebGLId program, WGC3Duint uniformBlockIndex, WGC3Denum pname, WGC3Dint *params) { }
-    virtual void getActiveUniformsiv(WebGLId program, WGC3Dsizei uniformCount, const WGC3Duint *uniformIndices, WGC3Denum pname, WGC3Dint *params) { }
-    virtual void getBufferParameteri64v(WGC3Denum target, WGC3Denum pname, WGC3Dint64 *value) { }
-    virtual WGC3Dint getFragDataLocation(WebGLId program, const WGC3Dchar *name) { return -1; }
-    virtual void getInternalformativ(WGC3Denum target, WGC3Denum internalformat, WGC3Denum pname, WGC3Dsizei bufSize, WGC3Dint *params) { }
-    virtual void getSamplerParameterfv(WebGLId sampler, WGC3Denum pname, WGC3Dfloat *params) { }
-    virtual void getSamplerParameteriv(WebGLId sampler, WGC3Denum pname, WGC3Dint *params) { }
-    virtual void getTransformFeedbackVarying(WebGLId program, WGC3Duint index, WGC3Dsizei bufSize, WGC3Dsizei *length, WGC3Dsizei *size, WGC3Denum *type, WGC3Dchar *name) { }
-    virtual WGC3Duint getUniformBlockIndex(WebGLId program, const WGC3Dchar *uniformBlockName) { return 0xFFFFFFFFu; /* GL_INVALID_INDEX */ }
-    virtual void getUniformIndices(WebGLId program, WGC3Dsizei uniformCount, const WGC3Dchar *const*uniformNames, WGC3Duint *uniformIndices) { }
-    virtual void getUniformuiv(WebGLId program, WGC3Dint location, WGC3Duint *params) { }
-    virtual void invalidateFramebuffer(WGC3Denum target, WGC3Dsizei numAttachments, const WGC3Denum *attachments) { }
-    virtual void invalidateSubFramebuffer(WGC3Denum target, WGC3Dsizei numAttachments, const WGC3Denum *attachments, WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height) { }
-    virtual WGC3Dboolean isSampler(WebGLId sampler) { return false; }
-    virtual WGC3Dboolean isTransformFeedback(WebGLId transformfeedback) { return false; }
-    virtual void* mapBufferRange(WGC3Denum target, WGC3Dintptr offset, WGC3Dsizeiptr length, WGC3Dbitfield access) { return 0; }
-    virtual void pauseTransformFeedback(void) { }
-    virtual void programParameteri(WebGLId program, WGC3Denum pname, WGC3Dint value) { }
-    virtual void readBuffer(WGC3Denum src) { }
-    virtual void resumeTransformFeedback(void) { }
-    virtual void samplerParameterf(WebGLId sampler, WGC3Denum pname, WGC3Dfloat param) { }
-    virtual void samplerParameterfv(WebGLId sampler, WGC3Denum pname, const WGC3Dfloat *param) { }
-    virtual void samplerParameteri(WebGLId sampler, WGC3Denum pname, WGC3Dint param) { }
-    virtual void samplerParameteriv(WebGLId sampler, WGC3Denum pname, const WGC3Dint *param) { }
-    virtual void transformFeedbackVaryings(WebGLId program, WGC3Dsizei count, const WGC3Dchar *const*varyings, WGC3Denum bufferMode) { }
-    virtual WGC3Dboolean unmapBuffer(WGC3Denum target) { return false; }
-
     // Prefer getting a GLES2Interface off WebGraphicsContext3DProvider if possible, and avoid using WebGraphicsContext3D at all.
     virtual gpu::gles2::GLES2Interface* getGLES2Interface() = 0;
 };
diff --git a/third_party/WebKit/public/platform/WebSecurityOrigin.h b/third_party/WebKit/public/platform/WebSecurityOrigin.h
index 7fa1f2b..528e473b 100644
--- a/third_party/WebKit/public/platform/WebSecurityOrigin.h
+++ b/third_party/WebKit/public/platform/WebSecurityOrigin.h
@@ -58,7 +58,6 @@
         return *this;
     }
 
-    BLINK_PLATFORM_EXPORT static WebSecurityOrigin createFromDatabaseIdentifier(const WebString& databaseIdentifier);
     BLINK_PLATFORM_EXPORT static WebSecurityOrigin createFromString(const WebString&);
     BLINK_PLATFORM_EXPORT static WebSecurityOrigin create(const WebURL&);
     BLINK_PLATFORM_EXPORT static WebSecurityOrigin createUnique();
@@ -102,10 +101,6 @@
     // non-empty WebSecurityOrigin resembles a standard URL.
     BLINK_PLATFORM_EXPORT WebString toString() const;
 
-    // Returns a string representation of this WebSecurityOrigin that can
-    // be used as a file.  Should be used in storage APIs only.
-    BLINK_PLATFORM_EXPORT WebString databaseIdentifier() const;
-
     // Returns true if this WebSecurityOrigin can access usernames and
     // passwords stored in password manager.
     BLINK_PLATFORM_EXPORT bool canAccessPasswordManager() const;
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h
index 37f94f0..21582b6 100644
--- a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h
+++ b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h
@@ -48,6 +48,7 @@
         ErrorTypeState,
         ErrorTypeTimeout,
         ErrorTypeUnknown,
+        ErrorTypeType,
         ErrorTypeLast = ErrorTypeUnknown
     };
 
diff --git a/third_party/WebKit/public/web/WebDatabase.h b/third_party/WebKit/public/web/WebDatabase.h
index deaf94b..7c6aacf 100644
--- a/third_party/WebKit/public/web/WebDatabase.h
+++ b/third_party/WebKit/public/web/WebDatabase.h
@@ -41,14 +41,14 @@
 class WebDatabase {
 public:
     BLINK_EXPORT static void updateDatabaseSize(
-        const WebString& originIdentifier, const WebString& name, long long size);
+        const WebSecurityOrigin&, const WebString& name, long long size);
     BLINK_EXPORT static void updateSpaceAvailable(
-        const WebString& originIdentifier, long long spaceAvailable);
+        const WebSecurityOrigin&, long long spaceAvailable);
     BLINK_EXPORT static void resetSpaceAvailable(
-        const WebString& originIdentifier);
+        const WebSecurityOrigin&);
 
     BLINK_EXPORT static void closeDatabaseImmediately(
-        const WebString& originIdentifier, const WebString& databaseName);
+        const WebSecurityOrigin&, const WebString& databaseName);
 
 private:
     WebDatabase() { }
diff --git a/third_party/WebKit/public/web/WebRuntimeFeatures.h b/third_party/WebKit/public/web/WebRuntimeFeatures.h
index 817d0a23..39009ab 100644
--- a/third_party/WebKit/public/web/WebRuntimeFeatures.h
+++ b/third_party/WebKit/public/web/WebRuntimeFeatures.h
@@ -46,6 +46,8 @@
 
     BLINK_EXPORT static void enableWebBluetooth(bool);
 
+    BLINK_EXPORT static void enableWebUsb(bool);
+
     BLINK_EXPORT static void enableTestOnlyFeatures(bool);
 
     // Enables a feature by its string identifier from
diff --git a/third_party/closure_compiler/externs/web_animations.js b/third_party/closure_compiler/externs/web_animations.js
index 9eaa712..e369b602b 100644
--- a/third_party/closure_compiler/externs/web_animations.js
+++ b/third_party/closure_compiler/externs/web_animations.js
@@ -34,6 +34,25 @@
 };
 
 /**
+ * @enum {number}
+ * @see https://w3c.github.io/web-animations/#enumdef-iterationcompositeoperation
+ */
+var IterationCompositeOperation = {
+  'replace': 0,
+  'accumulate': 1
+};
+
+/**
+ * @enum {number}
+ * @see https://w3c.github.io/web-animations/#enumdef-compositeoperation
+ */
+var CompositeOperation = {
+  'replace': 0,
+  'add': 1,
+  'accumulate': 2
+};
+
+/**
  * @constructor
  * @param {!Event} event
  */
@@ -85,6 +104,58 @@
 KeyframeEffectOptions.prototype.id;
 
 /**
+ * @constructor
+ * @param {?Animatable} target
+ * @param {?Object} frames
+ * @param {number|KeyframeEffectOptions=} opt_options
+ * @see https://w3c.github.io/web-animations/#keyframeeffectreadonly
+ */
+var KeyframeEffectReadOnly = function(target, frames, opt_options) {};
+
+/** @const {?Animatable} */
+KeyframeEffectReadOnly.prototype.target;
+
+/** @const {IterationCompositeOperation} */
+KeyframeEffectReadOnly.prototype.iterationComposite;
+
+/** @const {CompositeOperation} */
+KeyframeEffectReadOnly.prototype.composite;
+
+/** @const {string} */
+KeyframeEffectReadOnly.prototype.spacing;
+
+/** @return {KeyframeEffect} */
+KeyframeEffectReadOnly.prototype.clone;
+
+/** @return {Array<Object>} */
+KeyframeEffectReadOnly.prototype.getFrames;
+
+/**
+ * @constructor
+ * @extends KeyframeEffectReadOnly
+ * @param {?Animatable} target
+ * @param {?Object} frames
+ * @param {number|KeyframeEffectOptions=} opt_options
+ * @see https://w3c.github.io/web-animations/#keyframeeffect
+ */
+var KeyframeEffect = function(target, frames, opt_options) {};
+
+/** @override */
+KeyframeEffect.prototype.target;
+
+/** @override */
+KeyframeEffect.prototype.iterationComposite;
+
+/** @override */
+KeyframeEffect.prototype.composite;
+
+/** @override */
+KeyframeEffect.prototype.spacing;
+
+/** @param {?Object} frames */
+KeyframeEffect.prototype.setFrames;
+
+/**
  * @interface
  * @extends {EventTarget}
  * @see https://w3c.github.io/web-animations/#animation
diff --git a/third_party/polymer/v1_0/components-chromium/neon-animation/animations/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/neon-animation/animations/compiled_resources2.gyp
index a93ec4b..8595a951 100644
--- a/third_party/polymer/v1_0/components-chromium/neon-animation/animations/compiled_resources2.gyp
+++ b/third_party/polymer/v1_0/components-chromium/neon-animation/animations/compiled_resources2.gyp
@@ -9,6 +9,7 @@
       'target_name': 'cascaded-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -16,6 +17,7 @@
       'target_name': 'fade-in-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -23,6 +25,7 @@
       'target_name': 'fade-out-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -30,6 +33,7 @@
       'target_name': 'hero-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-shared-element-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -37,6 +41,7 @@
       'target_name': 'opaque-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -44,6 +49,7 @@
       'target_name': 'reverse-ripple-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-shared-element-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -51,6 +57,7 @@
       'target_name': 'ripple-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-shared-element-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -58,6 +65,7 @@
       'target_name': 'scale-down-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -65,6 +73,7 @@
       'target_name': 'scale-up-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -72,6 +81,7 @@
       'target_name': 'slide-down-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -79,6 +89,7 @@
       'target_name': 'slide-from-bottom-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -86,6 +97,7 @@
       'target_name': 'slide-from-left-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -93,6 +105,7 @@
       'target_name': 'slide-from-right-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -100,6 +113,7 @@
       'target_name': 'slide-from-top-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -107,6 +121,7 @@
       'target_name': 'slide-left-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -114,6 +129,7 @@
       'target_name': 'slide-right-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -121,6 +137,7 @@
       'target_name': 'slide-up-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
@@ -128,6 +145,7 @@
       'target_name': 'transform-animation-extracted',
       'dependencies': [
         '../compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
     },
diff --git a/third_party/polymer/v1_0/components-chromium/paper-menu-button/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-menu-button/compiled_resources2.gyp
index bd08ad2..b60ad12e 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-menu-button/compiled_resources2.gyp
+++ b/third_party/polymer/v1_0/components-chromium/paper-menu-button/compiled_resources2.gyp
@@ -9,6 +9,7 @@
       'target_name': 'paper-menu-button-animations-extracted',
       'dependencies': [
         '../neon-animation/compiled_resources2.gyp:neon-animation-behavior-extracted',
+        '<(EXTERNS_GYP):web_animations',
       ],
       'includes': ['../../../../closure_compiler/compile_js2.gypi'],
     },
diff --git a/tools/android/loading/chrome_cache.py b/tools/android/loading/chrome_cache.py
index 1df3010..9d486e9c 100644
--- a/tools/android/loading/chrome_cache.py
+++ b/tools/android/loading/chrome_cache.py
@@ -8,6 +8,7 @@
 from datetime import datetime
 import json
 import os
+import re
 import shutil
 import subprocess
 import sys
@@ -37,6 +38,13 @@
 # Default cachetool binary location.
 CACHETOOL_BIN_PATH = os.path.join(OUT_DIRECTORY, 'cachetool')
 
+# Default content_decoder_tool binary location.
+CONTENT_DECODER_TOOL_BIN_PATH = os.path.join(OUT_DIRECTORY,
+                                             'content_decoder_tool')
+
+# Regex used to parse HTTP headers line by line.
+HEADER_PARSING_REGEX = re.compile(r'^(?P<header>\S+):(?P<value>.*)$')
+
 
 def _EnsureCleanCacheDirectory(directory_dest_path):
   """Ensure that a cache directory is created and clean.
@@ -306,6 +314,42 @@
     assert process.returncode == 0
     return stdout_data
 
+  def GetDecodedContentForKey(self, key):
+    """Gets a key's decoded content.
+
+    HTTP cache is storing into key's index stream 1 the transport layer resource
+    binary. However, the resources might be encoded using a compression
+    algorithm specified in the Content-Encoding response header. This method
+    takes care of returning decoded binary content of the resource.
+
+    Args:
+      key: The key to access the decoded content.
+
+    Returns:
+      String holding binary content.
+    """
+    response_headers = self.GetStreamForKey(key, 0)
+    content_encoding = None
+    for response_header_line in response_headers.split('\n'):
+      match = HEADER_PARSING_REGEX.match(response_header_line)
+      if not match:
+        continue
+      if match.group('header').lower() == 'content-encoding':
+        content_encoding = match.group('value')
+        break
+    encoded_content = self.GetStreamForKey(key, 1)
+    if content_encoding == None:
+      return encoded_content
+
+    cmd = [CONTENT_DECODER_TOOL_BIN_PATH]
+    cmd.extend([s.strip() for s in content_encoding.split(',')])
+    process = subprocess.Popen(cmd,
+                               stdin=subprocess.PIPE,
+                               stdout=subprocess.PIPE)
+    decoded_content, _ = process.communicate(input=encoded_content)
+    assert process.returncode == 0
+    return decoded_content
+
 
 def ApplyUrlWhitelistToCacheArchive(cache_archive_path,
                                     whitelisted_urls,
@@ -333,18 +377,33 @@
     shutil.rmtree(cache_temp_directory)
 
 
-if __name__ == '__main__':
+def ManualTestMain():
   import argparse
   parser = argparse.ArgumentParser(description='Tests cache back-end.')
-  parser.add_argument('cache_path', type=str)
+  parser.add_argument('cache_archive_path', type=str)
   parser.add_argument('backend_type', type=str, choices=BACKEND_TYPES)
   command_line_args = parser.parse_args()
 
+  cache_path = tempfile.mkdtemp()
+  UnzipDirectoryContent(command_line_args.cache_archive_path, cache_path)
+
   cache_backend = CacheBackend(
-      cache_directory_path=command_line_args.cache_path,
+      cache_directory_path=cache_path,
       cache_backend_type=command_line_args.backend_type)
-  keys = cache_backend.ListKeys()
-  print '{}\'s HTTP response header:'.format(keys[0])
-  print cache_backend.GetStreamForKey(keys[0], 0)
+  keys = sorted(cache_backend.ListKeys())
+  selected_key = None
+  for key in keys:
+    if key.endswith('.js'):
+      selected_key = key
+      break
+  assert selected_key
+  print '{}\'s HTTP response header:'.format(selected_key)
+  print cache_backend.GetStreamForKey(selected_key, 0)
+  print cache_backend.GetDecodedContentForKey(selected_key)
   cache_backend.DeleteKey(keys[1])
   assert keys[1] not in cache_backend.ListKeys()
+  shutil.rmtree(cache_path)
+
+
+if __name__ == '__main__':
+  ManualTestMain()
diff --git a/tools/android/loading/controller.py b/tools/android/loading/controller.py
index 25fefaea..1a55085 100644
--- a/tools/android/loading/controller.py
+++ b/tools/android/loading/controller.py
@@ -14,6 +14,7 @@
 import logging
 import os
 import shutil
+import socket
 import subprocess
 import sys
 import tempfile
@@ -33,10 +34,6 @@
 
 OPTIONS = options.OPTIONS
 
-# An estimate of time to wait for the device to become idle after expensive
-# operations, such as opening the launcher activity.
-_TIME_TO_DEVICE_IDLE_SECONDS = 2
-
 
 class ChromeControllerBase(object):
   """Base class for all controllers.
@@ -193,8 +190,15 @@
 
 class RemoteChromeController(ChromeControllerBase):
   """A controller for an android device, aka remote chrome instance."""
-  # Seconds to sleep after starting chrome activity.
-  POST_ACTIVITY_SLEEP_SECONDS = 2
+  # Number of connection attempt to chrome's devtools.
+  DEVTOOLS_CONNECTION_ATTEMPTS = 10
+
+  # Time interval in seconds between chrome's devtools connection attempts.
+  DEVTOOLS_CONNECTION_ATTEMPT_INTERVAL_SECONDS = 1
+
+  # An estimate of time to wait for the device to become idle after expensive
+  # operations, such as opening the launcher activity.
+  TIME_TO_IDLE_SECONDS = 2
 
   def __init__(self, device):
     """Initialize the controller.
@@ -203,38 +207,50 @@
       device: an andriod device.
     """
     assert device is not None, 'Should you be using LocalController instead?'
-    self._device = device
     super(RemoteChromeController, self).__init__()
+    self._device = device
+    self._device.EnableRoot()
 
   @contextlib.contextmanager
   def Open(self):
     """Overridden connection creation."""
     package_info = OPTIONS.ChromePackage()
     command_line_path = '/data/local/chrome-command-line'
-
-    self._device.EnableRoot()
     self._device.KillAll(package_info.package, quiet=True)
-
+    chrome_args = self._GetChromeArguments()
+    logging.info('Launching %s with flags: %s' % (package_info.package,
+        subprocess.list2cmdline(chrome_args)))
     with device_setup.FlagReplacer(
         self._device, command_line_path, self._GetChromeArguments()):
       start_intent = intent.Intent(
           package=package_info.package, activity=package_info.activity,
           data='about:blank')
       self._device.StartActivity(start_intent, blocking=True)
-      time.sleep(self.POST_ACTIVITY_SLEEP_SECONDS)
-      with device_setup.ForwardPort(
-          self._device, 'tcp:%d' % OPTIONS.devtools_port,
-          'localabstract:chrome_devtools_remote'):
-        connection = devtools_monitor.DevToolsConnection(
-            OPTIONS.devtools_hostname, OPTIONS.devtools_port)
-        self._StartConnection(connection)
-        yield connection
-    if self._slow_death:
-      self._device.adb.Shell('am start com.google.android.launcher')
-      time.sleep(_TIME_TO_DEVICE_IDLE_SECONDS)
-      self._device.KillAll(OPTIONS.chrome_package_name, quiet=True)
-      time.sleep(_TIME_TO_DEVICE_IDLE_SECONDS)
-    self._device.KillAll(package_info.package, quiet=True)
+      try:
+        for attempt_id in xrange(self.DEVTOOLS_CONNECTION_ATTEMPTS + 1):
+          if attempt_id == self.DEVTOOLS_CONNECTION_ATTEMPTS:
+            raise RuntimeError('Failed to connect to chrome devtools after {} '
+                               'attempts.'.format(attempt_id))
+          logging.info('Devtools connection attempt %d' % attempt_id)
+          with device_setup.ForwardPort(
+              self._device, 'tcp:%d' % OPTIONS.devtools_port,
+              'localabstract:chrome_devtools_remote'):
+            try:
+              connection = devtools_monitor.DevToolsConnection(
+                  OPTIONS.devtools_hostname, OPTIONS.devtools_port)
+              self._StartConnection(connection)
+            except socket.error as e:
+              assert str(e).startswith('[Errno 104] Connection reset by peer')
+              time.sleep(self.DEVTOOLS_CONNECTION_ATTEMPT_INTERVAL_SECONDS)
+              continue
+            logging.info('Devtools connection success')
+            yield connection
+            if self._slow_death:
+              self._device.adb.Shell('am start com.google.android.launcher')
+              time.sleep(self.TIME_TO_IDLE_SECONDS)
+            break
+      finally:
+        self._device.KillAll(package_info.package, quiet=True)
 
   def PushBrowserCache(self, cache_path):
     """Override for chrome cache pushing."""
diff --git a/tools/chrome_proxy/OWNERS b/tools/chrome_proxy/OWNERS
index bd8dfc87..8dfefe6 100644
--- a/tools/chrome_proxy/OWNERS
+++ b/tools/chrome_proxy/OWNERS
@@ -5,3 +5,4 @@
 marq@chromium.org
 megjablon@chromium.org
 sclittle@chromium.org
+tbansal@chromium.org
diff --git a/tools/chrome_proxy/common/chrome_proxy_metrics.py b/tools/chrome_proxy/common/chrome_proxy_metrics.py
index 076e89bd..47a6d6b0 100644
--- a/tools/chrome_proxy/common/chrome_proxy_metrics.py
+++ b/tools/chrome_proxy/common/chrome_proxy_metrics.py
@@ -106,6 +106,9 @@
   def HasChromeProxyLoFiPreviewRequest(self):
     return self.HasRequestHeader('Chrome-Proxy', "q=preview")
 
+  def HasChromeProxyLoFiPreviewExpRequest(self):
+    return self.HasRequestHeader('Chrome-Proxy', "exp=ignore_preview_blacklist")
+
   def HasChromeProxyLoFiPreviewResponse(self):
     return self.HasResponseHeader('Chrome-Proxy', "q=preview")
 
diff --git a/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py b/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py
index 8a24d3b..4dd4846f 100644
--- a/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py
+++ b/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py
@@ -257,8 +257,8 @@
     super(ChromeProxyMetric, self).AddResults(tab, results)
 
   def AddResultsForLoFiPreview(self, tab, results):
-    lo_fi_request_count = 0
     lo_fi_preview_request_count = 0
+    lo_fi_preview_exp_request_count = 0
     lo_fi_preview_response_count = 0
 
     for resp in self.IterResponses(tab):
@@ -271,19 +271,26 @@
 
       if resp.HasChromeProxyLoFiPreviewRequest():
         lo_fi_preview_request_count += 1
-      elif resp.HasChromeProxyLoFiRequest():
-        lo_fi_request_count += 1
-      else:
-        raise ChromeProxyMetricException, (
-            '%s: LoFi not in request header.' % (resp.response.url))
+
+      if resp.HasChromeProxyLoFiPreviewExpRequest():
+        lo_fi_preview_exp_request_count += 1
 
       if resp.HasChromeProxyLoFiPreviewResponse():
         lo_fi_preview_response_count += 1
 
+      if resp.HasChromeProxyLoFiRequest():
+        raise ChromeProxyMetricException, (
+        '%s: Lo-Fi directive should not be in preview request header.' %
+        (resp.response.url))
+
     if lo_fi_preview_request_count == 0:
       raise ChromeProxyMetricException, (
           'Expected at least one LoFi preview request, but zero such requests '
           'were sent.')
+    if lo_fi_preview_exp_request_count == 0:
+      raise ChromeProxyMetricException, (
+          'Expected at least one LoFi preview exp=ignore_preview_blacklist '
+          'request, but zero such requests were sent.')
     if lo_fi_preview_response_count == 0:
       raise ChromeProxyMetricException, (
           'Expected at least one LoFi preview response, but zero such '
@@ -295,8 +302,8 @@
             'count', lo_fi_preview_request_count))
     results.AddValue(
         scalar.ScalarValue(
-            results.current_page, 'lo_fi_request',
-            'count', lo_fi_request_count))
+            results.current_page, 'lo_fi_preview_exp_request',
+            'count', lo_fi_preview_exp_request_count))
     results.AddValue(
         scalar.ScalarValue(
             results.current_page, 'lo_fi_preview_response',
diff --git a/tools/clang/plugins/FindBadConstructsConsumer.cpp b/tools/clang/plugins/FindBadConstructsConsumer.cpp
index d1fc29d..5385cc8 100644
--- a/tools/clang/plugins/FindBadConstructsConsumer.cpp
+++ b/tools/clang/plugins/FindBadConstructsConsumer.cpp
@@ -48,13 +48,6 @@
 const char kNoteProtectedNonVirtualDtor[] =
     "[chromium-style] Protected non-virtual destructor declared here";
 
-bool TypeHasNonTrivialDtor(const Type* type) {
-  if (const CXXRecordDecl* cxx_r = type->getAsCXXRecordDecl())
-    return !cxx_r->hasTrivialDestructor();
-
-  return false;
-}
-
 // Returns the underlying Type for |type| by expanding typedefs and removing
 // any namespace qualifiers. This is similar to desugaring, except that for
 // ElaboratedTypes, desugar will unwrap too much.
@@ -564,12 +557,17 @@
                                           int* templated_non_trivial_member) {
   switch (type->getTypeClass()) {
     case Type::Record: {
+      auto* record_decl = type->getAsCXXRecordDecl();
       // Simplifying; the whole class isn't trivial if the dtor is, but
       // we use this as a signal about complexity.
-      if (TypeHasNonTrivialDtor(type))
-        (*non_trivial_member)++;
-      else
+      // Note that if a record doesn't have a definition, it doesn't matter how
+      // it's counted, since the translation unit will fail to build. In that
+      // case, just count it as a trivial member to avoid emitting warnings that
+      // might be spurious.
+      if (!record_decl->hasDefinition() || record_decl->hasTrivialDestructor())
         (*trivial_member)++;
+      else
+        (*non_trivial_member)++;
       break;
     }
     case Type::TemplateSpecialization: {
diff --git a/content/gpu/content_gpu_message_generator.h b/tools/clang/plugins/tests/class_with_incomplete_type.cpp
similarity index 62%
rename from content/gpu/content_gpu_message_generator.h
rename to tools/clang/plugins/tests/class_with_incomplete_type.cpp
index 55af4ce..04c7e80 100644
--- a/content/gpu/content_gpu_message_generator.h
+++ b/tools/clang/plugins/tests/class_with_incomplete_type.cpp
@@ -2,6 +2,4 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Multiply-included file, hence no include guard.
-
-#include "content/gpu/gpu_host_messages.h"
+#include "class_with_incomplete_type.h"
diff --git a/tools/clang/plugins/tests/class_with_incomplete_type.h b/tools/clang/plugins/tests/class_with_incomplete_type.h
new file mode 100644
index 0000000..777cf24
--- /dev/null
+++ b/tools/clang/plugins/tests/class_with_incomplete_type.h
@@ -0,0 +1,18 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Make sure that the plugin doesn't crash when trying to calculate the weight
+// of a class that has fields of incomplete type.
+
+#ifndef CLASS_WITH_INCOMPLETE_TYPE_H_
+#define CLASS_WITH_INCOMPLETE_TYPE_H_
+
+struct B;
+
+struct A {
+  ~A();
+  B incomplete;
+};
+
+#endif  // CLASS_WITH_INCOMPLETE_TYPE_H_
diff --git a/tools/clang/plugins/tests/class_with_incomplete_type.txt b/tools/clang/plugins/tests/class_with_incomplete_type.txt
new file mode 100644
index 0000000..553c5051
--- /dev/null
+++ b/tools/clang/plugins/tests/class_with_incomplete_type.txt
@@ -0,0 +1,8 @@
+In file included from class_with_incomplete_type.cpp:5:
+./class_with_incomplete_type.h:12:5: error: field has incomplete type 'B'
+  B incomplete;
+    ^
+./class_with_incomplete_type.h:8:8: note: forward declaration of 'B'
+struct B;
+       ^
+1 error generated.
diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py
index ac1679b..499671f 100644
--- a/tools/json_schema_compiler/cc_generator.py
+++ b/tools/json_schema_compiler/cc_generator.py
@@ -126,8 +126,17 @@
       (c.Append('%s::%s()' % (classname_in_namespace, classname))
         .Cblock(self._GenerateInitializersAndBody(type_))
         .Append('%s::~%s() {}' % (classname_in_namespace, classname))
-        .Append()
       )
+      if 'use_movable_types' in type_.namespace.compiler_options:
+        # Note: we use 'rhs' because some API objects have a member 'other'.
+        (c.Append('%s::%s(%s&& rhs)' %
+                      (classname_in_namespace, classname, classname))
+          .Cblock(self._GenerateMoveCtor(type_))
+          .Append('%s& %s::operator=(%s&& rhs)' %
+                      (classname_in_namespace, classname_in_namespace,
+                       classname))
+          .Cblock(self._GenerateMoveAssignOperator(type_))
+        )
       if type_.origin.from_json:
         c.Cblock(self._GenerateTypePopulate(classname_in_namespace, type_))
         if cpp_namespace is None:  # only generate for top-level types
@@ -178,12 +187,78 @@
         raise TypeError(t)
 
     if items:
-      s = ': %s' % (', '.join(items))
+      s = ': %s' % (',\n'.join(items))
     else:
       s = ''
     s = s + ' {}'
     return Code().Append(s)
 
+  def _GetMoveProps(self, type_, copy_str, move_str):
+    """Returns a tuple of (props, dicts) for the type.
+
+    |props| is a list of all the copyable or movable properties generated using
+    the copy_str and move_str, and |dicts| is a list of all the dictionary
+    properties by name.
+
+    Properties:
+    - |type_| the Type to get the properties from
+    - |copy_str| the string to use when copying a value; should have two
+                 placeholders to take the property name.
+    - |move_str| the string to use when moving a value; should have two
+                 placeholders to take the property name.
+    """
+    props = []
+    dicts = []
+    for prop in type_.properties.values():
+      t = prop.type_
+
+      real_t = self._type_helper.FollowRef(t)
+      if (prop.optional or
+          t.property_type == PropertyType.ANY or
+          t.property_type == PropertyType.ARRAY or
+          t.property_type == PropertyType.BINARY or
+          t.property_type == PropertyType.CHOICES or
+          t.property_type == PropertyType.OBJECT or
+          t.property_type == PropertyType.REF or
+          t.property_type == PropertyType.STRING):
+        props.append(move_str % (prop.unix_name, prop.unix_name))
+      elif t.property_type == PropertyType.FUNCTION:
+        dicts.append(prop.unix_name)
+      elif (real_t.property_type == PropertyType.ENUM or
+            t.property_type == PropertyType.INTEGER or
+            t.property_type == PropertyType.DOUBLE or
+            t.property_type == PropertyType.BOOLEAN):
+        props.append(copy_str % (prop.unix_name, prop.unix_name))
+      else:
+        raise TypeError(t)
+
+    return (props, dicts)
+
+  def _GenerateMoveCtor(self, type_):
+    props, dicts = self._GetMoveProps(type_, '%s(rhs.%s)',
+                                      '%s(std::move(rhs.%s))')
+    s = ''
+    if props:
+      s = s + ': %s' % (',\n'.join(props))
+    s = s + '{'
+    for item in dicts:
+      s = s + ('\n%s.Swap(&rhs.%s);' % (item, item))
+    s = s + '\n}'
+
+    return Code().Append(s)
+
+  def _GenerateMoveAssignOperator(self, type_):
+    props, dicts = self._GetMoveProps(type_, '%s = rhs.%s;',
+                                      '%s = std::move(rhs.%s);')
+    s = '{\n'
+    if props:
+      s = s + '\n'.join(props)
+    for item in dicts:
+      s = s + ('\n%s.Swap(&rhs.%s);' % (item, item))
+    s = s + '\nreturn *this;\n}'
+
+    return Code().Append(s)
+
   def _GenerateTypePopulate(self, cpp_namespace, type_):
     """Generates the function for populating a type given a pointer to it.
 
diff --git a/tools/json_schema_compiler/cpp_type_generator.py b/tools/json_schema_compiler/cpp_type_generator.py
index 3d307a9..24cbf61 100644
--- a/tools/json_schema_compiler/cpp_type_generator.py
+++ b/tools/json_schema_compiler/cpp_type_generator.py
@@ -121,7 +121,12 @@
     # TODO(kalman): change this - but it's an exceedingly far-reaching change.
     if not self.FollowRef(type_).property_type == PropertyType.ENUM:
       if is_in_container and (is_ptr or not self.IsCopyable(type_)):
-        cpp_type = 'linked_ptr<%s>' % cpp_util.PadForGenerics(cpp_type)
+        # Only wrap the object in a linked_ptr if this API isn't using movable
+        # types. Since base::Values aren't yet movable, wrap them too.
+        # TODO(devlin): Eventually, movable types should be the default.
+        if (not 'use_movable_types' in type_.namespace.compiler_options or
+            cpp_type == 'base::Value' or cpp_type == 'base::DictionaryValue'):
+          cpp_type = 'linked_ptr<%s>' % cpp_util.PadForGenerics(cpp_type)
       elif is_ptr:
         cpp_type = 'scoped_ptr<%s>' % cpp_util.PadForGenerics(cpp_type)
 
diff --git a/tools/json_schema_compiler/cpp_type_generator_test.py b/tools/json_schema_compiler/cpp_type_generator_test.py
index 51fcfe9..69d80dc 100755
--- a/tools/json_schema_compiler/cpp_type_generator_test.py
+++ b/tools/json_schema_compiler/cpp_type_generator_test.py
@@ -6,6 +6,7 @@
 from cpp_namespace_environment import CppNamespaceEnvironment
 from cpp_type_generator import CppTypeGenerator
 from json_schema import CachedLoad
+import idl_schema
 import model
 import unittest
 
@@ -49,6 +50,10 @@
     self.content_settings_json = CachedLoad('test/content_settings.json')
     self.content_settings = self.models['content_settings'].AddNamespace(
         self.content_settings_json[0], 'path/to/content_settings.json')
+    self.objects_movable_idl = idl_schema.Load('test/objects_movable.idl')
+    self.objects_movable = self.models['objects_movable'].AddNamespace(
+        self.objects_movable_idl[0], 'path/to/objects_movable.idl',
+        include_compiler_options=True)
 
   def testGenerateIncludesAndForwardDeclarations(self):
     m = model.Model()
@@ -153,6 +158,14 @@
         manager.GetCppType(
             self.permissions.types['Permissions'].properties['origins'].type_))
 
+    manager = CppTypeGenerator(self.models.get('objects_movable'),
+                               _FakeSchemaLoader(None))
+    self.assertEquals(
+        'std::vector<MovablePod>',
+        manager.GetCppType(
+            self.objects_movable.types['MovableParent'].
+                properties['pods'].type_))
+
   def testGetCppTypeLocalRef(self):
     manager = CppTypeGenerator(self.models.get('tabs'), _FakeSchemaLoader(None))
     self.assertEquals(
diff --git a/tools/json_schema_compiler/h_generator.py b/tools/json_schema_compiler/h_generator.py
index 173e549..5452885 100644
--- a/tools/json_schema_compiler/h_generator.py
+++ b/tools/json_schema_compiler/h_generator.py
@@ -228,6 +228,10 @@
           .Append('%(classname)s();')
           .Append('~%(classname)s();')
       )
+      if 'use_movable_types' in type_.namespace.compiler_options:
+        (c.Append('%(classname)s(%(classname)s&& rhs);')
+          .Append('%(classname)s& operator=(%(classname)s&& rhs);')
+        )
       if type_.origin.from_json:
         (c.Append()
           .Comment('Populates a %s object from a base::Value. Returns'
diff --git a/tools/json_schema_compiler/idl_schema.py b/tools/json_schema_compiler/idl_schema.py
index 58efe28..5fda70ea 100755
--- a/tools/json_schema_compiler/idl_schema.py
+++ b/tools/json_schema_compiler/idl_schema.py
@@ -500,6 +500,8 @@
           compiler_options['implemented_in'] = node.value
         elif node.name == 'camel_case_enum_to_string':
           compiler_options['camel_case_enum_to_string'] = node.value
+        elif node.name == 'use_movable_types':
+          compiler_options['use_movable_types'] = node.value
         elif node.name == 'deprecated':
           deprecated = str(node.value)
         elif node.name == 'documentation_title':
diff --git a/tools/json_schema_compiler/test/BUILD.gn b/tools/json_schema_compiler/test/BUILD.gn
index 33e6219..e12493f 100644
--- a/tools/json_schema_compiler/test/BUILD.gn
+++ b/tools/json_schema_compiler/test/BUILD.gn
@@ -23,6 +23,7 @@
     "idl_other_namespace.idl",
     "idl_other_namespace_sub_namespace.idl",
     "objects.json",
+    "objects_movable.idl",
     "simple_api.json",
   ]
 
diff --git a/tools/json_schema_compiler/test/json_schema_compiler_tests.gyp b/tools/json_schema_compiler/test/json_schema_compiler_tests.gyp
index 404e9b0..a0203dc 100644
--- a/tools/json_schema_compiler/test/json_schema_compiler_tests.gyp
+++ b/tools/json_schema_compiler/test/json_schema_compiler_tests.gyp
@@ -25,6 +25,7 @@
           'idl_other_namespace_sub_namespace.idl',
           'idl_object_types.idl',
           'objects.json',
+          'objects_movable.idl',
           'simple_api.json',
           'error_generation.json'
         ],
diff --git a/tools/json_schema_compiler/test/objects_movable.idl b/tools/json_schema_compiler/test/objects_movable.idl
new file mode 100644
index 0000000..b09f1a8
--- /dev/null
+++ b/tools/json_schema_compiler/test/objects_movable.idl
@@ -0,0 +1,23 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Movable Objects.
+[use_movable_types=true] namespace objectsMovable {
+  enum Foo {
+    BAR,
+    BAZ
+  };
+
+  dictionary MovablePod {
+    Foo foo;
+    DOMString str;
+    long num;
+    boolean b;
+  };
+
+  dictionary MovableParent {
+    MovablePod[] pods;
+    DOMString[] strs;
+  };
+};
diff --git a/tools/json_schema_compiler/test/objects_unittest.cc b/tools/json_schema_compiler/test/objects_unittest.cc
index 5e28386..2cb6fc6 100644
--- a/tools/json_schema_compiler/test/objects_unittest.cc
+++ b/tools/json_schema_compiler/test/objects_unittest.cc
@@ -2,14 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "tools/json_schema_compiler/test/objects.h"
-
 #include <stddef.h>
 
 #include "base/json/json_writer.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "tools/json_schema_compiler/test/objects.h"
+#include "tools/json_schema_compiler/test/objects_movable.h"
 
 using namespace test::api::objects;
+using namespace test::api::objects_movable;
 
 TEST(JsonSchemaCompilerObjectsTest, ObjectParamParamsCreate) {
   {
@@ -71,3 +72,38 @@
   ASSERT_TRUE(results->GetDictionary(0, &result));
   ASSERT_TRUE(result->Equals(&expected));
 }
+TEST(JsonSchemaCompilerMovableObjectsTest, MovableObjectsTest) {
+  std::vector<MovablePod> pods;
+  {
+    MovablePod pod;
+    pod.foo = FOO_BAR;
+    pod.str = "str1";
+    pod.num = 42;
+    pod.b = true;
+    pods.push_back(std::move(pod));
+  }
+  {
+    MovablePod pod;
+    pod.foo = FOO_BAZ;
+    pod.str = "str2";
+    pod.num = 45;
+    pod.b = false;
+    pods.push_back(std::move(pod));
+  }
+  MovableParent parent;
+  parent.pods = std::move(pods);
+  parent.strs.push_back("pstr");
+
+  MovableParent parent2(std::move(parent));
+  ASSERT_EQ(2u, parent2.pods.size());
+  EXPECT_EQ(FOO_BAR, parent2.pods[0].foo);
+  EXPECT_EQ("str1", parent2.pods[0].str);
+  EXPECT_EQ(42, parent2.pods[0].num);
+  EXPECT_TRUE(parent2.pods[0].b);
+  EXPECT_EQ(FOO_BAZ, parent2.pods[1].foo);
+  EXPECT_EQ("str2", parent2.pods[1].str);
+  EXPECT_EQ(45, parent2.pods[1].num);
+  EXPECT_FALSE(parent2.pods[1].b);
+  ASSERT_EQ(1u, parent2.strs.size());
+  EXPECT_EQ("pstr", parent2.strs[0]);
+}
diff --git a/tools/json_schema_compiler/util.h b/tools/json_schema_compiler/util.h
index 59d65d010..945f061 100644
--- a/tools/json_schema_compiler/util.h
+++ b/tools/json_schema_compiler/util.h
@@ -57,6 +57,19 @@
   return true;
 }
 
+// This template is used for types generated by tools/json_schema_compiler.
+template <class T>
+bool PopulateItem(const base::Value& from, T* out) {
+  const base::DictionaryValue* dict = nullptr;
+  if (!from.GetAsDictionary(&dict))
+    return false;
+  T obj;
+  if (!T::Populate(*dict, &obj))
+    return false;
+  *out = std::move(obj);
+  return true;
+}
+
 // This template is used for types generated by tools/json_schema_compiler with
 // error generation enabled.
 template <class T>
@@ -82,7 +95,9 @@
   for (const base::Value* value : list) {
     if (!PopulateItem(*value, &item))
       return false;
-    out->push_back(item);
+    // T might not be movable, but in that case it should be copyable, and this
+    // will still work.
+    out->push_back(std::move(item));
   }
 
   return true;
@@ -148,12 +163,18 @@
   out->Append(from->ToValue().release());
 }
 
+// This template is used for types generated by tools/json_schema_compiler.
+template <class T>
+void AddItemToList(const T& from, base::ListValue* out) {
+  out->Append(from.ToValue());
+}
+
 // Set |out| to the the contents of |from|. Requires PopulateItem to be
 // implemented for |T|.
 template <class T>
 void PopulateListFromArray(const std::vector<T>& from, base::ListValue* out) {
   out->Clear();
-  for (const auto& item : from)
+  for (const T& item : from)
     AddItemToList(item, out);
 }
 
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 3e26152e..2148ffc7 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -20,15 +20,23 @@
     },
 
     'chromium.android': {
-      'Android Cronet ARM64 Builder': 'tbd',
-      'Android Cronet ARM64 Builder (dbg)': 'tbd',
-      'Android Cronet ARMv6 Builder': 'tbd',
-      'Android Cronet Builder': 'tbd',
-      'Android Cronet Builder (dbg)': 'tbd',
-      'Android Cronet Data Reduction Proxy Builder': 'tbd',
-      'Android Cronet MIPS Builder': 'tbd',
-      'Android Cronet x86 Builder': 'tbd',
-      'Android Cronet x86 Builder (dbg)': 'tbd',
+      'Android Cronet ARM64 Builder':
+          'android_cronet_gyp_release_bot_minimal_symbols_arm64',
+      'Android Cronet ARM64 Builder (dbg)':
+          'android_cronet_gyp_debug_static_bot_arm64',
+      'Android Cronet ARMv6 Builder':
+          'android_cronet_gyp_release_bot_minimal_symbols_armv6',
+      'Android Cronet Builder':
+          'android_cronet_gyp_release_bot_minimal_symbols',
+      'Android Cronet Builder (dbg)': 'android_cronet_gyp_debug_static_bot',
+      'Android Cronet Data Reduction Proxy Builder':
+          'android_cronet_data_reduction_proxy_gyp_release_bot_minimal_symbols',
+      'Android Cronet MIPS Builder':
+          'android_cronet_gyp_release_bot_minimal_symbols_mipsel',
+      'Android Cronet x86 Builder':
+          'android_cronet_gyp_release_bot_minimal_symbols_x86',
+      'Android Cronet x86 Builder (dbg)':
+          'android_cronet_gyp_debug_static_bot_x86',
       'Android WebView CTS L-MR1 (dbg)': 'tbd',
       'Android Webview L (dbg)': 'tbd',
       'Android Webview M (dbg)': 'tbd',
@@ -840,6 +848,43 @@
       'android', 'clang', 'asan', 'findbugs', 'gyp', 'debug_trybot',
     ],
 
+    'android_cronet_data_reduction_proxy_gyp_release_bot_minimal_symbols': [
+      'android', 'cronet', 'data_reduction_proxy', 'gyp',
+      'release_bot_minimal_symbols', 'arm'
+    ],
+
+    'android_cronet_gyp_debug_static_bot': [
+      'android', 'cronet', 'gyp', 'debug_static_bot', 'arm'
+    ],
+
+    'android_cronet_gyp_debug_static_bot_arm64': [
+      'android', 'cronet', 'gyp', 'debug_static_bot', 'arm64'
+    ],
+
+    'android_cronet_gyp_debug_static_bot_x86': [
+      'android', 'cronet', 'gyp', 'debug_static_bot', 'x86'
+    ],
+
+    'android_cronet_gyp_release_bot_minimal_symbols': [
+      'android', 'cronet', 'gyp', 'release_bot_minimal_symbols', 'arm'
+    ],
+
+    'android_cronet_gyp_release_bot_minimal_symbols_arm64': [
+      'android', 'cronet', 'gyp', 'release_bot_minimal_symbols', 'arm64'
+    ],
+
+    'android_cronet_gyp_release_bot_minimal_symbols_armv6': [
+      'android', 'cronet', 'gyp', 'release_bot_minimal_symbols', 'armv6'
+    ],
+
+    'android_cronet_gyp_release_bot_minimal_symbols_mipsel': [
+      'android', 'cronet', 'gyp', 'release_bot_minimal_symbols', 'mipsel'
+    ],
+
+    'android_cronet_gyp_release_bot_minimal_symbols_x86': [
+      'android', 'cronet', 'gyp', 'release_bot_minimal_symbols', 'x86'
+    ],
+
     'android_gn_debug_bot': [
       'android', 'gn', 'debug_bot',
     ],
@@ -1151,8 +1196,8 @@
     ],
 
     'swarming_gpu_fyi_tests_gn_release_trybot': [
-      'swarming', 'gpu_tests', 'gn', 'release_trybot',
-      'angle_deqp_tests',
+      'swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gn',
+      'release_bot', 'angle_deqp_tests',
     ],
 
     'swarming_gpu_tests_gn_debug_bot': [
@@ -1376,9 +1421,9 @@
       'gyp_defines': 'target_arch=arm64',
     },
 
-    'arm64': {
-      'gn_args': 'target_cpu="arm64"',
-      'gyp_defines': 'target_arch=arm64',
+    'armv6': {
+      'gn_args': 'arm_version=6',
+      'gyp_defines': 'arm_version=6',
     },
 
     'asan': {
@@ -1425,6 +1470,13 @@
       'gyp_defines': 'clang=1',
     },
 
+    'cronet': {
+      'gn_args': ('disable_file_support=true disable_ftp_support=true '
+                  'enable_websockets=false'),
+      'gyp_defines': ('disable_file_support=1 disable_ftp_support=1 '
+                      'enable_websockets=0'),
+    },
+
     'crosscompile': {
       # This mixin is only needed on GYP bots that are doing cross-compiles
       # but are *not* targetting Android or iOS (where build/gyp_chromium
@@ -1433,6 +1485,11 @@
       'gyp_crosscompile': True,
     },
 
+    'data_reduction_proxy': {
+      'gn_args': 'enable_data_reduction_proxy_support=true',
+      'gyp_defines': 'enable_data_reduction_proxy_support=1',
+    },
+
     'dcheck_always_on': {
       'gn_args': 'dcheck_always_on=true',
       'gyp_defines': 'dcheck_always_on=1',
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index b42f34c..d903227 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -7459,6 +7459,16 @@
 
 <histogram name="DefaultBrowser.SetDefaultResult"
     enum="SetDefaultAttemptResult">
+  <obsolete>
+    Deprecated 2016/03.
+  </obsolete>
+  <owner>pmonette@chromium.org</owner>
+  <summary>
+    The outcome of an attempt to set Chrome as the user's default browser.
+  </summary>
+</histogram>
+
+<histogram name="DefaultBrowser.SetDefaultResult2" enum="DefaultWebClientState">
   <owner>pmonette@chromium.org</owner>
   <summary>
     The outcome of an attempt to set Chrome as the user's default browser.
@@ -7535,6 +7545,18 @@
 
 <histogram name="DefaultProtocolClient.SetDefaultResult"
     enum="SetDefaultAttemptResult">
+  <obsolete>
+    Deprecated 2016/03.
+  </obsolete>
+  <owner>pmonette@chromium.org</owner>
+  <summary>
+    The outcome of an attempt to set Chrome as the user's default client for a
+    protocol.
+  </summary>
+</histogram>
+
+<histogram name="DefaultProtocolClient.SetDefaultResult2"
+    enum="DefaultWebClientState">
   <owner>pmonette@chromium.org</owner>
   <summary>
     The outcome of an attempt to set Chrome as the user's default client for a
@@ -21076,6 +21098,14 @@
   <summary>Location the user clicked to open the Media Router dialog.</summary>
 </histogram>
 
+<histogram name="MediaRouter.Provider.Version" enum="MediaRouteProviderVersion">
+  <owner>mfoltz@chromium.org</owner>
+  <summary>
+    Records how the major version of the Media Router component extension
+    compares to the major version of the browser.
+  </summary>
+</histogram>
+
 <histogram name="MediaRouter.Provider.WakeReason"
     enum="MediaRouteProviderWakeReason">
   <owner>mfoltz@chromium.org</owner>
@@ -21084,6 +21114,13 @@
   </summary>
 </histogram>
 
+<histogram name="MediaRouter.Provider.Wakeup" enum="MediaRouteProviderWakeup">
+  <owner>mfoltz@chromium.org</owner>
+  <summary>
+    Records the outcome of waking the Media Router component's event page.
+  </summary>
+</histogram>
+
 <histogram name="MediaRouter.Route.CreationOutcome"
     units="MediaRouterCreateRouteOutcome">
   <owner>apacible@chromium.org</owner>
@@ -26273,6 +26310,28 @@
   </summary>
 </histogram>
 
+<histogram name="Net.PacResultForStrippedUrl" enum="PacResultForStrippedUrl">
+  <owner>eroman@chromium.org</owner>
+  <summary>
+    Proxy Auto Config (PAC) allows specifying an arbitrary javascript program to
+    pick network proxies on a per-request basis (based on the URL). This works
+    by calling the script's FindProxyForURL() function with the target URL as
+    its first argument.
+
+    Traditionally, the URL parameter passed into the script contains the exact
+    URL being loaded, except maybe for having stripped the fragment and embedded
+    identity portions of the URL.
+
+    This histogram records what happens when the URL passed into
+    FindProxyForURL() additionally has had its path component stripped. Does it
+    return the same proxy list as when calling FindProxyForURL() with the
+    original (unmodified) URL?
+
+    This comparison is done only when the URL scheme implies a secure channel
+    (i.e. https:// and wss://), in order to gather data for crbug.com/593759.
+  </summary>
+</histogram>
+
 <histogram name="Net.Ping_ResponseStartedTime" units="ms">
   <obsolete>
     Deprecated 4/16/2014. No longer tracked.
@@ -29029,9 +29088,9 @@
     enum="TokenBinding.StoreEphemerality">
   <owner>nharper@chromium.org</owner>
   <summary>
-    For each request on a connection where Channel ID was sent, this logs
-    whether the Cookie store and the Channel ID store were ephemeral or
-    persistent.
+    For each request to accounts.google.com on a connection where Channel ID was
+    sent, this logs whether the Cookie store and the Channel ID store were
+    ephemeral or persistent.
   </summary>
 </histogram>
 
@@ -63118,6 +63177,14 @@
   <int value="8" label="DSP set to new engine with no previous value in prefs"/>
 </enum>
 
+<enum name="DefaultWebClientState" type="int">
+  <int value="0" label="Not default">Chrome is not the default web client.</int>
+  <int value="1" label="Is default">Chrome is the default web client.</int>
+  <int value="2" label="Unknown default">
+    Chrome is in a unknown default state.
+  </int>
+</enum>
+
 <enum name="DelayBasedEchoQuality" type="int">
   <int value="0" label="Good delays">
     Echo Cancellation quality most likely good.
@@ -74522,6 +74589,13 @@
   <int value="1" label="Has errors"/>
 </enum>
 
+<enum name="MediaRouteProviderVersion" type="int">
+  <int value="0" label="Unknown"/>
+  <int value="1" label="SameVersionAsChrome"/>
+  <int value="2" label="OneVersionBehindChrome"/>
+  <int value="3" label="MultipleVersionsBehindChrome"/>
+</enum>
+
 <enum name="MediaRouteProviderWakeReason" type="int">
   <int value="0" label="CreateRoute"/>
   <int value="1" label="JoinRoute"/>
@@ -74540,6 +74614,12 @@
   <int value="14" label="ConnectRouteByRouteId"/>
 </enum>
 
+<enum name="MediaRouteProviderWakeup" type="int">
+  <int value="0" label="Success"/>
+  <int value="1" label="ErrorUnknown"/>
+  <int value="2" label="ErrorTooManyRetries"/>
+</enum>
+
 <enum name="MediaRouterCreateRouteOutcome" type="int">
   <int value="0" label="Success"/>
   <int value="1" label="Failure No Route"/>
@@ -76492,6 +76572,21 @@
   <int value="4" label="Index"/>
 </enum>
 
+<enum name="PacResultForStrippedUrl" type="int">
+  <summary>
+    Result for PAC script experiment as defined in
+    net/proxy/proxy_resolver_v8_tracing.h
+  </summary>
+  <int value="0" label="SKIPPED_FALLBACK_BLOCKING_DNS"/>
+  <int value="1" label="SUCCESS"/>
+  <int value="2" label="SUCCESS_DIFFERENT_ALERTS"/>
+  <int value="3" label="SUCCESS_DIFFERENT_NUM_DNS"/>
+  <int value="4" label="FAIL_ABANDONED"/>
+  <int value="5" label="FAIL_FALLBACK_BLOCKING_DNS"/>
+  <int value="6" label="FAIL_ERROR"/>
+  <int value="7" label="FAIL_DIFFERENT_PROXY_LIST"/>
+</enum>
+
 <enum name="PageLoadEvent" type="int">
   <obsolete>
     Deprecated in favor of {Committed|Provisional|InternalError}LoadEvent
@@ -80725,6 +80820,9 @@
 </enum>
 
 <enum name="SetDefaultAttemptResult" type="int">
+  <obsolete>
+    Deprecated 2016/03. Replaced by DefaultWebClientState.
+  </obsolete>
   <int value="0" label="Success">Chrome was set as the default web client.</int>
   <int value="1" label="Already default">
     Chrome was already the default web client. This counts as a successful
diff --git a/tools/polymer/generate_compiled_resources_gyp.py b/tools/polymer/generate_compiled_resources_gyp.py
index 391974efc..38f8157 100755
--- a/tools/polymer/generate_compiled_resources_gyp.py
+++ b/tools/polymer/generate_compiled_resources_gyp.py
@@ -13,6 +13,8 @@
 _COMPILE_JS = path.join(
     _SRC, "third_party", "closure_compiler", "compile_js2.gypi")
 _POLYMERS = ["polymer%s.html" % p for p in "", "-mini", "-micro"]
+_WEB_ANIMATIONS_BASE = "web-animations.html"
+_WEB_ANIMATIONS_TARGET = "<(EXTERNS_GYP):web_animations"
 _COMPILED_RESOURCES_TEMPLATE = """
 # Copyright %d The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
@@ -46,6 +48,10 @@
       if import_base in _POLYMERS:
         continue
 
+      if import_base == _WEB_ANIMATIONS_BASE:
+        dependencies.append(_WEB_ANIMATIONS_TARGET)
+        continue
+
       target = import_base[:-5] + "-extracted"
       if not path.isfile(path.join(html_dir, import_dir, target + ".js")):
         continue
diff --git a/ui/app_list/app_list_view_delegate.cc b/ui/app_list/app_list_view_delegate.cc
index 7ec19b7..2ec5b4ac 100644
--- a/ui/app_list/app_list_view_delegate.cc
+++ b/ui/app_list/app_list_view_delegate.cc
@@ -13,4 +13,28 @@
 
 AppListViewDelegate::User::~User() {}
 
-}  // app_list
+#if !defined(OS_CHROMEOS)
+base::string16 AppListViewDelegate::GetMessageTitle() const {
+  return base::string16();
+}
+base::string16 AppListViewDelegate::GetMessageText(
+    size_t* message_break) const {
+  *message_break = 0;
+  return base::string16();
+}
+base::string16 AppListViewDelegate::GetAppsShortcutName() const {
+  return base::string16();
+}
+base::string16 AppListViewDelegate::GetLearnMoreText() const {
+  return base::string16();
+}
+base::string16 AppListViewDelegate::GetLearnMoreLink() const {
+  return base::string16();
+}
+gfx::ImageSkia* AppListViewDelegate::GetAppsIcon() const {
+  return nullptr;
+}
+void AppListViewDelegate::OpenLearnMoreLink() {}
+#endif
+
+}  // namespace app_list
diff --git a/ui/app_list/app_list_view_delegate.h b/ui/app_list/app_list_view_delegate.h
index 69462e78..2a2beca5 100644
--- a/ui/app_list/app_list_view_delegate.h
+++ b/ui/app_list/app_list_view_delegate.h
@@ -165,6 +165,21 @@
   // Adds/removes an observer for profile changes.
   virtual void AddObserver(AppListViewDelegateObserver* observer) {}
   virtual void RemoveObserver(AppListViewDelegateObserver* observer) {}
+
+#if !defined(OS_CHROMEOS)
+  // Methods to retrieve properties of the message displayed on the app launcher
+  // above the apps grid.
+  virtual base::string16 GetMessageTitle() const;
+  // Returns the message text (with the placeholder symbol removed).
+  // |message_break| is set to the index where the placeholder was in the
+  // string.
+  virtual base::string16 GetMessageText(size_t* message_break) const;
+  virtual base::string16 GetAppsShortcutName() const;
+  virtual base::string16 GetLearnMoreText() const;
+  virtual base::string16 GetLearnMoreLink() const;
+  virtual gfx::ImageSkia* GetAppsIcon() const;
+  virtual void OpenLearnMoreLink();
+#endif
 };
 
 }  // namespace app_list
diff --git a/ui/app_list/cocoa/app_list_view_controller.h b/ui/app_list/cocoa/app_list_view_controller.h
index 3329dd1..6e8534e 100644
--- a/ui/app_list/cocoa/app_list_view_controller.h
+++ b/ui/app_list/cocoa/app_list_view_controller.h
@@ -29,7 +29,8 @@
 APP_LIST_EXPORT
 @interface AppListViewController : NSViewController<AppsPaginationModelObserver,
                                                     AppsSearchBoxDelegate,
-                                                    AppsSearchResultsDelegate> {
+                                                    AppsSearchResultsDelegate,
+                                                    NSTextViewDelegate> {
  @private
   base::scoped_nsobject<AppsGridController> appsGridController_;
   base::scoped_nsobject<AppListPagerView> pagerControl_;
@@ -37,6 +38,10 @@
   base::scoped_nsobject<AppsSearchResultsController>
       appsSearchResultsController_;
 
+  // If set, a message displayed above the app list grid.
+  base::scoped_nsobject<NSTextView> messageText_;
+  base::scoped_nsobject<NSScrollView> messageScrollView_;
+
   // Subview for drawing the background.
   base::scoped_nsobject<NSView> backgroundView_;
 
diff --git a/ui/app_list/cocoa/app_list_view_controller.mm b/ui/app_list/cocoa/app_list_view_controller.mm
index 6862aec..568acc72 100644
--- a/ui/app_list/cocoa/app_list_view_controller.mm
+++ b/ui/app_list/cocoa/app_list_view_controller.mm
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "skia/ext/skia_utils_mac.h"
 #include "ui/app_list/app_list_constants.h"
 #include "ui/app_list/app_list_model.h"
@@ -20,6 +21,7 @@
 #import "ui/app_list/cocoa/apps_grid_controller.h"
 #include "ui/app_list/search_box_model.h"
 #import "ui/base/cocoa/flipped_view.h"
+#import "ui/gfx/image/image_skia_util_mac.h"
 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
 
 namespace {
@@ -45,6 +47,15 @@
 // Duration of the animation for sliding in and out search results.
 const NSTimeInterval kResultsAnimationDuration = 0.2;
 
+// Properties of the message rectangle, if it is shown.
+const NSRect kMessageRect = {{12, 12}, {370, 91}};
+const CGFloat kMessageCornerRadius = 2;
+const CGFloat kSpacingBelowMessageTitle = 6;
+const SkColor kMessageBackgroundColor = SkColorSetRGB(0xFF, 0xFD, 0xE7);
+const SkColor kMessageStrokeColor = SkColorSetARGB(0x3d, 0x00, 0x00, 0x00);
+// The inset should be 16px, but NSTextView has its own inset of 3.
+const CGFloat kMessageTextInset = 13;
+
 }  // namespace
 
 @interface BackgroundView : FlippedView;
@@ -74,8 +85,33 @@
 
 @end
 
+@interface MessageBackgroundView : FlippedView
+@end
+
+@implementation MessageBackgroundView
+
+- (void)drawRect:(NSRect)dirtyRect {
+  NSRect boundsRect = [self bounds];
+  gfx::ScopedNSGraphicsContextSaveGState context;
+  [[NSBezierPath bezierPathWithRoundedRect:boundsRect
+                                   xRadius:kMessageCornerRadius
+                                   yRadius:kMessageCornerRadius] addClip];
+
+  [skia::SkColorToSRGBNSColor(kMessageStrokeColor) set];
+  NSRectFill(boundsRect);
+
+  [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(boundsRect, 1, 1)
+                                   xRadius:kMessageCornerRadius
+                                   yRadius:kMessageCornerRadius] addClip];
+  [skia::SkColorToSRGBNSColor(kMessageBackgroundColor) set];
+  NSRectFill(boundsRect);
+}
+
+@end
+
 @interface AppListViewController ()
 
+- (void)updateMessage;
 - (void)loadAndSetView;
 - (void)revealSearchResults:(BOOL)show;
 
@@ -176,6 +212,7 @@
     [appsSearchResultsController_ setDelegate:nil];
     [appsSearchBoxController_ setDelegate:nil];
     [appsGridController_ setDelegate:nil];
+    [messageText_ setDelegate:nil];
   }
   delegate_ = newDelegate;
   if (delegate_) {
@@ -191,17 +228,179 @@
   app_list_model_observer_bridge_.reset(
       new app_list::AppListModelObserverBridge(self));
   [self onProfilesChanged];
+  [self updateMessage];
 }
 
--(void)loadAndSetView {
+- (void)updateMessage {
+  if (![AppsGridController hasFewerRows])
+    return;
+
+  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+  NSFont* messageFont = rb.GetFontWithDelta(0).GetNativeFont();
+  NSFont* titleFont = rb.GetFontWithDelta(2).GetNativeFont();
+
+  base::string16 title = delegate_->GetMessageTitle();
+  size_t messageBreak;
+  base::string16 messageFull = delegate_->GetMessageText(&messageBreak);
+  base::string16 shortcutName = delegate_->GetAppsShortcutName();
+  base::string16 learnMore = delegate_->GetLearnMoreText();
+  base::string16 learnMoreUrl = delegate_->GetLearnMoreLink();
+
+  base::string16 messagePre = messageFull.substr(0, messageBreak);
+  base::string16 messagePost = messageFull.substr(messageBreak);
+
+  NSURL* linkURL = [NSURL URLWithString:base::SysUTF16ToNSString(learnMoreUrl)];
+  gfx::ImageSkia* icon = delegate_->GetAppsIcon();
+
+  // Shift the baseline up so that the graphics align centered. 4 looks nice. It
+  // happens to be the image size minus the font size, but that's a coincidence.
+  const CGFloat kBaselineShift = 4;
+  base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
+      [[NSMutableParagraphStyle alloc] init]);
+  [paragraphStyle setLineSpacing:kSpacingBelowMessageTitle + kBaselineShift];
+
+  NSNumber* baselineOffset = [NSNumber numberWithFloat:kBaselineShift];
+  base::scoped_nsobject<NSMutableAttributedString> text(
+      [[NSMutableAttributedString alloc]
+          initWithString:base::SysUTF16ToNSString(title)
+              attributes:@{
+                NSParagraphStyleAttributeName : paragraphStyle,
+                NSFontAttributeName : titleFont
+              }]);
+
+  NSDictionary* defaultAttributes = @{
+    NSFontAttributeName : messageFont,
+    NSBaselineOffsetAttributeName : baselineOffset
+  };
+
+  base::scoped_nsobject<NSAttributedString> lineBreak(
+      [[NSAttributedString alloc] initWithString:@"\n"
+                                      attributes:defaultAttributes]);
+  base::scoped_nsobject<NSAttributedString> space([[NSAttributedString alloc]
+      initWithString:@" "
+          attributes:defaultAttributes]);
+  base::scoped_nsobject<NSAttributedString> messagePreString(
+      [[NSAttributedString alloc]
+          initWithString:base::SysUTF16ToNSString(messagePre)
+              attributes:defaultAttributes]);
+  base::scoped_nsobject<NSAttributedString> messagePostString(
+      [[NSAttributedString alloc]
+          initWithString:base::SysUTF16ToNSString(messagePost)
+              attributes:defaultAttributes]);
+
+  // NSNoUnderlineStyle is broken.
+  base::scoped_nsobject<NSAttributedString> learnMoreString(
+      [[NSAttributedString alloc]
+          initWithString:base::SysUTF16ToNSString(learnMore)
+              attributes:@{
+                NSParagraphStyleAttributeName : paragraphStyle,
+                NSFontAttributeName : messageFont,
+                NSLinkAttributeName : linkURL,
+                NSBaselineOffsetAttributeName : baselineOffset,
+                NSUnderlineStyleAttributeName :
+                    [NSNumber numberWithInt:NSNoUnderlineStyle]
+              }]);
+  base::scoped_nsobject<NSAttributedString> shortcutStringText(
+      [[NSAttributedString alloc]
+          initWithString:base::SysUTF16ToNSString(shortcutName)
+              attributes:defaultAttributes]);
+  base::scoped_nsobject<NSMutableAttributedString> shortcutString(
+      [[NSMutableAttributedString alloc] init]);
+  if (icon) {
+    NSImage* image = gfx::NSImageFromImageSkia(*icon);
+    // The image has a bunch of representations. Ensure the smallest is used.
+    // (Going smaller would make pixels all manky, so don't do that).
+    [image setSize:NSMakeSize(16, 16)];
+
+    base::scoped_nsobject<NSTextAttachmentCell> attachmentCell(
+        [[NSTextAttachmentCell alloc] initImageCell:image]);
+    base::scoped_nsobject<NSTextAttachment> attachment(
+        [[NSTextAttachment alloc] init]);
+    [attachment setAttachmentCell:attachmentCell];
+    [shortcutString
+        appendAttributedString:[NSAttributedString
+                                   attributedStringWithAttachment:attachment]];
+    [shortcutString appendAttributedString:space];
+  }
+  [shortcutString appendAttributedString:shortcutStringText];
+
+  [text appendAttributedString:lineBreak];
+  [text appendAttributedString:messagePreString];
+  [text appendAttributedString:shortcutString];
+  [text appendAttributedString:messagePostString];
+  [text appendAttributedString:space];
+  [text appendAttributedString:learnMoreString];
+
+  [[messageText_ textStorage] setAttributedString:text];
+  [messageText_ sizeToFit];
+
+  // If the user scroller preference is to always show scrollbars, and the
+  // translated message is long, the scroll track may be present. This means
+  // text will be under the scroller. We only want vertical scrolling, but
+  // reducing the width puts the scroll track in a weird spot. So, increase the
+  // width of the scroll view to move the track into the padding towards the
+  // message background border, then reduce the width of the text view. The
+  // non-overlay scroller still looks kinda weird but hopefully not many will
+  // actually see it.
+  CGFloat overlap =
+      NSWidth([messageText_ bounds]) - [messageScrollView_ contentSize].width;
+  if (overlap > 0) {
+    NSRect rect = [messageScrollView_ frame];
+    rect.size.width += kMessageTextInset - 2;
+    [messageScrollView_ setFrame:rect];
+    overlap -= kMessageTextInset - 2;
+    DCHECK_GT(overlap, 0);
+    rect = [messageText_ frame];
+    rect.size.width -= overlap;
+    [messageText_ setFrame:rect];
+    [messageText_ sizeToFit];
+
+    // And after doing all that for some reason Cocoa scrolls to the bottom. So
+    // fix that.
+    [[messageScrollView_ documentView] scrollPoint:NSMakePoint(0, 0)];
+  }
+
+  [messageText_ setDelegate:self];
+}
+
+- (void)loadAndSetView {
   pagerControl_.reset([[AppListPagerView alloc] init]);
   [pagerControl_ setTarget:appsGridController_];
   [pagerControl_ setAction:@selector(onPagerClicked:)];
 
   NSRect gridFrame = [[appsGridController_ view] frame];
-  NSRect contentsRect = NSMakeRect(0, kSearchInputHeight + kTopSeparatorSize,
-      NSWidth(gridFrame), NSHeight(gridFrame) + kPagerPreferredHeight -
-          [AppsGridController scrollerPadding]);
+
+  base::scoped_nsobject<NSView> messageTextBackground;
+  if ([AppsGridController hasFewerRows]) {
+    messageTextBackground.reset(
+        [[MessageBackgroundView alloc] initWithFrame:kMessageRect]);
+    NSRect frameRect =
+        NSInsetRect(kMessageRect, kMessageTextInset, kMessageTextInset);
+    messageText_.reset([[NSTextView alloc] initWithFrame:frameRect]);
+    // Provide a solid background here (as well as the background) so that
+    // subpixel AA works.
+    [messageText_
+        setBackgroundColor:skia::SkColorToSRGBNSColor(kMessageBackgroundColor)];
+    [messageText_ setDrawsBackground:YES];
+    [messageText_ setEditable:NO];
+    // Ideally setSelectable:NO would also be set here, but that disables mouse
+    // events completely, breaking the "Learn more" link. Instead, selection is
+    // "disabled" via a delegate method which Apple's documentation suggests. In
+    // reality, selection still happens, it just disappears once the mouse is
+    // released. To avoid the selection appearing, also set selected text to
+    // have no special attributes. Sadly, the mouse cursor still displays an
+    // I-beam, but hacking cursor rectangles on the view so that the "Learn
+    // More" link is still correctly handled is too hard.
+    [messageText_ setSelectedTextAttributes:@{}];
+    gridFrame.origin.y += NSMaxY([messageTextBackground frame]);
+  }
+
+  [[appsGridController_ view] setFrame:gridFrame];
+
+  NSRect contentsRect =
+      NSMakeRect(0, kSearchInputHeight + kTopSeparatorSize, NSWidth(gridFrame),
+                 NSMaxY(gridFrame) + kPagerPreferredHeight -
+                     [AppsGridController scrollerPadding]);
 
   contentsView_.reset([[FlippedView alloc] initWithFrame:contentsRect]);
 
@@ -236,6 +435,28 @@
   [loadingIndicator_ setDisplayedWhenStopped:NO];
   [loadingIndicator_ startAnimation:self];
 
+  if (messageText_) {
+    [contentsView_ addSubview:messageTextBackground];
+
+    // Add a scroll view in case the translation is long and doesn't fit. Mac
+    // likes to hide scrollbars, so add to the height so the user can see part
+    // of the next line of text: just extend out into the padding towards the
+    // text background's border. Subtract at least 2: one for the border stroke
+    // and one for a bit of padding.
+    NSRect frameRect = [messageText_ frame];
+    frameRect.size.height += kMessageTextInset - 2;
+    messageScrollView_.reset([[NSScrollView alloc] initWithFrame:frameRect]);
+    [messageScrollView_ setHasVerticalScroller:YES];
+    [messageScrollView_ setAutohidesScrollers:YES];
+
+    // Now the message is going into an NSScrollView, origin should be 0, 0.
+    frameRect = [messageText_ frame];
+    frameRect.origin = NSMakePoint(0, 0);
+    [messageText_ setFrame:frameRect];
+
+    [messageScrollView_ setDocumentView:messageText_];
+    [contentsView_ addSubview:messageScrollView_];
+  }
   [contentsView_ addSubview:[appsGridController_ view]];
   [contentsView_ addSubview:pagerControl_];
   [contentsView_ addSubview:loadingIndicator_];
@@ -368,4 +589,20 @@
   [appsSearchBoxController_ rebuildMenu];
 }
 
+// NSTextViewDelegate implementation.
+
+- (BOOL)textView:(NSTextView*)textView
+    clickedOnLink:(id)link
+          atIndex:(NSUInteger)charIndex {
+  DCHECK(delegate_);
+  delegate_->OpenLearnMoreLink();
+  return YES;
+}
+
+- (NSArray*)textView:(NSTextView*)aTextView
+    willChangeSelectionFromCharacterRanges:(NSArray*)oldSelectedCharRanges
+                         toCharacterRanges:(NSArray*)newSelectedCharRanges {
+  return oldSelectedCharRanges;
+}
+
 @end
diff --git a/ui/app_list/cocoa/apps_grid_controller.h b/ui/app_list/cocoa/apps_grid_controller.h
index b82f948..194f84a 100644
--- a/ui/app_list/cocoa/apps_grid_controller.h
+++ b/ui/app_list/cocoa/apps_grid_controller.h
@@ -59,6 +59,9 @@
 // invisible scroller that allows for gesture scrolling.
 + (CGFloat)scrollerPadding;
 
+// Whether the grid is configured with fewer rows than normal.
++ (BOOL)hasFewerRows;
+
 - (NSCollectionView*)collectionViewAtPageIndex:(size_t)pageIndex;
 - (size_t)pageIndexForCollectionView:(NSCollectionView*)page;
 
diff --git a/ui/app_list/cocoa/apps_grid_controller.mm b/ui/app_list/cocoa/apps_grid_controller.mm
index 53ea288..455c441 100644
--- a/ui/app_list/cocoa/apps_grid_controller.mm
+++ b/ui/app_list/cocoa/apps_grid_controller.mm
@@ -4,6 +4,7 @@
 
 #import "ui/app_list/cocoa/apps_grid_controller.h"
 
+#include "base/command_line.h"
 #include "base/mac/foundation_util.h"
 #include "base/macros.h"
 #include "ui/app_list/app_list_item.h"
@@ -17,10 +18,8 @@
 
 namespace {
 
-// OSX app list has hardcoded rows and columns for now.
-const int kFixedRows = 4;
+// OSX app list has hardcoded columns for now.
 const int kFixedColumns = 4;
-const int kItemsPerPage = kFixedRows * kFixedColumns;
 
 // Padding space in pixels for fixed layout.
 const CGFloat kGridTopPadding = 1;
@@ -34,11 +33,31 @@
 
 const CGFloat kViewWidth =
     kFixedColumns * kPreferredTileWidth + 2 * kLeftRightPadding;
-const CGFloat kViewHeight = kFixedRows * kPreferredTileHeight;
 
 const NSTimeInterval kScrollWhileDraggingDelay = 1.0;
 NSTimeInterval g_scroll_duration = 0.18;
 
+const char kTestType[] = "test-type";
+
+int DetermineFixedRowCount() {
+  // This needs to be called before a delegate exists, since it is needed to
+  // determine the height of the view.
+  return [AppsGridController hasFewerRows] ? 3 : 4;
+}
+
+int RowCount() {
+  static const int row_count = DetermineFixedRowCount();
+  return row_count;
+}
+
+int ItemsPerPage() {
+  return RowCount() * kFixedColumns;
+}
+
+CGFloat ViewHeight() {
+  return RowCount() * kPreferredTileHeight;
+}
+
 }  // namespace
 
 @interface AppsGridController ()
@@ -119,7 +138,7 @@
       return;
 
     [parent_ selectItemAtIndex:index];
-    [parent_ scrollToPage:index / kItemsPerPage];
+    [parent_ scrollToPage:index / ItemsPerPage()];
   }
 
   AppsGridController* parent_;  // Weak, owns us.
@@ -152,17 +171,21 @@
   return kScrollerPadding;
 }
 
++ (BOOL)hasFewerRows {
+  return !base::CommandLine::ForCurrentProcess()->HasSwitch(kTestType);
+}
+
 @synthesize paginationObserver = paginationObserver_;
 
 - (id)init {
   if ((self = [super init])) {
     bridge_.reset(new app_list::AppsGridDelegateBridge(self));
     NSSize cellSize = NSMakeSize(kPreferredTileWidth, kPreferredTileHeight);
-    dragManager_.reset(
-        [[AppsCollectionViewDragManager alloc] initWithCellSize:cellSize
-                                                           rows:kFixedRows
-                                                        columns:kFixedColumns
-                                                 gridController:self]);
+    dragManager_.reset([[AppsCollectionViewDragManager alloc]
+        initWithCellSize:cellSize
+                    rows:RowCount()
+                 columns:kFixedColumns
+          gridController:self]);
     pages_.reset([[NSMutableArray alloc] init]);
     items_.reset([[NSMutableArray alloc] init]);
     [self loadAndSetView];
@@ -357,7 +380,7 @@
       [[PageContainerView alloc] initWithFrame:NSZeroRect]);
 
   NSRect scrollFrame = NSMakeRect(0, kGridTopPadding, kViewWidth,
-                                  kViewHeight + kScrollerPadding);
+                                  ViewHeight() + kScrollerPadding);
   base::scoped_nsobject<ScrollViewWithNoScrollbars> scrollView(
       [[ScrollViewWithNoScrollbars alloc] initWithFrame:scrollFrame]);
   [scrollView setBorderType:NSNoBorder];
@@ -403,9 +426,9 @@
 }
 
 - (AppsGridViewItem*)itemAtIndex:(size_t)itemIndex {
-  const size_t pageIndex = itemIndex / kItemsPerPage;
+  const size_t pageIndex = itemIndex / ItemsPerPage();
   return [self itemAtPageIndex:pageIndex
-                   indexInPage:itemIndex - pageIndex * kItemsPerPage];
+                   indexInPage:itemIndex - pageIndex * ItemsPerPage()];
 }
 
 - (NSUInteger)selectedItemIndex {
@@ -414,7 +437,7 @@
   if (indexOnPage == NSNotFound)
     return NSNotFound;
 
-  return indexOnPage + visiblePage_ * kItemsPerPage;
+  return indexOnPage + visiblePage_ * ItemsPerPage();
 }
 
 - (NSButton*)selectedButton {
@@ -437,7 +460,7 @@
   // Note there is always at least one page.
   size_t targetPages = 1;
   if ([items_ count] != 0)
-    targetPages = ([items_ count] - 1) / kItemsPerPage + 1;
+    targetPages = ([items_ count] - 1) / ItemsPerPage() + 1;
 
   const size_t currentPages = [self pageCount];
   // First see if the number of pages have changed.
@@ -449,20 +472,19 @@
     } else {
       // Pages need to be added.
       for (size_t i = currentPages; i < targetPages; ++i) {
-        NSRect pageFrame = NSMakeRect(
-            kLeftRightPadding + kViewWidth * i, 0,
-            kViewWidth, kViewHeight);
+        NSRect pageFrame = NSMakeRect(kLeftRightPadding + kViewWidth * i, 0,
+                                      kViewWidth, ViewHeight());
         [pages_ addObject:[dragManager_ makePageWithFrame:pageFrame]];
       }
     }
 
     [[self pagesContainerView] setSubviews:pages_];
-    NSSize pagesSize = NSMakeSize(kViewWidth * targetPages, kViewHeight);
+    NSSize pagesSize = NSMakeSize(kViewWidth * targetPages, ViewHeight());
     [[self pagesContainerView] setFrameSize:pagesSize];
     [paginationObserver_ totalPagesChanged];
   }
 
-  const size_t startPage = startItemIndex / kItemsPerPage;
+  const size_t startPage = startItemIndex / ItemsPerPage();
   // All pages on or after |startPage| may need items added or removed.
   for (size_t pageIndex = startPage; pageIndex < targetPages; ++pageIndex) {
     [self updatePageContent:pageIndex
@@ -484,7 +506,7 @@
   }
 
   NSRange inPageRange = NSIntersectionRange(
-      NSMakeRange(pageIndex * kItemsPerPage, kItemsPerPage),
+      NSMakeRange(pageIndex * ItemsPerPage(), ItemsPerPage()),
       NSMakeRange(0, [items_ count]));
   NSArray* pageContent = [items_ subarrayWithRange:inPageRange];
   [pageView setContent:pageContent];
@@ -507,8 +529,8 @@
   [items_ insertObject:item
                atIndex:toIndex];
 
-  size_t fromPageIndex = fromIndex / kItemsPerPage;
-  size_t toPageIndex = toIndex / kItemsPerPage;
+  size_t fromPageIndex = fromIndex / ItemsPerPage();
+  size_t toPageIndex = toIndex / ItemsPerPage();
   if (fromPageIndex == toPageIndex) {
     [self updatePageContent:fromPageIndex
                  resetModel:NO];  // Just reorder items.
@@ -603,7 +625,7 @@
 
   // If nothing is currently selected, select the first item on the page.
   if (oldIndex == NSNotFound) {
-    [self selectItemAtIndex:visiblePage_ * kItemsPerPage];
+    [self selectItemAtIndex:visiblePage_ * ItemsPerPage()];
     return YES;
   }
 
@@ -629,8 +651,8 @@
   if (index >= [items_ count])
     return;
 
-  if (index / kItemsPerPage != visiblePage_)
-    [self scrollToPage:index / kItemsPerPage];
+  if (index / ItemsPerPage() != visiblePage_)
+    [self scrollToPage:index / ItemsPerPage()];
 
   [[self itemAtIndex:index] setSelected:YES];
 }
@@ -645,39 +667,41 @@
   NSUInteger oldIndex = [self selectedItemIndex];
   // If nothing is currently selected, select the first item on the page.
   if (oldIndex == NSNotFound) {
-    [self selectItemAtIndex:visiblePage_ * kItemsPerPage];
+    [self selectItemAtIndex:visiblePage_ * ItemsPerPage()];
     return YES;
   }
 
   if (command == @selector(moveLeft:)) {
-    return oldIndex % kFixedColumns == 0 ?
-        [self moveSelectionByDelta:-kItemsPerPage + kFixedColumns - 1] :
-        [self moveSelectionByDelta:-1];
+    return oldIndex % kFixedColumns == 0
+               ? [self moveSelectionByDelta:-ItemsPerPage() + kFixedColumns - 1]
+               : [self moveSelectionByDelta:-1];
   }
 
   if (command == @selector(moveRight:)) {
-    return oldIndex % kFixedColumns == kFixedColumns - 1 ?
-        [self moveSelectionByDelta:+kItemsPerPage - kFixedColumns + 1] :
-        [self moveSelectionByDelta:1];
+    return oldIndex % kFixedColumns == kFixedColumns - 1
+               ? [self moveSelectionByDelta:+ItemsPerPage() - kFixedColumns + 1]
+               : [self moveSelectionByDelta:1];
   }
 
   if (command == @selector(moveUp:)) {
-    return oldIndex / kFixedColumns % kFixedRows == 0 ?
-        NO : [self moveSelectionByDelta:-kFixedColumns];
+    return oldIndex / kFixedColumns % RowCount() == 0
+               ? NO
+               : [self moveSelectionByDelta:-kFixedColumns];
   }
 
   if (command == @selector(moveDown:)) {
-    return oldIndex / kFixedColumns % kFixedRows == kFixedRows - 1 ?
-        NO : [self moveSelectionByDelta:kFixedColumns];
+    return oldIndex / kFixedColumns % RowCount() == RowCount() - 1
+               ? NO
+               : [self moveSelectionByDelta:kFixedColumns];
   }
 
   if (command == @selector(pageUp:) ||
       command == @selector(scrollPageUp:))
-    return [self moveSelectionByDelta:-kItemsPerPage];
+    return [self moveSelectionByDelta:-ItemsPerPage()];
 
   if (command == @selector(pageDown:) ||
       command == @selector(scrollPageDown:))
-    return [self moveSelectionByDelta:kItemsPerPage];
+    return [self moveSelectionByDelta:ItemsPerPage()];
 
   return NO;
 }
diff --git a/ui/app_list/test/run_all_unittests.cc b/ui/app_list/test/run_all_unittests.cc
index eb2bf1f1..7b27bb9c 100644
--- a/ui/app_list/test/run_all_unittests.cc
+++ b/ui/app_list/test/run_all_unittests.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/bind.h"
+#include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/path_service.h"
@@ -24,12 +25,19 @@
 
 namespace {
 
+// Use the pattern established in content_switches.h, but don't add a content
+// dependency -- app list shouldn't have one.
+const char kTestType[] = "test-type";
+
 class AppListTestSuite : public base::TestSuite {
  public:
   AppListTestSuite(int argc, char** argv) : base::TestSuite(argc, argv) {}
 
  protected:
   void Initialize() override {
+    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+    command_line->AppendSwitchASCII(kTestType, "applist");
+
 #if defined(OS_MACOSX)
     mock_cr_app::RegisterMockCrApp();
 #endif
diff --git a/ui/aura/test/test_focus_client.cc b/ui/aura/test/test_focus_client.cc
index c7f9f8c..662f9b1 100644
--- a/ui/aura/test/test_focus_client.cc
+++ b/ui/aura/test/test_focus_client.cc
@@ -25,14 +25,18 @@
 // TestFocusClient, client::FocusClient implementation:
 
 void TestFocusClient::AddObserver(client::FocusChangeObserver* observer) {
+  focus_observers_.AddObserver(observer);
 }
 
 void TestFocusClient::RemoveObserver(client::FocusChangeObserver* observer) {
+  focus_observers_.RemoveObserver(observer);
 }
 
 void TestFocusClient::FocusWindow(Window* window) {
   if (window && !window->CanFocus())
     return;
+
+  aura::Window* lost_focus = focused_window_;
   if (focused_window_)
     observer_manager_.Remove(focused_window_);
   aura::Window* old_focused_window = focused_window_;
@@ -40,6 +44,9 @@
   if (focused_window_)
     observer_manager_.Add(focused_window_);
 
+  FOR_EACH_OBSERVER(aura::client::FocusChangeObserver,
+                     focus_observers_,
+                     OnWindowFocused(focused_window_, lost_focus));
   client::FocusChangeObserver* observer =
       client::GetFocusChangeObserver(old_focused_window);
   if (observer)
diff --git a/ui/aura/test/test_focus_client.h b/ui/aura/test/test_focus_client.h
index 39455935..78c3c3b 100644
--- a/ui/aura/test/test_focus_client.h
+++ b/ui/aura/test/test_focus_client.h
@@ -7,6 +7,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "base/observer_list.h"
 #include "base/scoped_observer.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/window_observer.h"
@@ -33,6 +34,7 @@
 
   Window* focused_window_;
   ScopedObserver<Window, WindowObserver> observer_manager_;
+  base::ObserverList<aura::client::FocusChangeObserver> focus_observers_;
 
   DISALLOW_COPY_AND_ASSIGN(TestFocusClient);
 };
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index a942a89..9c492698 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -468,6 +468,11 @@
                     OnCompositingAborted(this));
 }
 
+void Compositor::SetOutputIsSecure(bool output_is_secure) {
+  host_->SetOutputIsSecure(output_is_secure);
+  host_->SetNeedsRedraw();
+}
+
 void Compositor::SendBeginFramesToChildren(const cc::BeginFrameArgs& args) {
   FOR_EACH_OBSERVER(CompositorBeginFrameObserver, begin_frame_observer_list_,
                     OnSendBeginFrame(args));
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index 5222b41..acae0be4 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -318,6 +318,8 @@
 
   bool IsLocked() { return compositor_lock_ != NULL; }
 
+  void SetOutputIsSecure(bool output_is_secure);
+
   const cc::LayerTreeDebugState& GetLayerTreeDebugState() const;
   void SetLayerTreeDebugState(const cc::LayerTreeDebugState& debug_state);
   const cc::RendererSettings& GetRendererSettings() const;
diff --git a/ui/gfx/mac/io_surface.cc b/ui/gfx/mac/io_surface.cc
index e6079c7..e48a813 100644
--- a/ui/gfx/mac/io_surface.cc
+++ b/ui/gfx/mac/io_surface.cc
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include "base/logging.h"
+#include "base/mac/mac_util.h"
 #include "base/mac/mach_logging.h"
 #include "base/macros.h"
 #include "ui/gfx/buffer_format_util.h"
@@ -150,12 +151,18 @@
 
   IOSurfaceRef surface = IOSurfaceCreate(properties);
 
-  // Zero-initialize the IOSurface. Calling IOSurfaceLock/IOSurfaceUnlock
-  // appears to be sufficient. https://crbug.com/584760#c17
-  IOReturn r = IOSurfaceLock(surface, 0, nullptr);
-  DCHECK_EQ(kIOReturnSuccess, r);
-  r = IOSurfaceUnlock(surface, 0, nullptr);
-  DCHECK_EQ(kIOReturnSuccess, r);
+  // For unknown reasons, triggering this lock on OS X 10.9, on certain GPUs,
+  // causes PDFs to render incorrectly. Hopefully this check can be removed once
+  // pdfium switches to a Skia backend on Mac.
+  // https://crbug.com/594343.
+  if (!base::mac::IsOSMavericks()) {
+    // Zero-initialize the IOSurface. Calling IOSurfaceLock/IOSurfaceUnlock
+    // appears to be sufficient. https://crbug.com/584760#c17
+    IOReturn r = IOSurfaceLock(surface, 0, nullptr);
+    DCHECK_EQ(kIOReturnSuccess, r);
+    r = IOSurfaceUnlock(surface, 0, nullptr);
+    DCHECK_EQ(kIOReturnSuccess, r);
+  }
 
   return surface;
 }
diff --git a/ui/gl/test/gl_image_test_template.h b/ui/gl/test/gl_image_test_template.h
index 28567bc..e10c64c 100644
--- a/ui/gl/test/gl_image_test_template.h
+++ b/ui/gl/test/gl_image_test_template.h
@@ -13,6 +13,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/stringize_macros.h"
 #include "base/strings/stringprintf.h"
+#include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/buffer_types.h"
@@ -25,6 +26,10 @@
 #include "ui/gl/test/gl_image_test_support.h"
 #include "ui/gl/test/gl_test_helper.h"
 
+#if defined(OS_MACOSX)
+#include "base/mac/mac_util.h"
+#endif
+
 namespace gl {
 namespace {
 
@@ -178,6 +183,13 @@
 TYPED_TEST_CASE_P(GLImageZeroInitializeTest);
 
 TYPED_TEST_P(GLImageZeroInitializeTest, ZeroInitialize) {
+#if defined(OS_MACOSX)
+  // This functionality is disabled on Mavericks because it breaks PDF
+  // rendering. https://crbug.com/594343.
+  if (base::mac::IsOSMavericks())
+    return;
+#endif
+
   const gfx::Size image_size(256, 256);
 
   GLuint framebuffer =
diff --git a/ui/views/controls/button/custom_button.cc b/ui/views/controls/button/custom_button.cc
index d655ac34..fc07e0b 100644
--- a/ui/views/controls/button/custom_button.cc
+++ b/ui/views/controls/button/custom_button.cc
@@ -10,8 +10,10 @@
 #include "ui/events/event_utils.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/gfx/animation/throb_animation.h"
+#include "ui/gfx/canvas.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/screen.h"
+#include "ui/native_theme/native_theme.h"
 #include "ui/views/animation/ink_drop_delegate.h"
 #include "ui/views/animation/ink_drop_hover.h"
 #include "ui/views/controls/button/blue_button.h"
@@ -29,16 +31,51 @@
 
 namespace views {
 
-// How long the hover animation takes if uninterrupted.
-static const int kHoverFadeDurationMs = 150;
+namespace {
 
-// static
-const char CustomButton::kViewClassName[] = "CustomButton";
+// How long the hover animation takes if uninterrupted.
+const int kHoverFadeDurationMs = 150;
+
+// The amount to enlarge the focus border in all directions relative to the
+// button.
+const int kFocusBorderOutset = -2;
+
+// The corner radius of the focus border roundrect.
+const int kFocusBorderCornerRadius = 3;
+
+class MdFocusRing : public views::View {
+ public:
+  MdFocusRing() {
+    SetPaintToLayer(true);
+    layer()->SetFillsBoundsOpaquely(false);
+  }
+  ~MdFocusRing() override {}
+
+  void OnPaint(gfx::Canvas* canvas) override {
+    SkPaint paint;
+    paint.setAntiAlias(true);
+    paint.setColor(GetNativeTheme()->GetSystemColor(
+        ui::NativeTheme::kColorId_CallToActionColor));
+    paint.setStyle(SkPaint::kStroke_Style);
+    paint.setStrokeWidth(1);
+    gfx::RectF rect(GetLocalBounds());
+    rect.Inset(gfx::InsetsF(0.5));
+    canvas->DrawRoundRect(rect, kFocusBorderCornerRadius, paint);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MdFocusRing);
+};
+
+}  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
 // CustomButton, public:
 
 // static
+const char CustomButton::kViewClassName[] = "CustomButton";
+
+// static
 const CustomButton* CustomButton::AsCustomButton(const views::View* view) {
   return AsCustomButton(const_cast<views::View*>(view));
 }
@@ -352,6 +389,37 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// CustomButton, View overrides (public):
+
+void CustomButton::Layout() {
+  Button::Layout();
+  gfx::Rect focus_bounds = GetLocalBounds();
+  focus_bounds.Inset(gfx::Insets(kFocusBorderOutset));
+  if (md_focus_ring_)
+    md_focus_ring_->SetBoundsRect(focus_bounds);
+}
+
+void CustomButton::ViewHierarchyChanged(
+    const ViewHierarchyChangedDetails& details) {
+  if (!details.is_add && state_ != STATE_DISABLED)
+    SetState(STATE_NORMAL);
+}
+
+void CustomButton::OnFocus() {
+  Button::OnFocus();
+  if (md_focus_ring_)
+    md_focus_ring_->SetVisible(true);
+}
+
+void CustomButton::OnBlur() {
+  Button::OnBlur();
+  if (IsHotTracked())
+    SetState(STATE_NORMAL);
+  if (md_focus_ring_)
+    md_focus_ring_->SetVisible(false);
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // CustomButton, protected:
 
 CustomButton::CustomButton(ButtonListener* listener)
@@ -366,7 +434,8 @@
       notify_action_(NOTIFY_ON_RELEASE),
       has_ink_drop_action_on_click_(false),
       ink_drop_action_on_click_(InkDropState::QUICK_ACTION),
-      ink_drop_base_color_(gfx::kPlaceholderColor) {
+      ink_drop_base_color_(gfx::kPlaceholderColor),
+      md_focus_ring_(nullptr) {
   hover_animation_.SetSlideDuration(kHoverFadeDurationMs);
 }
 
@@ -412,19 +481,16 @@
   return check_mouse_position && IsMouseHovered();
 }
 
+void CustomButton::UseMdFocusRing() {
+  DCHECK(!md_focus_ring_);
+  md_focus_ring_ = new MdFocusRing();
+  AddChildView(md_focus_ring_);
+  md_focus_ring_->SetVisible(false);
+  set_request_focus_on_press(false);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
-// CustomButton, View overrides (protected):
-
-void CustomButton::ViewHierarchyChanged(
-    const ViewHierarchyChangedDetails& details) {
-  if (!details.is_add && state_ != STATE_DISABLED)
-    SetState(STATE_NORMAL);
-}
-
-void CustomButton::OnBlur() {
-  if (IsHotTracked())
-    SetState(STATE_NORMAL);
-}
+// CustomButton, Button overrides (protected):
 
 void CustomButton::NotifyClick(const ui::Event& event) {
   if (ink_drop_delegate() && has_ink_drop_action_on_click_)
diff --git a/ui/views/controls/button/custom_button.h b/ui/views/controls/button/custom_button.h
index fa0a215..d91d3e68 100644
--- a/ui/views/controls/button/custom_button.h
+++ b/ui/views/controls/button/custom_button.h
@@ -105,6 +105,13 @@
 
   InkDropDelegate* ink_drop_delegate() const { return ink_drop_delegate_; }
 
+  // Overridden from View:
+  void Layout() override;
+  void ViewHierarchyChanged(
+      const ViewHierarchyChangedDetails& details) override;
+  void OnFocus() override;
+  void OnBlur() override;
+
  protected:
   // Construct the Button with a Listener. See comment for Button's ctor.
   explicit CustomButton(ButtonListener* listener);
@@ -141,10 +148,8 @@
     ink_drop_delegate_ = ink_drop_delegate;
   }
 
-  // Overridden from View:
-  void ViewHierarchyChanged(
-      const ViewHierarchyChangedDetails& details) override;
-  void OnBlur() override;
+  // When called, creates and uses |md_focus_ring_| instead of a focus painter.
+  void UseMdFocusRing();
 
   // Overridden from Button:
   void NotifyClick(const ui::Event& event) override;
@@ -191,6 +196,11 @@
   // The color of the ripple and hover.
   SkColor ink_drop_base_color_;
 
+  // The MD-style focus ring. This is not done via a FocusPainter
+  // because it needs to paint to a layer so it can extend beyond the bounds of
+  // |this|.
+  views::View* md_focus_ring_;
+
   DISALLOW_COPY_AND_ASSIGN(CustomButton);
 };
 
diff --git a/ui/views/controls/button/image_button.cc b/ui/views/controls/button/image_button.cc
index fdaa275..a793419 100644
--- a/ui/views/controls/button/image_button.cc
+++ b/ui/views/controls/button/image_button.cc
@@ -136,13 +136,13 @@
 // ImageButton, protected:
 
 void ImageButton::OnFocus() {
-  View::OnFocus();
+  CustomButton::OnFocus();
   if (focus_painter_.get())
     SchedulePaint();
 }
 
 void ImageButton::OnBlur() {
-  View::OnBlur();
+  CustomButton::OnBlur();
   if (focus_painter_.get())
     SchedulePaint();
 }
diff --git a/ui/views/controls/button/label_button.cc b/ui/views/controls/button/label_button.cc
index 0068e12..f5b07e4 100644
--- a/ui/views/controls/button/label_button.cc
+++ b/ui/views/controls/button/label_button.cc
@@ -382,13 +382,13 @@
 }
 
 void LabelButton::OnFocus() {
-  View::OnFocus();
+  CustomButton::OnFocus();
   // Typically the border renders differently when focused.
   SchedulePaint();
 }
 
 void LabelButton::OnBlur() {
-  View::OnBlur();
+  CustomButton::OnBlur();
   // Typically the border renders differently when focused.
   SchedulePaint();
 }
diff --git a/ui/views/controls/button/md_text_button.cc b/ui/views/controls/button/md_text_button.cc
index 46e201e..bf0c9bd0 100644
--- a/ui/views/controls/button/md_text_button.cc
+++ b/ui/views/controls/button/md_text_button.cc
@@ -6,7 +6,6 @@
 
 #include "base/i18n/case_conversion.h"
 #include "ui/base/material_design/material_design_controller.h"
-#include "ui/gfx/canvas.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/native_theme/native_theme.h"
 #include "ui/views/background.h"
@@ -24,37 +23,6 @@
 // Minimum size to reserve for the button contents.
 const int kMinWidth = 48;
 
-// The amount to enlarge the focus border in all directions relative to the
-// button.
-const int kFocusBorderOutset = -2;
-
-// The corner radius of the focus border roundrect.
-const int kFocusBorderCornerRadius = 3;
-
-class MdFocusRing : public views::View {
- public:
-  MdFocusRing() {
-    SetPaintToLayer(true);
-    layer()->SetFillsBoundsOpaquely(false);
-  }
-  ~MdFocusRing() override {}
-
-  void OnPaint(gfx::Canvas* canvas) override {
-    SkPaint paint;
-    paint.setAntiAlias(true);
-    paint.setColor(GetNativeTheme()->GetSystemColor(
-        ui::NativeTheme::kColorId_CallToActionColor));
-    paint.setStyle(SkPaint::kStroke_Style);
-    paint.setStrokeWidth(1);
-    gfx::RectF rect(GetLocalBounds());
-    rect.Inset(gfx::InsetsF(0.5));
-    canvas->DrawRoundRect(rect, kFocusBorderCornerRadius, paint);
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MdFocusRing);
-};
-
 }  // namespace
 
 // static
@@ -88,14 +56,6 @@
   UpdateColorsFromNativeTheme();
 }
 
-void MdTextButton::Layout() {
-  LabelButton::Layout();
-
-  gfx::Rect focus_bounds = GetLocalBounds();
-  focus_bounds.Inset(gfx::Insets(kFocusBorderOutset));
-  focus_ring_->SetBoundsRect(focus_bounds);
-}
-
 void MdTextButton::OnNativeThemeChanged(const ui::NativeTheme* theme) {
   LabelButton::OnNativeThemeChanged(theme);
   UpdateColorsFromNativeTheme();
@@ -109,32 +69,17 @@
   LabelButton::SetText(base::i18n::ToUpper(text));
 }
 
-void MdTextButton::OnFocus() {
-  View::OnFocus();
-  focus_ring_->SetVisible(true);
-}
-
-void MdTextButton::OnBlur() {
-  View::OnBlur();
-  focus_ring_->SetVisible(false);
-}
-
 MdTextButton::MdTextButton(ButtonListener* listener)
     : LabelButton(listener, base::string16()),
       ink_drop_delegate_(this, this),
-      focus_ring_(new MdFocusRing()),
       cta_(NO_CALL_TO_ACTION) {
   set_ink_drop_delegate(&ink_drop_delegate_);
   set_has_ink_drop_action_on_click(true);
   SetHorizontalAlignment(gfx::ALIGN_CENTER);
   SetFocusable(true);
   SetMinSize(gfx::Size(kMinWidth, 0));
-
-  AddChildView(focus_ring_);
-  focus_ring_->SetVisible(false);
   SetFocusPainter(nullptr);
-  set_request_focus_on_press(false);
-
+  UseMdFocusRing();
   label()->SetAutoColorReadabilityEnabled(false);
 }
 
diff --git a/ui/views/controls/button/md_text_button.h b/ui/views/controls/button/md_text_button.h
index eecbf811..8350dac 100644
--- a/ui/views/controls/button/md_text_button.h
+++ b/ui/views/controls/button/md_text_button.h
@@ -32,16 +32,10 @@
   void SetCallToAction(CallToAction cta);
 
   // LabelButton:
-  void Layout() override;
   void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
   SkColor GetInkDropBaseColor() const override;
   void SetText(const base::string16& text) override;
 
- protected:
-  // LabelButton:
-  void OnFocus() override;
-  void OnBlur() override;
-
  private:
   MdTextButton(ButtonListener* listener);
   ~MdTextButton() override;
@@ -50,11 +44,6 @@
 
   ButtonInkDropDelegate ink_drop_delegate_;
 
-  // A child view to draw the focus ring. This is not done via a FocusPainter
-  // because it needs to paint to a layer so it can extend beyond the bounds of
-  // |this|.
-  views::View* focus_ring_;
-
   // The call to action style for this button.
   CallToAction cta_;
 
diff --git a/ui/views/test/views_test_helper_mac.h b/ui/views/test/views_test_helper_mac.h
index 6dbb253..34f5b355 100644
--- a/ui/views/test/views_test_helper_mac.h
+++ b/ui/views/test/views_test_helper_mac.h
@@ -12,6 +12,7 @@
 namespace ui {
 namespace test {
 class ScopedFakeNSWindowFocus;
+class ScopedFakeNSWindowFullscreen;
 }
 class ScopedAnimationDurationScaleMode;
 }
@@ -38,6 +39,12 @@
   // activation, causing it to be synchronous and per-process instead.
   scoped_ptr<ui::test::ScopedFakeNSWindowFocus> faked_focus_;
 
+  // Toggling fullscreen mode on Mac can be flaky for tests run in parallel
+  // because only one window may be animating into or out of fullscreen at a
+  // time. In non-interactive/sharded tests, |faked_fullscreen_| is initialized,
+  // permitting a unit test to 'fake' toggling fullscreen mode.
+  scoped_ptr<ui::test::ScopedFakeNSWindowFullscreen> faked_fullscreen_;
+
   DISALLOW_COPY_AND_ASSIGN(ViewsTestHelperMac);
 };
 
diff --git a/ui/views/test/views_test_helper_mac.mm b/ui/views/test/views_test_helper_mac.mm
index 529d5c6..bcb94869 100644
--- a/ui/views/test/views_test_helper_mac.mm
+++ b/ui/views/test/views_test_helper_mac.mm
@@ -8,6 +8,7 @@
 
 #import "base/mac/scoped_nsautorelease_pool.h"
 #include "ui/base/test/scoped_fake_nswindow_focus.h"
+#include "ui/base/test/scoped_fake_nswindow_fullscreen.h"
 #include "ui/base/test/ui_controls.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/views/test/event_generator_delegate_mac.h"
@@ -39,10 +40,12 @@
   ViewsTestHelper::SetUp();
   // Assume that if the methods in the ui_controls.h test header are enabled
   // then the test runner is in a non-sharded mode, and will use "real"
-  // activations. This allows interactive_ui_tests to test the actual OS window
-  // activation codepaths.
-  if (!ui_controls::IsUIControlsEnabled())
+  // activations and fullscreen mode. This allows interactive_ui_tests to test
+  // the actual OS window activation and fullscreen codepaths.
+  if (!ui_controls::IsUIControlsEnabled()) {
     faked_focus_.reset(new ui::test::ScopedFakeNSWindowFocus);
+    faked_fullscreen_.reset(new ui::test::ScopedFakeNSWindowFullscreen);
+  }
 }
 
 void ViewsTestHelperMac::TearDown() {
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc
index bf34e37..67c2a6c 100644
--- a/ui/views/widget/widget_unittest.cc
+++ b/ui/views/widget/widget_unittest.cc
@@ -45,7 +45,6 @@
 
 #if defined(OS_MACOSX)
 #include "base/mac/mac_util.h"
-#include "ui/base/test/scoped_fake_nswindow_fullscreen.h"
 #endif
 
 namespace views {
@@ -1134,11 +1133,6 @@
     return;
   }
 
-#if defined(OS_MACOSX)
-  // Fullscreen on Mac requires an interactive UI test, fake them here.
-  ui::test::ScopedFakeNSWindowFullscreen fake_fullscreen;
-#endif
-
   WidgetAutoclosePtr toplevel(CreateNativeDesktopWidget());
   toplevel->Show();
   // Initial restored bounds have non-zero size.
@@ -2994,28 +2988,35 @@
   init_params.bounds = gfx::Rect(0, 0, 500, 500);
   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
 
-  {
-    Widget top_level_widget;
-    top_level_widget.Init(init_params);
-    top_level_widget.SetFullscreen(true);
-    EXPECT_EQ(top_level_widget.IsVisible(),
-              IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
-    top_level_widget.CloseNow();
-  }
-#if !defined(OS_CHROMEOS)
-  {
-    Widget top_level_widget;
-    init_params.native_widget = CreatePlatformDesktopNativeWidgetImpl(
-        init_params, &top_level_widget, nullptr);
-    top_level_widget.Init(init_params);
-    top_level_widget.SetFullscreen(true);
-    EXPECT_EQ(top_level_widget.IsVisible(),
-              IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
-    top_level_widget.CloseNow();
-  }
-#endif
+  Widget top_level_widget;
+  top_level_widget.Init(init_params);
+  top_level_widget.SetFullscreen(true);
+  EXPECT_EQ(top_level_widget.IsVisible(),
+            IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
+  top_level_widget.CloseNow();
 }
 
+// Verifies nativeview visbility matches that of Widget visibility when
+// SetFullscreen is invoked, for a widget provided with a desktop widget.
+#if !defined(OS_CHROMEOS)
+TEST_F(WidgetTest, FullscreenStatePropagated_DesktopWidget) {
+  Widget::InitParams init_params =
+      CreateParams(Widget::InitParams::TYPE_WINDOW);
+  init_params.show_state = ui::SHOW_STATE_NORMAL;
+  init_params.bounds = gfx::Rect(0, 0, 500, 500);
+  init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  Widget top_level_widget;
+  init_params.native_widget = CreatePlatformDesktopNativeWidgetImpl(
+      init_params, &top_level_widget, nullptr);
+
+  top_level_widget.Init(init_params);
+  top_level_widget.SetFullscreen(true);
+  EXPECT_EQ(top_level_widget.IsVisible(),
+            IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
+  top_level_widget.CloseNow();
+}
+#endif
+
 namespace {
 
 class FullscreenAwareFrame : public views::NonClientFrameView {