diff --git a/DEPS b/DEPS
index f2ed7382..9e72239 100644
--- a/DEPS
+++ b/DEPS
@@ -39,7 +39,7 @@
   # 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': 'b800248c73c75b02ab808c5bdb53e19e6abc3adc',
+  'skia_revision': 'b988ecf639f1394ea5e821ac15b989e25e064534',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'a39f24c16d2f1b5d5a3b3c623b9857cbc5e02b98',
+  'catapult_revision': '373e8ae0a5f88eb4df8ca40d4a7d63605225f104',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/WATCHLISTS b/WATCHLISTS
index 0d0b147d..ee7f38f 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1348,7 +1348,8 @@
                            'piman+watch@chromium.org'],
     'browser_resources': ['arv+watch@chromium.org'],
     'browser_resources_md': ['michaelpg+watch-md-ui@chromium.org'],
-    'browsing_data': ['markusheintz@chromium.org'],
+    'browsing_data': ['markusheintz@chromium.org',
+                      'msramek+watch@chromium.org'],
     'bubble': ['msw+watch@chromium.org',
                'rouslan+bubble@chromium.org',
                'hcarmona+bubble@chromium.org',
diff --git a/android_webview/browser/aw_render_thread_context_provider.cc b/android_webview/browser/aw_render_thread_context_provider.cc
index 18c70870..93251fa66 100644
--- a/android_webview/browser/aw_render_thread_context_provider.cc
+++ b/android_webview/browser/aw_render_thread_context_provider.cc
@@ -58,8 +58,6 @@
 
   context_->GetImplementation()->SetLostContextCallback(base::Bind(
       &AwRenderThreadContextProvider::OnLostContext, base::Unretained(this)));
-
-  capabilities_.gpu = context_->GetImplementation()->capabilities();
 }
 
 AwRenderThreadContextProvider::~AwRenderThreadContextProvider() {
@@ -75,11 +73,9 @@
   return true;
 }
 
-cc::ContextProvider::Capabilities
-AwRenderThreadContextProvider::ContextCapabilities() {
+gpu::Capabilities AwRenderThreadContextProvider::ContextCapabilities() {
   DCHECK(main_thread_checker_.CalledOnValidThread());
-
-  return capabilities_;
+  return context_->GetImplementation()->capabilities();
 }
 
 gpu::gles2::GLES2Interface* AwRenderThreadContextProvider::ContextGL() {
diff --git a/android_webview/browser/aw_render_thread_context_provider.h b/android_webview/browser/aw_render_thread_context_provider.h
index dcf5ca4..cca675f 100644
--- a/android_webview/browser/aw_render_thread_context_provider.h
+++ b/android_webview/browser/aw_render_thread_context_provider.h
@@ -40,7 +40,7 @@
 
   // cc::ContextProvider:
   bool BindToCurrentThread() override;
-  Capabilities ContextCapabilities() override;
+  gpu::Capabilities ContextCapabilities() override;
   gpu::gles2::GLES2Interface* ContextGL() override;
   gpu::ContextSupport* ContextSupport() override;
   class GrContext* GrContext() override;
@@ -58,8 +58,6 @@
   std::unique_ptr<gpu::GLInProcessContext> context_;
   sk_sp<class GrContext> gr_context_;
 
-  cc::ContextProvider::Capabilities capabilities_;
-
   LostContextCallback lost_context_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(AwRenderThreadContextProvider);
diff --git a/android_webview/common/aw_content_client.cc b/android_webview/common/aw_content_client.cc
index 7dcd028..4839171 100644
--- a/android_webview/common/aw_content_client.cc
+++ b/android_webview/common/aw_content_client.cc
@@ -73,4 +73,8 @@
                   [](char c) { return !::isprint(c); }, '_');
 }
 
+bool AwContentClient::UsingSynchronousCompositing() {
+  return true;
+}
+
 }  // namespace android_webview
diff --git a/android_webview/common/aw_content_client.h b/android_webview/common/aw_content_client.h
index 28eb2fc..e3f8a0d 100644
--- a/android_webview/common/aw_content_client.h
+++ b/android_webview/common/aw_content_client.h
@@ -30,8 +30,9 @@
       int resource_id,
       ui::ScaleFactor scale_factor) const override;
   bool CanSendWhileSwappedOut(const IPC::Message* message) override;
-
   void SetGpuInfo(const gpu::GPUInfo& gpu_info) override;
+  bool UsingSynchronousCompositing() override;
+
   const std::string& gpu_fingerprint() const { return gpu_fingerprint_; }
 
  private:
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
index e00bc138..0a535ce 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
@@ -35,7 +35,6 @@
 import org.chromium.content.browser.ChildProcessConnection;
 import org.chromium.content.browser.ChildProcessLauncher;
 import org.chromium.content.browser.test.util.CallbackHelper;
-import org.chromium.content.common.ContentSwitches;
 import org.chromium.content_public.browser.AccessibilitySnapshotCallback;
 import org.chromium.content_public.browser.AccessibilitySnapshotNode;
 import org.chromium.net.test.util.TestWebServer;
@@ -594,9 +593,7 @@
      */
     @Feature({"AndroidWebView"})
     @SmallTest
-    @CommandLineFlags.Add({
-            AwSwitches.WEBVIEW_SANDBOXED_RENDERER,
-            ContentSwitches.IPC_SYNC_COMPOSITING})
+    @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER)
     @ParameterizedTest.Set
     public void testSandboxedRendererWorks() throws Throwable {
         MockBindingManager bindingManager = new MockBindingManager();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java
index f28d180..7664c12 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java
@@ -31,7 +31,6 @@
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageFinishedHelper;
-import org.chromium.content.common.ContentSwitches;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.net.test.util.TestWebServer;
 
@@ -63,8 +62,7 @@
                                 arguments = {
                                     @Parameter.Argument(
                                         name = CommandLineFlags.Parameter.ADD_ARG,
-                                        stringArray = {AwSwitches.WEBVIEW_SANDBOXED_RENDERER,
-                                                ContentSwitches.IPC_SYNC_COMPOSITING})
+                                        stringArray = {AwSwitches.WEBVIEW_SANDBOXED_RENDERER})
             })})})
 public class AwTestBase
         extends BaseActivityInstrumentationTestCase<AwTestRunnerActivity> {
diff --git a/android_webview/lib/main/aw_main_delegate.cc b/android_webview/lib/main/aw_main_delegate.cc
index f14d45d0..358500bd 100644
--- a/android_webview/lib/main/aw_main_delegate.cc
+++ b/android_webview/lib/main/aw_main_delegate.cc
@@ -72,7 +72,6 @@
       ->set_fling_touchscreen_tap_suppression_enabled(false);
 
   base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
-  cl->AppendSwitch(switches::kIPCSyncCompositing);
   cl->AppendSwitch(cc::switches::kEnableBeginFrameScheduling);
 
   // WebView uses the Android system's scrollbars and overscroll glow.
diff --git a/ash/ash.gyp b/ash/ash.gyp
index 5e7caf48..5ff00c3 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -535,6 +535,8 @@
       'wm/aura/wm_window_aura.h',
       'wm/boot_splash_screen_chromeos.cc',
       'wm/boot_splash_screen_chromeos.h',
+      'wm/common/root_window_finder.cc',
+      'wm/common/root_window_finder.h',
       'wm/common/window_animation_types.h',
       'wm/common/window_parenting_utils.cc',
       'wm/common/window_parenting_utils.h',
@@ -556,8 +558,6 @@
       'wm/common/wm_window_property.h',
       'wm/common/workspace/workspace_layout_manager_delegate.h',
       'wm/common/workspace/workspace_types.h',
-      'wm/coordinate_conversion.cc',
-      'wm/coordinate_conversion.h',
       'wm/cursor_manager_chromeos.cc',
       'wm/cursor_manager_chromeos.h',
       'wm/default_state.cc',
diff --git a/ash/autoclick/autoclick_controller.cc b/ash/autoclick/autoclick_controller.cc
index ed1b580..47846dc 100644
--- a/ash/autoclick/autoclick_controller.cc
+++ b/ash/autoclick/autoclick_controller.cc
@@ -5,7 +5,8 @@
 #include "ash/autoclick/autoclick_controller.h"
 
 #include "ash/shell.h"
-#include "ash/wm/coordinate_conversion.h"
+#include "ash/wm/aura/wm_window_aura.h"
+#include "ash/wm/common/root_window_finder.h"
 #include "base/timer/timer.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window_tree_host.h"
@@ -178,7 +179,8 @@
 void AutoclickControllerImpl::DoAutoclick() {
   gfx::Point screen_location =
       aura::Env::GetInstance()->last_mouse_location();
-  aura::Window* root_window = wm::GetRootWindowAt(screen_location);
+  aura::Window* root_window =
+      wm::WmWindowAura::GetAuraWindow(wm::GetRootWindowAt(screen_location));
   DCHECK(root_window) << "Root window not found while attempting autoclick.";
 
   gfx::Point click_location(screen_location);
diff --git a/ash/display/screen_ash.cc b/ash/display/screen_ash.cc
index d5c33a4e..4b420ba 100644
--- a/ash/display/screen_ash.cc
+++ b/ash/display/screen_ash.cc
@@ -11,7 +11,8 @@
 #include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shelf/shelf_widget.h"
 #include "ash/shell.h"
-#include "ash/wm/coordinate_conversion.h"
+#include "ash/wm/aura/wm_window_aura.h"
+#include "ash/wm/common/root_window_finder.h"
 #include "base/logging.h"
 #include "ui/aura/client/screen_position_client.h"
 #include "ui/aura/env.h"
@@ -104,7 +105,8 @@
 }
 
 gfx::NativeWindow ScreenAsh::GetWindowAtScreenPoint(const gfx::Point& point) {
-  aura::Window* root_window = wm::GetRootWindowAt(point);
+  aura::Window* root_window =
+      wm::WmWindowAura::GetAuraWindow(wm::GetRootWindowAt(point));
   aura::client::ScreenPositionClient* position_client =
       aura::client::GetScreenPositionClient(root_window);
 
diff --git a/ash/display/screen_position_controller.cc b/ash/display/screen_position_controller.cc
index 2c146a8..8467ea87 100644
--- a/ash/display/screen_position_controller.cc
+++ b/ash/display/screen_position_controller.cc
@@ -8,7 +8,6 @@
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/shell_window_ids.h"
-#include "ash/wm/coordinate_conversion.h"
 #include "ash/wm/system_modal_container_layout_manager.h"
 #include "ash/wm/window_properties.h"
 #include "ash/wm/window_state.h"
diff --git a/ash/display/shared_display_edge_indicator.cc b/ash/display/shared_display_edge_indicator.cc
index 0618622..aaec4db 100644
--- a/ash/display/shared_display_edge_indicator.cc
+++ b/ash/display/shared_display_edge_indicator.cc
@@ -6,7 +6,6 @@
 
 #include "ash/shell.h"
 #include "ash/shell_window_ids.h"
-#include "ash/wm/coordinate_conversion.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/aura/client/screen_position_client.h"
 #include "ui/aura/window_event_dispatcher.h"
diff --git a/ash/display/window_tree_host_manager.cc b/ash/display/window_tree_host_manager.cc
index b110eda..97b747b2 100644
--- a/ash/display/window_tree_host_manager.cc
+++ b/ash/display/window_tree_host_manager.cc
@@ -28,7 +28,6 @@
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
 #include "ash/system/tray/system_tray.h"
-#include "ash/wm/coordinate_conversion.h"
 #include "ash/wm/window_util.h"
 #include "base/command_line.h"
 #include "base/stl_util.h"
diff --git a/ash/drag_drop/drag_drop_tracker.cc b/ash/drag_drop/drag_drop_tracker.cc
index e0f8136..9a19070 100644
--- a/ash/drag_drop/drag_drop_tracker.cc
+++ b/ash/drag_drop/drag_drop_tracker.cc
@@ -6,7 +6,8 @@
 
 #include "ash/shell.h"
 #include "ash/shell_window_ids.h"
-#include "ash/wm/coordinate_conversion.h"
+#include "ash/wm/aura/wm_window_aura.h"
+#include "ash/wm/common/root_window_finder.h"
 #include "ui/aura/client/window_tree_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -72,7 +73,7 @@
   gfx::Point location_in_screen = event.location();
   ::wm::ConvertPointToScreen(capture_window_.get(), &location_in_screen);
   aura::Window* root_window_at_point =
-      wm::GetRootWindowAt(location_in_screen);
+      wm::WmWindowAura::GetAuraWindow(wm::GetRootWindowAt(location_in_screen));
   gfx::Point location_in_root = location_in_screen;
   ::wm::ConvertPointFromScreen(root_window_at_point, &location_in_root);
   return root_window_at_point->GetEventHandlerForPoint(location_in_root);
@@ -90,7 +91,7 @@
   gfx::Point target_root_location = event.root_location();
   aura::Window::ConvertPointToTarget(
       capture_window_->GetRootWindow(),
-      ash::wm::GetRootWindowAt(location_in_screen),
+      wm::WmWindowAura::GetAuraWindow(wm::GetRootWindowAt(location_in_screen)),
       &target_root_location);
   return new ui::MouseEvent(
       event.type(), target_location, target_root_location,
diff --git a/ash/drag_drop/drag_drop_tracker.h b/ash/drag_drop/drag_drop_tracker.h
index 703aa6f9..292e4a9 100644
--- a/ash/drag_drop/drag_drop_tracker.h
+++ b/ash/drag_drop/drag_drop_tracker.h
@@ -21,8 +21,7 @@
 // Provides functions for handling drag events inside and outside the root
 // window where drag is started. This internally sets up a capture window for
 // tracking drag events outside the root window where drag is initiated.
-// ash/wm/coordinate_conversion.h is used internally and only X11 environment
-// is supported for now.
+// Only X11 environment is supported for now.
 class ASH_EXPORT DragDropTracker {
  public:
   DragDropTracker(aura::Window* context_root,
diff --git a/ash/extended_desktop_unittest.cc b/ash/extended_desktop_unittest.cc
index e625eda..f1702cd 100644
--- a/ash/extended_desktop_unittest.cc
+++ b/ash/extended_desktop_unittest.cc
@@ -9,7 +9,8 @@
 #include "ash/shell_window_ids.h"
 #include "ash/system/tray/system_tray.h"
 #include "ash/test/ash_test_base.h"
-#include "ash/wm/coordinate_conversion.h"
+#include "ash/wm/aura/wm_window_aura.h"
+#include "ash/wm/common/root_window_finder.h"
 #include "ash/wm/window_properties.h"
 #include "ash/wm/window_util.h"
 #include "base/strings/string_util.h"
@@ -314,17 +315,24 @@
   SetSecondaryDisplayLayout(display::DisplayPlacement::LEFT);
   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
 
-  EXPECT_EQ(root_windows[1], wm::GetRootWindowAt(gfx::Point(-400, 100)));
-  EXPECT_EQ(root_windows[1], wm::GetRootWindowAt(gfx::Point(-1, 100)));
-  EXPECT_EQ(root_windows[0], wm::GetRootWindowAt(gfx::Point(0, 300)));
-  EXPECT_EQ(root_windows[0], wm::GetRootWindowAt(gfx::Point(700, 300)));
+  EXPECT_EQ(root_windows[1], wm::WmWindowAura::GetAuraWindow(
+                                 wm::GetRootWindowAt(gfx::Point(-400, 100))));
+  EXPECT_EQ(root_windows[1], wm::WmWindowAura::GetAuraWindow(
+                                 wm::GetRootWindowAt(gfx::Point(-1, 100))));
+  EXPECT_EQ(root_windows[0], wm::WmWindowAura::GetAuraWindow(
+                                 wm::GetRootWindowAt(gfx::Point(0, 300))));
+  EXPECT_EQ(root_windows[0], wm::WmWindowAura::GetAuraWindow(
+                                 wm::GetRootWindowAt(gfx::Point(700, 300))));
 
   // Zero origin.
-  EXPECT_EQ(root_windows[0], wm::GetRootWindowAt(gfx::Point(0, 0)));
+  EXPECT_EQ(root_windows[0], wm::WmWindowAura::GetAuraWindow(
+                                 wm::GetRootWindowAt(gfx::Point(0, 0))));
 
   // Out of range point should return the nearest root window
-  EXPECT_EQ(root_windows[1], wm::GetRootWindowAt(gfx::Point(-600, 0)));
-  EXPECT_EQ(root_windows[0], wm::GetRootWindowAt(gfx::Point(701, 100)));
+  EXPECT_EQ(root_windows[1], wm::WmWindowAura::GetAuraWindow(
+                                 wm::GetRootWindowAt(gfx::Point(-600, 0))));
+  EXPECT_EQ(root_windows[0], wm::WmWindowAura::GetAuraWindow(
+                                 wm::GetRootWindowAt(gfx::Point(701, 100))));
 }
 
 TEST_F(ExtendedDesktopTest, GetRootWindowMatching) {
@@ -338,33 +346,43 @@
 
   // Containing rect.
   EXPECT_EQ(root_windows[1],
-            wm::GetRootWindowMatching(gfx::Rect(-300, 10, 50, 50)));
+            wm::WmWindowAura::GetAuraWindow(
+                wm::GetRootWindowMatching(gfx::Rect(-300, 10, 50, 50))));
   EXPECT_EQ(root_windows[0],
-            wm::GetRootWindowMatching(gfx::Rect(100, 10, 50, 50)));
+            wm::WmWindowAura::GetAuraWindow(
+                wm::GetRootWindowMatching(gfx::Rect(100, 10, 50, 50))));
 
   // Intersecting rect.
   EXPECT_EQ(root_windows[1],
-            wm::GetRootWindowMatching(gfx::Rect(-200, 0, 300, 300)));
+            wm::WmWindowAura::GetAuraWindow(
+                wm::GetRootWindowMatching(gfx::Rect(-200, 0, 300, 300))));
   EXPECT_EQ(root_windows[0],
-            wm::GetRootWindowMatching(gfx::Rect(-100, 0, 300, 300)));
+            wm::WmWindowAura::GetAuraWindow(
+                wm::GetRootWindowMatching(gfx::Rect(-100, 0, 300, 300))));
 
   // Zero origin.
   EXPECT_EQ(root_windows[0],
-            wm::GetRootWindowMatching(gfx::Rect(0, 0, 0, 0)));
+            wm::WmWindowAura::GetAuraWindow(
+                wm::GetRootWindowMatching(gfx::Rect(0, 0, 0, 0))));
   EXPECT_EQ(root_windows[0],
-            wm::GetRootWindowMatching(gfx::Rect(0, 0, 1, 1)));
+            wm::WmWindowAura::GetAuraWindow(
+                wm::GetRootWindowMatching(gfx::Rect(0, 0, 1, 1))));
 
   // Empty rect.
   EXPECT_EQ(root_windows[1],
-            wm::GetRootWindowMatching(gfx::Rect(-400, 100, 0, 0)));
+            wm::WmWindowAura::GetAuraWindow(
+                wm::GetRootWindowMatching(gfx::Rect(-400, 100, 0, 0))));
   EXPECT_EQ(root_windows[0],
-            wm::GetRootWindowMatching(gfx::Rect(100, 100, 0, 0)));
+            wm::WmWindowAura::GetAuraWindow(
+                wm::GetRootWindowMatching(gfx::Rect(100, 100, 0, 0))));
 
   // Out of range rect should return the primary root window.
   EXPECT_EQ(root_windows[0],
-            wm::GetRootWindowMatching(gfx::Rect(-600, -300, 50, 50)));
+            wm::WmWindowAura::GetAuraWindow(
+                wm::GetRootWindowMatching(gfx::Rect(-600, -300, 50, 50))));
   EXPECT_EQ(root_windows[0],
-            wm::GetRootWindowMatching(gfx::Rect(0, 1000, 50, 50)));
+            wm::WmWindowAura::GetAuraWindow(
+                wm::GetRootWindowMatching(gfx::Rect(0, 1000, 50, 50))));
 }
 
 TEST_F(ExtendedDesktopTest, Capture) {
diff --git a/ash/screen_util.cc b/ash/screen_util.cc
index 7e4017e..931043e 100644
--- a/ash/screen_util.cc
+++ b/ash/screen_util.cc
@@ -9,7 +9,6 @@
 #include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shelf/shelf_widget.h"
 #include "ash/shell.h"
-#include "ash/wm/coordinate_conversion.h"
 #include "base/logging.h"
 #include "ui/aura/client/screen_position_client.h"
 #include "ui/aura/window_event_dispatcher.h"
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index 8313d15..26e685c45 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -27,7 +27,8 @@
 #include "ash/shelf/shelf_widget.h"
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
-#include "ash/wm/coordinate_conversion.h"
+#include "ash/wm/aura/wm_window_aura.h"
+#include "ash/wm/common/root_window_finder.h"
 #include "base/auto_reset.h"
 #include "base/metrics/histogram.h"
 #include "grit/ash_strings.h"
@@ -651,7 +652,9 @@
   views::View::ConvertPointFromScreen(drag_and_drop_view, &pt);
   gfx::Point point_in_root = location_in_screen_coordinates;
   ::wm::ConvertPointFromScreen(
-      ash::wm::GetRootWindowAt(location_in_screen_coordinates), &point_in_root);
+      wm::WmWindowAura::GetAuraWindow(
+          ash::wm::GetRootWindowAt(location_in_screen_coordinates)),
+      &point_in_root);
   ui::MouseEvent event(ui::ET_MOUSE_PRESSED, pt, point_in_root,
                        ui::EventTimeForNow(), 0, 0);
   PointerPressedOnButton(drag_and_drop_view, DRAG_AND_DROP, event);
@@ -672,7 +675,9 @@
   ConvertPointFromScreen(drag_and_drop_view, &pt);
   gfx::Point point_in_root = location_in_screen_coordinates;
   ::wm::ConvertPointFromScreen(
-      ash::wm::GetRootWindowAt(location_in_screen_coordinates), &point_in_root);
+      wm::WmWindowAura::GetAuraWindow(
+          ash::wm::GetRootWindowAt(location_in_screen_coordinates)),
+      &point_in_root);
   ui::MouseEvent event(ui::ET_MOUSE_DRAGGED, pt, point_in_root,
                        ui::EventTimeForNow(), 0, 0);
   PointerDraggedOnButton(drag_and_drop_view, DRAG_AND_DROP, event);
diff --git a/ash/shell.cc b/ash/shell.cc
index d559221..a24d502 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -60,7 +60,7 @@
 #include "ash/wm/ash_focus_rules.h"
 #include "ash/wm/ash_native_cursor_manager.h"
 #include "ash/wm/aura/wm_globals_aura.h"
-#include "ash/wm/coordinate_conversion.h"
+#include "ash/wm/common/root_window_finder.h"
 #include "ash/wm/event_client_impl.h"
 #include "ash/wm/lock_state_controller.h"
 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
@@ -299,8 +299,8 @@
   if (session_state_delegate_->IsScreenLocked())
     return;
 
-  aura::Window* root =
-      wm::GetRootWindowMatching(gfx::Rect(location_in_screen, gfx::Size()));
+  aura::Window* root = wm::WmWindowAura::GetAuraWindow(
+      wm::GetRootWindowMatching(gfx::Rect(location_in_screen, gfx::Size())));
   GetRootWindowController(root)
       ->ShowContextMenu(location_in_screen, source_type);
 }
diff --git a/ash/test/ui_controls_factory_ash.cc b/ash/test/ui_controls_factory_ash.cc
index 2ac98c8..af690d0 100644
--- a/ash/test/ui_controls_factory_ash.cc
+++ b/ash/test/ui_controls_factory_ash.cc
@@ -4,7 +4,8 @@
 
 #include "ash/shell.h"
 #include "ash/shell_factory.h"
-#include "ash/wm/coordinate_conversion.h"
+#include "ash/wm/aura/wm_window_aura.h"
+#include "ash/wm/common/root_window_finder.h"
 #include "ash/wm/window_properties.h"
 #include "ui/aura/client/capture_client.h"
 #include "ui/aura/client/screen_position_client.h"
@@ -45,7 +46,8 @@
 // Returns the UIControls object for the RootWindow at |point_in_screen|.
 UIControlsAura* GetUIControlsAt(const gfx::Point& point_in_screen) {
   // TODO(mazda): Support the case passive grab is taken.
-  return GetUIControlsForRootWindow(ash::wm::GetRootWindowAt(point_in_screen));
+  return GetUIControlsForRootWindow(wm::WmWindowAura::GetAuraWindow(
+      ash::wm::GetRootWindowAt(point_in_screen)));
 }
 
 }  // namespace
diff --git a/ash/wm/aura/wm_globals_aura.cc b/ash/wm/aura/wm_globals_aura.cc
index f308d936..0895ce17 100644
--- a/ash/wm/aura/wm_globals_aura.cc
+++ b/ash/wm/aura/wm_globals_aura.cc
@@ -70,6 +70,14 @@
   return Shell::GetInstance()->delegate()->IsForceMaximizeOnFirstRun();
 }
 
+void WmGlobalsAura::LockCursor() {
+  ash::Shell::GetInstance()->cursor_manager()->LockCursor();
+}
+
+void WmGlobalsAura::UnlockCursor() {
+  ash::Shell::GetInstance()->cursor_manager()->UnlockCursor();
+}
+
 std::vector<WmWindow*> WmGlobalsAura::GetAllRootWindows() {
   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
   std::vector<WmWindow*> wm_windows(root_windows.size());
diff --git a/ash/wm/aura/wm_globals_aura.h b/ash/wm/aura/wm_globals_aura.h
index d2195df..37872ef 100644
--- a/ash/wm/aura/wm_globals_aura.h
+++ b/ash/wm/aura/wm_globals_aura.h
@@ -27,6 +27,8 @@
   WmWindow* GetRootWindowForNewWindows() override;
   std::vector<WmWindow*> GetMruWindowListIgnoreModals() override;
   bool IsForceMaximizeOnFirstRun() override;
+  void LockCursor() override;
+  void UnlockCursor() override;
   std::vector<WmWindow*> GetAllRootWindows() override;
 
  private:
diff --git a/ash/wm/aura/wm_root_window_controller_aura.cc b/ash/wm/aura/wm_root_window_controller_aura.cc
index 8129875..ad249fe 100644
--- a/ash/wm/aura/wm_root_window_controller_aura.cc
+++ b/ash/wm/aura/wm_root_window_controller_aura.cc
@@ -4,8 +4,11 @@
 
 #include "ash/wm/aura/wm_root_window_controller_aura.h"
 
+#include "ash/display/window_tree_host_manager.h"
 #include "ash/root_window_controller.h"
+#include "ash/shell.h"
 #include "ash/wm/aura/wm_globals_aura.h"
+#include "ash/wm/aura/wm_window_aura.h"
 #include "ash/wm/workspace_controller.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_property.h"
@@ -20,6 +23,13 @@
                                  kWmRootWindowControllerKey,
                                  nullptr);
 
+// static
+WmRootWindowController* WmRootWindowController::GetWithDisplayId(int64_t id) {
+  return WmRootWindowControllerAura::Get(Shell::GetInstance()
+                                             ->window_tree_host_manager()
+                                             ->GetRootWindowForDisplayId(id));
+}
+
 WmRootWindowControllerAura::WmRootWindowControllerAura(
     RootWindowController* root_window_controller)
     : root_window_controller_(root_window_controller) {
@@ -62,5 +72,9 @@
   return root_window_controller_->workspace_controller()->GetWindowState();
 }
 
+WmWindow* WmRootWindowControllerAura::GetWindow() {
+  return WmWindowAura::Get(root_window_controller_->GetRootWindow());
+}
+
 }  // namespace wm
 }  // namespace ash
diff --git a/ash/wm/aura/wm_root_window_controller_aura.h b/ash/wm/aura/wm_root_window_controller_aura.h
index 1b22850..cde5d7e 100644
--- a/ash/wm/aura/wm_root_window_controller_aura.h
+++ b/ash/wm/aura/wm_root_window_controller_aura.h
@@ -35,6 +35,7 @@
   bool HasShelf() override;
   WmGlobals* GetGlobals() override;
   WorkspaceWindowState GetWorkspaceWindowState() override;
+  WmWindow* GetWindow() override;
 
  private:
   RootWindowController* root_window_controller_;
diff --git a/ash/wm/common/root_window_finder.cc b/ash/wm/common/root_window_finder.cc
new file mode 100644
index 0000000..69b2f99d
--- /dev/null
+++ b/ash/wm/common/root_window_finder.cc
@@ -0,0 +1,36 @@
+// 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 "ash/wm/common/root_window_finder.h"
+
+#include "ash/display/window_tree_host_manager.h"
+#include "ash/wm/common/wm_root_window_controller.h"
+#include "ash/wm/common/wm_window.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/screen.h"
+
+namespace ash {
+namespace wm {
+
+WmWindow* GetRootWindowAt(const gfx::Point& point) {
+  const gfx::Display& display =
+      gfx::Screen::GetScreen()->GetDisplayNearestPoint(point);
+  DCHECK(display.is_valid());
+  WmRootWindowController* root_window_controller =
+      WmRootWindowController::GetWithDisplayId(display.id());
+  return root_window_controller ? root_window_controller->GetWindow() : nullptr;
+}
+
+WmWindow* GetRootWindowMatching(const gfx::Rect& rect) {
+  const gfx::Display& display =
+      gfx::Screen::GetScreen()->GetDisplayMatching(rect);
+  WmRootWindowController* root_window_controller =
+      WmRootWindowController::GetWithDisplayId(display.id());
+  return root_window_controller ? root_window_controller->GetWindow() : nullptr;
+}
+
+}  // namespace wm
+}  // namespace ash
diff --git a/ash/wm/coordinate_conversion.h b/ash/wm/common/root_window_finder.h
similarity index 64%
rename from ash/wm/coordinate_conversion.h
rename to ash/wm/common/root_window_finder.h
index aa4a8485..f35459a6 100644
--- a/ash/wm/coordinate_conversion.h
+++ b/ash/wm/common/root_window_finder.h
@@ -2,15 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_WM_COORDINATE_CONVERSION_H_
-#define ASH_WM_COORDINATE_CONVERSION_H_
+#ifndef ASH_WM_COMMON_ROOT_WINDOW_FINDER_H_
+#define ASH_WM_COMMON_ROOT_WINDOW_FINDER_H_
 
 #include "ash/ash_export.h"
 
-namespace aura {
-class Window;
-}  // namespace gfx
-
 namespace gfx {
 class Point;
 class Rect;
@@ -19,16 +15,18 @@
 namespace ash {
 namespace wm {
 
+class WmWindow;
+
 // Returns the RootWindow at |point| in the virtual screen coordinates.
 // Returns NULL if the root window does not exist at the given
 // point.
-ASH_EXPORT aura::Window* GetRootWindowAt(const gfx::Point& point);
+ASH_EXPORT WmWindow* GetRootWindowAt(const gfx::Point& point);
 
 // Returns the RootWindow that shares the most area with |rect| in
 // the virtual scren coordinates.
-ASH_EXPORT aura::Window* GetRootWindowMatching(const gfx::Rect& rect);
+ASH_EXPORT WmWindow* GetRootWindowMatching(const gfx::Rect& rect);
 
 }  // namespace wm
 }  // namespace ash
 
-#endif  // ASH_WM_COORDINATE_CONVERSION_H_
+#endif  // ASH_WM_COMMON_ROOT_WINDOW_FINDER_H_
diff --git a/ash/wm/common/wm_globals.h b/ash/wm/common/wm_globals.h
index 9343281d..28823ef7 100644
--- a/ash/wm/common/wm_globals.h
+++ b/ash/wm/common/wm_globals.h
@@ -47,6 +47,10 @@
   // the window size.
   virtual bool IsForceMaximizeOnFirstRun() = 0;
 
+  // See aura::client::CursorClient for details on these.
+  virtual void LockCursor() = 0;
+  virtual void UnlockCursor() = 0;
+
   virtual std::vector<WmWindow*> GetAllRootWindows() = 0;
 };
 
diff --git a/ash/wm/common/wm_root_window_controller.h b/ash/wm/common/wm_root_window_controller.h
index a2b06dd..e247c0888 100644
--- a/ash/wm/common/wm_root_window_controller.h
+++ b/ash/wm/common/wm_root_window_controller.h
@@ -5,6 +5,8 @@
 #ifndef ASH_WM_COMMON_WM_ROOT_CONTROLLER_H_
 #define ASH_WM_COMMON_WM_ROOT_CONTROLLER_H_
 
+#include <stdint.h>
+
 #include "ash/ash_export.h"
 #include "ash/wm/common/workspace/workspace_types.h"
 
@@ -14,15 +16,21 @@
 class WmGlobals;
 class WmWindow;
 
+// Provides state associated with a root of a window hierarchy.
 class ASH_EXPORT WmRootWindowController {
  public:
   virtual ~WmRootWindowController() {}
 
+  static WmRootWindowController* GetWithDisplayId(int64_t id);
+
   virtual bool HasShelf() = 0;
 
   virtual WmGlobals* GetGlobals() = 0;
 
   virtual WorkspaceWindowState GetWorkspaceWindowState() = 0;
+
+  // Returns the window associated with this WmRootWindowController.
+  virtual WmWindow* GetWindow() = 0;
 };
 
 }  // namespace wm
diff --git a/ash/wm/coordinate_conversion.cc b/ash/wm/coordinate_conversion.cc
deleted file mode 100644
index e591f3f..0000000
--- a/ash/wm/coordinate_conversion.cc
+++ /dev/null
@@ -1,38 +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 "ash/wm/coordinate_conversion.h"
-
-#include "ash/display/window_tree_host_manager.h"
-#include "ash/shell.h"
-#include "ui/aura/client/screen_position_client.h"
-#include "ui/gfx/display.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/screen.h"
-
-namespace ash {
-namespace wm {
-
-aura::Window* GetRootWindowAt(const gfx::Point& point) {
-  const gfx::Display& display =
-      gfx::Screen::GetScreen()->GetDisplayNearestPoint(point);
-  DCHECK(display.is_valid());
-  // TODO(yusukes): Move coordinate_conversion.cc and .h to ui/aura/ once
-  // GetRootWindowForDisplayId() is moved to aura::Env.
-  return Shell::GetInstance()
-      ->window_tree_host_manager()
-      ->GetRootWindowForDisplayId(display.id());
-}
-
-aura::Window* GetRootWindowMatching(const gfx::Rect& rect) {
-  const gfx::Display& display =
-      gfx::Screen::GetScreen()->GetDisplayMatching(rect);
-  return Shell::GetInstance()
-      ->window_tree_host_manager()
-      ->GetRootWindowForDisplayId(display.id());
-}
-
-}  // namespace wm
-}  // namespace ash
diff --git a/ash/wm/default_window_resizer.cc b/ash/wm/default_window_resizer.cc
index ac0042d..cf415952 100644
--- a/ash/wm/default_window_resizer.cc
+++ b/ash/wm/default_window_resizer.cc
@@ -4,20 +4,14 @@
 
 #include "ash/wm/default_window_resizer.h"
 
-#include "ash/shell.h"
+#include "ash/wm/common/wm_globals.h"
+#include "ash/wm/common/wm_window.h"
 #include "ash/wm/window_state.h"
-#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/env.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_delegate.h"
-#include "ui/base/hit_test.h"
-#include "ui/base/ui_base_types.h"
-#include "ui/gfx/screen.h"
 
 namespace ash {
 
 DefaultWindowResizer::~DefaultWindowResizer() {
-  ash::Shell::GetInstance()->cursor_manager()->UnlockCursor();
+  globals_->UnlockCursor();
 }
 
 // static
@@ -28,7 +22,7 @@
 
 void DefaultWindowResizer::Drag(const gfx::Point& location, int event_flags) {
   gfx::Rect bounds(CalculateBoundsForDrag(location));
-  if (bounds != GetTarget()->bounds()) {
+  if (bounds != GetTarget()->GetBounds()) {
     if (!did_move_or_resize_ && !details().restore_bounds.IsEmpty())
       window_state_->ClearRestoreBounds();
     did_move_or_resize_ = true;
@@ -51,9 +45,10 @@
 
 DefaultWindowResizer::DefaultWindowResizer(wm::WindowState* window_state)
     : WindowResizer(window_state),
-      did_move_or_resize_(false) {
+      did_move_or_resize_(false),
+      globals_(GetTarget()->GetGlobals()) {
   DCHECK(details().is_resizable);
-  ash::Shell::GetInstance()->cursor_manager()->LockCursor();
+  globals_->LockCursor();
 }
 
 }  // namespace aura
diff --git a/ash/wm/default_window_resizer.h b/ash/wm/default_window_resizer.h
index fbf75ec..737d705 100644
--- a/ash/wm/default_window_resizer.h
+++ b/ash/wm/default_window_resizer.h
@@ -10,6 +10,9 @@
 #include "base/macros.h"
 
 namespace ash {
+namespace wm {
+class WmGlobals;
+}
 
 // WindowResizer is used by ToplevelWindowEventFilter to handle dragging, moving
 // or resizing a window. All coordinates passed to this are in the parent
@@ -40,6 +43,8 @@
   // Set to true once Drag() is invoked and the bounds of the window change.
   bool did_move_or_resize_;
 
+  wm::WmGlobals* globals_;
+
   DISALLOW_COPY_AND_ASSIGN(DefaultWindowResizer);
 };
 
diff --git a/ash/wm/dock/docked_window_layout_manager.cc b/ash/wm/dock/docked_window_layout_manager.cc
index 6d318ae..51c84ae6 100644
--- a/ash/wm/dock/docked_window_layout_manager.cc
+++ b/ash/wm/dock/docked_window_layout_manager.cc
@@ -15,7 +15,6 @@
 #include "ash/shell_window_ids.h"
 #include "ash/wm/common/window_animation_types.h"
 #include "ash/wm/common/window_parenting_utils.h"
-#include "ash/wm/coordinate_conversion.h"
 #include "ash/wm/window_animations.h"
 #include "ash/wm/window_properties.h"
 #include "ash/wm/window_resizer.h"
diff --git a/ash/wm/dock/docked_window_layout_manager_unittest.cc b/ash/wm/dock/docked_window_layout_manager_unittest.cc
index 6b108e4..5786919 100644
--- a/ash/wm/dock/docked_window_layout_manager_unittest.cc
+++ b/ash/wm/dock/docked_window_layout_manager_unittest.cc
@@ -19,7 +19,6 @@
 #include "ash/test/shelf_view_test_api.h"
 #include "ash/test/shell_test_api.h"
 #include "ash/test/test_shelf_delegate.h"
-#include "ash/wm/coordinate_conversion.h"
 #include "ash/wm/panels/panel_layout_manager.h"
 #include "ash/wm/window_resizer.h"
 #include "ash/wm/window_state.h"
diff --git a/ash/wm/dock/docked_window_resizer.cc b/ash/wm/dock/docked_window_resizer.cc
index 974d448..63ba9af 100644
--- a/ash/wm/dock/docked_window_resizer.cc
+++ b/ash/wm/dock/docked_window_resizer.cc
@@ -66,7 +66,7 @@
 
 void DockedWindowResizer::Drag(const gfx::Point& location, int event_flags) {
   last_location_ = location;
-  ::wm::ConvertPointToScreen(GetTarget()->parent(), &last_location_);
+  ::wm::ConvertPointToScreen(GetAuraTarget()->parent(), &last_location_);
   base::WeakPtr<DockedWindowResizer> resizer(weak_ptr_factory_.GetWeakPtr());
 
   if (!did_move_or_resize_) {
@@ -107,7 +107,7 @@
     // The window's initial layout manager already knows that the drag is
     // in progress for this window.
     if (new_dock_layout != initial_dock_layout_)
-      new_dock_layout->StartDragging(GetTarget());
+      new_dock_layout->StartDragging(GetAuraTarget());
   }
   // Window could get docked by the WorkspaceWindowResizer, update the state.
   is_docked_ = dock_layout_->is_dragged_window_docked();
@@ -129,7 +129,7 @@
   if (is_docked_ != was_docked_) {
     is_docked_ = was_docked_;
     if (is_docked_)
-      dock_layout_->DockDraggedWindow(GetTarget());
+      dock_layout_->DockDraggedWindow(GetAuraTarget());
     else
       dock_layout_->UndockDraggedWindow();
   }
@@ -149,12 +149,11 @@
       weak_ptr_factory_(this) {
   DCHECK(details().is_resizable);
   aura::Window* dock_container = Shell::GetContainer(
-      GetTarget()->GetRootWindow(),
-      kShellWindowId_DockedContainer);
+      GetAuraTarget()->GetRootWindow(), kShellWindowId_DockedContainer);
   dock_layout_ = static_cast<DockedWindowLayoutManager*>(
       dock_container->layout_manager());
   initial_dock_layout_ = dock_layout_;
-  was_docked_ = GetTarget()->parent() == dock_container;
+  was_docked_ = GetAuraTarget()->parent() == dock_container;
   is_docked_ = was_docked_;
 }
 
@@ -165,7 +164,7 @@
     return;
   DockedAlignment dock_alignment = dock_layout_->CalculateAlignment();
   gfx::Rect dock_bounds = ScreenUtil::ConvertRectFromScreen(
-      GetTarget()->parent(),
+      GetAuraTarget()->parent(),
       dock_layout_->dock_container()->GetBoundsInScreen());
 
   // Short-range magnetism when retaining docked state. Same constant as in
@@ -199,28 +198,27 @@
   // Tell the dock layout manager that we are dragging this window.
   // At this point we are not yet animating the window as it may not be
   // inside the docked area.
-  dock_layout_->StartDragging(GetTarget());
+  dock_layout_->StartDragging(GetAuraTarget());
   if (!resizer)
     return;
   // Reparent workspace windows during the drag to elevate them above workspace.
   // Other windows for which the DockedWindowResizer is instantiated include
   // panels and windows that are already docked. Those do not need reparenting.
-  if (GetTarget()->type() != ui::wm::WINDOW_TYPE_PANEL &&
-      GetTarget()->parent()->id() == kShellWindowId_DefaultContainer) {
+  if (GetAuraTarget()->type() != ui::wm::WINDOW_TYPE_PANEL &&
+      GetAuraTarget()->parent()->id() == kShellWindowId_DefaultContainer) {
     // Reparent the window into the docked windows container in order to get it
     // on top of other docked windows.
     aura::Window* docked_container = Shell::GetContainer(
-        GetTarget()->GetRootWindow(),
-        kShellWindowId_DockedContainer);
+        GetAuraTarget()->GetRootWindow(), kShellWindowId_DockedContainer);
     ReparentChildWithTransientChildren(
-        ash::wm::WmWindowAura::Get(GetTarget()),
-        ash::wm::WmWindowAura::Get(GetTarget()->parent()),
+        ash::wm::WmWindowAura::Get(GetAuraTarget()),
+        ash::wm::WmWindowAura::Get(GetAuraTarget()->parent()),
         ash::wm::WmWindowAura::Get(docked_container));
     if (!resizer)
       return;
   }
   if (is_docked_)
-    dock_layout_->DockDraggedWindow(GetTarget());
+    dock_layout_->DockDraggedWindow(GetAuraTarget());
 }
 
 void DockedWindowResizer::FinishedDragging(
@@ -228,7 +226,7 @@
   if (!did_move_or_resize_)
     return;
   did_move_or_resize_ = false;
-  aura::Window* window = GetTarget();
+  aura::Window* window = GetAuraTarget();
   const bool is_attached_panel = window->type() == ui::wm::WINDOW_TYPE_PANEL &&
                                  window_state_->panel_attached();
   const bool is_resized =
@@ -279,7 +277,7 @@
 
 DockedAction DockedWindowResizer::MaybeReparentWindowOnDragCompletion(
     bool is_resized, bool is_attached_panel) {
-  aura::Window* window = GetTarget();
+  aura::Window* window = GetAuraTarget();
 
   // Check if the window needs to be docked or returned to workspace.
   DockedAction action = DOCKED_ACTION_NONE;
diff --git a/ash/wm/drag_window_resizer.cc b/ash/wm/drag_window_resizer.cc
index e882cb8..6cb43311b 100644
--- a/ash/wm/drag_window_resizer.cc
+++ b/ash/wm/drag_window_resizer.cc
@@ -8,7 +8,6 @@
 #include "ash/screen_util.h"
 #include "ash/shell.h"
 #include "ash/wm/common/window_positioning_utils.h"
-#include "ash/wm/coordinate_conversion.h"
 #include "ash/wm/drag_window_controller.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
@@ -57,8 +56,8 @@
   // Show a phantom window for dragging in another root window.
   if (gfx::Screen::GetScreen()->GetNumDisplays() > 1) {
     gfx::Point location_in_screen = location;
-    ::wm::ConvertPointToScreen(GetTarget()->parent(), &location_in_screen);
-    UpdateDragWindow(GetTarget()->bounds(), location_in_screen);
+    ::wm::ConvertPointToScreen(GetAuraTarget()->parent(), &location_in_screen);
+    UpdateDragWindow(GetAuraTarget()->bounds(), location_in_screen);
   } else {
     drag_window_controller_.reset();
   }
@@ -67,23 +66,23 @@
 void DragWindowResizer::CompleteDrag() {
   next_window_resizer_->CompleteDrag();
 
-  GetTarget()->layer()->SetOpacity(details().initial_opacity);
+  GetAuraTarget()->layer()->SetOpacity(details().initial_opacity);
   drag_window_controller_.reset();
 
   // Check if the destination is another display.
   gfx::Point last_mouse_location_in_screen = last_mouse_location_;
-  ::wm::ConvertPointToScreen(GetTarget()->parent(),
+  ::wm::ConvertPointToScreen(GetAuraTarget()->parent(),
                              &last_mouse_location_in_screen);
   gfx::Screen* screen = gfx::Screen::GetScreen();
   const gfx::Display dst_display =
       screen->GetDisplayNearestPoint(last_mouse_location_in_screen);
 
   if (dst_display.id() !=
-      screen->GetDisplayNearestWindow(GetTarget()->GetRootWindow()).id()) {
+      screen->GetDisplayNearestWindow(GetAuraTarget()->GetRootWindow()).id()) {
     // Adjust the size and position so that it doesn't exceed the size of
     // work area.
     const gfx::Size& size = dst_display.work_area().size();
-    gfx::Rect bounds = GetTarget()->bounds();
+    gfx::Rect bounds = GetAuraTarget()->bounds();
     if (bounds.width() > size.width()) {
       int diff = bounds.width() - size.width();
       bounds.set_x(bounds.x() + diff / 2);
@@ -93,7 +92,7 @@
       bounds.set_height(size.height());
 
     gfx::Rect dst_bounds =
-        ScreenUtil::ConvertRectToScreen(GetTarget()->parent(), bounds);
+        ScreenUtil::ConvertRectToScreen(GetAuraTarget()->parent(), bounds);
 
     // Adjust the position so that the cursor is on the window.
     if (!dst_bounds.Contains(last_mouse_location_in_screen)) {
@@ -106,7 +105,7 @@
     ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility(
         dst_display.bounds(), &dst_bounds);
 
-    GetTarget()->SetBoundsInScreen(dst_bounds, dst_display);
+    GetAuraTarget()->SetBoundsInScreen(dst_bounds, dst_display);
   }
 }
 
@@ -114,7 +113,7 @@
   next_window_resizer_->RevertDrag();
 
   drag_window_controller_.reset();
-  GetTarget()->layer()->SetOpacity(details().initial_opacity);
+  GetAuraTarget()->layer()->SetOpacity(details().initial_opacity);
 }
 
 DragWindowResizer::DragWindowResizer(WindowResizer* next_window_resizer,
@@ -131,7 +130,8 @@
       Shell::GetInstance()->mouse_cursor_filter();
   mouse_cursor_filter->set_mouse_warp_enabled(ShouldAllowMouseWarp());
   if (ShouldAllowMouseWarp())
-    mouse_cursor_filter->ShowSharedEdgeIndicator(GetTarget()->GetRootWindow());
+    mouse_cursor_filter->ShowSharedEdgeIndicator(
+        GetAuraTarget()->GetRootWindow());
   instance_ = this;
 }
 
@@ -142,13 +142,13 @@
     return;
 
   if (!drag_window_controller_)
-    drag_window_controller_.reset(new DragWindowController(GetTarget()));
+    drag_window_controller_.reset(new DragWindowController(GetAuraTarget()));
 
-  const gfx::Rect bounds_in_screen =
-      ScreenUtil::ConvertRectToScreen(GetTarget()->parent(), bounds_in_parent);
+  const gfx::Rect bounds_in_screen = ScreenUtil::ConvertRectToScreen(
+      GetAuraTarget()->parent(), bounds_in_parent);
 
   gfx::Rect root_bounds_in_screen =
-      GetTarget()->GetRootWindow()->GetBoundsInScreen();
+      GetAuraTarget()->GetRootWindow()->GetBoundsInScreen();
   float opacity = 1.0f;
   if (!root_bounds_in_screen.Contains(drag_location_in_screen)) {
     gfx::Rect visible_bounds = root_bounds_in_screen;
@@ -156,14 +156,14 @@
     opacity = DragWindowController::GetDragWindowOpacity(bounds_in_screen,
                                                          visible_bounds);
   }
-  GetTarget()->layer()->SetOpacity(opacity);
+  GetAuraTarget()->layer()->SetOpacity(opacity);
   drag_window_controller_->Update(bounds_in_screen, drag_location_in_screen);
 }
 
 bool DragWindowResizer::ShouldAllowMouseWarp() {
   return details().window_component == HTCAPTION &&
-         !::wm::GetTransientParent(GetTarget()) &&
-         wm::IsWindowUserPositionable(GetTarget());
+         !::wm::GetTransientParent(GetAuraTarget()) &&
+         wm::IsWindowUserPositionable(GetAuraTarget());
 }
 
 }  // namespace ash
diff --git a/ash/wm/maximize_mode/maximize_mode_window_state.cc b/ash/wm/maximize_mode/maximize_mode_window_state.cc
index 34a962d0..5eb05d5 100644
--- a/ash/wm/maximize_mode/maximize_mode_window_state.cc
+++ b/ash/wm/maximize_mode/maximize_mode_window_state.cc
@@ -12,7 +12,6 @@
 #include "ash/wm/common/window_animation_types.h"
 #include "ash/wm/common/window_state_util.h"
 #include "ash/wm/common/wm_event.h"
-#include "ash/wm/coordinate_conversion.h"
 #include "ash/wm/maximize_mode/maximize_mode_window_manager.h"
 #include "ash/wm/window_animations.h"
 #include "ash/wm/window_properties.h"
diff --git a/ash/wm/panels/panel_window_resizer.cc b/ash/wm/panels/panel_window_resizer.cc
index 987c0c7..6a86d63 100644
--- a/ash/wm/panels/panel_window_resizer.cc
+++ b/ash/wm/panels/panel_window_resizer.cc
@@ -52,7 +52,7 @@
 
 void PanelWindowResizer::Drag(const gfx::Point& location, int event_flags) {
   last_location_ = location;
-  ::wm::ConvertPointToScreen(GetTarget()->parent(), &last_location_);
+  ::wm::ConvertPointToScreen(GetAuraTarget()->parent(), &last_location_);
   if (!did_move_or_resize_) {
     did_move_or_resize_ = true;
     StartedDragging();
@@ -69,7 +69,7 @@
     // when the panel is reparented, otherwise let the previous container know
     // the drag is complete. If we told the panel's parent that the drag was
     // complete it would begin positioning the panel.
-    if (GetTarget()->parent() != panel_container_)
+    if (GetAuraTarget()->parent() != panel_container_)
       GetPanelLayoutManager(panel_container_)->FinishDragging();
     aura::Window* dst_root = Shell::GetInstance()
                                  ->window_tree_host_manager()
@@ -79,8 +79,8 @@
 
     // The panel's parent already knows that the drag is in progress for this
     // panel.
-    if (panel_container_ && GetTarget()->parent() != panel_container_)
-      GetPanelLayoutManager(panel_container_)->StartDragging(GetTarget());
+    if (panel_container_ && GetAuraTarget()->parent() != panel_container_)
+      GetPanelLayoutManager(panel_container_)->StartDragging(GetAuraTarget());
   }
   gfx::Point offset;
   gfx::Rect bounds(CalculateBoundsForDrag(location));
@@ -124,7 +124,7 @@
       was_attached_(window_state->panel_attached()),
       weak_ptr_factory_(this) {
   DCHECK(details().is_resizable);
-  panel_container_ = Shell::GetContainer(GetTarget()->GetRootWindow(),
+  panel_container_ = Shell::GetContainer(GetAuraTarget()->GetRootWindow(),
                                          kShellWindowId_PanelContainer);
   initial_panel_container_ = panel_container_;
 }
@@ -136,9 +136,9 @@
     PanelLayoutManager* panel_layout_manager =
         GetPanelLayoutManager(panel_container_);
     gfx::Rect launcher_bounds = ScreenUtil::ConvertRectFromScreen(
-        GetTarget()->parent(),
-        panel_layout_manager->shelf()->
-        shelf_widget()->GetWindowBoundsInScreen());
+        GetAuraTarget()->parent(), panel_layout_manager->shelf()
+                                       ->shelf_widget()
+                                       ->GetWindowBoundsInScreen());
     switch (panel_layout_manager->shelf()->alignment()) {
       case SHELF_ALIGNMENT_BOTTOM:
       case SHELF_ALIGNMENT_BOTTOM_LOCKED:
@@ -171,13 +171,13 @@
   // Tell the panel layout manager that we are dragging this panel before
   // attaching it so that it does not get repositioned.
   if (panel_container_)
-    GetPanelLayoutManager(panel_container_)->StartDragging(GetTarget());
+    GetPanelLayoutManager(panel_container_)->StartDragging(GetAuraTarget());
   if (!was_attached_) {
     // Attach the panel while dragging placing it in front of other panels.
     window_state_->set_panel_attached(true);
     // We use root window coordinates to ensure that during the drag the panel
     // is reparented to a container in the root window that has that window.
-    aura::Window* target = GetTarget();
+    aura::Window* target = GetAuraTarget();
     aura::Window* target_root = target->GetRootWindow();
     aura::Window* old_parent = target->parent();
     aura::client::ParentWindowWithContext(
@@ -196,7 +196,7 @@
     window_state_->set_panel_attached(details().should_attach_to_shelf);
     // We use last known location to ensure that after the drag the panel
     // is reparented to a container in the root window that has that location.
-    aura::Window* target = GetTarget();
+    aura::Window* target = GetAuraTarget();
     aura::Window* target_root = target->GetRootWindow();
     aura::Window* old_parent = target->parent();
     aura::client::ParentWindowWithContext(
@@ -218,8 +218,9 @@
 
 void PanelWindowResizer::UpdateLauncherPosition() {
   if (panel_container_) {
-    GetPanelLayoutManager(panel_container_)->shelf()->
-        UpdateIconPositionForWindow(GetTarget());
+    GetPanelLayoutManager(panel_container_)
+        ->shelf()
+        ->UpdateIconPositionForWindow(GetAuraTarget());
   }
 }
 
diff --git a/ash/wm/stacking_controller.cc b/ash/wm/stacking_controller.cc
index 21b6310..e562694 100644
--- a/ash/wm/stacking_controller.cc
+++ b/ash/wm/stacking_controller.cc
@@ -9,7 +9,8 @@
 #include "ash/shell.h"
 #include "ash/shell_window_ids.h"
 #include "ash/wm/always_on_top_controller.h"
-#include "ash/wm/coordinate_conversion.h"
+#include "ash/wm/aura/wm_window_aura.h"
+#include "ash/wm/common/root_window_finder.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_state_aura.h"
 #include "ui/aura/client/aura_constants.h"
@@ -28,7 +29,7 @@
 aura::Window* FindContainerRoot(const gfx::Rect& bounds) {
   if (bounds.x() == 0 && bounds.y() == 0 && bounds.IsEmpty())
     return Shell::GetTargetRootWindow();
-  return wm::GetRootWindowMatching(bounds);
+  return wm::WmWindowAura::GetAuraWindow(wm::GetRootWindowMatching(bounds));
 }
 
 aura::Window* GetContainerById(aura::Window* root, int id) {
diff --git a/ash/wm/toplevel_window_event_handler.cc b/ash/wm/toplevel_window_event_handler.cc
index 399fcf7..5e702aa 100644
--- a/ash/wm/toplevel_window_event_handler.cc
+++ b/ash/wm/toplevel_window_event_handler.cc
@@ -123,7 +123,7 @@
     : handler_(handler),
       resizer_(resizer),
       grabbed_capture_(false) {
-  aura::Window* target = resizer_->GetTarget();
+  aura::Window* target = resizer_->GetAuraTarget();
   target->AddObserver(this);
   wm::GetWindowState(target)->AddObserver(this);
 
@@ -134,7 +134,7 @@
 }
 
 ToplevelWindowEventHandler::ScopedWindowResizer::~ScopedWindowResizer() {
-  aura::Window* target = resizer_->GetTarget();
+  aura::Window* target = resizer_->GetAuraTarget();
   target->RemoveObserver(this);
   wm::GetWindowState(target)->RemoveObserver(this);
   if (grabbed_capture_)
@@ -155,7 +155,7 @@
 
 void ToplevelWindowEventHandler::ScopedWindowResizer::OnWindowDestroying(
     aura::Window* window) {
-  DCHECK_EQ(resizer_->GetTarget(), window);
+  DCHECK_EQ(resizer_->GetAuraTarget(), window);
   handler_->ResizerWindowDestroyed();
 }
 
@@ -234,7 +234,7 @@
     return;
 
   if (window_resizer_.get() &&
-      window_resizer_->resizer()->GetTarget() != target) {
+      window_resizer_->resizer()->GetAuraTarget() != target) {
     return;
   }
 
@@ -477,7 +477,7 @@
       break;
     case DRAG_RESIZER_WINDOW_DESTROYED:
       // We explicitly do not invoke RevertDrag() since that may do things to
-      // WindowResizer::GetTarget() which was destroyed.
+      // WindowResizer::GetAuraTarget() which was destroyed.
       break;
   }
   drag_reverted_ = (status != DRAG_COMPLETE);
diff --git a/ash/wm/window_resizer.cc b/ash/wm/window_resizer.cc
index c0f2ca59..cad9947b 100644
--- a/ash/wm/window_resizer.cc
+++ b/ash/wm/window_resizer.cc
@@ -4,24 +4,17 @@
 
 #include "ash/wm/window_resizer.h"
 
-#include "ash/screen_util.h"
-#include "ash/shell.h"
 #include "ash/shell_window_ids.h"
+#include "ash/wm/common/root_window_finder.h"
 #include "ash/wm/common/window_positioning_utils.h"
-#include "ash/wm/coordinate_conversion.h"
 #include "ash/wm/dock/docked_window_layout_manager.h"
 #include "ash/wm/window_state.h"
-#include "ash/wm/window_util.h"
-#include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
-#include "ui/aura/window_delegate.h"
-#include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/hit_test.h"
 #include "ui/base/ui_base_types.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/gfx/display.h"
+#include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/screen.h"
-#include "ui/wm/core/coordinate_conversion.h"
 
 namespace ash {
 
@@ -138,18 +131,16 @@
   // has to come first since it might have an impact on the origin as well as
   // on the size.
   if (details().bounds_change & kBoundsChange_Resizes) {
-    gfx::Rect work_area = gfx::Screen::GetScreen()
-                              ->GetDisplayNearestWindow(GetTarget())
-                              .work_area();
-    aura::Window* dock_container = Shell::GetContainer(
-        GetTarget()->GetRootWindow(), kShellWindowId_DockedContainer);
+    gfx::Rect work_area = GetTarget()->GetDisplayNearestWindow().work_area();
+    wm::WmWindow* dock_container =
+        GetTarget()->GetRootWindow()->GetChildByShellWindowId(
+            kShellWindowId_DockedContainer);
     DockedWindowLayoutManager* dock_layout =
         static_cast<DockedWindowLayoutManager*>(
-            dock_container->layout_manager());
+            wm::WmWindowAura::GetAuraWindow(dock_container)->layout_manager());
 
     work_area.Union(dock_layout->docked_bounds());
-    work_area = ScreenUtil::ConvertRectFromScreen(GetTarget()->parent(),
-                                                 work_area);
+    work_area = GetTarget()->GetParent()->ConvertRectFromScreen(work_area);
     if (details().size_change_direction & kBoundsChangeDirection_Horizontal) {
       if (IsRightEdge(details().window_component) &&
           new_bounds.right() < work_area.x() + wm::kMinimumOnScreenArea) {
@@ -204,34 +195,32 @@
     // Make sure that |new_bounds| doesn't leave any of the displays.  Note that
     // the |work_area| above isn't good for this check since it is the work area
     // for the current display but the window can move to a different one.
-    aura::Window* parent = GetTarget()->parent();
-    gfx::Point passed_location_in_screen(passed_location);
-    ::wm::ConvertPointToScreen(parent, &passed_location_in_screen);
+    wm::WmWindow* parent = GetTarget()->GetParent();
+    gfx::Point passed_location_in_screen(
+        parent->ConvertPointToScreen(passed_location));
     gfx::Rect near_passed_location(passed_location_in_screen, gfx::Size());
     // Use a pointer location (matching the logic in DragWindowResizer) to
     // calculate the target display after the drag.
     const gfx::Display& display =
         gfx::Screen::GetScreen()->GetDisplayMatching(near_passed_location);
-    aura::Window* dock_container =
-        Shell::GetContainer(wm::GetRootWindowMatching(near_passed_location),
-                            kShellWindowId_DockedContainer);
+    wm::WmWindow* dock_container =
+        wm::GetRootWindowMatching(near_passed_location)
+            ->GetChildByShellWindowId(kShellWindowId_DockedContainer);
     DockedWindowLayoutManager* dock_layout =
         static_cast<DockedWindowLayoutManager*>(
-            dock_container->layout_manager());
+            wm::WmWindowAura::GetAuraWindow(dock_container)->layout_manager());
 
     gfx::Rect screen_work_area = display.work_area();
     screen_work_area.Union(dock_layout->docked_bounds());
     screen_work_area.Inset(wm::kMinimumOnScreenArea, 0);
-    gfx::Rect new_bounds_in_screen =
-        ScreenUtil::ConvertRectToScreen(parent, new_bounds);
+    gfx::Rect new_bounds_in_screen = parent->ConvertRectToScreen(new_bounds);
     if (!screen_work_area.Intersects(new_bounds_in_screen)) {
       // Make sure that the x origin does not leave the current display.
       new_bounds_in_screen.set_x(
           std::max(screen_work_area.x() - new_bounds.width(),
                    std::min(screen_work_area.right(),
                             new_bounds_in_screen.x())));
-      new_bounds =
-          ScreenUtil::ConvertRectFromScreen(parent, new_bounds_in_screen);
+      new_bounds = parent->ConvertRectFromScreen(new_bounds_in_screen);
     }
   }
 
@@ -287,7 +276,7 @@
 gfx::Size WindowResizer::GetSizeForDrag(int* delta_x, int* delta_y) {
   gfx::Size size = details().initial_bounds_in_parent.size();
   if (details().bounds_change & kBoundsChange_Resizes) {
-    gfx::Size min_size = GetTarget()->delegate()->GetMinimumSize();
+    gfx::Size min_size = GetTarget()->GetMinimumSize();
     size.SetSize(GetWidthForDrag(min_size.width(), delta_x),
                  GetHeightForDrag(min_size.height(), delta_y));
   } else if (!details().restore_bounds.IsEmpty()) {
@@ -312,11 +301,8 @@
     }
 
     // And don't let the window go bigger than the display.
-    int max_width = gfx::Screen::GetScreen()
-                        ->GetDisplayNearestWindow(GetTarget())
-                        .bounds()
-                        .width();
-    gfx::Size max_size = GetTarget()->delegate()->GetMaximumSize();
+    int max_width = GetTarget()->GetDisplayNearestWindow().bounds().width();
+    gfx::Size max_size = GetTarget()->GetMaximumSize();
     if (max_size.width() != 0)
       max_width = std::min(max_width, max_size.width());
     if (width > max_width) {
@@ -344,11 +330,8 @@
     }
 
     // And don't let the window go bigger than the display.
-    int max_height = gfx::Screen::GetScreen()
-                         ->GetDisplayNearestWindow(GetTarget())
-                         .bounds()
-                         .height();
-    gfx::Size max_size = GetTarget()->delegate()->GetMaximumSize();
+    int max_height = GetTarget()->GetDisplayNearestWindow().bounds().height();
+    gfx::Size max_size = GetTarget()->GetMaximumSize();
     if (max_size.height() != 0)
       max_height = std::min(max_height, max_size.height());
     if (height > max_height) {
diff --git a/ash/wm/window_resizer.h b/ash/wm/window_resizer.h
index af7a92c..39a47a8 100644
--- a/ash/wm/window_resizer.h
+++ b/ash/wm/window_resizer.h
@@ -11,14 +11,20 @@
 #include "ash/wm/drag_details.h"
 #include "ash/wm/window_state.h"
 #include "base/macros.h"
-#include "ui/gfx/geometry/rect.h"
 #include "ui/wm/public/window_move_client.h"
 
 namespace aura {
 class Window;
 }
 
+namespace gfx {
+class Rect;
+}
+
 namespace ash {
+namespace wm {
+class WmWindow;
+}
 
 // WindowResizer is used by ToplevelWindowEventFilter to handle dragging, moving
 // or resizing a window. All coordinates passed to this are in the parent
@@ -35,7 +41,7 @@
   static const int kBoundsChangeDirection_Horizontal;
   static const int kBoundsChangeDirection_Vertical;
 
-  WindowResizer(wm::WindowState* window_state);
+  explicit WindowResizer(wm::WindowState* window_state);
   virtual ~WindowResizer();
 
   // Returns a bitmask of the kBoundsChange_ values.
@@ -56,8 +62,13 @@
   virtual void RevertDrag() = 0;
 
   // Returns the target window the resizer was created for.
-  aura::Window* GetTarget() const {
-    return window_state_ ? window_state_->aura_window() : NULL;
+  wm::WmWindow* GetTarget() const {
+    return window_state_ ? window_state_->window() : nullptr;
+  }
+  // Deprecated.
+  // TODO(sky): remove.
+  aura::Window* GetAuraTarget() const {
+    return window_state_ ? window_state_->aura_window() : nullptr;
   }
 
   // See comment for |DragDetails::initial_location_in_parent|.
diff --git a/ash/wm/workspace/multi_window_resize_controller.cc b/ash/wm/workspace/multi_window_resize_controller.cc
index befcaeb..351e086b 100644
--- a/ash/wm/workspace/multi_window_resize_controller.cc
+++ b/ash/wm/workspace/multi_window_resize_controller.cc
@@ -471,7 +471,7 @@
 
 void MultiWindowResizeController::CompleteResize() {
   window_resizer_->CompleteDrag();
-  wm::GetWindowState(window_resizer_->GetTarget())->DeleteDragDetails();
+  wm::GetWindowState(window_resizer_->GetAuraTarget())->DeleteDragDetails();
   window_resizer_.reset();
 
   // Mouse may still be over resizer, if not hide.
@@ -494,7 +494,7 @@
   if (!window_resizer_)
     return;  // Happens if window was destroyed and we nuked the WindowResizer.
   window_resizer_->RevertDrag();
-  wm::GetWindowState(window_resizer_->GetTarget())->DeleteDragDetails();
+  wm::GetWindowState(window_resizer_->GetAuraTarget())->DeleteDragDetails();
   window_resizer_.reset();
   Hide();
 }
diff --git a/ash/wm/workspace/phantom_window_controller.cc b/ash/wm/workspace/phantom_window_controller.cc
index be3afae..d300137 100644
--- a/ash/wm/workspace/phantom_window_controller.cc
+++ b/ash/wm/workspace/phantom_window_controller.cc
@@ -8,7 +8,8 @@
 
 #include "ash/shell.h"
 #include "ash/shell_window_ids.h"
-#include "ash/wm/coordinate_conversion.h"
+#include "ash/wm/aura/wm_window_aura.h"
+#include "ash/wm/common/root_window_finder.h"
 #include "grit/ash_resources.h"
 #include "ui/aura/window.h"
 #include "ui/compositor/layer.h"
@@ -97,7 +98,8 @@
       floor((start_bounds_in_screen.width() - start_width) / 2.0f),
       floor((start_bounds_in_screen.height() - start_height) / 2.0f));
   phantom_widget_ = CreatePhantomWidget(
-      wm::GetRootWindowMatching(target_bounds_in_screen_),
+      wm::WmWindowAura::GetAuraWindow(
+          wm::GetRootWindowMatching(target_bounds_in_screen_)),
       start_bounds_in_screen);
 
   AnimateToBounds(phantom_widget_.get(), target_bounds_in_screen_);
diff --git a/ash/wm/workspace/workspace_window_resizer.cc b/ash/wm/workspace/workspace_window_resizer.cc
index 16151b8..8e6945b 100644
--- a/ash/wm/workspace/workspace_window_resizer.cc
+++ b/ash/wm/workspace/workspace_window_resizer.cc
@@ -367,7 +367,7 @@
   gfx::Rect bounds = CalculateBoundsForDrag(location_in_parent);
   AdjustBoundsForMainWindow(sticky_size, &bounds);
 
-  if (bounds != GetTarget()->bounds()) {
+  if (bounds != GetAuraTarget()->bounds()) {
     if (!did_move_or_resize_) {
       if (!details().restore_bounds.IsEmpty())
         window_state()->ClearRestoreBounds();
@@ -377,7 +377,7 @@
   }
 
   gfx::Point location_in_screen = location_in_parent;
-  ::wm::ConvertPointToScreen(GetTarget()->parent(), &location_in_screen);
+  ::wm::ConvertPointToScreen(GetAuraTarget()->parent(), &location_in_screen);
 
   aura::Window* root = NULL;
   gfx::Display display =
@@ -391,17 +391,18 @@
   }
   if (!attached_windows_.empty())
     LayoutAttachedWindows(&bounds);
-  if (bounds != GetTarget()->bounds()) {
+  if (bounds != GetAuraTarget()->bounds()) {
     // SetBounds needs to be called to update the layout which affects where the
     // phantom window is drawn. Keep track if the window was destroyed during
     // the drag and quit early if so.
     base::WeakPtr<WorkspaceWindowResizer> resizer(
         weak_ptr_factory_.GetWeakPtr());
-    GetTarget()->SetBounds(bounds);
+    GetAuraTarget()->SetBounds(bounds);
     if (!resizer)
       return;
   }
-  const bool in_original_root = !root || root == GetTarget()->GetRootWindow();
+  const bool in_original_root =
+      !root || root == GetAuraTarget()->GetRootWindow();
   // Hide a phantom window for snapping if the cursor is in another root window.
   if (in_original_root) {
     UpdateSnapPhantomWindow(location_in_parent, bounds);
@@ -430,7 +431,7 @@
   if (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT) {
     if (!window_state()->HasRestoreBounds()) {
       gfx::Rect initial_bounds = ScreenUtil::ConvertRectToScreen(
-          GetTarget()->parent(), details().initial_bounds_in_parent);
+          GetAuraTarget()->parent(), details().initial_bounds_in_parent);
       window_state()->SetRestoreBoundsInScreen(
           details().restore_bounds.IsEmpty() ?
           initial_bounds :
@@ -458,7 +459,7 @@
       // is slightly less confusing.
       if (details().window_component == HTCAPTION ||
           !AreBoundsValidSnappedBounds(window_state()->GetStateType(),
-                                       GetTarget()->bounds())) {
+                                       GetAuraTarget()->bounds())) {
         // Set the window to WINDOW_STATE_TYPE_NORMAL but keep the
         // window at the bounds that the user has moved/resized the
         // window to. ClearRestoreBounds() is used instead of
@@ -486,7 +487,7 @@
   if (!did_move_or_resize_)
     return;
 
-  GetTarget()->SetBounds(details().initial_bounds_in_parent);
+  GetAuraTarget()->SetBounds(details().initial_bounds_in_parent);
   if (!details().restore_bounds.IsEmpty()) {
     window_state()->SetRestoreBoundsInScreen(details().restore_bounds);
   }
@@ -537,7 +538,7 @@
   }
 
   aura::Window* dock_container = Shell::GetContainer(
-      GetTarget()->GetRootWindow(), kShellWindowId_DockedContainer);
+      GetAuraTarget()->GetRootWindow(), kShellWindowId_DockedContainer);
   dock_layout_ = static_cast<DockedWindowLayoutManager*>(
       dock_container->layout_manager());
 
@@ -567,8 +568,8 @@
 
 void WorkspaceWindowResizer::LayoutAttachedWindows(
     gfx::Rect* bounds) {
-  gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
-      GetTarget()));
+  gfx::Rect work_area(
+      ScreenUtil::GetDisplayWorkAreaBoundsInParent(GetAuraTarget()));
   int initial_size = PrimaryAxisSize(details().initial_bounds_in_parent.size());
   int current_size = PrimaryAxisSize(bounds->size());
   int start = PrimaryAxisCoordinate(bounds->right(), bounds->bottom());
@@ -708,11 +709,10 @@
 void WorkspaceWindowResizer::MagneticallySnapToOtherWindows(gfx::Rect* bounds) {
   if (UpdateMagnetismWindow(*bounds, kAllMagnetismEdges)) {
     gfx::Point point = OriginForMagneticAttach(
-        ScreenUtil::ConvertRectToScreen(GetTarget()->parent(), *bounds),
-        magnetism_window_->GetBoundsInScreen(),
-        magnetism_edge_);
-    aura::client::GetScreenPositionClient(GetTarget()->GetRootWindow())->
-        ConvertPointFromScreen(GetTarget()->parent(), &point);
+        ScreenUtil::ConvertRectToScreen(GetAuraTarget()->parent(), *bounds),
+        magnetism_window_->GetBoundsInScreen(), magnetism_edge_);
+    aura::client::GetScreenPositionClient(GetAuraTarget()->GetRootWindow())
+        ->ConvertPointFromScreen(GetAuraTarget()->parent(), &point);
     bounds->set_origin(point);
   }
 }
@@ -723,11 +723,10 @@
       WindowComponentToMagneticEdge(details().window_component);
   if (UpdateMagnetismWindow(*bounds, edges)) {
     *bounds = ScreenUtil::ConvertRectFromScreen(
-        GetTarget()->parent(),
+        GetAuraTarget()->parent(),
         BoundsForMagneticResizeAttach(
-            ScreenUtil::ConvertRectToScreen(GetTarget()->parent(), *bounds),
-            magnetism_window_->GetBoundsInScreen(),
-            magnetism_edge_));
+            ScreenUtil::ConvertRectToScreen(GetAuraTarget()->parent(), *bounds),
+            magnetism_window_->GetBoundsInScreen(), magnetism_edge_));
   }
 }
 
@@ -735,7 +734,7 @@
                                                    uint32_t edges) {
   // |bounds| are in coordinates of original window's parent.
   gfx::Rect bounds_in_screen =
-      ScreenUtil::ConvertRectToScreen(GetTarget()->parent(), bounds);
+      ScreenUtil::ConvertRectToScreen(GetAuraTarget()->parent(), bounds);
   MagnetismMatcher matcher(bounds_in_screen, edges);
 
   // If we snapped to a window then check it first. That way we don't bounce
@@ -765,7 +764,7 @@
     for (aura::Window::Windows::const_reverse_iterator i = children.rbegin();
          i != children.rend() && !matcher.AreEdgesObscured(); ++i) {
       wm::WindowState* other_state = wm::GetWindowState(*i);
-      if (other_state->aura_window() == GetTarget() ||
+      if (other_state->aura_window() == GetAuraTarget() ||
           !other_state->window()->IsVisible() ||
           !other_state->IsNormalOrSnapped() || !other_state->CanResize()) {
         continue;
@@ -785,13 +784,12 @@
     int sticky_size,
     gfx::Rect* bounds) {
   gfx::Point last_mouse_location_in_screen = last_mouse_location_;
-  ::wm::ConvertPointToScreen(GetTarget()->parent(),
+  ::wm::ConvertPointToScreen(GetAuraTarget()->parent(),
                              &last_mouse_location_in_screen);
   gfx::Display display = gfx::Screen::GetScreen()->GetDisplayNearestPoint(
       last_mouse_location_in_screen);
-  gfx::Rect work_area =
-      ScreenUtil::ConvertRectFromScreen(GetTarget()->parent(),
-                                       display.work_area());
+  gfx::Rect work_area = ScreenUtil::ConvertRectFromScreen(
+      GetAuraTarget()->parent(), display.work_area());
   if (details().window_component == HTCAPTION) {
     // Adjust the bounds to the work area where the mouse cursor is located.
     // Always keep kMinOnscreenHeight or the window height (whichever is less)
@@ -928,8 +926,9 @@
   DockedAlignment desired_alignment = (snap_type_ == SNAP_LEFT) ?
       DOCKED_ALIGNMENT_LEFT : DOCKED_ALIGNMENT_RIGHT;
   const bool can_dock =
-      dock_layout_->CanDockWindow(GetTarget(), desired_alignment) &&
-      dock_layout_->GetAlignmentOfWindow(GetTarget()) != DOCKED_ALIGNMENT_NONE;
+      dock_layout_->CanDockWindow(GetAuraTarget(), desired_alignment) &&
+      dock_layout_->GetAlignmentOfWindow(GetAuraTarget()) !=
+          DOCKED_ALIGNMENT_NONE;
   if (!can_dock) {
     // If the window cannot be docked, undock the window. This may change the
     // workspace bounds and hence |snap_type_|.
@@ -956,30 +955,30 @@
   // Windows that cannot be snapped or are less wide than kMaxDockWidth can get
   // docked without going through a snapping sequence.
   gfx::Rect phantom_bounds;
-  const bool should_dock = can_dock &&
-      (!can_snap ||
-       GetTarget()->bounds().width() <=
-           DockedWindowLayoutManager::kMaxDockWidth ||
-       edge_cycler_->use_second_mode() ||
-       dock_layout_->is_dragged_window_docked());
+  const bool should_dock =
+      can_dock && (!can_snap ||
+                   GetAuraTarget()->bounds().width() <=
+                       DockedWindowLayoutManager::kMaxDockWidth ||
+                   edge_cycler_->use_second_mode() ||
+                   dock_layout_->is_dragged_window_docked());
   if (should_dock) {
     SetDraggedWindowDocked(true);
     phantom_bounds = ScreenUtil::ConvertRectFromScreen(
-        GetTarget()->parent(), dock_layout_->dragged_bounds());
+        GetAuraTarget()->parent(), dock_layout_->dragged_bounds());
   } else {
     phantom_bounds = (snap_type_ == SNAP_LEFT)
                          ? wm::GetDefaultLeftSnappedWindowBoundsInParent(
-                               wm::WmWindowAura::Get(GetTarget()))
+                               wm::WmWindowAura::Get(GetAuraTarget()))
                          : wm::GetDefaultRightSnappedWindowBoundsInParent(
-                               wm::WmWindowAura::Get(GetTarget()));
+                               wm::WmWindowAura::Get(GetAuraTarget()));
   }
 
   if (!snap_phantom_window_controller_) {
     snap_phantom_window_controller_.reset(
-        new PhantomWindowController(GetTarget()));
+        new PhantomWindowController(GetAuraTarget()));
   }
   snap_phantom_window_controller_->Show(ScreenUtil::ConvertRectToScreen(
-      GetTarget()->parent(), phantom_bounds));
+      GetAuraTarget()->parent(), phantom_bounds));
 }
 
 void WorkspaceWindowResizer::RestackWindows() {
@@ -989,10 +988,10 @@
   // window with a different parent.
   typedef std::map<size_t, aura::Window*> IndexToWindowMap;
   IndexToWindowMap map;
-  aura::Window* parent = GetTarget()->parent();
+  aura::Window* parent = GetAuraTarget()->parent();
   const aura::Window::Windows& windows(parent->children());
-  map[std::find(windows.begin(), windows.end(), GetTarget()) -
-      windows.begin()] = GetTarget();
+  map[std::find(windows.begin(), windows.end(), GetAuraTarget()) -
+      windows.begin()] = GetAuraTarget();
   for (std::vector<aura::Window*>::const_iterator i =
            attached_windows_.begin(); i != attached_windows_.end(); ++i) {
     if ((*i)->parent() != parent)
@@ -1017,11 +1016,12 @@
     const gfx::Point& location) const {
   // TODO: this likely only wants total display area, not the area of a single
   // display.
-  gfx::Rect area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(GetTarget()));
+  gfx::Rect area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(GetAuraTarget()));
   if (details().source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) {
     // Increase tolerance for touch-snapping near the screen edges. This is only
     // necessary when the work area left or right edge is same as screen edge.
-    gfx::Rect display_bounds(ScreenUtil::GetDisplayBoundsInParent(GetTarget()));
+    gfx::Rect display_bounds(
+        ScreenUtil::GetDisplayBoundsInParent(GetAuraTarget()));
     int inset_left = 0;
     if (area.x() == display_bounds.x())
       inset_left = kScreenEdgeInsetForTouchDrag;
@@ -1041,7 +1041,7 @@
   if (should_dock) {
     if (!dock_layout_->is_dragged_window_docked()) {
       window_state()->set_bounds_changed_by_user(false);
-      dock_layout_->DockDraggedWindow(GetTarget());
+      dock_layout_->DockDraggedWindow(GetAuraTarget());
     }
   } else {
     if (dock_layout_->is_dragged_window_docked()) {
@@ -1056,8 +1056,8 @@
     const gfx::Rect& bounds_in_parent) const {
   DCHECK(snapped_type == wm::WINDOW_STATE_TYPE_LEFT_SNAPPED ||
          snapped_type == wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED);
-  gfx::Rect snapped_bounds = ScreenUtil::GetDisplayWorkAreaBoundsInParent(
-      GetTarget());
+  gfx::Rect snapped_bounds =
+      ScreenUtil::GetDisplayWorkAreaBoundsInParent(GetAuraTarget());
   if (snapped_type == wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED)
     snapped_bounds.set_x(snapped_bounds.right() - bounds_in_parent.width());
   snapped_bounds.set_width(bounds_in_parent.width());
diff --git a/blimp/client/BUILD.gn b/blimp/client/BUILD.gn
index e21efee..256aa9cd 100644
--- a/blimp/client/BUILD.gn
+++ b/blimp/client/BUILD.gn
@@ -325,7 +325,9 @@
       "app/android/java/src/org/chromium/blimp/BlimpLibraryLoader.java",
       "app/android/java/src/org/chromium/blimp/BlimpRendererActivity.java",
       "app/android/java/src/org/chromium/blimp/BlimpView.java",
+      "app/android/java/src/org/chromium/blimp/BrowserRestartActivity.java",
       "app/android/java/src/org/chromium/blimp/input/WebInputBox.java",
+      "app/android/java/src/org/chromium/blimp/preferences/PreferencesUtil.java",
       "app/android/java/src/org/chromium/blimp/session/BlimpClientSession.java",
       "app/android/java/src/org/chromium/blimp/session/EngineInfo.java",
       "app/android/java/src/org/chromium/blimp/session/TabControlFeature.java",
diff --git a/blimp/client/app/android/AndroidManifest.xml.jinja2 b/blimp/client/app/android/AndroidManifest.xml.jinja2
index 8ad10d5..dee9d81d 100644
--- a/blimp/client/app/android/AndroidManifest.xml.jinja2
+++ b/blimp/client/app/android/AndroidManifest.xml.jinja2
@@ -37,6 +37,13 @@
             </intent-filter>
         </activity>
         <activity android:name="org.chromium.blimp.settings.Preferences"/>
+        <activity android:name="org.chromium.blimp.BrowserRestartActivity"
+            android:launchMode="singleInstance"
+            android:exported="false"
+            android:theme="@android:style/Theme.Translucent.NoTitleBar"
+            android:excludeFromRecents="true"
+            android:process=":browser_restart_process">
+        </activity>
 
         <meta-data android:name="com.google.android.gms.version"
                 android:value="@integer/google_play_services_version" />
diff --git a/blimp/client/app/android/java/res/values/arrays.xml b/blimp/client/app/android/java/res/values/arrays.xml
new file mode 100644
index 0000000..9dfca1f
--- /dev/null
+++ b/blimp/client/app/android/java/res/values/arrays.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<resources>
+  <string-array name="assigner_envs">
+    <item>Production</item>
+    <item>Staging</item>
+    <item>Development</item>
+  </string-array>
+  <string-array name="assigner_urls">
+    <item>https://blimp-pa.googleapis.com/v1/assignment</item>
+    <item>https://staging-blimp-pa.sandbox.googleapis.com/v1/assignment</item>
+    <item>https://dev-blimp-pa.sandbox.googleapis.com/v1/assignment</item>
+  </string-array>
+</resources>
diff --git a/blimp/client/app/android/java/res/xml/about_blimp_preferences.xml b/blimp/client/app/android/java/res/xml/about_blimp_preferences.xml
index d3a0096..30cf166 100644
--- a/blimp/client/app/android/java/res/xml/about_blimp_preferences.xml
+++ b/blimp/client/app/android/java/res/xml/about_blimp_preferences.xml
@@ -17,7 +17,9 @@
     <Preference
         android:key="blimp_engine_version"
         android:title="@string/blimp_engine_version" />
-    <Preference
+    <ListPreference
         android:key="blimp_assigner_url"
-        android:title="@string/blimp_assigner_url" />
+        android:title="@string/blimp_assigner_url"
+        android:entries="@array/assigner_envs"
+        android:entryValues="@array/assigner_urls" />
 </PreferenceScreen>
diff --git a/blimp/client/app/android/java/src/org/chromium/blimp/BlimpRendererActivity.java b/blimp/client/app/android/java/src/org/chromium/blimp/BlimpRendererActivity.java
index c32d831..ebeeffc 100644
--- a/blimp/client/app/android/java/src/org/chromium/blimp/BlimpRendererActivity.java
+++ b/blimp/client/app/android/java/src/org/chromium/blimp/BlimpRendererActivity.java
@@ -16,6 +16,7 @@
 import org.chromium.blimp.auth.TokenSource;
 import org.chromium.blimp.auth.TokenSourceImpl;
 import org.chromium.blimp.input.WebInputBox;
+import org.chromium.blimp.preferences.PreferencesUtil;
 import org.chromium.blimp.session.BlimpClientSession;
 import org.chromium.blimp.session.EngineInfo;
 import org.chromium.blimp.session.TabControlFeature;
@@ -143,7 +144,7 @@
 
         setContentView(R.layout.blimp_main);
 
-        mBlimpClientSession = new BlimpClientSession();
+        mBlimpClientSession = new BlimpClientSession(PreferencesUtil.findAssignerUrl(this));
         mBlimpClientSession.addObserver(this);
 
         mBlimpView = (BlimpView) findViewById(R.id.renderer);
diff --git a/blimp/client/app/android/java/src/org/chromium/blimp/BrowserRestartActivity.java b/blimp/client/app/android/java/src/org/chromium/blimp/BrowserRestartActivity.java
new file mode 100644
index 0000000..ef7461e
--- /dev/null
+++ b/blimp/client/app/android/java/src/org/chromium/blimp/BrowserRestartActivity.java
@@ -0,0 +1,74 @@
+// 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.
+
+package org.chromium.blimp;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Process;
+
+/**
+ * Kills and (optionally) restarts the main Blimp process, then immediately kills itself.
+ *
+ * Starting this Activity requires passing in the process ID (the Intent should have the value of
+ * Process#myPid() as an extra).
+ *
+ * This Activity runs on a separate process from the main Blimp browser and cannot see the main
+ * process' Activities.  It is an workaround for crbug.com/515919 which doesn't use AlarmManager.
+ */
+public class BrowserRestartActivity extends Activity {
+    private static final String EXTRA_MAIN_PID =
+            "org.chromium.blimp.browser.BrowserRestartActivity.main_pid";
+    private static final String EXTRA_RESTART =
+            "org.chromium.blimp.browser.BrowserRestartActivity.restart";
+
+    private static final String TAG = "BrowserRestartActivity";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        destroyProcess(getIntent());
+    }
+
+    @Override
+    public void onNewIntent(Intent intent) {
+        destroyProcess(getIntent());
+    }
+
+    private void destroyProcess(Intent intent) {
+        // Kill the main Blimp process.
+        int mainBrowserPid = intent.getIntExtra(BrowserRestartActivity.EXTRA_MAIN_PID, -1);
+        assert mainBrowserPid != -1;
+        Process.killProcess(mainBrowserPid);
+
+        // Fire an Intent to restart Blimp.
+        boolean restart = intent.getBooleanExtra(BrowserRestartActivity.EXTRA_RESTART, false);
+        if (restart) {
+            Intent restartIntent = new Intent(Intent.ACTION_MAIN);
+            restartIntent.setPackage(getPackageName());
+            restartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            startActivity(restartIntent);
+        }
+
+        // Kill this process.
+        finish();
+        Process.killProcess(Process.myPid());
+    }
+
+    /**
+     * Helper method to create an Intent to restart the browser.
+     * @param context The current android context
+     * @return Intent to be fired
+     */
+    public static Intent createRestartIntent(Context context) {
+        Intent intent = new Intent();
+        intent.setClassName(context.getPackageName(), BrowserRestartActivity.class.getName());
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.putExtra(BrowserRestartActivity.EXTRA_MAIN_PID, Process.myPid());
+        intent.putExtra(BrowserRestartActivity.EXTRA_RESTART, true);
+        return intent;
+    }
+}
diff --git a/blimp/client/app/android/java/src/org/chromium/blimp/preferences/PreferencesUtil.java b/blimp/client/app/android/java/src/org/chromium/blimp/preferences/PreferencesUtil.java
new file mode 100644
index 0000000..fb6a9eb
--- /dev/null
+++ b/blimp/client/app/android/java/src/org/chromium/blimp/preferences/PreferencesUtil.java
@@ -0,0 +1,83 @@
+// 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.
+
+package org.chromium.blimp.preferences;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+
+import org.chromium.blimp.R;
+
+/**
+ * Provides helper methods for storing and retrieving values in android shared preferences.
+ */
+public class PreferencesUtil {
+    /**
+     * Preference that stores the last used assigner URL.
+     */
+    private static final String PREF_LAST_USED_ASSIGNER = "last_known_assigner";
+    private static final String DEFAULT_EMPTY_STRING = "";
+
+    private static SharedPreferences getPreferences(Context context) {
+        return PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
+    }
+
+    /**
+     * Finds the assigner to be used from user's last preference. If the app is being used for the
+     * first time, the first entry from the assigner array would be used.
+     * @return assigner to use.
+     */
+    public static String findAssignerUrl(Context context) {
+        String lastAssigner = getPreferences(context).getString(PREF_LAST_USED_ASSIGNER, "");
+        if (lastAssigner.isEmpty()) {
+            String[] assignerUrls = context.getResources().getStringArray(R.array.assigner_urls);
+            assert assignerUrls != null && assignerUrls.length > 0;
+            lastAssigner = assignerUrls[0];
+            writeString(context, PREF_LAST_USED_ASSIGNER, lastAssigner);
+        }
+
+        return lastAssigner;
+    }
+
+    /**
+     * Reads the last used assigner from shared preference.
+     * @param context The current Android context
+     * @return The saved value of assigner preference
+     */
+    public static String getLastUsedAssigner(Context context) {
+        return readString(context, PREF_LAST_USED_ASSIGNER);
+    }
+
+    /**
+     * Sets the last used assigner.
+     * @param context The current Android context
+     * @param assigner The new value of assigner preference
+     */
+    public static void setLastUsedAssigner(Context context, String assigner) {
+        writeString(context, PREF_LAST_USED_ASSIGNER, assigner);
+    }
+
+    /**
+     * Reads a string value from shared preference.
+     * @param context The current Android context
+     * @param key The name of the preference to read
+     * @return The current value of the preference or a default value
+     */
+    private static String readString(Context context, String key) {
+        return getPreferences(context).getString(key, DEFAULT_EMPTY_STRING);
+    }
+
+    /**
+     * Writes the given string into shared preference.
+     * @param context The current Android context
+     * @param key The name of the preference to modify
+     * @param value The new value for the preference
+     */
+    private static void writeString(Context context, String key, String value) {
+        SharedPreferences.Editor editor = getPreferences(context).edit();
+        editor.putString(key, value);
+        editor.apply();
+    }
+}
diff --git a/blimp/client/app/android/java/src/org/chromium/blimp/session/BlimpClientSession.java b/blimp/client/app/android/java/src/org/chromium/blimp/session/BlimpClientSession.java
index 95a4a8cc..d16cbc2 100644
--- a/blimp/client/app/android/java/src/org/chromium/blimp/session/BlimpClientSession.java
+++ b/blimp/client/app/android/java/src/org/chromium/blimp/session/BlimpClientSession.java
@@ -49,15 +49,12 @@
         void onDisconnected(String reason);
     }
 
-    private static final String DEFAULT_ASSIGNER_URL =
-            "https://blimp-pa.googleapis.com/v1/assignment";
-
     private final String mAssignerUrl;
     private final List<ConnectionObserver> mObservers;
     private long mNativeBlimpClientSessionAndroidPtr;
 
-    public BlimpClientSession() {
-        mAssignerUrl = DEFAULT_ASSIGNER_URL;
+    public BlimpClientSession(String assignerUrl) {
+        mAssignerUrl = assignerUrl;
         mObservers = new ArrayList<ConnectionObserver>();
         mNativeBlimpClientSessionAndroidPtr = nativeInit(mAssignerUrl);
     }
diff --git a/blimp/client/app/android/java/src/org/chromium/blimp/settings/AboutBlimpPreferences.java b/blimp/client/app/android/java/src/org/chromium/blimp/settings/AboutBlimpPreferences.java
index 8152c21..86339be 100644
--- a/blimp/client/app/android/java/src/org/chromium/blimp/settings/AboutBlimpPreferences.java
+++ b/blimp/client/app/android/java/src/org/chromium/blimp/settings/AboutBlimpPreferences.java
@@ -5,17 +5,24 @@
 package org.chromium.blimp.settings;
 
 import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.Bundle;
+import android.preference.ListPreference;
 import android.preference.Preference;
 import android.preference.PreferenceFragment;
 import android.text.TextUtils;
 
 import org.chromium.base.Log;
+import org.chromium.blimp.BrowserRestartActivity;
 import org.chromium.blimp.R;
+import org.chromium.blimp.preferences.PreferencesUtil;
 
 /**
  * Fragment to display blimp client and engine version related info.
@@ -38,8 +45,14 @@
         getActivity().setTitle(R.string.about_blimp_preferences);
         addPreferencesFromResource(R.xml.about_blimp_preferences);
 
-        Activity activity = getActivity();
-        PackageManager pm = getActivity().getPackageManager();
+        setAppVersion(getActivity());
+        setOSVersion();
+        setEngineIPandVersion(getActivity().getIntent());
+        setupAssignerPreferences();
+    }
+
+    private void setAppVersion(Activity activity) {
+        PackageManager pm = activity.getPackageManager();
         try {
             ApplicationInfo applicationInfo = pm.getApplicationInfo(activity.getPackageName(), 0);
             PackageInfo packageInfo = pm.getPackageInfo(activity.getPackageName(), 0);
@@ -58,20 +71,68 @@
         } catch (PackageManager.NameNotFoundException e) {
             Log.d(TAG, "Fetching ApplicationInfo failed.", e);
         }
+    }
 
+    private void setOSVersion() {
         Preference p = findPreference(PREF_OS_VERSION);
         p.setSummary("Android " + Build.VERSION.RELEASE);
+    }
 
-        String engineIP = getActivity().getIntent().getStringExtra(EXTRA_ENGINE_IP);
-        p = findPreference(PREF_ENGINE_IP);
+    private void setEngineIPandVersion(Intent intent) {
+        String engineIP = intent.getStringExtra(EXTRA_ENGINE_IP);
+        Preference p = findPreference(PREF_ENGINE_IP);
         p.setSummary(engineIP == null ? "" : engineIP);
 
-        String engineVersion = getActivity().getIntent().getStringExtra(EXTRA_ENGINE_VERSION);
+        String engineVersion = intent.getStringExtra(EXTRA_ENGINE_VERSION);
         p = findPreference(PREF_ENGINE_VERSION);
         p.setSummary(engineVersion == null ? "" : engineVersion);
+    }
 
-        String assigner = getActivity().getIntent().getStringExtra(EXTRA_ASSIGNER_URL);
-        p = findPreference(PREF_ASSIGNER_URL);
-        p.setSummary(assigner == null ? "" : assigner);
+    /**
+     * When the user taps on the current assigner, a list of available assigners pops up.
+     * User is allowed to change the assigner which is saved to shared preferences.
+     * A dialog is displayed which prompts the user to restart the application.
+     */
+    private void setupAssignerPreferences() {
+        final Activity activity = getActivity();
+        String assigner = PreferencesUtil.getLastUsedAssigner(activity);
+
+        final ListPreference lp = (ListPreference) findPreference(PREF_ASSIGNER_URL);
+        lp.setSummary(assigner == null ? "" : assigner);
+
+        lp.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+            @Override
+            public boolean onPreferenceChange(Preference preference, Object newValue) {
+                String newAssignmentUrl = (String) newValue;
+                lp.setSummary(newAssignmentUrl);
+                lp.setValue(newAssignmentUrl);
+
+                PreferencesUtil.setLastUsedAssigner(activity, newAssignmentUrl);
+                showRestartDialog(activity);
+
+                return true;
+            }
+        });
+    }
+
+    private void showRestartDialog(final Context context) {
+        // TODO(shaktisahu): Change this to use android.support.v7.app.AlertDialog later.
+        new AlertDialog.Builder(context)
+                .setTitle(R.string.restart_blimp)
+                .setMessage(R.string.blimp_assigner_changed_please_restart)
+                .setPositiveButton(R.string.restart_now,
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                restartBrowser(context);
+                            }
+                        })
+                .create()
+                .show();
+    }
+
+    private void restartBrowser(Context context) {
+        Intent intent = BrowserRestartActivity.createRestartIntent(context);
+        context.startActivity(intent);
     }
 }
diff --git a/blimp/client/app/android/java/strings/android_blimp_strings.grd b/blimp/client/app/android/java/strings/android_blimp_strings.grd
index 39db604..6ff4210e 100644
--- a/blimp/client/app/android/java/strings/android_blimp_strings.grd
+++ b/blimp/client/app/android/java/strings/android_blimp_strings.grd
@@ -169,6 +169,15 @@
       <message name="IDS_BLIMP_ASSIGNER_URL" desc="Blimp Assigner URL.">
         Assigner URL
       </message>
+      <message name="IDS_BLIMP_ASSIGNER_CHANGED_PLEASE_RESTART" desc="Blimp assigner changed, restart message.">
+        Please restart the application to use the new assigner configuration.
+      </message>
+      <message name="IDS_RESTART_BLIMP" desc="Blimp restart message.">
+        Restart Blimp
+      </message>
+      <message name="IDS_RESTART_NOW" desc="Restart now message">
+        Restart Now
+      </message>
     </messages>
   </release>
 </grit>
diff --git a/blimp/client/feature/compositor/blimp_context_provider.cc b/blimp/client/feature/compositor/blimp_context_provider.cc
index a1ee746..4d0e06e 100644
--- a/blimp/client/feature/compositor/blimp_context_provider.cc
+++ b/blimp/client/feature/compositor/blimp_context_provider.cc
@@ -56,8 +56,6 @@
 
 bool BlimpContextProvider::BindToCurrentThread() {
   DCHECK(context_thread_checker_.CalledOnValidThread());
-  capabilities_.gpu = context_->GetImplementation()->capabilities();
-  capabilities_.gpu.image = true;
   return true;
 }
 
@@ -65,9 +63,14 @@
   context_thread_checker_.DetachFromThread();
 }
 
-cc::ContextProvider::Capabilities BlimpContextProvider::ContextCapabilities() {
+gpu::Capabilities BlimpContextProvider::ContextCapabilities() {
   DCHECK(context_thread_checker_.CalledOnValidThread());
-  return capabilities_;
+  gpu::Capabilities capabilities =
+      context_->GetImplementation()->capabilities();
+  // TODO(danakj): Why? Is this even valid? This is the CHROMIUM_image extension
+  // to use GpuMemoryBuffers. Does the context not provide this?
+  capabilities.image = true;
+  return capabilities;
 }
 
 gpu::gles2::GLES2Interface* BlimpContextProvider::ContextGL() {
diff --git a/blimp/client/feature/compositor/blimp_context_provider.h b/blimp/client/feature/compositor/blimp_context_provider.h
index a1a01dc..7758bdbb 100644
--- a/blimp/client/feature/compositor/blimp_context_provider.h
+++ b/blimp/client/feature/compositor/blimp_context_provider.h
@@ -34,7 +34,7 @@
   // cc::ContextProvider implementation.
   bool BindToCurrentThread() override;
   void DetachFromThread() override;
-  Capabilities ContextCapabilities() override;
+  gpu::Capabilities ContextCapabilities() override;
   gpu::gles2::GLES2Interface* ContextGL() override;
   gpu::ContextSupport* ContextSupport() override;
   class GrContext* GrContext() override;
@@ -61,8 +61,6 @@
   std::unique_ptr<gpu::GLInProcessContext> context_;
   std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_;
 
-  cc::ContextProvider::Capabilities capabilities_;
-
   LostContextCallback lost_context_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(BlimpContextProvider);
diff --git a/build/android/adb_reverse_forwarder.py b/build/android/adb_reverse_forwarder.py
index e3a7b50..b0a8dc3 100755
--- a/build/android/adb_reverse_forwarder.py
+++ b/build/android/adb_reverse_forwarder.py
@@ -61,8 +61,8 @@
   blacklist = (device_blacklist.Blacklist(options.blacklist_file)
                if options.blacklist_file
                else None)
-  device = device_utils.DeviceUtils.HealthyDevices(blacklist=blacklist,
-                                                   device_arg=options.device)
+  device = device_utils.DeviceUtils.HealthyDevices(
+      blacklist=blacklist, device_arg=options.device)[0]
   constants.SetBuildType(options.build_type)
   try:
     forwarder.Forwarder.Map(port_pairs, device)
diff --git a/build/common.gypi b/build/common.gypi
index 963f9bc2..bf6732a8 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -2487,6 +2487,12 @@
       }, {
         'enable_hangout_services_extension%': 0,
       }],
+
+      # Gold doesn't respect section alignment and breaks gcc builds with icf
+      # https://bugs.chromium.org/p/chromium/issues/detail?id=576197
+      ['clang==0 and linux_use_bundled_gold==1', {
+        'gold_icf_level%': 'none'
+      }],
     ],
 
     # The path to the ANGLE library.
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index ec5f76c..61e5f97 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -679,9 +679,14 @@
         rebase_path("//", root_build_dir),
         "--emma-jar",
         rebase_path(_emma_jar, root_build_dir),
-        "--filter-string",
-        emma_filter,
       ]
+
+      if (emma_filter != "") {
+        args += [
+          "--filter-string",
+          emma_filter,
+        ]
+      }
     }
   } else {
     _output_jar_target = "${target_name}__copy_jar"
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index aae3bac6..07408d6 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -86,6 +86,10 @@
   # TODO(brettw) it's weird that Mac and desktop Linux are different. We should
   # explore favoring size over speed in this case as well.
   optimize_for_size = is_android || is_ios
+
+  # Gold icf level, values are "none", "safe", "all". If value isn't overridden,
+  # default initialization is below.
+  gold_icf_level = ""
 }
 
 # Apply the default logic for these values if they were not set explicitly.
@@ -103,6 +107,16 @@
                       linux_use_bundled_binutils && cc_wrapper == ""
 }
 
+if (gold_icf_level == "") {
+  if (use_gold && !is_clang) {
+    # Gold doesn't respect section alignment and breaks gcc builds with icf
+    # https://bugs.chromium.org/p/chromium/issues/detail?id=576197
+    gold_icf_level = "none"
+  } else {
+    gold_icf_level = "all"
+  }
+}
+
 # default_include_dirs ---------------------------------------------------------
 #
 # This is a separate config so that third_party code (which would not use the
@@ -304,7 +318,7 @@
 
     if (!using_sanitizer && !(is_android && use_order_profiling)) {
       # TODO(brettw) common.gypi has this only for target toolset.
-      ldflags += [ "-Wl,--icf=all" ]
+      ldflags += [ "-Wl,--icf=${gold_icf_level}" ]
     }
 
     # TODO(thestig): Make this flag work with GN.
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index bd8cf6b9..2afc662 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -199,7 +199,6 @@
     "output/compositor_frame_ack.h",
     "output/compositor_frame_metadata.cc",
     "output/compositor_frame_metadata.h",
-    "output/context_provider.cc",
     "output/context_provider.h",
     "output/copy_output_request.cc",
     "output/copy_output_request.h",
@@ -378,8 +377,8 @@
     "raster/texture_compressor.h",
     "raster/texture_compressor_etc1.cc",
     "raster/texture_compressor_etc1.h",
-    "raster/tile_task_runner.cc",
-    "raster/tile_task_runner.h",
+    "raster/tile_task.cc",
+    "raster/tile_task.h",
     "raster/tile_task_worker_pool.cc",
     "raster/tile_task_worker_pool.h",
     "raster/zero_copy_tile_task_worker_pool.cc",
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 0878db9..9978bda 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -260,7 +260,6 @@
         'output/compositor_frame_ack.h',
         'output/compositor_frame_metadata.cc',
         'output/compositor_frame_metadata.h',
-        'output/context_provider.cc',
         'output/context_provider.h',
         'output/copy_output_request.cc',
         'output/copy_output_request.h',
@@ -439,8 +438,8 @@
         'raster/texture_compressor.h',
         'raster/texture_compressor_etc1.cc',
         'raster/texture_compressor_etc1.h',
-        'raster/tile_task_runner.cc',
-        'raster/tile_task_runner.h',
+        'raster/tile_task.cc',
+        'raster/tile_task.h',
         'raster/tile_task_worker_pool.cc',
         'raster/tile_task_worker_pool.h',
         'raster/zero_copy_tile_task_worker_pool.cc',
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 7278504a..5f2c1dd 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -74,6 +74,7 @@
       raster_source_scale_(0.f),
       raster_contents_scale_(0.f),
       low_res_raster_contents_scale_(0.f),
+      raster_source_scale_is_fixed_(false),
       was_screen_space_transform_animating_(false),
       only_used_low_res_last_append_quads_(false),
       is_mask_(is_mask),
@@ -902,8 +903,10 @@
   if (raster_device_scale_ != ideal_device_scale_)
     return true;
 
-  // When the source scale changes we want to match it, but not when animating.
+  // When the source scale changes we want to match it, but not when animating
+  // or when we've fixed the scale in place.
   if (!draw_properties().screen_space_transform_is_animating &&
+      !raster_source_scale_is_fixed_ &&
       raster_source_scale_ != ideal_source_scale_)
     return true;
 
@@ -944,14 +947,33 @@
 }
 
 void PictureLayerImpl::RecalculateRasterScales() {
-  const float old_raster_contents_scale = raster_contents_scale_;
-  const float old_raster_page_scale = raster_page_scale_;
+  float old_raster_contents_scale = raster_contents_scale_;
+  float old_raster_page_scale = raster_page_scale_;
+  float old_raster_source_scale = raster_source_scale_;
 
   raster_device_scale_ = ideal_device_scale_;
   raster_page_scale_ = ideal_page_scale_;
   raster_source_scale_ = ideal_source_scale_;
   raster_contents_scale_ = ideal_contents_scale_;
 
+  // If we're not animating, or leaving an animation, and the
+  // ideal_source_scale_ changes, then things are unpredictable, and we fix
+  // the raster_source_scale_ in place.
+  if (old_raster_source_scale &&
+      !draw_properties().screen_space_transform_is_animating &&
+      !was_screen_space_transform_animating_ &&
+      old_raster_source_scale != ideal_source_scale_)
+    raster_source_scale_is_fixed_ = true;
+
+  // TODO(danakj): Adjust raster source scale closer to ideal source scale at
+  // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending
+  // tree. This will allow CSS scale changes to get re-rastered at an
+  // appropriate rate. (crbug.com/413636)
+  if (raster_source_scale_is_fixed_) {
+    raster_contents_scale_ /= raster_source_scale_;
+    raster_source_scale_ = 1.f;
+  }
+
   // During pinch we completely ignore the current ideal scale, and just use
   // a multiple of the previous scale.
   bool is_pinching = layer_tree_impl()->PinchGestureActive();
@@ -1122,6 +1144,7 @@
   raster_source_scale_ = 0.f;
   raster_contents_scale_ = 0.f;
   low_res_raster_contents_scale_ = 0.f;
+  raster_source_scale_is_fixed_ = false;
 }
 
 bool PictureLayerImpl::CanHaveTilings() const {
@@ -1205,7 +1228,6 @@
     base::trace_event::TracedValue* state) const {
   LayerImpl::AsValueInto(state);
   state->SetDouble("ideal_contents_scale", ideal_contents_scale_);
-  state->SetDouble("raster_contents_scale", raster_contents_scale_);
   state->SetDouble("geometry_contents_scale", MaximumTilingContentsScale());
   state->BeginArray("tilings");
   tilings_->AsValueInto(state);
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index d227d3f..30e4cbe 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -140,6 +140,7 @@
   float raster_contents_scale_;
   float low_res_raster_contents_scale_;
 
+  bool raster_source_scale_is_fixed_;
   bool was_screen_space_transform_animating_;
   bool only_used_low_res_last_append_quads_;
   const bool is_mask_;
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 526c921..448d557b 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -1101,72 +1101,44 @@
   active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
   ASSERT_EQ(4u, active_layer_->tilings()->num_tilings());
 
-  // Now move the ideal scale to 0.5.
+  // Now move the ideal scale to 0.5. Our target stays 1.2.
   SetContentsScaleOnBothLayers(0.5f, 1.f, page_scale, 1.f, 0.f, false);
-  ASSERT_EQ(6u, active_layer_->tilings()->num_tilings());
 
-  // And begin an animation to 1.2. There are now 3 tilings, 0.5, 1.0 and 1.2.
-  // The the 0.5 is ideal, but the 1.2 is high res. 1.0 sits between them.
-  // high-res tiling is in the middle. There are also ex-low-res tilings paired
-  // with each of the 3 tilings mentioned here, but since we're animating none
-  // are marked as LOW_RESOLUTION.
-  SetContentsScaleOnBothLayers(0.5, 1.f, page_scale, 1.2f, 0.f, true);
-  ASSERT_EQ(6u, active_layer_->tilings()->num_tilings());
-  EXPECT_EQ(HIGH_RESOLUTION,
-            active_layer_->tilings()->tiling_at(0)->resolution());
-  EXPECT_EQ(1.2f,  // High-res, though not the ideal scale.
-            active_layer_->tilings()->tiling_at(0)->contents_scale());
-  EXPECT_EQ(1.f,  // Tiling in the middle attack.
-            active_layer_->tilings()->tiling_at(1)->contents_scale());
-  EXPECT_EQ(0.5f,  // Ideal scale, but not considered high-res.
-            active_layer_->tilings()->tiling_at(2)->contents_scale());
-
-  EXPECT_EQ(NON_IDEAL_RESOLUTION,
-            active_layer_->tilings()->tiling_at(1)->resolution());
-  EXPECT_EQ(NON_IDEAL_RESOLUTION,
-            active_layer_->tilings()->tiling_at(2)->resolution());
-  EXPECT_EQ(NON_IDEAL_RESOLUTION,
-            active_layer_->tilings()->tiling_at(3)->resolution());
-  EXPECT_EQ(NON_IDEAL_RESOLUTION,
-            active_layer_->tilings()->tiling_at(4)->resolution());
-  EXPECT_EQ(NON_IDEAL_RESOLUTION,
-            active_layer_->tilings()->tiling_at(5)->resolution());
-
-  EXPECT_EQ(1.2f * low_res_factor,  // Low-res, paired with current high-res.
-            active_layer_->tilings()->tiling_at(3)->contents_scale());
-  EXPECT_EQ(1.f * low_res_factor,  // Ex-low-res, paired with the middle one.
-            active_layer_->tilings()->tiling_at(4)->contents_scale());
-  EXPECT_EQ(0.5f * low_res_factor,  // Ex-low-res, paired with current ideal.
-            active_layer_->tilings()->tiling_at(5)->contents_scale());
-
-  // The high resolution tiling is between target and ideal, so is not removed.
-  // The ex-low-res tilings are all smaller scale, so they are removed.
+  // The high resolution tiling is between target and ideal, so is not
+  // removed.  The low res tiling for the old ideal=1.0 scale is removed.
   used_tilings.clear();
   active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
   ASSERT_EQ(3u, active_layer_->tilings()->num_tilings());
 
-  // Now move the ideal scale to 1.0 on the active layer. The high-res tiling
-  // stays 1.2.
-  SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, page_scale, 1.2f,
-                                    0.f, true);
+  // Now move the ideal scale to 1.0. Our target stays 1.2.
+  SetContentsScaleOnBothLayers(1.f, 1.f, page_scale, 1.f, 0.f, false);
 
   // All the tilings are between are target and the ideal, so they are not
-  // Because the pending layer's ideal scale is still 0.5, all tilings fall
-  // in the range [0.5,1.2] and are kept.
+  // removed.
   used_tilings.clear();
   active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
   ASSERT_EQ(3u, active_layer_->tilings()->num_tilings());
 
-  // Move the ideal scale on the pending layer to 1.0 as well. Our high-res
-  // stays 1.2 still.
-  SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, page_scale, 1.f,
+  // Now move the ideal scale to 1.1 on the active layer. Our target stays 1.2.
+  SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.1f, 1.f, page_scale, 1.f,
                                     0.f, false);
 
-  // Our 0.5 tiling now falls outside the range between our ideal scale and our
-  // high-res raster scale. But it is in our used tilings set, so nothing is
+  // Because the pending layer's ideal scale is still 1.0, our tilings fall
+  // in the range [1.0,1.2] and are kept.
+  used_tilings.clear();
+  active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+  ASSERT_EQ(3u, active_layer_->tilings()->num_tilings());
+
+  // Move the ideal scale on the pending layer to 1.1 as well. Our target stays
+  // 1.2 still.
+  SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.1f, 1.f, page_scale, 1.f,
+                                    0.f, false);
+
+  // Our 1.0 tiling now falls outside the range between our ideal scale and our
+  // target raster scale. But it is in our used tilings set, so nothing is
   // deleted.
   used_tilings.clear();
-  used_tilings.push_back(active_layer_->tilings()->tiling_at(2));
+  used_tilings.push_back(active_layer_->tilings()->tiling_at(1));
   active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
   ASSERT_EQ(3u, active_layer_->tilings()->num_tilings());
 
@@ -1278,6 +1250,7 @@
   EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), contents_scale);
   EXPECT_BOTH_EQ(num_tilings(), 1u);
 
+  // TODO(danakj): Remove these when raster scale doesn't get fixed?
   ResetTilingsAndRasterScales();
 
   // Any content bounds that would create more than one tile will
@@ -1306,6 +1279,11 @@
 
   FakePictureLayerImpl* mask_raw =
       static_cast<FakePictureLayerImpl*>(pending_layer_->mask_layer());
+  // We did an UpdateDrawProperties above, which will set a contents scale on
+  // the mask layer, so allow us to reset the contents scale.
+  mask_raw->ReleaseResources();
+  mask_raw->RecreateResources();
+
   SetupDrawPropertiesAndUpdateTiles(
       mask_raw, contents_scale, device_scale, page_scale,
       maximum_animation_scale, starting_animation_scale, animating_transform);
@@ -1979,9 +1957,8 @@
   gfx::Size viewport_size(400, 400);
 
   host_impl_.SetViewportSize(viewport_size);
-
-  // Start with an ideal and raster contents scale of 2.
   SetInitialDeviceScaleFactor(2.f);
+
   SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region());
 
   // One ideal tile exists, this will get used when drawing.
@@ -1991,17 +1968,18 @@
   host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(
       ideal_tiles);
 
-  // Due to the animation, the raster contents scale moves to 1, while the
-  // ideal will still be 2.
+  // Due to layer scale throttling, the raster contents scale is changed to 1,
+  // while the ideal is still 2.
+  SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, 0.f,
+                                    false);
   SetupDrawPropertiesAndUpdateTiles(active_layer_, 2.f, 1.f, 1.f, 1.f, 0.f,
-                                    true);
+                                    false);
 
   EXPECT_EQ(1.f, active_layer_->HighResTiling()->contents_scale());
   EXPECT_EQ(1.f, active_layer_->raster_contents_scale());
   EXPECT_EQ(2.f, active_layer_->ideal_contents_scale());
 
   // Both tilings still exist.
-  ASSERT_GE(active_layer_->tilings()->num_tilings(), 2u);
   EXPECT_EQ(2.f, active_layer_->tilings()->tiling_at(0)->contents_scale());
   EXPECT_EQ(1.f, active_layer_->tilings()->tiling_at(1)->contents_scale());
 
@@ -3267,22 +3245,23 @@
                                starting_animation_scale, animating_transform);
   EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);
 
-  // Changing the source scale without being in an animation should be
-  // immediately honored.
+  // Changing the source scale without being in an animation will cause
+  // the layer to reset its source scale to 1.f.
   contents_scale = 3.f;
 
   SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
                                maximum_animation_scale,
                                starting_animation_scale, animating_transform);
-  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);
 
-  // Further changes to the source scale will continue to be honored.
+  // Further changes to the source scale will no longer be reflected in the
+  // contents scale.
   contents_scale = 0.5f;
 
   SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
                                maximum_animation_scale,
                                starting_animation_scale, animating_transform);
-  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 0.5f);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);
 }
 
 TEST_F(PictureLayerImplTest, LowResReadyToDrawNotEnoughToActivate) {
@@ -3582,58 +3561,52 @@
   active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
   ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
 
-  // Now move the ideal scale to 0.5.
+  // Now move the ideal scale to 0.5. Our target stays 1.2.
   SetContentsScaleOnBothLayers(0.5f, device_scale, page_scale, 1.f, 0.f, false);
-  ASSERT_EQ(3u, active_layer_->tilings()->num_tilings());
-
-  // And begin an animation to 1.2. There are now 3 tilings, 0.5, 1.0 and 1.2.
-  // The the 0.5 is ideal, but the 1.2 is high res. 1.0 sits between them.
-  // high-res tiling is in the middle.
-  SetContentsScaleOnBothLayers(0.5, device_scale, page_scale, 1.2f, 0.f, true);
-  EXPECT_EQ(HIGH_RESOLUTION,
-            active_layer_->tilings()->tiling_at(0)->resolution());
-  EXPECT_EQ(1.2f,  // High-res, though not the ideal scale.
-            active_layer_->tilings()->tiling_at(0)->contents_scale());
-  EXPECT_EQ(1.f,  // Tiling in the middle attack.
-            active_layer_->tilings()->tiling_at(1)->contents_scale());
-  EXPECT_EQ(0.5f,  // Ideal scale, but not considered high-res.
-            active_layer_->tilings()->tiling_at(2)->contents_scale());
 
   // The high resolution tiling is between target and ideal, so is not
+  // removed.  The low res tiling for the old ideal=1.0 scale is removed.
+  used_tilings.clear();
+  active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+  ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
+
+  // Now move the ideal scale to 1.0. Our target stays 1.2.
+  SetContentsScaleOnBothLayers(1.f, device_scale, page_scale, 1.f, 0.f, false);
+
+  // All the tilings are between are target and the ideal, so they are not
   // removed.
   used_tilings.clear();
   active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
-  ASSERT_EQ(3u, active_layer_->tilings()->num_tilings());
+  ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
 
-  // Now move the ideal scale to 1.0 on the active layer. The high-res tiling
-  // stays 1.2.
-  SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, device_scale,
-                                    page_scale, 1.2f, 0.f, true);
-
-  // Because the pending layer's ideal scale is still 0.5, all tilings fall
-  // in the range [0.5,1.2] and are kept.
-  used_tilings.clear();
-  active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
-  ASSERT_EQ(3u, active_layer_->tilings()->num_tilings());
-
-  // Move the ideal scale on the pending layer to 1.0 as well. Our high-res
-  // stays 1.2 still.
-  SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, device_scale,
+  // Now move the ideal scale to 1.1 on the active layer. Our target stays 1.2.
+  SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.1f, device_scale,
                                     page_scale, 1.f, 0.f, false);
 
-  // Our 0.5 tiling now falls outside the range between our ideal scale and our
-  // high-res raster scale. But it is in our used tilings set, so nothing is
+  // Because the pending layer's ideal scale is still 1.0, our tilings fall
+  // in the range [1.0,1.2] and are kept.
+  used_tilings.clear();
+  active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+  ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
+
+  // Move the ideal scale on the pending layer to 1.1 as well. Our target stays
+  // 1.2 still.
+  SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.1f, device_scale,
+                                    page_scale, 1.f, 0.f, false);
+
+  // Our 1.0 tiling now falls outside the range between our ideal scale and our
+  // target raster scale. But it is in our used tilings set, so nothing is
   // deleted.
   used_tilings.clear();
-  used_tilings.push_back(active_layer_->tilings()->tiling_at(2));
+  used_tilings.push_back(active_layer_->tilings()->tiling_at(1));
   active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
-  ASSERT_EQ(3u, active_layer_->tilings()->num_tilings());
+  ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
 
   // If we remove it from our used tilings set, it is outside the range to keep
   // so it is deleted.
   used_tilings.clear();
   active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
-  ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
+  ASSERT_EQ(1u, active_layer_->tilings()->num_tilings());
 }
 
 TEST_F(NoLowResPictureLayerImplTest, ReleaseResources) {
diff --git a/cc/output/context_provider.cc b/cc/output/context_provider.cc
deleted file mode 100644
index 5ff7f930..0000000
--- a/cc/output/context_provider.cc
+++ /dev/null
@@ -1,16 +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 "cc/output/context_provider.h"
-
-#include <stddef.h>
-
-#include <limits>
-
-namespace cc {
-
-ContextProvider::Capabilities::Capabilities()
-    : max_transfer_buffer_usage_bytes(std::numeric_limits<size_t>::max()) {}
-
-}  // namespace cc
diff --git a/cc/output/context_provider.h b/cc/output/context_provider.h
index c560ad0f..7fe7dbe 100644
--- a/cc/output/context_provider.h
+++ b/cc/output/context_provider.h
@@ -64,13 +64,6 @@
   virtual gpu::ContextSupport* ContextSupport() = 0;
   virtual class GrContext* GrContext() = 0;
 
-  struct Capabilities {
-    gpu::Capabilities gpu;
-    size_t max_transfer_buffer_usage_bytes;
-
-    CC_EXPORT Capabilities();
-  };
-
   // Invalidates the cached OpenGL state in GrContext.
   // See skia GrContext::resetContext for details.
   virtual void InvalidateGrContext(uint32_t state) = 0;
@@ -85,7 +78,7 @@
   virtual base::Lock* GetLock() = 0;
 
   // Returns the capabilities of the currently bound 3d context.
-  virtual Capabilities ContextCapabilities() = 0;
+  virtual gpu::Capabilities ContextCapabilities() = 0;
 
   // Delete all cached gpu resources.
   virtual void DeleteCachedResources() = 0;
diff --git a/cc/output/delegating_renderer.cc b/cc/output/delegating_renderer.cc
index a3746cc..c063c7f 100644
--- a/cc/output/delegating_renderer.cc
+++ b/cc/output/delegating_renderer.cc
@@ -48,22 +48,22 @@
   if (!output_surface_->context_provider()) {
     capabilities_.using_shared_memory_resources = true;
   } else {
-    const ContextProvider::Capabilities& caps =
+    const auto& caps =
         output_surface_->context_provider()->ContextCapabilities();
 
-    DCHECK(!caps.gpu.iosurface || caps.gpu.texture_rectangle);
+    DCHECK(!caps.iosurface || caps.texture_rectangle);
 
-    capabilities_.using_egl_image = caps.gpu.egl_image_external;
-    capabilities_.using_image = caps.gpu.image;
+    capabilities_.using_egl_image = caps.egl_image_external;
+    capabilities_.using_image = caps.image;
 
     capabilities_.allow_rasterize_on_demand = false;
 
     // If MSAA is slow, we want this renderer to behave as though MSAA is not
     // available. Set samples to 0 to achieve this.
-    if (caps.gpu.msaa_is_slow)
+    if (caps.msaa_is_slow)
       capabilities_.max_msaa_samples = 0;
     else
-      capabilities_.max_msaa_samples = caps.gpu.max_samples;
+      capabilities_.max_msaa_samples = caps.max_samples;
   }
 }
 
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 414ffc0..bc405a3 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -337,17 +337,17 @@
   DCHECK(gl_);
   DCHECK(context_support_);
 
-  ContextProvider::Capabilities context_caps =
+  const auto& context_caps =
       output_surface_->context_provider()->ContextCapabilities();
 
   capabilities_.using_partial_swap =
-      settings_->partial_swap_enabled && context_caps.gpu.post_sub_buffer;
-  capabilities_.allow_empty_swap = capabilities_.using_partial_swap ||
-                                   context_caps.gpu.commit_overlay_planes;
+      settings_->partial_swap_enabled && context_caps.post_sub_buffer;
+  capabilities_.allow_empty_swap =
+      capabilities_.using_partial_swap || context_caps.commit_overlay_planes;
 
-  DCHECK(!context_caps.gpu.iosurface || context_caps.gpu.texture_rectangle);
+  DCHECK(!context_caps.iosurface || context_caps.texture_rectangle);
 
-  capabilities_.using_egl_image = context_caps.gpu.egl_image_external;
+  capabilities_.using_egl_image = context_caps.egl_image_external;
 
   capabilities_.max_texture_size = resource_provider_->max_texture_size();
   capabilities_.best_texture_format = resource_provider_->best_texture_format();
@@ -355,24 +355,23 @@
   // The updater can access textures while the GLRenderer is using them.
   capabilities_.allow_partial_texture_updates = true;
 
-  capabilities_.using_image = context_caps.gpu.image;
+  capabilities_.using_image = context_caps.image;
 
-  capabilities_.using_discard_framebuffer =
-      context_caps.gpu.discard_framebuffer;
+  capabilities_.using_discard_framebuffer = context_caps.discard_framebuffer;
 
   capabilities_.allow_rasterize_on_demand = true;
 
   // If MSAA is slow, we want this renderer to behave as though MSAA is not
   // available. Set samples to 0 to achieve this.
-  if (context_caps.gpu.msaa_is_slow)
+  if (context_caps.msaa_is_slow)
     capabilities_.max_msaa_samples = 0;
   else
-    capabilities_.max_msaa_samples = context_caps.gpu.max_samples;
+    capabilities_.max_msaa_samples = context_caps.max_samples;
 
-  use_sync_query_ = context_caps.gpu.sync_query;
-  use_blend_equation_advanced_ = context_caps.gpu.blend_equation_advanced;
+  use_sync_query_ = context_caps.sync_query;
+  use_blend_equation_advanced_ = context_caps.blend_equation_advanced;
   use_blend_equation_advanced_coherent_ =
-      context_caps.gpu.blend_equation_advanced_coherent;
+      context_caps.blend_equation_advanced_coherent;
 
   InitializeSharedObjects();
 }
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc
index 2a533d7..6f32dd0 100644
--- a/cc/output/gl_renderer_unittest.cc
+++ b/cc/output/gl_renderer_unittest.cc
@@ -725,7 +725,7 @@
 
 class ClearCountingContext : public TestWebGraphicsContext3D {
  public:
-  ClearCountingContext() { test_capabilities_.gpu.discard_framebuffer = true; }
+  ClearCountingContext() { test_capabilities_.discard_framebuffer = true; }
 
   MOCK_METHOD3(discardFramebufferEXT,
                void(GLenum target,
@@ -862,7 +862,7 @@
 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
  public:
   TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM) {
-    test_capabilities_.gpu.egl_image_external = true;
+    test_capabilities_.egl_image_external = true;
   }
 
   MOCK_METHOD1(waitSyncToken, void(const GLbyte* sync_token));
@@ -1749,7 +1749,7 @@
 
 class OutputSurfaceMockContext : public TestWebGraphicsContext3D {
  public:
-  OutputSurfaceMockContext() { test_capabilities_.gpu.post_sub_buffer = true; }
+  OutputSurfaceMockContext() { test_capabilities_.post_sub_buffer = true; }
 
   // Specifically override methods even if they are unused (used in conjunction
   // with StrictMock). We need to make sure that GLRenderer does not issue
diff --git a/cc/raster/bitmap_tile_task_worker_pool.cc b/cc/raster/bitmap_tile_task_worker_pool.cc
index 7a29df2..c08bdcd 100644
--- a/cc/raster/bitmap_tile_task_worker_pool.cc
+++ b/cc/raster/bitmap_tile_task_worker_pool.cc
@@ -87,10 +87,6 @@
 BitmapTileTaskWorkerPool::~BitmapTileTaskWorkerPool() {
 }
 
-TileTaskRunner* BitmapTileTaskWorkerPool::AsTileTaskRunner() {
-  return this;
-}
-
 void BitmapTileTaskWorkerPool::Shutdown() {
   TRACE_EVENT0("cc", "BitmapTileTaskWorkerPool::Shutdown");
 
diff --git a/cc/raster/bitmap_tile_task_worker_pool.h b/cc/raster/bitmap_tile_task_worker_pool.h
index 0a492a9b..5d7e409 100644
--- a/cc/raster/bitmap_tile_task_worker_pool.h
+++ b/cc/raster/bitmap_tile_task_worker_pool.h
@@ -9,7 +9,6 @@
 
 #include "base/macros.h"
 #include "base/values.h"
-#include "cc/raster/tile_task_runner.h"
 #include "cc/raster/tile_task_worker_pool.h"
 
 namespace base {
@@ -22,7 +21,6 @@
 class ResourceProvider;
 
 class CC_EXPORT BitmapTileTaskWorkerPool : public TileTaskWorkerPool,
-                                           public TileTaskRunner,
                                            public RasterBufferProvider {
  public:
   ~BitmapTileTaskWorkerPool() override;
@@ -33,9 +31,6 @@
       ResourceProvider* resource_provider);
 
   // Overridden from TileTaskWorkerPool:
-  TileTaskRunner* AsTileTaskRunner() override;
-
-  // Overridden from TileTaskRunner:
   void Shutdown() override;
   void ScheduleTasks(TaskGraph* graph) override;
   void CheckForCompletedTasks() override;
diff --git a/cc/raster/gpu_tile_task_worker_pool.cc b/cc/raster/gpu_tile_task_worker_pool.cc
index f34cf7af..c1f82d1b 100644
--- a/cc/raster/gpu_tile_task_worker_pool.cc
+++ b/cc/raster/gpu_tile_task_worker_pool.cc
@@ -120,10 +120,6 @@
   DCHECK_EQ(0u, completed_tasks_.size());
 }
 
-TileTaskRunner* GpuTileTaskWorkerPool::AsTileTaskRunner() {
-  return this;
-}
-
 void GpuTileTaskWorkerPool::Shutdown() {
   TRACE_EVENT0("cc", "GpuTileTaskWorkerPool::Shutdown");
 
diff --git a/cc/raster/gpu_tile_task_worker_pool.h b/cc/raster/gpu_tile_task_worker_pool.h
index 5ebd623..a0a7291 100644
--- a/cc/raster/gpu_tile_task_worker_pool.h
+++ b/cc/raster/gpu_tile_task_worker_pool.h
@@ -8,7 +8,6 @@
 #include <stdint.h>
 
 #include "base/macros.h"
-#include "cc/raster/tile_task_runner.h"
 #include "cc/raster/tile_task_worker_pool.h"
 
 namespace cc {
@@ -17,7 +16,6 @@
 class ResourceProvider;
 
 class CC_EXPORT GpuTileTaskWorkerPool : public TileTaskWorkerPool,
-                                        public TileTaskRunner,
                                         public RasterBufferProvider {
  public:
   ~GpuTileTaskWorkerPool() override;
@@ -31,9 +29,6 @@
       int gpu_rasterization_msaa_sample_count);
 
   // Overridden from TileTaskWorkerPool:
-  TileTaskRunner* AsTileTaskRunner() override;
-
-  // Overridden from TileTaskRunner:
   void Shutdown() override;
   void ScheduleTasks(TaskGraph* graph) override;
   void CheckForCompletedTasks() override;
diff --git a/cc/raster/one_copy_tile_task_worker_pool.cc b/cc/raster/one_copy_tile_task_worker_pool.cc
index de1ab4d..5ee2e9bb 100644
--- a/cc/raster/one_copy_tile_task_worker_pool.cc
+++ b/cc/raster/one_copy_tile_task_worker_pool.cc
@@ -110,10 +110,6 @@
 OneCopyTileTaskWorkerPool::~OneCopyTileTaskWorkerPool() {
 }
 
-TileTaskRunner* OneCopyTileTaskWorkerPool::AsTileTaskRunner() {
-  return this;
-}
-
 void OneCopyTileTaskWorkerPool::Shutdown() {
   TRACE_EVENT0("cc", "OneCopyTileTaskWorkerPool::Shutdown");
 
diff --git a/cc/raster/one_copy_tile_task_worker_pool.h b/cc/raster/one_copy_tile_task_worker_pool.h
index 5d6162d..da41020e 100644
--- a/cc/raster/one_copy_tile_task_worker_pool.h
+++ b/cc/raster/one_copy_tile_task_worker_pool.h
@@ -9,7 +9,6 @@
 
 #include "base/macros.h"
 #include "cc/output/context_provider.h"
-#include "cc/raster/tile_task_runner.h"
 #include "cc/raster/tile_task_worker_pool.h"
 #include "cc/resources/resource_provider.h"
 
@@ -19,7 +18,6 @@
 class ResourcePool;
 
 class CC_EXPORT OneCopyTileTaskWorkerPool : public TileTaskWorkerPool,
-                                            public TileTaskRunner,
                                             public RasterBufferProvider {
  public:
   ~OneCopyTileTaskWorkerPool() override;
@@ -35,9 +33,6 @@
       ResourceFormat preferred_tile_format);
 
   // Overridden from TileTaskWorkerPool:
-  TileTaskRunner* AsTileTaskRunner() override;
-
-  // Overridden from TileTaskRunner:
   void Shutdown() override;
   void ScheduleTasks(TaskGraph* graph) override;
   void CheckForCompletedTasks() override;
diff --git a/cc/raster/tile_task_runner.cc b/cc/raster/tile_task.cc
similarity index 67%
rename from cc/raster/tile_task_runner.cc
rename to cc/raster/tile_task.cc
index fde8ad80..7b44a8e 100644
--- a/cc/raster/tile_task_runner.cc
+++ b/cc/raster/tile_task.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.
 
-#include "cc/raster/tile_task_runner.h"
-#include "cc/resources/platform_color.h"
+#include "cc/raster/tile_task.h"
+
+#include "base/logging.h"
 
 namespace cc {
 
@@ -52,24 +53,4 @@
   return did_complete_;
 }
 
-bool TileTaskRunner::ResourceFormatRequiresSwizzle(ResourceFormat format) {
-  switch (format) {
-    case RGBA_8888:
-    case BGRA_8888:
-      // Initialize resource using the preferred PlatformColor component
-      // order and swizzle in the shader instead of in software.
-      return !PlatformColor::SameComponentOrder(format);
-    case RGBA_4444:
-    case ETC1:
-    case ALPHA_8:
-    case LUMINANCE_8:
-    case RGB_565:
-    case RED_8:
-    case LUMINANCE_F16:
-      return false;
-  }
-  NOTREACHED();
-  return false;
-}
-
 }  // namespace cc
diff --git a/cc/raster/tile_task.h b/cc/raster/tile_task.h
new file mode 100644
index 0000000..7b0f84e
--- /dev/null
+++ b/cc/raster/tile_task.h
@@ -0,0 +1,52 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_RASTER_TILE_TASK_H_
+#define CC_RASTER_TILE_TASK_H_
+
+#include <vector>
+
+#include "cc/raster/task.h"
+
+namespace cc {
+class RasterBufferProvider;
+
+class CC_EXPORT TileTask : public Task {
+ public:
+  typedef std::vector<scoped_refptr<TileTask>> Vector;
+
+  const TileTask::Vector& dependencies() const { return dependencies_; }
+
+  // Indicates whether this TileTask can be run at the same time as other tasks
+  // in the task graph. If false, this task will be scheduled with
+  // TASK_CATEGORY_NONCONCURRENT_FOREGROUND.
+  bool supports_concurrent_execution() const {
+    return supports_concurrent_execution_;
+  }
+
+  virtual void ScheduleOnOriginThread(RasterBufferProvider* provider) = 0;
+  virtual void CompleteOnOriginThread(RasterBufferProvider* provider) = 0;
+
+  void WillSchedule();
+  void DidSchedule();
+  bool HasBeenScheduled() const;
+
+  void WillComplete();
+  void DidComplete();
+  bool HasCompleted() const;
+
+ protected:
+  explicit TileTask(bool supports_concurrent_execution);
+  TileTask(bool supports_concurrent_execution, TileTask::Vector* dependencies);
+  ~TileTask() override;
+
+  const bool supports_concurrent_execution_;
+  TileTask::Vector dependencies_;
+  bool did_schedule_;
+  bool did_complete_;
+};
+
+}  // namespace cc
+
+#endif  // CC_RASTER_TILE_TASK_H_
diff --git a/cc/raster/tile_task_runner.h b/cc/raster/tile_task_runner.h
deleted file mode 100644
index 3bda3ad..0000000
--- a/cc/raster/tile_task_runner.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_RASTER_TILE_TASK_RUNNER_H_
-#define CC_RASTER_TILE_TASK_RUNNER_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/callback.h"
-#include "cc/raster/raster_buffer.h"
-#include "cc/raster/task.h"
-#include "cc/resources/resource_format.h"
-
-namespace cc {
-
-class CC_EXPORT TileTask : public Task {
- public:
-  typedef std::vector<scoped_refptr<TileTask>> Vector;
-
-  const TileTask::Vector& dependencies() const { return dependencies_; }
-
-  // Indicates whether this TileTask can be run at the same time as other tasks
-  // in the task graph. If false, this task will be scheduled with
-  // TASK_CATEGORY_NONCONCURRENT_FOREGROUND. The base implementation always
-  // returns true.
-  bool SupportsConcurrentExecution() const {
-    return supports_concurrent_execution_;
-  }
-
-  virtual void ScheduleOnOriginThread(RasterBufferProvider* provider) = 0;
-  virtual void CompleteOnOriginThread(RasterBufferProvider* provider) = 0;
-
-  void WillSchedule();
-  void DidSchedule();
-  bool HasBeenScheduled() const;
-
-  void WillComplete();
-  void DidComplete();
-  bool HasCompleted() const;
-
- protected:
-  explicit TileTask(bool supports_concurrent_execution);
-  TileTask(bool supports_concurrent_execution, TileTask::Vector* dependencies);
-  ~TileTask() override;
-
-  const bool supports_concurrent_execution_;
-  TileTask::Vector dependencies_;
-  bool did_schedule_;
-  bool did_complete_;
-};
-
-// This interface can be used to schedule and run tile tasks.
-// The client can call CheckForCompletedTasks() at any time to dispatch
-// pending completion callbacks for all tasks that have finished running.
-class CC_EXPORT TileTaskRunner {
- public:
-  // Tells the worker pool to shutdown after canceling all previously scheduled
-  // tasks. Reply callbacks are still guaranteed to run when
-  // CheckForCompletedTasks() is called.
-  virtual void Shutdown() = 0;
-
-  // Schedule running of tile tasks in |graph| and all dependencies.
-  // Previously scheduled tasks that are not in |graph| will be canceled unless
-  // already running. Once scheduled, reply callbacks are guaranteed to run for
-  // all tasks even if they later get canceled by another call to
-  // ScheduleTasks().
-  virtual void ScheduleTasks(TaskGraph* graph) = 0;
-
-  // Check for completed tasks and dispatch reply callbacks.
-  virtual void CheckForCompletedTasks() = 0;
-
-  // Returns the format to use for the tiles.
-  virtual ResourceFormat GetResourceFormat(bool must_support_alpha) const = 0;
-
-  // Determine if the resource requires swizzling.
-  virtual bool GetResourceRequiresSwizzle(bool must_support_alpha) const = 0;
-
-  // Downcasting routine for RasterBufferProvider interface.
-  virtual RasterBufferProvider* AsRasterBufferProvider() = 0;
-
- protected:
-  // Check if resource format matches output format.
-  static bool ResourceFormatRequiresSwizzle(ResourceFormat format);
-
-  virtual ~TileTaskRunner() {}
-};
-
-}  // namespace cc
-
-#endif  // CC_RASTER_TILE_TASK_RUNNER_H_
diff --git a/cc/raster/tile_task_worker_pool.cc b/cc/raster/tile_task_worker_pool.cc
index 1e41942..b14cd836 100644
--- a/cc/raster/tile_task_worker_pool.cc
+++ b/cc/raster/tile_task_worker_pool.cc
@@ -9,6 +9,7 @@
 #include "base/trace_event/trace_event.h"
 #include "cc/playback/raster_source.h"
 #include "cc/raster/texture_compressor.h"
+#include "cc/resources/platform_color.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkSurface.h"
 
@@ -145,4 +146,24 @@
   NOTREACHED();
 }
 
+bool TileTaskWorkerPool::ResourceFormatRequiresSwizzle(ResourceFormat format) {
+  switch (format) {
+    case RGBA_8888:
+    case BGRA_8888:
+      // Initialize resource using the preferred PlatformColor component
+      // order and swizzle in the shader instead of in software.
+      return !PlatformColor::SameComponentOrder(format);
+    case RGBA_4444:
+    case ETC1:
+    case ALPHA_8:
+    case LUMINANCE_8:
+    case RGB_565:
+    case RED_8:
+    case LUMINANCE_F16:
+      return false;
+  }
+  NOTREACHED();
+  return false;
+}
+
 }  // namespace cc
diff --git a/cc/raster/tile_task_worker_pool.h b/cc/raster/tile_task_worker_pool.h
index f4e675c..9542d02 100644
--- a/cc/raster/tile_task_worker_pool.h
+++ b/cc/raster/tile_task_worker_pool.h
@@ -8,8 +8,10 @@
 #include <stddef.h>
 
 #include "cc/playback/raster_source.h"
+#include "cc/raster/raster_buffer.h"
 #include "cc/raster/task_graph_runner.h"
-#include "cc/raster/tile_task_runner.h"
+#include "cc/raster/tile_task.h"
+#include "cc/resources/resource_format.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 
@@ -20,6 +22,10 @@
 namespace cc {
 class RenderingStatsInstrumentation;
 
+// This class provides the wrapper over TaskGraphRunner for scheduling and
+// collecting tasks. The client can call CheckForCompletedTasks() at any time to
+// process all completed tasks at the moment that have finished running or
+// cancelled.
 class CC_EXPORT TileTaskWorkerPool {
  public:
   TileTaskWorkerPool();
@@ -47,8 +53,33 @@
       float scale,
       const RasterSource::PlaybackSettings& playback_settings);
 
-  // Type-checking downcast routine.
-  virtual TileTaskRunner* AsTileTaskRunner() = 0;
+  // Tells the worker pool to shutdown after canceling all previously scheduled
+  // tasks. Reply callbacks are still guaranteed to run when
+  // CheckForCompletedTasks() is called.
+  virtual void Shutdown() = 0;
+
+  // Schedule running of tile tasks in |graph| and all dependencies.
+  // Previously scheduled tasks that are not in |graph| will be canceled unless
+  // already running. Once scheduled, reply callbacks are guaranteed to run for
+  // all tasks even if they later get canceled by another call to
+  // ScheduleTasks().
+  virtual void ScheduleTasks(TaskGraph* graph) = 0;
+
+  // Check for completed tasks and dispatch reply callbacks.
+  virtual void CheckForCompletedTasks() = 0;
+
+  // Returns the format to use for the tiles.
+  virtual ResourceFormat GetResourceFormat(bool must_support_alpha) const = 0;
+
+  // Determine if the resource requires swizzling.
+  virtual bool GetResourceRequiresSwizzle(bool must_support_alpha) const = 0;
+
+  // Downcasting routine for RasterBufferProvider interface.
+  virtual RasterBufferProvider* AsRasterBufferProvider() = 0;
+
+ protected:
+  // Check if resource format matches output format.
+  static bool ResourceFormatRequiresSwizzle(ResourceFormat format);
 };
 
 }  // namespace cc
diff --git a/cc/raster/tile_task_worker_pool_perftest.cc b/cc/raster/tile_task_worker_pool_perftest.cc
index 04922d68..b41343f 100644
--- a/cc/raster/tile_task_worker_pool_perftest.cc
+++ b/cc/raster/tile_task_worker_pool_perftest.cc
@@ -16,7 +16,6 @@
 #include "cc/raster/gpu_tile_task_worker_pool.h"
 #include "cc/raster/one_copy_tile_task_worker_pool.h"
 #include "cc/raster/synchronous_task_graph_runner.h"
-#include "cc/raster/tile_task_runner.h"
 #include "cc/raster/tile_task_worker_pool.h"
 #include "cc/raster/zero_copy_tile_task_worker_pool.h"
 #include "cc/resources/resource_pool.h"
@@ -75,10 +74,10 @@
   PerfContextProvider() : context_gl_(new PerfGLES2Interface) {}
 
   bool BindToCurrentThread() override { return true; }
-  Capabilities ContextCapabilities() override {
-    Capabilities capabilities;
-    capabilities.gpu.image = true;
-    capabilities.gpu.sync_query = true;
+  gpu::Capabilities ContextCapabilities() override {
+    gpu::Capabilities capabilities;
+    capabilities.image = true;
+    capabilities.sync_query = true;
     return capabilities;
   }
   gpu::gles2::GLES2Interface* ContextGL() override { return context_gl_.get(); }
@@ -288,8 +287,8 @@
     DCHECK(tile_task_worker_pool_);
   }
   void TearDown() override {
-    tile_task_worker_pool_->AsTileTaskRunner()->Shutdown();
-    tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
+    tile_task_worker_pool_->Shutdown();
+    tile_task_worker_pool_->CheckForCompletedTasks();
   }
 
   void RunMessageLoopUntilAllTasksHaveCompleted() {
@@ -312,13 +311,13 @@
     do {
       graph.Reset();
       BuildTileTaskGraph(&graph, raster_tasks);
-      tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&graph);
-      tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
+      tile_task_worker_pool_->ScheduleTasks(&graph);
+      tile_task_worker_pool_->CheckForCompletedTasks();
       timer_.NextLap();
     } while (!timer_.HasTimeLimitExpired());
 
     TaskGraph empty;
-    tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&empty);
+    tile_task_worker_pool_->ScheduleTasks(&empty);
     RunMessageLoopUntilAllTasksHaveCompleted();
 
     perf_test::PrintResult("schedule_tasks", TestModifierString(), test_name,
@@ -345,14 +344,14 @@
     do {
       graph.Reset();
       BuildTileTaskGraph(&graph, raster_tasks[count % kNumVersions]);
-      tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&graph);
-      tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
+      tile_task_worker_pool_->ScheduleTasks(&graph);
+      tile_task_worker_pool_->CheckForCompletedTasks();
       ++count;
       timer_.NextLap();
     } while (!timer_.HasTimeLimitExpired());
 
     TaskGraph empty;
-    tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&empty);
+    tile_task_worker_pool_->ScheduleTasks(&empty);
     RunMessageLoopUntilAllTasksHaveCompleted();
 
     perf_test::PrintResult("schedule_alternate_tasks", TestModifierString(),
@@ -374,13 +373,13 @@
     do {
       graph.Reset();
       BuildTileTaskGraph(&graph, raster_tasks);
-      tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&graph);
+      tile_task_worker_pool_->ScheduleTasks(&graph);
       RunMessageLoopUntilAllTasksHaveCompleted();
       timer_.NextLap();
     } while (!timer_.HasTimeLimitExpired());
 
     TaskGraph empty;
-    tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&empty);
+    tile_task_worker_pool_->ScheduleTasks(&empty);
     RunMessageLoopUntilAllTasksHaveCompleted();
 
     perf_test::PrintResult("schedule_and_execute_tasks", TestModifierString(),
diff --git a/cc/raster/tile_task_worker_pool_unittest.cc b/cc/raster/tile_task_worker_pool_unittest.cc
index 03f835c..caf7c93 100644
--- a/cc/raster/tile_task_worker_pool_unittest.cc
+++ b/cc/raster/tile_task_worker_pool_unittest.cc
@@ -23,7 +23,6 @@
 #include "cc/raster/gpu_tile_task_worker_pool.h"
 #include "cc/raster/one_copy_tile_task_worker_pool.h"
 #include "cc/raster/synchronous_task_graph_runner.h"
-#include "cc/raster/tile_task_runner.h"
 #include "cc/raster/zero_copy_tile_task_worker_pool.h"
 #include "cc/resources/resource_pool.h"
 #include "cc/resources/resource_provider.h"
@@ -175,18 +174,18 @@
   }
 
   void TearDown() override {
-    tile_task_worker_pool_->AsTileTaskRunner()->Shutdown();
-    tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
+    tile_task_worker_pool_->Shutdown();
+    tile_task_worker_pool_->CheckForCompletedTasks();
   }
 
   void AllTileTasksFinished() {
-    tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
+    tile_task_worker_pool_->CheckForCompletedTasks();
     base::MessageLoop::current()->QuitWhenIdle();
   }
 
   void RunMessageLoopUntilAllTasksHaveCompleted() {
     task_graph_runner_.RunUntilIdle();
-    tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
+    tile_task_worker_pool_->CheckForCompletedTasks();
   }
 
   void ScheduleTasks() {
@@ -200,7 +199,7 @@
                                 0 /* dependencies */);
     }
 
-    tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&graph_);
+    tile_task_worker_pool_->ScheduleTasks(&graph_);
   }
 
   void AppendTask(unsigned id, const gfx::Size& size) {
diff --git a/cc/raster/zero_copy_tile_task_worker_pool.cc b/cc/raster/zero_copy_tile_task_worker_pool.cc
index afbf04f..e423450b 100644
--- a/cc/raster/zero_copy_tile_task_worker_pool.cc
+++ b/cc/raster/zero_copy_tile_task_worker_pool.cc
@@ -89,10 +89,6 @@
 ZeroCopyTileTaskWorkerPool::~ZeroCopyTileTaskWorkerPool() {
 }
 
-TileTaskRunner* ZeroCopyTileTaskWorkerPool::AsTileTaskRunner() {
-  return this;
-}
-
 void ZeroCopyTileTaskWorkerPool::Shutdown() {
   TRACE_EVENT0("cc", "ZeroCopyTileTaskWorkerPool::Shutdown");
 
diff --git a/cc/raster/zero_copy_tile_task_worker_pool.h b/cc/raster/zero_copy_tile_task_worker_pool.h
index b5c31b15..7a78233 100644
--- a/cc/raster/zero_copy_tile_task_worker_pool.h
+++ b/cc/raster/zero_copy_tile_task_worker_pool.h
@@ -10,7 +10,6 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
-#include "cc/raster/tile_task_runner.h"
 #include "cc/raster/tile_task_worker_pool.h"
 
 namespace base {
@@ -23,7 +22,6 @@
 class ResourceProvider;
 
 class CC_EXPORT ZeroCopyTileTaskWorkerPool : public TileTaskWorkerPool,
-                                             public TileTaskRunner,
                                              public RasterBufferProvider {
  public:
   ~ZeroCopyTileTaskWorkerPool() override;
@@ -35,9 +33,6 @@
       ResourceFormat preferred_tile_format);
 
   // Overridden from TileTaskWorkerPool:
-  TileTaskRunner* AsTileTaskRunner() override;
-
-  // Overridden from TileTaskRunner:
   void Shutdown() override;
   void ScheduleTasks(TaskGraph* graph) override;
   void CheckForCompletedTasks() override;
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index 5b277f0..f8ba2be 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -429,7 +429,7 @@
 }
 
 bool ResourceProvider::IsResourceFormatSupported(ResourceFormat format) const {
-  ContextProvider::Capabilities caps;
+  gpu::Capabilities caps;
   if (output_surface_->context_provider())
     caps = output_surface_->context_provider()->ContextCapabilities();
 
@@ -441,13 +441,13 @@
     case LUMINANCE_8:
       return true;
     case BGRA_8888:
-      return caps.gpu.texture_format_bgra8888;
+      return caps.texture_format_bgra8888;
     case ETC1:
-      return caps.gpu.texture_format_etc1;
+      return caps.texture_format_etc1;
     case RED_8:
-      return caps.gpu.texture_rg;
+      return caps.texture_rg;
     case LUMINANCE_F16:
-      return caps.gpu.texture_half_float_linear;
+      return caps.texture_half_float_linear;
   }
 
   NOTREACHED();
@@ -1233,19 +1233,19 @@
   DCHECK(!texture_id_allocator_);
   DCHECK(!buffer_id_allocator_);
 
-  const ContextProvider::Capabilities& caps =
+  const gpu::Capabilities& caps =
       output_surface_->context_provider()->ContextCapabilities();
 
   DCHECK(IsGpuResourceType(default_resource_type_));
-  use_texture_storage_ext_ = caps.gpu.texture_storage;
-  use_texture_format_bgra_ = caps.gpu.texture_format_bgra8888;
-  use_texture_usage_hint_ = caps.gpu.texture_usage;
-  use_compressed_texture_etc1_ = caps.gpu.texture_format_etc1;
-  yuv_resource_format_ = caps.gpu.texture_rg ? RED_8 : LUMINANCE_8;
+  use_texture_storage_ext_ = caps.texture_storage;
+  use_texture_format_bgra_ = caps.texture_format_bgra8888;
+  use_texture_usage_hint_ = caps.texture_usage;
+  use_compressed_texture_etc1_ = caps.texture_format_etc1;
+  yuv_resource_format_ = caps.texture_rg ? RED_8 : LUMINANCE_8;
   yuv_highbit_resource_format_ = yuv_resource_format_;
-  if (caps.gpu.texture_half_float_linear)
+  if (caps.texture_half_float_linear)
     yuv_highbit_resource_format_ = LUMINANCE_F16;
-  use_sync_query_ = caps.gpu.sync_query;
+  use_sync_query_ = caps.sync_query;
 
   max_texture_size_ = 0;  // Context expects cleared value.
   gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_);
@@ -1253,7 +1253,7 @@
       PlatformColor::BestSupportedTextureFormat(use_texture_format_bgra_);
 
   best_render_buffer_format_ = PlatformColor::BestSupportedTextureFormat(
-      caps.gpu.render_buffer_format_bgra8888);
+      caps.render_buffer_format_bgra8888);
 
   texture_id_allocator_.reset(
       new TextureIdAllocator(gl, id_allocation_chunk_size_));
diff --git a/cc/test/fake_tile_manager.cc b/cc/test/fake_tile_manager.cc
index 7397ae4a3..94ca37b 100644
--- a/cc/test/fake_tile_manager.cc
+++ b/cc/test/fake_tile_manager.cc
@@ -13,16 +13,16 @@
 #include "base/lazy_instance.h"
 #include "base/thread_task_runner_handle.h"
 #include "cc/raster/raster_buffer.h"
-#include "cc/raster/tile_task_runner.h"
+#include "cc/raster/tile_task_worker_pool.h"
 
 namespace cc {
 
 namespace {
 
-class FakeTileTaskRunnerImpl : public TileTaskRunner,
-                               public RasterBufferProvider {
+class FakeTileTaskWorkerPoolImpl : public TileTaskWorkerPool,
+                                   public RasterBufferProvider {
  public:
-  // Overridden from TileTaskRunner:
+  // Overridden from TileTaskWorkerPool:
   void Shutdown() override {}
   void ScheduleTasks(TaskGraph* graph) override {
     for (const auto& node : graph->nodes) {
@@ -66,7 +66,7 @@
  private:
   TileTask::Vector completed_tasks_;
 };
-base::LazyInstance<FakeTileTaskRunnerImpl> g_fake_tile_task_runner =
+base::LazyInstance<FakeTileTaskWorkerPoolImpl> g_fake_tile_task_worker_pool =
     LAZY_INSTANCE_INITIALIZER;
 
 }  // namespace
@@ -76,7 +76,7 @@
                   base::ThreadTaskRunnerHandle::Get(),
                   std::numeric_limits<size_t>::max(),
                   false /* use_partial_raster */) {
-  SetResources(nullptr, g_fake_tile_task_runner.Pointer(),
+  SetResources(nullptr, g_fake_tile_task_worker_pool.Pointer(),
                &image_decode_controller_, std::numeric_limits<size_t>::max(),
                false /* use_gpu_rasterization */);
 }
@@ -87,7 +87,7 @@
                   base::ThreadTaskRunnerHandle::Get(),
                   std::numeric_limits<size_t>::max(),
                   false /* use_partial_raster */) {
-  SetResources(resource_pool, g_fake_tile_task_runner.Pointer(),
+  SetResources(resource_pool, g_fake_tile_task_worker_pool.Pointer(),
                &image_decode_controller_, std::numeric_limits<size_t>::max(),
                false /* use_gpu_rasterization */);
 }
diff --git a/cc/test/test_context_provider.cc b/cc/test/test_context_provider.cc
index 180c4c3..6fbf5eb 100644
--- a/cc/test/test_context_provider.cc
+++ b/cc/test/test_context_provider.cc
@@ -86,10 +86,9 @@
   context_thread_checker_.DetachFromThread();
 }
 
-ContextProvider::Capabilities TestContextProvider::ContextCapabilities() {
+gpu::Capabilities TestContextProvider::ContextCapabilities() {
   DCHECK(bound_);
   DCHECK(context_thread_checker_.CalledOnValidThread());
-
   return context3d_->test_capabilities();
 }
 
@@ -169,9 +168,4 @@
   lost_context_callback_ = cb;
 }
 
-void TestContextProvider::SetMaxTransferBufferUsageBytes(
-    size_t max_transfer_buffer_usage_bytes) {
-  context3d_->SetMaxTransferBufferUsageBytes(max_transfer_buffer_usage_bytes);
-}
-
 }  // namespace cc
diff --git a/cc/test/test_context_provider.h b/cc/test/test_context_provider.h
index 99d15c8..ecb1ec6 100644
--- a/cc/test/test_context_provider.h
+++ b/cc/test/test_context_provider.h
@@ -38,7 +38,7 @@
 
   bool BindToCurrentThread() override;
   void DetachFromThread() override;
-  Capabilities ContextCapabilities() override;
+  gpu::Capabilities ContextCapabilities() override;
   gpu::gles2::GLES2Interface* ContextGL() override;
   gpu::ContextSupport* ContextSupport() override;
   class GrContext* GrContext() override;
@@ -58,8 +58,6 @@
 
   TestContextSupport* support() { return &support_; }
 
-  void SetMaxTransferBufferUsageBytes(size_t max_transfer_buffer_usage_bytes);
-
  protected:
   explicit TestContextProvider(
       std::unique_ptr<TestWebGraphicsContext3D> context);
diff --git a/cc/test/test_in_process_context_provider.cc b/cc/test/test_in_process_context_provider.cc
index 490e5bb5..d444f0e 100644
--- a/cc/test/test_in_process_context_provider.cc
+++ b/cc/test/test_in_process_context_provider.cc
@@ -68,7 +68,9 @@
 TestInProcessContextProvider::~TestInProcessContextProvider() {
 }
 
-bool TestInProcessContextProvider::BindToCurrentThread() { return true; }
+bool TestInProcessContextProvider::BindToCurrentThread() {
+  return true;
+}
 
 gpu::gles2::GLES2Interface* TestInProcessContextProvider::ContextGL() {
   return context_->GetImplementation();
@@ -98,22 +100,19 @@
   return &context_lock_;
 }
 
-ContextProvider::Capabilities
-TestInProcessContextProvider::ContextCapabilities() {
-  ContextProvider::Capabilities capabilities;
-  capabilities.gpu.image = true;
-  capabilities.gpu.texture_rectangle = true;
-  capabilities.gpu.sync_query = true;
-
+gpu::Capabilities TestInProcessContextProvider::ContextCapabilities() {
+  gpu::Capabilities capabilities;
+  capabilities.image = true;
+  capabilities.texture_rectangle = true;
+  capabilities.sync_query = true;
   switch (PlatformColor::Format()) {
     case PlatformColor::SOURCE_FORMAT_RGBA8:
-      capabilities.gpu.texture_format_bgra8888 = false;
+      capabilities.texture_format_bgra8888 = false;
       break;
     case PlatformColor::SOURCE_FORMAT_BGRA8:
-      capabilities.gpu.texture_format_bgra8888 = true;
+      capabilities.texture_format_bgra8888 = true;
       break;
   }
-
   return capabilities;
 }
 
diff --git a/cc/test/test_in_process_context_provider.h b/cc/test/test_in_process_context_provider.h
index 5062909..2985f608 100644
--- a/cc/test/test_in_process_context_provider.h
+++ b/cc/test/test_in_process_context_provider.h
@@ -45,7 +45,7 @@
   void InvalidateGrContext(uint32_t state) override;
   void SetupLock() override;
   base::Lock* GetLock() override;
-  Capabilities ContextCapabilities() override;
+  gpu::Capabilities ContextCapabilities() override;
   void DeleteCachedResources() override;
   void SetLostContextCallback(
       const LostContextCallback& lost_context_callback) override;
diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc
index 0e1ea25..2641c90 100644
--- a/cc/test/test_web_graphics_context_3d.cc
+++ b/cc/test/test_web_graphics_context_3d.cc
@@ -57,8 +57,6 @@
       times_end_query_succeeds_(-1),
       context_lost_(false),
       times_map_buffer_chromium_succeeds_(-1),
-      current_used_transfer_buffer_usage_bytes_(0),
-      max_used_transfer_buffer_usage_bytes_(0),
       next_program_id_(1000),
       next_shader_id_(2000),
       next_framebuffer_id_(1),
@@ -550,19 +548,10 @@
     return;
   }
 
-  size_t old_size = buffer->size;
-
   buffer->pixels.reset(new uint8_t[size]);
   buffer->size = size;
-  if (data != NULL)
+  if (data != nullptr)
     memcpy(buffer->pixels.get(), data, size);
-  if (buffer->target == GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM)
-    current_used_transfer_buffer_usage_bytes_ +=
-        base::checked_cast<int>(buffer->size) -
-        base::checked_cast<int>(old_size);
-  max_used_transfer_buffer_usage_bytes_ =
-      std::max(max_used_transfer_buffer_usage_bytes_,
-               current_used_transfer_buffer_usage_bytes_);
 }
 
 void TestWebGraphicsContext3D::pixelStorei(GLenum pname, GLint param) {
@@ -773,14 +762,8 @@
   namespace_->renderbuffer_set.erase(id);
 }
 
-void TestWebGraphicsContext3D::SetMaxTransferBufferUsageBytes(
-    size_t max_transfer_buffer_usage_bytes) {
-  test_capabilities_.max_transfer_buffer_usage_bytes =
-      max_transfer_buffer_usage_bytes;
-}
-
 void TestWebGraphicsContext3D::SetMaxSamples(int max_samples) {
-  test_capabilities_.gpu.max_samples = max_samples;
+  test_capabilities_.max_samples = max_samples;
 }
 
 TestWebGraphicsContext3D::TextureTargets::TextureTargets() {
diff --git a/cc/test/test_web_graphics_context_3d.h b/cc/test/test_web_graphics_context_3d.h
index 4e14629..d37ef51e 100644
--- a/cc/test/test_web_graphics_context_3d.h
+++ b/cc/test/test_web_graphics_context_3d.h
@@ -284,7 +284,7 @@
     return last_waited_sync_token_;
   }
 
-  const ContextProvider::Capabilities& test_capabilities() const {
+  const gpu::Capabilities& test_capabilities() const {
     return test_capabilities_;
   }
 
@@ -311,47 +311,45 @@
   void ResetUsedTextures() { used_textures_.clear(); }
 
   void set_have_extension_io_surface(bool have) {
-    test_capabilities_.gpu.iosurface = have;
-    test_capabilities_.gpu.texture_rectangle = have;
+    test_capabilities_.iosurface = have;
+    test_capabilities_.texture_rectangle = have;
   }
   void set_have_extension_egl_image(bool have) {
-    test_capabilities_.gpu.egl_image_external = have;
+    test_capabilities_.egl_image_external = have;
   }
   void set_have_post_sub_buffer(bool have) {
-    test_capabilities_.gpu.post_sub_buffer = have;
+    test_capabilities_.post_sub_buffer = have;
   }
   void set_have_commit_overlay_planes(bool have) {
-    test_capabilities_.gpu.commit_overlay_planes = have;
+    test_capabilities_.commit_overlay_planes = have;
   }
   void set_have_discard_framebuffer(bool have) {
-    test_capabilities_.gpu.discard_framebuffer = have;
+    test_capabilities_.discard_framebuffer = have;
   }
   void set_support_compressed_texture_etc1(bool support) {
-    test_capabilities_.gpu.texture_format_etc1 = support;
+    test_capabilities_.texture_format_etc1 = support;
   }
   void set_support_texture_format_bgra8888(bool support) {
-    test_capabilities_.gpu.texture_format_bgra8888 = support;
+    test_capabilities_.texture_format_bgra8888 = support;
   }
   void set_support_texture_storage(bool support) {
-    test_capabilities_.gpu.texture_storage = support;
+    test_capabilities_.texture_storage = support;
   }
   void set_support_texture_usage(bool support) {
-    test_capabilities_.gpu.texture_usage = support;
+    test_capabilities_.texture_usage = support;
   }
   void set_support_sync_query(bool support) {
-    test_capabilities_.gpu.sync_query = support;
+    test_capabilities_.sync_query = support;
   }
-  void set_support_image(bool support) {
-    test_capabilities_.gpu.image = support;
-  }
+  void set_support_image(bool support) { test_capabilities_.image = support; }
   void set_support_texture_rectangle(bool support) {
-    test_capabilities_.gpu.texture_rectangle = support;
+    test_capabilities_.texture_rectangle = support;
   }
   void set_support_texture_half_float_linear(bool support) {
-    test_capabilities_.gpu.texture_half_float_linear = support;
+    test_capabilities_.texture_half_float_linear = support;
   }
   void set_msaa_is_slow(bool msaa_is_slow) {
-    test_capabilities_.gpu.msaa_is_slow = msaa_is_slow;
+    test_capabilities_.msaa_is_slow = msaa_is_slow;
   }
 
   // When this context is lost, all contexts in its share group are also lost.
@@ -377,11 +375,6 @@
   virtual GLuint NextRenderbufferId();
   virtual void RetireRenderbufferId(GLuint id);
 
-  void SetMaxTransferBufferUsageBytes(size_t max_transfer_buffer_usage_bytes);
-  size_t max_used_transfer_buffer_usage_bytes() const {
-    return max_used_transfer_buffer_usage_bytes_;
-  }
-
   void SetMaxSamples(int max_samples);
   void set_test_support(TestContextSupport* test_support) {
     test_support_ = test_support;
@@ -465,13 +458,11 @@
   void CheckTextureIsBound(GLenum target);
 
   unsigned context_id_;
-  ContextProvider::Capabilities test_capabilities_;
+  gpu::Capabilities test_capabilities_;
   int times_bind_texture_succeeds_;
   int times_end_query_succeeds_;
   bool context_lost_;
   int times_map_buffer_chromium_succeeds_;
-  int current_used_transfer_buffer_usage_bytes_;
-  int max_used_transfer_buffer_usage_bytes_;
   base::Closure context_lost_callback_;
   std::unordered_set<unsigned> used_textures_;
   unsigned next_program_id_;
diff --git a/cc/tiles/gpu_image_decode_controller.cc b/cc/tiles/gpu_image_decode_controller.cc
index cdb6f33c..d72553e0 100644
--- a/cc/tiles/gpu_image_decode_controller.cc
+++ b/cc/tiles/gpu_image_decode_controller.cc
@@ -11,7 +11,7 @@
 #include "base/thread_task_runner_handle.h"
 #include "cc/debug/devtools_instrumentation.h"
 #include "cc/output/context_provider.h"
-#include "cc/raster/tile_task_runner.h"
+#include "cc/raster/tile_task.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu_image_decode_controller.h"
diff --git a/cc/tiles/gpu_image_decode_controller_unittest.cc b/cc/tiles/gpu_image_decode_controller_unittest.cc
index 71bc063..f5949253 100644
--- a/cc/tiles/gpu_image_decode_controller_unittest.cc
+++ b/cc/tiles/gpu_image_decode_controller_unittest.cc
@@ -5,7 +5,7 @@
 #include "cc/tiles/gpu_image_decode_controller.h"
 
 #include "cc/playback/draw_image.h"
-#include "cc/raster/tile_task_runner.h"
+#include "cc/raster/tile_task.h"
 #include "cc/test/test_context_provider.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/cc/tiles/software_image_decode_controller.cc b/cc/tiles/software_image_decode_controller.cc
index 80190b4..c074af988 100644
--- a/cc/tiles/software_image_decode_controller.cc
+++ b/cc/tiles/software_image_decode_controller.cc
@@ -16,7 +16,7 @@
 #include "base/thread_task_runner_handle.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "cc/debug/devtools_instrumentation.h"
-#include "cc/raster/tile_task_runner.h"
+#include "cc/raster/tile_task.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkImage.h"
 #include "ui/gfx/skia_util.h"
diff --git a/cc/tiles/software_image_decode_controller.h b/cc/tiles/software_image_decode_controller.h
index 8f6ed0d..fe55d88b 100644
--- a/cc/tiles/software_image_decode_controller.h
+++ b/cc/tiles/software_image_decode_controller.h
@@ -22,7 +22,7 @@
 #include "cc/base/cc_export.h"
 #include "cc/playback/decoded_draw_image.h"
 #include "cc/playback/draw_image.h"
-#include "cc/raster/tile_task_runner.h"
+#include "cc/resources/resource_format.h"
 #include "cc/tiles/image_decode_controller.h"
 #include "skia/ext/refptr.h"
 
diff --git a/cc/tiles/software_image_decode_controller_unittest.cc b/cc/tiles/software_image_decode_controller_unittest.cc
index cbf6e3c..6374bce 100644
--- a/cc/tiles/software_image_decode_controller_unittest.cc
+++ b/cc/tiles/software_image_decode_controller_unittest.cc
@@ -5,6 +5,7 @@
 #include "cc/tiles/software_image_decode_controller.h"
 
 #include "cc/playback/draw_image.h"
+#include "cc/raster/tile_task.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cc {
diff --git a/cc/tiles/tile.h b/cc/tiles/tile.h
index 9dc8afc..76142e8 100644
--- a/cc/tiles/tile.h
+++ b/cc/tiles/tile.h
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "cc/raster/tile_task.h"
 #include "cc/tiles/tile_draw_info.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
diff --git a/cc/tiles/tile_draw_info.h b/cc/tiles/tile_draw_info.h
index 4178383..084f437 100644
--- a/cc/tiles/tile_draw_info.h
+++ b/cc/tiles/tile_draw_info.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "base/trace_event/trace_event_argument.h"
-#include "cc/raster/tile_task_runner.h"
 #include "cc/resources/platform_color.h"
 #include "cc/resources/resource_provider.h"
 #include "cc/resources/scoped_resource.h"
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index 74f1707e..f4d8fc5f 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -26,7 +26,6 @@
 #include "cc/layers/picture_layer_impl.h"
 #include "cc/raster/raster_buffer.h"
 #include "cc/raster/task_category.h"
-#include "cc/raster/tile_task_runner.h"
 #include "cc/tiles/tile.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 
@@ -169,7 +168,7 @@
       dependency_count = 1u;
     }
   }
-  InsertNodeForTask(graph, task, task->SupportsConcurrentExecution()
+  InsertNodeForTask(graph, task, task->supports_concurrent_execution()
                                      ? category
                                      : TASK_CATEGORY_NONCONCURRENT_FOREGROUND,
                     priority, dependency_count);
@@ -309,7 +308,7 @@
     : client_(client),
       task_runner_(std::move(task_runner)),
       resource_pool_(nullptr),
-      tile_task_runner_(nullptr),
+      tile_task_worker_pool_(nullptr),
       scheduled_raster_task_limit_(scheduled_raster_task_limit),
       use_partial_raster_(use_partial_raster),
       use_gpu_rasterization_(false),
@@ -333,25 +332,25 @@
 }
 
 void TileManager::FinishTasksAndCleanUp() {
-  if (!tile_task_runner_)
+  if (!tile_task_worker_pool_)
     return;
 
   global_state_ = GlobalStateThatImpactsTilePriority();
 
   // This cancels tasks if possible, finishes pending tasks, and release any
   // uninitialized resources.
-  tile_task_runner_->Shutdown();
+  tile_task_worker_pool_->Shutdown();
 
   // Now that all tasks have been finished, we can clear any
   // |orphan_tasks_|.
   orphan_tasks_.clear();
 
-  tile_task_runner_->CheckForCompletedTasks();
+  tile_task_worker_pool_->CheckForCompletedTasks();
 
   FreeResourcesForReleasedTiles();
   CleanUpReleasedTiles();
 
-  tile_task_runner_ = nullptr;
+  tile_task_worker_pool_ = nullptr;
   resource_pool_ = nullptr;
   more_tiles_need_prepare_check_notifier_.Cancel();
   signals_check_notifier_.Cancel();
@@ -359,17 +358,17 @@
 }
 
 void TileManager::SetResources(ResourcePool* resource_pool,
-                               TileTaskRunner* tile_task_runner,
+                               TileTaskWorkerPool* tile_task_worker_pool,
                                ImageDecodeController* image_decode_controller,
                                size_t scheduled_raster_task_limit,
                                bool use_gpu_rasterization) {
-  DCHECK(!tile_task_runner_);
-  DCHECK(tile_task_runner);
+  DCHECK(!tile_task_worker_pool_);
+  DCHECK(tile_task_worker_pool);
 
   use_gpu_rasterization_ = use_gpu_rasterization;
   scheduled_raster_task_limit_ = scheduled_raster_task_limit;
   resource_pool_ = resource_pool;
-  tile_task_runner_ = tile_task_runner;
+  tile_task_worker_pool_ = tile_task_worker_pool;
   image_decode_controller_ = image_decode_controller;
 }
 
@@ -420,7 +419,7 @@
   TRACE_EVENT0("cc", "TileManager::DidFinishRunningAllTileTasks");
   TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
   DCHECK(resource_pool_);
-  DCHECK(tile_task_runner_);
+  DCHECK(tile_task_worker_pool_);
 
   has_scheduled_tile_tasks_ = false;
 
@@ -447,7 +446,7 @@
   TRACE_EVENT1("cc", "TileManager::PrepareTiles", "prepare_tiles_id",
                prepare_tiles_count_);
 
-  if (!tile_task_runner_) {
+  if (!tile_task_worker_pool_) {
     TRACE_EVENT_INSTANT0("cc", "PrepareTiles aborted",
                          TRACE_EVENT_SCOPE_THREAD);
     return false;
@@ -459,7 +458,7 @@
   // We need to call CheckForCompletedTasks() once in-between each call
   // to ScheduleTasks() to prevent canceled tasks from being scheduled.
   if (!did_check_for_completed_tasks_since_last_schedule_tasks_) {
-    tile_task_runner_->CheckForCompletedTasks();
+    tile_task_worker_pool_->CheckForCompletedTasks();
     did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
   }
 
@@ -491,12 +490,12 @@
 void TileManager::Flush() {
   TRACE_EVENT0("cc", "TileManager::Flush");
 
-  if (!tile_task_runner_) {
+  if (!tile_task_worker_pool_) {
     TRACE_EVENT_INSTANT0("cc", "Flush aborted", TRACE_EVENT_SCOPE_THREAD);
     return;
   }
 
-  tile_task_runner_->CheckForCompletedTasks();
+  tile_task_worker_pool_->CheckForCompletedTasks();
 
   did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
 
@@ -593,7 +592,7 @@
   TRACE_EVENT_BEGIN0("cc", "TileManager::AssignGpuMemoryToTiles");
 
   DCHECK(resource_pool_);
-  DCHECK(tile_task_runner_);
+  DCHECK(tile_task_worker_pool_);
 
   // Maintain the list of released resources that can potentially be re-used
   // or deleted. If this operation becomes expensive too, only do this after
@@ -830,7 +829,7 @@
   // Schedule running of |raster_queue_|. This replaces any previously
   // scheduled tasks and effectively cancels all tasks not present
   // in |raster_queue_|.
-  tile_task_runner_->ScheduleTasks(&graph_);
+  tile_task_worker_pool_->ScheduleTasks(&graph_);
 
   // It's now safe to clean up orphan tasks as raster worker pool is not
   // allowed to keep around unreferenced raster tasks after ScheduleTasks() has
@@ -959,7 +958,7 @@
                                       int flags) {
   // We need to have a tile task worker pool to do anything meaningful with
   // tiles.
-  DCHECK(tile_task_runner_);
+  DCHECK(tile_task_worker_pool_);
   ScopedTilePtr tile(
       new Tile(this, info, layer_id, source_frame_number, flags));
   DCHECK(tiles_.find(tile->id()) == tiles_.end());
@@ -968,9 +967,9 @@
   return tile;
 }
 
-void TileManager::SetTileTaskRunnerForTesting(
-    TileTaskRunner* tile_task_runner) {
-  tile_task_runner_ = tile_task_runner;
+void TileManager::SetTileTaskWorkerPoolForTesting(
+    TileTaskWorkerPool* tile_task_worker_pool) {
+  tile_task_worker_pool_ = tile_task_worker_pool;
 }
 
 bool TileManager::AreRequiredTilesReadyToDraw(
@@ -1013,7 +1012,7 @@
 
 void TileManager::CheckAndIssueSignals() {
   TRACE_EVENT0("cc", "TileManager::CheckAndIssueSignals");
-  tile_task_runner_->CheckForCompletedTasks();
+  tile_task_worker_pool_->CheckForCompletedTasks();
   did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
 
   // Ready to activate.
@@ -1053,7 +1052,7 @@
 }
 
 void TileManager::CheckIfMoreTilesNeedToBePrepared() {
-  tile_task_runner_->CheckForCompletedTasks();
+  tile_task_worker_pool_->CheckForCompletedTasks();
   did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
 
   // When OOM, keep re-assigning memory until we reach a steady state
@@ -1140,11 +1139,11 @@
 }
 
 ResourceFormat TileManager::DetermineResourceFormat(const Tile* tile) const {
-  return tile_task_runner_->GetResourceFormat(!tile->is_opaque());
+  return tile_task_worker_pool_->GetResourceFormat(!tile->is_opaque());
 }
 
 bool TileManager::DetermineResourceRequiresSwizzle(const Tile* tile) const {
-  return tile_task_runner_->GetResourceRequiresSwizzle(!tile->is_opaque());
+  return tile_task_worker_pool_->GetResourceRequiresSwizzle(!tile->is_opaque());
 }
 
 std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
diff --git a/cc/tiles/tile_manager.h b/cc/tiles/tile_manager.h
index d58d5b0..dfcf478 100644
--- a/cc/tiles/tile_manager.h
+++ b/cc/tiles/tile_manager.h
@@ -18,7 +18,7 @@
 #include "base/values.h"
 #include "cc/base/unique_notifier.h"
 #include "cc/playback/raster_source.h"
-#include "cc/raster/tile_task_runner.h"
+#include "cc/raster/tile_task_worker_pool.h"
 #include "cc/resources/memory_history.h"
 #include "cc/resources/resource_pool.h"
 #include "cc/tiles/eviction_tile_priority_queue.h"
@@ -117,7 +117,7 @@
   // FinishTasksAndCleanUp must be called in between consecutive calls to
   // SetResources.
   void SetResources(ResourcePool* resource_pool,
-                    TileTaskRunner* tile_task_runner,
+                    TileTaskWorkerPool* tile_task_worker_pool,
                     ImageDecodeController* image_decode_controller,
                     size_t scheduled_raster_task_limit,
                     bool use_gpu_rasterization);
@@ -147,7 +147,7 @@
       TileDrawInfo& draw_info = tiles[i]->draw_info();
       draw_info.resource_ = resource_pool_->AcquireResource(
           tiles[i]->desired_texture_size(),
-          tile_task_runner_->GetResourceFormat(false));
+          tile_task_worker_pool_->GetResourceFormat(false));
     }
   }
 
@@ -163,7 +163,8 @@
     global_state_ = state;
   }
 
-  void SetTileTaskRunnerForTesting(TileTaskRunner* tile_task_runner);
+  void SetTileTaskWorkerPoolForTesting(
+      TileTaskWorkerPool* tile_task_worker_pool);
 
   void FreeResourcesAndCleanUpReleasedTilesForTesting() {
     FreeResourcesForReleasedTiles();
@@ -286,7 +287,7 @@
   TileManagerClient* client_;
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
   ResourcePool* resource_pool_;
-  TileTaskRunner* tile_task_runner_;
+  TileTaskWorkerPool* tile_task_worker_pool_;
   GlobalStateThatImpactsTilePriority global_state_;
   size_t scheduled_raster_task_limit_;
   const bool use_partial_raster_;
diff --git a/cc/tiles/tile_manager_perftest.cc b/cc/tiles/tile_manager_perftest.cc
index e5c7106..46f9017 100644
--- a/cc/tiles/tile_manager_perftest.cc
+++ b/cc/tiles/tile_manager_perftest.cc
@@ -37,10 +37,10 @@
 static const int kWarmupRuns = 5;
 static const int kTimeCheckInterval = 10;
 
-class FakeTileTaskRunnerImpl : public TileTaskRunner,
-                               public RasterBufferProvider {
+class FakeTileTaskWorkerPoolImpl : public TileTaskWorkerPool,
+                                   public RasterBufferProvider {
  public:
-  // Overridden from TileTaskRunner:
+  // Overridden from TileTaskWorkerPool:
   void Shutdown() override {}
   void ScheduleTasks(TaskGraph* graph) override {
     for (auto& node : graph->nodes) {
@@ -84,7 +84,7 @@
  private:
   TileTask::Vector completed_tasks_;
 };
-base::LazyInstance<FakeTileTaskRunnerImpl> g_fake_tile_task_runner =
+base::LazyInstance<FakeTileTaskWorkerPoolImpl> g_fake_tile_task_worker_pool =
     LAZY_INSTANCE_INITIALIZER;
 
 class TileManagerPerfTest : public testing::Test {
@@ -127,8 +127,8 @@
   virtual void InitializeRenderer() {
     host_impl_.SetVisible(true);
     host_impl_.InitializeRenderer(output_surface_.get());
-    tile_manager()->SetTileTaskRunnerForTesting(
-        g_fake_tile_task_runner.Pointer());
+    tile_manager()->SetTileTaskWorkerPoolForTesting(
+        g_fake_tile_task_worker_pool.Pointer());
   }
 
   void SetupDefaultTrees(const gfx::Size& layer_bounds) {
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc
index 2da6e3e..3b82483 100644
--- a/cc/tiles/tile_manager_unittest.cc
+++ b/cc/tiles/tile_manager_unittest.cc
@@ -1827,13 +1827,14 @@
   }
 }
 
-// Fake TileTaskRunner that just no-ops all calls.
-class FakeTileTaskRunner : public TileTaskRunner, public RasterBufferProvider {
+// Fake TileTaskWorkerPool that just no-ops all calls.
+class FakeTileTaskWorkerPool : public TileTaskWorkerPool,
+                               public RasterBufferProvider {
  public:
-  FakeTileTaskRunner() {}
-  ~FakeTileTaskRunner() override {}
+  FakeTileTaskWorkerPool() {}
+  ~FakeTileTaskWorkerPool() override {}
 
-  // TileTaskRunner methods.
+  // TileTaskWorkerPool methods.
   void Shutdown() override {}
   void CheckForCompletedTasks() override {}
   ResourceFormat GetResourceFormat(bool must_support_alpha) const override {
@@ -1857,11 +1858,11 @@
   void ReleaseBufferForRaster(std::unique_ptr<RasterBuffer> buffer) override {}
 };
 
-// Fake TileTaskRunner that just cancels all scheduled tasks immediately.
-class CancellingTileTaskRunner : public FakeTileTaskRunner {
+// Fake TileTaskWorkerPool that just cancels all scheduled tasks immediately.
+class CancellingTileTaskWorkerPool : public FakeTileTaskWorkerPool {
  public:
-  CancellingTileTaskRunner() {}
-  ~CancellingTileTaskRunner() override {}
+  CancellingTileTaskWorkerPool() {}
+  ~CancellingTileTaskWorkerPool() override {}
 
   void ScheduleTasks(TaskGraph* graph) override {
     // Just call CompleteOnOriginThread on each item in the queue. As none of
@@ -1884,8 +1885,9 @@
 TEST_F(PartialRasterTileManagerTest, CancelledTasksHaveNoContentId) {
   // Create a CancellingTaskRunner and set it on the tile manager so that all
   // scheduled work is immediately cancelled.
-  CancellingTileTaskRunner cancelling_runner;
-  host_impl_->tile_manager()->SetTileTaskRunnerForTesting(&cancelling_runner);
+  CancellingTileTaskWorkerPool cancelling_worker_pool;
+  host_impl_->tile_manager()->SetTileTaskWorkerPoolForTesting(
+      &cancelling_worker_pool);
 
   // Pick arbitrary IDs - they don't really matter as long as they're constant.
   const int kLayerId = 7;
@@ -1918,7 +1920,8 @@
   EXPECT_FALSE(queue->IsEmpty());
   queue->Top().tile()->SetInvalidated(gfx::Rect(), kInvalidatedId);
 
-  // PrepareTiles to schedule tasks. Due to the CancellingTileTaskRunner, these
+  // PrepareTiles to schedule tasks. Due to the CancellingTileTaskWorkerPool,
+  // these
   // tasks will immediately be canceled.
   host_impl_->tile_manager()->PrepareTiles(host_impl_->global_tile_state());
 
@@ -1928,17 +1931,21 @@
   EXPECT_FALSE(host_impl_->resource_pool()->TryAcquireResourceWithContentId(
       kInvalidatedId));
 
-  // Free our host_impl_ before the cancelling_runner we passed it, as it will
+  // Free our host_impl_ before the cancelling_worker_pool we passed it, as it
+  // will
   // use that class in clean up.
   host_impl_ = nullptr;
 }
 
-// Fake TileTaskRunner that verifies the resource content ID of raster tasks.
-class VerifyResourceContentIdTileTaskRunner : public FakeTileTaskRunner {
+// Fake TileTaskWorkerPool that verifies the resource content ID of raster
+// tasks.
+class VerifyResourceContentIdTileTaskWorkerPool
+    : public FakeTileTaskWorkerPool {
  public:
-  explicit VerifyResourceContentIdTileTaskRunner(uint64_t expected_resource_id)
+  explicit VerifyResourceContentIdTileTaskWorkerPool(
+      uint64_t expected_resource_id)
       : expected_resource_id_(expected_resource_id) {}
-  ~VerifyResourceContentIdTileTaskRunner() override {}
+  ~VerifyResourceContentIdTileTaskWorkerPool() override {}
 
   void ScheduleTasks(TaskGraph* graph) override {
     for (const auto& node : graph->nodes) {
@@ -1974,10 +1981,12 @@
   const uint64_t kExpectedId = partial_raster_enabled ? kInvalidatedId : 0u;
   const gfx::Size kTileSize(128, 128);
 
-  // Create a VerifyResourceContentIdTileTaskRunner to ensure that the raster
+  // Create a VerifyResourceContentIdTileTaskWorkerPool to ensure that the
+  // raster
   // task we see is created with |kExpectedId|.
-  VerifyResourceContentIdTileTaskRunner verifying_runner(kExpectedId);
-  host_impl->tile_manager()->SetTileTaskRunnerForTesting(&verifying_runner);
+  VerifyResourceContentIdTileTaskWorkerPool verifying_worker_pool(kExpectedId);
+  host_impl->tile_manager()->SetTileTaskWorkerPoolForTesting(
+      &verifying_worker_pool);
 
   // Ensure there's a resource with our |kInvalidatedId| in the resource pool.
   host_impl->resource_pool()->ReleaseResource(
@@ -2012,11 +2021,12 @@
   queue->Top().tile()->SetInvalidated(gfx::Rect(), kInvalidatedId);
 
   // PrepareTiles to schedule tasks. Due to the
-  // VerifyPreviousContentTileTaskRunner, these tasks will verified and
+  // VerifyPreviousContentTileTaskWorkerPool, these tasks will verified and
   // cancelled.
   host_impl->tile_manager()->PrepareTiles(host_impl->global_tile_state());
 
-  // Free our host_impl before the cancelling_runner we passed it, as it will
+  // Free our host_impl before the cancelling_worker_pool we passed it, as it
+  // will
   // use that class in clean up.
   host_impl = nullptr;
 }
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 696f96c..5bfb96a 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2149,7 +2149,7 @@
 
   // TODO(vmpstr): Initialize tile task limit at ctor time.
   tile_manager_->SetResources(
-      resource_pool_.get(), tile_task_worker_pool_->AsTileTaskRunner(),
+      resource_pool_.get(), tile_task_worker_pool_.get(),
       image_decode_controller_.get(),
       is_synchronous_single_threaded_ ? std::numeric_limits<size_t>::max()
                                       : settings_.scheduled_raster_task_limit,
@@ -2224,8 +2224,8 @@
   *resource_pool =
       ResourcePool::Create(resource_provider_.get(), GetTaskRunner());
 
-  int max_copy_texture_chromium_size = context_provider->ContextCapabilities()
-                                           .gpu.max_copy_texture_chromium_size;
+  const int max_copy_texture_chromium_size =
+      context_provider->ContextCapabilities().max_copy_texture_chromium_size;
 
   *tile_task_worker_pool = OneCopyTileTaskWorkerPool::Create(
       GetTaskRunner(), task_graph_runner, context_provider,
diff --git a/chrome/VERSION b/chrome/VERSION
index e7b2245..2110bd1 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=52
 MINOR=0
-BUILD=2713
+BUILD=2714
 PATCH=0
diff --git a/chrome/browser/chrome_quota_permission_context.cc b/chrome/browser/chrome_quota_permission_context.cc
index a517382a..306ccac 100644
--- a/chrome/browser/chrome_quota_permission_context.cc
+++ b/chrome/browser/chrome_quota_permission_context.cc
@@ -52,6 +52,7 @@
 
   ~QuotaPermissionRequest() override;
 
+ private:
   // PermissionBubbleRequest:
   int GetIconId() const override;
   base::string16 GetMessageText() const override;
@@ -61,8 +62,8 @@
   void PermissionDenied() override;
   void Cancelled() override;
   void RequestFinished() override;
+  PermissionBubbleType GetPermissionBubbleType() const override;
 
- private:
   scoped_refptr<ChromeQuotaPermissionContext> context_;
   GURL origin_url_;
   int64_t requested_quota_;
@@ -131,6 +132,10 @@
   delete this;
 }
 
+PermissionBubbleType QuotaPermissionRequest::GetPermissionBubbleType() const {
+  return PermissionBubbleType::QUOTA;
+}
+
 #if defined(OS_ANDROID)
 // RequestQuotaInfoBarDelegate ------------------------------------------------
 
diff --git a/chrome/browser/custom_handlers/register_protocol_handler_permission_request.cc b/chrome/browser/custom_handlers/register_protocol_handler_permission_request.cc
index f1a54d1..7f91ba8 100644
--- a/chrome/browser/custom_handlers/register_protocol_handler_permission_request.cc
+++ b/chrome/browser/custom_handlers/register_protocol_handler_permission_request.cc
@@ -112,3 +112,8 @@
 void RegisterProtocolHandlerPermissionRequest::RequestFinished() {
   delete this;
 }
+
+PermissionBubbleType
+RegisterProtocolHandlerPermissionRequest::GetPermissionBubbleType() const {
+  return PermissionBubbleType::REGISTER_PROTOCOL_HANDLER;
+}
diff --git a/chrome/browser/custom_handlers/register_protocol_handler_permission_request.h b/chrome/browser/custom_handlers/register_protocol_handler_permission_request.h
index db0e143..5e50d50 100644
--- a/chrome/browser/custom_handlers/register_protocol_handler_permission_request.h
+++ b/chrome/browser/custom_handlers/register_protocol_handler_permission_request.h
@@ -24,6 +24,7 @@
       bool user_gesture);
   ~RegisterProtocolHandlerPermissionRequest() override;
 
+ private:
   // PermissionBubbleRequest:
   gfx::VectorIconId GetVectorIconId() const override;
   int GetIconId() const override;
@@ -34,8 +35,8 @@
   void PermissionDenied() override;
   void Cancelled() override;
   void RequestFinished() override;
+  PermissionBubbleType GetPermissionBubbleType() const override;
 
- private:
   ProtocolHandlerRegistry* registry_;
   ProtocolHandler handler_;
   GURL origin_;
diff --git a/chrome/browser/download/download_permission_request.cc b/chrome/browser/download/download_permission_request.cc
index a8a35ad..7e88c78 100644
--- a/chrome/browser/download/download_permission_request.cc
+++ b/chrome/browser/download/download_permission_request.cc
@@ -59,3 +59,8 @@
 void DownloadPermissionRequest::RequestFinished() {
   delete this;
 }
+
+PermissionBubbleType DownloadPermissionRequest::GetPermissionBubbleType()
+    const {
+  return PermissionBubbleType::DOWNLOAD;
+}
diff --git a/chrome/browser/download/download_permission_request.h b/chrome/browser/download/download_permission_request.h
index 979711a..fa4e0d9 100644
--- a/chrome/browser/download/download_permission_request.h
+++ b/chrome/browser/download/download_permission_request.h
@@ -20,6 +20,7 @@
       base::WeakPtr<DownloadRequestLimiter::TabDownloadState> host);
   ~DownloadPermissionRequest() override;
 
+ private:
   // PermisisonBubbleDelegate:
   int GetIconId() const override;
   base::string16 GetMessageText() const override;
@@ -29,8 +30,8 @@
   void PermissionDenied() override;
   void Cancelled() override;
   void RequestFinished() override;
+  PermissionBubbleType GetPermissionBubbleType() const override;
 
- private:
   base::WeakPtr<DownloadRequestLimiter::TabDownloadState> host_;
   GURL request_origin_;
 
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api.cc b/chrome/browser/extensions/api/input_ime/input_ime_api.cc
index 8cef3353..a74a6f6 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api.cc
@@ -264,7 +264,7 @@
   if (!profile || router_map_.empty())
     return;
   auto it = router_map_.find(profile);
-  if (it != router_map_.end()) {
+  if (it != router_map_.end() && it->first == profile) {
     delete it->second;
     router_map_.erase(it);
   }
diff --git a/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc b/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
index 0bb2a193..1368740 100644
--- a/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
+++ b/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
@@ -4,10 +4,8 @@
 
 #include "chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.h"
 
-#include <memory>
 #include <string>
 #include <utility>
-#include <vector>
 
 #include "base/location.h"
 #include "base/metrics/histogram.h"
@@ -25,14 +23,11 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "components/update_client/update_query_params.h"
 #include "content/public/browser/notification_service.h"
-#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/notification_types.h"
 #include "extensions/browser/warning_service.h"
 #include "extensions/browser/warning_set.h"
 #include "extensions/common/api/runtime.h"
-#include "extensions/common/constants.h"
-#include "net/base/backoff_entry.h"
 
 #if defined(OS_CHROMEOS)
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -60,69 +55,19 @@
 // disabled.
 const int kFastReloadCount = 5;
 
-// The policy we use for exponential backoff of update check requests.
-const net::BackoffEntry::Policy kBackoffPolicy = {
-    // num_errors_to_ignore
-    0,
-
-    // initial_delay_ms (note that we set 'always_use_initial_delay' to false
-    // below)
-    1000 * extensions::kDefaultUpdateFrequencySeconds,
-
-    // multiply_factor
-    1,
-
-    // jitter_factor
-    0.1,
-
-    // maximum_backoff_ms (-1 means no maximum)
-    -1,
-
-    // entry_lifetime_ms (-1 means never discard)
-    -1,
-
-    // always_use_initial_delay
-    false,
-};
-
-base::TickClock* g_test_clock = nullptr;
-
 }  // namespace
 
-struct ChromeRuntimeAPIDelegate::UpdateCheckInfo {
- public:
-  UpdateCheckInfo() {
-    if (g_test_clock)
-      backoff.reset(new net::BackoffEntry(&kBackoffPolicy, g_test_clock));
-    else
-      backoff.reset(new net::BackoffEntry(&kBackoffPolicy));
-  }
-
-  std::unique_ptr<net::BackoffEntry> backoff;
-  std::vector<UpdateCheckCallback> callbacks;
-};
-
 ChromeRuntimeAPIDelegate::ChromeRuntimeAPIDelegate(
     content::BrowserContext* context)
-    : browser_context_(context),
-      registered_for_updates_(false),
-      extension_registry_observer_(this) {
+    : browser_context_(context), registered_for_updates_(false) {
   registrar_.Add(this,
                  extensions::NOTIFICATION_EXTENSION_UPDATE_FOUND,
                  content::NotificationService::AllSources());
-  extension_registry_observer_.Add(
-      extensions::ExtensionRegistry::Get(browser_context_));
 }
 
 ChromeRuntimeAPIDelegate::~ChromeRuntimeAPIDelegate() {
 }
 
-// static
-void ChromeRuntimeAPIDelegate::set_tick_clock_for_tests(
-    base::TickClock* clock) {
-  g_test_clock = clock;
-}
-
 void ChromeRuntimeAPIDelegate::AddUpdateObserver(
     extensions::UpdateObserver* observer) {
   registered_for_updates_ = true;
@@ -207,20 +152,17 @@
   if (!updater) {
     return false;
   }
-
-  UpdateCheckInfo& info = update_check_info_[extension_id];
-
-  // If not enough time has elapsed, or we have 10 or more outstanding calls,
-  // return a status of throttled.
-  if (info.backoff->ShouldRejectRequest() || info.callbacks.size() >= 10) {
+  if (!updater->CheckExtensionSoon(
+          extension_id,
+          base::Bind(&ChromeRuntimeAPIDelegate::UpdateCheckComplete,
+                     base::Unretained(this),
+                     extension_id))) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
         base::Bind(callback, UpdateCheckResult(true, kUpdateThrottled, "")));
   } else {
-    info.callbacks.push_back(callback);
-    updater->CheckExtensionSoon(
-        extension_id, base::Bind(&ChromeRuntimeAPIDelegate::UpdateCheckComplete,
-                                 base::Unretained(this), extension_id));
+    UpdateCallbackList& callbacks = pending_update_checks_[extension_id];
+    callbacks.push_back(callback);
   }
   return true;
 }
@@ -317,31 +259,11 @@
   }
 }
 
-void ChromeRuntimeAPIDelegate::OnExtensionInstalled(
-    content::BrowserContext* browser_context,
-    const Extension* extension,
-    bool is_update) {
-  if (!is_update)
-    return;
-  auto info = update_check_info_.find(extension->id());
-  if (info != update_check_info_.end()) {
-    info->second.backoff->Reset();
-  }
-}
-
 void ChromeRuntimeAPIDelegate::UpdateCheckComplete(
     const std::string& extension_id) {
   ExtensionSystem* system = ExtensionSystem::Get(browser_context_);
   ExtensionService* service = system->extension_service();
   const Extension* update = service->GetPendingExtensionUpdate(extension_id);
-  UpdateCheckInfo& info = update_check_info_[extension_id];
-
-  // We always inform the BackoffEntry of a "failure" here, because we only
-  // want to consider an update check request a success from a throttling
-  // standpoint once the extension goes on to actually update to a new
-  // version. See OnExtensionInstalled for where we reset the BackoffEntry.
-  info.backoff->InformOfRequest(false);
-
   if (update) {
     CallUpdateCallbacks(
         extension_id,
@@ -355,12 +277,12 @@
 void ChromeRuntimeAPIDelegate::CallUpdateCallbacks(
     const std::string& extension_id,
     const UpdateCheckResult& result) {
-  auto it = update_check_info_.find(extension_id);
-  if (it == update_check_info_.end())
-    return;
-  std::vector<UpdateCheckCallback> callbacks;
-  it->second.callbacks.swap(callbacks);
-  for (const auto& callback : callbacks) {
+  UpdateCallbackList callbacks = pending_update_checks_[extension_id];
+  pending_update_checks_.erase(extension_id);
+  for (UpdateCallbackList::const_iterator iter = callbacks.begin();
+       iter != callbacks.end();
+       ++iter) {
+    const UpdateCheckCallback& callback = *iter;
     callback.Run(result);
   }
 }
diff --git a/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.h b/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.h
index 6ff1a05..934bcd8 100644
--- a/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.h
+++ b/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.h
@@ -6,19 +6,15 @@
 #define CHROME_BROWSER_EXTENSIONS_API_RUNTIME_CHROME_RUNTIME_API_DELEGATE_H_
 
 #include <map>
-#include <string>
-#include <utility>
+#include <vector>
 
 #include "base/macros.h"
-#include "base/scoped_observer.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "extensions/browser/api/runtime/runtime_api.h"
 #include "extensions/browser/api/runtime/runtime_api_delegate.h"
-#include "extensions/browser/extension_registry_observer.h"
 
 namespace base {
-class TickClock;
 class TimeTicks;
 }
 
@@ -29,21 +25,16 @@
 }
 
 namespace extensions {
-class ExtensionRegistry;
 class RuntimeAPI;
 class UpdateObserver;
 }
 
 class ChromeRuntimeAPIDelegate : public extensions::RuntimeAPIDelegate,
-                                 public content::NotificationObserver,
-                                 public extensions::ExtensionRegistryObserver {
+                                 public content::NotificationObserver {
  public:
   explicit ChromeRuntimeAPIDelegate(content::BrowserContext* context);
   ~ChromeRuntimeAPIDelegate() override;
 
-  // Sets a custom TickClock to use in tests.
-  static void set_tick_clock_for_tests(base::TickClock* clock);
-
  private:
   friend class extensions::RuntimeAPI;
 
@@ -65,11 +56,6 @@
                const content::NotificationSource& source,
                const content::NotificationDetails& details) override;
 
-  // ExtensionRegistryObserver implementation.
-  void OnExtensionInstalled(content::BrowserContext* browser_context,
-                            const extensions::Extension* extension,
-                            bool is_update) override;
-
   void UpdateCheckComplete(const std::string& extension_id);
   void CallUpdateCallbacks(const std::string& extension_id,
                            const UpdateCheckResult& result);
@@ -87,14 +73,12 @@
   // it was reloaded with not enough time in between reloads.
   std::map<std::string, std::pair<base::TimeTicks, int> > last_reload_time_;
 
-  // Information about update checks, keyed by extension id.
-  struct UpdateCheckInfo;
-  std::map<std::string, UpdateCheckInfo> update_check_info_;
+  // Pending update checks.
+  typedef std::vector<UpdateCheckCallback> UpdateCallbackList;
+  typedef std::map<std::string, UpdateCallbackList> UpdateCallbackMap;
+  UpdateCallbackMap pending_update_checks_;
 
-  ScopedObserver<extensions::ExtensionRegistry,
-                 extensions::ExtensionRegistryObserver>
-      extension_registry_observer_;
-
+ private:
   DISALLOW_COPY_AND_ASSIGN(ChromeRuntimeAPIDelegate);
 };
 
diff --git a/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc b/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc
deleted file mode 100644
index 0313064a..0000000
--- a/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc
+++ /dev/null
@@ -1,317 +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 <deque>
-#include <memory>
-#include <set>
-#include <utility>
-
-#include "base/callback.h"
-#include "base/files/file_path.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_service_test_with_install.h"
-#include "chrome/browser/extensions/test_extension_system.h"
-#include "chrome/browser/extensions/update_install_gate.h"
-#include "chrome/browser/extensions/updater/extension_updater.h"
-#include "extensions/browser/event_router.h"
-#include "extensions/browser/event_router_factory.h"
-#include "extensions/browser/extension_prefs.h"
-#include "extensions/browser/extension_registry.h"
-#include "extensions/browser/updater/extension_downloader.h"
-#include "extensions/browser/updater/extension_downloader_test_delegate.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace extensions {
-
-namespace {
-
-// A fake EventRouter that lets us pretend an extension has a listener
-// registered for named events.
-class TestEventRouter : public EventRouter {
- public:
-  explicit TestEventRouter(content::BrowserContext* context)
-      : EventRouter(context, ExtensionPrefs::Get(context)) {}
-  ~TestEventRouter() override {}
-
-  // An entry in our fake event registry.
-  using Entry = std::pair<std::string, std::string>;
-
-  bool ExtensionHasEventListener(const std::string& extension_id,
-                                 const std::string& event_name) override {
-    return fake_registry_.find(Entry(extension_id, event_name)) !=
-           fake_registry_.end();
-  }
-
-  // Pretend that |extension_id| is listening for |event_name|.
-  void AddFakeListener(const std::string& extension_id,
-                       const std::string& event_name) {
-    fake_registry_.insert(Entry(extension_id, event_name));
-  }
-
- private:
-  std::set<Entry> fake_registry_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestEventRouter);
-};
-
-std::unique_ptr<KeyedService> TestEventRouterFactoryFunction(
-    content::BrowserContext* context) {
-  return base::WrapUnique(new TestEventRouter(context));
-}
-
-// This class lets us intercept extension update checks and respond as if
-// either no update was found, or one was (and it was downloaded).
-class DownloaderTestDelegate : public ExtensionDownloaderTestDelegate {
- public:
-  DownloaderTestDelegate() {}
-
-  // On the next update check for extension |id|, we'll respond that no update
-  // is available.
-  void AddNoUpdateResponse(const std::string& id) {
-    no_updates_.insert(id);
-    if (updates_.find(id) != updates_.end())
-      updates_.erase(id);
-  }
-
-  // On the next update check for extension |id|, pretend that an update to
-  // version |version| has been downloaded to |path|.
-  void AddUpdateResponse(const std::string& id,
-                         const base::FilePath& path,
-                         const std::string& version) {
-    if (no_updates_.find(id) != no_updates_.end())
-      no_updates_.erase(id);
-    DownloadFinishedArgs args;
-    args.path = path;
-    args.version = version;
-    updates_[id] = std::move(args);
-  }
-
-  void StartUpdateCheck(
-      ExtensionDownloader* downloader,
-      ExtensionDownloaderDelegate* delegate,
-      std::unique_ptr<ManifestFetchData> fetch_data) override {
-    // Instead of immediately firing callbacks to the delegate in matching
-    // cases below, we instead post a task since the delegate typically isn't
-    // expecting a synchronous reply (the real code has to go do at least one
-    // network request before getting a response, so this is is a reasonable
-    // expectation by delegates).
-    for (const std::string& id : fetch_data->extension_ids()) {
-      auto no_update = no_updates_.find(id);
-      if (no_update != no_updates_.end()) {
-        no_updates_.erase(no_update);
-        base::MessageLoop::current()->task_runner()->PostTask(
-            FROM_HERE,
-            base::Bind(&ExtensionDownloaderDelegate::OnExtensionDownloadFailed,
-                       base::Unretained(delegate), id,
-                       ExtensionDownloaderDelegate::NO_UPDATE_AVAILABLE,
-                       ExtensionDownloaderDelegate::PingResult(),
-                       fetch_data->request_ids()));
-        continue;
-      }
-      auto update = updates_.find(id);
-      if (update != updates_.end()) {
-        CRXFileInfo info(id, update->second.path, "" /* no hash */);
-        std::string version = update->second.version;
-        updates_.erase(update);
-        base::MessageLoop::current()->task_runner()->PostTask(
-            FROM_HERE,
-            base::Bind(
-                &ExtensionDownloaderDelegate::OnExtensionDownloadFinished,
-                base::Unretained(delegate), info,
-                false /* file_ownership_passed */, GURL(), version,
-                ExtensionDownloaderDelegate::PingResult(),
-                fetch_data->request_ids(),
-                ExtensionDownloaderDelegate::InstallCallback()));
-        continue;
-      }
-      ADD_FAILURE() << "Unexpected extension id " << id;
-    }
-  }
-
- private:
-  // Simple holder for the data passed in AddUpdateResponse calls.
-  struct DownloadFinishedArgs {
-    base::FilePath path;
-    std::string version;
-  };
-
-  // These keep track of what response we should give for update checks, keyed
-  // by extension id. A given extension id should only appear in one or the
-  // other.
-  std::set<std::string> no_updates_;
-  std::map<std::string, DownloadFinishedArgs> updates_;
-
-  DISALLOW_COPY_AND_ASSIGN(DownloaderTestDelegate);
-};
-
-// Helper to let test code wait for and return an update check result.
-class UpdateCheckResultCatcher {
- public:
-  UpdateCheckResultCatcher() {}
-
-  void OnResult(const RuntimeAPIDelegate::UpdateCheckResult& result) {
-    EXPECT_EQ(nullptr, result_.get());
-    result_.reset(new RuntimeAPIDelegate::UpdateCheckResult(
-        result.success, result.response, result.version));
-    if (run_loop_)
-      run_loop_->Quit();
-  }
-
-  std::unique_ptr<RuntimeAPIDelegate::UpdateCheckResult> WaitForResult() {
-    if (!result_) {
-      run_loop_.reset(new base::RunLoop);
-      run_loop_->Run();
-    }
-    return std::move(result_);
-  }
-
- private:
-  std::unique_ptr<RuntimeAPIDelegate::UpdateCheckResult> result_;
-  std::unique_ptr<base::RunLoop> run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(UpdateCheckResultCatcher);
-};
-
-class ChromeRuntimeAPIDelegateTest : public ExtensionServiceTestWithInstall {
- public:
-  ChromeRuntimeAPIDelegateTest() {}
-
-  void SetUp() override {
-    ExtensionServiceTestWithInstall::SetUp();
-    ExtensionDownloader::set_test_delegate(&downloader_test_delegate_);
-    ChromeRuntimeAPIDelegate::set_tick_clock_for_tests(&clock_);
-
-    InitializeExtensionServiceWithUpdater();
-    runtime_delegate_.reset(new ChromeRuntimeAPIDelegate(browser_context()));
-    service()->updater()->SetExtensionCacheForTesting(nullptr);
-    EventRouterFactory::GetInstance()->SetTestingFactory(
-        browser_context(), &TestEventRouterFactoryFunction);
-
-    // Setup the ExtensionService so that extension updates won't complete
-    // installation until the extension is idle.
-    update_install_gate_.reset(new UpdateInstallGate(service()));
-    service()->RegisterInstallGate(ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE,
-                                   update_install_gate_.get());
-    static_cast<TestExtensionSystem*>(ExtensionSystem::Get(browser_context()))
-        ->SetReady();
-  }
-
-  void TearDown() override {
-    ExtensionDownloader::set_test_delegate(nullptr);
-    ChromeRuntimeAPIDelegate::set_tick_clock_for_tests(nullptr);
-    ExtensionServiceTestWithInstall::TearDown();
-  }
-
-  // Uses runtime_delegate_ to run an update check for |id|, expecting
-  // |expected_response| and (if an update was available) |expected_version|.
-  // The |expected_response| should be one of 'throttled', 'no_update', or
-  // 'update_available'.
-  void DoUpdateCheck(const std::string& id,
-                     const std::string& expected_response,
-                     const std::string& expected_version) {
-    UpdateCheckResultCatcher catcher;
-    EXPECT_TRUE(runtime_delegate_->CheckForUpdates(
-        id, base::Bind(&UpdateCheckResultCatcher::OnResult,
-                       base::Unretained(&catcher))));
-    std::unique_ptr<RuntimeAPIDelegate::UpdateCheckResult> result =
-        catcher.WaitForResult();
-    ASSERT_NE(nullptr, result.get());
-    EXPECT_TRUE(result->success);
-    EXPECT_EQ(expected_response, result->response);
-    EXPECT_EQ(expected_version, result->version);
-  }
-
- protected:
-  // A clock we pass to the code used for throttling, so that we can manually
-  // increment time to test various throttling scenarios.
-  base::SimpleTestTickClock clock_;
-
-  // Used for intercepting update check requests and possibly returning fake
-  // download results.
-  DownloaderTestDelegate downloader_test_delegate_;
-
-  // The object whose behavior we're testing.
-  std::unique_ptr<RuntimeAPIDelegate> runtime_delegate_;
-
-  // For preventing extensions from being updated immediately.
-  std::unique_ptr<UpdateInstallGate> update_install_gate_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ChromeRuntimeAPIDelegateTest);
-};
-
-TEST_F(ChromeRuntimeAPIDelegateTest, RequestUpdateCheck) {
-  base::FilePath v1_path = data_dir().AppendASCII("autoupdate/v1.crx");
-  base::FilePath v2_path = data_dir().AppendASCII("autoupdate/v2.crx");
-
-  // Start by installing version 1.
-  scoped_refptr<const Extension> v1(InstallCRX(v1_path, INSTALL_NEW));
-  std::string id = v1->id();
-
-  // Make it look like our test extension listens for the
-  // runtime.onUpdateAvailable event, so that it won't be updated immediately
-  // when the ExtensionUpdater hands the new version to the ExtensionService.
-  TestEventRouter* event_router =
-      static_cast<TestEventRouter*>(EventRouter::Get(browser_context()));
-  event_router->AddFakeListener(id, "runtime.onUpdateAvailable");
-
-  // Run an update check that should get a "no_update" response.
-  downloader_test_delegate_.AddNoUpdateResponse(id);
-  DoUpdateCheck(id, "no_update", "");
-
-  // Check again after a short delay - we should be throttled because
-  // not enough time has passed.
-  clock_.Advance(base::TimeDelta::FromMinutes(15));
-  downloader_test_delegate_.AddNoUpdateResponse(id);
-  DoUpdateCheck(id, "throttled", "");
-
-  // Now simulate checking a few times at a 6 hour interval - none of these
-  // should be throttled.
-  for (int i = 0; i < 5; i++) {
-    clock_.Advance(base::TimeDelta::FromHours(6));
-    downloader_test_delegate_.AddNoUpdateResponse(id);
-    DoUpdateCheck(id, "no_update", "");
-  }
-
-  // Run an update check that should get an "update_available" response. This
-  // actually causes the new version to be downloaded/unpacked, but the install
-  // will not complete until we reload the extension.
-  clock_.Advance(base::TimeDelta::FromDays(1));
-  downloader_test_delegate_.AddUpdateResponse(id, v2_path, "2.0");
-  DoUpdateCheck(id, "update_available", "2.0");
-
-  // Call again after short delay - it should be throttled instead of getting
-  // another "update_available" response.
-  clock_.Advance(base::TimeDelta::FromMinutes(30));
-  downloader_test_delegate_.AddUpdateResponse(id, v2_path, "2.0");
-  DoUpdateCheck(id, "throttled", "");
-
-  // Reload the extension, causing the delayed update to v2 to happen, then do
-  // another update check - we should get a no_update instead of throttled.
-  service()->ReloadExtension(id);
-  const Extension* current =
-      ExtensionRegistry::Get(browser_context())->GetInstalledExtension(id);
-  ASSERT_NE(nullptr, current);
-  EXPECT_EQ("2.0", current->VersionString());
-  clock_.Advance(base::TimeDelta::FromSeconds(10));
-  downloader_test_delegate_.AddNoUpdateResponse(id);
-  DoUpdateCheck(id, "no_update", "");
-
-  // Check again after short delay; we should be throttled.
-  clock_.Advance(base::TimeDelta::FromMinutes(5));
-  DoUpdateCheck(id, "throttled", "");
-
-  // Call again after a longer delay, we should should be unthrottled.
-  clock_.Advance(base::TimeDelta::FromHours(8));
-  downloader_test_delegate_.AddNoUpdateResponse(id);
-  DoUpdateCheck(id, "no_update", "");
-}
-
-}  // namespace
-
-}  // namespace extensions
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index a16b493..43f3ca0 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -518,8 +518,7 @@
                  << " because it is not installed or pending";
     // Delete extension_path since we're not creating a CrxInstaller
     // that would do it for us.
-    if (file_ownership_passed &&
-        !GetFileTaskRunner()->PostTask(
+    if (!GetFileTaskRunner()->PostTask(
             FROM_HERE,
             base::Bind(&extensions::file_util::DeleteFile, file.path, false)))
       NOTREACHED();
@@ -692,12 +691,12 @@
 }
 
 void ExtensionService::ReloadExtension(const std::string& extension_id) {
-  ReloadExtensionImpl(extension_id, true);  // be_noisy
+  ReloadExtensionImpl(extension_id, true); // be_noisy
 }
 
 void ExtensionService::ReloadExtensionWithQuietFailure(
     const std::string& extension_id) {
-  ReloadExtensionImpl(extension_id, false);  // be_noisy
+  ReloadExtensionImpl(extension_id, false); // be_noisy
 }
 
 bool ExtensionService::UninstallExtension(
diff --git a/chrome/browser/extensions/updater/extension_updater.cc b/chrome/browser/extensions/updater/extension_updater.cc
index 484029f7..bd93ba3 100644
--- a/chrome/browser/extensions/updater/extension_updater.cc
+++ b/chrome/browser/extensions/updater/extension_updater.cc
@@ -60,6 +60,10 @@
 #endif
 const int kMaxUpdateFrequencySeconds = 60 * 60 * 24 * 7;  // 7 days
 
+// Require at least 5 seconds between consecutive non-succesful extension update
+// checks.
+const int kMinUpdateThrottleTime = 5;
+
 // When we've computed a days value, we want to make sure we don't send a
 // negative value (due to the system clock being set backwards, etc.), since -1
 // is a special sentinel value that means "never pinged", and other negative
@@ -125,6 +129,17 @@
 
 ExtensionUpdater::InProgressCheck::~InProgressCheck() {}
 
+struct ExtensionUpdater::ThrottleInfo {
+  ThrottleInfo()
+      : in_progress(true),
+        throttle_delay(kMinUpdateThrottleTime),
+        check_start(Time::Now()) {}
+
+  bool in_progress;
+  int throttle_delay;
+  Time check_start;
+};
+
 ExtensionUpdater::ExtensionUpdater(
     ExtensionServiceInterface* service,
     ExtensionPrefs* extension_prefs,
@@ -142,6 +157,7 @@
       prefs_(prefs),
       profile_(profile),
       next_request_id_(0),
+      extension_registry_observer_(this),
       crx_install_is_running_(false),
       extension_cache_(cache),
       weak_ptr_factory_(this) {
@@ -152,6 +168,8 @@
   frequency_seconds_ = std::max(frequency_seconds_, kMinUpdateFrequencySeconds);
 #endif
   frequency_seconds_ = std::min(frequency_seconds_, kMaxUpdateFrequencySeconds);
+
+  extension_registry_observer_.Add(ExtensionRegistry::Get(profile));
 }
 
 ExtensionUpdater::~ExtensionUpdater() {
@@ -404,12 +422,56 @@
     NotifyIfFinished(request_id);
 }
 
-void ExtensionUpdater::CheckExtensionSoon(const std::string& extension_id,
+bool ExtensionUpdater::CheckExtensionSoon(const std::string& extension_id,
                                           const FinishedCallback& callback) {
+  bool have_throttle_info = ContainsKey(throttle_info_, extension_id);
+  ThrottleInfo& info = throttle_info_[extension_id];
+  if (have_throttle_info) {
+    // We already had a ThrottleInfo object for this extension, check if the
+    // update check request should be allowed.
+
+    // If another check is in progress, don't start a new check.
+    if (info.in_progress)
+      return false;
+
+    Time now = Time::Now();
+    Time last = info.check_start;
+    // If somehow time moved back, we don't want to infinitely keep throttling.
+    if (now < last) {
+      last = now;
+      info.check_start = now;
+    }
+    Time earliest = last + TimeDelta::FromSeconds(info.throttle_delay);
+    // If check is too soon, throttle.
+    if (now < earliest)
+      return false;
+
+    // TODO(mek): Somehow increase time between allowing checks when checks
+    // are repeatedly throttled and don't result in updates being installed.
+
+    // It's okay to start a check, update values.
+    info.check_start = now;
+    info.in_progress = true;
+  }
+
   CheckParams params;
   params.ids.push_back(extension_id);
-  params.callback = callback;
+  params.callback = base::Bind(&ExtensionUpdater::ExtensionCheckFinished,
+                               weak_ptr_factory_.GetWeakPtr(),
+                               extension_id, callback);
   CheckNow(params);
+  return true;
+}
+
+void ExtensionUpdater::ExtensionCheckFinished(
+    const std::string& extension_id,
+    const FinishedCallback& callback) {
+  std::map<std::string, ThrottleInfo>::iterator it =
+      throttle_info_.find(extension_id);
+  if (it != throttle_info_.end()) {
+    it->second.in_progress = false;
+  }
+  callback.Run();
 }
 
 void ExtensionUpdater::OnExtensionDownloadFailed(
@@ -597,6 +659,14 @@
   MaybeInstallCRXFile();
 }
 
+void ExtensionUpdater::OnExtensionWillBeInstalled(
+    content::BrowserContext* browser_context,
+    const Extension* extension,
+    bool is_update,
+    const std::string& old_name) {
+  throttle_info_.erase(extension->id());
+}
+
 void ExtensionUpdater::NotifyStarted() {
   content::NotificationService::current()->Notify(
       extensions::NOTIFICATION_EXTENSION_UPDATING_STARTED,
diff --git a/chrome/browser/extensions/updater/extension_updater.h b/chrome/browser/extensions/updater/extension_updater.h
index 92851e8..d2568296 100644
--- a/chrome/browser/extensions/updater/extension_updater.h
+++ b/chrome/browser/extensions/updater/extension_updater.h
@@ -56,6 +56,7 @@
 // ....
 // updater->Stop();
 class ExtensionUpdater : public ExtensionDownloaderDelegate,
+                         public ExtensionRegistryObserver,
                          public content::NotificationObserver {
  public:
   typedef base::Closure FinishedCallback;
@@ -103,8 +104,10 @@
   // already a pending task that has not yet run.
   void CheckSoon();
 
-  // Starts an update check for the specified extension soon.
-  void CheckExtensionSoon(const std::string& extension_id,
+  // Starts an update check for the specified extension soon. If a check
+  // is already running, or finished too recently without an update being
+  // installed, this method returns false and the check won't be scheduled.
+  bool CheckExtensionSoon(const std::string& extension_id,
                           const FinishedCallback& callback);
 
   // Starts an update check right now, instead of waiting for the next
@@ -155,6 +158,8 @@
     std::list<std::string> in_progress_ids_;
   };
 
+  struct ThrottleInfo;
+
   // Ensure that we have a valid ExtensionDownloader instance referenced by
   // |downloader|.
   void EnsureDownloaderCreated();
@@ -209,6 +214,12 @@
                const content::NotificationSource& source,
                const content::NotificationDetails& details) override;
 
+  // Implementation of ExtensionRegistryObserver.
+  void OnExtensionWillBeInstalled(content::BrowserContext* browser_context,
+                                  const Extension* extension,
+                                  bool is_update,
+                                  const std::string& old_name) override;
+
   // Send a notification that update checks are starting.
   void NotifyStarted();
 
@@ -245,6 +256,9 @@
   // Observes CRX installs we initiate.
   content::NotificationRegistrar registrar_;
 
+  ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
+      extension_registry_observer_;
+
   // True when a CrxInstaller is doing an install.  Used in MaybeUpdateCrxFile()
   // to keep more than one install from running at once.
   bool crx_install_is_running_;
@@ -255,6 +269,10 @@
 
   ExtensionCache* extension_cache_;
 
+  // Keeps track of when an extension tried to update itself, so we can throttle
+  // checks to prevent too many requests from being made.
+  std::map<std::string, ThrottleInfo> throttle_info_;
+
   base::WeakPtrFactory<ExtensionUpdater> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ExtensionUpdater);
diff --git a/chrome/browser/media/media_stream_devices_controller.cc b/chrome/browser/media/media_stream_devices_controller.cc
index 47e68a1..ab5ed91 100644
--- a/chrome/browser/media/media_stream_devices_controller.cc
+++ b/chrome/browser/media/media_stream_devices_controller.cc
@@ -306,6 +306,11 @@
   delete this;
 }
 
+PermissionBubbleType MediaStreamDevicesController::GetPermissionBubbleType()
+    const {
+  return PermissionBubbleType::MEDIA_STREAM;
+}
+
 content::MediaStreamDevices MediaStreamDevicesController::GetDevices(
     ContentSetting audio_setting,
     ContentSetting video_setting) {
diff --git a/chrome/browser/media/media_stream_devices_controller.h b/chrome/browser/media/media_stream_devices_controller.h
index 90c19b5..6d58371 100644
--- a/chrome/browser/media/media_stream_devices_controller.h
+++ b/chrome/browser/media/media_stream_devices_controller.h
@@ -58,6 +58,7 @@
   void PermissionDenied() override;
   void Cancelled() override;
   void RequestFinished() override;
+  PermissionBubbleType GetPermissionBubbleType() const override;
 
  private:
   // Returns a list of devices available for the request for the given
diff --git a/chrome/browser/metrics/chromeos_metrics_provider.cc b/chrome/browser/metrics/chromeos_metrics_provider.cc
index baa8917..9e867c2 100644
--- a/chrome/browser/metrics/chromeos_metrics_provider.cc
+++ b/chrome/browser/metrics/chromeos_metrics_provider.cc
@@ -228,12 +228,19 @@
     metrics::ChromeUserMetricsExtension* uma_proto) {
   std::vector<SampledProfile> sampled_profiles;
   if (perf_provider_.GetSampledProfiles(&sampled_profiles)) {
-    for (std::vector<SampledProfile>::iterator iter = sampled_profiles.begin();
-         iter != sampled_profiles.end();
-         ++iter) {
-      uma_proto->add_sampled_profile()->Swap(&(*iter));
+    for (auto& profile : sampled_profiles) {
+      uma_proto->add_sampled_profile()->Swap(&profile);
     }
   }
+
+  if (leak_detector_controller_) {
+    std::vector<metrics::MemoryLeakReportProto> reports;
+    leak_detector_controller_->GetLeakReports(&reports);
+    for (auto& report : reports) {
+      uma_proto->add_memory_leak_report()->Swap(&report);
+    }
+  }
+
   RecordEnrollmentStatus();
 }
 
diff --git a/chrome/browser/permissions/permission_bubble_request_impl.cc b/chrome/browser/permissions/permission_bubble_request_impl.cc
index 99f5318..dfbe7c2 100644
--- a/chrome/browser/permissions/permission_bubble_request_impl.cc
+++ b/chrome/browser/permissions/permission_bubble_request_impl.cc
@@ -163,3 +163,8 @@
   is_finished_ = true;
   delete_callback_.Run();
 }
+
+PermissionBubbleType PermissionBubbleRequestImpl::GetPermissionBubbleType()
+    const {
+  return PermissionBubbleType::PERMISSION;
+}
diff --git a/chrome/browser/permissions/permission_bubble_request_impl.h b/chrome/browser/permissions/permission_bubble_request_impl.h
index 5e1a470e..75e2bf3 100644
--- a/chrome/browser/permissions/permission_bubble_request_impl.h
+++ b/chrome/browser/permissions/permission_bubble_request_impl.h
@@ -30,6 +30,10 @@
 
   ~PermissionBubbleRequestImpl() override;
 
+ protected:
+  void RegisterActionTaken() { action_taken_ = true; }
+
+ private:
   // PermissionBubbleRequest:
   gfx::VectorIconId GetVectorIconId() const override;
   int GetIconId() const override;
@@ -42,11 +46,8 @@
   void PermissionDenied() override;
   void Cancelled() override;
   void RequestFinished() override;
+  PermissionBubbleType GetPermissionBubbleType() const override;
 
- protected:
-  void RegisterActionTaken() { action_taken_ = true; }
-
- private:
   GURL request_origin_;
   content::PermissionType permission_type_;
 
diff --git a/chrome/browser/permissions/permission_uma_util.cc b/chrome/browser/permissions/permission_uma_util.cc
index 1195256..8d38d045 100644
--- a/chrome/browser/permissions/permission_uma_util.cc
+++ b/chrome/browser/permissions/permission_uma_util.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/permissions/permission_manager.h"
 #include "chrome/browser/permissions/permission_util.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/website_settings/permission_bubble_request.h"
 #include "components/rappor/rappor_service.h"
 #include "components/rappor/rappor_utils.h"
 #include "content/public/browser/permission_type.h"
@@ -274,3 +275,15 @@
     RecordPermissionAction(permission, REVOKED, revoked_origin);
   }
 }
+
+void PermissionUmaUtil::PermissionPromptShown(
+    const std::vector<PermissionBubbleRequest*>& requests) {
+  DCHECK(!requests.empty());
+  PermissionBubbleType permission_prompt_type = PermissionBubbleType::MULTIPLE;
+  if (requests.size() == 1)
+    permission_prompt_type = requests[0]->GetPermissionBubbleType();
+  UMA_HISTOGRAM_ENUMERATION(
+      "Permissions.Prompt.Shown",
+      static_cast<base::HistogramBase::Sample>(permission_prompt_type),
+      static_cast<base::HistogramBase::Sample>(PermissionBubbleType::NUM));
+}
diff --git a/chrome/browser/permissions/permission_uma_util.h b/chrome/browser/permissions/permission_uma_util.h
index 1f5f24b..c4c8001 100644
--- a/chrome/browser/permissions/permission_uma_util.h
+++ b/chrome/browser/permissions/permission_uma_util.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_PERMISSIONS_PERMISSION_UMA_UTIL_H_
 #define CHROME_BROWSER_PERMISSIONS_PERMISSION_UMA_UTIL_H_
 
+#include <vector>
+
 #include "base/logging.h"
 #include "base/macros.h"
 
@@ -15,6 +17,8 @@
 enum class PermissionType;
 }  // namespace content
 
+class PermissionBubbleRequest;
+
 // Enum for UMA purposes, make sure you update histograms.xml if you add new
 // permission actions. Never delete or reorder an entry; only add new entries
 // immediately before PERMISSION_NUM
@@ -49,6 +53,18 @@
   static void PermissionRevoked(content::PermissionType permission,
                                 const GURL& revoked_origin);
 
+  // UMA specifically for when permission prompts are shown. This should be
+  // roughly equivalent to the metrics above, however it is
+  // useful to have separate UMA to a few reasons:
+  // - to account for, and get data on coalesced permission bubbles
+  // - there are other types of permissions prompts (e.g. download limiting)
+  //   which don't go through PermissionContext
+  // - the above metrics don't always add up (e.g. sum of
+  //   granted+denied+dismissed+ignored is not equal to requested), so it is
+  //   unclear from those metrics alone how many prompts are seen by users.
+  static void PermissionPromptShown(
+      const std::vector<PermissionBubbleRequest*>& requests);
+
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(PermissionUmaUtil);
 };
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
index b9a9bda..6b164f4 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
@@ -1,6 +1,7 @@
 <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/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.html">
 <link rel="import" href="chrome://md-settings/controls/settings_checkbox.html">
@@ -10,7 +11,13 @@
 
 <dom-module id="settings-clear-browsing-data-dialog">
   <template>
-    <style include="settings-shared"></style>
+    <style include="settings-shared">
+      paper-spinner {
+        margin-bottom: auto;
+        margin-top: auto;
+        -webkit-margin-end: 16px;
+      }
+    </style>
     <settings-dialog id="dialog">
       <div class="title" i18n-content="clearBrowsingData"></div>
       <div class="body">
@@ -55,10 +62,11 @@
         </settings-checkbox>
       </div>
       <div class="button-container">
+        <paper-spinner active="[[clearingInProgress_]]"></paper-spinner>
         <paper-button class="cancel-button" i18n-content="cancel"
-            dialog-dismiss></paper-button>
-        <paper-button class="action-button" id="clearBrowsingData"
-            i18n-content="clearBrowsingData" on-tap="onClearBrowsingDataTap_">
+            dialog-dismiss disabled="[[clearingInProgress_]]"></paper-button>
+        <paper-button class="action-button" i18n-content="clearBrowsingData"
+            on-tap="onClearBrowsingDataTap_" disabled="[[clearingInProgress_]]">
         </paper-button>
       </div>
       <div class="footer">
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
index b6b045d..381b54f 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
@@ -35,6 +35,9 @@
         {value: 4, name: loadTimeData.getString('clearDataEverything')},
       ],
     },
+
+    /** @private */
+    clearingInProgress_: Boolean,
   },
 
   /** @private {!settings.ClearBrowsingDataBrowserProxy} */
@@ -69,9 +72,9 @@
 
   /** @private */
   onClearBrowsingDataTap_: function() {
-    // TODO(dpapad): Show spinner, disable buttons here.
+    this.clearingInProgress_ = true;
     this.browserProxy_.clearBrowsingData().then(function() {
-      // TODO(dpapad): Hide spinner, re-enable buttons here.
+      this.clearingInProgress_ = false;
       this.$.dialog.close();
     }.bind(this));
   },
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 691428c..d7ff874 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -436,7 +436,7 @@
   // Cancel any pending tab transition.
   hover_tab_selector_.CancelTabTransition();
 
-  tabstrip_->RemoveTabAt(model_index);
+  tabstrip_->RemoveTabAt(contents, model_index);
 }
 
 void BrowserTabStripController::TabSelectionChanged(
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 3f79b7f..44a03a3 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
@@ -34,7 +34,7 @@
 
 void FakeBaseTabStripController::RemoveTab(int index) {
   num_tabs_--;
-  tab_strip_->RemoveTabAt(index);
+  tab_strip_->RemoveTabAt(nullptr, index);
   if (active_index_ == index)
     active_index_ = -1;
 }
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
index 4867955..e2d6d410 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -24,10 +24,8 @@
 #include "chrome/browser/ui/views/tabs/tab.h"
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
 #include "chrome/browser/ui/views/tabs/window_finder.h"
-#include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
 #include "content/public/browser/user_metrics.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/extension_function_dispatcher.h"
@@ -336,6 +334,14 @@
   move_behavior_ = behavior;
 }
 
+bool TabDragController::IsDraggingTab(content::WebContents* contents) {
+  for (auto drag_data : drag_data_) {
+    if (drag_data.contents == contents)
+      return true;
+  }
+  return false;
+}
+
 void TabDragController::Drag(const gfx::Point& point_in_screen) {
   TRACE_EVENT1("views", "TabDragController::Drag",
                "point_in_screen", point_in_screen.ToString());
@@ -412,32 +418,6 @@
   drag_data->contents = GetModel(source_tabstrip_)->GetWebContentsAt(
       drag_data->source_model_index);
   drag_data->pinned = source_tabstrip_->IsTabPinned(tab);
-  registrar_.Add(
-      this,
-      content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
-      content::Source<WebContents>(drag_data->contents));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TabDragController, content::NotificationObserver implementation:
-
-void TabDragController::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  DCHECK_EQ(content::NOTIFICATION_WEB_CONTENTS_DESTROYED, type);
-  WebContents* destroyed_web_contents =
-      content::Source<WebContents>(source).ptr();
-  for (size_t i = 0; i < drag_data_.size(); ++i) {
-    if (drag_data_[i].contents == destroyed_web_contents) {
-      // One of the tabs we're dragging has been destroyed. Cancel the drag.
-      drag_data_[i].contents = NULL;
-      EndDragImpl(TAB_DESTROYED);
-      return;
-    }
-  }
-  // If we get here it means we got notification for a tab we don't know about.
-  NOTREACHED();
 }
 
 void TabDragController::OnWidgetBoundsChanged(views::Widget* widget,
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.h b/chrome/browser/ui/views/tabs/tab_drag_controller.h
index 284bef2..318766083 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.h
@@ -16,8 +16,6 @@
 #include "base/timer/timer.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_types.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
 #include "ui/base/models/list_selection_model.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
@@ -52,8 +50,7 @@
 // that the tabs should be moved out of the tab strip a new Browser is created
 // and RunMoveLoop() is invoked on the Widget to drag the browser around. This
 // is the default on aura.
-class TabDragController : public content::NotificationObserver,
-                          public views::WidgetObserver,
+class TabDragController : public views::WidgetObserver,
                           public TabStripModelObserver {
  public:
   // What should happen as the mouse is dragged within the tabstrip.
@@ -125,6 +122,9 @@
   // move message loop.
   bool is_dragging_window() const { return is_dragging_window_; }
 
+  // Returns true if currently dragging a tab with |contents|.
+  bool IsDraggingTab(content::WebContents* contents);
+
   // Invoked to drag to the new location, in screen coordinates.
   void Drag(const gfx::Point& point_in_screen);
 
@@ -220,11 +220,6 @@
   // notifications and resets the delegate of the WebContents.
   void InitTabDragData(Tab* tab, TabDragData* drag_data);
 
-  // Overridden from content::NotificationObserver:
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
-
   // Overriden from views::WidgetObserver:
   void OnWidgetBoundsChanged(views::Widget* widget,
                              const gfx::Rect& new_bounds) override;
@@ -383,7 +378,7 @@
   // Restores |initial_selection_model_| to the |source_tabstrip_|.
   void RestoreInitialSelection();
 
-  // Finishes a succesful drag operation.
+  // Finishes a successful drag operation.
   void CompleteDrag();
 
   // Maximizes the attached window.
@@ -463,9 +458,6 @@
                                  bool exclude_dragged_view,
                                  gfx::NativeWindow* window) WARN_UNUSED_RESULT;
 
-  // Handles registering for notifications.
-  content::NotificationRegistrar registrar_;
-
   EventSource event_source_;
 
   // The TabStrip the drag originated from.
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index ce7f56d..b720a77 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -57,7 +57,8 @@
 #include "ash/display/display_manager.h"
 #include "ash/shell.h"
 #include "ash/test/cursor_manager_test_api.h"
-#include "ash/wm/coordinate_conversion.h"
+#include "ash/wm/aura/wm_window_aura.h"
+#include "ash/wm/common/root_window_finder.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_state_aura.h"
 #include "ash/wm/window_util.h"
@@ -387,7 +388,8 @@
       return;
 #if defined(OS_CHROMEOS)
     event_generator_.reset(new ui::test::EventGenerator(
-        new ScreenEventGeneratorDelegate(ash::wm::GetRootWindowAt(point))));
+        new ScreenEventGeneratorDelegate(ash::wm::WmWindowAura::GetAuraWindow(
+            ash::wm::GetRootWindowAt(point)))));
 #endif
   }
 
@@ -1140,10 +1142,8 @@
   ASSERT_FALSE(tab_strip->IsDragSessionActive());
   ASSERT_FALSE(TabDragController::IsActive());
 
-  // Only tab "1" gets closed; tab "2" which was also selected gets restored.
-  // TODO(varkha): fix this expectation once closing a tab while dragging
-  // stops the drag and causes all selected tabs to get closed.
-  EXPECT_EQ("0 3 2", IDString(browser()->tab_strip_model()));
+  // Both tabs "1" and "2" get closed.
+  EXPECT_EQ("0 3", IDString(browser()->tab_strip_model()));
 
   EXPECT_FALSE(GetIsDragged(browser()));
 }
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 287ad82..e540f84 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -835,7 +835,7 @@
                     TabStripMovedTab(this, from_model_index, to_model_index));
 }
 
-void TabStrip::RemoveTabAt(int model_index) {
+void TabStrip::RemoveTabAt(content::WebContents* contents, int model_index) {
   if (touch_layout_) {
     Tab* tab = tab_at(model_index);
     tab->set_closing(true);
@@ -855,6 +855,21 @@
 
   FOR_EACH_OBSERVER(TabStripObserver, observers_,
                     TabStripRemovedTabAt(this, model_index));
+
+  // Stop dragging when a new tab is removed and dragging a window. Doing
+  // otherwise results in a confusing state if the user attempts to reattach. We
+  // could allow this and make TabDragController update itself during the
+  // remove operation, but this comes up infrequently enough that it's not worth
+  // the complexity.
+  //
+  // At the start of RemoveTabAt() the model and tabs are out sync. Any queries
+  // to find a tab given a model index can go off the end of |tabs_|. As such,
+  // it is important that we complete the drag *after* removing the tab so that
+  // the model and tabstrip are in sync.
+  if (contents && drag_controller_.get() && !drag_controller_->is_mutating() &&
+      drag_controller_->IsDraggingTab(contents)) {
+    EndDrag(END_DRAG_COMPLETE);
+  }
 }
 
 void TabStrip::SetTabData(int model_index, const TabRendererData& data) {
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
index 58e03c60..fe80352d 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.h
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -101,8 +101,9 @@
                int to_model_index,
                const TabRendererData& data);
 
-  // Removes a tab at the specified index.
-  void RemoveTabAt(int model_index);
+  // Removes a tab at the specified index. If the tab with |contents| is being
+  // dragged then the drag is completed.
+  void RemoveTabAt(content::WebContents* contents, int model_index);
 
   // Sets the tab data at the specified model index.
   void SetTabData(int model_index, const TabRendererData& data);
diff --git a/chrome/browser/ui/views/tabs/window_finder_ash.cc b/chrome/browser/ui/views/tabs/window_finder_ash.cc
index 1628a82..e9d76f4 100644
--- a/chrome/browser/ui/views/tabs/window_finder_ash.cc
+++ b/chrome/browser/ui/views/tabs/window_finder_ash.cc
@@ -5,7 +5,8 @@
 #include "chrome/browser/ui/views/tabs/window_finder.h"
 
 #include "ash/shell_window_ids.h"
-#include "ash/wm/coordinate_conversion.h"
+#include "ash/wm/aura/wm_window_aura.h"
+#include "ash/wm/common/root_window_finder.h"
 #include "ui/aura/client/screen_position_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -56,5 +57,6 @@
     const gfx::Point& screen_point,
     const std::set<gfx::NativeWindow>& ignore) {
   return GetLocalProcessWindowAtPointImpl(
-      screen_point, ignore, ::ash::wm::GetRootWindowAt(screen_point));
+      screen_point, ignore, ash::wm::WmWindowAura::GetAuraWindow(
+                                ash::wm::GetRootWindowAt(screen_point)));
 }
diff --git a/chrome/browser/ui/website_settings/permission_bubble_manager.cc b/chrome/browser/ui/website_settings/permission_bubble_manager.cc
index 194ae9c..cb3739c 100644
--- a/chrome/browser/ui/website_settings/permission_bubble_manager.cc
+++ b/chrome/browser/ui/website_settings/permission_bubble_manager.cc
@@ -9,6 +9,7 @@
 #include "base/command_line.h"
 #include "base/metrics/user_metrics_action.h"
 #include "build/build_config.h"
+#include "chrome/browser/permissions/permission_uma_util.h"
 #include "chrome/browser/ui/website_settings/permission_bubble_request.h"
 #include "chrome/common/chrome_switches.h"
 #include "content/public/browser/browser_thread.h"
@@ -385,6 +386,7 @@
   }
 
   view_->Show(requests_, accept_states_);
+  PermissionUmaUtil::PermissionPromptShown(requests_);
   NotifyBubbleAdded();
 
   // If in testing mode, automatically respond to the bubble that was shown.
diff --git a/chrome/browser/ui/website_settings/permission_bubble_request.cc b/chrome/browser/ui/website_settings/permission_bubble_request.cc
index 8597f62..62afb9f 100644
--- a/chrome/browser/ui/website_settings/permission_bubble_request.cc
+++ b/chrome/browser/ui/website_settings/permission_bubble_request.cc
@@ -9,3 +9,7 @@
 gfx::VectorIconId PermissionBubbleRequest::GetVectorIconId() const {
   return gfx::VectorIconId::VECTOR_ICON_NONE;
 }
+
+PermissionBubbleType PermissionBubbleRequest::GetPermissionBubbleType() const {
+  return PermissionBubbleType::UNKNOWN;
+}
diff --git a/chrome/browser/ui/website_settings/permission_bubble_request.h b/chrome/browser/ui/website_settings/permission_bubble_request.h
index 9da18802..50692c8 100644
--- a/chrome/browser/ui/website_settings/permission_bubble_request.h
+++ b/chrome/browser/ui/website_settings/permission_bubble_request.h
@@ -12,6 +12,25 @@
 enum class VectorIconId;
 }
 
+// Used for UMA to record the types of permission prompts shown.
+// This corresponds to the PermissionBubbleType enum in
+// src/tools/metrics/histograms.xml. The usual rules of updating UMA values
+// applies to this enum:
+// - don't remove values
+// - only ever add values at the end
+// - keep the PermissionBubbleType enum in sync with this definition.
+enum class PermissionBubbleType {
+  UNKNOWN,
+  MULTIPLE,
+  PERMISSION,
+  QUOTA,
+  DOWNLOAD,
+  MEDIA_STREAM,
+  REGISTER_PROTOCOL_HANDLER,
+  // NUM must be the last value in the enum.
+  NUM
+};
+
 // Describes the interface a feature utilizing permission bubbles should
 // implement. A class of this type is registered with the permission bubble
 // manager to receive updates about the result of the permissions request
@@ -62,6 +81,8 @@
   // no further message from the permission bubble system. This method will
   // eventually be called on every request which is not unregistered.
   virtual void RequestFinished() = 0;
+
+  virtual PermissionBubbleType GetPermissionBubbleType() const;
 };
 
 #endif  // CHROME_BROWSER_UI_WEBSITE_SETTINGS_PERMISSION_BUBBLE_REQUEST_H_
diff --git a/chrome/browser/ui/website_settings/permission_ui_uma_util.cc b/chrome/browser/ui/website_settings/permission_ui_uma_util.cc
new file mode 100644
index 0000000..b97b05f
--- /dev/null
+++ b/chrome/browser/ui/website_settings/permission_ui_uma_util.cc
@@ -0,0 +1,19 @@
+// 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/ui/website_settings/permission_ui_uma_util.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "chrome/browser/ui/website_settings/permission_bubble_request.h"
+
+void PermissionUiUmaUtil::PermissionPromptShown(
+    const std::vector<PermissionBubbleRequest*>& requests) {
+  PermissionBubbleType permission_prompt_type = PermissionBubbleType::MULTIPLE;
+  if (requests.size() == 1)
+    permission_prompt_type = requests[0]->GetPermissionBubbleType();
+  UMA_HISTOGRAM_ENUMERATION(
+      "Permissions.Prompt.Shown",
+      static_cast<base::HistogramBase::Sample>(permission_prompt_type),
+      static_cast<base::HistogramBase::Sample>(PermissionBubbleType::NUM));
+}
diff --git a/chrome/browser/ui/webui/options/password_manager_handler.cc b/chrome/browser/ui/webui/options/password_manager_handler.cc
index 404018f3..66c9effe 100644
--- a/chrome/browser/ui/webui/options/password_manager_handler.cc
+++ b/chrome/browser/ui/webui/options/password_manager_handler.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
-#include "base/debug/leak_annotations.h"
 #include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
@@ -326,10 +325,8 @@
   DCHECK(!file_type_info.extensions.empty() &&
          !file_type_info.extensions[0].empty());
   file_type_info.include_all_files = true;
-  ChromeSelectFilePolicy* select_file_policy =
-      new ChromeSelectFilePolicy(web_ui()->GetWebContents());
-  ANNOTATE_LEAKING_OBJECT_PTR(select_file_policy);
-  select_file_dialog_ = ui::SelectFileDialog::Create(this, select_file_policy);
+  select_file_dialog_ = ui::SelectFileDialog::Create(
+      this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
   select_file_dialog_->SelectFile(
       ui::SelectFileDialog::SELECT_OPEN_FILE,
       l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_IMPORT_DIALOG_TITLE),
@@ -391,10 +388,8 @@
   DCHECK(!file_type_info.extensions.empty() &&
          !file_type_info.extensions[0].empty());
   file_type_info.include_all_files = true;
-  ChromeSelectFilePolicy* select_file_policy =
-      new ChromeSelectFilePolicy(web_ui()->GetWebContents());
-  ANNOTATE_LEAKING_OBJECT_PTR(select_file_policy);
-  select_file_dialog_ = ui::SelectFileDialog::Create(this, select_file_policy);
+  select_file_dialog_ = ui::SelectFileDialog::Create(
+      this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
   select_file_dialog_->SelectFile(
       ui::SelectFileDialog::SELECT_SAVEAS_FILE,
       l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EXPORT_DIALOG_TITLE),
diff --git a/chrome/browser/ui/webui/options/password_manager_handler_unittest.cc b/chrome/browser/ui/webui/options/password_manager_handler_unittest.cc
index e3bf459..6605a28 100644
--- a/chrome/browser/ui/webui/options/password_manager_handler_unittest.cc
+++ b/chrome/browser/ui/webui/options/password_manager_handler_unittest.cc
@@ -25,12 +25,14 @@
 using password_manager::MockPasswordStore;
 
 namespace {
+
 class TestSelectFileDialogFactory final : public ui::SelectFileDialogFactory {
  public:
   TestSelectFileDialogFactory() {}
   ~TestSelectFileDialogFactory() override {}
   ui::SelectFileDialog* Create(ui::SelectFileDialog::Listener* listener,
                                ui::SelectFilePolicy* policy) override {
+    delete policy;  // Ignore the policy, replace it with a test one.
     return new TestSelectFileDialog(listener, new TestSelectFilePolicy);
   }
 
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 82332eb..70ec0b87 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -454,7 +454,6 @@
       'browser/extensions/api/permissions/permissions_api_helpers_unittest.cc',
       'browser/extensions/api/preference/preference_api_prefs_unittest.cc',
       'browser/extensions/api/proxy/proxy_api_helpers_unittest.cc',
-      'browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc',
       'browser/extensions/api/signed_in_devices/id_mapping_helper_unittest.cc',
       'browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc',
       'browser/extensions/api/signed_in_devices/signed_in_devices_manager_unittest.cc',
@@ -914,9 +913,9 @@
       # TODO(lukasza): Move Drive tests outside of CrOS (crbug.com/498951).
       '../components/drive/change_list_loader_unittest.cc',
       '../components/drive/change_list_processor_unittest.cc',
+      '../components/drive/chromeos/file_cache_unittest.cc',
       '../components/drive/directory_loader_unittest.cc',
       '../components/drive/fake_file_system_unittest.cc',
-      '../components/drive/file_cache_unittest.cc',
       '../components/drive/file_change_unittest.cc',
       '../components/drive/file_system/copy_operation_unittest.cc',
       '../components/drive/file_system/create_directory_operation_unittest.cc',
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js
index 5ed9efa..43c5960b 100644
--- a/chrome/test/data/webui/settings/cr_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -320,6 +320,7 @@
 
   /** @override */
   extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([
+    ROOT_PATH + 'ui/webui/resources/js/promise_resolver.js',
     'test_browser_proxy.js',
     'privacy_page_test.js',
   ]),
diff --git a/chrome/test/data/webui/settings/privacy_page_test.js b/chrome/test/data/webui/settings/privacy_page_test.js
index 120096c..e7474b7 100644
--- a/chrome/test/data/webui/settings/privacy_page_test.js
+++ b/chrome/test/data/webui/settings/privacy_page_test.js
@@ -28,15 +28,29 @@
    */
   function TestClearBrowsingDataBrowserProxy() {
     settings.TestBrowserProxy.call(this, ['clearBrowsingData']);
+
+    /**
+     * The promise to return from |clearBrowsingData|.
+     * Allows testing code to test what happens after the call is made, and
+     * before the browser responds.
+     * @private {?Promise}
+     */
+    this.clearBrowsingDataPromise_ = null;
   }
 
   TestClearBrowsingDataBrowserProxy.prototype = {
     __proto__: settings.TestBrowserProxy.prototype,
 
+    /** @param {!Promise} promise */
+    setClearBrowsingDataPromise: function(promise) {
+      this.clearBrowsingDataPromise_ = promise;
+    },
+
     /** @override */
     clearBrowsingData: function() {
       this.methodCalled('clearBrowsingData');
-      return Promise.resolve();
+      return this.clearBrowsingDataPromise_ !== null ?
+          this.clearBrowsingDataPromise_ : Promise.resolve();
     },
   };
 
@@ -86,13 +100,40 @@
       test('ClearBrowsingDataTap', function() {
         element.open();
         assertTrue(element.$.dialog.opened);
-        var clearBrowsingDataButton = element.$.clearBrowsingData;
-        assertTrue(!!clearBrowsingDataButton);
 
-        MockInteractions.tap(clearBrowsingDataButton);
+        var cancelButton = element.$$('.cancel-button');
+        assertTrue(!!cancelButton);
+        var actionButton = element.$$('.action-button');
+        assertTrue(!!actionButton);
+        var spinner = element.$$('paper-spinner');
+        assertTrue(!!spinner);
+
+        assertFalse(cancelButton.disabled);
+        assertFalse(actionButton.disabled);
+        assertFalse(spinner.active);
+
+        var promiseResolver = new PromiseResolver();
+        testBrowserProxy.setClearBrowsingDataPromise(promiseResolver.promise);
+        MockInteractions.tap(actionButton);
+
         return testBrowserProxy.whenCalled('clearBrowsingData').then(
             function() {
+              assertTrue(element.$.dialog.opened);
+              assertTrue(cancelButton.disabled);
+              assertTrue(actionButton.disabled);
+              assertTrue(spinner.active);
+
+              // Simulate signal from browser indicating that clearing has
+              // completed.
+              promiseResolver.resolve();
+              // Yields to the message loop to allow the callback chain of the
+              // Promise that was just resolved to execute before the
+              // assertions.
+            }).then(function() {
               assertFalse(element.$.dialog.opened);
+              assertFalse(cancelButton.disabled);
+              assertFalse(actionButton.disabled);
+              assertFalse(spinner.active);
             });
       });
     });
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index 244ff1c..2039ad0 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -493,6 +493,7 @@
       'password_manager/core/browser/psl_matching_helper_unittest.cc',
       'password_manager/core/browser/statistics_table_unittest.cc',
       'password_manager/core/common/credential_manager_types_unittest.cc',
+      'password_manager/sync/browser/password_manager_setting_migrator_service_unittest.cc',
       'password_manager/sync/browser/password_sync_util_unittest.cc',
       'password_manager/sync/browser/sync_credentials_filter_unittest.cc',
       'password_manager/sync/browser/sync_username_test_base.cc',
diff --git a/components/drive/chromeos/file_cache.cc b/components/drive/chromeos/file_cache.cc
index f3df512..a2eb6ea 100644
--- a/components/drive/chromeos/file_cache.cc
+++ b/components/drive/chromeos/file_cache.cc
@@ -4,6 +4,8 @@
 
 #include "components/drive/chromeos/file_cache.h"
 
+#include <unistd.h>
+
 #include <queue>
 #include <vector>
 
@@ -684,7 +686,8 @@
 
 // static
 bool FileCache::MigrateCacheFiles(const base::FilePath& from,
-                                  const base::FilePath& to,
+                                  const base::FilePath& to_files,
+                                  const base::FilePath& to_links,
                                   ResourceMetadataStorage* metadata_storage) {
   std::unique_ptr<ResourceMetadataStorage::Iterator> it =
       metadata_storage->GetIterator();
@@ -694,17 +697,31 @@
       continue;
     }
 
+    // Ignore missing cache file case since it never succeeds.
+    // TODO(yawano): handle this case at metadata validation in FileCache.
     const base::FilePath move_from = GetPathForId(from, entry.local_id());
     if (!base::PathExists(move_from)) {
       continue;
     }
 
-    const base::FilePath move_to = GetPathForId(to, entry.local_id());
+    // Create hard link to cache file if it's pinned or dirty. cryptohome will
+    // not delete a cache file if there is a hard link to it.
+    const FileCacheEntry& file_cache_entry =
+        entry.file_specific_info().cache_state();
+    if (file_cache_entry.is_pinned() || file_cache_entry.is_dirty()) {
+      const base::FilePath link_path = GetPathForId(to_links, entry.local_id());
+      int link_result = link(move_from.AsUTF8Unsafe().c_str(),
+                             link_path.AsUTF8Unsafe().c_str());
+      if (link_result != 0 && errno != EEXIST) {
+        return false;
+      }
+    }
+
+    // Move cache file.
+    const base::FilePath move_to = GetPathForId(to_files, entry.local_id());
     if (!base::Move(move_from, move_to)) {
       return false;
     }
-
-    // TODO(yawano): create hard link if entry is marked as pinned or dirty.
   }
 
   return true;
diff --git a/components/drive/chromeos/file_cache.h b/components/drive/chromeos/file_cache.h
index 2b9848e..23b104c9 100644
--- a/components/drive/chromeos/file_cache.h
+++ b/components/drive/chromeos/file_cache.h
@@ -158,10 +158,12 @@
       const ResourceMetadataStorage::RecoveredCacheInfoMap&
           recovered_cache_info);
 
-  // Migrates cache files from |from| directory to |to| directory. Returns true
-  // for success.
+  // Migrates cache files from |from| directory to |to_files| directory with
+  // creating links in |to_links| directory if necessary. Returns true for
+  // success.
   static bool MigrateCacheFiles(const base::FilePath& from,
-                                const base::FilePath& to,
+                                const base::FilePath& to_files,
+                                const base::FilePath& to_links,
                                 ResourceMetadataStorage* metadata_storage);
 
  private:
diff --git a/components/drive/file_cache_unittest.cc b/components/drive/chromeos/file_cache_unittest.cc
similarity index 86%
rename from components/drive/file_cache_unittest.cc
rename to components/drive/chromeos/file_cache_unittest.cc
index c60756a..7fd7b5d 100644
--- a/components/drive/file_cache_unittest.cc
+++ b/components/drive/chromeos/file_cache_unittest.cc
@@ -6,6 +6,9 @@
 
 #include <stddef.h>
 #include <stdint.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include <string>
 #include <vector>
@@ -37,9 +40,18 @@
     FILE_PATH_LITERAL("files");
 const base::FilePath::CharType kNewCacheFileDirectory[] =
     FILE_PATH_LITERAL("blobs");
+const base::FilePath::CharType kLinkDirectory[] = FILE_PATH_LITERAL("links");
 
 const int kTemporaryFileSizeInBytes = 10;
 
+int GetNumberOfLinks(const base::FilePath& file_path) {
+  struct stat result;
+  if (stat(file_path.AsUTF8Unsafe().c_str(), &result) != 0) {
+    return -1;
+  }
+  return result.st_nlink;
+}
+
 }  // namespace
 
 // Tests FileCache methods working with the blocking task runner.
@@ -709,8 +721,10 @@
       temp_dir_.path().Append(kCacheFileDirectory);
   const base::FilePath new_cache_dir =
       temp_dir_.path().Append(kNewCacheFileDirectory);
+  const base::FilePath link_dir = temp_dir_.path().Append(kLinkDirectory);
   ASSERT_TRUE(base::CreateDirectory(old_cache_dir));
   ASSERT_TRUE(base::CreateDirectory(new_cache_dir));
+  ASSERT_TRUE(base::CreateDirectory(link_dir));
 
   // Entry A: cache file in old cache directory with metadata.
   const std::string id_a = "id_a";
@@ -746,16 +760,107 @@
       true);
   ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_d));
 
+  // Entry E: pinned cache file.
+  const std::string id_e = "id_e";
+  ResourceEntry entry_e;
+  entry_e.set_local_id(id_e);
+  FileCacheEntry* file_cache_entry_e =
+      entry_e.mutable_file_specific_info()->mutable_cache_state();
+  file_cache_entry_e->set_is_present(true);
+  file_cache_entry_e->set_is_pinned(true);
+  file_cache_entry_e->set_is_dirty(false);
+  ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_e));
+  const base::FilePath old_file_path_e = old_cache_dir.AppendASCII(id_e);
+  const base::FilePath new_file_path_e = new_cache_dir.AppendASCII(id_e);
+  const base::FilePath link_path_e = link_dir.AppendASCII(id_e);
+  ASSERT_TRUE(base::CopyFile(temp_file, old_file_path_e));
+
+  // Entry F: dirty cache file.
+  const std::string id_f = "id_f";
+  ResourceEntry entry_f;
+  entry_f.set_local_id(id_f);
+  FileCacheEntry* file_cache_entry_f =
+      entry_f.mutable_file_specific_info()->mutable_cache_state();
+  file_cache_entry_f->set_is_present(true);
+  file_cache_entry_f->set_is_pinned(false);
+  file_cache_entry_f->set_is_dirty(true);
+  ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_f));
+  const base::FilePath old_file_path_f = old_cache_dir.AppendASCII(id_f);
+  const base::FilePath new_file_path_f = new_cache_dir.AppendASCII(id_f);
+  const base::FilePath link_path_f = link_dir.AppendASCII(id_f);
+  ASSERT_TRUE(base::CopyFile(temp_file, old_file_path_f));
+
+  // Entry G: partially migrated pinned cache file.
+  const std::string id_g = "id_g";
+  ResourceEntry entry_g;
+  entry_g.set_local_id(id_g);
+  FileCacheEntry* file_cache_entry_g =
+      entry_g.mutable_file_specific_info()->mutable_cache_state();
+  file_cache_entry_g->set_is_present(true);
+  file_cache_entry_g->set_is_pinned(true);
+  file_cache_entry_g->set_is_dirty(false);
+  ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_g));
+  const base::FilePath old_file_path_g = old_cache_dir.AppendASCII(id_g);
+  const base::FilePath new_file_path_g = new_cache_dir.AppendASCII(id_g);
+  const base::FilePath link_path_g = link_dir.AppendASCII(id_g);
+  ASSERT_TRUE(base::CopyFile(temp_file, old_file_path_g));
+  ASSERT_EQ(0, link(old_file_path_g.AsUTF8Unsafe().c_str(),
+                    link_path_g.AsUTF8Unsafe().c_str()));
+
+  // Entry H: pinned entry without cache file.
+  const std::string id_h = "id_h";
+  ResourceEntry entry_h;
+  entry_h.set_local_id(id_h);
+  FileCacheEntry* file_cache_entry_h =
+      entry_h.mutable_file_specific_info()->mutable_cache_state();
+  file_cache_entry_h->set_is_present(true);
+  file_cache_entry_h->set_is_pinned(true);
+  file_cache_entry_h->set_is_dirty(false);
+  ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_h));
+
+  // Entry I: already migrated pinned cache file.
+  const std::string id_i = "id_i";
+  ResourceEntry entry_i;
+  entry_i.set_local_id(id_i);
+  FileCacheEntry* file_cache_entry_i =
+      entry_i.mutable_file_specific_info()->mutable_cache_state();
+  file_cache_entry_i->set_is_present(true);
+  file_cache_entry_i->set_is_pinned(true);
+  file_cache_entry_i->set_is_dirty(false);
+  ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_i));
+  const base::FilePath new_file_path_i = new_cache_dir.AppendASCII(id_i);
+  const base::FilePath link_path_i = link_dir.AppendASCII(id_i);
+  ASSERT_TRUE(base::CopyFile(temp_file, new_file_path_i));
+  ASSERT_EQ(0, link(new_file_path_i.AsUTF8Unsafe().c_str(),
+                    link_path_i.AsUTF8Unsafe().c_str()));
+
   // Run migration.
   ASSERT_TRUE(FileCache::MigrateCacheFiles(old_cache_dir, new_cache_dir,
-                                           metadata_storage_.get()));
+                                           link_dir, metadata_storage_.get()));
 
   // Check result.
   EXPECT_FALSE(base::PathExists(old_file_path_a));
   EXPECT_TRUE(base::PathExists(new_file_path_a));
+  EXPECT_EQ(1, GetNumberOfLinks(new_file_path_a));
   // MigrateCacheFiles doesn't delete invalid cache file.
   EXPECT_TRUE(base::PathExists(old_file_path_b));
   EXPECT_TRUE(base::PathExists(new_file_path_c));
+  EXPECT_EQ(1, GetNumberOfLinks(new_file_path_c));
+  EXPECT_FALSE(base::PathExists(old_file_path_e));
+  EXPECT_TRUE(base::PathExists(new_file_path_e));
+  EXPECT_TRUE(base::PathExists(link_path_e));
+  EXPECT_EQ(2, GetNumberOfLinks(new_file_path_e));
+  EXPECT_FALSE(base::PathExists(old_file_path_f));
+  EXPECT_TRUE(base::PathExists(new_file_path_f));
+  EXPECT_TRUE(base::PathExists(link_path_f));
+  EXPECT_EQ(2, GetNumberOfLinks(new_file_path_f));
+  EXPECT_FALSE(base::PathExists(old_file_path_g));
+  EXPECT_TRUE(base::PathExists(new_file_path_g));
+  EXPECT_TRUE(base::PathExists(link_path_g));
+  EXPECT_EQ(2, GetNumberOfLinks(new_file_path_g));
+  EXPECT_TRUE(base::PathExists(new_file_path_i));
+  EXPECT_TRUE(base::PathExists(link_path_i));
+  EXPECT_EQ(2, GetNumberOfLinks(new_file_path_i));
 }
 
 TEST_F(FileCacheTest, ClearAll) {
diff --git a/components/mus/public/cpp/context_provider.h b/components/mus/public/cpp/context_provider.h
index 67f374a9..8b93a2f 100644
--- a/components/mus/public/cpp/context_provider.h
+++ b/components/mus/public/cpp/context_provider.h
@@ -28,7 +28,7 @@
   void InvalidateGrContext(uint32_t state) override;
   void SetupLock() override;
   base::Lock* GetLock() override;
-  Capabilities ContextCapabilities() override;
+  gpu::Capabilities ContextCapabilities() override;
   void DeleteCachedResources() override {}
   void SetLostContextCallback(
       const LostContextCallback& lost_context_callback) override {}
@@ -43,7 +43,6 @@
   }
   void ContextLost();
 
-  cc::ContextProvider::Capabilities capabilities_;
   mojo::ScopedMessagePipeHandle command_buffer_handle_;
   MojoGLES2Context context_;
   scoped_ptr<gpu::gles2::GLES2Interface> context_gl_;
diff --git a/components/mus/public/cpp/lib/context_provider.cc b/components/mus/public/cpp/lib/context_provider.cc
index 0b0b470..97e3af4 100644
--- a/components/mus/public/cpp/lib/context_provider.cc
+++ b/components/mus/public/cpp/lib/context_provider.cc
@@ -16,9 +16,6 @@
     mojo::ScopedMessagePipeHandle command_buffer_handle)
     : command_buffer_handle_(std::move(command_buffer_handle)),
       context_(nullptr) {
-  // Enabled the CHROMIUM_image extension to use GpuMemoryBuffers. The
-  // implementation of which is used in CommandBufferDriver.
-  capabilities_.gpu.image = true;
 }
 
 bool ContextProvider::BindToCurrentThread() {
@@ -46,8 +43,12 @@
 
 void ContextProvider::InvalidateGrContext(uint32_t state) {}
 
-cc::ContextProvider::Capabilities ContextProvider::ContextCapabilities() {
-  return capabilities_;
+gpu::Capabilities ContextProvider::ContextCapabilities() {
+  gpu::Capabilities capabilities;
+  // Enabled the CHROMIUM_image extension to use GpuMemoryBuffers. The
+  // implementation of which is used in CommandBufferDriver.
+  capabilities.image = true;
+  return capabilities;
 }
 
 void ContextProvider::SetupLock() {}
diff --git a/components/mus/surfaces/direct_output_surface.cc b/components/mus/surfaces/direct_output_surface.cc
index da6b35e..5fd3ab6 100644
--- a/components/mus/surfaces/direct_output_surface.cc
+++ b/components/mus/surfaces/direct_output_surface.cc
@@ -36,7 +36,7 @@
 
   if (capabilities_.uses_default_gl_framebuffer) {
     capabilities_.flipped_output_surface =
-        context_provider()->ContextCapabilities().gpu.flips_vertically;
+        context_provider()->ContextCapabilities().flips_vertically;
   }
   return true;
 }
diff --git a/components/mus/surfaces/direct_output_surface_ozone.cc b/components/mus/surfaces/direct_output_surface_ozone.cc
index e04a4796..74eebc1f 100644
--- a/components/mus/surfaces/direct_output_surface_ozone.cc
+++ b/components/mus/surfaces/direct_output_surface_ozone.cc
@@ -96,7 +96,7 @@
 
   if (capabilities_.uses_default_gl_framebuffer) {
     capabilities_.flipped_output_surface =
-        context_provider()->ContextCapabilities().gpu.flips_vertically;
+        context_provider()->ContextCapabilities().flips_vertically;
   }
   return true;
 }
diff --git a/components/mus/surfaces/surfaces_context_provider.cc b/components/mus/surfaces/surfaces_context_provider.cc
index a2271d21..ceb853b 100644
--- a/components/mus/surfaces/surfaces_context_provider.cc
+++ b/components/mus/surfaces/surfaces_context_provider.cc
@@ -16,17 +16,11 @@
 #include "components/mus/surfaces/surfaces_context_provider_delegate.h"
 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
 
 namespace mus {
 
-namespace {
-const size_t kDefaultCommandBufferSize = 1024 * 1024;
-const size_t kDefaultStartTransferBufferSize = 1 * 1024 * 1024;
-const size_t kDefaultMinTransferBufferSize = 1 * 256 * 1024;
-const size_t kDefaultMaxTransferBufferSize = 16 * 1024 * 1024;
-}
-
 SurfacesContextProvider::SurfacesContextProvider(
     gfx::AcceleratedWidget widget,
     const scoped_refptr<GpuState>& state)
@@ -51,15 +45,17 @@
   DCHECK(CalledOnValidThread());
   if (!command_buffer_local_->Initialize())
     return false;
+
+  constexpr gpu::SharedMemoryLimits default_limits;
   gles2_helper_.reset(
       new gpu::gles2::GLES2CmdHelper(command_buffer_local_));
-  if (!gles2_helper_->Initialize(kDefaultCommandBufferSize))
+  if (!gles2_helper_->Initialize(default_limits.command_buffer_size))
     return false;
   gles2_helper_->SetAutomaticFlushes(false);
   transfer_buffer_.reset(new gpu::TransferBuffer(gles2_helper_.get()));
-  capabilities_.gpu = command_buffer_local_->GetCapabilities();
+  capabilities_ = command_buffer_local_->GetCapabilities();
   bool bind_generates_resource =
-      !!capabilities_.gpu.bind_generates_resource_chromium;
+      !!capabilities_.bind_generates_resource_chromium;
   // TODO(piman): Some contexts (such as compositor) want this to be true, so
   // this needs to be a public parameter.
   bool lose_context_when_out_of_memory = false;
@@ -69,8 +65,10 @@
       bind_generates_resource, lose_context_when_out_of_memory,
       support_client_side_arrays, command_buffer_local_));
   return implementation_->Initialize(
-      kDefaultStartTransferBufferSize, kDefaultMinTransferBufferSize,
-      kDefaultMaxTransferBufferSize, gpu::gles2::GLES2Implementation::kNoLimit);
+      default_limits.start_transfer_buffer_size,
+      default_limits.min_transfer_buffer_size,
+      default_limits.max_transfer_buffer_size,
+      default_limits.mapped_memory_reclaim_limit);
 }
 
 gpu::gles2::GLES2Interface* SurfacesContextProvider::ContextGL() {
@@ -88,8 +86,7 @@
 
 void SurfacesContextProvider::InvalidateGrContext(uint32_t state) {}
 
-cc::ContextProvider::Capabilities
-SurfacesContextProvider::ContextCapabilities() {
+gpu::Capabilities SurfacesContextProvider::ContextCapabilities() {
   return capabilities_;
 }
 
diff --git a/components/mus/surfaces/surfaces_context_provider.h b/components/mus/surfaces/surfaces_context_provider.h
index 5562af49..a554dbd 100644
--- a/components/mus/surfaces/surfaces_context_provider.h
+++ b/components/mus/surfaces/surfaces_context_provider.h
@@ -51,7 +51,7 @@
   gpu::ContextSupport* ContextSupport() override;
   class GrContext* GrContext() override;
   void InvalidateGrContext(uint32_t state) override;
-  Capabilities ContextCapabilities() override;
+  gpu::Capabilities ContextCapabilities() override;
   void DeleteCachedResources() override {}
   void SetLostContextCallback(
       const LostContextCallback& lost_context_callback) override;
@@ -77,7 +77,7 @@
   std::unique_ptr<gpu::TransferBuffer> transfer_buffer_;
   std::unique_ptr<gpu::gles2::GLES2Implementation> implementation_;
 
-  cc::ContextProvider::Capabilities capabilities_;
+  gpu::Capabilities capabilities_;
   LostContextCallback lost_context_callback_;
 
   SurfacesContextProviderDelegate* delegate_;
diff --git a/components/mus/surfaces/top_level_display_client.cc b/components/mus/surfaces/top_level_display_client.cc
index b70f8b3..cdcd6cf 100644
--- a/components/mus/surfaces/top_level_display_client.cc
+++ b/components/mus/surfaces/top_level_display_client.cc
@@ -54,7 +54,7 @@
   CHECK(surfaces_context_provider->BindToCurrentThread());
 
   std::unique_ptr<cc::OutputSurface> output_surface;
-  if (surfaces_context_provider->ContextCapabilities().gpu.surfaceless) {
+  if (surfaces_context_provider->ContextCapabilities().surfaceless) {
 #if defined(USE_OZONE)
     output_surface = base::WrapUnique(new DirectOutputSurfaceOzone(
         surfaces_context_provider, widget, task_runner_.get(), GL_TEXTURE_2D,
diff --git a/components/password_manager/sync/browser/password_manager_setting_migrator_service_unittest.cc b/components/password_manager/sync/browser/password_manager_setting_migrator_service_unittest.cc
index 78b788f..ce644d4 100644
--- a/components/password_manager/sync/browser/password_manager_setting_migrator_service_unittest.cc
+++ b/components/password_manager/sync/browser/password_manager_setting_migrator_service_unittest.cc
@@ -286,7 +286,7 @@
     PasswordManagerPreferencesInitialValues histogram_initial_value;
     PasswordManagerPreferencesInitialAndFinalValues histogram_initial_and_final;
   } kTestingTable[] = {
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_IOS)
     {ON, OFF, ON, EMPTY, false, N1L0, I10F00},
     {ON, OFF, OFF, EMPTY, false, N1L0, I10F00},
     {ON, OFF, EMPTY, EMPTY, false, N1L0, I10F00},
@@ -342,7 +342,7 @@
     NotifyProfileAdded();
     StartSyncingPref(prefs(), prefs::kCredentialsEnableService,
                      test_case.new_pref_sync_value);
-#if !defined(OS_ANDROID)
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
     StartSyncingPref(prefs(), prefs::kPasswordManagerSavingEnabled,
                      test_case.old_pref_sync_value);
 #endif
@@ -368,7 +368,7 @@
     bool result_old_pref_value;
     PasswordManagerPreferencesInitialValues histogram_initial_value;
   } kTestingTable[] = {
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_IOS)
     {ON, OFF, ON, EMPTY, true, false, N1L0},
     {ON, OFF, OFF, EMPTY, false, false, N1L0},
     {ON, OFF, EMPTY, EMPTY, true, false, N1L0},
@@ -422,7 +422,7 @@
     NotifyProfileAdded();
     StartSyncingPref(prefs(), prefs::kCredentialsEnableService,
                      test_case.new_pref_sync_value);
-#if !defined(OS_ANDROID)
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
     StartSyncingPref(prefs(), prefs::kPasswordManagerSavingEnabled,
                      test_case.old_pref_sync_value);
 #endif
diff --git a/components/safe_browsing_db/database_manager.cc b/components/safe_browsing_db/database_manager.cc
index 218e8e0..2013c865 100644
--- a/components/safe_browsing_db/database_manager.cc
+++ b/components/safe_browsing_db/database_manager.cc
@@ -40,7 +40,39 @@
     delete v4_get_hash_protocol_manager_;
     v4_get_hash_protocol_manager_ = NULL;
   }
-  // TODO(kcarattini): Call back clients with pending requests.
+
+  // Delete pending checks, calling back any clients with empty metadata.
+  for (auto check : api_checks_) {
+    if (check->client()) {
+      check->client()->
+          OnCheckApiBlacklistUrlResult(check->url(), ThreatMetadata());
+    }
+  }
+  STLDeleteElements(&api_checks_);
+}
+
+SafeBrowsingDatabaseManager::CurrentApiChecks::iterator
+SafeBrowsingDatabaseManager::FindClientApiCheck(Client* client) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  for (CurrentApiChecks::iterator it = api_checks_.begin();
+      it != api_checks_.end(); ++it) {
+    if ((*it)->client() == client) {
+      return it;
+    }
+  }
+  return api_checks_.end();
+}
+
+bool SafeBrowsingDatabaseManager::CancelApiCheck(Client* client) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  CurrentApiChecks::iterator it = FindClientApiCheck(client);
+  if (it != api_checks_.end()) {
+    delete *it;
+    api_checks_.erase(it);
+    return true;
+  }
+  NOTREACHED();
+  return false;
 }
 
 bool SafeBrowsingDatabaseManager::CheckApiBlacklistUrl(const GURL& url,
@@ -53,6 +85,9 @@
     return true;
   }
 
+  // There can only be one in-progress check for the same client at a time.
+  DCHECK(FindClientApiCheck(client) == api_checks_.end());
+
   // Compute a list of hashes for this url.
   std::vector<SBFullHash> full_hashes;
   UrlToFullHashes(url, false, &full_hashes);
@@ -69,9 +104,9 @@
   prefixes.erase(std::unique(prefixes.begin(), prefixes.end()), prefixes.end());
   DCHECK(!prefixes.empty());
 
-  // TODO(kcarattini): Track checks in a map.
-  std::shared_ptr<SafeBrowsingApiCheck> check(
-      new SafeBrowsingApiCheck(url, full_hashes, client));
+  SafeBrowsingApiCheck* check =
+      new SafeBrowsingApiCheck(url, full_hashes, client);
+  api_checks_.insert(check);
 
   // TODO(kcarattini): Implement cache compliance.
   v4_get_hash_protocol_manager_->GetFullHashesWithApis(prefixes,
@@ -82,12 +117,18 @@
 }
 
 void SafeBrowsingDatabaseManager::HandleGetHashesWithApisResults(
-    std::shared_ptr<SafeBrowsingApiCheck> check,
+    SafeBrowsingApiCheck* check,
     const std::vector<SBFullHashResult>& full_hash_results,
     const base::TimeDelta& negative_cache_duration) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(check);
 
+  // If the check is not in |api_checks_| then the request was cancelled by the
+  // client.
+  CurrentApiChecks::iterator it = api_checks_.find(check);
+  if (it == api_checks_.end())
+    return;
+
   ThreatMetadata md;
   // Merge the metadata from all matching results.
   // TODO(kcarattini): This is O(N^2). Look at improving performance by
@@ -104,6 +145,8 @@
   }
 
   check->client()->OnCheckApiBlacklistUrlResult(check->url(), md);
+  api_checks_.erase(it);
+  delete check;
 }
 
 SafeBrowsingDatabaseManager::SafeBrowsingApiCheck::SafeBrowsingApiCheck(
diff --git a/components/safe_browsing_db/database_manager.h b/components/safe_browsing_db/database_manager.h
index df5fe35..9a15bed6e 100644
--- a/components/safe_browsing_db/database_manager.h
+++ b/components/safe_browsing_db/database_manager.h
@@ -154,15 +154,19 @@
   // are handled separately. To cancel an API check use CancelApiCheck.
   virtual void CancelCheck(Client* client) = 0;
 
-  // TODO(kcarattini): Add a CancelApiCheck method.
+  // Called on the IO thread to cancel a pending API check if the result is no
+  // longer needed. Returns true if the client was found and the check
+  // successfully cancelled.
+  virtual bool CancelApiCheck(Client* client);
 
   // Called on the IO thread to check if the given url has blacklisted APIs.
-  // "client" is called asynchronously with the result when it is ready.
-  // This method has the same implementation for both the local and remote
-  // database managers since it pings Safe Browsing servers directly without
-  // accessing the database at all.  Returns true if we can synchronously
-  // determine that the url is safe. Otherwise it returns false, and "client" is
-  // called asynchronously with the result when it is ready.
+  // "client" is called asynchronously with the result when it is ready. Callers
+  // should wait for results before calling this method a second time with the
+  // same client. This method has the same implementation for both the local and
+  // remote database managers since it pings Safe Browsing servers directly
+  // without accessing the database at all.  Returns true if we can
+  // synchronously determine that the url is safe. Otherwise it returns false,
+  // and "client" is called asynchronously with the result when it is ready.
   virtual bool CheckApiBlacklistUrl(const GURL& url, Client* client);
 
   // Called to initialize objects that are used on the io_thread, such as the
@@ -211,17 +215,29 @@
                            HandleGetHashesWithApisResultsNoMatch);
   FRIEND_TEST_ALL_PREFIXES(SafeBrowsingDatabaseManagerTest,
                            HandleGetHashesWithApisResultsMatches);
+  FRIEND_TEST_ALL_PREFIXES(SafeBrowsingDatabaseManagerTest,
+                           CancelApiCheck);
+
+  typedef std::set<SafeBrowsingApiCheck*> CurrentApiChecks;
+
+  // In-progress checks. This set owns the SafeBrowsingApiCheck pointers and is
+  // responsible for deleting them when removing from the set.
+  CurrentApiChecks api_checks_;
 
   // Called on the IO thread wheh the SafeBrowsingProtocolManager has received
   // the full hash and api results for prefixes of the |url| argument in
   // CheckApiBlacklistUrl.
   virtual void HandleGetHashesWithApisResults(
-      std::shared_ptr<SafeBrowsingApiCheck> check,
+      SafeBrowsingApiCheck* check,
       const std::vector<SBFullHashResult>& full_hash_results,
       const base::TimeDelta& negative_cache_duration);
 
   // Created and destroyed via StartOnIOThread/StopOnIOThread.
   V4GetHashProtocolManager* v4_get_hash_protocol_manager_;
+
+ private:
+  // Returns an iterator to the pending API check with the given |client|.
+  CurrentApiChecks::iterator FindClientApiCheck(Client* client);
 };  // class SafeBrowsingDatabaseManager
 
 }  // namespace safe_browsing
diff --git a/components/safe_browsing_db/database_manager_unittest.cc b/components/safe_browsing_db/database_manager_unittest.cc
index c914a08..c936712 100644
--- a/components/safe_browsing_db/database_manager_unittest.cc
+++ b/components/safe_browsing_db/database_manager_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "components/safe_browsing_db/database_manager.h"
 #include "components/safe_browsing_db/test_database_manager.h"
@@ -25,6 +26,12 @@
 
 namespace {
 
+void InvokeFullHashCallback(
+    V4GetHashProtocolManager::FullHashCallback callback,
+    const std::vector<SBFullHashResult>& full_hashes) {
+  callback.Run(full_hashes, base::TimeDelta::FromMinutes(0));
+}
+
 // A TestV4GetHashProtocolManager that returns fixed responses from the
 // Safe Browsing server for testing purpose.
 class TestV4GetHashProtocolManager : public V4GetHashProtocolManager {
@@ -32,14 +39,21 @@
   TestV4GetHashProtocolManager(
       net::URLRequestContextGetter* request_context_getter,
       const V4ProtocolConfig& config)
-      : V4GetHashProtocolManager(request_context_getter, config) {}
+      : V4GetHashProtocolManager(request_context_getter, config),
+        delay_seconds_(0) {}
 
   ~TestV4GetHashProtocolManager() override {}
 
   void GetFullHashesWithApis(const std::vector<SBPrefix>& prefixes,
                              FullHashCallback callback) override {
     prefixes_ = prefixes;
-    callback.Run(full_hashes_, base::TimeDelta::FromMinutes(0));
+    base::MessageLoop::current()->PostDelayedTask(
+        FROM_HERE, base::Bind(InvokeFullHashCallback, callback, full_hashes_),
+        base::TimeDelta::FromSeconds(delay_seconds_));
+  }
+
+  void SetDelaySeconds(int delay) {
+    delay_seconds_ = delay;
   }
 
   // Prepare the GetFullHash results for the next request.
@@ -53,6 +67,7 @@
  private:
   std::vector<SBPrefix> prefixes_;
   std::vector<SBFullHashResult> full_hashes_;
+  int delay_seconds_;
 };
 
 // Factory that creates test protocol manager instances.
@@ -76,20 +91,24 @@
 
 class TestClient : public SafeBrowsingDatabaseManager::Client {
  public:
-  TestClient() {}
+  TestClient() : callback_invoked_(false) {}
   ~TestClient() override {}
 
   void OnCheckApiBlacklistUrlResult(const GURL& url,
                                     const ThreatMetadata& metadata) override {
     blocked_permissions_ = metadata.api_permissions;
+    callback_invoked_ = true;
   }
 
   const std::vector<std::string>& GetBlockedPermissions() {
     return blocked_permissions_;
   }
 
+  bool callback_invoked() {return callback_invoked_;}
+
  private:
   std::vector<std::string> blocked_permissions_;
+  bool callback_invoked_;
   DISALLOW_COPY_AND_ASSIGN(TestClient);
 };
 
@@ -130,6 +149,7 @@
       {1237562338, 2871045197, 3553205461, 3766933875};
 
   EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
+  base::RunLoop().RunUntilIdle();
   std::vector<SBPrefix> prefixes = static_cast<TestV4GetHashProtocolManager*>(
       db_manager_->v4_get_hash_protocol_manager_)->GetRequestPrefixes();
   EXPECT_EQ(expected_prefixes.size(), prefixes.size());
@@ -151,6 +171,7 @@
   EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
   base::RunLoop().RunUntilIdle();
 
+  EXPECT_TRUE(client.callback_invoked());
   const std::vector<std::string>& permissions = client.GetBlockedPermissions();
   EXPECT_EQ(1ul, permissions.size());
   EXPECT_EQ("GEOLOCATION", permissions[0]);
@@ -169,6 +190,7 @@
   EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
   base::RunLoop().RunUntilIdle();
 
+  EXPECT_TRUE(client.callback_invoked());
   const std::vector<std::string>& permissions = client.GetBlockedPermissions();
   EXPECT_EQ(0ul, permissions.size());
 }
@@ -194,10 +216,31 @@
   EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
   base::RunLoop().RunUntilIdle();
 
+  EXPECT_TRUE(client.callback_invoked());
   const std::vector<std::string>& permissions = client.GetBlockedPermissions();
   EXPECT_EQ(2ul, permissions.size());
   EXPECT_EQ("GEOLOCATION", permissions[0]);
   EXPECT_EQ("NOTIFICATIONS", permissions[1]);
 }
 
+TEST_F(SafeBrowsingDatabaseManagerTest, CancelApiCheck) {
+  TestClient client;
+  const GURL url("https://www.example.com/more");
+  TestV4GetHashProtocolManager* pm = static_cast<TestV4GetHashProtocolManager*>(
+      db_manager_->v4_get_hash_protocol_manager_);
+  SBFullHashResult full_hash_result;
+  full_hash_result.hash = SBFullHashForString("example.com/");
+  full_hash_result.metadata.api_permissions.push_back("GEOLOCATION");
+  pm->AddGetFullHashResponse(full_hash_result);
+  pm->SetDelaySeconds(100);
+
+  EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
+  EXPECT_TRUE(db_manager_->CancelApiCheck(&client));
+  base::RunLoop().RunUntilIdle();
+
+  const std::vector<std::string>& permissions = client.GetBlockedPermissions();
+  EXPECT_EQ(0ul, permissions.size());
+  EXPECT_FALSE(client.callback_invoked());
+}
+
 }  // namespace safe_browsing
diff --git a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
deleted file mode 100644
index 76331a11..0000000
--- a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/android/in_process/synchronous_compositor_factory_impl.h"
-
-#include <stdint.h>
-
-#include <utility>
-
-#include "base/command_line.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/thread_task_runner_handle.h"
-#include "content/browser/android/in_process/synchronous_compositor_impl.h"
-#include "content/browser/android/in_process/synchronous_compositor_registry_in_proc.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/common/content_switches.h"
-#include "content/renderer/android/synchronous_compositor_external_begin_frame_source.h"
-#include "content/renderer/android/synchronous_compositor_output_surface.h"
-#include "content/renderer/gpu/frame_swap_message_queue.h"
-#include "content/renderer/render_thread_impl.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
-#include "gpu/ipc/client/gpu_channel_host.h"
-
-namespace content {
-
-SynchronousCompositorFactoryImpl::SynchronousCompositorFactoryImpl() {
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kSingleProcess)) {
-    // TODO(boliu): Figure out how to deal with this more nicely.
-    SynchronousCompositorFactory::SetInstance(this);
-  }
-}
-
-SynchronousCompositorFactoryImpl::~SynchronousCompositorFactoryImpl() {}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-SynchronousCompositorFactoryImpl::GetCompositorTaskRunner() {
-  return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
-}
-
-std::unique_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 base::WrapUnique(new SynchronousCompositorOutputSurface(
-      onscreen_context, worker_context, routing_id, output_surface_id,
-      SynchronousCompositorRegistryInProc::GetInstance(),
-      frame_swap_message_queue));
-}
-
-InputHandlerManagerClient*
-SynchronousCompositorFactoryImpl::GetInputHandlerManagerClient() {
-  return synchronous_input_event_filter();
-}
-
-SynchronousInputHandlerProxyClient*
-SynchronousCompositorFactoryImpl::GetSynchronousInputHandlerProxyClient() {
-  return synchronous_input_event_filter();
-}
-
-std::unique_ptr<cc::BeginFrameSource>
-SynchronousCompositorFactoryImpl::CreateExternalBeginFrameSource(
-    int routing_id) {
-  return base::WrapUnique(new SynchronousCompositorExternalBeginFrameSource(
-      routing_id, SynchronousCompositorRegistryInProc::GetInstance()));
-}
-
-}  // namespace content
diff --git a/content/browser/android/in_process/synchronous_compositor_factory_impl.h b/content/browser/android/in_process/synchronous_compositor_factory_impl.h
deleted file mode 100644
index 013175f..0000000
--- a/content/browser/android/in_process/synchronous_compositor_factory_impl.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_FACTORY_IMPL_H_
-#define CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_FACTORY_IMPL_H_
-
-#include "base/synchronization/lock.h"
-#include "cc/blink/context_provider_web_context.h"
-#include "content/browser/android/in_process/synchronous_input_event_filter.h"
-#include "content/common/gpu/client/command_buffer_metrics.h"
-#include "content/renderer/android/synchronous_compositor_factory.h"
-
-namespace content {
-
-class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
- public:
-  SynchronousCompositorFactoryImpl();
-  ~SynchronousCompositorFactoryImpl() override;
-
-  // SynchronousCompositorFactory
-  scoped_refptr<base::SingleThreadTaskRunner> GetCompositorTaskRunner()
-      override;
-  std::unique_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;
-  InputHandlerManagerClient* GetInputHandlerManagerClient() override;
-  SynchronousInputHandlerProxyClient* GetSynchronousInputHandlerProxyClient()
-      override;
-  std::unique_ptr<cc::BeginFrameSource> CreateExternalBeginFrameSource(
-      int routing_id) override;
-
-  SynchronousInputEventFilter* synchronous_input_event_filter() {
-    return &synchronous_input_event_filter_;
-  }
-
- private:
-  SynchronousInputEventFilter synchronous_input_event_filter_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_FACTORY_IMPL_H_
diff --git a/content/browser/android/in_process/synchronous_compositor_impl.cc b/content/browser/android/in_process/synchronous_compositor_impl.cc
deleted file mode 100644
index 652753ed..0000000
--- a/content/browser/android/in_process/synchronous_compositor_impl.cc
+++ /dev/null
@@ -1,376 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/android/in_process/synchronous_compositor_impl.h"
-
-#include <utility>
-
-#include "base/auto_reset.h"
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "base/message_loop/message_loop.h"
-#include "content/browser/android/in_process/synchronous_compositor_factory_impl.h"
-#include "content/browser/android/in_process/synchronous_compositor_registry_in_proc.h"
-#include "content/browser/android/in_process/synchronous_input_event_filter.h"
-#include "content/browser/gpu/gpu_process_host.h"
-#include "content/browser/renderer_host/render_widget_host_view_android.h"
-#include "content/common/input/did_overscroll_params.h"
-#include "content/common/input_messages.h"
-#include "content/public/browser/android/synchronous_compositor_client.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host.h"
-#include "content/public/common/child_process_host.h"
-#include "ui/gfx/geometry/scroll_offset.h"
-#include "ui/gl/gl_surface.h"
-
-namespace content {
-
-namespace {
-
-int g_process_id = ChildProcessHost::kInvalidUniqueID;
-
-base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory =
-    LAZY_INSTANCE_INITIALIZER;
-
-}  // namespace
-
-SynchronousCompositorImpl* SynchronousCompositorImpl::FromRoutingID(
-    int routing_id) {
-  if (g_factory == nullptr)
-    return nullptr;
-  if (g_process_id == ChildProcessHost::kInvalidUniqueID)
-    return nullptr;
-  RenderViewHost* rvh = RenderViewHost::FromID(g_process_id, routing_id);
-  if (!rvh)
-    return nullptr;
-  RenderWidgetHostViewAndroid* rwhva =
-      static_cast<RenderWidgetHostViewAndroid*>(rvh->GetWidget()->GetView());
-  if (!rwhva)
-    return nullptr;
-  return static_cast<SynchronousCompositorImpl*>(
-      rwhva->GetSynchronousCompositor());
-}
-
-SynchronousCompositorImpl::SynchronousCompositorImpl(
-    RenderWidgetHostViewAndroid* rwhva,
-    SynchronousCompositorClient* client)
-    : rwhva_(rwhva),
-      routing_id_(rwhva_->GetRenderWidgetHost()->GetRoutingID()),
-      compositor_client_(client),
-      output_surface_(nullptr),
-      begin_frame_source_(nullptr),
-      synchronous_input_handler_proxy_(nullptr),
-      registered_with_client_(false),
-      is_active_(true),
-      renderer_needs_begin_frames_(false),
-      need_animate_input_(false),
-      weak_ptr_factory_(this) {
-  DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
-  g_factory.Get();  // Ensure it's initialized.
-
-  int process_id = rwhva_->GetRenderWidgetHost()->GetProcess()->GetID();
-  if (g_process_id == ChildProcessHost::kInvalidUniqueID) {
-    g_process_id = process_id;
-  } else {
-    DCHECK_EQ(g_process_id, process_id);  // Not multiprocess compatible.
-  }
-
-  SynchronousCompositorRegistryInProc::GetInstance()->RegisterCompositor(
-      routing_id_, this);
-}
-
-SynchronousCompositorImpl::~SynchronousCompositorImpl() {
-  SynchronousCompositorRegistryInProc::GetInstance()->UnregisterCompositor(
-      routing_id_, this);
-}
-
-void SynchronousCompositorImpl::RegisterWithClient() {
-  DCHECK(CalledOnValidThread());
-  DCHECK(output_surface_);
-  DCHECK(synchronous_input_handler_proxy_);
-  DCHECK(!registered_with_client_);
-  registered_with_client_ = true;
-
-  compositor_client_->DidInitializeCompositor(this);
-  compositor_client_->DidBecomeCurrent(this);
-
-  output_surface_->SetTreeActivationCallback(
-    base::Bind(&SynchronousCompositorImpl::DidActivatePendingTree,
-               weak_ptr_factory_.GetWeakPtr()));
-
-  // This disables the input system from animating inputs autonomously, instead
-  // routing all input animations through the SynchronousInputHandler, which is
-  // |this| class. Calling this causes an UpdateRootLayerState() immediately so,
-  // do it after setting the client.
-  synchronous_input_handler_proxy_->SetOnlySynchronouslyAnimateRootFlings(this);
-}
-
-void SynchronousCompositorImpl::DidInitializeRendererObjects(
-    SynchronousCompositorOutputSurface* output_surface,
-    SynchronousCompositorExternalBeginFrameSource* begin_frame_source,
-    ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy) {
-  DCHECK(!output_surface_);
-  DCHECK(!begin_frame_source_);
-  DCHECK(output_surface);
-  DCHECK(begin_frame_source);
-  DCHECK(synchronous_input_handler_proxy);
-
-  output_surface_ = output_surface;
-  begin_frame_source_ = begin_frame_source;
-  synchronous_input_handler_proxy_ = synchronous_input_handler_proxy;
-
-  output_surface_->SetSyncClient(this);
-  begin_frame_source_->SetClient(this);
-  begin_frame_source_->SetBeginFrameSourcePaused(!is_active_);
-}
-
-void SynchronousCompositorImpl::DidDestroyRendererObjects() {
-  DCHECK(output_surface_);
-  DCHECK(begin_frame_source_);
-
-  if (registered_with_client_) {
-    output_surface_->SetTreeActivationCallback(base::Closure());
-    compositor_client_->DidDestroyCompositor(this);
-    registered_with_client_ = false;
-  }
-
-  // This object is being destroyed, so remove pointers to it.
-  begin_frame_source_->SetClient(nullptr);
-  output_surface_->SetSyncClient(nullptr);
-  synchronous_input_handler_proxy_->SetOnlySynchronouslyAnimateRootFlings(
-      nullptr);
-
-  synchronous_input_handler_proxy_ = nullptr;
-  begin_frame_source_ = nullptr;
-  output_surface_ = nullptr;
-  // Don't propogate this signal from one renderer to the next.
-  need_animate_input_ = false;
-}
-
-SynchronousCompositor::Frame SynchronousCompositorImpl::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) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(output_surface_);
-  DCHECK(begin_frame_source_);
-  DCHECK(!frame_holder_.frame);
-
-  output_surface_->DemandDrawHw(surface_size, transform, viewport, clip,
-                                viewport_rect_for_tile_priority,
-                                transform_for_tile_priority);
-
-  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(output_surface_id, frame_ack);
-}
-
-bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(output_surface_);
-  DCHECK(begin_frame_source_);
-  DCHECK(!frame_holder_.frame);
-
-  output_surface_->DemandDrawSw(canvas);
-
-  bool success = !!frame_holder_.frame;
-  if (frame_holder_.frame) {
-    UpdateFrameMetaData(frame_holder_.frame->metadata);
-    frame_holder_.frame.reset();
-  }
-
-  return success;
-}
-
-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(
-    const cc::CompositorFrameMetadata& frame_metadata) {
-  rwhva_->SynchronousFrameMetadata(frame_metadata);
-  DeliverMessages();
-}
-
-void SynchronousCompositorImpl::SetMemoryPolicy(size_t bytes_limit) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(output_surface_);
-  output_surface_->SetMemoryPolicy(bytes_limit);
-}
-
-void SynchronousCompositorImpl::Invalidate() {
-  DCHECK(CalledOnValidThread());
-  if (registered_with_client_)
-    compositor_client_->PostInvalidate();
-}
-
-void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset(
-    const gfx::ScrollOffset& root_offset) {
-  DCHECK(CalledOnValidThread());
-  if (!synchronous_input_handler_proxy_)
-    return;
-  synchronous_input_handler_proxy_->SynchronouslySetRootScrollOffset(
-      root_offset);
-}
-
-void SynchronousCompositorImpl::SynchronouslyZoomBy(float zoom_delta,
-                                                    const gfx::Point& anchor) {
-  DCHECK(CalledOnValidThread());
-  if (!synchronous_input_handler_proxy_)
-    return;
-  synchronous_input_handler_proxy_->SynchronouslyZoomBy(zoom_delta, anchor);
-}
-
-void SynchronousCompositorImpl::SetIsActive(bool is_active) {
-  TRACE_EVENT1("cc", "SynchronousCompositorImpl::SetIsActive", "is_active",
-               is_active);
-  if (is_active_ == is_active)
-    return;
-
-  is_active_ = is_active;
-  UpdateNeedsBeginFrames();
-  if (begin_frame_source_)
-    begin_frame_source_->SetBeginFrameSourcePaused(!is_active_);
-}
-
-void SynchronousCompositorImpl::OnComputeScroll(
-    base::TimeTicks animation_time) {
-  if (need_animate_input_) {
-    need_animate_input_ = false;
-    synchronous_input_handler_proxy_->SynchronouslyAnimate(animation_time);
-  }
-}
-
-void SynchronousCompositorImpl::OnNeedsBeginFramesChange(
-    bool needs_begin_frames) {
-  renderer_needs_begin_frames_ = needs_begin_frames;
-  UpdateNeedsBeginFrames();
-}
-
-void SynchronousCompositorImpl::BeginFrame(const cc::BeginFrameArgs& args) {
-  if (!registered_with_client_ && is_active_ && renderer_needs_begin_frames_) {
-    // Make sure this is a BeginFrame that renderer side explicitly requested.
-    // Otherwise it is possible renderer objects not initialized.
-    RegisterWithClient();
-    DCHECK(registered_with_client_);
-  }
-  if (begin_frame_source_)
-    begin_frame_source_->BeginFrame(args);
-}
-
-void SynchronousCompositorImpl::UpdateNeedsBeginFrames() {
-  rwhva_->OnSetNeedsBeginFrames(is_active_ && renderer_needs_begin_frames_);
-}
-
-void SynchronousCompositorImpl::DidOverscrollInProcess(
-    const DidOverscrollParams& params) {
-  if (registered_with_client_) {
-    compositor_client_->DidOverscroll(params.accumulated_overscroll,
-                                      params.latest_overscroll_delta,
-                                      params.current_fling_velocity);
-  }
-}
-
-void SynchronousCompositorImpl::DidStopFlinging() {
-  // It's important that the fling-end notification follow the same path as it
-  // takes on other platforms (using an IPC). This ensures consistent
-  // bookkeeping at all stages of the input pipeline.
-  rwhva_->GetRenderWidgetHost()->GetProcess()->OnMessageReceived(
-      InputHostMsg_DidStopFlinging(routing_id_));
-}
-
-InputEventAckState SynchronousCompositorImpl::HandleInputEvent(
-    const blink::WebInputEvent& input_event) {
-  DCHECK(CalledOnValidThread());
-  return g_factory.Get().synchronous_input_event_filter()->HandleInputEvent(
-      routing_id_, input_event);
-}
-
-void SynchronousCompositorImpl::DidOverscroll(
-    const DidOverscrollParams& params) {
-  // SynchronousCompositorImpl uses synchronous DidOverscrollInProcess for
-  // overscroll instead of this async path.
-  NOTREACHED();
-}
-
-bool SynchronousCompositorImpl::OnMessageReceived(const IPC::Message& message) {
-  NOTREACHED();
-  return false;
-}
-
-void SynchronousCompositorImpl::DidBecomeCurrent() {
-  // This is single process synchronous compositor. There is only one
-  // RenderViewHost.  DidBecomeCurrent could be called before the renderer
-  // objects are initialized. So hold off calling DidBecomeCurrent until
-  // RegisterWithClient. Intentional no-op here.
-}
-
-void SynchronousCompositorImpl::DeliverMessages() {
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-  output_surface_->GetMessagesToDeliver(&messages);
-  RenderProcessHost* rph = rwhva_->GetRenderWidgetHost()->GetProcess();
-  for (const auto& msg : messages) {
-    rph->OnMessageReceived(*msg);
-  }
-}
-
-void SynchronousCompositorImpl::DidActivatePendingTree() {
-  if (registered_with_client_)
-    compositor_client_->DidUpdateContent();
-  DeliverMessages();
-}
-
-void SynchronousCompositorImpl::SetNeedsSynchronousAnimateInput() {
-  DCHECK(CalledOnValidThread());
-  if (!registered_with_client_)
-    return;
-  need_animate_input_ = true;
-  compositor_client_->PostInvalidate();
-}
-
-void SynchronousCompositorImpl::UpdateRootLayerState(
-    const gfx::ScrollOffset& total_scroll_offset,
-    const gfx::ScrollOffset& max_scroll_offset,
-    const gfx::SizeF& scrollable_size,
-    float page_scale_factor,
-    float min_page_scale_factor,
-    float max_page_scale_factor) {
-  DCHECK(CalledOnValidThread());
-
-  if (registered_with_client_) {
-    // TODO(miletus): Pass in ScrollOffset. crbug.com/414283.
-    compositor_client_->UpdateRootLayerState(
-        gfx::ScrollOffsetToVector2dF(total_scroll_offset),
-        gfx::ScrollOffsetToVector2dF(max_scroll_offset),
-        scrollable_size,
-        page_scale_factor,
-        min_page_scale_factor,
-        max_page_scale_factor);
-  }
-}
-
-// Not using base::NonThreadSafe as we want to enforce a more exacting threading
-// requirement: SynchronousCompositorImpl() must only be used on the UI thread.
-bool SynchronousCompositorImpl::CalledOnValidThread() const {
-  return BrowserThread::CurrentlyOn(BrowserThread::UI);
-}
-
-}  // namespace content
diff --git a/content/browser/android/in_process/synchronous_compositor_impl.h b/content/browser/android/in_process/synchronous_compositor_impl.h
deleted file mode 100644
index 3d071c0..0000000
--- a/content/browser/android/in_process/synchronous_compositor_impl.h
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_IMPL_H_
-#define CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_IMPL_H_
-
-#include <stddef.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "content/browser/android/synchronous_compositor_base.h"
-#include "content/renderer/android/synchronous_compositor_external_begin_frame_source.h"
-#include "content/renderer/android/synchronous_compositor_output_surface.h"
-#include "ipc/ipc_message.h"
-#include "ui/events/blink/synchronous_input_handler_proxy.h"
-
-namespace cc {
-class InputHandler;
-}
-
-namespace content {
-class InputHandlerManager;
-class RenderWidgetHostViewAndroid;
-class SynchronousCompositorExternalBeginFrameSource;
-struct DidOverscrollParams;
-
-// The purpose of this class is to act as the intermediary between the various
-// components that make up the 'synchronous compositor mode' implementation and
-// expose their functionality via the SynchronousCompositor interface.
-// This class is created on the main thread but most of the APIs are called
-// from the Compositor thread.
-class SynchronousCompositorImpl
-    : public ui::SynchronousInputHandler,
-      public SynchronousCompositorBase,
-      public SynchronousCompositorExternalBeginFrameSourceClient,
-      public SynchronousCompositorOutputSurfaceClient {
- public:
-  // For handling upcalls from renderer code; the process id
-  // is implicitly that of the in-process renderer.
-  static SynchronousCompositorImpl* FromRoutingID(int routing_id);
-
-  ~SynchronousCompositorImpl() override;
-
-  // Called by SynchronousCompositorRegistry.
-  void DidInitializeRendererObjects(
-      SynchronousCompositorOutputSurface* output_surface,
-      SynchronousCompositorExternalBeginFrameSource* begin_frame_source,
-      ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy);
-  void DidDestroyRendererObjects();
-
-  // SynchronousCompositorExternalBeginFrameSourceClient overrides.
-  void OnNeedsBeginFramesChange(bool needs_begin_frames) override;
-
-  // SynchronousCompositorOutputSurfaceClient overrides.
-  void Invalidate() override;
-  void SwapBuffers(uint32_t output_surface_id,
-                   cc::CompositorFrame* frame) override;
-
-  // SynchronousCompositor overrides.
-  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;
-  bool DemandDrawSw(SkCanvas* canvas) 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;
-  void SynchronouslyZoomBy(float zoom_delta, const gfx::Point& anchor) override;
-  void SetIsActive(bool is_active) override;
-  void OnComputeScroll(base::TimeTicks animation_time) override;
-
-  // SynchronousCompositorBase overrides.
-  void BeginFrame(const cc::BeginFrameArgs& args) override;
-  InputEventAckState HandleInputEvent(
-      const blink::WebInputEvent& input_event) override;
-  void DidOverscroll(const DidOverscrollParams& params) override;
-  bool OnMessageReceived(const IPC::Message& message) override;
-  void DidBecomeCurrent() override;
-
-  // SynchronousInputHandler
-  void SetNeedsSynchronousAnimateInput() override;
-  void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset,
-                            const gfx::ScrollOffset& max_scroll_offset,
-                            const gfx::SizeF& scrollable_size,
-                            float page_scale_factor,
-                            float min_page_scale_factor,
-                            float max_page_scale_factor) override;
-
-  void DidOverscrollInProcess(const DidOverscrollParams& params);
-  void DidStopFlinging();
-
- private:
-  friend class SynchronousCompositorBase;
-  SynchronousCompositorImpl(RenderWidgetHostViewAndroid* rwhva,
-                            SynchronousCompositorClient* client);
-  void RegisterWithClient();
-  void UpdateFrameMetaData(const cc::CompositorFrameMetadata& frame_info);
-  void DidActivatePendingTree();
-  void DeliverMessages();
-  bool CalledOnValidThread() const;
-  void UpdateNeedsBeginFrames();
-
-  RenderWidgetHostViewAndroid* const rwhva_;
-  const int routing_id_;
-  SynchronousCompositorClient* const compositor_client_;
-  SynchronousCompositorOutputSurface* output_surface_;
-  SynchronousCompositorExternalBeginFrameSource* begin_frame_source_;
-  ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy_;
-  bool registered_with_client_;
-  bool is_active_;
-  bool renderer_needs_begin_frames_;
-  bool need_animate_input_;
-  SynchronousCompositor::Frame frame_holder_;
-
-  base::WeakPtrFactory<SynchronousCompositorImpl> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorImpl);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_IMPL_H_
diff --git a/content/browser/android/in_process/synchronous_compositor_registry_in_proc.cc b/content/browser/android/in_process/synchronous_compositor_registry_in_proc.cc
deleted file mode 100644
index 4292a87..0000000
--- a/content/browser/android/in_process/synchronous_compositor_registry_in_proc.cc
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/android/in_process/synchronous_compositor_registry_in_proc.h"
-
-#include "content/browser/android/in_process/synchronous_compositor_impl.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace content {
-
-namespace {
-base::LazyInstance<SynchronousCompositorRegistryInProc> g_compositor_registry =
-    LAZY_INSTANCE_INITIALIZER;
-}
-
-// static
-SynchronousCompositorRegistryInProc*
-SynchronousCompositorRegistryInProc::GetInstance() {
-  return g_compositor_registry.Pointer();
-}
-
-SynchronousCompositorRegistryInProc::SynchronousCompositorRegistryInProc() {
-  DCHECK(CalledOnValidThread());
-}
-
-SynchronousCompositorRegistryInProc::~SynchronousCompositorRegistryInProc() {
-  DCHECK(CalledOnValidThread());
-}
-
-void SynchronousCompositorRegistryInProc::RegisterCompositor(
-    int routing_id,
-    SynchronousCompositorImpl* compositor) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(compositor);
-  Entry& entry = entry_map_[routing_id];
-  DCHECK(!entry.compositor);
-  entry.compositor = compositor;
-  CheckIsReady(routing_id);
-}
-
-void SynchronousCompositorRegistryInProc::UnregisterCompositor(
-    int routing_id,
-    SynchronousCompositorImpl* compositor) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(compositor);
-  DCHECK(entry_map_.find(routing_id) != entry_map_.end());
-  Entry& entry = entry_map_[routing_id];
-  DCHECK_EQ(compositor, entry.compositor);
-
-  if (entry.IsReady())
-    UnregisterObjects(routing_id);
-  entry.compositor = nullptr;
-  RemoveEntryIfNeeded(routing_id);
-}
-
-void SynchronousCompositorRegistryInProc::RegisterBeginFrameSource(
-    int routing_id,
-    SynchronousCompositorExternalBeginFrameSource* begin_frame_source) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(begin_frame_source);
-  Entry& entry = entry_map_[routing_id];
-  DCHECK(!entry.begin_frame_source);
-  entry.begin_frame_source = begin_frame_source;
-  CheckIsReady(routing_id);
-}
-
-void SynchronousCompositorRegistryInProc::UnregisterBeginFrameSource(
-    int routing_id,
-    SynchronousCompositorExternalBeginFrameSource* begin_frame_source) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(begin_frame_source);
-  DCHECK(entry_map_.find(routing_id) != entry_map_.end());
-  Entry& entry = entry_map_[routing_id];
-  DCHECK_EQ(begin_frame_source, entry.begin_frame_source);
-
-  if (entry.IsReady())
-    UnregisterObjects(routing_id);
-  entry.begin_frame_source = nullptr;
-  RemoveEntryIfNeeded(routing_id);
-}
-
-void SynchronousCompositorRegistryInProc::RegisterOutputSurface(
-    int routing_id,
-    SynchronousCompositorOutputSurface* output_surface) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(output_surface);
-  Entry& entry = entry_map_[routing_id];
-  DCHECK(!entry.output_surface);
-  entry.output_surface = output_surface;
-  CheckIsReady(routing_id);
-}
-
-void SynchronousCompositorRegistryInProc::UnregisterOutputSurface(
-    int routing_id,
-    SynchronousCompositorOutputSurface* output_surface) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(output_surface);
-  DCHECK(entry_map_.find(routing_id) != entry_map_.end());
-  Entry& entry = entry_map_[routing_id];
-  DCHECK_EQ(output_surface, entry.output_surface);
-
-  if (entry.IsReady())
-    UnregisterObjects(routing_id);
-  entry.output_surface = nullptr;
-  RemoveEntryIfNeeded(routing_id);
-}
-
-void SynchronousCompositorRegistryInProc::RegisterInputHandler(
-    int routing_id,
-    ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(synchronous_input_handler_proxy);
-  Entry& entry = entry_map_[routing_id];
-  DCHECK(!entry.synchronous_input_handler_proxy);
-  entry.synchronous_input_handler_proxy = synchronous_input_handler_proxy;
-  CheckIsReady(routing_id);
-}
-
-void SynchronousCompositorRegistryInProc::UnregisterInputHandler(
-    int routing_id) {
-  DCHECK(CalledOnValidThread());
-  DCHECK(entry_map_.find(routing_id) != entry_map_.end());
-  Entry& entry = entry_map_[routing_id];
-
-  if (entry.IsReady())
-    UnregisterObjects(routing_id);
-  entry.synchronous_input_handler_proxy = nullptr;
-  RemoveEntryIfNeeded(routing_id);
-}
-
-void SynchronousCompositorRegistryInProc::CheckIsReady(int routing_id) {
-  DCHECK(entry_map_.find(routing_id) != entry_map_.end());
-  Entry& entry = entry_map_[routing_id];
-  if (entry.IsReady()) {
-    entry.compositor->DidInitializeRendererObjects(
-        entry.output_surface, entry.begin_frame_source,
-        entry.synchronous_input_handler_proxy);
-  }
-}
-
-void SynchronousCompositorRegistryInProc::UnregisterObjects(int routing_id) {
-  DCHECK(entry_map_.find(routing_id) != entry_map_.end());
-  Entry& entry = entry_map_[routing_id];
-  DCHECK(entry.IsReady());
-  entry.compositor->DidDestroyRendererObjects();
-}
-
-void SynchronousCompositorRegistryInProc::RemoveEntryIfNeeded(int routing_id) {
-  DCHECK(entry_map_.find(routing_id) != entry_map_.end());
-  Entry& entry = entry_map_[routing_id];
-  if (!entry.compositor && !entry.begin_frame_source && !entry.output_surface &&
-      !entry.synchronous_input_handler_proxy) {
-    entry_map_.erase(routing_id);
-  }
-}
-
-bool SynchronousCompositorRegistryInProc::CalledOnValidThread() const {
-  return BrowserThread::CurrentlyOn(BrowserThread::UI);
-}
-
-SynchronousCompositorRegistryInProc::Entry::Entry()
-    : compositor(nullptr),
-      begin_frame_source(nullptr),
-      output_surface(nullptr),
-      synchronous_input_handler_proxy(nullptr) {}
-
-bool SynchronousCompositorRegistryInProc::Entry::IsReady() {
-  return compositor && begin_frame_source && output_surface &&
-         synchronous_input_handler_proxy;
-}
-
-}  // namespace content
diff --git a/content/browser/android/in_process/synchronous_compositor_registry_in_proc.h b/content/browser/android/in_process/synchronous_compositor_registry_in_proc.h
deleted file mode 100644
index 1de2002..0000000
--- a/content/browser/android/in_process/synchronous_compositor_registry_in_proc.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_REGISTRY_IN_PROC_H_
-#define CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_REGISTRY_IN_PROC_H_
-
-#include "base/containers/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/macros.h"
-#include "content/renderer/android/synchronous_compositor_registry.h"
-#include "ui/events/blink/synchronous_input_handler_proxy.h"
-
-namespace ui {
-class SynchronousInputHandlerProxy;
-}
-
-namespace content {
-
-class SynchronousCompositorExternalBeginFrameSource;
-class SynchronousCompositorImpl;
-class SynchronousCompositorOutputSurface;
-
-class SynchronousCompositorRegistryInProc
-    : public SynchronousCompositorRegistry {
- public:
-  static SynchronousCompositorRegistryInProc* GetInstance();
-
-  void RegisterCompositor(int routing_id,
-                          SynchronousCompositorImpl* compositor);
-  void UnregisterCompositor(int routing_id,
-                            SynchronousCompositorImpl* compositor);
-  void RegisterInputHandler(
-      int routing_id,
-      ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy);
-  void UnregisterInputHandler(int routing_id);
-
-  // SynchronousCompositorRegistry overrides.
-  void RegisterBeginFrameSource(int routing_id,
-                                SynchronousCompositorExternalBeginFrameSource*
-                                    begin_frame_source) override;
-  void UnregisterBeginFrameSource(int routing_id,
-                                  SynchronousCompositorExternalBeginFrameSource*
-                                      begin_frame_source) override;
-  void RegisterOutputSurface(
-      int routing_id,
-      SynchronousCompositorOutputSurface* output_surface) override;
-  void UnregisterOutputSurface(
-      int routing_id,
-      SynchronousCompositorOutputSurface* output_surface) override;
-
- private:
-  friend struct base::DefaultLazyInstanceTraits<
-      SynchronousCompositorRegistryInProc>;
-  SynchronousCompositorRegistryInProc();
-  ~SynchronousCompositorRegistryInProc() override;
-
-  struct Entry {
-    SynchronousCompositorImpl* compositor;
-    SynchronousCompositorExternalBeginFrameSource* begin_frame_source;
-    SynchronousCompositorOutputSurface* output_surface;
-    ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy;
-
-    Entry();
-    bool IsReady();
-  };
-
-  using EntryMap = base::hash_map<int, Entry>;
-
-  void CheckIsReady(int routing_id);
-  void UnregisterObjects(int routing_id);
-  void RemoveEntryIfNeeded(int routing_id);
-  bool CalledOnValidThread() const;
-
-  EntryMap entry_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorRegistryInProc);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_REGISTRY_IN_PROC_H_
diff --git a/content/browser/android/in_process/synchronous_input_event_filter.cc b/content/browser/android/in_process/synchronous_input_event_filter.cc
deleted file mode 100644
index b4d9f7f..0000000
--- a/content/browser/android/in_process/synchronous_input_event_filter.cc
+++ /dev/null
@@ -1,91 +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 "content/browser/android/in_process/synchronous_input_event_filter.h"
-
-#include "base/callback.h"
-#include "content/browser/android/in_process/synchronous_compositor_impl.h"
-#include "content/browser/android/in_process/synchronous_compositor_registry_in_proc.h"
-#include "content/public/browser/browser_thread.h"
-#include "ui/events/blink/synchronous_input_handler_proxy.h"
-#include "ui/events/latency_info.h"
-
-using blink::WebInputEvent;
-
-namespace content {
-
-SynchronousInputEventFilter::SynchronousInputEventFilter() {
-}
-
-SynchronousInputEventFilter::~SynchronousInputEventFilter() {
-}
-
-InputEventAckState SynchronousInputEventFilter::HandleInputEvent(
-    int routing_id,
-    const blink::WebInputEvent& input_event) {
-  // The handler will be empty both before renderer initialization and after
-  // renderer destruction. It's possible that this will be reached in such a
-  // state. While not good, it should also not be fatal.
-  if (handler_.is_null())
-    return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
-  ui::LatencyInfo latency;
-  return handler_.Run(routing_id, &input_event, &latency);
-}
-
-void SynchronousInputEventFilter::SetBoundHandler(const Handler& handler) {
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&SynchronousInputEventFilter::SetBoundHandlerOnUIThread,
-                 base::Unretained(this), handler));
-}
-
-void SynchronousInputEventFilter::DidAddInputHandler(int routing_id) {}
-void SynchronousInputEventFilter::DidRemoveInputHandler(int routing_id) {}
-
-void SynchronousInputEventFilter::SetBoundHandlerOnUIThread(
-    const Handler& handler) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  handler_ = handler;
-}
-
-void SynchronousInputEventFilter::DidOverscroll(
-    int routing_id,
-    const DidOverscrollParams& params) {
-  // The SynchronusCompositorImpl can be NULL if the WebContents that it's
-  // bound to has already been deleted.
-  SynchronousCompositorImpl* compositor =
-      SynchronousCompositorImpl::FromRoutingID(routing_id);
-  if (compositor)
-    compositor->DidOverscrollInProcess(params);
-}
-
-void SynchronousInputEventFilter::DidStopFlinging(int routing_id) {
-  // The SynchronusCompositorImpl can be NULL if the WebContents that it's
-  // bound to has already been deleted.
-  SynchronousCompositorImpl* compositor =
-      SynchronousCompositorImpl::FromRoutingID(routing_id);
-  if (compositor)
-    compositor->DidStopFlinging();
-}
-
-void SynchronousInputEventFilter::NotifyInputEventHandled(
-    int routing_id,
-    blink::WebInputEvent::Type type) {}
-
-void SynchronousInputEventFilter::DidAddSynchronousHandlerProxy(
-    int routing_id,
-    ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  SynchronousCompositorRegistryInProc::GetInstance()->RegisterInputHandler(
-      routing_id, synchronous_input_handler_proxy);
-}
-
-void SynchronousInputEventFilter::DidRemoveSynchronousHandlerProxy(
-    int routing_id) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  SynchronousCompositorRegistryInProc::GetInstance()->UnregisterInputHandler(
-      routing_id);
-}
-
-}  // namespace content
diff --git a/content/browser/android/in_process/synchronous_input_event_filter.h b/content/browser/android/in_process/synchronous_input_event_filter.h
deleted file mode 100644
index 9ecb400f..0000000
--- a/content/browser/android/in_process/synchronous_input_event_filter.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_INPUT_EVENT_FILTER_H_
-#define CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_INPUT_EVENT_FILTER_H_
-
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "content/common/input/input_event_ack_state.h"
-#include "content/renderer/input/input_handler_manager_client.h"
-#include "ui/gfx/geometry/vector2d_f.h"
-
-namespace blink {
-class WebInputEvent;
-}
-
-namespace ui {
-class SynchronousInputHandlerProxy;
-}
-
-namespace content {
-
-// This class perform synchronous, in-process InputEvent handling.
-//
-// The provided |handler| process WebInputEvents synchronously on the merged
-// UI and compositing thread. If the event goes unhandled, that is reflected in
-// the InputEventAckState; no forwarding is performed.
-class SynchronousInputEventFilter
-    : public InputHandlerManagerClient,
-      public SynchronousInputHandlerProxyClient {
- public:
-  SynchronousInputEventFilter();
-  ~SynchronousInputEventFilter() override;
-
-  InputEventAckState HandleInputEvent(int routing_id,
-                                      const blink::WebInputEvent& input_event);
-
-  // InputHandlerManagerClient implementation.
-  void SetBoundHandler(const Handler& handler) override;
-  void DidAddInputHandler(int routing_id) override;
-  void DidRemoveInputHandler(int routing_id) override;
-  void DidOverscroll(int routing_id,
-                     const DidOverscrollParams& params) override;
-  void DidStopFlinging(int routing_id) override;
-  void NotifyInputEventHandled(int routing_id,
-                               blink::WebInputEvent::Type type) override;
-
-  // SynchronousInputHandlerProxyClient overrides.
-  void DidAddSynchronousHandlerProxy(
-      int routing_id,
-      ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy)
-      override;
-  void DidRemoveSynchronousHandlerProxy(int routing_id) override;
-
- private:
-  void SetBoundHandlerOnUIThread(const Handler& handler);
-
-  Handler handler_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_INPUT_EVENT_FILTER_H_
diff --git a/content/browser/android/synchronous_compositor_base.cc b/content/browser/android/synchronous_compositor_base.cc
index 967b871e..704018ed 100644
--- a/content/browser/android/synchronous_compositor_base.cc
+++ b/content/browser/android/synchronous_compositor_base.cc
@@ -7,7 +7,6 @@
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "base/supports_user_data.h"
-#include "content/browser/android/in_process/synchronous_compositor_impl.h"
 #include "content/browser/android/synchronous_compositor_host.h"
 #include "content/browser/gpu/gpu_process_host.h"
 #include "content/browser/web_contents/web_contents_android.h"
@@ -65,17 +64,13 @@
     return nullptr;  // Not using sync compositing.
 
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kIPCSyncCompositing)) {
-    bool async_input =
-        !command_line->HasSwitch(switches::kSyncInputForSyncCompositor);
-    bool use_in_proc_software_draw =
-        command_line->HasSwitch(switches::kSingleProcess);
-    return base::WrapUnique(new SynchronousCompositorHost(
-        rwhva, web_contents_android->synchronous_compositor_client(),
-        async_input, use_in_proc_software_draw));
-  }
-  return base::WrapUnique(new SynchronousCompositorImpl(
-      rwhva, web_contents_android->synchronous_compositor_client()));
+  bool async_input =
+      !command_line->HasSwitch(switches::kSyncInputForSyncCompositor);
+  bool use_in_proc_software_draw =
+      command_line->HasSwitch(switches::kSingleProcess);
+  return base::WrapUnique(new SynchronousCompositorHost(
+      rwhva, web_contents_android->synchronous_compositor_client(), async_input,
+      use_in_proc_software_draw));
 }
 
 }  // namespace content
diff --git a/content/browser/android/synchronous_compositor_base.h b/content/browser/android/synchronous_compositor_base.h
index 8611696..51aa519 100644
--- a/content/browser/android/synchronous_compositor_base.h
+++ b/content/browser/android/synchronous_compositor_base.h
@@ -28,6 +28,7 @@
 class WebContents;
 struct DidOverscrollParams;
 
+// TODO(boliu): Merge this into SynchronousCompositorHost.
 class SynchronousCompositorBase : public SynchronousCompositor {
  public:
   static std::unique_ptr<SynchronousCompositorBase> Create(
diff --git a/content/browser/cache_storage/cache_storage_cache.cc b/content/browser/cache_storage/cache_storage_cache.cc
index 7e3b8e24..2b5f17a 100644
--- a/content/browser/cache_storage/cache_storage_cache.cc
+++ b/content/browser/cache_storage/cache_storage_cache.cc
@@ -57,8 +57,6 @@
 
 typedef base::Callback<void(std::unique_ptr<CacheMetadata>)> MetadataCallback;
 
-enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY, INDEX_SIDE_DATA };
-
 // The maximum size of each cache. Ultimately, cache size
 // is controlled per-origin by the QuotaManager.
 const int kMaxCacheBytes = std::numeric_limits<int>::max();
@@ -152,14 +150,15 @@
 void ReadMetadata(disk_cache::Entry* entry, const MetadataCallback& callback) {
   DCHECK(entry);
 
-  scoped_refptr<net::IOBufferWithSize> buffer(
-      new net::IOBufferWithSize(entry->GetDataSize(INDEX_HEADERS)));
+  scoped_refptr<net::IOBufferWithSize> buffer(new net::IOBufferWithSize(
+      entry->GetDataSize(CacheStorageCache::INDEX_HEADERS)));
 
   net::CompletionCallback read_header_callback =
       base::Bind(ReadMetadataDidReadMetadata, entry, callback, buffer);
 
-  int read_rv = entry->ReadData(INDEX_HEADERS, 0, buffer.get(), buffer->size(),
-                                read_header_callback);
+  int read_rv =
+      entry->ReadData(CacheStorageCache::INDEX_HEADERS, 0, buffer.get(),
+                      buffer->size(), read_header_callback);
 
   if (read_rv != net::ERR_IO_PENDING)
     read_header_callback.Run(read_rv);
@@ -1540,9 +1539,9 @@
   storage::BlobDataBuilder blob_data(response->blob_uuid);
 
   disk_cache::Entry* temp_entry = entry.get();
-  blob_data.AppendDiskCacheEntry(
+  blob_data.AppendDiskCacheEntryWithSideData(
       new CacheStorageCacheDataHandle(this, std::move(entry)), temp_entry,
-      INDEX_RESPONSE_BODY);
+      INDEX_RESPONSE_BODY, INDEX_SIDE_DATA);
   return blob_storage_context_->AddFinishedBlob(&blob_data);
 }
 
diff --git a/content/browser/cache_storage/cache_storage_cache.h b/content/browser/cache_storage/cache_storage_cache.h
index 78a457cb..034027d 100644
--- a/content/browser/cache_storage/cache_storage_cache.h
+++ b/content/browser/cache_storage/cache_storage_cache.h
@@ -62,6 +62,8 @@
       base::Callback<void(CacheStorageError, std::unique_ptr<Requests>)>;
   using SizeCallback = base::Callback<void(int64_t)>;
 
+  enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY, INDEX_SIDE_DATA };
+
   static scoped_refptr<CacheStorageCache> CreateMemoryCache(
       const GURL& origin,
       const std::string& cache_name,
diff --git a/content/browser/cache_storage/cache_storage_cache_unittest.cc b/content/browser/cache_storage/cache_storage_cache_unittest.cc
index 503c894b..e8a9117 100644
--- a/content/browser/cache_storage/cache_storage_cache_unittest.cc
+++ b/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -170,6 +170,31 @@
   }
 }
 
+void CopySideData(const storage::BlobDataHandle& blob_handle,
+                  std::string* output) {
+  *output = std::string();
+  std::unique_ptr<storage::BlobDataSnapshot> data =
+      blob_handle.CreateSnapshot();
+  const auto& items = data->items();
+  ASSERT_EQ(1u, items.size());
+  const auto& item = items[0];
+  ASSERT_EQ(storage::DataElement::TYPE_DISK_CACHE_ENTRY, item->type());
+  ASSERT_EQ(CacheStorageCache::INDEX_SIDE_DATA,
+            item->disk_cache_side_stream_index());
+
+  disk_cache::Entry* entry = item->disk_cache_entry();
+  int32_t body_size = entry->GetDataSize(item->disk_cache_side_stream_index());
+  scoped_refptr<net::IOBuffer> io_buffer = new net::IOBuffer(body_size);
+  net::TestCompletionCallback callback;
+  int rv = entry->ReadData(item->disk_cache_side_stream_index(), 0,
+                           io_buffer.get(), body_size, callback.callback());
+  if (rv == net::ERR_IO_PENDING)
+    rv = callback.WaitForResult();
+  EXPECT_EQ(body_size, rv);
+  if (rv > 0)
+    output->append(io_buffer->data(), rv);
+}
+
 bool ResponseMetadataEqual(const ServiceWorkerResponse& expected,
                            const ServiceWorkerResponse& actual) {
   EXPECT_EQ(expected.status_code, actual.status_code);
@@ -213,6 +238,13 @@
   return expected_body == actual_body;
 }
 
+bool ResponseSideDataEqual(const std::string& expected_side_data,
+                           const storage::BlobDataHandle& actual_body_handle) {
+  std::string actual_body;
+  CopySideData(actual_body_handle, &actual_body);
+  return expected_side_data == actual_body;
+}
+
 ServiceWorkerResponse SetCacheName(const ServiceWorkerResponse& original) {
   return ServiceWorkerResponse(
       original.url, original.status_code, original.status_text,
@@ -1085,26 +1117,36 @@
 
 TEST_P(CacheStorageCacheTestP, WriteSideData) {
   base::Time response_time(base::Time::Now());
-  ServiceWorkerResponse response;
+  ServiceWorkerResponse response(body_response_);
   response.response_time = response_time;
-  EXPECT_TRUE(Put(no_body_request_, response));
+  EXPECT_TRUE(Put(body_request_, response));
 
-  const size_t kSize1 = 10;
-  scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
-  memset(buffer1->data(), 0, kSize1);
+  const std::string expected_side_data1 = "SideDataSample";
+  scoped_refptr<net::IOBuffer> buffer1(
+      new net::StringIOBuffer(expected_side_data1));
+  EXPECT_TRUE(WriteSideData(body_request_.url, response_time, buffer1,
+                            expected_side_data1.length()));
+
+  EXPECT_TRUE(Match(body_request_));
+  EXPECT_TRUE(callback_response_data_);
   EXPECT_TRUE(
-      WriteSideData(no_body_request_.url, response_time, buffer1, kSize1));
-
-  // TODO(horo): Check the content of the saved side data when we will implement
-  // ReadMetadata() method in BlobReader.
-
-  const size_t kSize2 = 20;
-  scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize2));
-  memset(buffer2->data(), 0, kSize2);
+      ResponseBodiesEqual(expected_blob_data_, *callback_response_data_));
   EXPECT_TRUE(
-      WriteSideData(no_body_request_.url, response_time, buffer2, kSize2));
+      ResponseSideDataEqual(expected_side_data1, *callback_response_data_));
 
-  ASSERT_TRUE(Delete(no_body_request_));
+  const std::string expected_side_data2 = "New data";
+  scoped_refptr<net::IOBuffer> buffer2(
+      new net::StringIOBuffer(expected_side_data2));
+  EXPECT_TRUE(WriteSideData(body_request_.url, response_time, buffer2,
+                            expected_side_data2.length()));
+  EXPECT_TRUE(Match(body_request_));
+  EXPECT_TRUE(callback_response_data_);
+  EXPECT_TRUE(
+      ResponseBodiesEqual(expected_blob_data_, *callback_response_data_));
+  EXPECT_TRUE(
+      ResponseSideDataEqual(expected_side_data2, *callback_response_data_));
+
+  ASSERT_TRUE(Delete(body_request_));
 }
 
 TEST_P(CacheStorageCacheTestP, WriteSideData_QuotaExeeded) {
diff --git a/content/browser/compositor/gpu_browser_compositor_output_surface.cc b/content/browser/compositor/gpu_browser_compositor_output_surface.cc
index 7075406..d6b38ff 100644
--- a/content/browser/compositor/gpu_browser_compositor_output_surface.cc
+++ b/content/browser/compositor/gpu_browser_compositor_output_surface.cc
@@ -65,7 +65,7 @@
       update_vsync_parameters_callback_.callback());
   if (capabilities_.uses_default_gl_framebuffer) {
     capabilities_.flipped_output_surface =
-        context_provider()->ContextCapabilities().gpu.flips_vertically;
+        context_provider()->ContextCapabilities().flips_vertically;
   }
   return true;
 }
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index abbef9d..7bf913c4 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -45,6 +45,7 @@
 #include "content/public/common/content_switches.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/ipc/client/gpu_channel_host.h"
 #include "third_party/khronos/GLES2/gl2.h"
@@ -120,7 +121,6 @@
   return base::WrapUnique(new content::WebGraphicsContext3DCommandBufferImpl(
       surface_handle, url, gpu_channel_host.get(), attributes,
       gfx::PreferIntegratedGpu, share_resources, automatic_flushes,
-      content::WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(),
       nullptr));
 }
 
@@ -335,7 +335,7 @@
       // compositor.
       context_provider = new ContextProviderCommandBuffer(
           CreateContextCommon(gpu_channel_host, surface_handle),
-          DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT);
+          gpu::SharedMemoryLimits(), DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT);
       if (!context_provider->BindToCurrentThread())
         context_provider = nullptr;
 
@@ -343,7 +343,7 @@
         shared_worker_context_provider_ = new ContextProviderCommandBuffer(
             CreateContextCommon(std::move(gpu_channel_host),
                                 gpu::kNullSurfaceHandle),
-            BROWSER_WORKER_CONTEXT);
+            gpu::SharedMemoryLimits(), BROWSER_WORKER_CONTEXT);
         if (shared_worker_context_provider_->BindToCurrentThread())
           shared_worker_context_provider_->SetupLock();
         else
@@ -376,14 +376,13 @@
         compositor->vsync_manager(), compositor->task_runner().get()));
   } else {
     DCHECK(context_provider);
-    ContextProvider::Capabilities capabilities =
-        context_provider->ContextCapabilities();
+    const auto& capabilities = context_provider->ContextCapabilities();
     if (!data->surface_id) {
       surface = base::WrapUnique(new OffscreenBrowserCompositorOutputSurface(
           context_provider, shared_worker_context_provider_,
           compositor->vsync_manager(), compositor->task_runner().get(),
           std::unique_ptr<BrowserCompositorOverlayCandidateValidator>()));
-    } else if (capabilities.gpu.surfaceless) {
+    } else if (capabilities.surfaceless) {
       GLenum target = GL_TEXTURE_2D;
       GLenum format = GL_RGB;
 #if defined(OS_MACOSX)
@@ -628,7 +627,7 @@
   // don't step on each other.
   shared_main_thread_contexts_ = new ContextProviderCommandBuffer(
       CreateContextCommon(std::move(gpu_channel_host), gpu::kNullSurfaceHandle),
-      BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT);
+      gpu::SharedMemoryLimits(), BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT);
   shared_main_thread_contexts_->SetLostContextCallback(base::Bind(
       &GpuProcessTransportFactory::OnLostMainThreadSharedContextInsideCallback,
       callback_factory_.GetWeakPtr()));
diff --git a/content/browser/compositor/offscreen_browser_compositor_output_surface.cc b/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
index 2254cbfc..acff916 100644
--- a/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
+++ b/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
@@ -62,8 +62,8 @@
 
     GLES2Interface* gl = context_provider_->ContextGL();
 
-    int max_texture_size =
-        context_provider_->ContextCapabilities().gpu.max_texture_size;
+    const int max_texture_size =
+        context_provider_->ContextCapabilities().max_texture_size;
     int texture_width = std::min(max_texture_size, surface_size_.width());
     int texture_height = std::min(max_texture_size, surface_size_.height());
 
diff --git a/content/browser/fileapi/blob_reader_unittest.cc b/content/browser/fileapi/blob_reader_unittest.cc
index 4d8489a5..8c2fe410 100644
--- a/content/browser/fileapi/blob_reader_unittest.cc
+++ b/content/browser/fileapi/blob_reader_unittest.cc
@@ -48,6 +48,7 @@
 namespace {
 
 const int kTestDiskCacheStreamIndex = 0;
+const int kTestDiskCacheSideStreamIndex = 1;
 
 // Our disk cache tests don't need a real data handle since the tests themselves
 // scope the disk cache and entries.
@@ -176,6 +177,21 @@
   return entry;
 }
 
+disk_cache::ScopedEntryPtr CreateDiskCacheEntryWithSideData(
+    disk_cache::Backend* cache,
+    const char* key,
+    const std::string& data,
+    const std::string& side_data) {
+  disk_cache::ScopedEntryPtr entry = CreateDiskCacheEntry(cache, key, data);
+  scoped_refptr<net::StringIOBuffer> iobuffer =
+      new net::StringIOBuffer(side_data);
+  net::TestCompletionCallback callback;
+  int rv = entry->WriteData(kTestDiskCacheSideStreamIndex, 0, iobuffer.get(),
+                            iobuffer->size(), callback.callback(), false);
+  EXPECT_EQ(static_cast<int>(side_data.size()), callback.GetResult(rv));
+  return entry;
+}
+
 template <typename T>
 void SetValue(T* address, T value) {
   *address = value;
@@ -504,6 +520,8 @@
             reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
   CheckSizeCalculatedSynchronously(kData.size(), size_result);
 
+  EXPECT_FALSE(reader_->has_side_data());
+
   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
 
   int bytes_read = 0;
@@ -517,6 +535,41 @@
   EXPECT_EQ(0, memcmp(buffer->data(), "Test Blob Data", kData.size()));
 }
 
+TEST_F(BlobReaderTest, DiskCacheWithSideData) {
+  std::unique_ptr<disk_cache::Backend> cache =
+      CreateInMemoryDiskCache(message_loop_.task_runner());
+  ASSERT_TRUE(cache);
+
+  BlobDataBuilder b("uuid");
+  const std::string kData = "Test Blob Data";
+  const std::string kSideData = "Test side data";
+  scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
+      new EmptyDataHandle();
+  disk_cache::ScopedEntryPtr entry = CreateDiskCacheEntryWithSideData(
+      cache.get(), "test entry", kData, kSideData);
+  b.AppendDiskCacheEntryWithSideData(data_handle, entry.get(),
+                                     kTestDiskCacheStreamIndex,
+                                     kTestDiskCacheSideStreamIndex);
+  this->InitializeReader(&b);
+
+  int size_result = -1;
+  EXPECT_FALSE(IsReaderTotalSizeCalculated());
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  CheckSizeCalculatedSynchronously(kData.size(), size_result);
+
+  EXPECT_TRUE(reader_->has_side_data());
+  BlobReader::Status status = BlobReader::Status::DONE;
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->ReadSideData(
+                base::Bind(&SetValue<BlobReader::Status>, &status)));
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_TRUE(reader_->side_data());
+  std::string result(reader_->side_data()->data(),
+                     reader_->side_data()->size());
+  EXPECT_EQ(kSideData, result);
+}
+
 TEST_F(BlobReaderTest, BufferLargerThanMemory) {
   BlobDataBuilder b("uuid");
   const std::string kData("Hello!!!");
diff --git a/content/browser/fileapi/blob_url_request_job_unittest.cc b/content/browser/fileapi/blob_url_request_job_unittest.cc
index dd17549..bcaca831 100644
--- a/content/browser/fileapi/blob_url_request_job_unittest.cc
+++ b/content/browser/fileapi/blob_url_request_job_unittest.cc
@@ -56,8 +56,11 @@
 const char kTestFileData2[] = "This is sample file.";
 const char kTestFileSystemFileData1[] = "abcdefghijklmnop";
 const char kTestFileSystemFileData2[] = "File system file test data.";
-const char kTestDiskCacheKey[] = "pipe";
-const char kTestDiskCacheData[] = "Ceci n'est pas un pamplemousse.";
+const char kTestDiskCacheKey1[] = "key1";
+const char kTestDiskCacheKey2[] = "key2";
+const char kTestDiskCacheData1[] = "disk cache test data1.";
+const char kTestDiskCacheData2[] = "disk cache test data2.";
+const char kTestDiskCacheSideData[] = "test side data";
 const char kTestContentType[] = "foo/bar";
 const char kTestContentDisposition[] = "attachment; filename=foo.txt";
 
@@ -66,6 +69,7 @@
     storage::kFileSystemTypeTemporary;
 
 const int kTestDiskCacheStreamIndex = 0;
+const int kTestDiskCacheSideStreamIndex = 1;
 
 // Our disk cache tests don't need a real data handle since the tests themselves
 // scope the disk cache and entries.
@@ -104,6 +108,21 @@
   return entry;
 }
 
+disk_cache::ScopedEntryPtr CreateDiskCacheEntryWithSideData(
+    disk_cache::Backend* cache,
+    const char* key,
+    const std::string& data,
+    const std::string& side_data) {
+  disk_cache::ScopedEntryPtr entry = CreateDiskCacheEntry(cache, key, data);
+  scoped_refptr<net::StringIOBuffer> iobuffer =
+      new net::StringIOBuffer(side_data);
+  net::TestCompletionCallback callback;
+  int rv = entry->WriteData(kTestDiskCacheSideStreamIndex, 0, iobuffer.get(),
+                            iobuffer->size(), callback.callback(), false);
+  EXPECT_EQ(static_cast<int>(side_data.size()), callback.GetResult(rv));
+  return entry;
+}
+
 }  // namespace
 
 class BlobURLRequestJobTest : public testing::Test {
@@ -152,7 +171,7 @@
 
     disk_cache_backend_ = CreateInMemoryDiskCache();
     disk_cache_entry_ = CreateDiskCacheEntry(
-        disk_cache_backend_.get(), kTestDiskCacheKey, kTestDiskCacheData);
+        disk_cache_backend_.get(), kTestDiskCacheKey1, kTestDiskCacheData1);
 
     url_request_job_factory_.SetProtocolHandler(
         "blob", base::WrapUnique(new MockProtocolHandler(this)));
@@ -240,6 +259,7 @@
     expected_status_code_ = expected_status_code;
     expected_response_ = "";
     TestRequest("GET", net::HttpRequestHeaders());
+    EXPECT_FALSE(url_request_delegate_.metadata());
   }
 
   void TestRequest(const std::string& method,
@@ -270,7 +290,7 @@
     blob_data_->AppendDiskCacheEntry(new EmptyDataHandle(),
                                      disk_cache_entry_.get(),
                                      kTestDiskCacheStreamIndex);
-    *expected_result += std::string(kTestDiskCacheData);
+    *expected_result += std::string(kTestDiskCacheData1);
 
     blob_data_->AppendFileSystemFile(temp_file_system_file1_, 3, 4,
                                      temp_file_system_file_modification_time1_);
@@ -449,8 +469,8 @@
   blob_data_->AppendDiskCacheEntry(new EmptyDataHandle(),
                                    disk_cache_entry_.get(),
                                    kTestDiskCacheStreamIndex);
-  TestSuccessNonrangeRequest(kTestDiskCacheData,
-                             arraysize(kTestDiskCacheData) - 1);
+  TestSuccessNonrangeRequest(kTestDiskCacheData1,
+                             arraysize(kTestDiskCacheData1) - 1);
 }
 
 TEST_F(BlobURLRequestJobTest, TestGetComplicatedDataFileAndDiskCacheRequest) {
@@ -472,6 +492,7 @@
   TestRequest("GET", extra_headers);
 
   EXPECT_EQ(6, request_->response_headers()->GetContentLength());
+  EXPECT_FALSE(url_request_delegate_.metadata());
 
   int64_t first = 0, last = 0, length = 0;
   EXPECT_TRUE(
@@ -493,6 +514,7 @@
   TestRequest("GET", extra_headers);
 
   EXPECT_EQ(10, request_->response_headers()->GetContentLength());
+  EXPECT_FALSE(url_request_delegate_.metadata());
 
   int64_t total = GetTotalBlobLength();
   int64_t first = 0, last = 0, length = 0;
@@ -515,6 +537,7 @@
   TestRequest("GET", extra_headers);
 
   EXPECT_EQ(3, request_->response_headers()->GetContentLength());
+  EXPECT_FALSE(url_request_delegate_.metadata());
 
   int64_t first = 0, last = 0, length = 0;
   EXPECT_TRUE(
@@ -535,6 +558,7 @@
   std::string content_type;
   EXPECT_TRUE(request_->response_headers()->GetMimeType(&content_type));
   EXPECT_EQ(kTestContentType, content_type);
+  EXPECT_FALSE(url_request_delegate_.metadata());
   size_t iter = 0;
   std::string content_disposition;
   EXPECT_TRUE(request_->response_headers()->EnumerateHeader(
@@ -542,4 +566,41 @@
   EXPECT_EQ(kTestContentDisposition, content_disposition);
 }
 
+TEST_F(BlobURLRequestJobTest, TestSideData) {
+  disk_cache::ScopedEntryPtr disk_cache_entry_with_side_data =
+      CreateDiskCacheEntryWithSideData(disk_cache_backend_.get(),
+                                       kTestDiskCacheKey2, kTestDiskCacheData2,
+                                       kTestDiskCacheSideData);
+  blob_data_->AppendDiskCacheEntryWithSideData(
+      new EmptyDataHandle(), disk_cache_entry_with_side_data.get(),
+      kTestDiskCacheStreamIndex, kTestDiskCacheSideStreamIndex);
+  expected_status_code_ = 200;
+  expected_response_ = kTestDiskCacheData2;
+  TestRequest("GET", net::HttpRequestHeaders());
+  EXPECT_EQ(static_cast<int>(arraysize(kTestDiskCacheData2) - 1),
+            request_->response_headers()->GetContentLength());
+
+  EXPECT_TRUE(url_request_delegate_.metadata());
+  std::string metadata(url_request_delegate_.metadata()->data(),
+                       url_request_delegate_.metadata()->size());
+  EXPECT_EQ(std::string(kTestDiskCacheSideData), metadata);
+}
+
+TEST_F(BlobURLRequestJobTest, TestZeroSizeSideData) {
+  disk_cache::ScopedEntryPtr disk_cache_entry_with_side_data =
+      CreateDiskCacheEntryWithSideData(disk_cache_backend_.get(),
+                                       kTestDiskCacheKey2, kTestDiskCacheData2,
+                                       "");
+  blob_data_->AppendDiskCacheEntryWithSideData(
+      new EmptyDataHandle(), disk_cache_entry_with_side_data.get(),
+      kTestDiskCacheStreamIndex, kTestDiskCacheSideStreamIndex);
+  expected_status_code_ = 200;
+  expected_response_ = kTestDiskCacheData2;
+  TestRequest("GET", net::HttpRequestHeaders());
+  EXPECT_EQ(static_cast<int>(arraysize(kTestDiskCacheData2) - 1),
+            request_->response_headers()->GetContentLength());
+
+  EXPECT_FALSE(url_request_delegate_.metadata());
+}
+
 }  // namespace content
diff --git a/content/browser/fileapi/mock_url_request_delegate.cc b/content/browser/fileapi/mock_url_request_delegate.cc
index 79333b7..de7303a 100644
--- a/content/browser/fileapi/mock_url_request_delegate.cc
+++ b/content/browser/fileapi/mock_url_request_delegate.cc
@@ -26,6 +26,7 @@
 void MockURLRequestDelegate::OnResponseStarted(net::URLRequest* request) {
   if (request->status().is_success()) {
     EXPECT_TRUE(request->response_headers());
+    metadata_ = request->response_info().metadata;
     ReadSome(request);
   } else {
     RequestComplete();
diff --git a/content/browser/fileapi/mock_url_request_delegate.h b/content/browser/fileapi/mock_url_request_delegate.h
index d52d1bb..322d244 100644
--- a/content/browser/fileapi/mock_url_request_delegate.h
+++ b/content/browser/fileapi/mock_url_request_delegate.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_BROWSER_FILEAPI_MOCK_URL_REQUEST_DELEGATE_H_
 #define CONTENT_BROWSER_FILEAPI_MOCK_URL_REQUEST_DELEGATE_H_
 
+#include "net/base/io_buffer.h"
 #include "net/url_request/url_request.h"
 
 namespace net {
@@ -22,6 +23,7 @@
   void OnResponseStarted(net::URLRequest* request) override;
   void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
   const std::string& response_data() const { return response_data_; }
+  const net::IOBufferWithSize* metadata() const { return metadata_.get(); }
 
  private:
   void ReadSome(net::URLRequest* request);
@@ -30,6 +32,7 @@
 
   scoped_refptr<net::IOBuffer> io_buffer_;
   std::string response_data_;
+  scoped_refptr<net::IOBufferWithSize> metadata_;
 };
 
 }  // namespace content
diff --git a/content/browser/gpu/gpu_ipc_browsertests.cc b/content/browser/gpu/gpu_ipc_browsertests.cc
index 730e6a2..11d246c 100644
--- a/content/browser/gpu/gpu_ipc_browsertests.cc
+++ b/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -43,8 +43,7 @@
   bool automatic_flushes = false;
   return base::WrapUnique(new WebGraphicsContext3DCommandBufferImpl(
       gpu::kNullSurfaceHandle, GURL(), gpu_channel_host, attributes,
-      gfx::PreferIntegratedGpu, share_resources, automatic_flushes,
-      WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(), nullptr));
+      gfx::PreferIntegratedGpu, share_resources, automatic_flushes, nullptr));
 }
 
 class ContextTestBase : public content::ContentBrowserTest {
@@ -69,7 +68,7 @@
     CHECK(gpu_channel_host);
 
     provider_ = new content::ContextProviderCommandBuffer(
-        CreateContext(gpu_channel_host.get()),
+        CreateContext(gpu_channel_host.get()), gpu::SharedMemoryLimits(),
         content::OFFSCREEN_CONTEXT_FOR_TESTING);
     bool bound = provider_->BindToCurrentThread();
     CHECK(bound);
@@ -228,6 +227,7 @@
   // retain the host after provider is destroyed.
   scoped_refptr<ContextProviderCommandBuffer> provider =
       new ContextProviderCommandBuffer(CreateContext(GetGpuChannel()),
+                                       gpu::SharedMemoryLimits(),
                                        OFFSCREEN_CONTEXT_FOR_TESTING);
   EXPECT_TRUE(provider->BindToCurrentThread());
 
@@ -276,6 +276,7 @@
 
   scoped_refptr<ContextProviderCommandBuffer> provider =
       new ContextProviderCommandBuffer(CreateContext(GetGpuChannel()),
+                                       gpu::SharedMemoryLimits(),
                                        OFFSCREEN_CONTEXT_FOR_TESTING);
   base::RunLoop run_loop;
   int counter = 0;
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index a1da9c5..e59169c 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -147,7 +147,7 @@
         swap_buffers_completion_callback_.callback());
 
     populate_gpu_capabilities_callback_.Run(
-        context_provider_->ContextCapabilities().gpu);
+        context_provider_->ContextCapabilities());
     compositor_->AddObserver(this);
 
     client->SetBeginFrameSource(begin_frame_source_.get());
@@ -418,35 +418,6 @@
   host_->SetNeedsAnimate();
 }
 
-static std::unique_ptr<WebGraphicsContext3DCommandBufferImpl>
-CreateGpuProcessViewContext(
-    const scoped_refptr<gpu::GpuChannelHost>& gpu_channel_host,
-    const gpu::gles2::ContextCreationAttribHelper& attributes,
-    int surface_id) {
-  GURL url("chrome://gpu/Compositor::createContext3D");
-  static const size_t kBytesPerPixel = 4;
-  gfx::DeviceDisplayInfo display_info;
-  size_t full_screen_texture_size_in_bytes =
-      display_info.GetDisplayHeight() *
-      display_info.GetDisplayWidth() *
-      kBytesPerPixel;
-  WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
-  limits.command_buffer_size = 64 * 1024;
-  limits.start_transfer_buffer_size = 64 * 1024;
-  limits.min_transfer_buffer_size = 64 * 1024;
-  limits.max_transfer_buffer_size = std::min(
-      3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
-  limits.mapped_memory_reclaim_limit = 2 * 1024 * 1024;
-  GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get();
-  gpu::SurfaceHandle surface_handle = tracker->GetSurfaceHandle(surface_id);
-  bool share_resources = true;
-  bool automatic_flushes = false;
-  return base::WrapUnique(new WebGraphicsContext3DCommandBufferImpl(
-      surface_handle, url, gpu_channel_host.get(), attributes,
-      gfx::PreferIntegratedGpu, share_resources, automatic_flushes, limits,
-      nullptr));
-}
-
 void CompositorImpl::UpdateLayerTreeHost() {
   client_->UpdateLayerTreeHost();
   if (needs_animate_) {
@@ -549,11 +520,40 @@
   // But from here on just try and always lead to either
   // DidInitializeOutputSurface() or DidFailToInitializeOutputSurface().
   scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(factory->GetGpuChannel());
+
+  GURL url("chrome://gpu/CompositorImpl::CreateOutputSurface");
+  gpu::SurfaceHandle surface_handle =
+      GpuSurfaceTracker::Get()->GetSurfaceHandle(surface_id_);
+  constexpr bool share_resources = true;
+  constexpr bool automatic_flushes = false;
+
+  gpu::SharedMemoryLimits limits;
+  // This limit is meant to hold the contents of the display compositor
+  // drawing the scene. See discussion here:
+  // https://codereview.chromium.org/1900993002/diff/90001/content/browser/renderer_host/compositor_impl_android.cc?context=3&column_width=80&tab_spaces=8
+  limits.command_buffer_size = 64 * 1024;
+  // These limits are meant to hold the uploads for the browser UI without
+  // any excess space.
+  limits.start_transfer_buffer_size = 64 * 1024;
+  limits.min_transfer_buffer_size = 64 * 1024;
+  constexpr size_t kBytesPerPixel = 4;
+  const size_t full_screen_texture_size_in_bytes =
+      gfx::DeviceDisplayInfo().GetDisplayHeight() *
+      gfx::DeviceDisplayInfo().GetDisplayWidth() * kBytesPerPixel;
+  limits.max_transfer_buffer_size = std::min(
+      3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
+  // TODO(danakj): This limit should be on the GLHelper context instead in
+  // RWHVAndroid since that is where we do the async readback and map gpu
+  // memory to do so.
+  limits.mapped_memory_reclaim_limit = 2 * 1024 * 1024;
+
   scoped_refptr<ContextProviderCommandBuffer> context_provider(
       new ContextProviderCommandBuffer(
-          CreateGpuProcessViewContext(gpu_channel_host, attributes,
-                                      surface_id_),
-          DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT));
+          base::WrapUnique(new WebGraphicsContext3DCommandBufferImpl(
+              surface_handle, url, gpu_channel_host.get(), attributes,
+              gfx::PreferIntegratedGpu, share_resources, automatic_flushes,
+              nullptr)),
+          limits, DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT));
   DCHECK(context_provider.get());
 
   std::unique_ptr<cc::OutputSurface> real_output_surface(
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index f272f265..c7fc7f2 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -821,8 +821,7 @@
     // for Android WebView to maintain backward compatibility.
     // See crbug.com/526842 for details.
 #if defined(OS_ANDROID)
-    if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kIPCSyncCompositing)) {
+    if (GetContentClient()->UsingSynchronousCompositing()) {
       return IPC::SyncChannel::Create(
           IPC::ChannelMojo::CreateServerFactory(std::move(handle)), this,
           runner.get(), true, &never_signaled_);
@@ -836,8 +835,7 @@
 
     // Do NOT expand ifdef or run time condition checks here! See comment above.
 #if defined(OS_ANDROID)
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kIPCSyncCompositing)) {
+  if (GetContentClient()->UsingSynchronousCompositing()) {
     return IPC::SyncChannel::Create(channel_id, IPC::Channel::MODE_SERVER, this,
                                     runner.get(), true, &never_signaled_);
   }
@@ -1567,7 +1565,6 @@
     switches::kDisableLowEndDeviceMode,
 #if defined(OS_ANDROID)
     switches::kDisableUnifiedMediaPipeline,
-    switches::kIPCSyncCompositing,
     switches::kRendererWaitForJavaDebugger,
 #endif
 #if defined(OS_MACOSX)
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 d8a3a745..db2165795 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -170,14 +170,12 @@
   size_t full_screen_texture_size_in_bytes = display_info.GetDisplayHeight() *
                                              display_info.GetDisplayWidth() *
                                              kBytesPerPixel;
-  WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
+  gpu::SharedMemoryLimits limits;
   limits.command_buffer_size = 64 * 1024;
   limits.start_transfer_buffer_size = 64 * 1024;
   limits.min_transfer_buffer_size = 64 * 1024;
   limits.max_transfer_buffer_size = std::min(
       3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
-  limits.mapped_memory_reclaim_limit =
-      WebGraphicsContext3DCommandBufferImpl::kNoLimit;
 
   bool share_resources = true;
   // TODO(danakj): This should be false probably, it is for the main thread
@@ -189,9 +187,9 @@
       new WebGraphicsContext3DCommandBufferImpl(
           gpu::kNullSurfaceHandle,  // offscreen
           url, gpu_channel_host.get(), attributes, gfx::PreferIntegratedGpu,
-          share_resources, automatic_flushes, limits, nullptr));
+          share_resources, automatic_flushes, nullptr));
   provider_ = new ContextProviderCommandBuffer(
-      std::move(context), BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT);
+      std::move(context), limits, BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT);
   if (!provider_->BindToCurrentThread())
     return;
   provider_->ContextGL()->TraceBeginCHROMIUM(
diff --git a/content/common/gpu/client/context_provider_command_buffer.cc b/content/common/gpu/client/context_provider_command_buffer.cc
index e1712f5..204287f2 100644
--- a/content/common/gpu/client/context_provider_command_buffer.cc
+++ b/content/common/gpu/client/context_provider_command_buffer.cc
@@ -40,8 +40,10 @@
 
 ContextProviderCommandBuffer::ContextProviderCommandBuffer(
     std::unique_ptr<WebGraphicsContext3DCommandBufferImpl> context3d,
+    const gpu::SharedMemoryLimits& memory_limits,
     CommandBufferContextType type)
     : context3d_(std::move(context3d)),
+      memory_limits_(memory_limits),
       context_type_(type),
       debug_name_(CommandBufferContextTypeToString(type)) {
   DCHECK(main_thread_checker_.CalledOnValidThread());
@@ -81,11 +83,9 @@
     return true;
 
   context3d_->SetContextType(context_type_);
-  if (!context3d_->InitializeOnCurrentThread())
+  if (!context3d_->InitializeOnCurrentThread(memory_limits_))
     return false;
 
-  InitializeCapabilities();
-
   std::string unique_context_name =
       base::StringPrintf("%s-%p", debug_name_.c_str(), context3d_.get());
   context3d_->GetGLInterface()->TraceBeginCHROMIUM("gpu_toplevel",
@@ -146,12 +146,10 @@
   return &context_lock_;
 }
 
-cc::ContextProvider::Capabilities
-ContextProviderCommandBuffer::ContextCapabilities() {
+gpu::Capabilities ContextProviderCommandBuffer::ContextCapabilities() {
   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
   DCHECK(context_thread_checker_.CalledOnValidThread());
-
-  return capabilities_;
+  return context3d_->GetImplementation()->capabilities();
 }
 
 void ContextProviderCommandBuffer::DeleteCachedResources() {
@@ -170,18 +168,6 @@
     gr_context_->OnLostContext();
 }
 
-void ContextProviderCommandBuffer::InitializeCapabilities() {
-  Capabilities caps;
-  caps.gpu = context3d_->GetImplementation()->capabilities();
-
-  size_t mapped_memory_limit = context3d_->GetMappedMemoryLimit();
-  caps.max_transfer_buffer_usage_bytes =
-      mapped_memory_limit == WebGraphicsContext3DCommandBufferImpl::kNoLimit
-      ? std::numeric_limits<size_t>::max() : mapped_memory_limit;
-
-  capabilities_ = caps;
-}
-
 void ContextProviderCommandBuffer::SetLostContextCallback(
     const LostContextCallback& lost_context_callback) {
   DCHECK(context_thread_checker_.CalledOnValidThread());
diff --git a/content/common/gpu/client/context_provider_command_buffer.h b/content/common/gpu/client/context_provider_command_buffer.h
index 00efb1f..48a5216 100644
--- a/content/common/gpu/client/context_provider_command_buffer.h
+++ b/content/common/gpu/client/context_provider_command_buffer.h
@@ -17,6 +17,7 @@
 #include "content/common/content_export.h"
 #include "content/common/gpu/client/command_buffer_metrics.h"
 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
 
 namespace skia_bindings {
 class GrContextForGLES2Interface;
@@ -31,6 +32,7 @@
  public:
   ContextProviderCommandBuffer(
       std::unique_ptr<WebGraphicsContext3DCommandBufferImpl> context3d,
+      const gpu::SharedMemoryLimits& memory_limits,
       CommandBufferContextType type);
 
   gpu::CommandBufferProxyImpl* GetCommandBufferProxy();
@@ -47,7 +49,7 @@
   void InvalidateGrContext(uint32_t state) override;
   void SetupLock() override;
   base::Lock* GetLock() override;
-  Capabilities ContextCapabilities() override;
+  gpu::Capabilities ContextCapabilities() override;
   void DeleteCachedResources() override;
   void SetLostContextCallback(
       const LostContextCallback& lost_context_callback) override;
@@ -58,15 +60,13 @@
   void OnLostContext();
 
  private:
-  void InitializeCapabilities();
-
   base::ThreadChecker main_thread_checker_;
   base::ThreadChecker context_thread_checker_;
 
   std::unique_ptr<WebGraphicsContext3DCommandBufferImpl> context3d_;
   std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_;
 
-  cc::ContextProvider::Capabilities capabilities_;
+  gpu::SharedMemoryLimits memory_limits_;
   CommandBufferContextType context_type_;
   std::string debug_name_;
 
diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
index c9c4cf1..fa3a16f 100644
--- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
+++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
@@ -29,6 +29,7 @@
 #include "gpu/command_buffer/client/gles2_implementation.h"
 #include "gpu/command_buffer/client/gles2_trace_implementation.h"
 #include "gpu/command_buffer/client/gpu_switches.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/common/constants.h"
 #include "gpu/command_buffer/common/gpu_memory_allocation.h"
@@ -68,13 +69,6 @@
 
 } // namespace anonymous
 
-WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits::SharedMemoryLimits()
-    : command_buffer_size(kDefaultCommandBufferSize),
-      start_transfer_buffer_size(kDefaultStartTransferBufferSize),
-      min_transfer_buffer_size(kDefaultMinTransferBufferSize),
-      max_transfer_buffer_size(kDefaultMaxTransferBufferSize),
-      mapped_memory_reclaim_limit(gpu::gles2::GLES2Implementation::kNoLimit) {}
-
 WebGraphicsContext3DCommandBufferImpl::ShareGroup::ShareGroup() {
 }
 
@@ -90,7 +84,6 @@
     gfx::GpuPreference gpu_preference,
     bool share_resources,
     bool automatic_flushes,
-    const SharedMemoryLimits& limits,
     WebGraphicsContext3DCommandBufferImpl* share_context)
     : automatic_flushes_(automatic_flushes),
       attributes_(attributes),
@@ -98,7 +91,6 @@
       surface_handle_(surface_handle),
       active_url_(active_url),
       gpu_preference_(gpu_preference),
-      mem_limits_(limits),
       weak_ptr_factory_(this) {
   DCHECK(host);
   switch (attributes.context_type) {
@@ -127,7 +119,8 @@
   Destroy();
 }
 
-bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL() {
+bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL(
+    const gpu::SharedMemoryLimits& memory_limits) {
   if (initialized_)
     return true;
 
@@ -141,7 +134,7 @@
       FROM_HERE_WITH_EXPLICIT_FUNCTION(
           "125248 WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL"));
 
-  if (!CreateContext()) {
+  if (!CreateContext(memory_limits)) {
     Destroy();
 
     initialize_failed_ = true;
@@ -199,7 +192,8 @@
   return result;
 }
 
-bool WebGraphicsContext3DCommandBufferImpl::CreateContext() {
+bool WebGraphicsContext3DCommandBufferImpl::CreateContext(
+    const gpu::SharedMemoryLimits& memory_limits) {
   TRACE_EVENT0("gpu", "WebGfxCtx3DCmdBfrImpl::CreateContext");
   scoped_refptr<gpu::gles2::ShareGroup> gles2_share_group;
 
@@ -224,7 +218,7 @@
 
   // Create the GLES2 helper, which writes the command buffer protocol.
   gles2_helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer_.get()));
-  if (!gles2_helper_->Initialize(mem_limits_.command_buffer_size)) {
+  if (!gles2_helper_->Initialize(memory_limits.command_buffer_size)) {
     LOG(ERROR) << "Failed to initialize GLES2CmdHelper.";
     return false;
   }
@@ -249,11 +243,10 @@
       support_client_side_arrays, command_buffer_.get()));
   SetGLInterface(real_gl_.get());
 
-  if (!real_gl_->Initialize(
-      mem_limits_.start_transfer_buffer_size,
-      mem_limits_.min_transfer_buffer_size,
-      mem_limits_.max_transfer_buffer_size,
-      mem_limits_.mapped_memory_reclaim_limit)) {
+  if (!real_gl_->Initialize(memory_limits.start_transfer_buffer_size,
+                            memory_limits.min_transfer_buffer_size,
+                            memory_limits.max_transfer_buffer_size,
+                            memory_limits.mapped_memory_reclaim_limit)) {
     LOG(ERROR) << "Failed to initialize GLES2Implementation.";
     return false;
   }
@@ -269,8 +262,9 @@
   return true;
 }
 
-bool WebGraphicsContext3DCommandBufferImpl::InitializeOnCurrentThread() {
-  if (!MaybeInitializeGL()) {
+bool WebGraphicsContext3DCommandBufferImpl::InitializeOnCurrentThread(
+    const gpu::SharedMemoryLimits& memory_limits) {
+  if (!MaybeInitializeGL(memory_limits)) {
     DLOG(ERROR) << "Failed to initialize context.";
     return false;
   }
diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
index 8b6c8b2..f649a21 100644
--- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
+++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
@@ -31,6 +31,7 @@
 
 class ContextSupport;
 class GpuChannelHost;
+struct SharedMemoryLimits;
 class TransferBuffer;
 
 namespace gles2 {
@@ -54,16 +55,6 @@
     kNoLimit = 0,
   };
 
-  struct CONTENT_EXPORT SharedMemoryLimits {
-    SharedMemoryLimits();
-
-    size_t command_buffer_size;
-    size_t start_transfer_buffer_size;
-    size_t min_transfer_buffer_size;
-    size_t max_transfer_buffer_size;
-    size_t mapped_memory_reclaim_limit;
-  };
-
   class ShareGroup : public base::RefCountedThreadSafe<ShareGroup> {
    public:
     ShareGroup();
@@ -116,7 +107,6 @@
       gfx::GpuPreference gpu_preference,
       bool share_resources,
       bool automatic_flushes,
-      const SharedMemoryLimits& limits,
       WebGraphicsContext3DCommandBufferImpl* share_context);
 
   ~WebGraphicsContext3DCommandBufferImpl() override;
@@ -131,11 +121,8 @@
     return real_gl_.get();
   }
 
-  size_t GetMappedMemoryLimit() {
-    return mem_limits_.mapped_memory_reclaim_limit;
-  }
-
-  CONTENT_EXPORT bool InitializeOnCurrentThread();
+  CONTENT_EXPORT bool InitializeOnCurrentThread(
+      const gpu::SharedMemoryLimits& memory_limits);
 
   void SetContextType(CommandBufferContextType type) {
     context_type_ = type;
@@ -152,7 +139,7 @@
   // and subsequent calls are ignored. Must be called from the thread that is
   // going to use this object to issue GL commands (which might not be the main
   // thread).
-  bool MaybeInitializeGL();
+  bool MaybeInitializeGL(const gpu::SharedMemoryLimits& memory_limits);
 
   bool InitializeCommandBuffer(
       WebGraphicsContext3DCommandBufferImpl* share_context);
@@ -172,7 +159,7 @@
   // allocate both fake PluginWindowHandles and NativeViewIds and map
   // from fake NativeViewIds to PluginWindowHandles, but this seems like
   // unnecessary complexity at the moment.
-  bool CreateContext();
+  bool CreateContext(const gpu::SharedMemoryLimits& memory_limits);
 
   void OnContextLost();
 
@@ -192,7 +179,6 @@
   std::unique_ptr<gpu::TransferBuffer> transfer_buffer_;
   std::unique_ptr<gpu::gles2::GLES2Implementation> real_gl_;
   std::unique_ptr<gpu::gles2::GLES2Interface> trace_gl_;
-  SharedMemoryLimits mem_limits_;
   scoped_refptr<ShareGroup> share_group_;
 
   // Member variables should appear before the WeakPtrFactory, to ensure
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 94c9ae5..27102035 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -1724,16 +1724,8 @@
       'browser/web_contents/web_contents_view_android.h',
     ],
     'android_in_process_browser_sources': [
-      'browser/android/in_process/synchronous_compositor_factory_impl.cc',
-      'browser/android/in_process/synchronous_compositor_factory_impl.h',
-      'browser/android/in_process/synchronous_compositor_impl.cc',
-      'browser/android/in_process/synchronous_compositor_impl.h',
-      'browser/android/in_process/synchronous_compositor_registry_in_proc.cc',
-      'browser/android/in_process/synchronous_compositor_registry_in_proc.h',
       'browser/android/in_process/synchronous_compositor_renderer_statics.cc',
       'browser/android/in_process/synchronous_compositor_renderer_statics.h',
-      'browser/android/in_process/synchronous_input_event_filter.cc',
-      'browser/android/in_process/synchronous_input_event_filter.h',
       'browser/android/synchronous_compositor_base.cc',
       'browser/android/synchronous_compositor_base.h',
       'browser/android/synchronous_compositor_host.cc',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 7d73b7c..a6992de 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -115,8 +115,6 @@
       'renderer/android/renderer_date_time_picker.h',
       'renderer/android/synchronous_compositor_external_begin_frame_source.cc',
       'renderer/android/synchronous_compositor_external_begin_frame_source.h',
-      'renderer/android/synchronous_compositor_factory.cc',
-      'renderer/android/synchronous_compositor_factory.h',
       'renderer/android/synchronous_compositor_filter.cc',
       'renderer/android/synchronous_compositor_filter.h',
       'renderer/android/synchronous_compositor_output_surface.cc',
diff --git a/content/public/android/java/src/org/chromium/content/common/ContentSwitches.java b/content/public/android/java/src/org/chromium/content/common/ContentSwitches.java
index 4180cac..ebd10c0 100644
--- a/content/public/android/java/src/org/chromium/content/common/ContentSwitches.java
+++ b/content/public/android/java/src/org/chromium/content/common/ContentSwitches.java
@@ -73,9 +73,6 @@
     // Native switch kInProcessGPU
     public static final String IN_PROCESS_GPU = "in-process-gpu";
 
-    // Native switch kIPCSyncCompositing
-    public static final String IPC_SYNC_COMPOSITING = "ipc-sync-compositing";
-
     // Native switch kProcessType
     public static final String SWITCH_PROCESS_TYPE = "type";
 
diff --git a/content/public/common/content_client.cc b/content/public/common/content_client.cc
index 087d8b7..9085b75 100644
--- a/content/public/common/content_client.cc
+++ b/content/public/common/content_client.cc
@@ -123,4 +123,10 @@
   return base::StringPiece();
 }
 
+#if defined(OS_ANDROID)
+bool ContentClient::UsingSynchronousCompositing() {
+  return false;
+}
+#endif  // OS_ANDROID
+
 }  // namespace content
diff --git a/content/public/common/content_client.h b/content/public/common/content_client.h
index d7b0230..243afcc 100644
--- a/content/public/common/content_client.h
+++ b/content/public/common/content_client.h
@@ -158,6 +158,13 @@
   // origin trials are not enabled in this context.
   virtual base::StringPiece GetOriginTrialPublicKey();
 
+#if defined(OS_ANDROID)
+  // Returns true for clients like Android WebView that uses synchronous
+  // compositor. Note setting this to true will permit synchronous IPCs from
+  // the browser UI thread.
+  virtual bool UsingSynchronousCompositing();
+#endif  // OS_ANDROID
+
  private:
   friend class ContentClientInitializer;  // To set these pointers.
   friend class InternalTestInitializer;
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 98cf2e1..839a886 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -919,9 +919,6 @@
 // Enable drag manipulation of longpress-triggered text selections.
 const char kEnableLongpressDragSelection[]  = "enable-longpress-drag-selection";
 
-// Enable IPC-based synchronous compositing. Used by Android WebView.
-const char kIPCSyncCompositing[]            = "ipc-sync-compositing";
-
 // The telephony region (ISO country code) to use in phone number detection.
 const char kNetworkCountryIso[] = "network-country-iso";
 
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 4488907..a41744e 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -262,7 +262,6 @@
 CONTENT_EXPORT extern const char kDisableScreenOrientationLock[];
 CONTENT_EXPORT extern const char kEnableAdaptiveSelectionHandleOrientation[];
 CONTENT_EXPORT extern const char kEnableLongpressDragSelection[];
-CONTENT_EXPORT extern const char kIPCSyncCompositing[];
 CONTENT_EXPORT extern const char kHideScrollbars[];
 extern const char kNetworkCountryIso[];
 CONTENT_EXPORT extern const char kRemoteDebuggingSocketName[];
diff --git a/content/renderer/android/synchronous_compositor_factory.cc b/content/renderer/android/synchronous_compositor_factory.cc
deleted file mode 100644
index e2724be..0000000
--- a/content/renderer/android/synchronous_compositor_factory.cc
+++ /dev/null
@@ -1,27 +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 "content/renderer/android/synchronous_compositor_factory.h"
-
-#include "base/logging.h"
-
-namespace content {
-
-namespace {
-SynchronousCompositorFactory* g_instance = nullptr;
-}  // namespace
-
-// static
-void SynchronousCompositorFactory::SetInstance(
-    SynchronousCompositorFactory* instance) {
-  DCHECK(g_instance == nullptr);
-  g_instance = instance;
-}
-
-// static
-SynchronousCompositorFactory* SynchronousCompositorFactory::GetInstance() {
-  return g_instance;
-}
-
-}  // namespace content
diff --git a/content/renderer/android/synchronous_compositor_factory.h b/content/renderer/android/synchronous_compositor_factory.h
deleted file mode 100644
index 47ea588..0000000
--- a/content/renderer/android/synchronous_compositor_factory.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_FACTORY_H_
-#define CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_FACTORY_H_
-
-#include <memory>
-
-#include "base/memory/ref_counted.h"
-#include "gpu/config/gpu_info.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace cc {
-class BeginFrameSource;
-class ContextProvider;
-class OutputSurface;
-}
-
-namespace content {
-
-class InputHandlerManagerClient;
-class SynchronousInputHandlerProxyClient;
-class FrameSwapMessageQueue;
-
-// Decouples creation from usage of the parts needed for the synchonous
-// compositor rendering path. In practice this is only used in single
-// process mode (namely, for Android WebView) hence the implementation of
-// this will be injected from the logical 'browser' side code.
-class SynchronousCompositorFactory {
- public:
-  // Must only be called once, e.g. on startup. Ownership of |instance| remains
-  // with the caller.
-  static void SetInstance(SynchronousCompositorFactory* instance);
-  static SynchronousCompositorFactory* GetInstance();
-
-  virtual scoped_refptr<base::SingleThreadTaskRunner>
-  GetCompositorTaskRunner() = 0;
-  virtual std::unique_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;
-
-  // The factory maintains ownership of the returned interface.
-  virtual InputHandlerManagerClient* GetInputHandlerManagerClient() = 0;
-  virtual SynchronousInputHandlerProxyClient*
-  GetSynchronousInputHandlerProxyClient() = 0;
-
-  virtual std::unique_ptr<cc::BeginFrameSource> CreateExternalBeginFrameSource(
-      int routing_id) = 0;
-
- protected:
-  SynchronousCompositorFactory() {}
-  virtual ~SynchronousCompositorFactory() {}
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_FACTORY_H_
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index 1204f2b5..fe5ff02 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -44,6 +44,7 @@
 #include "content/common/content_switches_internal.h"
 #include "content/common/gpu/client/context_provider_command_buffer.h"
 #include "content/common/input/input_event_utils.h"
+#include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
 #include "content/renderer/gpu/render_widget_compositor_delegate.h"
 #include "content/renderer/input/input_handler_manager.h"
@@ -60,7 +61,6 @@
 
 #if defined(OS_ANDROID)
 #include "base/android/build_info.h"
-#include "content/renderer/android/synchronous_compositor_factory.h"
 #include "ui/gfx/android/device_display_info.h"
 #endif
 
@@ -368,11 +368,8 @@
   }
 
 #if defined(OS_ANDROID)
-  DCHECK(!SynchronousCompositorFactory::GetInstance() ||
-         !cmd->HasSwitch(switches::kIPCSyncCompositing));
   bool using_synchronous_compositor =
-      SynchronousCompositorFactory::GetInstance() ||
-      cmd->HasSwitch(switches::kIPCSyncCompositing);
+      GetContentClient()->UsingSynchronousCompositing();
 
   // We can't use GPU rasterization on low-end devices, because the Ganesh
   // cache would consume too much memory.
diff --git a/content/renderer/media/renderer_gpu_video_accelerator_factories.cc b/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
index ee7911bd..63ee303d 100644
--- a/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
+++ b/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
@@ -242,11 +242,11 @@
     return media::PIXEL_FORMAT_UNKNOWN;
   cc::ContextProvider::ScopedContextLock lock(context_provider_);
   auto capabilities = context_provider_->ContextCapabilities();
-  if (capabilities.gpu.image_ycbcr_420v)
+  if (capabilities.image_ycbcr_420v)
     return media::PIXEL_FORMAT_NV12;
-  if (capabilities.gpu.image_ycbcr_422)
+  if (capabilities.image_ycbcr_422)
     return media::PIXEL_FORMAT_UYVY;
-  if (capabilities.gpu.texture_rg)
+  if (capabilities.texture_rg)
     return media::PIXEL_FORMAT_I420;
   return media::PIXEL_FORMAT_UNKNOWN;
 }
diff --git a/content/renderer/media/rtc_video_encoder.cc b/content/renderer/media/rtc_video_encoder.cc
index e01a706..ae67c980 100644
--- a/content/renderer/media/rtc_video_encoder.cc
+++ b/content/renderer/media/rtc_video_encoder.cc
@@ -25,7 +25,7 @@
 #include "media/renderers/gpu_video_accelerator_factories.h"
 #include "media/video/video_encode_accelerator.h"
 #include "third_party/libyuv/include/libyuv.h"
-#include "third_party/webrtc/system_wrappers/include/tick_util.h"
+#include "third_party/webrtc/base/timeutils.h"
 
 namespace content {
 
@@ -422,7 +422,7 @@
 
   // Use webrtc timestamps to ensure correct RTP sender behavior.
   // TODO(hshi): obtain timestamp from the capturer, see crbug.com/350106.
-  const int64_t capture_time_us = webrtc::TickTime::MicrosecondTimestamp();
+  const int64_t capture_time_us = rtc::TimeMicros();
 
   // Derive the capture time (in ms) and RTP timestamp (in 90KHz ticks).
   const int64_t capture_time_ms = capture_time_us / 1000;
diff --git a/content/renderer/media/webrtc/media_stream_remote_video_source.cc b/content/renderer/media/webrtc/media_stream_remote_video_source.cc
index 8bac9d7..b82695e 100644
--- a/content/renderer/media/webrtc/media_stream_remote_video_source.cc
+++ b/content/renderer/media/webrtc/media_stream_remote_video_source.cc
@@ -19,7 +19,6 @@
 #include "media/base/video_util.h"
 #include "third_party/webrtc/media/base/videoframe.h"
 #include "third_party/webrtc/media/base/videosinkinterface.h"
-#include "third_party/webrtc/system_wrappers/include/tick_util.h"
 
 namespace content {
 
@@ -71,8 +70,7 @@
       // the offset, 2) the rate (i.e., one clock runs faster than the other).
       // See http://crbug/516700
       time_diff_(base::TimeTicks::Now() - base::TimeTicks() -
-                 base::TimeDelta::FromMicroseconds(
-                     webrtc::TickTime::MicrosecondTimestamp())) {}
+                 base::TimeDelta::FromMicroseconds(rtc::TimeMicros())) {}
 
 MediaStreamRemoteVideoSource::
 RemoteVideoSourceDelegate::~RemoteVideoSourceDelegate() {
diff --git a/content/renderer/pepper/video_decoder_shim.cc b/content/renderer/pepper/video_decoder_shim.cc
index 2024207..2b01901e 100644
--- a/content/renderer/pepper/video_decoder_shim.cc
+++ b/content/renderer/pepper/video_decoder_shim.cc
@@ -316,7 +316,7 @@
 
 bool VideoDecoderShim::YUVConverter::Initialize() {
   // If texture_rg extension is not available, use slower GL_LUMINANCE.
-  if (context_provider_->ContextCapabilities().gpu.texture_rg) {
+  if (context_provider_->ContextCapabilities().texture_rg) {
     internal_format_ = GL_RED_EXT;
     format_ = GL_RED_EXT;
   } else {
@@ -324,8 +324,7 @@
     format_ = GL_LUMINANCE;
   }
 
-  if (context_provider_->ContextCapabilities().gpu.max_texture_image_units <
-      4) {
+  if (context_provider_->ContextCapabilities().max_texture_image_units < 4) {
     // We support YUVA textures and require 4 texture units in the fragment
     // stage.
     return false;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 5126b34..ade8c17b 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -127,6 +127,7 @@
 #include "content/renderer/shared_worker/embedded_shared_worker_stub.h"
 #include "gin/public/debug.h"
 #include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/ipc/client/gpu_channel_host.h"
 #include "ipc/ipc_channel_handle.h"
 #include "ipc/ipc_platform_file.h"
@@ -165,7 +166,6 @@
 #if defined(OS_ANDROID)
 #include <cpu-features.h>
 #include "content/renderer/android/synchronous_compositor_external_begin_frame_source.h"
-#include "content/renderer/android/synchronous_compositor_factory.h"
 #include "content/renderer/android/synchronous_compositor_filter.h"
 #include "content/renderer/media/android/renderer_demuxer_android.h"
 #include "content/renderer/media/android/stream_texture_factory_impl.h"
@@ -468,8 +468,7 @@
       gpu::kNullSurfaceHandle,
       GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext3d"),
       gpu_channel_host.get(), attributes, gfx::PreferIntegratedGpu,
-      share_resources, automatic_flushes,
-      WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(), nullptr));
+      share_resources, automatic_flushes, nullptr));
 }
 
 }  // namespace
@@ -1149,53 +1148,31 @@
 }
 
 void RenderThreadImpl::InitializeCompositorThread() {
+  base::Thread::Options options;
 #if defined(OS_ANDROID)
-  SynchronousCompositorFactory* sync_compositor_factory =
-      SynchronousCompositorFactory::GetInstance();
-  const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
-  bool using_ipc_sync_compositing =
-      cmd_line->HasSwitch(switches::kIPCSyncCompositing);
-  bool sync_input_for_sync_compositing =
-      cmd_line->HasSwitch(switches::kSyncInputForSyncCompositor);
-  DCHECK(!sync_compositor_factory || !using_ipc_sync_compositing);
-  DCHECK(!sync_input_for_sync_compositing || using_ipc_sync_compositing);
-
-  if (sync_compositor_factory) {
-    compositor_task_runner_ =
-        sync_compositor_factory->GetCompositorTaskRunner();
-  }
+  options.priority = base::ThreadPriority::DISPLAY;
 #endif
-  if (!compositor_task_runner_.get()) {
-    base::Thread::Options options;
-#if defined(OS_ANDROID)
-    options.priority = base::ThreadPriority::DISPLAY;
-#endif
-    compositor_thread_.reset(new WebThreadForCompositor(options));
-    blink_platform_impl_->SetCompositorThread(compositor_thread_.get());
-    compositor_task_runner_ = compositor_thread_->GetTaskRunner();
-    compositor_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(base::IgnoreResult(&ThreadRestrictions::SetIOAllowed),
-                   false));
-  }
+  compositor_thread_.reset(new WebThreadForCompositor(options));
+  blink_platform_impl_->SetCompositorThread(compositor_thread_.get());
+  compositor_task_runner_ = compositor_thread_->GetTaskRunner();
+  compositor_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(base::IgnoreResult(&ThreadRestrictions::SetIOAllowed), false));
 
   InputHandlerManagerClient* input_handler_manager_client = nullptr;
   SynchronousInputHandlerProxyClient* synchronous_input_handler_proxy_client =
       nullptr;
 #if defined(OS_ANDROID)
-  if (using_ipc_sync_compositing) {
+  if (GetContentClient()->UsingSynchronousCompositing()) {
     sync_compositor_message_filter_ =
         new SynchronousCompositorFilter(compositor_task_runner_);
     AddFilter(sync_compositor_message_filter_.get());
-    if (sync_input_for_sync_compositing)
+    if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+            switches::kSyncInputForSyncCompositor)) {
       input_handler_manager_client = sync_compositor_message_filter_.get();
+    }
     synchronous_input_handler_proxy_client =
         sync_compositor_message_filter_.get();
-  } else if (sync_compositor_factory) {
-    input_handler_manager_client =
-        sync_compositor_factory->GetInputHandlerManagerClient();
-    synchronous_input_handler_proxy_client =
-        sync_compositor_factory->GetSynchronousInputHandlerProxyClient();
   }
 #endif
   if (!input_handler_manager_client) {
@@ -1531,7 +1508,7 @@
 
   shared_main_thread_contexts_ = new ContextProviderCommandBuffer(
       CreateOffscreenContext(std::move(gpu_channel_host)),
-      RENDERER_MAINTHREAD_CONTEXT);
+      gpu::SharedMemoryLimits(), RENDERER_MAINTHREAD_CONTEXT);
   if (!shared_main_thread_contexts_->BindToCurrentThread())
     shared_main_thread_contexts_ = nullptr;
   return shared_main_thread_contexts_;
@@ -1671,11 +1648,7 @@
 std::unique_ptr<cc::BeginFrameSource>
 RenderThreadImpl::CreateExternalBeginFrameSource(int routing_id) {
 #if defined(OS_ANDROID)
-  if (SynchronousCompositorFactory* factory =
-          SynchronousCompositorFactory::GetInstance()) {
-    DCHECK(!sync_compositor_message_filter_);
-    return factory->CreateExternalBeginFrameSource(routing_id);
-  } else if (sync_compositor_message_filter_) {
+  if (sync_compositor_message_filter_) {
     return base::WrapUnique(new SynchronousCompositorExternalBeginFrameSource(
         routing_id, sync_compositor_message_filter_.get()));
   }
@@ -2050,7 +2023,7 @@
 
   shared_worker_context_provider_ = new ContextProviderCommandBuffer(
       CreateOffscreenContext(std::move(gpu_channel_host)),
-      RENDER_WORKER_CONTEXT);
+      gpu::SharedMemoryLimits(), RENDER_WORKER_CONTEXT);
   if (!shared_worker_context_provider_->BindToCurrentThread())
     shared_worker_context_provider_ = nullptr;
   if (shared_worker_context_provider_)
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 896f57c8..6009c96 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -62,6 +62,7 @@
 #include "content/renderer/render_widget_owner_delegate.h"
 #include "content/renderer/renderer_blink_platform_impl.h"
 #include "content/renderer/resizing_mode_selector.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "ipc/ipc_sync_message.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
@@ -91,7 +92,6 @@
 
 #if defined(OS_ANDROID)
 #include <android/keycodes.h>
-#include "content/renderer/android/synchronous_compositor_factory.h"
 #include "content/renderer/android/synchronous_compositor_filter.h"
 #include "content/renderer/android/synchronous_compositor_output_surface.h"
 #endif
@@ -222,21 +222,12 @@
   attributes.bind_generates_resource = false;
   attributes.lose_context_when_out_of_memory = true;
 
-  content::WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
-  // The renderer compositor context doesn't do a lot of stuff, so we don't
-  // expect it to need a lot of space for commands or transfer. Raster and
-  // uploads happen on the worker context instead.
-  limits.command_buffer_size = 64 * 1024;
-  limits.start_transfer_buffer_size = 64 * 1024;
-  limits.min_transfer_buffer_size = 64 * 1024;
-
   bool share_resources = true;
   bool automatic_flushes = false;
 
   return base::WrapUnique(new content::WebGraphicsContext3DCommandBufferImpl(
       gpu::kNullSurfaceHandle, url, gpu_channel_host.get(), attributes,
-      gfx::PreferIntegratedGpu, share_resources, automatic_flushes, limits,
-      nullptr));
+      gfx::PreferIntegratedGpu, share_resources, automatic_flushes, nullptr));
 }
 
 }  // namespace
@@ -790,10 +781,18 @@
     }
 #endif
 
+    gpu::SharedMemoryLimits limits;
+    // The renderer compositor context doesn't do a lot of stuff, so we don't
+    // expect it to need a lot of space for commands or transfer. Raster and
+    // uploads happen on the worker context instead.
+    limits.command_buffer_size = 64 * 1024;
+    limits.start_transfer_buffer_size = 64 * 1024;
+    limits.min_transfer_buffer_size = 64 * 1024;
+
     context_provider = new ContextProviderCommandBuffer(
         CreateOffscreenContext(std::move(gpu_channel_host),
                                GetURLForGraphicsContext3D()),
-        RENDER_COMPOSITOR_CONTEXT);
+        limits, RENDER_COMPOSITOR_CONTEXT);
     worker_context_provider =
         RenderThreadImpl::current()->SharedWorkerContextProvider();
     if (!worker_context_provider) {
@@ -802,18 +801,13 @@
     }
 
 #if defined(OS_ANDROID)
-    if (SynchronousCompositorFactory* factory =
-            SynchronousCompositorFactory::GetInstance()) {
-      uint32_t output_surface_id = next_output_surface_id_++;
-      return factory->CreateOutputSurface(
-          routing_id(), output_surface_id, frame_swap_message_queue_,
-          context_provider, worker_context_provider);
-    } else if (RenderThreadImpl::current()->sync_compositor_message_filter()) {
+    if (RenderThreadImpl::current() &&
+        RenderThreadImpl::current()->sync_compositor_message_filter()) {
       uint32_t output_surface_id = next_output_surface_id_++;
       return base::WrapUnique(new SynchronousCompositorOutputSurface(
           context_provider, worker_context_provider, routing_id(),
-          output_surface_id, content::RenderThreadImpl::current()
-                                 ->sync_compositor_message_filter(),
+          output_surface_id,
+          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 d214791f..5a15965 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -1058,15 +1058,14 @@
   bool automatic_flushes = true;
   // Prefer discrete GPU for WebGL.
   gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
-  WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
 
   scoped_refptr<ContextProviderCommandBuffer> provider(
       new ContextProviderCommandBuffer(
           base::WrapUnique(new WebGraphicsContext3DCommandBufferImpl(
               gpu::kNullSurfaceHandle, GURL(top_document_web_url),
               gpu_channel_host.get(), attributes, gpu_preference,
-              share_resources, automatic_flushes, limits, share_context)),
-          RENDERER_MAINTHREAD_CONTEXT));
+              share_resources, automatic_flushes, share_context)),
+          gpu::SharedMemoryLimits(), RENDERER_MAINTHREAD_CONTEXT));
   if (!provider->BindToCurrentThread()) {
     // Collect Graphicsinfo if there is a context failure or it is failed
     // purposefully in case of layout tests.
diff --git a/content/renderer/webgraphicscontext3d_provider_impl.cc b/content/renderer/webgraphicscontext3d_provider_impl.cc
index 74c2866f..16deb534 100644
--- a/content/renderer/webgraphicscontext3d_provider_impl.cc
+++ b/content/renderer/webgraphicscontext3d_provider_impl.cc
@@ -30,7 +30,7 @@
 }
 
 gpu::Capabilities WebGraphicsContext3DProviderImpl::getCapabilities() {
-  return provider_->ContextCapabilities().gpu;
+  return provider_->ContextCapabilities();
 }
 
 void WebGraphicsContext3DProviderImpl::setLostContextCallback(
diff --git a/content/test/gpu/gpu_tests/webgl_conformance.py b/content/test/gpu/gpu_tests/webgl_conformance.py
index b2ec479e..803b44e 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance.py
@@ -71,6 +71,13 @@
   size = min(len(ver_num1), len(ver_num2))
   return cmp(ver_num1[0:size], ver_num2[0:size])
 
+
+def GenerateTestNameFromTestPath(test_path):
+  return  ('WebglConformance.%s' %
+           test_path.replace('/', '_').replace('-', '_').
+           replace('\\', '_').rpartition('.')[0].replace('.', '_'))
+
+
 class WebglConformanceValidator(gpu_test_base.ValidatorBase):
   def __init__(self):
     super(WebglConformanceValidator, self).__init__()
@@ -175,9 +182,7 @@
     super(WebglConformancePage, self).__init__(
       url='file://' + test, page_set=story_set, base_dir=story_set.base_dir,
       shared_page_state_class=gpu_test_base.DesktopGpuSharedPageState,
-      name=('WebglConformance.%s' %
-              test.replace('/', '_').replace('-', '_').
-                 replace('\\', '_').rpartition('.')[0].replace('.', '_')),
+      name=(GenerateTestNameFromTestPath(test)),
       expectations=expectations)
     self.script_to_evaluate_on_commit = conformance_harness_script
 
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py b/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py
new file mode 100644
index 0000000..f611d08
--- /dev/null
+++ b/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py
@@ -0,0 +1,62 @@
+# 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.
+
+from gpu_tests import webgl_conformance
+
+from telemetry.testing import serially_executed_browser_test_case
+
+
+class WebGLConformanceIntegrationTest(
+    serially_executed_browser_test_case.SeriallyBrowserTestCase):
+
+  _webgl_version = None
+
+  @classmethod
+  def Name(cls):
+    return 'webgl_conformance'
+
+  @classmethod
+  def AddCommandlineArgs(cls, parser):
+    parser.add_option('--webgl-conformance-version',
+        help='Version of the WebGL conformance tests to run.',
+        default='1.0.4')
+    parser.add_option('--webgl2-only',
+        help='Whether we include webgl 1 tests if version is 2.0.0 or above.',
+        default='false')
+
+  @classmethod
+  def GenerateTestCases_RunWebGLTests(cls, options):
+    test_paths = webgl_conformance.WebglConformance._ParseTests(
+        '00_test_list.txt',
+        options.webgl_conformance_version,
+        (options.webgl2_only == 'true'),
+        None)
+    cls._webgl_version = [
+        int(x) for x in options.webgl_conformance_version.split('.')][0]
+    for test in test_paths:
+      # generated test name cannot contain '.'
+      name = webgl_conformance.GenerateTestNameFromTestPath(test).replace(
+          '.', '_')
+      yield name, (test, )
+
+  def RunWebGLTests(self, test_path):
+    url = self.UrlOfStaticFilePath(test_path)
+    harness_script = webgl_conformance.conformance_harness_script
+    self.tab.Navigate(url, script_to_evaluate_on_commit=harness_script)
+
+    if not webgl_conformance._DidWebGLTestSucceed(self.tab):
+      self.fail(webgl_conformance._WebGLTestMessages(self.tab))
+
+  @classmethod
+  def CustomizeOptions(cls):
+    validator = webgl_conformance.WebglConformanceValidator()
+    validator.CustomizeBrowserOptions(cls._finder_options.browser_options)
+
+  @classmethod
+  def setUpClass(cls):
+    super(cls, WebGLConformanceIntegrationTest).setUpClass()
+    cls.CustomizeOptions()
+    cls.StartBrowser(cls._finder_options)
+    cls.tab = cls._browser.tabs[0]
+    cls.SetStaticServerDir(webgl_conformance.conformance_path)
diff --git a/content/test/gpu/run_gpu_integration_test.py b/content/test/gpu/run_gpu_integration_test.py
new file mode 100755
index 0000000..9a06168
--- /dev/null
+++ b/content/test/gpu/run_gpu_integration_test.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+# 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.
+
+import sys
+
+from gpu_tests import path_util
+import gpu_project_config
+
+path_util.SetupTelemetryPaths()
+
+from telemetry.testing import browser_test_runner
+
+
+def main():
+  options = browser_test_runner.TestRunOptions()
+  return browser_test_runner.Run(
+      gpu_project_config.CONFIG, options, sys.argv[1:])
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/extensions/browser/event_router.h b/extensions/browser/event_router.h
index e93110d3..c90a335 100644
--- a/extensions/browser/event_router.h
+++ b/extensions/browser/event_router.h
@@ -164,8 +164,8 @@
   bool HasEventListener(const std::string& event_name);
 
   // Returns true if the extension is listening to the given event.
-  virtual bool ExtensionHasEventListener(const std::string& extension_id,
-                                         const std::string& event_name);
+  bool ExtensionHasEventListener(const std::string& extension_id,
+                                 const std::string& event_name);
 
   // Return or set the list of events for which the given extension has
   // registered.
diff --git a/extensions/browser/updater/extension_downloader.cc b/extensions/browser/updater/extension_downloader.cc
index 6d94e86..116ef7a 100644
--- a/extensions/browser/updater/extension_downloader.cc
+++ b/extensions/browser/updater/extension_downloader.cc
@@ -27,7 +27,6 @@
 #include "extensions/browser/extensions_browser_client.h"
 #include "extensions/browser/notification_types.h"
 #include "extensions/browser/updater/extension_cache.h"
-#include "extensions/browser/updater/extension_downloader_test_delegate.h"
 #include "extensions/browser/updater/request_queue_impl.h"
 #include "extensions/browser/updater/safe_manifest_parser.h"
 #include "extensions/common/extension_urls.h"
@@ -91,8 +90,6 @@
 const char kWebstoreOAuth2Scope[] =
     "https://www.googleapis.com/auth/chromewebstore.readonly";
 
-ExtensionDownloaderTestDelegate* g_test_delegate = nullptr;
-
 #define RETRY_HISTOGRAM(name, retry_count, url)                           \
   if ((url).DomainIs(kGoogleDotCom)) {                                    \
     UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions." name "RetryCountGoogleUrl", \
@@ -281,12 +278,6 @@
   identity_provider_.swap(identity_provider);
 }
 
-// static
-void ExtensionDownloader::set_test_delegate(
-    ExtensionDownloaderTestDelegate* delegate) {
-  g_test_delegate = delegate;
-}
-
 bool ExtensionDownloader::AddExtensionData(const std::string& id,
                                            const Version& version,
                                            Manifest::Type extension_type,
@@ -414,11 +405,6 @@
 
 void ExtensionDownloader::StartUpdateCheck(
     scoped_ptr<ManifestFetchData> fetch_data) {
-  if (g_test_delegate) {
-    g_test_delegate->StartUpdateCheck(this, delegate_, std::move(fetch_data));
-    return;
-  }
-
   const std::set<std::string>& id_set(fetch_data->extension_ids());
 
   if (!ExtensionsBrowserClient::Get()->IsBackgroundUpdateAllowed()) {
diff --git a/extensions/browser/updater/extension_downloader.h b/extensions/browser/updater/extension_downloader.h
index 3de9b13..81b9134 100644
--- a/extensions/browser/updater/extension_downloader.h
+++ b/extensions/browser/updater/extension_downloader.h
@@ -46,7 +46,6 @@
 };
 
 class ExtensionCache;
-class ExtensionDownloaderTestDelegate;
 class ExtensionUpdaterTest;
 
 // A class that checks for updates of a given list of extensions, and downloads
@@ -115,10 +114,6 @@
     enable_extra_update_metrics_ = enable;
   }
 
-  // Sets a test delegate to use by any instances of this class. The |delegate|
-  // should outlive all instances.
-  static void set_test_delegate(ExtensionDownloaderTestDelegate* delegate);
-
   // These are needed for unit testing, to help identify the correct mock
   // URLFetcher objects.
   static const int kManifestFetcherId = 1;
diff --git a/extensions/browser/updater/extension_downloader_test_delegate.h b/extensions/browser/updater/extension_downloader_test_delegate.h
deleted file mode 100644
index 64714d6f..0000000
--- a/extensions/browser/updater/extension_downloader_test_delegate.h
+++ /dev/null
@@ -1,32 +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 EXTENSIONS_BROWSER_UPDATER_EXTENSION_DOWNLOADER_TEST_DELEGATE_H_
-#define EXTENSIONS_BROWSER_UPDATER_EXTENSION_DOWNLOADER_TEST_DELEGATE_H_
-
-#include <memory>
-
-namespace extensions {
-
-class ExtensionDownloader;
-class ExtensionDownloaderDelegate;
-class ManifestFetchData;
-
-// A class for intercepting the work of checking for / downloading extension
-// updates.
-class ExtensionDownloaderTestDelegate {
- public:
-  // This method gets called when an update check is being started for an
-  // extension. Normally implementors should eventually call either
-  // OnExtensionDownloadFailed or OnExtensionDownloadFinished on
-  // |delegate|.
-  virtual void StartUpdateCheck(
-      ExtensionDownloader* downloader,
-      ExtensionDownloaderDelegate* delegate,
-      std::unique_ptr<ManifestFetchData> fetch_data) = 0;
-};
-
-}  // namespace extensions
-
-#endif  // EXTENSIONS_BROWSER_UPDATER_EXTENSION_DOWNLOADER_TEST_DELEGATE_H_
diff --git a/extensions/extensions.gypi b/extensions/extensions.gypi
index d9b258a..c7b0a08 100644
--- a/extensions/extensions.gypi
+++ b/extensions/extensions.gypi
@@ -761,7 +761,6 @@
       'browser/updater/extension_downloader.h',
       'browser/updater/extension_downloader_delegate.cc',
       'browser/updater/extension_downloader_delegate.h',
-      'browser/updater/extension_downloader_test_delegate.h',
       'browser/updater/manifest_fetch_data.cc',
       'browser/updater/manifest_fetch_data.h',
       'browser/updater/null_extension_cache.cc',
diff --git a/gpu/command_buffer/client/gl_in_process_context.cc b/gpu/command_buffer/client/gl_in_process_context.cc
index 74a7d59..ea9b3315 100644
--- a/gpu/command_buffer/client/gl_in_process_context.cc
+++ b/gpu/command_buffer/client/gl_in_process_context.cc
@@ -28,6 +28,7 @@
 #include "base/message_loop/message_loop.h"
 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/common/command_buffer.h"
 #include "gpu/command_buffer/common/constants.h"
@@ -208,8 +209,7 @@
       start_transfer_buffer_size(kDefaultStartTransferBufferSize),
       min_transfer_buffer_size(kDefaultMinTransferBufferSize),
       max_transfer_buffer_size(kDefaultMaxTransferBufferSize),
-      mapped_memory_reclaim_limit(gles2::GLES2Implementation::kNoLimit) {
-}
+      mapped_memory_reclaim_limit(SharedMemoryLimits::kNoLimit) {}
 
 // static
 GLInProcessContext* GLInProcessContext::Create(
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index d19a44bd..f46e453 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -32,6 +32,7 @@
 #include "gpu/command_buffer/client/gpu_control.h"
 #include "gpu/command_buffer/client/program_info_manager.h"
 #include "gpu/command_buffer/client/query_tracker.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/client/vertex_array_object_manager.h"
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
@@ -215,7 +216,7 @@
   mapped_memory_.reset(new MappedMemoryManager(helper_, mapped_memory_limit));
 
   unsigned chunk_size = 2 * 1024 * 1024;
-  if (mapped_memory_limit != kNoLimit) {
+  if (mapped_memory_limit != SharedMemoryLimits::kNoLimit) {
     // Use smaller chunks if the client is very memory conscientious.
     chunk_size = std::min(mapped_memory_limit / 4, chunk_size);
   }
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 059e87d4f..a5e287a 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -124,10 +124,6 @@
       NON_EXPORTED_BASE(public GpuControlClient),
       NON_EXPORTED_BASE(public base::trace_event::MemoryDumpProvider) {
  public:
-  enum MappedMemoryLimit {
-    kNoLimit = MappedMemoryManager::kNoLimit,
-  };
-
   // Stores GL state that never changes.
   struct GLES2_IMPL_EXPORT GLStaticState {
     GLStaticState();
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index 9f6a376a..df9081d 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -22,6 +22,7 @@
 #include "gpu/command_buffer/client/program_info_manager.h"
 #include "gpu/command_buffer/client/query_tracker.h"
 #include "gpu/command_buffer/client/ring_buffer.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/common/command_buffer.h"
 #include "gpu/command_buffer/common/sync_token.h"
@@ -501,7 +502,7 @@
       EXPECT_CALL(*gpu_control_, SetGpuControlClient(gl_.get())).Times(1);
 
       if (!gl_->Initialize(kTransferBufferSize, kTransferBufferSize,
-                           kTransferBufferSize, GLES2Implementation::kNoLimit))
+                           kTransferBufferSize, SharedMemoryLimits::kNoLimit))
         return false;
 
       helper_->CommandBufferHelper::Finish();
diff --git a/gpu/command_buffer/client/mapped_memory.cc b/gpu/command_buffer/client/mapped_memory.cc
index cd1ff41f..69ed174 100644
--- a/gpu/command_buffer/client/mapped_memory.cc
+++ b/gpu/command_buffer/client/mapped_memory.cc
@@ -18,6 +18,7 @@
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/common/buffer.h"
 
 namespace gpu {
@@ -44,7 +45,7 @@
       helper_(helper),
       allocated_memory_(0),
       max_free_bytes_(unused_memory_reclaim_limit),
-      max_allocated_bytes_(kNoLimit),
+      max_allocated_bytes_(SharedMemoryLimits::kNoLimit),
       tracing_id_(g_next_mapped_memory_manager_tracing_id.GetNext()) {
   // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
   // Don't register a dump provider in these cases.
@@ -88,7 +89,7 @@
     // If there is a memory limit being enforced and total free
     // memory (allocated_memory_ - total_bytes_in_use) is larger than
     // the limit try waiting.
-    if (max_free_bytes_ != kNoLimit &&
+    if (max_free_bytes_ != SharedMemoryLimits::kNoLimit &&
         (allocated_memory_ - total_bytes_in_use) >= max_free_bytes_) {
       TRACE_EVENT0("gpu", "MappedMemoryManager::Alloc::wait");
       for (auto& chunk : chunks_) {
@@ -103,7 +104,7 @@
     }
   }
 
-  if (max_allocated_bytes_ != kNoLimit &&
+  if (max_allocated_bytes_ != SharedMemoryLimits::kNoLimit &&
       (allocated_memory_ + size) > max_allocated_bytes_) {
     return nullptr;
   }
diff --git a/gpu/command_buffer/client/shared_memory_limits.h b/gpu/command_buffer/client/shared_memory_limits.h
new file mode 100644
index 0000000..8066c42
--- /dev/null
+++ b/gpu/command_buffer/client/shared_memory_limits.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 GPU_COMMAND_BUFFER_CLIENT_SHARED_MEMORY_LIMITS_H_
+#define GPU_COMMAND_BUFFER_CLIENT_SHARED_MEMORY_LIMITS_H_
+
+#include <stddef.h>
+
+namespace gpu {
+
+struct SharedMemoryLimits {
+  int32_t command_buffer_size = 1024 * 1024;
+  uint32_t start_transfer_buffer_size = 1 * 1024 * 1024;
+  uint32_t min_transfer_buffer_size = 1 * 256 * 1024;
+  uint32_t max_transfer_buffer_size = 16 * 1024 * 1024;
+
+  static constexpr uint32_t kNoLimit = 0;
+  uint32_t mapped_memory_reclaim_limit = kNoLimit;
+};
+
+}  // namespace gpu
+
+#endif  // GPU_COMMAND_BUFFER_CLIENT_SHARED_MEMORY_LIMITS_H_
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index 006903c..4b37c2c 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -21,6 +21,7 @@
 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
 #include "gpu/command_buffer/client/gles2_lib.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/common/constants.h"
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
@@ -384,11 +385,9 @@
                                      this));
 
   ASSERT_TRUE(gles2_implementation_->Initialize(
-      kStartTransferBufferSize,
-      kMinTransferBufferSize,
-      kMaxTransferBufferSize,
-      gpu::gles2::GLES2Implementation::kNoLimit))
-          << "Could not init GLES2Implementation";
+      kStartTransferBufferSize, kMinTransferBufferSize, kMaxTransferBufferSize,
+      SharedMemoryLimits::kNoLimit))
+      << "Could not init GLES2Implementation";
 
   MakeCurrent();
 }
diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc
index f1ce3a23..bf695a71 100644
--- a/gpu/gles2_conform_support/egl/display.cc
+++ b/gpu/gles2_conform_support/egl/display.cc
@@ -15,6 +15,7 @@
 #include "base/lazy_instance.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
 #include "gpu/command_buffer/client/gles2_lib.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/common/value_state.h"
 #include "gpu/command_buffer/service/context_group.h"
@@ -294,11 +295,9 @@
                                           support_client_side_arrays,
                                           this));
 
-  if (!context_->Initialize(
-      kTransferBufferSize,
-      kTransferBufferSize / 2,
-      kTransferBufferSize * 2,
-      gpu::gles2::GLES2Implementation::kNoLimit)) {
+  if (!context_->Initialize(kTransferBufferSize, kTransferBufferSize / 2,
+                            kTransferBufferSize * 2,
+                            gpu::SharedMemoryLimits::kNoLimit)) {
     return EGL_NO_CONTEXT;
   }
 
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 8dcbb291..d002871 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -534,17 +534,17 @@
         'gles2_conform_support/egl/test_support.cc',
         'gles2_conform_support/egl/test_support.h',
       ],
-          'defines': [
+      'defines': [
         'COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY',
         'EGLAPIENTRY=',
-          ],
+      ],
       'conditions': [
         ['OS=="win"', {
           'defines': [
             'EGLAPI=__declspec(dllexport)',
           ],
         }, { # OS!="win"
-                  'defines': [
+          'defines': [
             'EGLAPI=__attribute__((visibility(\"default\")))'
           ],
         }],
@@ -567,7 +567,7 @@
         'command_buffer/tests/command_buffer_gles2_tests_main.cc',
         'command_buffer/tests/egl_test.cc',
       ],
-          'defines': [
+      'defines': [
          'COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY',
          'EGLAPIENTRY=',
       ],
@@ -577,7 +577,7 @@
             'EGLAPI=__declspec(dllimport)',
           ],
         }, { # OS!="win"
-                  'defines': [
+          'defines': [
             'EGLAPI=',
           ],
         }],
diff --git a/mojo/gles2/gles2_context.cc b/mojo/gles2/gles2_context.cc
index 58b86bd..8159407b 100644
--- a/mojo/gles2/gles2_context.cc
+++ b/mojo/gles2/gles2_context.cc
@@ -11,19 +11,13 @@
 
 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "mojo/public/c/gles2/gles2.h"
 #include "mojo/public/cpp/system/core.h"
 
 namespace gles2 {
 
-namespace {
-const size_t kDefaultCommandBufferSize = 1024 * 1024;
-const size_t kDefaultStartTransferBufferSize = 1 * 1024 * 1024;
-const size_t kDefaultMinTransferBufferSize = 1 * 256 * 1024;
-const size_t kDefaultMaxTransferBufferSize = 16 * 1024 * 1024;
-}
-
 GLES2Context::GLES2Context(const std::vector<int32_t>& attribs,
                            mojo::ScopedMessagePipeHandle command_buffer_handle,
                            MojoGLES2ContextLost lost_callback,
@@ -37,8 +31,10 @@
 bool GLES2Context::Initialize() {
   if (!command_buffer_.Initialize())
     return false;
+
+  constexpr gpu::SharedMemoryLimits default_limits;
   gles2_helper_.reset(new gpu::gles2::GLES2CmdHelper(&command_buffer_));
-  if (!gles2_helper_->Initialize(kDefaultCommandBufferSize))
+  if (!gles2_helper_->Initialize(default_limits.command_buffer_size))
     return false;
   gles2_helper_->SetAutomaticFlushes(false);
   transfer_buffer_.reset(new gpu::TransferBuffer(gles2_helper_.get()));
@@ -57,10 +53,10 @@
                                           lose_context_when_out_of_memory,
                                           support_client_side_arrays,
                                           &command_buffer_));
-  if (!implementation_->Initialize(kDefaultStartTransferBufferSize,
-                                   kDefaultMinTransferBufferSize,
-                                   kDefaultMaxTransferBufferSize,
-                                   gpu::gles2::GLES2Implementation::kNoLimit))
+  if (!implementation_->Initialize(default_limits.start_transfer_buffer_size,
+                                   default_limits.min_transfer_buffer_size,
+                                   default_limits.max_transfer_buffer_size,
+                                   default_limits.mapped_memory_reclaim_limit))
     return false;
   implementation_->SetLostContextCallback(
       base::Bind(&GLES2Context::OnLostContext, base::Unretained(this)));
diff --git a/net/android/network_change_notifier_android_unittest.cc b/net/android/network_change_notifier_android_unittest.cc
index 6d714706..c6ba7c5 100644
--- a/net/android/network_change_notifier_android_unittest.cc
+++ b/net/android/network_change_notifier_android_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/message_loop/message_loop.h"
 #include "net/android/network_change_notifier_android.h"
 #include "net/android/network_change_notifier_delegate_android.h"
+#include "net/base/ip_address.h"
 #include "net/base/network_change_notifier.h"
 #include "net/dns/dns_config_service.h"
 #include "net/dns/dns_protocol.h"
@@ -293,10 +294,8 @@
     : public BaseNetworkChangeNotifierAndroidTest {
  protected:
   void SetUp() override {
-    IPAddressNumber dns_number;
-    ASSERT_TRUE(ParseIPLiteralToNumber("8.8.8.8", &dns_number));
     dns_config_.nameservers.push_back(
-        IPEndPoint(dns_number, dns_protocol::kDefaultPort));
+        IPEndPoint(IPAddress(8, 8, 8, 8), dns_protocol::kDefaultPort));
     notifier_.reset(new NetworkChangeNotifierAndroid(&delegate_, &dns_config_));
     NetworkChangeNotifier::AddConnectionTypeObserver(
         &connection_type_observer_);
diff --git a/net/base/ip_address_unittest.cc b/net/base/ip_address_unittest.cc
index 35fdd741..75347c5 100644
--- a/net/base/ip_address_unittest.cc
+++ b/net/base/ip_address_unittest.cc
@@ -124,7 +124,7 @@
   EXPECT_FALSE(empty_address.IsZero());
 }
 
-TEST(IpAddressNumberTest, IsIPv4Mapped) {
+TEST(IPAddressTest, IsIPv4Mapped) {
   IPAddress ipv4_address(192, 168, 0, 1);
   EXPECT_FALSE(ipv4_address.IsIPv4MappedIPv6());
   IPAddress ipv6_address(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
@@ -193,7 +193,7 @@
   EXPECT_EQ("1:abcd::3:4:ff", address.ToString());
 }
 
-TEST(IpAddressNumberTest, IsIPv4MappedIPv6) {
+TEST(IPAddressTest, IsIPv4MappedIPv6) {
   IPAddress ipv4_address(192, 168, 0, 1);
   EXPECT_FALSE(ipv4_address.IsIPv4MappedIPv6());
   IPAddress ipv6_address = IPAddress::IPv6Localhost();
diff --git a/net/dns/mojo_host_type_converters.cc b/net/dns/mojo_host_type_converters.cc
index 2e404e0..760ee3b 100644
--- a/net/dns/mojo_host_type_converters.cc
+++ b/net/dns/mojo_host_type_converters.cc
@@ -89,8 +89,8 @@
   net::AddressList address_list;
   for (size_t i = 0; i < obj.addresses.size(); i++) {
     const net::interfaces::IPEndPointPtr& ep = obj.addresses[i];
-    address_list.push_back(
-        net::IPEndPoint(ep->address.To<net::IPAddressNumber>(), ep->port));
+    net::IPAddress ip_address(ep->address.To<std::vector<uint8_t>>());
+    address_list.push_back(net::IPEndPoint(ip_address, ep->port));
   }
   return address_list;
 }
diff --git a/net/tools/quic/quic_packet_reader.cc b/net/tools/quic/quic_packet_reader.cc
index beba973..5e690a4 100644
--- a/net/tools/quic/quic_packet_reader.cc
+++ b/net/tools/quic/quic_packet_reader.cc
@@ -112,7 +112,7 @@
     }
 
     IPEndPoint client_address = IPEndPoint(packets_[i].raw_address);
-    IPAddressNumber server_ip;
+    IPAddress server_ip;
     QuicTime packet_timestamp = QuicTime::Zero();
     QuicSocketUtils::GetAddressAndTimestampFromMsghdr(
         &mmsg_hdr_[i].msg_hdr, &server_ip, &packet_timestamp);
diff --git a/ppapi/shared_impl/ppb_graphics_3d_shared.cc b/ppapi/shared_impl/ppb_graphics_3d_shared.cc
index 108b415..af53bfb 100644
--- a/ppapi/shared_impl/ppb_graphics_3d_shared.cc
+++ b/ppapi/shared_impl/ppb_graphics_3d_shared.cc
@@ -7,6 +7,7 @@
 #include "base/logging.h"
 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "ppapi/c/pp_errors.h"
@@ -143,10 +144,9 @@
       GetGpuControl()));
 
   if (!gles2_impl_->Initialize(
-           transfer_buffer_size,
-           kMinTransferBufferSize,
-           std::max(kMaxTransferBufferSize, transfer_buffer_size),
-           gpu::gles2::GLES2Implementation::kNoLimit)) {
+          transfer_buffer_size, kMinTransferBufferSize,
+          std::max(kMaxTransferBufferSize, transfer_buffer_size),
+          gpu::SharedMemoryLimits::kNoLimit)) {
     return false;
   }
 
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
index 32dc4d1..f0392b1a 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
@@ -248,6 +248,19 @@
 TEST_BASELINE_SIGSYS(__NR_vserver);
 #endif
 
+#if defined(LIBC_GLIBC) && !defined(OS_CHROMEOS)
+BPF_TEST_C(BaselinePolicy, FutexEINVAL, BaselinePolicy) {
+  int ops[] = {
+      FUTEX_CMP_REQUEUE_PI, FUTEX_CMP_REQUEUE_PI_PRIVATE,
+      FUTEX_UNLOCK_PI_PRIVATE,
+  };
+
+  for (int op : ops) {
+    BPF_ASSERT_EQ(-1, syscall(__NR_futex, NULL, op, 0, NULL, NULL, 0));
+    BPF_ASSERT_EQ(EINVAL, errno);
+  }
+}
+#else
 BPF_DEATH_TEST_C(BaselinePolicy,
                  FutexWithRequeuePriorityInheritence,
                  DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
@@ -271,6 +284,7 @@
   syscall(__NR_futex, NULL, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0);
   _exit(1);
 }
+#endif  // defined(LIBC_GLIBC) && !defined(OS_CHROMEOS)
 
 BPF_TEST_C(BaselinePolicy, PrctlDumpable, BaselinePolicy) {
   const int is_dumpable = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
index 98ac100..f5cbef00 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -99,6 +99,18 @@
 #endif
 }
 
+// Ubuntu's version of glibc has a race condition in sem_post that can cause
+// it to call futex(2) with bogus op arguments. To workaround this, we need
+// to allow those futex(2) calls to fail with EINVAL, instead of crashing the
+// process. See crbug.com/598471.
+inline bool IsBuggyGlibcSemPost() {
+#if defined(LIBC_GLIBC) && !defined(OS_CHROMEOS)
+  return true;
+#else
+  return false;
+#endif
+}
+
 }  // namespace.
 
 #define CASES SANDBOX_BPF_DSL_CASES
@@ -253,15 +265,10 @@
   const uint64_t kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME;
   const Arg<int> op(1);
   return Switch(op & ~kAllowedFutexFlags)
-      .CASES((FUTEX_WAIT,
-              FUTEX_WAKE,
-              FUTEX_REQUEUE,
-              FUTEX_CMP_REQUEUE,
-              FUTEX_WAKE_OP,
-              FUTEX_WAIT_BITSET,
-              FUTEX_WAKE_BITSET),
+      .CASES((FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE, FUTEX_CMP_REQUEUE,
+              FUTEX_WAKE_OP, FUTEX_WAIT_BITSET, FUTEX_WAKE_BITSET),
              Allow())
-      .Default(CrashSIGSYSFutex());
+      .Default(IsBuggyGlibcSemPost() ? Error(EINVAL) : CrashSIGSYSFutex());
 }
 
 ResultExpr RestrictGetSetpriority(pid_t target_pid) {
diff --git a/storage/browser/blob/blob_data_builder.cc b/storage/browser/blob/blob_data_builder.cc
index 6b62106..1397ced 100644
--- a/storage/browser/blob/blob_data_builder.cc
+++ b/storage/browser/blob/blob_data_builder.cc
@@ -18,6 +18,12 @@
 
 namespace storage {
 
+namespace {
+
+const static int kInvalidDiskCacheSideStreamIndex = -1;
+
+}  // namespace
+
 const char BlobDataBuilder::kAppendFutureFileTemporaryFileName[] =
     "kFakeFilenameToBeChangedByPopulateFutureFile";
 
@@ -184,7 +190,21 @@
   element->SetToDiskCacheEntryRange(
       0U, disk_cache_entry->GetDataSize(disk_cache_stream_index));
   items_.push_back(new BlobDataItem(std::move(element), data_handle,
-                                    disk_cache_entry, disk_cache_stream_index));
+                                    disk_cache_entry, disk_cache_stream_index,
+                                    kInvalidDiskCacheSideStreamIndex));
+}
+
+void BlobDataBuilder::AppendDiskCacheEntryWithSideData(
+    const scoped_refptr<DataHandle>& data_handle,
+    disk_cache::Entry* disk_cache_entry,
+    int disk_cache_stream_index,
+    int disk_cache_side_stream_index) {
+  std::unique_ptr<DataElement> element(new DataElement());
+  element->SetToDiskCacheEntryRange(
+      0U, disk_cache_entry->GetDataSize(disk_cache_stream_index));
+  items_.push_back(new BlobDataItem(std::move(element), data_handle,
+                                    disk_cache_entry, disk_cache_stream_index,
+                                    disk_cache_side_stream_index));
 }
 
 void BlobDataBuilder::Clear() {
diff --git a/storage/browser/blob/blob_data_builder.h b/storage/browser/blob/blob_data_builder.h
index 5600ca8..f304f446 100644
--- a/storage/browser/blob/blob_data_builder.h
+++ b/storage/browser/blob/blob_data_builder.h
@@ -106,6 +106,12 @@
   void AppendDiskCacheEntry(const scoped_refptr<DataHandle>& data_handle,
                             disk_cache::Entry* disk_cache_entry,
                             int disk_cache_stream_index);
+  // The content of the side data is accessible with BlobReader::ReadSideData().
+  void AppendDiskCacheEntryWithSideData(
+      const scoped_refptr<DataHandle>& data_handle,
+      disk_cache::Entry* disk_cache_entry,
+      int disk_cache_stream_index,
+      int disk_cache_side_stream_index);
 
   void set_content_type(const std::string& content_type) {
     content_type_ = content_type;
diff --git a/storage/browser/blob/blob_data_item.cc b/storage/browser/blob/blob_data_item.cc
index 0e44427..030b0d0 100644
--- a/storage/browser/blob/blob_data_item.cc
+++ b/storage/browser/blob/blob_data_item.cc
@@ -15,23 +15,27 @@
 BlobDataItem::BlobDataItem(std::unique_ptr<DataElement> item)
     : item_(std::move(item)),
       disk_cache_entry_(nullptr),
-      disk_cache_stream_index_(-1) {}
+      disk_cache_stream_index_(-1),
+      disk_cache_side_stream_index_(-1) {}
 
 BlobDataItem::BlobDataItem(std::unique_ptr<DataElement> item,
                            const scoped_refptr<DataHandle>& data_handle)
     : item_(std::move(item)),
       data_handle_(data_handle),
       disk_cache_entry_(nullptr),
-      disk_cache_stream_index_(-1) {}
+      disk_cache_stream_index_(-1),
+      disk_cache_side_stream_index_(-1) {}
 
 BlobDataItem::BlobDataItem(std::unique_ptr<DataElement> item,
                            const scoped_refptr<DataHandle>& data_handle,
                            disk_cache::Entry* entry,
-                           int disk_cache_stream_index)
+                           int disk_cache_stream_index,
+                           int disk_cache_side_stream_index)
     : item_(std::move(item)),
       data_handle_(data_handle),
       disk_cache_entry_(entry),
-      disk_cache_stream_index_(disk_cache_stream_index) {}
+      disk_cache_stream_index_(disk_cache_stream_index),
+      disk_cache_side_stream_index_(disk_cache_side_stream_index) {}
 
 BlobDataItem::~BlobDataItem() {}
 
@@ -47,6 +51,7 @@
 bool operator==(const BlobDataItem& a, const BlobDataItem& b) {
   return a.disk_cache_entry() == b.disk_cache_entry() &&
          a.disk_cache_stream_index() == b.disk_cache_stream_index() &&
+         a.disk_cache_side_stream_index() == b.disk_cache_side_stream_index() &&
          a.data_element() == b.data_element();
 }
 
diff --git a/storage/browser/blob/blob_data_item.h b/storage/browser/blob/blob_data_item.h
index 6212b7c5..a711a4c 100644
--- a/storage/browser/blob/blob_data_item.h
+++ b/storage/browser/blob/blob_data_item.h
@@ -59,6 +59,9 @@
 
   disk_cache::Entry* disk_cache_entry() const { return disk_cache_entry_; }
   int disk_cache_stream_index() const { return disk_cache_stream_index_; }
+  int disk_cache_side_stream_index() const {
+    return disk_cache_side_stream_index_;
+  }
 
  private:
   friend class BlobDataBuilder;
@@ -72,7 +75,8 @@
   BlobDataItem(std::unique_ptr<DataElement> item,
                const scoped_refptr<DataHandle>& data_handle,
                disk_cache::Entry* entry,
-               int disk_cache_stream_index_);
+               int disk_cache_stream_index,
+               int disk_cache_side_stream_index);
   virtual ~BlobDataItem();
 
   std::unique_ptr<DataElement> item_;
@@ -82,6 +86,7 @@
   // instance for disk cache entries during the lifetime of this BlobDataItem.
   disk_cache::Entry* disk_cache_entry_;
   int disk_cache_stream_index_;  // For TYPE_DISK_CACHE_ENTRY.
+  int disk_cache_side_stream_index_;  // For TYPE_DISK_CACHE_ENTRY.
 };
 
 STORAGE_EXPORT bool operator==(const BlobDataItem& a, const BlobDataItem& b);
diff --git a/storage/browser/blob/blob_reader.cc b/storage/browser/blob/blob_reader.cc
index 3e8ade6a..2eafdbc 100644
--- a/storage/browser/blob/blob_reader.cc
+++ b/storage/browser/blob/blob_reader.cc
@@ -95,6 +95,55 @@
   return CalculateSizeImpl(done);
 }
 
+bool BlobReader::has_side_data() const {
+  if (!blob_data_.get())
+    return false;
+  const auto& items = blob_data_->items();
+  if (items.size() != 1)
+    return false;
+  const BlobDataItem& item = *items.at(0);
+  if (item.type() != DataElement::TYPE_DISK_CACHE_ENTRY)
+    return false;
+  const int disk_cache_side_stream_index = item.disk_cache_side_stream_index();
+  if (disk_cache_side_stream_index < 0)
+    return false;
+  return item.disk_cache_entry()->GetDataSize(disk_cache_side_stream_index) > 0;
+}
+
+BlobReader::Status BlobReader::ReadSideData(const StatusCallback& done) {
+  if (!has_side_data())
+    return ReportError(net::ERR_FILE_NOT_FOUND);
+  const BlobDataItem* item = blob_data_->items()[0].get();
+  const int disk_cache_side_stream_index = item->disk_cache_side_stream_index();
+  const int side_data_size =
+      item->disk_cache_entry()->GetDataSize(disk_cache_side_stream_index);
+  side_data_ = new net::IOBufferWithSize(side_data_size);
+  net_error_ = net::OK;
+  const int result = item->disk_cache_entry()->ReadData(
+      disk_cache_side_stream_index, 0, side_data_.get(), side_data_size,
+      base::Bind(&BlobReader::DidReadDiskCacheEntrySideData,
+                 weak_factory_.GetWeakPtr(), done, side_data_size));
+  if (result >= 0) {
+    DCHECK_EQ(side_data_size, result);
+    return Status::DONE;
+  }
+  if (result == net::ERR_IO_PENDING)
+    return Status::IO_PENDING;
+  return ReportError(result);
+}
+
+void BlobReader::DidReadDiskCacheEntrySideData(const StatusCallback& done,
+                                               int expected_size,
+                                               int result) {
+  if (result >= 0) {
+    DCHECK_EQ(expected_size, result);
+    done.Run(Status::DONE);
+    return;
+  }
+  side_data_ = nullptr;
+  done.Run(ReportError(result));
+}
+
 BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) {
   if (!blob_handle_.get() || blob_handle_->IsBroken()) {
     return ReportError(net::ERR_FILE_NOT_FOUND);
diff --git a/storage/browser/blob/blob_reader.h b/storage/browser/blob/blob_reader.h
index 57943832..a3c7cfa 100644
--- a/storage/browser/blob/blob_reader.h
+++ b/storage/browser/blob/blob_reader.h
@@ -31,6 +31,7 @@
 namespace net {
 class DrainableIOBuffer;
 class IOBuffer;
+class IOBufferWithSize;
 }
 
 namespace storage {
@@ -65,6 +66,7 @@
         const base::Time& expected_modification_time) = 0;
   };
   enum class Status { NET_ERROR, IO_PENDING, DONE };
+  typedef base::Callback<void(Status)> StatusCallback;
   virtual ~BlobReader();
 
   // This calculates the total size of the blob, and initializes the reading
@@ -77,6 +79,25 @@
   //    total_size() value to query the blob size, as it's uint64_t.
   Status CalculateSize(const net::CompletionCallback& done);
 
+  // Returns true when the blob has side data. CalculateSize must be called
+  // beforehand. Currently side data is supported only for single DiskCache
+  // entry blob. So it returns false when the blob has more than single data
+  // item. This side data is used to pass the V8 code cache which is stored
+  // as a side stream in the CacheStorage to the renderer. (crbug.com/581613)
+  bool has_side_data() const;
+
+  // Reads the side data of the blob. CalculateSize must be called beforehand.
+  // * If the side data is read immediately, returns Status::DONE.
+  // * If an error happens or the blob doesn't have side data, returns
+  //   Status::NET_ERROR and the net error code is set.
+  // * If this function returns Status::IO_PENDING, the done callback will be
+  //   called with Status::DONE or Status::NET_ERROR.
+  // Currently side data is supported only for single DiskCache entry blob.
+  Status ReadSideData(const StatusCallback& done);
+
+  // Returns the side data which has been already read with ReadSideData().
+  net::IOBufferWithSize* side_data() const { return side_data_.get(); }
+
   // Used to set the read position.
   // * This should be called after CalculateSize and before Read.
   // * Range can only be set once.
@@ -159,6 +180,9 @@
   Status ReadDiskCacheEntryItem(const BlobDataItem& item, int bytes_to_read);
   void DidReadDiskCacheEntry(int result);
   void DidReadItem(int result);
+  void DidReadDiskCacheEntrySideData(const StatusCallback& done,
+                                     int expected_size,
+                                     int result);
   int ComputeBytesToRead() const;
   int BytesReadCompleted();
 
@@ -177,6 +201,7 @@
   std::unique_ptr<BlobDataSnapshot> blob_data_;
   std::unique_ptr<FileStreamReaderProvider> file_stream_provider_;
   scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
+  scoped_refptr<net::IOBufferWithSize> side_data_;
 
   int net_error_;
   bool item_list_populated_ = false;
diff --git a/storage/browser/blob/blob_storage_context.cc b/storage/browser/blob/blob_storage_context.cc
index 5beb1a52..d61390f6 100644
--- a/storage/browser/blob/blob_storage_context.cc
+++ b/storage/browser/blob/blob_storage_context.cc
@@ -439,7 +439,8 @@
             target_blob_uuid,
             new BlobDataItem(std::move(element), item.data_handle_,
                              item.disk_cache_entry(),
-                             item.disk_cache_stream_index())));
+                             item.disk_cache_stream_index(),
+                             item.disk_cache_side_stream_index())));
       } break;
       case DataElement::TYPE_BYTES_DESCRIPTION:
       case DataElement::TYPE_BLOB:
diff --git a/storage/browser/blob/blob_url_request_job.cc b/storage/browser/blob/blob_url_request_job.cc
index 58863d0..bdaff14 100644
--- a/storage/browser/blob/blob_url_request_job.cc
+++ b/storage/browser/blob/blob_url_request_job.cc
@@ -208,11 +208,30 @@
     blob_reader_->SetReadRange(byte_range_.first_byte_position(), length);
 
   net::HttpStatusCode status_code = net::HTTP_OK;
-  if (byte_range_set_ && byte_range_.IsValid())
+  if (byte_range_set_ && byte_range_.IsValid()) {
     status_code = net::HTTP_PARTIAL_CONTENT;
+  } else {
+    // TODO(horo): When the requester doesn't need the side data (ex:FileReader)
+    // we should skip reading the side data.
+    if (blob_reader_->has_side_data() &&
+        blob_reader_->ReadSideData(base::Bind(
+            &BlobURLRequestJob::DidReadMetadata, weak_factory_.GetWeakPtr())) ==
+            BlobReader::Status::IO_PENDING) {
+      return;
+    }
+  }
+
   HeadersCompleted(status_code);
 }
 
+void BlobURLRequestJob::DidReadMetadata(BlobReader::Status result) {
+  if (result != BlobReader::Status::DONE) {
+    NotifyFailure(blob_reader_->net_error());
+    return;
+  }
+  HeadersCompleted(net::HTTP_OK);
+}
+
 void BlobURLRequestJob::DidReadRawData(int result) {
   TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid",
                          blob_handle_ ? blob_handle_->uuid() : "NotFound");
@@ -294,6 +313,8 @@
 
   response_info_.reset(new net::HttpResponseInfo());
   response_info_->headers = headers;
+  if (blob_reader_)
+    response_info_->metadata = blob_reader_->side_data();
 
   NotifyHeadersComplete();
 }
diff --git a/storage/browser/blob/blob_url_request_job.h b/storage/browser/blob/blob_url_request_job.h
index 24621f5..1dadbd4f 100644
--- a/storage/browser/blob/blob_url_request_job.h
+++ b/storage/browser/blob/blob_url_request_job.h
@@ -16,6 +16,7 @@
 #include "net/http/http_byte_range.h"
 #include "net/http/http_status_code.h"
 #include "net/url_request/url_request_job.h"
+#include "storage/browser/blob/blob_reader.h"
 #include "storage/browser/storage_browser_export.h"
 
 namespace base {
@@ -30,7 +31,6 @@
 namespace storage {
 
 class BlobDataHandle;
-class BlobReader;
 class FileStreamReader;
 class FileSystemContext;
 
@@ -62,6 +62,7 @@
   // For preparing for read: get the size, apply the range and perform seek.
   void DidStart();
   void DidCalculateSize(int result);
+  void DidReadMetadata(BlobReader::Status result);
   void DidReadRawData(int result);
 
   void NotifyFailure(int);
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 5ed06ff..fff00bb 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1499,7 +1499,6 @@
 crbug.com/601166 [ Mac10.9 ]  fast/text/zero-font-size.html [ Failure ]
 crbug.com/601166 [ Mac10.9 ]  ietestcenter/css3/text/textshadow-003.htm [ Failure ]
 crbug.com/601166 [ Mac10.9 ]  ietestcenter/css3/text/textshadow-004.htm [ Failure ]
-crbug.com/601166 [ Mac10.9 ]  svg/transforms/animated-path-inside-transformed-html.xhtml [ Failure ]
 
 crbug.com/600261 imported/web-platform-tests/mediacapture-streams/GUM-deny.html [ Failure ]
 crbug.com/600261 imported/web-platform-tests/mediacapture-streams/MediaStream-MediaElement-srcObject.html [ Failure ]
@@ -2713,3 +2712,52 @@
 crbug.com/600248 imported/web-platform-tests/web-animations/animation/constructor.html [ Failure Timeout ]
 
 crbug.com/604642 [ Mac ]  fast/text/midword-break-after-breakable-char.html [ Failure ]
+crbug.com/605024 [ Mac ]  svg/transforms/animated-path-inside-transformed-html.xhtml [ Failure ]
+
+crbug.com/605047 [ Mac10.11 ]  fast/text/emphasis.html [ Failure ]
+crbug.com/605047 [ Mac10.11 ]  fast/text/international/complex-character-based-fallback.html [ Failure ]
+
+crbug.com/605059 [ Retina ] fast/text/international/bidi-neutral-directionality-paragraph-start.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/international/bidi-AN-after-empty-run.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/003.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/005.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/015.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/midword-break-before-surrogate-pair.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/basic/012.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/011.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/international/bidi-european-terminators.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/international/thai-baht-space.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/bidi-embedding-pop-and-push-same.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/international/thai-line-breaks.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/shadow-translucent-fill.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/capitalize-boundaries.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/008.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/027.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/016.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/024.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/002.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/atsui-kerning-and-ligatures.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/fake-italic.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/international/unicode-bidi-plaintext-in-textarea.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/international/bidi-override.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/line-initial-and-final-swashes.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/010.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/international/bold-bengali.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/shaping/shaping-selection-rect.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/007.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/complex-preferred-logical-widths.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/wbr.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/international/lang-glyph-cache-separation.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/basic/011.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/firstline/002.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/should-use-atsui.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/text-letter-spacing.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/aat-morx.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/international/rtl-white-space-pre-wrap.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/international/hebrew-vowels.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/006.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/caps-lock-indicator-enabled.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/018.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/004.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/whitespace/009.html [ Failure ]
+crbug.com/605059 [ Retina ] fast/text/international/rtl-negative-letter-spacing.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/fixed-element-escape-fixed-overflow-clip-expected.html b/third_party/WebKit/LayoutTests/compositing/overflow/fixed-element-escape-fixed-overflow-clip-expected.html
new file mode 100644
index 0000000..c9eef7d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/compositing/overflow/fixed-element-escape-fixed-overflow-clip-expected.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<style>
+#scroller {
+    position: fixed;
+    left: 0;
+    top: 0;
+    width: 100px;
+    height: 100px;
+    overflow: scroll;
+}
+
+#bloat {
+    height: 1000px;
+}
+
+#fixed {
+    position: fixed;
+    left: 200px;
+    top: 200px;
+    width: 100px;
+    height: 100px;
+    background: green;
+}
+</style>
+<div id="scroller">
+    <div id="bloat"></div>
+</div>
+<div id="fixed"></div>
+The test passes if a green box is visible on the screen. The purpose of this test is to verify fixed-position elements are not clipped by an ancestor fixed-position overflow clip.
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/fixed-element-escape-fixed-overflow-clip.html b/third_party/WebKit/LayoutTests/compositing/overflow/fixed-element-escape-fixed-overflow-clip.html
new file mode 100644
index 0000000..a56d32e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/compositing/overflow/fixed-element-escape-fixed-overflow-clip.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<style>
+#scroller {
+    position: fixed;
+    left: 0;
+    top: 0;
+    width: 100px;
+    height: 100px;
+    overflow: scroll;
+}
+
+#bloat {
+    height: 1000px;
+}
+
+#fixed {
+    position: fixed;
+    left: 200px;
+    top: 200px;
+    width: 100px;
+    height: 100px;
+    background: green;
+}
+</style>
+<div id="scroller">
+    <div id="bloat"></div>
+    <div id="fixed"></div>
+</div>
+The test passes if a green box is visible on the screen. The purpose of this test is to verify fixed-position elements are not clipped by an ancestor fixed-position overflow clip.
diff --git a/third_party/WebKit/LayoutTests/fast/hidpi/image-set-border-image-button-expected.html b/third_party/WebKit/LayoutTests/fast/hidpi/image-set-border-image-button-expected.html
new file mode 100644
index 0000000..2e69a096
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/hidpi/image-set-border-image-button-expected.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script src="resources/srcset-helper.js"></script>
+<style>
+div {
+    width: 102px;
+    height: 22px;
+    background: black;
+    border: 1px solid blue;
+}
+</style>
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/fast/hidpi/image-set-border-image-button.html b/third_party/WebKit/LayoutTests/fast/hidpi/image-set-border-image-button.html
new file mode 100644
index 0000000..3bf35e9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/hidpi/image-set-border-image-button.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>border-image with border-image-repeat in hidpi setting</title>
+<script src="resources/srcset-helper.js"></script>
+<!-- Mimicking hidpi border-image features from buttons in
+     ui/webui/resources/css/apps/common.css -->
+<style>
+div {
+    border-image-source: -webkit-image-set(
+        url(resources/black-blue-outline-6-px-square.png) 1x,
+        url(resources/black-blue-outline-12-px-square.png) 2x);
+    border-image-slice: 2 fill;
+    border-image-width: 2px;
+    border-image-repeat: repeat;
+    width: 100px;
+    height: 20px;
+    border-width: 2px;
+    border-style: solid;
+}
+</style>
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/fast/hidpi/resources/black-blue-outline-12-px-square.png b/third_party/WebKit/LayoutTests/fast/hidpi/resources/black-blue-outline-12-px-square.png
new file mode 100644
index 0000000..a8e5cd2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/hidpi/resources/black-blue-outline-12-px-square.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/hidpi/resources/black-blue-outline-6-px-square.png b/third_party/WebKit/LayoutTests/fast/hidpi/resources/black-blue-outline-6-px-square.png
new file mode 100644
index 0000000..2d52e73
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/hidpi/resources/black-blue-outline-6-px-square.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/resources/global-interface-listing-worker.js b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/resources/global-interface-listing-worker.js
index 3911fd0..dceb07a 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/resources/global-interface-listing-worker.js
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/resources/global-interface-listing-worker.js
@@ -108,9 +108,7 @@
       var proto_properties = new Set(Object.keys(object.prototype).concat(
                                      Object.keys(object.__proto__)));
       var property_names = Object.keys(object).filter(function(name) {
-        // TODO(johnme): Stop filtering out 'toString' once
-        //               https://crbug.com/547773 is fixed.
-        return !proto_properties.has(name) && name !== 'toString';
+        return !proto_properties.has(name);
       });
     } else {
       var property_names = Object.getOwnPropertyNames(object);
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
index cab88fa7..09c404d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
@@ -1,109 +1,109 @@
-CONSOLE MESSAGE: line 139: interface ByteLengthQueuingStrategy
-CONSOLE MESSAGE: line 139:     method constructor
-CONSOLE MESSAGE: line 139:     method size
-CONSOLE MESSAGE: line 139: interface CountQueuingStrategy
-CONSOLE MESSAGE: line 139:     method constructor
-CONSOLE MESSAGE: line 139:     method size
-CONSOLE MESSAGE: line 139: interface DataView
-CONSOLE MESSAGE: line 139:     getter buffer
-CONSOLE MESSAGE: line 139:     getter byteLength
-CONSOLE MESSAGE: line 139:     getter byteOffset
-CONSOLE MESSAGE: line 139:     method constructor
-CONSOLE MESSAGE: line 139:     method getFloat32
-CONSOLE MESSAGE: line 139:     method getFloat64
-CONSOLE MESSAGE: line 139:     method getInt16
-CONSOLE MESSAGE: line 139:     method getInt32
-CONSOLE MESSAGE: line 139:     method getInt8
-CONSOLE MESSAGE: line 139:     method getUint16
-CONSOLE MESSAGE: line 139:     method getUint32
-CONSOLE MESSAGE: line 139:     method getUint8
-CONSOLE MESSAGE: line 139:     method setFloat32
-CONSOLE MESSAGE: line 139:     method setFloat64
-CONSOLE MESSAGE: line 139:     method setInt16
-CONSOLE MESSAGE: line 139:     method setInt32
-CONSOLE MESSAGE: line 139:     method setInt8
-CONSOLE MESSAGE: line 139:     method setUint16
-CONSOLE MESSAGE: line 139:     method setUint32
-CONSOLE MESSAGE: line 139:     method setUint8
-CONSOLE MESSAGE: line 139: interface PaintRenderingContext2D
-CONSOLE MESSAGE: line 139:     getter currentTransform
-CONSOLE MESSAGE: line 139:     getter fillStyle
-CONSOLE MESSAGE: line 139:     getter globalAlpha
-CONSOLE MESSAGE: line 139:     getter globalCompositeOperation
-CONSOLE MESSAGE: line 139:     getter imageSmoothingEnabled
-CONSOLE MESSAGE: line 139:     getter imageSmoothingQuality
-CONSOLE MESSAGE: line 139:     getter lineCap
-CONSOLE MESSAGE: line 139:     getter lineDashOffset
-CONSOLE MESSAGE: line 139:     getter lineJoin
-CONSOLE MESSAGE: line 139:     getter lineWidth
-CONSOLE MESSAGE: line 139:     getter miterLimit
-CONSOLE MESSAGE: line 139:     getter shadowBlur
-CONSOLE MESSAGE: line 139:     getter shadowColor
-CONSOLE MESSAGE: line 139:     getter shadowOffsetX
-CONSOLE MESSAGE: line 139:     getter shadowOffsetY
-CONSOLE MESSAGE: line 139:     getter strokeStyle
-CONSOLE MESSAGE: line 139:     method arc
-CONSOLE MESSAGE: line 139:     method arcTo
-CONSOLE MESSAGE: line 139:     method beginPath
-CONSOLE MESSAGE: line 139:     method bezierCurveTo
-CONSOLE MESSAGE: line 139:     method clearRect
-CONSOLE MESSAGE: line 139:     method clip
-CONSOLE MESSAGE: line 139:     method closePath
-CONSOLE MESSAGE: line 139:     method constructor
-CONSOLE MESSAGE: line 139:     method createLinearGradient
-CONSOLE MESSAGE: line 139:     method createPattern
-CONSOLE MESSAGE: line 139:     method createRadialGradient
-CONSOLE MESSAGE: line 139:     method drawImage
-CONSOLE MESSAGE: line 139:     method ellipse
-CONSOLE MESSAGE: line 139:     method fill
-CONSOLE MESSAGE: line 139:     method fillRect
-CONSOLE MESSAGE: line 139:     method getLineDash
-CONSOLE MESSAGE: line 139:     method isPointInPath
-CONSOLE MESSAGE: line 139:     method isPointInStroke
-CONSOLE MESSAGE: line 139:     method lineTo
-CONSOLE MESSAGE: line 139:     method moveTo
-CONSOLE MESSAGE: line 139:     method quadraticCurveTo
-CONSOLE MESSAGE: line 139:     method rect
-CONSOLE MESSAGE: line 139:     method resetTransform
-CONSOLE MESSAGE: line 139:     method restore
-CONSOLE MESSAGE: line 139:     method rotate
-CONSOLE MESSAGE: line 139:     method save
-CONSOLE MESSAGE: line 139:     method scale
-CONSOLE MESSAGE: line 139:     method setLineDash
-CONSOLE MESSAGE: line 139:     method setTransform
-CONSOLE MESSAGE: line 139:     method stroke
-CONSOLE MESSAGE: line 139:     method strokeRect
-CONSOLE MESSAGE: line 139:     method transform
-CONSOLE MESSAGE: line 139:     method translate
-CONSOLE MESSAGE: line 139:     setter currentTransform
-CONSOLE MESSAGE: line 139:     setter fillStyle
-CONSOLE MESSAGE: line 139:     setter globalAlpha
-CONSOLE MESSAGE: line 139:     setter globalCompositeOperation
-CONSOLE MESSAGE: line 139:     setter imageSmoothingEnabled
-CONSOLE MESSAGE: line 139:     setter imageSmoothingQuality
-CONSOLE MESSAGE: line 139:     setter lineCap
-CONSOLE MESSAGE: line 139:     setter lineDashOffset
-CONSOLE MESSAGE: line 139:     setter lineJoin
-CONSOLE MESSAGE: line 139:     setter lineWidth
-CONSOLE MESSAGE: line 139:     setter miterLimit
-CONSOLE MESSAGE: line 139:     setter shadowBlur
-CONSOLE MESSAGE: line 139:     setter shadowColor
-CONSOLE MESSAGE: line 139:     setter shadowOffsetX
-CONSOLE MESSAGE: line 139:     setter shadowOffsetY
-CONSOLE MESSAGE: line 139:     setter strokeStyle
-CONSOLE MESSAGE: line 139: interface PaintWorkletGlobalScope : WorkletGlobalScope
-CONSOLE MESSAGE: line 139:     method constructor
-CONSOLE MESSAGE: line 139: interface ReadableStream
-CONSOLE MESSAGE: line 139:     getter locked
-CONSOLE MESSAGE: line 139:     method cancel
-CONSOLE MESSAGE: line 139:     method constructor
-CONSOLE MESSAGE: line 139:     method getReader
-CONSOLE MESSAGE: line 139:     method tee
-CONSOLE MESSAGE: line 139: interface WorkletGlobalScope
-CONSOLE MESSAGE: line 139:     getter console
-CONSOLE MESSAGE: line 139:     method constructor
-CONSOLE MESSAGE: line 139:     setter console
-CONSOLE MESSAGE: line 139: global object
-CONSOLE MESSAGE: line 139:     method gc
-CONSOLE MESSAGE: line 139:     method registerPaint
+CONSOLE MESSAGE: line 137: interface ByteLengthQueuingStrategy
+CONSOLE MESSAGE: line 137:     method constructor
+CONSOLE MESSAGE: line 137:     method size
+CONSOLE MESSAGE: line 137: interface CountQueuingStrategy
+CONSOLE MESSAGE: line 137:     method constructor
+CONSOLE MESSAGE: line 137:     method size
+CONSOLE MESSAGE: line 137: interface DataView
+CONSOLE MESSAGE: line 137:     getter buffer
+CONSOLE MESSAGE: line 137:     getter byteLength
+CONSOLE MESSAGE: line 137:     getter byteOffset
+CONSOLE MESSAGE: line 137:     method constructor
+CONSOLE MESSAGE: line 137:     method getFloat32
+CONSOLE MESSAGE: line 137:     method getFloat64
+CONSOLE MESSAGE: line 137:     method getInt16
+CONSOLE MESSAGE: line 137:     method getInt32
+CONSOLE MESSAGE: line 137:     method getInt8
+CONSOLE MESSAGE: line 137:     method getUint16
+CONSOLE MESSAGE: line 137:     method getUint32
+CONSOLE MESSAGE: line 137:     method getUint8
+CONSOLE MESSAGE: line 137:     method setFloat32
+CONSOLE MESSAGE: line 137:     method setFloat64
+CONSOLE MESSAGE: line 137:     method setInt16
+CONSOLE MESSAGE: line 137:     method setInt32
+CONSOLE MESSAGE: line 137:     method setInt8
+CONSOLE MESSAGE: line 137:     method setUint16
+CONSOLE MESSAGE: line 137:     method setUint32
+CONSOLE MESSAGE: line 137:     method setUint8
+CONSOLE MESSAGE: line 137: interface PaintRenderingContext2D
+CONSOLE MESSAGE: line 137:     getter currentTransform
+CONSOLE MESSAGE: line 137:     getter fillStyle
+CONSOLE MESSAGE: line 137:     getter globalAlpha
+CONSOLE MESSAGE: line 137:     getter globalCompositeOperation
+CONSOLE MESSAGE: line 137:     getter imageSmoothingEnabled
+CONSOLE MESSAGE: line 137:     getter imageSmoothingQuality
+CONSOLE MESSAGE: line 137:     getter lineCap
+CONSOLE MESSAGE: line 137:     getter lineDashOffset
+CONSOLE MESSAGE: line 137:     getter lineJoin
+CONSOLE MESSAGE: line 137:     getter lineWidth
+CONSOLE MESSAGE: line 137:     getter miterLimit
+CONSOLE MESSAGE: line 137:     getter shadowBlur
+CONSOLE MESSAGE: line 137:     getter shadowColor
+CONSOLE MESSAGE: line 137:     getter shadowOffsetX
+CONSOLE MESSAGE: line 137:     getter shadowOffsetY
+CONSOLE MESSAGE: line 137:     getter strokeStyle
+CONSOLE MESSAGE: line 137:     method arc
+CONSOLE MESSAGE: line 137:     method arcTo
+CONSOLE MESSAGE: line 137:     method beginPath
+CONSOLE MESSAGE: line 137:     method bezierCurveTo
+CONSOLE MESSAGE: line 137:     method clearRect
+CONSOLE MESSAGE: line 137:     method clip
+CONSOLE MESSAGE: line 137:     method closePath
+CONSOLE MESSAGE: line 137:     method constructor
+CONSOLE MESSAGE: line 137:     method createLinearGradient
+CONSOLE MESSAGE: line 137:     method createPattern
+CONSOLE MESSAGE: line 137:     method createRadialGradient
+CONSOLE MESSAGE: line 137:     method drawImage
+CONSOLE MESSAGE: line 137:     method ellipse
+CONSOLE MESSAGE: line 137:     method fill
+CONSOLE MESSAGE: line 137:     method fillRect
+CONSOLE MESSAGE: line 137:     method getLineDash
+CONSOLE MESSAGE: line 137:     method isPointInPath
+CONSOLE MESSAGE: line 137:     method isPointInStroke
+CONSOLE MESSAGE: line 137:     method lineTo
+CONSOLE MESSAGE: line 137:     method moveTo
+CONSOLE MESSAGE: line 137:     method quadraticCurveTo
+CONSOLE MESSAGE: line 137:     method rect
+CONSOLE MESSAGE: line 137:     method resetTransform
+CONSOLE MESSAGE: line 137:     method restore
+CONSOLE MESSAGE: line 137:     method rotate
+CONSOLE MESSAGE: line 137:     method save
+CONSOLE MESSAGE: line 137:     method scale
+CONSOLE MESSAGE: line 137:     method setLineDash
+CONSOLE MESSAGE: line 137:     method setTransform
+CONSOLE MESSAGE: line 137:     method stroke
+CONSOLE MESSAGE: line 137:     method strokeRect
+CONSOLE MESSAGE: line 137:     method transform
+CONSOLE MESSAGE: line 137:     method translate
+CONSOLE MESSAGE: line 137:     setter currentTransform
+CONSOLE MESSAGE: line 137:     setter fillStyle
+CONSOLE MESSAGE: line 137:     setter globalAlpha
+CONSOLE MESSAGE: line 137:     setter globalCompositeOperation
+CONSOLE MESSAGE: line 137:     setter imageSmoothingEnabled
+CONSOLE MESSAGE: line 137:     setter imageSmoothingQuality
+CONSOLE MESSAGE: line 137:     setter lineCap
+CONSOLE MESSAGE: line 137:     setter lineDashOffset
+CONSOLE MESSAGE: line 137:     setter lineJoin
+CONSOLE MESSAGE: line 137:     setter lineWidth
+CONSOLE MESSAGE: line 137:     setter miterLimit
+CONSOLE MESSAGE: line 137:     setter shadowBlur
+CONSOLE MESSAGE: line 137:     setter shadowColor
+CONSOLE MESSAGE: line 137:     setter shadowOffsetX
+CONSOLE MESSAGE: line 137:     setter shadowOffsetY
+CONSOLE MESSAGE: line 137:     setter strokeStyle
+CONSOLE MESSAGE: line 137: interface PaintWorkletGlobalScope : WorkletGlobalScope
+CONSOLE MESSAGE: line 137:     method constructor
+CONSOLE MESSAGE: line 137: interface ReadableStream
+CONSOLE MESSAGE: line 137:     getter locked
+CONSOLE MESSAGE: line 137:     method cancel
+CONSOLE MESSAGE: line 137:     method constructor
+CONSOLE MESSAGE: line 137:     method getReader
+CONSOLE MESSAGE: line 137:     method tee
+CONSOLE MESSAGE: line 137: interface WorkletGlobalScope
+CONSOLE MESSAGE: line 137:     getter console
+CONSOLE MESSAGE: line 137:     method constructor
+CONSOLE MESSAGE: line 137:     setter console
+CONSOLE MESSAGE: line 137: global object
+CONSOLE MESSAGE: line 137:     method gc
+CONSOLE MESSAGE: line 137:     method registerPaint
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/resources/global-interface-listing-worklet.js b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/resources/global-interface-listing-worklet.js
index bbcea8d..2c12314 100644
--- a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/resources/global-interface-listing-worklet.js
+++ b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/resources/global-interface-listing-worklet.js
@@ -108,9 +108,7 @@
       var proto_properties = new Set(Object.keys(object.prototype).concat(
                                      Object.keys(object.__proto__)));
       var property_names = Object.keys(object).filter(function(name) {
-        // TODO(johnme): Stop filtering out 'toString' once
-        //               https://crbug.com/547773 is fixed.
-        return !proto_properties.has(name) && name !== 'toString';
+        return !proto_properties.has(name);
       });
     } else {
       var property_names = Object.getOwnPropertyNames(object);
diff --git a/third_party/WebKit/LayoutTests/webexposed/resources/global-interface-listing.js b/third_party/WebKit/LayoutTests/webexposed/resources/global-interface-listing.js
index a789fe2..5ff26530 100644
--- a/third_party/WebKit/LayoutTests/webexposed/resources/global-interface-listing.js
+++ b/third_party/WebKit/LayoutTests/webexposed/resources/global-interface-listing.js
@@ -144,9 +144,7 @@
        return propertyKeys = Object.keys(object).
            concat(ownEnumerableSymbols(object)).
            filter(function(name) {
-                // TODO(johnme): Stop filtering out 'toString' once
-                //               https://crbug.com/547773 is fixed.
-               return !protoProperties.has(name) && name !== 'toString';
+               return !protoProperties.has(name);
            });
    }
    return Object.getOwnPropertyNames(object).concat(Object.getOwnPropertySymbols(object));
diff --git a/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp b/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp
index 8d4873a..b15b6f1a 100644
--- a/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp
@@ -100,7 +100,7 @@
 bool BindingSecurity::shouldAllowAccessTo(v8::Isolate* isolate, const LocalDOMWindow* accessingWindow, const EventTarget* target, ExceptionState& exceptionState)
 {
     ASSERT(target);
-    const DOMWindow* window = target->toDOMWindow();
+    const DOMWindow* window = target->toLocalDOMWindow();
     if (!window) {
         // We only need to check the access to Window objects which are
         // cross-origin accessible.  If it's not a Window, the object's
diff --git a/third_party/WebKit/Source/bindings/scripts/interface_dependency_resolver.py b/third_party/WebKit/Source/bindings/scripts/interface_dependency_resolver.py
index 1922008..fe49fb1 100644
--- a/third_party/WebKit/Source/bindings/scripts/interface_dependency_resolver.py
+++ b/third_party/WebKit/Source/bindings/scripts/interface_dependency_resolver.py
@@ -253,17 +253,25 @@
     interface post-merging).
 
     The data storing consists of:
-    * applying certain extended attributes from the dependency interface
-      to its members
+    * moving certain extended attributes from the dependency interface
+      to its members (deleting the extended attribute from the interface)
     * storing the C++ class of the implementation in an internal
       extended attribute of each member, [PartialInterfaceImplementedAs]
 
     No return: modifies dependency_interface in place.
     """
-    merged_extended_attributes = dict(
-        (key, value)
-        for key, value in dependency_interface.extended_attributes.iteritems()
-        if key in DEPENDENCY_EXTENDED_ATTRIBUTES)
+    merged_extended_attributes = {}
+    for key in DEPENDENCY_EXTENDED_ATTRIBUTES:
+        value = dependency_interface.extended_attributes.get(key)
+        if not value:
+            continue
+
+        merged_extended_attributes[key] = value
+        # Remove the merged attributes from the original dependency interface.
+        # This ensures that if other dependency interfaces are merged onto this
+        # one, its extended_attributes do not leak through
+        # (https://crbug.com/603782).
+        del dependency_interface.extended_attributes[key]
 
     # A partial interface's members are implemented as static member functions
     # in a separate C++ class. This class name is stored in
@@ -291,7 +299,7 @@
     if (dependency_interface.is_partial or
         'LegacyTreatAsPartialInterface' in dependency_interface.extended_attributes):
         merged_extended_attributes['PartialInterfaceImplementedAs'] = (
-            dependency_interface.extended_attributes.get(
+            dependency_interface.extended_attributes.pop(
                 'ImplementedAs', dependency_interface_basename))
 
     def update_attributes(attributes, extras):
diff --git a/third_party/WebKit/Source/bindings/templates/methods.cpp b/third_party/WebKit/Source/bindings/templates/methods.cpp
index cac64f07..bb515be 100644
--- a/third_party/WebKit/Source/bindings/templates/methods.cpp
+++ b/third_party/WebKit/Source/bindings/templates/methods.cpp
@@ -31,7 +31,7 @@
     // prior to the call to BindingSecurity::shouldAllowAccessTo increases 30%
     // of speed performance on Android Nexus 7 as of Dec 2016.  ALWAYS_INLINE
     // didn't work in this case.
-    if (LocalDOMWindow* window = impl->toDOMWindow()) {
+    if (LocalDOMWindow* window = impl->toLocalDOMWindow()) {
         if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), window, exceptionState)) {
             {% if not method.returns_promise %}
             exceptionState.throwIfNeeded();
diff --git a/third_party/WebKit/Source/bindings/tests/idls/modules/TestInterface2Partial.idl b/third_party/WebKit/Source/bindings/tests/idls/modules/TestInterface2Partial.idl
new file mode 100644
index 0000000..dd84fb4
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/tests/idls/modules/TestInterface2Partial.idl
@@ -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.
+
+// Regression test for https://crbug.com/603782: if the main interface is
+// declared in 'core', the alphabetically first partial interface in 'modules'
+// with a RuntimeEnabled will leak onto all of the other partial interfaces in
+// 'modules' that do not have an extended attributes section (i.e.,
+// TestInterface2Partial2.idl).
+//
+// This test ensures that TestInterface2Partial2 is NOT conditional on the
+// Interface2PartialFeatureName runtime flag.
+[
+    RuntimeEnabled=Interface2PartialFeatureName,
+]
+partial interface TestInterface2 {
+    void voidMethodPartial1(DOMString value);
+};
diff --git a/third_party/WebKit/Source/bindings/tests/idls/modules/TestInterface2Partial2.idl b/third_party/WebKit/Source/bindings/tests/idls/modules/TestInterface2Partial2.idl
new file mode 100644
index 0000000..d0a90575
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/tests/idls/modules/TestInterface2Partial2.idl
@@ -0,0 +1,10 @@
+// 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.
+
+// Regression test for https://crbug.com/603782: see note in
+// TestInterface2Partial.idl. This test only works if there is *no*
+// RuntimeEnabled condition for this partial interface.
+partial interface TestInterface2 {
+    void voidMethodPartial2(DOMString value);
+};
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
index 9cb5486..c57f899d 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
@@ -29,7 +29,7 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wglobal-constructors"
 #endif
-const WrapperTypeInfo V8TestInterface2::wrapperTypeInfo = { gin::kEmbedderBlink, V8TestInterface2::domTemplate, V8TestInterface2::trace, V8TestInterface2::toActiveScriptWrappable, V8TestInterface2::visitDOMWrapper, V8TestInterface2::preparePrototypeAndInterfaceObject, V8TestInterface2::installConditionallyEnabledProperties, "TestInterface2", 0, WrapperTypeInfo::WrapperTypeObjectPrototype, WrapperTypeInfo::ObjectClassId, WrapperTypeInfo::NotInheritFromEventTarget, WrapperTypeInfo::Dependent };
+WrapperTypeInfo V8TestInterface2::wrapperTypeInfo = { gin::kEmbedderBlink, V8TestInterface2::domTemplate, V8TestInterface2::trace, V8TestInterface2::toActiveScriptWrappable, V8TestInterface2::visitDOMWrapper, V8TestInterface2::preparePrototypeAndInterfaceObject, V8TestInterface2::installConditionallyEnabledProperties, "TestInterface2", 0, WrapperTypeInfo::WrapperTypeObjectPrototype, WrapperTypeInfo::ObjectClassId, WrapperTypeInfo::NotInheritFromEventTarget, WrapperTypeInfo::Dependent };
 #if defined(COMPONENT_BUILD) && defined(WIN32) && COMPILER(CLANG)
 #pragma clang diagnostic pop
 #endif
@@ -596,7 +596,7 @@
     TestInterface2V8Internal::constructor(info);
 }
 
-static void installV8TestInterface2Template(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate)
+void V8TestInterface2::installV8TestInterface2Template(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate)
 {
     // Initialize the interface object's template.
     V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterface2::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestInterface2::internalFieldCount);
@@ -630,7 +630,7 @@
 
 v8::Local<v8::FunctionTemplate> V8TestInterface2::domTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world)
 {
-    return V8DOMConfiguration::domClassTemplate(isolate, world, const_cast<WrapperTypeInfo*>(&wrapperTypeInfo), installV8TestInterface2Template);
+    return V8DOMConfiguration::domClassTemplate(isolate, world, const_cast<WrapperTypeInfo*>(&wrapperTypeInfo), V8TestInterface2::installV8TestInterface2TemplateFunction);
 }
 
 bool V8TestInterface2::hasInstance(v8::Local<v8::Value> v8Value, v8::Isolate* isolate)
@@ -653,4 +653,13 @@
     return toImpl(wrapper);
 }
 
+InstallTemplateFunction V8TestInterface2::installV8TestInterface2TemplateFunction = (InstallTemplateFunction)&V8TestInterface2::installV8TestInterface2Template;
+
+void V8TestInterface2::updateWrapperTypeInfo(InstallTemplateFunction installTemplateFunction, PreparePrototypeAndInterfaceObjectFunction preparePrototypeAndInterfaceObjectFunction)
+{
+    V8TestInterface2::installV8TestInterface2TemplateFunction = installTemplateFunction;
+    if (preparePrototypeAndInterfaceObjectFunction)
+        V8TestInterface2::wrapperTypeInfo.preparePrototypeAndInterfaceObjectFunction = preparePrototypeAndInterfaceObjectFunction;
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h
index c6556237..60d075d 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h
@@ -29,7 +29,7 @@
         return toScriptWrappable(object)->toImpl<TestInterface2>();
     }
     CORE_EXPORT static TestInterface2* toImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
-    CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
+    CORE_EXPORT static WrapperTypeInfo wrapperTypeInfo;
     template<typename VisitorDispatcher>
     static void trace(VisitorDispatcher visitor, ScriptWrappable* scriptWrappable)
     {
@@ -41,6 +41,11 @@
     static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + 0;
     static void installConditionallyEnabledProperties(v8::Local<v8::Object>, v8::Isolate*) { }
     static void preparePrototypeAndInterfaceObject(v8::Local<v8::Context>, const DOMWrapperWorld&, v8::Local<v8::Object> prototypeObject, v8::Local<v8::Function> interfaceObject, v8::Local<v8::FunctionTemplate> interfaceTemplate) { }
+    CORE_EXPORT static void updateWrapperTypeInfo(InstallTemplateFunction, PreparePrototypeAndInterfaceObjectFunction);
+    CORE_EXPORT static void installV8TestInterface2Template(v8::Isolate*, const DOMWrapperWorld&, v8::Local<v8::FunctionTemplate> interfaceTemplate);
+
+private:
+    static InstallTemplateFunction installV8TestInterface2TemplateFunction;
 };
 
 template <>
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.cpp
new file mode 100644
index 0000000..3ecaefd6
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.cpp
@@ -0,0 +1,106 @@
+// 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.
+
+// This file has been auto-generated by code_generator_v8.py. DO NOT MODIFY!
+
+#include "V8TestInterface2Partial.h"
+
+#include "bindings/core/v8/ExceptionState.h"
+#include "bindings/core/v8/V8DOMConfiguration.h"
+#include "bindings/core/v8/V8GCController.h"
+#include "bindings/core/v8/V8ObjectConstructor.h"
+#include "bindings/core/v8/V8TestInterface2.h"
+#include "bindings/tests/idls/modules/TestInterface2Partial.h"
+#include "bindings/tests/idls/modules/TestInterface2Partial2.h"
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "wtf/GetPtr.h"
+#include "wtf/RefPtr.h"
+
+namespace blink {
+
+namespace TestInterface2PartialV8Internal {
+
+static void voidMethodPartial1Method(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+    if (UNLIKELY(info.Length() < 1)) {
+        V8ThrowException::throwException(createMinimumArityTypeErrorForMethod(info.GetIsolate(), "voidMethodPartial1", "TestInterface2", 1, info.Length()), info.GetIsolate());
+        return;
+    }
+    TestInterface2* impl = V8TestInterface2::toImpl(info.Holder());
+    V8StringResource<> value;
+    {
+        value = info[0];
+        if (!value.prepare())
+            return;
+    }
+    TestInterface2Partial::voidMethodPartial1(*impl, value);
+}
+
+static void voidMethodPartial1MethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+    TestInterface2PartialV8Internal::voidMethodPartial1Method(info);
+}
+
+static void voidMethodPartial2Method(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+    if (UNLIKELY(info.Length() < 1)) {
+        V8ThrowException::throwException(createMinimumArityTypeErrorForMethod(info.GetIsolate(), "voidMethodPartial2", "TestInterface2", 1, info.Length()), info.GetIsolate());
+        return;
+    }
+    TestInterface2* impl = V8TestInterface2::toImpl(info.Holder());
+    V8StringResource<> value;
+    {
+        value = info[0];
+        if (!value.prepare())
+            return;
+    }
+    TestInterface2Partial2::voidMethodPartial2(*impl, value);
+}
+
+static void voidMethodPartial2MethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+    TestInterface2PartialV8Internal::voidMethodPartial2Method(info);
+}
+
+} // namespace TestInterface2PartialV8Internal
+
+const V8DOMConfiguration::MethodConfiguration V8TestInterface2Methods[] = {
+    {"voidMethodPartial2", TestInterface2PartialV8Internal::voidMethodPartial2MethodCallback, 0, 1, v8::None, V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype},
+};
+
+void V8TestInterface2Partial::installV8TestInterface2Template(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate)
+{
+    // Initialize the interface object's template.
+    V8TestInterface2::installV8TestInterface2Template(isolate, world, interfaceTemplate);
+    v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
+    ALLOW_UNUSED_LOCAL(signature);
+    v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
+    ALLOW_UNUSED_LOCAL(instanceTemplate);
+    v8::Local<v8::ObjectTemplate> prototypeTemplate = interfaceTemplate->PrototypeTemplate();
+    ALLOW_UNUSED_LOCAL(prototypeTemplate);
+    // Register DOM constants, attributes and operations.
+    V8DOMConfiguration::installMethods(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, V8TestInterface2Methods, WTF_ARRAY_LENGTH(V8TestInterface2Methods));
+
+    if (RuntimeEnabledFeatures::interface2PartialFeatureNameEnabled()) {
+        const V8DOMConfiguration::MethodConfiguration voidMethodPartial1MethodConfiguration = {"voidMethodPartial1", TestInterface2PartialV8Internal::voidMethodPartial1MethodCallback, 0, 1, v8::None, V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype};
+        V8DOMConfiguration::installMethod(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, voidMethodPartial1MethodConfiguration);
+    }
+}
+
+void V8TestInterface2Partial::preparePrototypeAndInterfaceObject(v8::Local<v8::Context> context, const DOMWrapperWorld& world, v8::Local<v8::Object> prototypeObject, v8::Local<v8::Function> interfaceObject, v8::Local<v8::FunctionTemplate> interfaceTemplate)
+{
+    V8TestInterface2::preparePrototypeAndInterfaceObject(context, world, prototypeObject, interfaceObject, interfaceTemplate);
+}
+
+void V8TestInterface2Partial::initialize()
+{
+    // Should be invoked from ModulesInitializer.
+    V8TestInterface2::updateWrapperTypeInfo(
+        &V8TestInterface2Partial::installV8TestInterface2Template,
+        &V8TestInterface2Partial::preparePrototypeAndInterfaceObject);
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.h b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.h
new file mode 100644
index 0000000..c2ad05a
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.h
@@ -0,0 +1,29 @@
+// 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.
+
+// This file has been auto-generated by code_generator_v8.py. DO NOT MODIFY!
+
+#ifndef V8TestInterface2Partial_h
+#define V8TestInterface2Partial_h
+
+#include "bindings/core/v8/ScriptWrappable.h"
+#include "bindings/core/v8/ToV8.h"
+#include "bindings/core/v8/V8Binding.h"
+#include "bindings/core/v8/V8DOMWrapper.h"
+#include "bindings/core/v8/WrapperTypeInfo.h"
+#include "bindings/tests/idls/core/TestInterface2.h"
+#include "platform/heap/Handle.h"
+
+namespace blink {
+
+class V8TestInterface2Partial {
+    STATIC_ONLY(V8TestInterface2Partial);
+public:
+    static void initialize();
+    static void preparePrototypeAndInterfaceObject(v8::Local<v8::Context>, const DOMWrapperWorld&, v8::Local<v8::Object>, v8::Local<v8::Function>, v8::Local<v8::FunctionTemplate>);
+private:
+    static void installV8TestInterface2Template(v8::Isolate*, const DOMWrapperWorld&, v8::Local<v8::FunctionTemplate> interfaceTemplate);
+};
+}
+#endif // V8TestInterface2Partial_h
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index 5183381..a14c543d 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -5378,7 +5378,7 @@
     // http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/DocumentAdditionsReference/DocumentAdditions/DocumentAdditions.html
     // when this method should throw and nor is it by inspection of iOS behavior. It would be nice to verify any cases where it throws under iOS
     // and implement them here. See https://bugs.webkit.org/show_bug.cgi?id=47819
-    LocalFrame* frame = window && window->isLocalDOMWindow() ? toLocalDOMWindow(window)->frame() : this->frame();
+    LocalFrame* frame = window && window->isLocalDOMWindow() ? blink::toLocalDOMWindow(window)->frame() : this->frame();
     return Touch::create(frame, target, identifier, FloatPoint(screenX, screenY), FloatPoint(pageX, pageY), FloatSize(radiusX, radiusY), rotationAngle, force, String());
 }
 
diff --git a/third_party/WebKit/Source/core/dom/Element.h b/third_party/WebKit/Source/core/dom/Element.h
index dfa90ec..efa40dbb 100644
--- a/third_party/WebKit/Source/core/dom/Element.h
+++ b/third_party/WebKit/Source/core/dom/Element.h
@@ -484,11 +484,9 @@
 
     DOMStringMap& dataset();
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
     virtual bool isDateTimeEditElement() const { return false; }
     virtual bool isDateTimeFieldElement() const { return false; }
     virtual bool isPickerIndicatorElement() const { return false; }
-#endif
 
     virtual bool isFormControlElement() const { return false; }
     virtual bool isSpinButtonElement() const { return false; }
diff --git a/third_party/WebKit/Source/core/dom/ScriptedAnimationController.cpp b/third_party/WebKit/Source/core/dom/ScriptedAnimationController.cpp
index 4fd5de5..fdf4df6 100644
--- a/third_party/WebKit/Source/core/dom/ScriptedAnimationController.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptedAnimationController.cpp
@@ -117,7 +117,7 @@
         // special casting window.
         // FIXME: We should not fire events for nodes that are no longer in the tree.
         InspectorInstrumentation::AsyncTask asyncTask(eventTarget->getExecutionContext(), events[i]);
-        if (LocalDOMWindow* window = eventTarget->toDOMWindow())
+        if (LocalDOMWindow* window = eventTarget->toLocalDOMWindow())
             window->dispatchEvent(events[i], nullptr);
         else
             eventTarget->dispatchEvent(events[i]);
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp b/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp
index e16b67f..27388b1 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp
@@ -542,6 +542,15 @@
     EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 0));
     EXPECT_EQ(5, nextGraphemeBoundaryOf(node, 4));
 
+    // Not only Glue_After_ZWJ or EBG but also other emoji shouldn't break
+    // before ZWJ.
+    // U+1F5FA(WORLD MAP) doesn't have either Glue_After_Zwj or EBG but has
+    // Emoji property.
+    setBodyContent("<p id='target'>&#x200D;&#x1F5FA;</p>");
+    node = document().getElementById("target")->firstChild();
+    EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 3));
+    EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 0));
+
     // GB999: Otherwise break everywhere.
     // Breaks between Hangul syllable except for GB6, GB7, GB8.
     setBodyContent("<p id='target'>" + L + T + "</p>");
@@ -618,9 +627,9 @@
 
     // For GB11, if trailing character is not Glue_After_Zwj or EBG, break happens after ZWJ.
     // U+1F5FA(WORLD MAP) doesn't have either Glue_After_Zwj or EBG.
-    setBodyContent("<p id='target'>&#x200D;&#x1F5FA;</p>");
+    setBodyContent("<p id='target'>&#x200D;a</p>");
     node = document().getElementById("target")->firstChild();
-    EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3));
+    EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2));
     EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0));
 }
 
diff --git a/third_party/WebKit/Source/core/editing/state_machines/BackspaceStateMachine.cpp b/third_party/WebKit/Source/core/editing/state_machines/BackspaceStateMachine.cpp
index 3ea60fb..0f0a262 100644
--- a/third_party/WebKit/Source/core/editing/state_machines/BackspaceStateMachine.cpp
+++ b/third_party/WebKit/Source/core/editing/state_machines/BackspaceStateMachine.cpp
@@ -11,23 +11,6 @@
 
 namespace blink {
 
-namespace {
-
-// Returns true if the code point can be a part of ZWJ sequence.
-bool isZwjEmoji(uint32_t codePoint)
-{
-    return codePoint == WTF::Unicode::boyCharacter
-        || codePoint == WTF::Unicode::eyeCharacter
-        || codePoint == WTF::Unicode::girlCharacter
-        || codePoint == WTF::Unicode::heavyBlackHeartCharacter
-        || codePoint == WTF::Unicode::kissMarkCharacter
-        || codePoint == WTF::Unicode::leftSpeechBubbleCharacter
-        || codePoint == WTF::Unicode::manCharacter
-        || codePoint == WTF::Unicode::womanCharacter;
-}
-
-} // namespace
-
 #define FOR_EACH_BACKSPACE_STATE_MACHINE_STATE(V)                          \
     /* Initial state */                                                    \
     V(Start)                                                               \
@@ -118,12 +101,12 @@
             return moveToNextState(BackspaceState::BeforeLF);
         if (u_hasBinaryProperty(codePoint, UCHAR_VARIATION_SELECTOR))
             return moveToNextState(BackspaceState::BeforeVS);
-        if (isZwjEmoji(codePoint))
-            return moveToNextState(BackspaceState::BeforeZWJEmoji);
         if (Character::isRegionalIndicator(codePoint))
             return moveToNextState(BackspaceState::OddNumberedRIS);
         if (Character::isModifier(codePoint))
             return moveToNextState(BackspaceState::BeforeEmojiModifier);
+        if (Character::isEmoji(codePoint))
+            return moveToNextState(BackspaceState::BeforeZWJEmoji);
         if (codePoint == combiningEnclosingKeycapCharacter)
             return moveToNextState(BackspaceState::BeforeKeycap);
         return finish();
@@ -166,7 +149,7 @@
         }
         return finish();
     case BackspaceState::BeforeVS:
-        if (isZwjEmoji(codePoint)) {
+        if (Character::isEmoji(codePoint)) {
             m_codeUnitsToBeDeleted += U16_LENGTH(codePoint);
             return moveToNextState(BackspaceState::BeforeZWJEmoji);
         }
@@ -178,7 +161,7 @@
         return codePoint == zeroWidthJoinerCharacter ?
             moveToNextState(BackspaceState::BeforeZWJ) : finish();
     case BackspaceState::BeforeZWJ:
-        if (isZwjEmoji(codePoint)) {
+        if (Character::isEmoji(codePoint)) {
             m_codeUnitsToBeDeleted += U16_LENGTH(codePoint) + 1; // +1 for ZWJ
             return moveToNextState(BackspaceState::BeforeZWJEmoji);
         }
@@ -189,7 +172,7 @@
         }
         return finish();
     case BackspaceState::BeforeVSAndZWJ:
-        if (!isZwjEmoji(codePoint))
+        if (!Character::isEmoji(codePoint))
             return finish();
 
         DCHECK_GT(m_lastSeenVSCodeUnits, 0);
diff --git a/third_party/WebKit/Source/core/editing/state_machines/BackspaceStateMachineTest.cpp b/third_party/WebKit/Source/core/editing/state_machines/BackspaceStateMachineTest.cpp
index 16d8f0c..712dd56 100644
--- a/third_party/WebKit/Source/core/editing/state_machines/BackspaceStateMachineTest.cpp
+++ b/third_party/WebKit/Source/core/editing/state_machines/BackspaceStateMachineTest.cpp
@@ -49,9 +49,9 @@
 {
     BackspaceStateMachine machine;
 
-    // U+1F5FA(WORLD MAP) is \uD83D\uDDFA in UTF-16.
-    const UChar leadSurrogate = 0xD83D;
-    const UChar trailSurrogate = 0xDDFA;
+    // U+20BB7 is \uD83D\uDDFA in UTF-16.
+    const UChar leadSurrogate = 0xD842;
+    const UChar trailSurrogate = 0xDFB7;
 
     EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(trailSurrogate));
     EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(leadSurrogate));
@@ -433,10 +433,10 @@
 {
     BackspaceStateMachine machine;
 
-    UChar vs16 = 0xFE0F;
-    UChar vs16Base = '0';
-    UChar vs16BaseLead = 0xD83C;
-    UChar vs16BaseTrail = 0xDD70;
+    UChar vs01 = 0xFE00;
+    UChar vs01Base = 0xA85E;
+    UChar vs01BaseLead = 0xD802;
+    UChar vs01BaseTrail = 0xDEC6;
 
     UChar vs17Lead = 0xDB40;
     UChar vs17Trail = 0xDD00;
@@ -453,8 +453,8 @@
 
     // VS_BASE + VS
     machine.reset();
-    EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
-    EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(vs16Base));
+    EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs01));
+    EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(vs01Base));
     EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
     EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
 
@@ -468,9 +468,9 @@
 
     // VS_BASE(surrogate pairs) + VS
     machine.reset();
-    EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
-    EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16BaseTrail));
-    EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(vs16BaseLead));
+    EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs01));
+    EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs01BaseTrail));
+    EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(vs01BaseLead));
     EXPECT_EQ(-3, machine.finalizeAndGetBoundaryOffset());
     EXPECT_EQ(-3, machine.finalizeAndGetBoundaryOffset());
 
@@ -493,7 +493,7 @@
     // Followings are edge case. Delete only variation selector.
     // Not VS_BASE + VS
     machine.reset();
-    EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+    EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs01));
     EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notvsBase));
     EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
     EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
@@ -508,7 +508,7 @@
 
     // Not VS_BASE(surrogate pairs) + VS
     machine.reset();
-    EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+    EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs01));
     EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(notvsBaseTrail));
     EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notvsBaseLead));
     EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
@@ -540,7 +540,7 @@
 
     // Sot + VS
     machine.reset();
-    EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+    EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs01));
     EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
     EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
 
diff --git a/third_party/WebKit/Source/core/editing/state_machines/StateMachineUtil.cpp b/third_party/WebKit/Source/core/editing/state_machines/StateMachineUtil.cpp
index 2889d75..28235cb 100644
--- a/third_party/WebKit/Source/core/editing/state_machines/StateMachineUtil.cpp
+++ b/third_party/WebKit/Source/core/editing/state_machines/StateMachineUtil.cpp
@@ -13,15 +13,6 @@
 
 namespace {
 
-// Returns true if the code point has Glue_After_Zwj grapheme break property.
-// See http://www.unicode.org/Public/9.0.0/ucd/auxiliary/GraphemeBreakProperty-9.0.0d18.txt
-bool isGlueAfterZwj(uint32_t codePoint)
-{
-    return codePoint == WTF::Unicode::heavyBlackHeartCharacter
-        || codePoint == WTF::Unicode::kissMarkCharacter
-        || codePoint == WTF::Unicode::leftSpeechBubbleCharacter;
-}
-
 // Returns true if the code point has E_Basae_GAZ grapheme break property.
 // See http://www.unicode.org/Public/9.0.0/ucd/auxiliary/GraphemeBreakProperty-9.0.0d18.txt
 bool isEBaseGAZ(uint32_t codePoint)
@@ -128,9 +119,9 @@
         && Character::isModifier(nextCodePoint))
         return false;
 
-    // Proposed Rule GB11, ZWJ x (Glue_After_Zwj | EBG)
+    // Proposed Rule GB11, ZWJ x Emoji
     if (prevCodePoint == zeroWidthJoinerCharacter
-        && (isGlueAfterZwj(nextCodePoint) || isEBaseGAZ(nextCodePoint)))
+        && (Character::isEmoji(nextCodePoint)))
         return false;
 
     // Rule GB999 any ÷ any
diff --git a/third_party/WebKit/Source/core/editing/state_machines/StateMachineUtilTest.cpp b/third_party/WebKit/Source/core/editing/state_machines/StateMachineUtilTest.cpp
index d5ab01f8..b99e759 100644
--- a/third_party/WebKit/Source/core/editing/state_machines/StateMachineUtilTest.cpp
+++ b/third_party/WebKit/Source/core/editing/state_machines/StateMachineUtilTest.cpp
@@ -135,16 +135,23 @@
     const UChar32 kGlueAfterZwj = 0x2764;
     // U+1F466 (BOY) has E_Base_GAZ grapheme property.
     const UChar32 kEBaseGAZ = 0x1F466;
+    // U+1F5FA (WORLD MAP) doesn'T have Glue_After_Zwj or E_Base_GAZ property
+    // but has Emoji property.
+    const UChar32 kEmoji = 0x1F5FA;
 
     // Grapheme Cluster Boundary Rule GB11: ZWJ x (Glue_After_Zwj | EBG)
     EXPECT_FALSE(isGraphemeBreak(WTF::Unicode::zeroWidthJoinerCharacter,
         kGlueAfterZwj));
     EXPECT_FALSE(isGraphemeBreak(WTF::Unicode::zeroWidthJoinerCharacter,
         kEBaseGAZ));
+    EXPECT_FALSE(isGraphemeBreak(WTF::Unicode::zeroWidthJoinerCharacter,
+        kEmoji));
 
     EXPECT_TRUE(isGraphemeBreak(kGlueAfterZwj, kEBaseGAZ));
     EXPECT_TRUE(isGraphemeBreak(kGlueAfterZwj, kGlueAfterZwj));
     EXPECT_TRUE(isGraphemeBreak(kEBaseGAZ, kGlueAfterZwj));
+
+    EXPECT_TRUE(isGraphemeBreak(WTF::Unicode::zeroWidthJoinerCharacter, 'a'));
 }
 
 TEST(StateMachineUtilTest, IsGraphmeBreak_IndicSyllabicCategoryVirama)
diff --git a/third_party/WebKit/Source/core/events/DOMWindowEventQueue.cpp b/third_party/WebKit/Source/core/events/DOMWindowEventQueue.cpp
index 2a39790..11d7eebb 100644
--- a/third_party/WebKit/Source/core/events/DOMWindowEventQueue.cpp
+++ b/third_party/WebKit/Source/core/events/DOMWindowEventQueue.cpp
@@ -148,8 +148,8 @@
 {
     EventTarget* eventTarget = event->target();
     InspectorInstrumentation::AsyncTask asyncTask(eventTarget->getExecutionContext(), event);
-    if (eventTarget->toDOMWindow())
-        eventTarget->toDOMWindow()->dispatchEvent(event, nullptr);
+    if (LocalDOMWindow* window = eventTarget->toLocalDOMWindow())
+        window->dispatchEvent(event, nullptr);
     else
         eventTarget->dispatchEvent(event);
 }
diff --git a/third_party/WebKit/Source/core/events/Event.cpp b/third_party/WebKit/Source/core/events/Event.cpp
index 9966366..fcbe35e 100644
--- a/third_party/WebKit/Source/core/events/Event.cpp
+++ b/third_party/WebKit/Source/core/events/Event.cpp
@@ -314,7 +314,7 @@
 
     // Returns [window] for events that are directly dispatched to the window object;
     // e.g., window.load, pageshow, etc.
-    if (LocalDOMWindow* window = m_currentTarget->toDOMWindow())
+    if (LocalDOMWindow* window = m_currentTarget->toLocalDOMWindow())
         return HeapVector<Member<EventTarget>>(1, window);
 
     return HeapVector<Member<EventTarget>>();
diff --git a/third_party/WebKit/Source/core/events/EventTarget.cpp b/third_party/WebKit/Source/core/events/EventTarget.cpp
index b9950837..ac4e5e4 100644
--- a/third_party/WebKit/Source/core/events/EventTarget.cpp
+++ b/third_party/WebKit/Source/core/events/EventTarget.cpp
@@ -96,12 +96,12 @@
     return nullptr;
 }
 
-const LocalDOMWindow* EventTarget::toDOMWindow() const
+const LocalDOMWindow* EventTarget::toLocalDOMWindow() const
 {
     return nullptr;
 }
 
-LocalDOMWindow* EventTarget::toDOMWindow()
+LocalDOMWindow* EventTarget::toLocalDOMWindow()
 {
     return nullptr;
 }
diff --git a/third_party/WebKit/Source/core/events/EventTarget.h b/third_party/WebKit/Source/core/events/EventTarget.h
index 237ab4025..8d198511 100644
--- a/third_party/WebKit/Source/core/events/EventTarget.h
+++ b/third_party/WebKit/Source/core/events/EventTarget.h
@@ -107,8 +107,8 @@
     virtual ExecutionContext* getExecutionContext() const = 0;
 
     virtual Node* toNode();
-    virtual const LocalDOMWindow* toDOMWindow() const;
-    virtual LocalDOMWindow* toDOMWindow();
+    virtual const LocalDOMWindow* toLocalDOMWindow() const;
+    virtual LocalDOMWindow* toLocalDOMWindow();
     virtual MessagePort* toMessagePort();
 
     bool addEventListener(const AtomicString& eventType, EventListener*, bool useCapture = false);
@@ -205,14 +205,14 @@
     static EventListener* on##attribute(EventTarget& eventTarget) { \
         if (Node* node = eventTarget.toNode()) \
             return node->document().getWindowAttributeEventListener(EventTypeNames::attribute); \
-        ASSERT(eventTarget.toDOMWindow()); \
+        ASSERT(eventTarget.toLocalDOMWindow()); \
         return eventTarget.getAttributeEventListener(EventTypeNames::attribute); \
     } \
     static void setOn##attribute(EventTarget& eventTarget, EventListener* listener) { \
         if (Node* node = eventTarget.toNode()) \
             node->document().setWindowAttributeEventListener(EventTypeNames::attribute, listener); \
         else { \
-            ASSERT(eventTarget.toDOMWindow()); \
+            ASSERT(eventTarget.toLocalDOMWindow()); \
             eventTarget.setAttributeEventListener(EventTypeNames::attribute, listener); \
         } \
     }
diff --git a/third_party/WebKit/Source/core/events/MessageEvent.cpp b/third_party/WebKit/Source/core/events/MessageEvent.cpp
index 8b04e6cd..ee0dbbc 100644
--- a/third_party/WebKit/Source/core/events/MessageEvent.cpp
+++ b/third_party/WebKit/Source/core/events/MessageEvent.cpp
@@ -35,7 +35,7 @@
 
 static inline bool isValidSource(EventTarget* source)
 {
-    return !source || source->toDOMWindow() || source->toMessagePort();
+    return !source || source->toLocalDOMWindow() || source->toMessagePort();
 }
 
 MessageEvent::MessageEvent()
diff --git a/third_party/WebKit/Source/core/frame/DOMWindow.cpp b/third_party/WebKit/Source/core/frame/DOMWindow.cpp
index b2c0e024..62e2189a 100644
--- a/third_party/WebKit/Source/core/frame/DOMWindow.cpp
+++ b/third_party/WebKit/Source/core/frame/DOMWindow.cpp
@@ -226,7 +226,7 @@
     if (InspectorInstrumentation::consoleAgentEnabled(sourceDocument))
         stackTrace = ScriptCallStack::capture();
 
-    toLocalDOMWindow(this)->schedulePostMessage(event, target.get(), stackTrace.release());
+    blink::toLocalDOMWindow(this)->schedulePostMessage(event, target.get(), stackTrace.release());
 }
 
 // FIXME: Once we're throwing exceptions for cross-origin access violations, we will always sanitize the target
diff --git a/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp b/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp
index e30482a4..0f3d57d 100644
--- a/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp
+++ b/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp
@@ -252,7 +252,7 @@
         const EventTargetSet* targets = &m_targets[handlerClass];
         for (const auto& eventTarget : *targets) {
             Node* node = eventTarget.key->toNode();
-            LocalDOMWindow* window = eventTarget.key->toDOMWindow();
+            LocalDOMWindow* window = eventTarget.key->toLocalDOMWindow();
             if (node && !ThreadHeap::isHeapObjectAlive(node)) {
                 deadTargets.append(node);
             } else if (window && !ThreadHeap::isHeapObjectAlive(window)) {
@@ -279,7 +279,7 @@
                         break;
                     }
                 }
-            } else if (eventTarget.key->toDOMWindow()) {
+            } else if (eventTarget.key->toLocalDOMWindow()) {
                 // DOMWindows may outlive their documents, so we shouldn't remove their handlers
                 // here.
             } else {
@@ -302,7 +302,7 @@
                 // See the comment for |documentDetached| if either of these assertions fails.
                 ASSERT(node->document().frameHost());
                 ASSERT(node->document().frameHost() == m_frameHost);
-            } else if (LocalDOMWindow* window = eventTarget.key->toDOMWindow()) {
+            } else if (LocalDOMWindow* window = eventTarget.key->toLocalDOMWindow()) {
                 // If any of these assertions fail, LocalDOMWindow failed to unregister its handlers
                 // properly.
                 ASSERT(window->frame());
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
index a9450a2..c148399 100644
--- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -467,12 +467,12 @@
     return m_document.get();
 }
 
-const LocalDOMWindow* LocalDOMWindow::toDOMWindow() const
+const LocalDOMWindow* LocalDOMWindow::toLocalDOMWindow() const
 {
     return this;
 }
 
-LocalDOMWindow* LocalDOMWindow::toDOMWindow()
+LocalDOMWindow* LocalDOMWindow::toLocalDOMWindow()
 {
     return this;
 }
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
index f45aa85..c1d5f0f 100644
--- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
+++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
@@ -82,8 +82,8 @@
 
     // EventTarget overrides:
     ExecutionContext* getExecutionContext() const override;
-    const LocalDOMWindow* toDOMWindow() const override;
-    LocalDOMWindow* toDOMWindow() override;
+    const LocalDOMWindow* toLocalDOMWindow() const override;
+    LocalDOMWindow* toLocalDOMWindow() override;
 
     // DOMWindow overrides:
     bool isLocalDOMWindow() const override { return true; }
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
index 47c40e1..be485fc 100644
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -1040,7 +1040,7 @@
 
 ScriptPromise HTMLCanvasElement::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& options, ExceptionState& exceptionState)
 {
-    ASSERT(eventTarget.toDOMWindow());
+    ASSERT(eventTarget.toLocalDOMWindow());
     if (!sw || !sh) {
         exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width"));
         return ScriptPromise();
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
index 44ca967..5c79e60 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
@@ -684,7 +684,7 @@
 
 ScriptPromise HTMLImageElement::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& options, ExceptionState& exceptionState)
 {
-    ASSERT(eventTarget.toDOMWindow());
+    ASSERT(eventTarget.toLocalDOMWindow());
     if (!cachedImage()) {
         exceptionState.throwDOMException(InvalidStateError, "No image can be retrieved from the provided element.");
         return ScriptPromise();
@@ -700,7 +700,7 @@
         exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width"));
         return ScriptPromise();
     }
-    return ImageBitmapSource::fulfillImageBitmap(scriptState, ImageBitmap::create(this, IntRect(sx, sy, sw, sh), eventTarget.toDOMWindow()->document(), options));
+    return ImageBitmapSource::fulfillImageBitmap(scriptState, ImageBitmap::create(this, IntRect(sx, sy, sw, sh), eventTarget.toLocalDOMWindow()->document(), options));
 }
 
 void HTMLImageElement::selectSourceURL(ImageLoader::UpdateFromElementBehavior behavior)
diff --git a/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp b/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp
index 0fbe815..b98afbf 100644
--- a/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp
@@ -328,7 +328,7 @@
 
 ScriptPromise HTMLVideoElement::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& options, ExceptionState& exceptionState)
 {
-    ASSERT(eventTarget.toDOMWindow());
+    ASSERT(eventTarget.toLocalDOMWindow());
     if (getNetworkState() == HTMLMediaElement::NETWORK_EMPTY) {
         exceptionState.throwDOMException(InvalidStateError, "The provided element has not retrieved data.");
         return ScriptPromise();
@@ -341,7 +341,7 @@
         exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width"));
         return ScriptPromise();
     }
-    return ImageBitmapSource::fulfillImageBitmap(scriptState, ImageBitmap::create(this, IntRect(sx, sy, sw, sh), eventTarget.toDOMWindow()->document(), options));
+    return ImageBitmapSource::fulfillImageBitmap(scriptState, ImageBitmap::create(this, IntRect(sx, sy, sw, sh), eventTarget.toLocalDOMWindow()->document(), options));
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.h b/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.h
index 3910137..e6638e1aa4 100644
--- a/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.h
@@ -32,6 +32,7 @@
 #define BaseDateAndTimeInputType_h
 
 #include "core/html/forms/InputType.h"
+#include "core/html/shadow/DateTimeEditElement.h"
 #include "platform/DateComponents.h"
 
 namespace blink {
@@ -43,6 +44,11 @@
 public:
     String visibleValue() const override;
 
+    // Provide some helpers for BaseMultipleFieldsDateAndTimeInputType.
+    virtual String formatDateTimeFieldsState(const DateTimeFieldsState&) const = 0;
+    virtual void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const = 0;
+    virtual bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const = 0;
+
 protected:
     BaseDateAndTimeInputType(HTMLInputElement& element) : InputType(element) { }
     Decimal parseToNumber(const String&, const Decimal&) const override;
diff --git a/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h b/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h
index f29f528..9b059a1 100644
--- a/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h
@@ -53,16 +53,12 @@
     USING_GARBAGE_COLLECTED_MIXIN(BaseMultipleFieldsDateAndTimeInputType);
 
 public:
-    virtual bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const = 0;
-
     DEFINE_INLINE_VIRTUAL_TRACE() { BaseDateAndTimeInputType::trace(visitor); }
 
 protected:
     BaseMultipleFieldsDateAndTimeInputType(HTMLInputElement&);
     ~BaseMultipleFieldsDateAndTimeInputType() override;
 
-    virtual void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const = 0;
-
 private:
     // DateTimeEditElement::EditControlOwner functions
     void didBlurFromControl() final;
diff --git a/third_party/WebKit/Source/core/html/forms/DateInputType.cpp b/third_party/WebKit/Source/core/html/forms/DateInputType.cpp
index 4126d52b..0a69f9b 100644
--- a/third_party/WebKit/Source/core/html/forms/DateInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/DateInputType.cpp
@@ -94,7 +94,6 @@
         addWarningToConsole("The specified value %s does not conform to the required format, \"yyyy-MM-dd\".", value);
 }
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 String DateInputType::formatDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) const
 {
     if (!dateTimeFieldsState.hasDayOfMonth() || !dateTimeFieldsState.hasMonth() || !dateTimeFieldsState.hasYear())
@@ -120,6 +119,5 @@
 {
     return hasYear && hasMonth && hasDay;
 }
-#endif
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/DateInputType.h b/third_party/WebKit/Source/core/html/forms/DateInputType.h
index 0afb7f38..86ba0e7 100644
--- a/third_party/WebKit/Source/core/html/forms/DateInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/DateInputType.h
@@ -56,12 +56,10 @@
     bool setMillisecondToDateComponents(double, DateComponents*) const override;
     void warnIfValueIsInvalid(const String&) const override;
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-    // BaseMultipleFieldsDateAndTimeInputType functions
+    // BaseDateAndTimeInputType functions
     String formatDateTimeFieldsState(const DateTimeFieldsState&) const override;
     void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const override;
     bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const override;
-#endif
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/DateTimeFieldsState.cpp b/third_party/WebKit/Source/core/html/forms/DateTimeFieldsState.cpp
index aa15d8f..07c787a 100644
--- a/third_party/WebKit/Source/core/html/forms/DateTimeFieldsState.cpp
+++ b/third_party/WebKit/Source/core/html/forms/DateTimeFieldsState.cpp
@@ -25,7 +25,6 @@
 
 #include "core/html/forms/DateTimeFieldsState.h"
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "core/html/forms/FormController.h"
 
 namespace blink {
@@ -107,5 +106,3 @@
 }
 
 } // namespace blink
-
-#endif
diff --git a/third_party/WebKit/Source/core/html/forms/DateTimeFieldsState.h b/third_party/WebKit/Source/core/html/forms/DateTimeFieldsState.h
index 1db5f4df..c346e4c8 100644
--- a/third_party/WebKit/Source/core/html/forms/DateTimeFieldsState.h
+++ b/third_party/WebKit/Source/core/html/forms/DateTimeFieldsState.h
@@ -26,9 +26,6 @@
 #ifndef DateTimeFieldsState_h
 #define DateTimeFieldsState_h
 
-#include "wtf/build_config.h"
-
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "wtf/Allocator.h"
 
 namespace blink {
@@ -103,4 +100,3 @@
 } // namespace blink
 
 #endif
-#endif
diff --git a/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.cpp b/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.cpp
index ca99794..7c525fc2 100644
--- a/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.cpp
@@ -113,9 +113,6 @@
         addWarningToConsole("The specified value %s does not conform to the required format.  The format is \"yyyy-MM-ddThh:mm\" followed by optional \":ss\" or \":ss.SSS\".", value);
 }
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-// FIXME: It is better to share code for DateTimeInputType::formatDateTimeFieldsState()
-// and DateTimeInputLocalType::formatDateTimeFieldsState().
 String DateTimeLocalInputType::formatDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) const
 {
     if (!dateTimeFieldsState.hasDayOfMonth() || !dateTimeFieldsState.hasMonth() || !dateTimeFieldsState.hasYear()
@@ -173,6 +170,5 @@
 {
     return hasYear && hasMonth && hasDay && hasAMPM && hasHour && hasMinute;
 }
-#endif
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.h b/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.h
index b57a167..5a4dbf4 100644
--- a/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.h
@@ -61,12 +61,10 @@
     String localizeValue(const String&) const override;
     void warnIfValueIsInvalid(const String&) const override;
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-    // BaseMultipleFieldsDateAndTimeInputType functions
+    // BaseDateAndTimeInputType functions
     String formatDateTimeFieldsState(const DateTimeFieldsState&) const final;
     void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const final;
     bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const override;
-#endif
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/MonthInputType.cpp b/third_party/WebKit/Source/core/html/forms/MonthInputType.cpp
index 5f36d9e..2b331863 100644
--- a/third_party/WebKit/Source/core/html/forms/MonthInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/MonthInputType.cpp
@@ -133,7 +133,6 @@
         addWarningToConsole("The specified value %s does not conform to the required format.  The format is \"yyyy-MM\" where yyyy is year in four or more digits, and MM is 01-12.", value);
 }
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 String MonthInputType::formatDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) const
 {
     if (!dateTimeFieldsState.hasMonth() || !dateTimeFieldsState.hasYear())
@@ -157,5 +156,5 @@
 {
     return hasYear && hasMonth;
 }
-#endif
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/MonthInputType.h b/third_party/WebKit/Source/core/html/forms/MonthInputType.h
index 2ec6dd5..1016917e 100644
--- a/third_party/WebKit/Source/core/html/forms/MonthInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/MonthInputType.h
@@ -61,12 +61,10 @@
     bool canSetSuggestedValue() override;
     void warnIfValueIsInvalid(const String&) const override;
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-    // BaseMultipleFieldsDateAndTimeInputType functions
+    // BaseDateAndTimeInputType functions
     String formatDateTimeFieldsState(const DateTimeFieldsState&) const override;
     void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const override;
     bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const override;
-#endif
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/TimeInputType.cpp b/third_party/WebKit/Source/core/html/forms/TimeInputType.cpp
index 4e42409c..a5f9583 100644
--- a/third_party/WebKit/Source/core/html/forms/TimeInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/TimeInputType.cpp
@@ -120,8 +120,6 @@
     return localized.isEmpty() ? proposedValue : localized;
 }
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-
 String TimeInputType::formatDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) const
 {
     if (!dateTimeFieldsState.hasHour() || !dateTimeFieldsState.hasMinute() || !dateTimeFieldsState.hasAMPM())
@@ -161,6 +159,5 @@
 {
     return hasHour && hasMinute && hasAMPM;
 }
-#endif
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/TimeInputType.h b/third_party/WebKit/Source/core/html/forms/TimeInputType.h
index bd2074d..3def9ae 100644
--- a/third_party/WebKit/Source/core/html/forms/TimeInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/TimeInputType.h
@@ -58,12 +58,10 @@
     void warnIfValueIsInvalid(const String&) const override;
     String localizeValue(const String&) const override;
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-    // BaseMultipleFieldsDateAndTimeInputType functions
+    // BaseDateAndTimeInputType functions
     String formatDateTimeFieldsState(const DateTimeFieldsState&) const override;
     void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const override;
     bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const override;
-#endif
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/WeekInputType.cpp b/third_party/WebKit/Source/core/html/forms/WeekInputType.cpp
index 630ee74..f9592d9 100644
--- a/third_party/WebKit/Source/core/html/forms/WeekInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/WeekInputType.cpp
@@ -88,7 +88,6 @@
         addWarningToConsole("The specified value %s does not conform to the required format.  The format is \"yyyy-Www\" where yyyy is year in four or more digits, and ww is 01-53.", value);
 }
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 String WeekInputType::formatDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) const
 {
     if (!dateTimeFieldsState.hasYear() || !dateTimeFieldsState.hasWeekOfYear())
@@ -111,6 +110,5 @@
 {
     return hasYear && hasWeek;
 }
-#endif
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/WeekInputType.h b/third_party/WebKit/Source/core/html/forms/WeekInputType.h
index 09a2ebb1..16163188 100644
--- a/third_party/WebKit/Source/core/html/forms/WeekInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/WeekInputType.h
@@ -56,12 +56,10 @@
     bool setMillisecondToDateComponents(double, DateComponents*) const override;
     void warnIfValueIsInvalid(const String&) const override;
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-    // BaseMultipleFieldsDateAndTimeInputType functions
+    // BaseDateAndTimeInputType functions
     String formatDateTimeFieldsState(const DateTimeFieldsState&) const override;
     void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const override;
     bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const override;
-#endif
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.cpp b/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.cpp
index 01794a9..e76201e85 100644
--- a/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.cpp
+++ b/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.cpp
@@ -25,7 +25,6 @@
 
 #include "core/html/shadow/DateTimeEditElement.h"
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
 #include "core/HTMLNames.h"
 #include "core/dom/Document.h"
@@ -814,5 +813,3 @@
 }
 
 } // namespace blink
-
-#endif
diff --git a/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.h b/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.h
index bfcd721..d69b0cd5 100644
--- a/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.h
+++ b/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.h
@@ -26,9 +26,6 @@
 #ifndef DateTimeEditElement_h
 #define DateTimeEditElement_h
 
-#include "wtf/build_config.h"
-
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "core/html/forms/StepRange.h"
 #include "core/html/shadow/DateTimeFieldElement.h"
 #include "platform/DateComponents.h"
@@ -161,4 +158,3 @@
 } // namespace blink
 
 #endif
-#endif
diff --git a/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.cpp b/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.cpp
index 163f92e..12586db3 100644
--- a/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.cpp
+++ b/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.cpp
@@ -25,7 +25,6 @@
 
 #include "core/html/shadow/DateTimeFieldElement.h"
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "core/HTMLNames.h"
 #include "core/dom/Document.h"
 #include "core/dom/StyleChangeReason.h"
@@ -246,4 +245,3 @@
 
 } // namespace blink
 
-#endif
diff --git a/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.h b/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.h
index 9792067e..483ae6a2 100644
--- a/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.h
+++ b/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.h
@@ -26,9 +26,6 @@
 #ifndef DateTimeFieldElement_h
 #define DateTimeFieldElement_h
 
-#include "wtf/build_config.h"
-
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "core/html/HTMLDivElement.h"
 #include "core/html/HTMLSpanElement.h"
 
@@ -109,4 +106,3 @@
 } // namespace blink
 
 #endif
-#endif
diff --git a/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.cpp b/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.cpp
index 7d25b67..c5518cd8 100644
--- a/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.cpp
+++ b/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.cpp
@@ -25,7 +25,6 @@
 
 #include "core/html/shadow/DateTimeFieldElements.h"
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "core/html/forms/DateTimeFieldsState.h"
 #include "platform/DateComponents.h"
 #include "platform/text/PlatformLocale.h"
@@ -630,5 +629,3 @@
 }
 
 } // namespace blink
-
-#endif
diff --git a/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.h b/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.h
index f17954e..fa8a298 100644
--- a/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.h
+++ b/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.h
@@ -26,9 +26,6 @@
 #ifndef DateTimeFieldElements_h
 #define DateTimeFieldElements_h
 
-#include "wtf/build_config.h"
-
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "core/html/shadow/DateTimeNumericFieldElement.h"
 #include "core/html/shadow/DateTimeSymbolicFieldElement.h"
 #include "wtf/Allocator.h"
@@ -266,4 +263,3 @@
 } // namespace blink
 
 #endif
-#endif
diff --git a/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.cpp b/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.cpp
index e9a9168b..2cd857c 100644
--- a/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.cpp
+++ b/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.cpp
@@ -25,7 +25,6 @@
 
 #include "core/html/shadow/DateTimeNumericFieldElement.h"
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "core/CSSPropertyNames.h"
 #include "core/CSSValueKeywords.h"
 #include "core/events/KeyboardEvent.h"
@@ -242,5 +241,3 @@
 }
 
 } // namespace blink
-
-#endif
diff --git a/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.h b/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.h
index 3c2f54c2..bf7f1a3 100644
--- a/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.h
+++ b/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.h
@@ -26,9 +26,6 @@
 #ifndef DateTimeNumericFieldElement_h
 #define DateTimeNumericFieldElement_h
 
-#include "wtf/build_config.h"
-
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "core/html/shadow/DateTimeFieldElement.h"
 #include "wtf/Allocator.h"
 #include "wtf/text/StringBuilder.h"
@@ -110,4 +107,3 @@
 } // namespace blink
 
 #endif
-#endif
diff --git a/third_party/WebKit/Source/core/html/shadow/DateTimeSymbolicFieldElement.cpp b/third_party/WebKit/Source/core/html/shadow/DateTimeSymbolicFieldElement.cpp
index adbc28e..a37caae 100644
--- a/third_party/WebKit/Source/core/html/shadow/DateTimeSymbolicFieldElement.cpp
+++ b/third_party/WebKit/Source/core/html/shadow/DateTimeSymbolicFieldElement.cpp
@@ -25,7 +25,6 @@
 
 #include "core/html/shadow/DateTimeSymbolicFieldElement.h"
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "core/events/KeyboardEvent.h"
 #include "platform/fonts/Font.h"
 #include "platform/text/TextBreakIterator.h"
@@ -176,5 +175,3 @@
 }
 
 } // namespace blink
-
-#endif
diff --git a/third_party/WebKit/Source/core/html/shadow/DateTimeSymbolicFieldElement.h b/third_party/WebKit/Source/core/html/shadow/DateTimeSymbolicFieldElement.h
index 51690dd..3e24a33 100644
--- a/third_party/WebKit/Source/core/html/shadow/DateTimeSymbolicFieldElement.h
+++ b/third_party/WebKit/Source/core/html/shadow/DateTimeSymbolicFieldElement.h
@@ -26,9 +26,6 @@
 #ifndef DateTimeSymbolicFieldElement_h
 #define DateTimeSymbolicFieldElement_h
 
-#include "wtf/build_config.h"
-
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
 #include "core/html/forms/TypeAhead.h"
 #include "core/html/shadow/DateTimeFieldElement.h"
 
@@ -82,4 +79,3 @@
 } // namespace blink
 
 #endif
-#endif
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
index 77c2e8c..0c501b8 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
@@ -133,7 +133,7 @@
 
 ImageBitmapFactories& ImageBitmapFactories::from(EventTarget& eventTarget)
 {
-    if (LocalDOMWindow* window = eventTarget.toDOMWindow())
+    if (LocalDOMWindow* window = eventTarget.toLocalDOMWindow())
         return fromInternal(*window);
 
     ASSERT(eventTarget.getExecutionContext()->isWorkerGlobalScope());
diff --git a/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py b/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py
index b8f54a74..2b56d55b 100755
--- a/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py
+++ b/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py
@@ -53,31 +53,6 @@
 #endif // !defined(${file_name}_h)
 """)
 
-template_inline = string.Template("""
-inline void ${name}(${params_public})
-{   ${fast_return}
-    if (${condition})
-        ${name}Impl(${params_impl});
-}
-""")
-
-template_inline_forward = string.Template("""
-inline void ${name}(${params_public})
-{   ${fast_return}
-    ${name}Impl(${params_impl});
-}
-""")
-
-template_inline_returns_value = string.Template("""
-inline ${return_type} ${name}(${params_public})
-{   ${fast_return}
-    if (${condition})
-        return ${name}Impl(${params_impl});
-    return ${default_return_value};
-}
-""")
-
-
 template_cpp = string.Template("""// Code generated from InspectorInstrumentation.idl
 
 ${includes}
@@ -93,14 +68,16 @@
 } // namespace blink
 """)
 
-template_outofline = string.Template("""
-${return_type} ${name}Impl(${params_impl})
-{${impl_lines}
+template_impl = string.Template("""
+${return_type} ${name}(${params})
+{
+    if (${condition}) {${impl_lines}
+    }${default_return}
 }""")
 
 template_agent_call = string.Template("""
-    if (${agent_class}* agent = ${agent_fetch})
-        ${maybe_return}agent->${name}(${params_agent});""")
+        if (${agent_class}* agent = ${agent_fetch})
+            ${maybe_return}agent->${name}(${params_agent});""")
 
 template_instrumenting_agents_h = string.Template("""// Code generated from InspectorInstrumentation.idl
 
@@ -250,94 +227,61 @@
 
         if self.return_type == "bool":
             self.default_return_value = "false"
-        elif self.return_type == "int":
-            self.default_return_value = "0"
-        elif self.return_type == "String":
-            self.default_return_value = "\"\""
-        else:
+        elif self.returns_cookie:
             self.default_return_value = self.return_type + "()"
-
-        for param in self.params:
-            if "DefaultReturn" in param.options:
-                self.default_return_value = param.name
+        elif self.returns_value:
+            sys.stderr.write("Can only return bool or cookie: %s\n" % self.name)
+            sys.exit(1)
 
         self.params_impl = self.params
-        if not self.accepts_cookie and not "Inline=Forward" in self.options:
+        if not self.accepts_cookie:
             if not "Keep" in self.params_impl[0].options:
                 self.params_impl = self.params_impl[1:]
-            self.params_impl = [Parameter("InstrumentingAgents* agents")] + self.params_impl
+        else:
+            self.params_impl = self.params_impl[1:]
 
         self.agents = filter(lambda option: not "=" in option, self.options)
 
+        if self.returns_value and not self.returns_cookie and len(self.agents) > 1:
+            sys.stderr.write("Can only return value from a single agent: %s\n" % self.name)
+            sys.exit(1)
+
     def generate_header(self, header_lines):
-        if "Inline=Custom" in self.options:
-            return
-
-        header_lines.append("CORE_EXPORT %s %sImpl(%s);" % (
-            self.return_type, self.name, ", ".join(map(Parameter.to_str_class, self.params_impl))))
-
-        if "Inline=FastReturn" in self.options or "Inline=Forward" in self.options:
-            fast_return = "\n    FAST_RETURN_IF_NO_FRONTENDS(%s);" % self.default_return_value
-        else:
-            fast_return = ""
-
-        for param in self.params:
-            if "FastReturn" in param.options:
-                fast_return += "\n    if (!%s)\n        return %s;" % (param.name, self.default_return_value)
-
-        if self.accepts_cookie:
-            condition = "%s.isValid()" % self.params_impl[0].name
-            template = template_inline
-        elif "Inline=Forward" in self.options:
-            condition = ""
-            template = template_inline_forward
-        else:
-            condition = "InstrumentingAgents* agents = instrumentingAgentsFor(%s)" % self.params[0].name
-
-            if self.returns_value:
-                template = template_inline_returns_value
-            else:
-                template = template_inline
-
-        header_lines.append(template.substitute(
-            None,
-            name=self.name,
-            fast_return=fast_return,
-            return_type=self.return_type,
-            default_return_value=self.default_return_value,
-            params_public=", ".join(map(Parameter.to_str_full, self.params)),
-            params_impl=", ".join(map(Parameter.to_str_name, self.params_impl)),
-            condition=condition))
+        header_lines.append("CORE_EXPORT %s %s(%s);" % (
+            self.return_type, self.name, ", ".join(map(Parameter.to_str_class, self.params))))
 
     def generate_cpp(self, cpp_lines):
-        if len(self.agents) == 0:
-            return
+        if self.accepts_cookie:
+            condition = "%s.isValid()" % self.params[0].name
+        else:
+            condition = "InstrumentingAgents* instrumentingAgents = instrumentingAgentsFor(%s)" % self.params[0].name
+
+        default_return = ""
+        if self.returns_value:
+            default_return = "\n    return %s;" % self.default_return_value
 
         body_lines = map(self.generate_ref_ptr, self.params)
         body_lines += map(self.generate_agent_call, self.agents)
 
         if self.returns_cookie:
-            body_lines.append("\n    return InspectorInstrumentationCookie(agents);")
-        elif self.returns_value:
-            body_lines.append("\n    return %s;" % self.default_return_value)
+            body_lines.append("\n        return InspectorInstrumentationCookie(instrumentingAgents);")
 
-        generated_outofline = template_outofline.substitute(
+        cpp_lines.append(template_impl.substitute(
             None,
-            return_type=self.return_type,
             name=self.name,
-            params_impl=", ".join(map(Parameter.to_str_class_and_name, self.params_impl)),
-            impl_lines="".join(body_lines))
-        if generated_outofline not in cpp_lines:
-            cpp_lines.append(generated_outofline)
+            return_type=self.return_type,
+            params=", ".join(map(Parameter.to_str_class_and_name, self.params)),
+            default_return=default_return,
+            impl_lines="".join(body_lines),
+            condition=condition))
 
     def generate_agent_call(self, agent):
         agent_class, agent_getter = agent_getter_signature(agent)
 
-        leading_param_name = self.params_impl[0].name
         if not self.accepts_cookie:
-            agent_fetch = "%s->%s()" % (leading_param_name, agent_getter)
+            agent_fetch = "instrumentingAgents->%s()" % agent_getter
         else:
-            agent_fetch = "%s.instrumentingAgents()->%s()" % (leading_param_name, agent_getter)
+            agent_fetch = "%s.instrumentingAgents()->%s()" % (self.params[0].name, agent_getter)
 
         template = template_agent_call
 
@@ -352,11 +296,11 @@
             agent_class=agent_class,
             agent_fetch=agent_fetch,
             maybe_return=maybe_return,
-            params_agent=", ".join(map(Parameter.to_str_value, self.params_impl)[1:]))
+            params_agent=", ".join(map(Parameter.to_str_value, self.params_impl)))
 
     def generate_ref_ptr(self, param):
         if param.is_prp:
-            return "\n    RefPtr<%s> %s = %s;" % (param.inner_type, param.value, param.name)
+            return "\n        RefPtr<%s> %s = %s;" % (param.inner_type, param.value, param.name)
         else:
             return ""
 
diff --git a/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.cpp b/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.cpp
index 7194e6e..0912f7a 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.cpp
@@ -111,29 +111,31 @@
 
 namespace InspectorInstrumentation {
 
-bool isDebuggerPausedImpl(InstrumentingAgents* instrumentingAgents)
+bool isDebuggerPaused(LocalFrame* frame)
 {
-    if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents->inspectorDebuggerAgent())
-        return debuggerAgent->isPaused();
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsFor(frame)) {
+        if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents->inspectorDebuggerAgent())
+            return debuggerAgent->isPaused();
+    }
     return false;
 }
 
-void didReceiveResourceResponseButCanceledImpl(LocalFrame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
+void didReceiveResourceResponseButCanceled(LocalFrame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
 {
     didReceiveResourceResponse(frame, identifier, loader, r, 0);
 }
 
-void continueAfterXFrameOptionsDeniedImpl(LocalFrame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
+void continueAfterXFrameOptionsDenied(LocalFrame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
 {
-    didReceiveResourceResponseButCanceledImpl(frame, loader, identifier, r);
+    didReceiveResourceResponseButCanceled(frame, loader, identifier, r);
 }
 
-void continueWithPolicyIgnoreImpl(LocalFrame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
+void continueWithPolicyIgnore(LocalFrame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
 {
-    didReceiveResourceResponseButCanceledImpl(frame, loader, identifier, r);
+    didReceiveResourceResponseButCanceled(frame, loader, identifier, r);
 }
 
-void removedResourceFromMemoryCacheImpl(Resource* cachedResource)
+void removedResourceFromMemoryCache(Resource* cachedResource)
 {
     ASSERT(isMainThread());
     for (InstrumentingAgents* instrumentingAgents: instrumentingAgentsSet()) {
@@ -142,10 +144,12 @@
     }
 }
 
-bool collectingHTMLParseErrorsImpl(InstrumentingAgents* instrumentingAgents)
+bool collectingHTMLParseErrors(Document* document)
 {
     ASSERT(isMainThread());
-    return instrumentingAgentsSet().contains(instrumentingAgents);
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsFor(document))
+        return instrumentingAgentsSet().contains(instrumentingAgents);
+    return false;
 }
 
 bool consoleAgentEnabled(ExecutionContext* executionContext)
diff --git a/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.h b/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.h
index a0a4d31d..d566467 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.h
@@ -41,8 +41,6 @@
 class InstrumentingAgents;
 class WorkerGlobalScope;
 
-#define FAST_RETURN_IF_NO_FRONTENDS(value) if (!hasFrontends()) return value;
-
 class CORE_EXPORT InspectorInstrumentationCookie {
     STACK_ALLOCATED();
 public:
diff --git a/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.idl b/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.idl
index d7824ce..565652a 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.idl
+++ b/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.idl
@@ -40,19 +40,13 @@
 *
 * Where:
 *   methodAttributes - optional list of method attributes.
-*       Attributes containing "=" are code generation options:
-*           Inline=Custom - do not generate the public inline method.
-*           Inline=FastReturn - return early from the inline method if there are no frontends.
-*           Inline=Forward - generate a simple forwarding inline method that does not
-                             modify the parameter list (implies Inline=FastReturn)
 *       Attributes without "=" are the names of the agents to be invoked.
 *           Examples: DOM, Page, Debugger.
 *
 *   paramAttr - optional attribute controlling the parameters handling (one attribute per parameter max).
 *       Keep - pass first parameter (used to access the InstrumentingAgents instance) to agents.
-*       FastReturn - return early from the inline method if this parameter is 0/false.
 *
-*   returnValue: C++ return value. Only "void" and "InspectorInstrumentationCookie" are supported.
+*   returnValue: C++ return value. Only "void", "bool" and "InspectorInstrumentationCookie" are supported.
 *
 *   methodName: C++ name for the public instrumentation method and agents methods.
 *
@@ -80,91 +74,91 @@
     [PageRuntime, Page, Animation]
     void didClearDocumentOfWindowObject([Keep] LocalFrame*);
 
-    [DOMDebugger, Inline=FastReturn]
+    [DOMDebugger]
     void willInsertDOMNode([Keep] Node* parent);
 
-    [DOM, DOMDebugger, Inline=FastReturn]
+    [DOM, DOMDebugger]
     void didInsertDOMNode([Keep] Node*);
 
-    [DOMDebugger, DOM, Inline=FastReturn]
+    [DOMDebugger, DOM]
     void willRemoveDOMNode([Keep] Node*);
 
-    [DOMDebugger, DOM, Inline=FastReturn]
+    [DOMDebugger, DOM]
     void willModifyDOMAttr([Keep] Element*, const AtomicString& oldValue, const AtomicString& newValue);
 
-    [DOM, Inline=FastReturn]
+    [DOM]
     void didModifyDOMAttr([Keep] Element*, const QualifiedName& name, const AtomicString& value);
 
-    [DOM, Inline=FastReturn]
+    [DOM]
     void didRemoveDOMAttr([Keep] Element*, const QualifiedName& name);
 
-    [DOM, Inline=FastReturn]
+    [DOM]
     void characterDataModified([Keep] CharacterData*);
 
-    [DOM, DOMDebugger, Inline=FastReturn]
+    [DOM, DOMDebugger]
     void didInvalidateStyleAttr([Keep] Node*);
 
-    [DOM, Inline=FastReturn]
+    [DOM]
     void didPerformElementShadowDistribution([Keep] Element*);
 
     [CSS]
     void documentDetached([Keep] Document*);
 
-    [CSS, Inline=FastReturn]
+    [CSS]
     void activeStyleSheetsUpdated([Keep] Document*);
 
-    [CSS, Inline=FastReturn]
+    [CSS]
     void mediaQueryResultChanged(Document*);
 
-    [DOM, Inline=FastReturn]
+    [DOM]
     void didPushShadowRoot([Keep] Element* host, ShadowRoot*);
 
-    [DOM, Inline=FastReturn]
+    [DOM]
     void willPopShadowRoot([Keep] Element* host, ShadowRoot*);
 
-    [DOMDebugger, Inline=FastReturn]
+    [DOMDebugger]
     void willSendXMLHttpRequest(ExecutionContext*, const String& url);
 
-    [DOMDebugger, Inline=FastReturn]
+    [DOMDebugger]
     void didFireWebGLError(Element*, const String& errorName);
 
-    [DOMDebugger, Inline=FastReturn]
+    [DOMDebugger]
     void didFireWebGLWarning(Element*);
 
-    [DOMDebugger, Inline=FastReturn]
+    [DOMDebugger]
     void didFireWebGLErrorOrWarning(Element*, const String& message);
 
-    [Debugger, Inline=FastReturn]
+    [Debugger]
     InspectorInstrumentationCookie willExecuteScript(ExecutionContext*, int scriptId);
 
-    [Debugger, Inline=FastReturn]
+    [Debugger]
     void didExecuteScript(const InspectorInstrumentationCookie&);
 
-    [DOMDebugger, Inline=FastReturn]
+    [DOMDebugger]
     InspectorInstrumentationCookie willHandleEvent([Keep] EventTarget*, Event*, EventListener* listener, bool useCapture);
 
-    [DOMDebugger, Inline=FastReturn]
+    [DOMDebugger]
     void cancelPauseOnNextStatement(const InspectorInstrumentationCookie&);
 
-    [Page, Inline=FastReturn]
+    [Page]
     void didUpdateLayout(LocalFrame*);
 
-    [Page, Inline=FastReturn]
+    [Page]
     void didResizeMainFrame(LocalFrame*);
 
-    [LayerTree, Inline=FastReturn]
+    [LayerTree]
     void didPaint(LocalFrame*, const GraphicsLayer*, GraphicsContext&, const LayoutRect&);
 
-    [Resource, Inline=FastReturn]
+    [Resource]
     InspectorInstrumentationCookie willRecalculateStyle([Keep] Document*);
 
-    [Resource, Page, Inline=FastReturn]
+    [Resource, Page]
     void didRecalculateStyle(const InspectorInstrumentationCookie&, int elementCount);
 
-    [Resource, Inline=FastReturn]
+    [Resource]
     void didScheduleStyleRecalculation([Keep] Document*);
 
-    [Resource, Inline=FastReturn]
+    [Resource]
     void applyUserAgentOverride(LocalFrame*, String* userAgent);
 
     [Resource]
@@ -179,13 +173,7 @@
     [Resource]
     void didReceiveResourceResponse([Keep] LocalFrame*, unsigned long identifier, DocumentLoader*, const ResourceResponse&, ResourceLoader*);
 
-    [Inline=Forward]
-    void continueAfterXFrameOptionsDenied(LocalFrame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r);
-
-    [Inline=Forward]
-    void continueWithPolicyIgnore(LocalFrame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r);
-
-    [Resource, Inline=FastReturn]
+    [Resource]
     void didReceiveData([Keep] LocalFrame*, unsigned long identifier, const char* data, int dataLength, int encodedDataLength);
 
     [Resource]
@@ -254,7 +242,7 @@
     [Resource, DOM, Page]
     void didCommitLoad([Keep] LocalFrame*, DocumentLoader*);
 
-    [DOM, Inline=FastReturn]
+    [DOM]
     void frameDocumentUpdated([Keep] LocalFrame*);
 
     [Page]
@@ -269,15 +257,12 @@
     [Page, Resource]
     void frameClearedScheduledNavigation([Keep] LocalFrame*);
 
-    [Page, Inline=FastReturn]
+    [Page]
     InspectorInstrumentationCookie willRunJavaScriptDialog(LocalFrame*, const String& message, ChromeClient::DialogType dialogType);
 
-    [Page, Inline=FastReturn]
+    [Page]
     void didRunJavaScriptDialog(const InspectorInstrumentationCookie&, bool result);
 
-    [Inline=Forward]
-    void removedResourceFromMemoryCache(Resource* cachedResource);
-
     [DOMDebugger]
     InspectorInstrumentationCookie allowNativeBreakpoint(ExecutionContext*, const String& name, bool sync);
 
@@ -320,40 +305,40 @@
     [Resource]
     void didReceiveWebSocketFrameError(Document*, unsigned long identifier, const String& errorMessage);
 
-    [ApplicationCache, Inline=FastReturn]
+    [ApplicationCache]
     void networkStateChanged([Keep] LocalFrame*, bool online);
 
-    [ApplicationCache, Inline=FastReturn]
+    [ApplicationCache]
     void updateApplicationCacheStatus([Keep] LocalFrame*);
 
-    [LayerTree, Inline=FastReturn]
+    [LayerTree]
     void layerTreeDidChange(LocalFrame*);
 
-    [DOM, Inline=FastReturn]
+    [DOM]
     void pseudoElementCreated([Keep] PseudoElement*);
 
-    [DOM, Inline=FastReturn]
+    [DOM]
     void pseudoElementDestroyed([Keep] PseudoElement*);
 
-    [Debugger, Inline=FastReturn]
+    [Debugger]
     void asyncTaskScheduled(ExecutionContext*, const String& name, void*);
 
-    [Debugger, Inline=FastReturn]
+    [Debugger]
     void asyncTaskScheduled(ExecutionContext*, const String& name, void*, bool recurring);
 
-    [Debugger, Inline=FastReturn]
+    [Debugger]
     void asyncTaskCanceled(ExecutionContext*, void*);
 
-    [Debugger, Inline=FastReturn]
+    [Debugger]
     void allAsyncTasksCanceled(ExecutionContext*);
 
-    [Animation, Inline=FastReturn]
+    [Animation]
     void didCreateAnimation(Document*, unsigned);
 
-    [Animation, Inline=FastReturn]
+    [Animation]
     void animationPlayStateChanged(Document*, Animation*, Animation::AnimationPlayState oldPlayState, Animation::AnimationPlayState newPlayState);
 
-    [Page, Inline=FastReturn]
+    [Page]
     void windowCreated(LocalFrame* opener, LocalFrame* created);
 }
 
@@ -366,10 +351,10 @@
     [Console]
     void addMessageToConsole(ExecutionContext* context, ConsoleMessage* consoleMessage);
 
-    [Profiler, Inline=FastReturn]
+    [Profiler]
     void consoleProfile([Keep] ExecutionContext* context, const String& title);
 
-    [Profiler, Inline=FastReturn]
+    [Profiler]
     void consoleProfileEnd(ExecutionContext* context, const String& title);
 
     [Console]
@@ -377,12 +362,12 @@
 }
 
 interface InspectorOverrides {
-    [CSS, Inline=FastReturn]
+    [CSS]
     bool forcePseudoState([Keep] Element* element, CSSSelector::PseudoType pseudoState);
 
-    [Worker, Inline=FastReturn]
+    [Worker]
     bool shouldWaitForDebuggerOnWorkerStart(ExecutionContext* context);
 
-    [Resource, Inline=FastReturn]
+    [Resource]
     bool shouldForceCORSPreflight(Document*);
 }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorInstrumentationCustomInl.h b/third_party/WebKit/Source/core/inspector/InspectorInstrumentationCustomInl.h
index 68518ed..31241ae 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorInstrumentationCustomInl.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorInstrumentationCustomInl.h
@@ -37,27 +37,12 @@
 
 namespace InspectorInstrumentation {
 
-bool isDebuggerPausedImpl(InstrumentingAgents*);
-bool collectingHTMLParseErrorsImpl(InstrumentingAgents*);
-CORE_EXPORT void appendAsyncCallStack(ExecutionContext*, ScriptCallStack*);
-
+CORE_EXPORT bool isDebuggerPaused(LocalFrame*);
+CORE_EXPORT bool collectingHTMLParseErrors(Document*);
+CORE_EXPORT void continueAfterXFrameOptionsDenied(LocalFrame*, DocumentLoader*, unsigned long identifier, const ResourceResponse&);
+CORE_EXPORT void continueWithPolicyIgnore(LocalFrame*, DocumentLoader*, unsigned long identifier, const ResourceResponse&);
 CORE_EXPORT bool consoleAgentEnabled(ExecutionContext*);
-
-inline bool isDebuggerPaused(LocalFrame* frame)
-{
-    FAST_RETURN_IF_NO_FRONTENDS(false);
-    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsFor(frame))
-        return isDebuggerPausedImpl(instrumentingAgents);
-    return false;
-}
-
-inline bool collectingHTMLParseErrors(Document* document)
-{
-    FAST_RETURN_IF_NO_FRONTENDS(false);
-    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsFor(document))
-        return collectingHTMLParseErrorsImpl(instrumentingAgents);
-    return false;
-}
+CORE_EXPORT void removedResourceFromMemoryCache(Resource*);
 
 } // namespace InspectorInstrumentation
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index c0aad303..0204a26 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -748,23 +748,13 @@
     return true;
 }
 
-void LayoutObject::markContainerChainForLayout(bool scheduleRelayout)
-{
-    markContainerChainForLayout(scheduleRelayout, nullptr);
-}
-
-void LayoutObject::markContainerChainForLayout(SubtreeLayoutScope* layouter)
-{
-    // When we have a layouter, it means that we're in layout and we're marking
-    // a descendant as needing layout with the intention of visiting it during
-    // this layout. We shouldn't be scheduling it to be laid out later.
-    markContainerChainForLayout(!layouter, layouter);
-}
-
 void LayoutObject::markContainerChainForLayout(bool scheduleRelayout, SubtreeLayoutScope* layouter)
 {
     ASSERT(!isSetNeedsLayoutForbidden());
     ASSERT(!layouter || this != layouter->root());
+    // When we have a layouter, it means that we're in layout and we're marking
+    // a descendant as needing layout with the intention of visiting it during
+    // this layout. We shouldn't be scheduling it to be laid out later.
     ASSERT(!scheduleRelayout || !layouter);
 
     LayoutObject* object = container();
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h
index 69bd973..12791e8 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.h
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -88,6 +88,7 @@
 enum MarkingBehavior {
     MarkOnlyThis,
     MarkContainerChain,
+    MarkContainerChainInLayout,
 };
 
 enum MapCoordinatesMode {
@@ -810,8 +811,7 @@
 
     Element* offsetParent() const;
 
-    void markContainerChainForLayout(bool scheduleRelayout = true);
-    void markContainerChainForLayout(SubtreeLayoutScope*);
+    void markContainerChainForLayout(bool scheduleRelayout = true, SubtreeLayoutScope* = nullptr);
     void setNeedsLayout(LayoutInvalidationReasonForTracing, MarkingBehavior = MarkContainerChain, SubtreeLayoutScope* = nullptr);
     void setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReasonForTracing, MarkingBehavior = MarkContainerChain, SubtreeLayoutScope* = nullptr);
     void clearNeedsLayout();
@@ -1607,8 +1607,6 @@
 
     void setNeedsOverflowRecalcAfterStyleChange();
 
-    void markContainerChainForLayout(bool scheduleRelayout, SubtreeLayoutScope*);
-
     // FIXME: This should be 'markContaingBoxChainForOverflowRecalc when we make LayoutBox
     // recomputeOverflow-capable. crbug.com/437012 and crbug.com/434700.
     inline void markAncestorsForOverflowRecalcIfNeeded();
@@ -2017,8 +2015,8 @@
             TRACE_EVENT_SCOPE_THREAD,
             "data",
             InspectorLayoutInvalidationTrackingEvent::data(this, reason));
-        if (markParents == MarkContainerChain && (!layouter || layouter->root() != this))
-            markContainerChainForLayout(layouter);
+        if (markParents != MarkOnlyThis && (!layouter || layouter->root() != this))
+            markContainerChainForLayout(!layouter && markParents == MarkContainerChain, layouter);
     }
 }
 
@@ -2054,8 +2052,8 @@
     bool alreadyNeededLayout = normalChildNeedsLayout();
     setNormalChildNeedsLayout(true);
     // FIXME: Replace MarkOnlyThis with the SubtreeLayoutScope code path and remove the MarkingBehavior argument entirely.
-    if (!alreadyNeededLayout && markParents == MarkContainerChain && (!layouter || layouter->root() != this))
-        markContainerChainForLayout(layouter);
+    if (!alreadyNeededLayout && markParents != MarkOnlyThis && (!layouter || layouter->root() != this))
+        markContainerChainForLayout(!layouter && markParents == MarkContainerChain, layouter);
 }
 
 inline void LayoutObject::setNeedsPositionedMovementLayout()
diff --git a/third_party/WebKit/Source/core/layout/TextAutosizer.cpp b/third_party/WebKit/Source/core/layout/TextAutosizer.cpp
index 3560c5c..a1477fc 100644
--- a/third_party/WebKit/Source/core/layout/TextAutosizer.cpp
+++ b/third_party/WebKit/Source/core/layout/TextAutosizer.cpp
@@ -996,7 +996,7 @@
         // TODO(kojii): layouter should not be nullptr once all callers are
         // fixed to pass SubtreeLayoutScope.
         DCHECK(!layouter || layoutObject->isDescendantOf(&layouter->root()));
-        layoutObject->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::TextAutosizing, MarkContainerChain, layouter);
+        layoutObject->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::TextAutosizing, MarkContainerChainInLayout, layouter);
         break;
 
     case LayoutNeeded:
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositingInputsUpdater.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositingInputsUpdater.cpp
index c823e20..21452394 100644
--- a/third_party/WebKit/Source/core/layout/compositing/CompositingInputsUpdater.cpp
+++ b/third_party/WebKit/Source/core/layout/compositing/CompositingInputsUpdater.cpp
@@ -36,13 +36,6 @@
     while (current) {
         if (current->style()->position() == FixedPosition) {
             for (current = current->parent(); current && !current->canContainFixedPositionObjects(); current = current->parent()) {
-                // All types of clips apply to fixed-position descendants of other fixed-position elements.
-                // Note: it's unclear whether this is what the spec says. Firefox does not clip, but Chrome does.
-                if (current->style()->position() == FixedPosition && current->hasClipRelatedProperty()) {
-                    ASSERT(current->hasLayer());
-                    return static_cast<const LayoutBoxModelObject*>(current)->layer();
-                }
-
                 // CSS clip applies to fixed position elements even for ancestors that are not what the
                 // fixed element is positioned with respect to.
                 if (current->hasClip()) {
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
index 65f09ba..e6c9e2c3 100644
--- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
@@ -791,7 +791,7 @@
         for (const auto& eventTarget : *targets) {
             EventTarget* target = eventTarget.key;
             Node* node = target->toNode();
-            if (target->toDOMWindow() || node == document || node == document->documentElement() || node == document->body()) {
+            if (target->toLocalDOMWindow() || node == document || node == document->documentElement() || node == document->body()) {
                 if (LayoutViewItem layoutView = document->layoutViewItem()) {
                     layoutView.computeLayerHitTestRects(rects);
                 }
diff --git a/third_party/WebKit/Source/core/paint/NinePieceImageGrid.cpp b/third_party/WebKit/Source/core/paint/NinePieceImageGrid.cpp
index 16c1dad..2980a04 100644
--- a/third_party/WebKit/Source/core/paint/NinePieceImageGrid.cpp
+++ b/third_party/WebKit/Source/core/paint/NinePieceImageGrid.cpp
@@ -226,8 +226,10 @@
     drawInfo.tileRule = { m_horizontalTileRule, m_verticalTileRule };
 }
 
-NinePieceImageGrid::NinePieceDrawInfo NinePieceImageGrid::getNinePieceDrawInfo(NinePiece piece) const
+NinePieceImageGrid::NinePieceDrawInfo NinePieceImageGrid::getNinePieceDrawInfo(NinePiece piece, float imageScaleFactor) const
 {
+    DCHECK_NE(imageScaleFactor, 0);
+
     NinePieceDrawInfo drawInfo;
     drawInfo.isCornerPiece =
         piece == TopLeftPiece || piece == TopRightPiece || piece == BottomLeftPiece || piece == BottomRightPiece;
@@ -239,6 +241,15 @@
     else
         setDrawInfoMiddle(drawInfo);
 
+    if (imageScaleFactor != 1) {
+        // The nine piece grid is computed in unscaled image coordinates but must be drawn using
+        // scaled image coordinates.
+        drawInfo.source.scale(imageScaleFactor);
+
+        // Compensate for source scaling by scaling down the individual tiles.
+        drawInfo.tileScale.scale(1 / imageScaleFactor);
+    }
+
     return drawInfo;
 }
 
diff --git a/third_party/WebKit/Source/core/paint/NinePieceImageGrid.h b/third_party/WebKit/Source/core/paint/NinePieceImageGrid.h
index b23a07b..17f4dbc 100644
--- a/third_party/WebKit/Source/core/paint/NinePieceImageGrid.h
+++ b/third_party/WebKit/Source/core/paint/NinePieceImageGrid.h
@@ -79,7 +79,7 @@
             Image::TileRule vertical;
         } tileRule;
     };
-    NinePieceDrawInfo getNinePieceDrawInfo(NinePiece) const;
+    NinePieceDrawInfo getNinePieceDrawInfo(NinePiece, float) const;
 
     struct Edge {
         DISALLOW_NEW();
diff --git a/third_party/WebKit/Source/core/paint/NinePieceImageGridTest.cpp b/third_party/WebKit/Source/core/paint/NinePieceImageGridTest.cpp
index 5244aab8..ca6a528 100644
--- a/third_party/WebKit/Source/core/paint/NinePieceImageGridTest.cpp
+++ b/third_party/WebKit/Source/core/paint/NinePieceImageGridTest.cpp
@@ -42,7 +42,7 @@
 
     NinePieceImageGrid grid = NinePieceImageGrid(ninePiece, imageSize, borderImageArea, borderWidths);
     for (NinePiece piece = MinPiece; piece < MaxPiece; ++piece) {
-        NinePieceImageGrid::NinePieceDrawInfo drawInfo = grid.getNinePieceDrawInfo(piece);
+        NinePieceImageGrid::NinePieceDrawInfo drawInfo = grid.getNinePieceDrawInfo(piece, 1);
         EXPECT_FALSE(drawInfo.isDrawable);
     }
 }
@@ -60,7 +60,7 @@
 
     NinePieceImageGrid grid = NinePieceImageGrid(ninePiece, imageSize, borderImageArea, borderWidths);
     for (NinePiece piece = MinPiece; piece < MaxPiece; ++piece) {
-        NinePieceImageGrid::NinePieceDrawInfo drawInfo = grid.getNinePieceDrawInfo(piece);
+        NinePieceImageGrid::NinePieceDrawInfo drawInfo = grid.getNinePieceDrawInfo(piece, 1);
         EXPECT_TRUE(drawInfo.isDrawable);
     }
 }
@@ -78,7 +78,7 @@
 
     NinePieceImageGrid grid = NinePieceImageGrid(ninePiece, imageSize, borderImageArea, borderWidths);
     for (NinePiece piece = MinPiece; piece < MaxPiece; ++piece) {
-        NinePieceImageGrid::NinePieceDrawInfo drawInfo = grid.getNinePieceDrawInfo(piece);
+        NinePieceImageGrid::NinePieceDrawInfo drawInfo = grid.getNinePieceDrawInfo(piece, 1);
         if (piece != MiddlePiece)
             EXPECT_TRUE(drawInfo.isDrawable);
         else
@@ -109,7 +109,7 @@
     for (const auto& testCase : testCases) {
         NinePieceImageGrid grid = NinePieceImageGrid(ninePiece, imageSize, borderImageArea, testCase.borderWidths);
         for (NinePiece piece = MinPiece; piece < MaxPiece; ++piece) {
-            NinePieceImageGrid::NinePieceDrawInfo drawInfo = grid.getNinePieceDrawInfo(piece);
+            NinePieceImageGrid::NinePieceDrawInfo drawInfo = grid.getNinePieceDrawInfo(piece, 1);
             if (piece == TopLeftPiece)
                 EXPECT_EQ(drawInfo.isDrawable, testCase.expectedIsDrawable);
         }
@@ -132,7 +132,7 @@
 
     NinePieceImageGrid grid = NinePieceImageGrid(ninePiece, imageSize, borderImageArea, borderWidths);
     for (NinePiece piece = MinPiece; piece < MaxPiece; ++piece) {
-        NinePieceImageGrid::NinePieceDrawInfo drawInfo = grid.getNinePieceDrawInfo(piece);
+        NinePieceImageGrid::NinePieceDrawInfo drawInfo = grid.getNinePieceDrawInfo(piece, 1);
         if (drawInfo.isCornerPiece)
             EXPECT_EQ(drawInfo.destination.size(), FloatSize(50, 50));
         else
@@ -239,7 +239,7 @@
 
         NinePieceImageGrid grid = NinePieceImageGrid(ninePiece, testCase.imageSize, testCase.borderImageArea, testCase.borderWidths);
         for (NinePiece piece = MinPiece; piece < MaxPiece; ++piece) {
-            NinePieceImageGrid::NinePieceDrawInfo drawInfo = grid.getNinePieceDrawInfo(piece);
+            NinePieceImageGrid::NinePieceDrawInfo drawInfo = grid.getNinePieceDrawInfo(piece, 1);
             EXPECT_EQ(testCase.pieces[piece].isDrawable, drawInfo.isDrawable);
             if (!testCase.pieces[piece].isDrawable)
                 continue;
diff --git a/third_party/WebKit/Source/core/paint/NinePieceImagePainter.cpp b/third_party/WebKit/Source/core/paint/NinePieceImagePainter.cpp
index 1bd7430..334f029 100644
--- a/third_party/WebKit/Source/core/paint/NinePieceImagePainter.cpp
+++ b/third_party/WebKit/Source/core/paint/NinePieceImagePainter.cpp
@@ -60,11 +60,7 @@
         InspectorPaintImageEvent::data(m_layoutObject, *styleImage));
 
     for (NinePiece piece = MinPiece; piece < MaxPiece; ++piece) {
-        NinePieceImageGrid::NinePieceDrawInfo drawInfo = grid.getNinePieceDrawInfo(piece);
-
-        // The nine piece grid is computed in unscaled image coordinates but must be drawn using
-        // scaled image coordinates.
-        drawInfo.source.scale(styleImage->imageScaleFactor());
+        NinePieceImageGrid::NinePieceDrawInfo drawInfo = grid.getNinePieceDrawInfo(piece, styleImage->imageScaleFactor());
 
         if (drawInfo.isDrawable) {
             if (drawInfo.isCornerPiece) {
diff --git a/third_party/WebKit/Source/core/streams/ReadableStream.js b/third_party/WebKit/Source/core/streams/ReadableStream.js
index 6252253..414c923 100644
--- a/third_party/WebKit/Source/core/streams/ReadableStream.js
+++ b/third_party/WebKit/Source/core/streams/ReadableStream.js
@@ -487,6 +487,10 @@
     return stream[readableStreamBits] & DISTURBED;
   }
 
+  function SetReadableStreamDisturbed(stream) {
+    return stream[readableStreamBits] |= DISTURBED;
+  }
+
   function IsReadableStreamLocked(stream) {
     return stream[readableStreamReader] !== undefined;
   }
@@ -495,6 +499,18 @@
     return hasOwnProperty(x, readableStreamControllerControlledReadableStream);
   }
 
+  function IsReadableStreamReadable(stream) {
+    return stream[readableStreamState] === STATE_READABLE;
+  }
+
+  function IsReadableStreamClosed(stream) {
+    return stream[readableStreamState] === STATE_CLOSED;
+  }
+
+  function IsReadableStreamErrored(stream) {
+    return stream[readableStreamState] === STATE_ERRORED;
+  }
+
   function IsReadableStreamReader(x) {
     return hasOwnProperty(x, readableStreamReaderOwnerReadableStream);
   }
@@ -784,7 +800,11 @@
   binding.AcquireReadableStreamReader = AcquireReadableStreamReader;
   binding.IsReadableStream = IsReadableStream;
   binding.IsReadableStreamDisturbed = IsReadableStreamDisturbed;
+  binding.SetReadableStreamDisturbed = SetReadableStreamDisturbed;
   binding.IsReadableStreamLocked = IsReadableStreamLocked;
+  binding.IsReadableStreamReadable = IsReadableStreamReadable;
+  binding.IsReadableStreamClosed = IsReadableStreamClosed;
+  binding.IsReadableStreamErrored = IsReadableStreamErrored;
   binding.IsReadableStreamReader = IsReadableStreamReader;
   binding.ReadFromReadableStreamReader = ReadFromReadableStreamReader;
 
diff --git a/third_party/WebKit/Source/core/streams/ReadableStreamOperations.cpp b/third_party/WebKit/Source/core/streams/ReadableStreamOperations.cpp
index 1410d5d..612a1ad4 100644
--- a/third_party/WebKit/Source/core/streams/ReadableStreamOperations.cpp
+++ b/third_party/WebKit/Source/core/streams/ReadableStreamOperations.cpp
@@ -65,6 +65,14 @@
     return V8ScriptRunner::callExtraOrCrash(scriptState, "IsReadableStreamDisturbed", args)->ToBoolean()->Value();
 }
 
+void ReadableStreamOperations::setDisturbed(ScriptState* scriptState, ScriptValue stream)
+{
+    ASSERT(isReadableStream(scriptState, stream));
+
+    v8::Local<v8::Value> args[] = { stream.v8Value() };
+    V8ScriptRunner::callExtraOrCrash(scriptState, "SetReadableStreamDisturbed", args);
+}
+
 bool ReadableStreamOperations::isLocked(ScriptState* scriptState, ScriptValue stream)
 {
     ASSERT(isReadableStream(scriptState, stream));
@@ -73,6 +81,30 @@
     return V8ScriptRunner::callExtraOrCrash(scriptState, "IsReadableStreamLocked", args)->ToBoolean()->Value();
 }
 
+bool ReadableStreamOperations::isReadable(ScriptState* scriptState, ScriptValue stream)
+{
+    ASSERT(isReadableStream(scriptState, stream));
+
+    v8::Local<v8::Value> args[] = { stream.v8Value() };
+    return V8ScriptRunner::callExtraOrCrash(scriptState, "IsReadableStreamReadable", args)->ToBoolean()->Value();
+}
+
+bool ReadableStreamOperations::isClosed(ScriptState* scriptState, ScriptValue stream)
+{
+    ASSERT(isReadableStream(scriptState, stream));
+
+    v8::Local<v8::Value> args[] = { stream.v8Value() };
+    return V8ScriptRunner::callExtraOrCrash(scriptState, "IsReadableStreamClosed", args)->ToBoolean()->Value();
+}
+
+bool ReadableStreamOperations::isErrored(ScriptState* scriptState, ScriptValue stream)
+{
+    ASSERT(isReadableStream(scriptState, stream));
+
+    v8::Local<v8::Value> args[] = { stream.v8Value() };
+    return V8ScriptRunner::callExtraOrCrash(scriptState, "IsReadableStreamErrored", args)->ToBoolean()->Value();
+}
+
 bool ReadableStreamOperations::isReadableStreamReader(ScriptState* scriptState, ScriptValue value)
 {
     ASSERT(!value.isEmpty());
diff --git a/third_party/WebKit/Source/core/streams/ReadableStreamOperations.h b/third_party/WebKit/Source/core/streams/ReadableStreamOperations.h
index 2a0d064..bd885ba6 100644
--- a/third_party/WebKit/Source/core/streams/ReadableStreamOperations.h
+++ b/third_party/WebKit/Source/core/streams/ReadableStreamOperations.h
@@ -43,10 +43,26 @@
     // This function assumes |isReadableStream(stream)|.
     static bool isDisturbed(ScriptState*, ScriptValue stream);
 
+    // SetReadableStreamDisturbed
+    // This function assumes |isReadableStream(stream)|.
+    static void setDisturbed(ScriptState*, ScriptValue stream);
+
     // IsReadableStreamLocked
     // This function assumes |isReadableStream(stream)|.
     static bool isLocked(ScriptState*, ScriptValue stream);
 
+    // IsReadableStreamReadable
+    // This function assumes |isReadableStream(stream)|.
+    static bool isReadable(ScriptState*, ScriptValue stream);
+
+    // IsReadableStreamClosed
+    // This function assumes |isReadableStream(stream)|.
+    static bool isClosed(ScriptState*, ScriptValue stream);
+
+    // IsReadableStreamErrored
+    // This function assumes |isReadableStream(stream)|.
+    static bool isErrored(ScriptState*, ScriptValue stream);
+
     // IsReadableStreamReader
     static bool isReadableStreamReader(ScriptState*, ScriptValue);
 
diff --git a/third_party/WebKit/Source/core/streams/ReadableStreamOperationsTest.cpp b/third_party/WebKit/Source/core/streams/ReadableStreamOperationsTest.cpp
index 7bfa71d..d3b9175 100644
--- a/third_party/WebKit/Source/core/streams/ReadableStreamOperationsTest.cpp
+++ b/third_party/WebKit/Source/core/streams/ReadableStreamOperationsTest.cpp
@@ -334,6 +334,58 @@
     EXPECT_TRUE(it3->isDone());
 }
 
+TEST_F(ReadableStreamOperationsTest, SetDisturbed)
+{
+    ScriptValue stream = evalWithPrintingError("new ReadableStream()");
+    ASSERT_FALSE(stream.isEmpty());
+
+    EXPECT_FALSE(ReadableStreamOperations::isDisturbed(getScriptState(), stream));
+    ReadableStreamOperations::setDisturbed(getScriptState(), stream);
+    EXPECT_TRUE(ReadableStreamOperations::isDisturbed(getScriptState(), stream));
+}
+
+TEST_F(ReadableStreamOperationsTest, IsReadable)
+{
+    ScriptValue readable = evalWithPrintingError("new ReadableStream()");
+    ScriptValue closed = evalWithPrintingError("new ReadableStream({start: c => c.close()})");
+    ScriptValue errored = evalWithPrintingError("new ReadableStream({start: c => c.error()})");
+    ASSERT_FALSE(readable.isEmpty());
+    ASSERT_FALSE(closed.isEmpty());
+    ASSERT_FALSE(errored.isEmpty());
+
+    EXPECT_TRUE(ReadableStreamOperations::isReadable(getScriptState(), readable));
+    EXPECT_FALSE(ReadableStreamOperations::isReadable(getScriptState(), closed));
+    EXPECT_FALSE(ReadableStreamOperations::isReadable(getScriptState(), errored));
+}
+
+TEST_F(ReadableStreamOperationsTest, IsClosed)
+{
+    ScriptValue readable = evalWithPrintingError("new ReadableStream()");
+    ScriptValue closed = evalWithPrintingError("new ReadableStream({start: c => c.close()})");
+    ScriptValue errored = evalWithPrintingError("new ReadableStream({start: c => c.error()})");
+    ASSERT_FALSE(readable.isEmpty());
+    ASSERT_FALSE(closed.isEmpty());
+    ASSERT_FALSE(errored.isEmpty());
+
+    EXPECT_FALSE(ReadableStreamOperations::isClosed(getScriptState(), readable));
+    EXPECT_TRUE(ReadableStreamOperations::isClosed(getScriptState(), closed));
+    EXPECT_FALSE(ReadableStreamOperations::isClosed(getScriptState(), errored));
+}
+
+TEST_F(ReadableStreamOperationsTest, IsErrored)
+{
+    ScriptValue readable = evalWithPrintingError("new ReadableStream()");
+    ScriptValue closed = evalWithPrintingError("new ReadableStream({start: c => c.close()})");
+    ScriptValue errored = evalWithPrintingError("new ReadableStream({start: c => c.error()})");
+    ASSERT_FALSE(readable.isEmpty());
+    ASSERT_FALSE(closed.isEmpty());
+    ASSERT_FALSE(errored.isEmpty());
+
+    EXPECT_FALSE(ReadableStreamOperations::isErrored(getScriptState(), readable));
+    EXPECT_FALSE(ReadableStreamOperations::isErrored(getScriptState(), closed));
+    EXPECT_TRUE(ReadableStreamOperations::isErrored(getScriptState(), errored));
+}
+
 } // namespace
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/text/Character.h b/third_party/WebKit/Source/platform/text/Character.h
index 2f64ac5..5ca5136 100644
--- a/third_party/WebKit/Source/platform/text/Character.h
+++ b/third_party/WebKit/Source/platform/text/Character.h
@@ -112,6 +112,9 @@
         return u_hasBinaryProperty(c, UCHAR_GRAPHEME_EXTEND);
     }
 
+    // Returns true if the character has a Emoji property.
+    // See http://www.unicode.org/Public/emoji/3.0/emoji-data.txt
+    static bool isEmoji(UChar32);
     // Default presentation style according to:
     // http://www.unicode.org/reports/tr51/#Presentation_Style
     static bool isEmojiTextDefault(UChar32);
diff --git a/third_party/WebKit/Source/platform/text/CharacterEmoji.cpp b/third_party/WebKit/Source/platform/text/CharacterEmoji.cpp
index e0fbb83..ab3b981 100644
--- a/third_party/WebKit/Source/platform/text/CharacterEmoji.cpp
+++ b/third_party/WebKit/Source/platform/text/CharacterEmoji.cpp
@@ -84,6 +84,11 @@
     ASSERT(err == U_ZERO_ERROR);
 }
 
+bool Character::isEmoji(UChar32 ch)
+{
+    return Character::isEmojiTextDefault(ch) || Character::isEmojiEmojiDefault(ch);
+}
+
 bool Character::isEmojiTextDefault(UChar32 ch)
 {
     DEFINE_STATIC_LOCAL(icu::UnicodeSet, emojiTextSet, ());
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/bindings/main.py b/third_party/WebKit/Tools/Scripts/webkitpy/bindings/main.py
index 6841f14..5e41836 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/bindings/main.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/bindings/main.py
@@ -69,7 +69,8 @@
     'TestPartialInterface.idl',
     'TestPartialInterface2.idl',
     'TestPartialInterface3.idl',
-    'TestPartialInterface4.idl',
+    'TestInterface2Partial.idl',
+    'TestInterface2Partial2.idl',
 ])
 
 # core/inspector/InspectorInstrumentation.idl is not a valid Blink IDL.
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/repaint_overlay.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/repaint_overlay.py
index 01a413f..d6fd1c2 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/repaint_overlay.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/repaint_overlay.py
@@ -7,7 +7,7 @@
 
 def result_contains_repaint_rects(text):
     return isinstance(text, str) and (
-        re.search('"repaintRects": \[$', text, re.MULTILINE) != None or
+        re.search('"paintInvalidations": \[$', text, re.MULTILINE) is not None or
         text.find('Minimum repaint:') != -1)
 
 
@@ -139,12 +139,12 @@
         context.transform(t[0][0], t[0][1], t[1][0], t[1][1], t[3][0], t[3][1]);
         context.translate(-origin[0], -origin[1]);
     }
-    if (result.repaintRects) {
-        draw_rects(context, result.repaintRects);
-    } else if (result.paintInvalidations) {
+    if (result.paintInvalidations) {
         var rects = [];
-        for (var i = 0; i < result.paintInvalidations.length; ++i)
-            rects.push(result.paintInvalidations[i].rect);
+        for (var i = 0; i < result.paintInvalidations.length; ++i) {
+            if (result.paintInvalidations[i].rect)
+                rects.push(result.paintInvalidations[i].rect);
+        }
         draw_rects(context, rects);
     }
     if (result.children) {
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/repaint_overlay_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/repaint_overlay_unittest.py
index 0c963ea..4157a50 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/repaint_overlay_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/repaint_overlay_unittest.py
@@ -15,9 +15,19 @@
       "bounds": [800.00, 600.00],
       "contentsOpaque": true,
       "drawsContent": true,
-      "repaintRects": [
-        [8, 108, 100, 100],
-        [0, 216, 800, 100]
+      "paintInvalidations": [
+        {
+          "object": "object1",
+          "rect": [8, 108, 100, 100],
+          "reason": "full"
+        }, {
+          "object": "object2",
+          "rect": [0, 216, 800, 100],
+          "reason": "full"
+        }, {
+          "object": "object1",
+          "reason": "location change"
+        }
       ]
     }
   ]
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath
index 125f04e..a6d7e26 100644
--- a/tools/android/eclipse/.classpath
+++ b/tools/android/eclipse/.classpath
@@ -24,8 +24,8 @@
     <classpathentry kind="src" path="base/android/java/src"/>
     <classpathentry kind="src" path="base/android/javatests/src"/>
     <classpathentry kind="src" path="base/test/android/javatests/src"/>
-    <classpathentry kind="src" path="blimp/client/android/java/src"/>
-    <classpathentry kind="src" path="blimp/client/android/javatests/src"/>
+    <classpathentry kind="src" path="blimp/client/app/android/java/src"/>
+    <classpathentry kind="src" path="blimp/client/app/android/javatests/src"/>
     <classpathentry kind="src" path="chrome/android/java/src"/>
     <classpathentry kind="src" path="chrome/android/javatests/src"/>
     <classpathentry kind="src" path="chrome/android/sync_shell/javatests/src"/>
diff --git a/tools/android/loading/controller.py b/tools/android/loading/controller.py
index 5944711b..0511998 100644
--- a/tools/android/loading/controller.py
+++ b/tools/android/loading/controller.py
@@ -215,7 +215,7 @@
     """Overridden connection creation."""
     package_info = OPTIONS.ChromePackage()
     command_line_path = '/data/local/chrome-command-line'
-    self._device.KillAll(package_info.package, quiet=True)
+    self._device.ForceStop(package_info.package)
     if OPTIONS.clear_device_data:
       logging.info('Clear Chrome data')
       self._device.adb.Shell('pm clear ' + package_info.package)
@@ -252,7 +252,7 @@
               time.sleep(self.TIME_TO_IDLE_SECONDS)
             break
       finally:
-        self._device.KillAll(package_info.package, quiet=True)
+        self._device.ForceStop(package_info.package)
 
   def PushBrowserCache(self, cache_path):
     """Override for chrome cache pushing."""
diff --git a/tools/android/loading/loading_trace.py b/tools/android/loading/loading_trace.py
index ff8b8c55..d4139f7 100644
--- a/tools/android/loading/loading_trace.py
+++ b/tools/android/loading/loading_trace.py
@@ -74,7 +74,7 @@
 
   @classmethod
   def RecordUrlNavigation(
-      cls, url, connection, chrome_metadata, categories=None,
+      cls, url, connection, chrome_metadata, additional_categories=None,
       timeout_seconds=devtools_monitor.DEFAULT_TIMEOUT_SECONDS):
     """Create a loading trace by using controller to fetch url.
 
@@ -82,7 +82,8 @@
       url: (str) url to fetch.
       connection: An opened devtools connection.
       chrome_metadata: Dictionary of chrome metadata.
-      categories: TracingTrack categories to capture.
+      additional_categories: ([str] or None) TracingTrack additional categories
+                             to capture.
       timeout_seconds: monitoring connection timeout in seconds.
 
     Returns:
@@ -92,8 +93,7 @@
     request = request_track.RequestTrack(connection)
     trace = tracing.TracingTrack(
         connection,
-        categories=(tracing.DEFAULT_CATEGORIES if categories is None
-                    else categories))
+        additional_categories=additional_categories)
     connection.MonitorUrl(url, timeout_seconds=timeout_seconds)
     return cls(url, chrome_metadata, page, request, trace)
 
diff --git a/tools/android/loading/sandwich_metrics.py b/tools/android/loading/sandwich_metrics.py
index 1a9e96d..98d6317 100644
--- a/tools/android/loading/sandwich_metrics.py
+++ b/tools/android/loading/sandwich_metrics.py
@@ -30,15 +30,8 @@
 
 
 # List of selected trace event categories when running chrome.
-CATEGORIES = [
-    # Need blink network trace events for prefetch_view.PrefetchSimulationView
-    'blink.net',
-
-    # Need to get mark trace events for _GetWebPageTrackedEvents()
-    'blink.user_timing',
-
-    # Need to memory dump trace event for _GetBrowserDumpEvents()
-    'disabled-by-default-memory-infra']
+ADDITIONAL_CATEGORIES = (
+    'disabled-by-default-memory-infra',)  # Used by _GetBrowserDumpEvents()
 
 CSV_FIELD_NAMES = [
     'id',
@@ -145,6 +138,11 @@
   Returns:
     Dictionary with all CSV_FIELD_NAMES's field set (except the 'id').
   """
+  assert all(
+      cat in loading_trace.tracing_track.Categories()
+      for cat in ADDITIONAL_CATEGORIES), (
+          'This trace was not generated with the required set of categories '
+          'to be processed by this script.')
   browser_dump_events = _GetBrowserDumpEvents(loading_trace.tracing_track)
   web_page_tracked_events = _GetWebPageTrackedEvents(
       loading_trace.tracing_track)
diff --git a/tools/android/loading/sandwich_metrics_unittest.py b/tools/android/loading/sandwich_metrics_unittest.py
index 7cbe7951..19764627 100644
--- a/tools/android/loading/sandwich_metrics_unittest.py
+++ b/tools/android/loading/sandwich_metrics_unittest.py
@@ -44,7 +44,9 @@
 
 
 def TracingTrack(events):
-  return tracing.TracingTrack.FromJsonDict({'events': events})
+  return tracing.TracingTrack.FromJsonDict({
+      'events': events,
+      'categories': tracing.INITIAL_CATEGORIES + puller.ADDITIONAL_CATEGORIES})
 
 
 def LoadingTrace(events):
@@ -103,7 +105,7 @@
         {'pid': 354, 'ts': 11000, 'cat': 'whatever0', 'ph': 'R'},
         {'pid': 672, 'ts': 12000, 'cat': _MEM_CAT, 'ph': 'v', 'name': NAME}]
 
-    self.assertTrue(_MEM_CAT in puller.CATEGORIES)
+    self.assertTrue(_MEM_CAT in puller.ADDITIONAL_CATEGORIES)
 
     bump_events = RunHelper(TRACE_EVENTS, 123)
     self.assertEquals(2, len(bump_events))
@@ -124,8 +126,6 @@
       RunHelper(TRACE_EVENTS, 895)
 
   def testGetWebPageTrackedEvents(self):
-    self.assertTrue(_BLINK_CAT in puller.CATEGORIES)
-
     trace_events = puller._GetWebPageTrackedEvents(TracingTrack([
         {'ph': 'R', 'ts':  0000, 'args': {},             'cat': 'whatever',
             'name': _START},
diff --git a/tools/android/loading/sandwich_runner.py b/tools/android/loading/sandwich_runner.py
index ebef772..39bf4d6 100644
--- a/tools/android/loading/sandwich_runner.py
+++ b/tools/android/loading/sandwich_runner.py
@@ -204,14 +204,14 @@
               url=url,
               connection=connection,
               chrome_metadata=self._chrome_ctl.ChromeMetadata(),
-              categories=sandwich_metrics.CATEGORIES,
+              additional_categories=sandwich_metrics.ADDITIONAL_CATEGORIES,
               timeout_seconds=_DEVTOOLS_TIMEOUT)
       else:
         trace = loading_trace.LoadingTrace.RecordUrlNavigation(
             url=url,
             connection=connection,
             chrome_metadata=self._chrome_ctl.ChromeMetadata(),
-            categories=sandwich_metrics.CATEGORIES,
+            additional_categories=sandwich_metrics.ADDITIONAL_CATEGORIES,
             timeout_seconds=_DEVTOOLS_TIMEOUT)
     if run_path is not None:
       trace_path = os.path.join(run_path, 'trace.json')
diff --git a/tools/android/loading/testdata/scanner_vs_parser.trace b/tools/android/loading/testdata/scanner_vs_parser.trace
index 627d1415..75d10a2 100644
--- a/tools/android/loading/testdata/scanner_vs_parser.trace
+++ b/tools/android/loading/testdata/scanner_vs_parser.trace
@@ -52,6 +52,7 @@
     }
   },
   "tracing_track": {
+   "categories": [],
     "events": [
       {
         "args": {
diff --git a/tools/android/loading/tracing.py b/tools/android/loading/tracing.py
index 4891d3e3..c1ecf71 100644
--- a/tools/android/loading/tracing.py
+++ b/tools/android/loading/tracing.py
@@ -12,7 +12,11 @@
 import devtools_monitor
 
 
-DEFAULT_CATEGORIES = None
+_DISABLED_CATEGORIES = ('cc',) # Contains a lot of events, none of which we use.
+INITIAL_CATEGORIES = (
+    'toplevel', 'blink', 'v8', 'java', 'devtools.timeline',
+    'blink.user_timing', 'blink.net') + tuple(
+        '-' + cat for cat in _DISABLED_CATEGORIES)
 
 
 class TracingTrack(devtools_monitor.Track):
@@ -20,16 +24,16 @@
 
   See https://goo.gl/Qabkqk for details on the protocol.
   """
-  def __init__(self, connection,
-               categories=DEFAULT_CATEGORIES,
+  def __init__(self, connection, additional_categories=None,
                fetch_stream=False):
     """Initialize this TracingTrack.
 
     Args:
       connection: a DevToolsConnection.
-      categories: None, or a string, or list of strings, of tracing categories
-        to filter.
-
+      additional_categories: ([str] or None) If set, a list of additional
+                             categories to add. This cannot be used to re-enable
+                             a category which is disabled by default (see
+                             INITIAL_CATEGORIES), nor to disable a category.
       fetch_stream: if true, use a websocket stream to fetch tracing data rather
         than dataCollected events. It appears based on very limited testing that
         a stream is slower than the default reporting as dataCollected events.
@@ -37,10 +41,15 @@
     super(TracingTrack, self).__init__(connection)
     if connection:
       connection.RegisterListener('Tracing.dataCollected', self)
+    extra_categories = additional_categories or []
+    assert not (set(extra_categories) & set(_DISABLED_CATEGORIES)), (
+        'Cannot enable a disabled category')
+    assert not any(cat.startswith('-') for cat in extra_categories), (
+        'Cannot disable a category')
+    self._categories = set(
+        itertools.chain(INITIAL_CATEGORIES, extra_categories))
     params = {}
-    if categories:
-      params['categories'] = (categories if type(categories) is str
-                              else ','.join(categories))
+    params['categories'] = ','.join(self._categories)
     if fetch_stream:
       params['transferMode'] = 'ReturnAsStream'
 
@@ -62,15 +71,9 @@
     # update.
     self._interval_tree = None
 
-  def _GetMainFrameID(self):
-    """Returns the main frame ID."""
-    if not self._main_frame_id:
-      navigation_start_events = [e for e in self.GetEvents()
-          if e.Matches('blink.user_timing', 'navigationStart')]
-      first_event = min(navigation_start_events, key=lambda e: e.start_msec)
-      self._main_frame_id = first_event.args['frame']
-
-    return self._main_frame_id
+  def Categories(self):
+    """Returns the set of categories in this trace."""
+    return self._categories
 
   def GetFirstEventMillis(self):
     """Find the canonical start time for this track.
@@ -110,9 +113,6 @@
     self._IndexEvents()
     return self._interval_tree.EventsAt(msec)
 
-  def ToJsonDict(self):
-    return {'events': [e.ToJsonDict() for e in self._events]}
-
   def Filter(self, pid=None, tid=None, categories=None):
     """Returns a new TracingTrack with a subset of the events.
 
@@ -133,8 +133,15 @@
           events)
     tracing_track = TracingTrack(None)
     tracing_track._events = events
+    tracing_track._categories = self._categories
+    if categories is not None:
+      tracing_track._categories = self._categories.intersection(categories)
     return tracing_track
 
+  def ToJsonDict(self):
+    return {'categories': list(self._categories),
+            'events': [e.ToJsonDict() for e in self._events]}
+
   @classmethod
   def FromJsonDict(cls, json_dict):
     if not json_dict:
@@ -142,6 +149,7 @@
     assert 'events' in json_dict
     events = [Event(e) for e in json_dict['events']]
     tracing_track = TracingTrack(None)
+    tracing_track._categories = set(json_dict.get('categories', []))
     tracing_track._events = events
     tracing_track._base_msec = events[0].start_msec if events else 0
     for e in events[1:]:
@@ -189,6 +197,16 @@
         return event
     return None
 
+  def _GetMainFrameID(self):
+    """Returns the main frame ID."""
+    if not self._main_frame_id:
+      navigation_start_events = [e for e in self.GetEvents()
+          if e.Matches('blink.user_timing', 'navigationStart')]
+      first_event = min(navigation_start_events, key=lambda e: e.start_msec)
+      self._main_frame_id = first_event.args['frame']
+
+    return self._main_frame_id
+
   def _IndexEvents(self, strict=False):
     if self._interval_tree:
       return
diff --git a/tools/android/loading/tracing_unittest.py b/tools/android/loading/tracing_unittest.py
index 0d7ba27e..cce5809 100644
--- a/tools/android/loading/tracing_unittest.py
+++ b/tools/android/loading/tracing_unittest.py
@@ -42,7 +42,7 @@
   def setUp(self):
     self.tree_threshold = _IntervalTree._TRESHOLD
     _IntervalTree._TRESHOLD = 2  # Expose more edge cases in the tree.
-    self.track = TracingTrack(None)
+    self.track = TracingTrack(None, additional_categories=('A', 'B', 'C', 'D'))
 
   def tearDown(self):
     _IntervalTree._TRESHOLD = self.tree_threshold
@@ -357,6 +357,18 @@
     filtered_events = self.track.Filter(categories=set(['B', 'C'])).GetEvents()
     self.assertEquals(3, len(filtered_events))
     self.assertListEqual(tracing_events[1:], filtered_events)
+    self.assertSetEqual(
+        set('A'), self.track.Filter(categories=set('A')).Categories())
+
+  def testAdditionalCategories(self):
+    track = TracingTrack(None, additional_categories=('best-category-ever',))
+    self.assertIn('best-category-ever', track.Categories())
+    # Cannot re-enable a category.
+    with self.assertRaises(AssertionError):
+      TracingTrack(None, additional_categories=('cc',))
+    # Cannot disable categories.
+    with self.assertRaises(AssertionError):
+      TracingTrack(None, additional_categories=('-best-category-ever',))
 
   def _HandleEvents(self, events):
     self.track.Handle('Tracing.dataCollected', {'params': {'value': [
diff --git a/tools/gn/visual_studio_writer.cc b/tools/gn/visual_studio_writer.cc
index 4f92344..14a02cd 100644
--- a/tools/gn/visual_studio_writer.cc
+++ b/tools/gn/visual_studio_writer.cc
@@ -181,7 +181,11 @@
     const std::string& _config_platform)
     : SolutionEntry(_name, _path, _guid),
       label_dir_path(_label_dir_path),
-      config_platform(_config_platform) {}
+      config_platform(_config_platform) {
+  // Make sure all paths use the same drive letter case. This is especially
+  // important when searching for the common path prefix.
+  label_dir_path[0] = base::ToUpperASCII(label_dir_path[0]);
+}
 
 VisualStudioWriter::SolutionProject::~SolutionProject() = default;
 
diff --git a/tools/gn/visual_studio_writer_unittest.cc b/tools/gn/visual_studio_writer_unittest.cc
index 16e327b..f89c1c1 100644
--- a/tools/gn/visual_studio_writer_unittest.cc
+++ b/tools/gn/visual_studio_writer_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "tools/gn/visual_studio_writer.h"
 
+#include "base/strings/string_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "tools/gn/test_with_scope.h"
 #include "tools/gn/visual_studio_utils.h"
@@ -100,11 +101,15 @@
       "bar", path, MakeGuid(path, "project"), MakeTestPath("/foo/bar"),
       "Win32"));
 
+  std::string baz_label_dir_path = MakeTestPath("/foo/bar/baz");
+#if defined(OS_WIN)
+  // Make sure mixed lower and upper-case drive letters are handled properly.
+  baz_label_dir_path[0] = base::ToLowerASCII(baz_label_dir_path[0]);
+#endif
   path = MakeTestPath(
       "/foo/chromium/src/out/Debug/obj/ABS_PATH/C/foo/bar/baz/baz.vcxproj");
   writer.projects_.emplace_back(new VisualStudioWriter::SolutionProject(
-      "baz", path, MakeGuid(path, "project"), MakeTestPath("/foo/bar/baz"),
-      "Win32"));
+      "baz", path, MakeGuid(path, "project"), baz_label_dir_path, "Win32"));
 
   writer.ResolveSolutionFolders();
 
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index ddb181d..91cbf8a9 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -35686,6 +35686,14 @@
   </summary>
 </histogram>
 
+<histogram name="Permissions.Prompt.Shown" enum="PermissionBubbleType">
+  <owner>benwells@chromium.org</owner>
+  <owner>tsergeant@chromium.org</owner>
+  <summary>
+    Tracks how many times permission prompts are shown to users.
+  </summary>
+</histogram>
+
 <histogram name="Permissions.Requested.CrossOrigin" enum="PermissionStatus">
   <owner>keenanb@google.com</owner>
   <owner>jww@chromium.org</owner>
@@ -80105,6 +80113,16 @@
   <int value="4" label="REVOKED"/>
 </enum>
 
+<enum name="PermissionBubbleType" type="int">
+  <int value="0" label="PERMISSION_BUBBLE_UNKNOWN"/>
+  <int value="1" label="PERMISSION_BUBBLE_MULTIPLE"/>
+  <int value="2" label="PERMISSION_BUBBLE_PERMISSION"/>
+  <int value="3" label="PERMISSION_BUBBLE_QUOTA"/>
+  <int value="4" label="PERMISSION_BUBBLE_DOWNLOAD"/>
+  <int value="5" label="PERMISSION_BUBBLE_MEDIA_STREAM"/>
+  <int value="6" label="PERMISSION_BUBBLE_REGISTER_PROTOCOL_HANDLER"/>
+</enum>
+
 <enum name="PermissionStatus" type="int">
   <int value="0" label="PERMISSION_STATUS_GRANTED"/>
   <int value="1" label="PERMISSION_STATUS_DENIED"/>
@@ -80112,7 +80130,7 @@
 </enum>
 
 <enum name="PermissionType" type="int">
-  <int value="0" label="PERMISSION_UNKONWN"/>
+  <int value="0" label="PERMISSION_UNKNOWN"/>
   <int value="1" label="PERMISSION_MIDI_SYSEX"/>
   <int value="2" label="PERMISSION_PUSH_MESSAGING"/>
   <int value="3" label="PERMISSION_NOTIFICATIONS"/>
@@ -88312,19 +88330,6 @@
   <affected-histogram name="PLT.LoadType"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="ContentSettingsTypes">
-  <suffix name="MidiSysEx" label="Midi SysEx permsision actions"/>
-  <suffix name="PushMessaging" label="Push messaging permission actions"/>
-  <suffix name="Notifications" label="Notification permission actions"/>
-  <suffix name="Geolocation" label="Geolocation permission actions"/>
-  <suffix name="ProtectedMedia" label="Protected media permission actions"/>
-  <suffix name="DurableStorage" label="Durable Storage permission actions"/>
-  <affected-histogram name="ContentSettings.PermissionActions"/>
-  <affected-histogram name="ContentSettings.PermissionActionsInsecureOrigin"/>
-  <affected-histogram name="ContentSettings.PermissionActionsSecureOrigin"/>
-  <affected-histogram name="Permissions.Requested.CrossOrigin"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="ContextMenuType" separator=".">
   <suffix name="Link"
       label="The context menu was shown for a (non-image) link"/>
@@ -91669,9 +91674,13 @@
   <suffix name="DurableStorage" label="Durable Storage permission actions"/>
   <suffix name="AudioCapture" label="Microphone permission actions"/>
   <suffix name="VideoCapture" label="Camera permission actions"/>
+  <affected-histogram name="ContentSettings.PermissionActions"/>
+  <affected-histogram name="ContentSettings.PermissionActionsInsecureOrigin"/>
+  <affected-histogram name="ContentSettings.PermissionActionsSecureOrigin"/>
   <affected-histogram name="Permissions.Action"/>
   <affected-histogram name="Permissions.Action.InsecureOrigin"/>
   <affected-histogram name="Permissions.Action.SecureOrigin"/>
+  <affected-histogram name="Permissions.Requested.CrossOrigin"/>
 </histogram_suffixes>
 
 <histogram_suffixes name="PhysicalWebDebugActions" separator=".">
diff --git a/tools/perf/benchmarks/service_worker.py b/tools/perf/benchmarks/service_worker.py
index 8542e54..6cef574c 100644
--- a/tools/perf/benchmarks/service_worker.py
+++ b/tools/perf/benchmarks/service_worker.py
@@ -9,7 +9,6 @@
 from core import perf_benchmark
 
 from telemetry.core import util
-from telemetry.page import action_runner
 from telemetry.page import page_test
 from telemetry.timeline import async_slice as async_slice_module
 from telemetry.timeline import slice as slice_module
@@ -105,12 +104,11 @@
     self._speed_index.Start(page, tab)
 
   def ValidateAndMeasurePage(self, page, tab, results):
-    runner = action_runner.ActionRunner(tab)
     # timeline_controller requires creation of at least a single interaction
     # record. service_worker should be refactored to follow the
     # timeline_based_measurement or it should not re-use timeline_controller
     # logic for start & stop tracing.
-    with runner.CreateInteraction('_DummyInteraction'):
+    with tab.action_runner.CreateInteraction('_DummyInteraction'):
       pass
     tab.WaitForDocumentReadyStateToBeComplete(40)
     self._timeline_controller.Stop(tab, results)
diff --git a/tools/perf/measurements/blink_style.py b/tools/perf/measurements/blink_style.py
index 576c254..886579d 100644
--- a/tools/perf/measurements/blink_style.py
+++ b/tools/perf/measurements/blink_style.py
@@ -6,7 +6,6 @@
 from itertools import starmap
 from telemetry.core import exceptions
 from telemetry.core import util
-from telemetry.page import action_runner
 from telemetry.page import page_test
 from telemetry.value import scalar
 
@@ -30,8 +29,7 @@
       self._controller.CleanUp(platform)
 
   def ValidateAndMeasurePage(self, page, tab, results):
-    runner = action_runner.ActionRunner(tab)
-    with runner.CreateInteraction('wait-for-quiescence'):
+    with tab.action_runner.CreateInteraction('wait-for-quiescence'):
       tab.ExecuteJavaScript('console.time("");')
       try:
         util.WaitFor(tab.HasReachedQuiescence, 15)
diff --git a/tools/perf/measurements/oilpan_gc_times.py b/tools/perf/measurements/oilpan_gc_times.py
index 8bdaf93b..151b0cf 100644
--- a/tools/perf/measurements/oilpan_gc_times.py
+++ b/tools/perf/measurements/oilpan_gc_times.py
@@ -4,7 +4,6 @@
 
 import os
 
-from telemetry.page import action_runner
 from telemetry.page import page_test
 from telemetry.timeline.model import TimelineModel
 from telemetry.timeline import tracing_config
@@ -164,8 +163,7 @@
     self._interaction = None
 
   def DidNavigateToPage(self, page, tab):
-    runner = action_runner.ActionRunner(tab)
-    self._interaction = runner.CreateInteraction(_RUN_SMOOTH_ACTIONS)
+    self._interaction = tab.action_runner.CreateInteraction(_RUN_SMOOTH_ACTIONS)
     self._interaction.Begin()
 
   def ValidateAndMeasurePage(self, page, tab, results):
diff --git a/tools/perf/measurements/timeline_controller.py b/tools/perf/measurements/timeline_controller.py
index a413d83..93f29e37 100644
--- a/tools/perf/measurements/timeline_controller.py
+++ b/tools/perf/measurements/timeline_controller.py
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-from telemetry.page import action_runner
 from telemetry.page import page_test
 from telemetry.timeline.model import TimelineModel
 from telemetry.timeline import tracing_config
@@ -43,9 +42,8 @@
 
   def Start(self, tab):
     # Start the smooth marker for all actions.
-    runner = action_runner.ActionRunner(tab)
     if self._enable_auto_issuing_record:
-      self._interaction = runner.CreateInteraction(
+      self._interaction = tab.action_runner.CreateInteraction(
           RUN_SMOOTH_ACTIONS)
       self._interaction.Begin()
 
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt
index f5df2d9..2996ceb9 100644
--- a/tools/valgrind/memcheck/suppressions.txt
+++ b/tools/valgrind/memcheck/suppressions.txt
@@ -576,12 +576,6 @@
    fun:_ZN4base12_GLOBAL__N_114WorkerPoolImpl8PostTaskERKN15tracked_objects8LocationERKNS_8CallbackIF*
    fun:_ZN4base10WorkerPool8PostTaskERKN15tracked_objects8LocationERKNS_8CallbackIF*
 }
-{
-   bug_341477
-   Memcheck:Leak
-   fun:_Znw*
-   fun:_ZN7options22PasswordManagerHandler20HandlePassword*
-}
 
 
 #-----------------------------------------------------------------------
diff --git a/ui/compositor/test/in_process_context_provider.cc b/ui/compositor/test/in_process_context_provider.cc
index 591eedc3..78953b7 100644
--- a/ui/compositor/test/in_process_context_provider.cc
+++ b/ui/compositor/test/in_process_context_provider.cc
@@ -96,8 +96,6 @@
       return false;
   }
 
-  capabilities_.gpu = context_->GetImplementation()->capabilities();
-
   std::string unique_context_name =
       base::StringPrintf("%s-%p", debug_name_.c_str(), context_.get());
   context_->GetImplementation()->TraceBeginCHROMIUM(
@@ -110,10 +108,9 @@
   context_thread_checker_.DetachFromThread();
 }
 
-cc::ContextProvider::Capabilities
-InProcessContextProvider::ContextCapabilities() {
+gpu::Capabilities InProcessContextProvider::ContextCapabilities() {
   DCHECK(context_thread_checker_.CalledOnValidThread());
-  return capabilities_;
+  return context_->GetImplementation()->capabilities();
 }
 
 gpu::gles2::GLES2Interface* InProcessContextProvider::ContextGL() {
diff --git a/ui/compositor/test/in_process_context_provider.h b/ui/compositor/test/in_process_context_provider.h
index e3dfce15..d1aab9c39 100644
--- a/ui/compositor/test/in_process_context_provider.h
+++ b/ui/compositor/test/in_process_context_provider.h
@@ -49,7 +49,7 @@
   // cc::ContextProvider:
   bool BindToCurrentThread() override;
   void DetachFromThread() override;
-  Capabilities ContextCapabilities() override;
+  gpu::Capabilities ContextCapabilities() override;
   gpu::gles2::GLES2Interface* ContextGL() override;
   gpu::ContextSupport* ContextSupport() override;
   class GrContext* GrContext() override;
@@ -82,7 +82,6 @@
   gpu::ImageFactory* image_factory_;
   gfx::AcceleratedWidget window_;
   std::string debug_name_;
-  cc::ContextProvider::Capabilities capabilities_;
 
   base::Lock context_lock_;