diff --git a/DEPS b/DEPS
index c475edc..3b9e41e 100644
--- a/DEPS
+++ b/DEPS
@@ -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': 'dee2ad3570ce578a81ad73a1acbf4f4c7bf5cdf0',
+  'catapult_revision': '9026a6670297e11f65ca2cb662ae71f94cdf403e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -416,7 +416,7 @@
 
     # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
     'src/third_party/chromite':
-      Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '19dc69036d1af1e6ad00f1993f8c3a2b7a770e3e',
+      Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '07d4626c40a501866d7c01954f8cabef7b50f482',
 
     # Dependency of chromite.git and skia.
     'src/third_party/pyelftools':
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java
index 9b0f2c09..f094c9a 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java
@@ -160,6 +160,16 @@
 
     @MediumTest
     @Feature({"AndroidWebView", "Privacy"})
+    public void testSetSecureCookieForHttpUrl() throws Throwable {
+        String url = "http://www.example.com";
+        String secureUrl = "https://www.example.com";
+        String cookie = "name=test";
+        mCookieManager.setCookie(url, cookie + ";secure");
+        assertEquals(cookie, mCookieManager.getCookie(secureUrl));
+    }
+
+    @MediumTest
+    @Feature({"AndroidWebView", "Privacy"})
     public void testHasCookie() throws Throwable {
         assertFalse(mCookieManager.hasCookies());
         mCookieManager.setCookie("http://www.example.com", "name=test");
diff --git a/android_webview/native/cookie_manager.cc b/android_webview/native/cookie_manager.cc
index fc75336..33c24db6 100644
--- a/android_webview/native/cookie_manager.cc
+++ b/android_webview/native/cookie_manager.cc
@@ -388,12 +388,20 @@
   options.set_include_httponly();
 
   // Log message for catching strict secure cookies related bugs.
-  if (!host.has_scheme() || host.SchemeIs(url::kHttpScheme)) {
+  // TODO(sgurun) temporary. Add UMA stats to monitor, and remove afterwards.
+  if (host.is_valid() &&
+      (!host.has_scheme() || host.SchemeIs(url::kHttpScheme))) {
     net::ParsedCookie parsed_cookie(value);
     if (parsed_cookie.IsValid() && parsed_cookie.IsSecure()) {
       LOG(WARNING) << "Strict Secure Cookie policy does not allow setting a "
                       "secure cookie for "
                    << host.spec();
+      GURL::Replacements replace_host;
+      replace_host.SetSchemeStr("https");
+      GURL new_host = host.ReplaceComponents(replace_host);
+      GetCookieStore()->SetCookieWithOptionsAsync(new_host, value, options,
+                                                  callback);
+      return;
     }
   }
 
diff --git a/ash/devtools/ash_devtools_unittest.cc b/ash/devtools/ash_devtools_unittest.cc
index 5ebb719c..29d7ca1 100644
--- a/ash/devtools/ash_devtools_unittest.cc
+++ b/ash/devtools/ash_devtools_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "ash/devtools/ash_devtools_css_agent.h"
 #include "ash/devtools/ash_devtools_dom_agent.h"
+#include "ash/public/cpp/shell_window_ids.h"
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/shell_port.h"
@@ -176,6 +177,10 @@
                                   ->get_color());
 }
 
+WmWindow* GetPrimaryRootWindow() {
+  return ShellPort::Get()->GetPrimaryRootWindow();
+}
+
 }  // namespace
 
 class AshDevToolsTest : public AshTest {
@@ -346,8 +351,9 @@
   std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
-  WmWindow* parent_window = ShellPort::Get()->GetPrimaryRootWindow();
-  DOM::Node* parent_node = root->getChildren(nullptr)->get(0);
+  WmWindow* root_window = GetPrimaryRootWindow();
+  WmWindow* parent_window = root_window->GetChildren()[0];
+  DOM::Node* parent_node = FindInRoot(parent_window, root.get());
   Array<DOM::Node>* parent_node_children = parent_node->getChildren(nullptr);
   DOM::Node* sibling_node =
       parent_node_children->get(parent_node_children->length() - 1);
@@ -361,10 +367,12 @@
   std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
-  WmWindow* parent_window =
-      ShellPort::Get()->GetPrimaryRootWindow()->GetChildren()[0];
+  WmWindow* root_window = GetPrimaryRootWindow();
+  WmWindow* rotation_window = root_window->GetChildren()[0];
+  WmWindow* parent_window = rotation_window->GetChildren()[0];
   WmWindow* child_window = parent_window->GetChildren()[0];
-  DOM::Node* root_node = root->getChildren(nullptr)->get(0);
+  DOM::Node* root_node =
+      root->getChildren(nullptr)->get(0)->getChildren(nullptr)->get(0);
   DOM::Node* parent_node = root_node->getChildren(nullptr)->get(0);
   DOM::Node* child_node = parent_node->getChildren(nullptr)->get(0);
 
@@ -379,11 +387,14 @@
   std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
-  WmWindow* root_window = ShellPort::Get()->GetPrimaryRootWindow();
-  WmWindow* target_window = root_window->GetChildren()[1];
-  WmWindow* child_window = root_window->GetChildren()[0]->GetChildren()[0];
+  WmWindow* root_window = GetPrimaryRootWindow();
+  WmWindow* rotation_window = root_window->GetChildren()[0];
+  WmWindow* parent_window = rotation_window->GetChildren()[0];
+  WmWindow* target_window = rotation_window->GetChildren()[1];
+  WmWindow* child_window = parent_window->GetChildren()[0];
 
-  DOM::Node* root_node = root->getChildren(nullptr)->get(0);
+  DOM::Node* root_node =
+      root->getChildren(nullptr)->get(0)->getChildren(nullptr)->get(0);
   DOM::Node* parent_node = root_node->getChildren(nullptr)->get(0);
   DOM::Node* target_node = root_node->getChildren(nullptr)->get(1);
   Array<DOM::Node>* target_node_children = target_node->getChildren(nullptr);
@@ -391,6 +402,7 @@
       target_node_children->get(target_node_children->length() - 1);
   DOM::Node* child_node = parent_node->getChildren(nullptr)->get(0);
 
+  Compare(parent_window, parent_node);
   Compare(target_window, target_node);
   Compare(child_window, child_node);
   target_window->AddChild(child_window);
@@ -399,17 +411,18 @@
 }
 
 TEST_F(AshDevToolsTest, WindowReorganizedChildNodeRemovedAndInserted) {
-  WmWindow* root_window = ShellPort::Get()->GetPrimaryRootWindow();
-  WmWindow* target_window = root_window->GetChildren()[1];
-  WmWindow* parent_window = root_window->GetChildren()[0];
+  WmWindow* root_window = GetPrimaryRootWindow();
+  WmWindow* rotation_window = root_window->GetChildren()[0];
+  WmWindow* parent_window = rotation_window->GetChildren()[0];
+  WmWindow* target_window = rotation_window->GetChildren()[1];
   std::unique_ptr<WindowOwner> child_owner(CreateChildWindow(parent_window));
   WmWindow* child_window = child_owner->window();
 
   // Initialize DOMAgent
   std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
-  DOM::Node* root_node = root->getChildren(nullptr)->get(0);
-
+  DOM::Node* root_node =
+      root->getChildren(nullptr)->get(0)->getChildren(nullptr)->get(0);
   DOM::Node* parent_node = root_node->getChildren(nullptr)->get(0);
   DOM::Node* target_node = root_node->getChildren(nullptr)->get(1);
   Array<DOM::Node>* target_node_children = target_node->getChildren(nullptr);
@@ -419,6 +432,7 @@
   DOM::Node* child_node =
       parent_node_children->get(parent_node_children->length() - 1);
 
+  Compare(parent_window, parent_node);
   Compare(target_window, target_node);
   Compare(child_window, child_node);
   parent_window->RemoveChild(child_window);
@@ -432,11 +446,13 @@
   std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
-  WmWindow* parent_window = ShellPort::Get()->GetPrimaryRootWindow();
+  WmWindow* root_window = GetPrimaryRootWindow();
+  WmWindow* parent_window = root_window->GetChildren()[0];
   WmWindow* child_window = parent_window->GetChildren()[0];
   WmWindow* target_window = parent_window->GetChildren()[1];
 
-  DOM::Node* parent_node = root->getChildren(nullptr)->get(0);
+  DOM::Node* parent_node =
+      root->getChildren(nullptr)->get(0)->getChildren(nullptr)->get(0);
   Array<DOM::Node>* parent_node_children = parent_node->getChildren(nullptr);
   DOM::Node* child_node = parent_node_children->get(0);
   DOM::Node* sibling_node = parent_node_children->get(1);
diff --git a/ash/public/cpp/shell_window_ids.h b/ash/public/cpp/shell_window_ids.h
index f5f1fc2..38f2771 100644
--- a/ash/public/cpp/shell_window_ids.h
+++ b/ash/public/cpp/shell_window_ids.h
@@ -17,93 +17,97 @@
 // Used to indicate no shell window id.
 const int32_t kShellWindowId_Invalid = -1;
 
+// The screen rotation container in between root window and its children, used
+// for screen rotation animation.
+const int32_t kShellWindowId_ScreenRotationContainer = 0;
+
 // A higher-level container that holds all of the containers stacked below
 // kShellWindowId_LockScreenContainer.  Only used by PowerButtonController for
 // animating lower-level containers.
-const int32_t kShellWindowId_NonLockScreenContainersContainer = 0;
+const int32_t kShellWindowId_NonLockScreenContainersContainer = 1;
 
 // A higher-level container that holds containers that hold lock-screen
 // windows.  Only used by PowerButtonController for animating lower-level
 // containers.
-const int32_t kShellWindowId_LockScreenContainersContainer = 1;
+const int32_t kShellWindowId_LockScreenContainersContainer = 2;
 
 // A higher-level container that holds containers that hold lock-screen-related
 // windows (which we want to display while the screen is locked; effectively
 // containers stacked above kShellWindowId_LockSystemModalContainer).  Only used
 // by PowerButtonController for animating lower-level containers.
-const int32_t kShellWindowId_LockScreenRelatedContainersContainer = 2;
+const int32_t kShellWindowId_LockScreenRelatedContainersContainer = 3;
 
 // A container used for windows of WINDOW_TYPE_CONTROL that have no parent.
 // This container is not visible.
-const int32_t kShellWindowId_UnparentedControlContainer = 3;
+const int32_t kShellWindowId_UnparentedControlContainer = 4;
 
 // The wallpaper (desktop background) window.
-const int32_t kShellWindowId_WallpaperContainer = 4;
+const int32_t kShellWindowId_WallpaperContainer = 5;
 
 // The virtual keyboard container.
 // NOTE: this is lazily created.
-const int32_t kShellWindowId_VirtualKeyboardContainer = 5;
+const int32_t kShellWindowId_VirtualKeyboardContainer = 6;
 
 // The container for standard top-level windows.
-const int32_t kShellWindowId_DefaultContainer = 6;
+const int32_t kShellWindowId_DefaultContainer = 7;
 
 // The container for top-level windows with the 'always-on-top' flag set.
-const int32_t kShellWindowId_AlwaysOnTopContainer = 7;
+const int32_t kShellWindowId_AlwaysOnTopContainer = 8;
 
 // The container for the shelf.
-const int32_t kShellWindowId_ShelfContainer = 8;
+const int32_t kShellWindowId_ShelfContainer = 9;
 
 // The container for bubbles which float over the shelf.
-const int32_t kShellWindowId_ShelfBubbleContainer = 9;
+const int32_t kShellWindowId_ShelfBubbleContainer = 10;
 
 // The container for panel windows.
-const int32_t kShellWindowId_PanelContainer = 10;
+const int32_t kShellWindowId_PanelContainer = 11;
 
 // The container for the app list.
-const int32_t kShellWindowId_AppListContainer = 11;
+const int32_t kShellWindowId_AppListContainer = 12;
 
 // The container for user-specific modal windows.
-const int32_t kShellWindowId_SystemModalContainer = 12;
+const int32_t kShellWindowId_SystemModalContainer = 13;
 
 // The container for the lock screen wallpaper (lock screen background).
-const int32_t kShellWindowId_LockScreenWallpaperContainer = 13;
+const int32_t kShellWindowId_LockScreenWallpaperContainer = 14;
 
 // The container for the lock screen.
-const int32_t kShellWindowId_LockScreenContainer = 14;
+const int32_t kShellWindowId_LockScreenContainer = 15;
 
 // The container for the lock screen modal windows.
-const int32_t kShellWindowId_LockSystemModalContainer = 15;
+const int32_t kShellWindowId_LockSystemModalContainer = 16;
 
 // The container for the status area.
-const int32_t kShellWindowId_StatusContainer = 16;
+const int32_t kShellWindowId_StatusContainer = 17;
 
 // A parent container that holds the virtual keyboard container and ime windows
 // if any. This is to ensure that the virtual keyboard or ime window is stacked
 // above most containers but below the mouse cursor and the power off animation.
-const int32_t kShellWindowId_ImeWindowParentContainer = 17;
+const int32_t kShellWindowId_ImeWindowParentContainer = 18;
 
 // The container for menus.
-const int32_t kShellWindowId_MenuContainer = 18;
+const int32_t kShellWindowId_MenuContainer = 19;
 
 // The container for drag/drop images and tooltips.
-const int32_t kShellWindowId_DragImageAndTooltipContainer = 19;
+const int32_t kShellWindowId_DragImageAndTooltipContainer = 20;
 
 // The container for bubbles briefly overlaid onscreen to show settings changes
 // (volume, brightness, input method bubbles, etc.).
-const int32_t kShellWindowId_SettingBubbleContainer = 20;
+const int32_t kShellWindowId_SettingBubbleContainer = 21;
 
 // The container for special components overlaid onscreen, such as the
 // region selector for partial screenshots.
-const int32_t kShellWindowId_OverlayContainer = 21;
+const int32_t kShellWindowId_OverlayContainer = 22;
 
 // ID of the window created by PhantomWindowController or DragWindowController.
-const int32_t kShellWindowId_PhantomWindow = 22;
+const int32_t kShellWindowId_PhantomWindow = 23;
 
 // The container for mouse cursor.
-const int32_t kShellWindowId_MouseCursorContainer = 23;
+const int32_t kShellWindowId_MouseCursorContainer = 24;
 
 // The topmost container, used for power off animation.
-const int32_t kShellWindowId_PowerButtonAnimationContainer = 24;
+const int32_t kShellWindowId_PowerButtonAnimationContainer = 25;
 
 const int32_t kShellWindowId_Min = 0;
 const int32_t kShellWindowId_Max = kShellWindowId_PowerButtonAnimationContainer;
@@ -111,31 +115,32 @@
 // A list of all the above valid container IDs. Add any new ID to this list.
 // This list is needed to validate we have no duplicate IDs.
 const int32_t kAllShellContainerIds[] = {
-  kShellWindowId_NonLockScreenContainersContainer,
-  kShellWindowId_LockScreenContainersContainer,
-  kShellWindowId_LockScreenRelatedContainersContainer,
-  kShellWindowId_UnparentedControlContainer,
-  kShellWindowId_WallpaperContainer,
-  kShellWindowId_VirtualKeyboardContainer,
-  kShellWindowId_DefaultContainer,
-  kShellWindowId_AlwaysOnTopContainer,
-  kShellWindowId_ShelfContainer,
-  kShellWindowId_ShelfBubbleContainer,
-  kShellWindowId_PanelContainer,
-  kShellWindowId_AppListContainer,
-  kShellWindowId_SystemModalContainer,
-  kShellWindowId_LockScreenWallpaperContainer,
-  kShellWindowId_LockScreenContainer,
-  kShellWindowId_LockSystemModalContainer,
-  kShellWindowId_StatusContainer,
-  kShellWindowId_ImeWindowParentContainer,
-  kShellWindowId_MenuContainer,
-  kShellWindowId_DragImageAndTooltipContainer,
-  kShellWindowId_SettingBubbleContainer,
-  kShellWindowId_OverlayContainer,
-  kShellWindowId_PhantomWindow,
-  kShellWindowId_MouseCursorContainer,
-  kShellWindowId_PowerButtonAnimationContainer,
+    kShellWindowId_ScreenRotationContainer,
+    kShellWindowId_NonLockScreenContainersContainer,
+    kShellWindowId_LockScreenContainersContainer,
+    kShellWindowId_LockScreenRelatedContainersContainer,
+    kShellWindowId_UnparentedControlContainer,
+    kShellWindowId_WallpaperContainer,
+    kShellWindowId_VirtualKeyboardContainer,
+    kShellWindowId_DefaultContainer,
+    kShellWindowId_AlwaysOnTopContainer,
+    kShellWindowId_ShelfContainer,
+    kShellWindowId_ShelfBubbleContainer,
+    kShellWindowId_PanelContainer,
+    kShellWindowId_AppListContainer,
+    kShellWindowId_SystemModalContainer,
+    kShellWindowId_LockScreenWallpaperContainer,
+    kShellWindowId_LockScreenContainer,
+    kShellWindowId_LockSystemModalContainer,
+    kShellWindowId_StatusContainer,
+    kShellWindowId_ImeWindowParentContainer,
+    kShellWindowId_MenuContainer,
+    kShellWindowId_DragImageAndTooltipContainer,
+    kShellWindowId_SettingBubbleContainer,
+    kShellWindowId_OverlayContainer,
+    kShellWindowId_PhantomWindow,
+    kShellWindowId_MouseCursorContainer,
+    kShellWindowId_PowerButtonAnimationContainer,
 };
 
 // These are the list of container ids of containers which may contain windows
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index fa9d48b..aceb5340 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -867,37 +867,46 @@
 
 void RootWindowController::CreateContainers() {
   WmWindow* root = GetWindow();
+  // For screen rotation animation: add a NOT_DRAWN layer in between the
+  // root_window's layer and its current children so that we only need to
+  // initiate two LayerAnimationSequences. One for the new layers and one for
+  // the old layers.
+  WmWindow* screen_rotation_container = CreateContainer(
+      kShellWindowId_ScreenRotationContainer, "ScreenRotationContainer", root);
+
   // These containers are just used by PowerButtonController to animate groups
   // of containers simultaneously without messing up the current transformations
-  // on those containers. These are direct children of the root window; all of
-  // the other containers are their children.
+  // on those containers. These are direct children of the
+  // screen_rotation_container window; all of the other containers are their
+  // children.
 
   // The wallpaper container is not part of the lock animation, so it is not
   // included in those animate groups. When the screen is locked, the wallpaper
   // is moved to the lock screen wallpaper container (and moved back on unlock).
   // Ensure that there's an opaque layer occluding the non-lock-screen layers.
-  WmWindow* wallpaper_container = CreateContainer(
-      kShellWindowId_WallpaperContainer, "WallpaperContainer", root);
+  WmWindow* wallpaper_container =
+      CreateContainer(kShellWindowId_WallpaperContainer, "WallpaperContainer",
+                      screen_rotation_container);
   wallpaper_container->SetChildWindowVisibilityChangesAnimated();
 
-  WmWindow* non_lock_screen_containers =
-      CreateContainer(kShellWindowId_NonLockScreenContainersContainer,
-                      "NonLockScreenContainersContainer", root);
+  WmWindow* non_lock_screen_containers = CreateContainer(
+      kShellWindowId_NonLockScreenContainersContainer,
+      "NonLockScreenContainersContainer", screen_rotation_container);
   // Clip all windows inside this container, as half pixel of the window's
   // texture may become visible when the screen is scaled. crbug.com/368591.
   non_lock_screen_containers->SetMasksToBounds(true);
 
-  WmWindow* lock_wallpaper_containers =
-      CreateContainer(kShellWindowId_LockScreenWallpaperContainer,
-                      "LockScreenWallpaperContainer", root);
+  WmWindow* lock_wallpaper_containers = CreateContainer(
+      kShellWindowId_LockScreenWallpaperContainer,
+      "LockScreenWallpaperContainer", screen_rotation_container);
   lock_wallpaper_containers->SetChildWindowVisibilityChangesAnimated();
 
-  WmWindow* lock_screen_containers =
-      CreateContainer(kShellWindowId_LockScreenContainersContainer,
-                      "LockScreenContainersContainer", root);
-  WmWindow* lock_screen_related_containers =
-      CreateContainer(kShellWindowId_LockScreenRelatedContainersContainer,
-                      "LockScreenRelatedContainersContainer", root);
+  WmWindow* lock_screen_containers = CreateContainer(
+      kShellWindowId_LockScreenContainersContainer,
+      "LockScreenContainersContainer", screen_rotation_container);
+  WmWindow* lock_screen_related_containers = CreateContainer(
+      kShellWindowId_LockScreenRelatedContainersContainer,
+      "LockScreenRelatedContainersContainer", screen_rotation_container);
 
   CreateContainer(kShellWindowId_UnparentedControlContainer,
                   "UnparentedControlContainer", non_lock_screen_containers);
@@ -1024,13 +1033,14 @@
   overlay_container->SetBoundsInScreenBehaviorForChildren(
       WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES);
 
-  WmWindow* mouse_cursor_container = CreateContainer(
-      kShellWindowId_MouseCursorContainer, "MouseCursorContainer", root);
+  WmWindow* mouse_cursor_container =
+      CreateContainer(kShellWindowId_MouseCursorContainer,
+                      "MouseCursorContainer", screen_rotation_container);
   mouse_cursor_container->SetBoundsInScreenBehaviorForChildren(
       WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES);
 
   CreateContainer(kShellWindowId_PowerButtonAnimationContainer,
-                  "PowerButtonAnimationContainer", root);
+                  "PowerButtonAnimationContainer", screen_rotation_container);
 }
 
 void RootWindowController::CreateSystemWallpaper(
diff --git a/ash/rotator/screen_rotation_animator.cc b/ash/rotator/screen_rotation_animator.cc
index 279238d..f1c51a4 100644
--- a/ash/rotator/screen_rotation_animator.cc
+++ b/ash/rotator/screen_rotation_animator.cc
@@ -10,6 +10,7 @@
 
 #include "ash/ash_switches.h"
 #include "ash/display/window_tree_host_manager.h"
+#include "ash/public/cpp/shell_window_ids.h"
 #include "ash/rotator/screen_rotation_animation.h"
 #include "ash/rotator/screen_rotation_animator_observer.h"
 #include "ash/shell.h"
@@ -52,14 +53,6 @@
 const int kCounterClockWiseRotationFactor = 1;
 const int kClockWiseRotationFactor = -1;
 
-// Aborts the active animations of the layer, and recurses upon its child
-// layers.
-void AbortAnimations(ui::Layer* layer) {
-  for (ui::Layer* child_layer : layer->children())
-    AbortAnimations(child_layer);
-  layer->GetAnimator()->AbortAllAnimations();
-}
-
 display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) {
   return Shell::Get()
       ->display_manager()
@@ -317,31 +310,25 @@
   const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
                                       rotated_screen_bounds.height() / 2);
 
-  // We must animate each non-cloned child layer individually because the cloned
-  // layer was added as a child to |root_window|'s layer so that it will be
-  // rendered.
-  // TODO(bruthig): Add a NOT_DRAWN layer in between the root_window's layer and
-  // its current children so that we only need to initiate two
-  // LayerAnimationSequences. One for the new layers and one for the old layer.
-  for (ui::Layer* child_layer : root_window->layer()->children()) {
-    // Skip the cloned layer because it has a different animation.
-    if (child_layer == old_root_layer)
-      continue;
+  ui::Layer* screen_rotation_container_layer =
+      root_window->GetChildById(kShellWindowId_ScreenRotationContainer)
+          ->layer();
+  std::unique_ptr<ScreenRotationAnimation> current_layer_screen_rotation =
+      base::MakeUnique<ScreenRotationAnimation>(
+          screen_rotation_container_layer, kRotationDegrees * rotation_factor,
+          0 /* end_degrees */, screen_rotation_container_layer->opacity(),
+          screen_rotation_container_layer->opacity() /* target_opacity */,
+          pivot, duration, tween_type);
 
-    std::unique_ptr<ScreenRotationAnimation> screen_rotation =
-        base::MakeUnique<ScreenRotationAnimation>(
-            child_layer, kRotationDegrees * rotation_factor,
-            0 /* end_degrees */, child_layer->opacity(),
-            1.0f /* target_opacity */, pivot, duration, tween_type);
-
-    ui::LayerAnimator* animator = child_layer->GetAnimator();
-    animator->set_preemption_strategy(
-        ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
-    std::unique_ptr<ui::LayerAnimationSequence> animation_sequence =
-        base::MakeUnique<ui::LayerAnimationSequence>(
-            std::move(screen_rotation));
-    animator->StartAnimation(animation_sequence.release());
-  }
+  ui::LayerAnimator* current_layer_animator =
+      screen_rotation_container_layer->GetAnimator();
+  current_layer_animator->set_preemption_strategy(
+      ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
+  std::unique_ptr<ui::LayerAnimationSequence> current_layer_animation_sequence =
+      base::MakeUnique<ui::LayerAnimationSequence>(
+          std::move(current_layer_screen_rotation));
+  current_layer_animator->StartAnimation(
+      current_layer_animation_sequence.release());
 
   // The old layer will also be transformed into the new orientation. We will
   // translate it so that the old layer's center point aligns with the new
@@ -353,7 +340,7 @@
       (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2);
   old_root_layer->SetTransform(translate_transform);
 
-  std::unique_ptr<ScreenRotationAnimation> screen_rotation =
+  std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation =
       base::MakeUnique<ScreenRotationAnimation>(
           old_root_layer, old_layer_initial_rotation_degrees * rotation_factor,
           (old_layer_initial_rotation_degrees - kRotationDegrees) *
@@ -361,20 +348,25 @@
           old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration,
           tween_type);
 
-  ui::LayerAnimator* animator = old_root_layer->GetAnimator();
-  animator->set_preemption_strategy(
+  ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator();
+  old_layer_animator->set_preemption_strategy(
       ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
-  std::unique_ptr<ui::LayerAnimationSequence> animation_sequence =
-      base::MakeUnique<ui::LayerAnimationSequence>(std::move(screen_rotation));
+  std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence =
+      base::MakeUnique<ui::LayerAnimationSequence>(
+          std::move(old_layer_screen_rotation));
   // Add an observer so that the cloned layers can be cleaned up with the
   // animation completes/aborts.
-  animation_sequence->AddObserver(old_layer_cleanup_observer.release());
+  old_layer_animation_sequence->AddObserver(
+      old_layer_cleanup_observer.release());
   // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to
   // control the animation.
   if (disable_animation_timers_for_test_)
-    animator->set_disable_timer_for_test(true);
-  animation_sequence->SetAnimationMetricsReporter(metrics_reporter_.get());
-  animator->StartAnimation(animation_sequence.release());
+    old_layer_animator->set_disable_timer_for_test(true);
+  old_layer_animation_sequence->SetAnimationMetricsReporter(
+      metrics_reporter_.get());
+  old_layer_animator->StartAnimation(old_layer_animation_sequence.release());
+
+  rotation_request.reset();
 }
 
 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation,
@@ -434,15 +426,13 @@
 }
 
 void ScreenRotationAnimator::StopAnimating() {
-  aura::Window* root_window = GetRootWindow(display_id_);
-  for (ui::Layer* child_layer : root_window->layer()->children()) {
-    if (child_layer == old_layer_tree_owner_->root())
-      continue;
-
-    child_layer->GetAnimator()->StopAnimating();
-  }
-
-  old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
+  GetRootWindow(display_id_)
+      ->GetChildById(kShellWindowId_ScreenRotationContainer)
+      ->layer()
+      ->GetAnimator()
+      ->StopAnimating();
+  if (old_layer_tree_owner_)
+    old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
 }
 
 }  // namespace ash
diff --git a/ash/wm/root_window_layout_manager.cc b/ash/wm/root_window_layout_manager.cc
index aa7301d..40b4df6 100644
--- a/ash/wm/root_window_layout_manager.cc
+++ b/ash/wm/root_window_layout_manager.cc
@@ -9,6 +9,34 @@
 #include "ui/aura/window_tracker.h"
 
 namespace ash {
+
+namespace {
+
+// Resize all container windows that RootWindowLayoutManager is responsible for.
+// That includes all container windows up to three depth except that top level
+// window which has a delegate. We cannot simply check top level window, because
+// we need to skip other windows without a delegate, such as ScreenDimmer
+// windows.
+// TODO(wutao): The above logic is error prone. Consider using a Shell window id
+// to indentify such a container.
+void ResizeWindow(const aura::Window::Windows& children,
+                  const gfx::Rect& fullscreen_bounds,
+                  int depth) {
+  if (depth > 2)
+    return;
+  const int child_depth = depth + 1;
+  aura::WindowTracker children_tracker(children);
+  while (!children_tracker.windows().empty()) {
+    aura::Window* child = children_tracker.Pop();
+    if (child->GetToplevelWindow())
+      continue;
+    child->SetBounds(fullscreen_bounds);
+    ResizeWindow(child->children(), fullscreen_bounds, child_depth);
+  }
+}
+
+}  // namespace
+
 namespace wm {
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -23,26 +51,8 @@
 // RootWindowLayoutManager, aura::LayoutManager implementation:
 
 void RootWindowLayoutManager::OnWindowResized() {
-  const gfx::Rect fullscreen_bounds = gfx::Rect(owner_->GetBounds().size());
-
-  // Resize both our immediate children (the containers-of-containers animated
-  // by PowerButtonController) and their children (the actual containers).
-  aura::WindowTracker children_tracker(owner_->aura_window()->children());
-  while (!children_tracker.windows().empty()) {
-    aura::Window* child = children_tracker.Pop();
-    // Skip descendants of top-level windows, i.e. only resize containers and
-    // other windows without a delegate, such as ScreenDimmer windows.
-    if (child->GetToplevelWindow())
-      continue;
-
-    child->SetBounds(fullscreen_bounds);
-    aura::WindowTracker grandchildren_tracker(child->children());
-    while (!grandchildren_tracker.windows().empty()) {
-      child = grandchildren_tracker.Pop();
-      if (!child->GetToplevelWindow())
-        child->SetBounds(fullscreen_bounds);
-    }
-  }
+  ResizeWindow(owner_->aura_window()->children(),
+               gfx::Rect(owner_->GetBounds().size()), 0);
 }
 
 void RootWindowLayoutManager::OnWindowAddedToLayout(WmWindow* child) {}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index c62ac3a..f7918544 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -647,8 +647,6 @@
     "test/test_occlusion_tracker.h",
     "test/test_shared_bitmap_manager.cc",
     "test/test_shared_bitmap_manager.h",
-    "test/test_skcanvas.cc",
-    "test/test_skcanvas.h",
     "test/test_task_graph_runner.cc",
     "test/test_task_graph_runner.h",
     "test/test_texture.cc",
@@ -766,7 +764,6 @@
     "output/texture_mailbox_deleter_unittest.cc",
     "paint/discardable_image_map_unittest.cc",
     "paint/display_item_list_unittest.cc",
-    "paint/paint_op_buffer_unittest.cc",
     "quads/draw_polygon_unittest.cc",
     "quads/draw_quad_unittest.cc",
     "quads/nine_patch_generator_unittest.cc",
@@ -937,7 +934,6 @@
     "//cc/ipc",
     "//cc/ipc:interfaces",
     "//cc/paint",
-    "//cc/paint",
     "//cc/surfaces",
     "//cc/surfaces:surface_id",
     "//gpu",
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn
index 11f9fdac..3af5dee 100644
--- a/cc/paint/BUILD.gn
+++ b/cc/paint/BUILD.gn
@@ -32,19 +32,13 @@
     "paint_canvas.cc",
     "paint_canvas.h",
     "paint_export.h",
-    "paint_flags.cc",
     "paint_flags.h",
     "paint_image.cc",
     "paint_image.h",
-    "paint_op_buffer.cc",
-    "paint_op_buffer.h",
-    "paint_record.cc",
     "paint_record.h",
     "paint_recorder.cc",
     "paint_recorder.h",
     "paint_shader.h",
-    "record_paint_canvas.cc",
-    "record_paint_canvas.h",
     "skia_paint_canvas.cc",
     "skia_paint_canvas.h",
     "transform_display_item.cc",
diff --git a/cc/paint/display_item_list.cc b/cc/paint/display_item_list.cc
index c1b069548..8359948 100644
--- a/cc/paint/display_item_list.cc
+++ b/cc/paint/display_item_list.cc
@@ -100,13 +100,9 @@
       if (canvas->quickReject(item.picture->cullRect()))
         break;
 
-      // TODO(enne): Maybe the PaintRecord itself could know whether this
-      // was needed?  It's not clear whether these save/restore semantics
-      // that SkPicture handles during playback are things that should be
-      // kept around.
-      canvas->save();
+      // SkPicture always does a wrapping save/restore on the canvas, so it is
+      // not necessary here.
       item.picture->playback(canvas, callback);
-      canvas->restore();
       break;
     }
     case DisplayItem::FLOAT_CLIP: {
@@ -180,33 +176,6 @@
   canvas->restore();
 }
 
-// Atttempts to merge a CompositingDisplayItem and DrawingDisplayItem
-// into a single "draw with alpha".  This function returns true if
-// it was successful.  If false, then the caller is responsible for
-// drawing these items.  This is a DisplayItemList version of the
-// SkRecord optimization SkRecordNoopSaveLayerDrawRestores.
-static bool MergeAndDrawIfPossible(const CompositingDisplayItem& save_item,
-                                   const DrawingDisplayItem& draw_item,
-                                   SkCanvas* canvas) {
-  if (save_item.color_filter)
-    return false;
-  if (save_item.xfermode != SkBlendMode::kSrcOver)
-    return false;
-  // TODO(enne): I believe that lcd_text_requires_opaque_layer is not
-  // relevant here and that lcd text is preserved post merge, but I haven't
-  // tested that.
-  const PaintRecord* record = draw_item.picture.get();
-  if (record->approximateOpCount() != 1)
-    return false;
-
-  const PaintOp* op = record->GetFirstOp();
-  if (!op->IsDrawOp())
-    return false;
-
-  op->RasterWithAlpha(canvas, save_item.alpha);
-  return true;
-}
-
 void DisplayItemList::Raster(SkCanvas* canvas,
                              SkPicture::AbortCallback* callback) const {
   gfx::Rect canvas_playback_rect;
@@ -215,33 +184,14 @@
 
   std::vector<size_t> indices;
   rtree_.Search(canvas_playback_rect, &indices);
-  for (size_t i = 0; i < indices.size(); ++i) {
+  for (size_t index : indices) {
+    RasterItem(items_[index], canvas, callback);
+
     // We use a callback during solid color analysis on the compositor thread to
     // break out early. Since we're handling a sequence of pictures via rtree
     // query results ourselves, we have to respect the callback and early out.
     if (callback && callback->abort())
       break;
-
-    const DisplayItem& item = items_[indices[i]];
-    // Optimize empty begin/end compositing and merge begin/draw/end compositing
-    // where possible.
-    // TODO(enne): remove empty clips here too?
-    // TODO(enne): does this happen recursively? Or is this good enough?
-    if (i < indices.size() - 2 && item.type == DisplayItem::COMPOSITING) {
-      const DisplayItem& second = items_[indices[i + 1]];
-      const DisplayItem& third = items_[indices[i + 2]];
-      if (second.type == DisplayItem::DRAWING &&
-          third.type == DisplayItem::END_COMPOSITING) {
-        if (MergeAndDrawIfPossible(
-                static_cast<const CompositingDisplayItem&>(item),
-                static_cast<const DrawingDisplayItem&>(second), canvas)) {
-          i += 2;
-          continue;
-        }
-      }
-    }
-
-    RasterItem(item, canvas, callback);
   }
 }
 
diff --git a/cc/paint/display_item_list_unittest.cc b/cc/paint/display_item_list_unittest.cc
index b166229c6..f1b9e75 100644
--- a/cc/paint/display_item_list_unittest.cc
+++ b/cc/paint/display_item_list_unittest.cc
@@ -17,17 +17,16 @@
 #include "cc/paint/compositing_display_item.h"
 #include "cc/paint/drawing_display_item.h"
 #include "cc/paint/filter_display_item.h"
+
 #include "cc/paint/float_clip_display_item.h"
 #include "cc/paint/paint_canvas.h"
 #include "cc/paint/paint_flags.h"
 #include "cc/paint/paint_record.h"
 #include "cc/paint/paint_recorder.h"
-#include "cc/paint/skia_paint_canvas.h"
 #include "cc/paint/transform_display_item.h"
 #include "cc/test/geometry_test_utils.h"
 #include "cc/test/pixel_test_utils.h"
 #include "cc/test/skia_common.h"
-#include "cc/test/test_skcanvas.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -81,19 +80,6 @@
   return recorder.finishRecordingAsPicture();
 }
 
-sk_sp<const PaintRecord> CreateRectPictureWithAlpha(const gfx::Rect& bounds,
-                                                    uint8_t alpha) {
-  PaintRecorder recorder;
-  PaintCanvas* canvas =
-      recorder.beginRecording(bounds.width(), bounds.height());
-  PaintFlags flags;
-  flags.setAlpha(alpha);
-  canvas->drawRect(
-      SkRect::MakeXYWH(bounds.x(), bounds.y(), bounds.width(), bounds.height()),
-      flags);
-  return recorder.finishRecordingAsPicture();
-}
-
 void AppendFirstSerializationTestPicture(scoped_refptr<DisplayItemList> list,
                                          const gfx::Size& layer_size) {
   gfx::PointF offset(2.f, 3.f);
@@ -718,110 +704,4 @@
   EXPECT_RECT_EQ(filter_bounds, list->VisualRectForTesting(3));
 }
 
-// Verify that raster time optimizations for compositing item / draw single op /
-// end compositing item can be collapsed together into a single draw op
-// with the opacity from the compositing item folded in.
-TEST(DisplayItemListTest, SaveDrawRestore) {
-  auto list = make_scoped_refptr(new DisplayItemList);
-
-  list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>(
-      80, SkBlendMode::kSrcOver, nullptr, nullptr, false);
-  list->CreateAndAppendDrawingItem<DrawingDisplayItem>(
-      kVisualRect, CreateRectPictureWithAlpha(kVisualRect, 40));
-  list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>();
-  list->Finalize();
-
-  SaveCountingCanvas canvas;
-  list->Raster(&canvas, nullptr);
-
-  EXPECT_EQ(0, canvas.save_count_);
-  EXPECT_EQ(0, canvas.restore_count_);
-  EXPECT_EQ(gfx::RectToSkRect(kVisualRect), canvas.draw_rect_);
-
-  float expected_alpha = 80 * 40 / 255.f;
-  EXPECT_LE(std::abs(expected_alpha - canvas.paint_.getAlpha()), 1.f);
-}
-
-// Verify that compositing item / end compositing item is a noop.
-// Here we're testing that Skia does an optimization that skips
-// save/restore with nothing in between.  If skia stops doing this
-// then we should reimplement this optimization in display list raster.
-TEST(DisplayItemListTest, SaveRestoreNoops) {
-  auto list = make_scoped_refptr(new DisplayItemList);
-
-  list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>(
-      80, SkBlendMode::kSrcOver, nullptr, nullptr, false);
-  list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>();
-  list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>(
-      255, SkBlendMode::kSrcOver, nullptr, nullptr, false);
-  list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>();
-  list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>(
-      255, SkBlendMode::kSrc, nullptr, nullptr, false);
-  list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>();
-  list->Finalize();
-
-  SaveCountingCanvas canvas;
-  list->Raster(&canvas, nullptr);
-
-  EXPECT_EQ(0, canvas.save_count_);
-  EXPECT_EQ(0, canvas.restore_count_);
-}
-
-// The same as SaveDrawRestore, but with save flags that prevent the
-// optimization.
-TEST(DisplayItemListTest, SaveDrawRestoreFail_BadSaveFlags) {
-  auto list = make_scoped_refptr(new DisplayItemList);
-
-  // Use a blend mode that's not compatible with the SaveDrawRestore
-  // optimization.
-  list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>(
-      80, SkBlendMode::kSrc, nullptr, nullptr, false);
-  list->CreateAndAppendDrawingItem<DrawingDisplayItem>(
-      kVisualRect, CreateRectPictureWithAlpha(kVisualRect, 40));
-  list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>();
-  list->Finalize();
-
-  SaveCountingCanvas canvas;
-  list->Raster(&canvas, nullptr);
-
-  EXPECT_EQ(1, canvas.save_count_);
-  EXPECT_EQ(1, canvas.restore_count_);
-  EXPECT_EQ(gfx::RectToSkRect(kVisualRect), canvas.draw_rect_);
-  EXPECT_LE(40, canvas.paint_.getAlpha());
-}
-
-// The same as SaveDrawRestore, but with too many ops in the PaintRecord.
-TEST(DisplayItemListTest, SaveDrawRestoreFail_TooManyOps) {
-  sk_sp<const PaintRecord> record;
-  {
-    PaintRecorder recorder;
-    PaintCanvas* canvas =
-        recorder.beginRecording(kVisualRect.width(), kVisualRect.height());
-    PaintFlags flags;
-    flags.setAlpha(40);
-    canvas->drawRect(gfx::RectToSkRect(kVisualRect), flags);
-    // Add an extra op here.
-    canvas->drawRect(gfx::RectToSkRect(kVisualRect), flags);
-    record = recorder.finishRecordingAsPicture();
-  }
-  EXPECT_GT(record->approximateOpCount(), 1);
-
-  auto list = make_scoped_refptr(new DisplayItemList);
-
-  list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>(
-      80, SkBlendMode::kSrcOver, nullptr, nullptr, false);
-  list->CreateAndAppendDrawingItem<DrawingDisplayItem>(kVisualRect,
-                                                       std::move(record));
-  list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>();
-  list->Finalize();
-
-  SaveCountingCanvas canvas;
-  list->Raster(&canvas, nullptr);
-
-  EXPECT_EQ(1, canvas.save_count_);
-  EXPECT_EQ(1, canvas.restore_count_);
-  EXPECT_EQ(gfx::RectToSkRect(kVisualRect), canvas.draw_rect_);
-  EXPECT_LE(40, canvas.paint_.getAlpha());
-}
-
 }  // namespace cc
diff --git a/cc/paint/paint_canvas.h b/cc/paint/paint_canvas.h
index d45e84b..6b9a0df 100644
--- a/cc/paint/paint_canvas.h
+++ b/cc/paint/paint_canvas.h
@@ -11,24 +11,19 @@
 #include "build/build_config.h"
 #include "cc/paint/paint_export.h"
 #include "cc/paint/paint_image.h"
+#include "cc/paint/paint_record.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 
 namespace cc {
 
 class DisplayItemList;
 class PaintFlags;
-class PaintOpBuffer;
-
-using PaintRecord = PaintOpBuffer;
 
 class CC_PAINT_EXPORT PaintCanvas {
  public:
   virtual ~PaintCanvas() {}
 
   virtual SkMetaData& getMetaData() = 0;
-
-  // TODO(enne): this only appears to mostly be used to determine if this is
-  // recording or not, so could be simplified or removed.
   virtual SkImageInfo imageInfo() const = 0;
 
   // TODO(enne): It would be nice to get rid of flush() entirely, as it
@@ -47,7 +42,7 @@
                            int y) = 0;
   virtual int save() = 0;
   virtual int saveLayer(const SkRect* bounds, const PaintFlags* flags) = 0;
-  virtual int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) = 0;
+  virtual int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) = 0;
 
   virtual void restore() = 0;
   virtual int getSaveCount() const = 0;
@@ -98,8 +93,6 @@
   virtual bool getDeviceClipBounds(SkIRect* bounds) const = 0;
   virtual void drawColor(SkColor color, SkBlendMode mode) = 0;
   void drawColor(SkColor color) { drawColor(color, SkBlendMode::kSrcOver); }
-
-  // TODO(enne): This is a synonym for drawColor with kSrc.  Remove it.
   virtual void clear(SkColor color) = 0;
 
   virtual void drawLine(SkScalar x0,
diff --git a/cc/paint/paint_flags.cc b/cc/paint/paint_flags.cc
deleted file mode 100644
index e16a8bb..0000000
--- a/cc/paint/paint_flags.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2017 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/paint/paint_flags.h"
-
-namespace cc {
-
-bool PaintFlags::IsSimpleOpacity() const {
-  uint32_t color = getColor();
-  if (SK_ColorTRANSPARENT != SkColorSetA(color, SK_AlphaTRANSPARENT))
-    return false;
-  if (!isSrcOver())
-    return false;
-  if (getLooper())
-    return false;
-  if (getPathEffect())
-    return false;
-  if (getShader())
-    return false;
-  if (getMaskFilter())
-    return false;
-  if (getColorFilter())
-    return false;
-  if (getImageFilter())
-    return false;
-  return true;
-}
-
-bool PaintFlags::SupportsFoldingAlpha() const {
-  if (!isSrcOver())
-    return false;
-  if (getColorFilter())
-    return false;
-  if (getImageFilter())
-    return false;
-  if (getLooper())
-    return false;
-  return true;
-}
-
-}  // namespace cc
diff --git a/cc/paint/paint_flags.h b/cc/paint/paint_flags.h
index 37b460d6..b7e96c6 100644
--- a/cc/paint/paint_flags.h
+++ b/cc/paint/paint_flags.h
@@ -7,6 +7,7 @@
 
 #include "base/compiler_specific.h"
 #include "cc/paint/paint_export.h"
+#include "cc/paint/paint_shader.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkColorFilter.h"
 #include "third_party/skia/include/core/SkDrawLooper.h"
@@ -18,8 +19,6 @@
 
 namespace cc {
 
-using PaintShader = SkShader;
-
 class CC_PAINT_EXPORT PaintFlags {
  public:
   enum Style {
@@ -199,14 +198,6 @@
     return paint_.computeFastBounds(orig, storage);
   }
 
-  bool operator==(const PaintFlags& flags) { return flags.paint_ == paint_; }
-  bool operator!=(const PaintFlags& flags) { return flags.paint_ != paint_; }
-
-  // Returns true if this just represents an opacity blend when
-  // used as saveLayer flags.
-  bool IsSimpleOpacity() const;
-  bool SupportsFoldingAlpha() const;
-
  private:
   friend const SkPaint& ToSkPaint(const PaintFlags& flags);
   friend const SkPaint* ToSkPaint(const PaintFlags* flags);
diff --git a/cc/paint/paint_image.cc b/cc/paint/paint_image.cc
index d34d05d..70644ed 100644
--- a/cc/paint/paint_image.cc
+++ b/cc/paint/paint_image.cc
@@ -12,9 +12,6 @@
     : sk_image_(std::move(sk_image)),
       animation_type_(animation_type),
       completion_state_(completion_state) {}
-
-PaintImage::PaintImage(const PaintImage& image) = default;
-
 PaintImage::~PaintImage() = default;
 
 }  // namespace cc
diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h
index c772316..0ed1edd 100644
--- a/cc/paint/paint_image.h
+++ b/cc/paint/paint_image.h
@@ -23,7 +23,6 @@
   PaintImage(sk_sp<const SkImage> sk_image,
              AnimationType animation_type,
              CompletionState completion_state);
-  PaintImage(const PaintImage& image);
   ~PaintImage();
 
   const sk_sp<const SkImage>& sk_image() const { return sk_image_; }
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
deleted file mode 100644
index a98392a..0000000
--- a/cc/paint/paint_op_buffer.cc
+++ /dev/null
@@ -1,556 +0,0 @@
-// Copyright 2017 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/paint/paint_op_buffer.h"
-
-#include "cc/paint/display_item_list.h"
-#include "cc/paint/paint_record.h"
-#include "third_party/skia/include/core/SkAnnotation.h"
-
-namespace cc {
-
-#define TYPES(M)           \
-  M(AnnotateOp)            \
-  M(ClipPathOp)            \
-  M(ClipRectOp)            \
-  M(ClipRRectOp)           \
-  M(ConcatOp)              \
-  M(DrawArcOp)             \
-  M(DrawCircleOp)          \
-  M(DrawColorOp)           \
-  M(DrawDisplayItemListOp) \
-  M(DrawDRRectOp)          \
-  M(DrawImageOp)           \
-  M(DrawImageRectOp)       \
-  M(DrawIRectOp)           \
-  M(DrawLineOp)            \
-  M(DrawOvalOp)            \
-  M(DrawPathOp)            \
-  M(DrawPosTextOp)         \
-  M(DrawRecordOp)          \
-  M(DrawRectOp)            \
-  M(DrawRRectOp)           \
-  M(DrawTextOp)            \
-  M(DrawTextBlobOp)        \
-  M(NoopOp)                \
-  M(RestoreOp)             \
-  M(RotateOp)              \
-  M(SaveOp)                \
-  M(SaveLayerOp)           \
-  M(SaveLayerAlphaOp)      \
-  M(ScaleOp)               \
-  M(SetMatrixOp)           \
-  M(TranslateOp)
-
-// Helper template to share common code for RasterWithAlpha when paint ops
-// have or don't have PaintFlags.
-template <typename T, bool HasFlags>
-struct Rasterizer {
-  static void Raster(const T* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    // Paint ops with kHasPaintFlags need to declare RasterWithPaintFlags
-    // otherwise, the paint op needs its own Raster function.  Without its
-    // own, this becomes an infinite loop as PaintOp::Raster calls itself.
-    static_assert(
-        !std::is_same<decltype(&PaintOp::Raster), decltype(&T::Raster)>::value,
-        "No Raster function");
-
-    op->Raster(canvas);
-  }
-  static void RasterWithAlpha(const T* op, SkCanvas* canvas, uint8_t alpha) {
-    DCHECK(T::kIsDrawOp);
-    // TODO(enne): is it ok to just drop the bounds here?
-    canvas->saveLayerAlpha(nullptr, alpha);
-    op->Raster(canvas);
-    canvas->restore();
-  }
-};
-
-template <typename T>
-struct Rasterizer<T, true> {
-  static void Raster(const T* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    op->RasterWithFlags(canvas, op->flags);
-  }
-  static void RasterWithAlpha(const T* op, SkCanvas* canvas, uint8_t alpha) {
-    DCHECK(T::kIsDrawOp);
-    SkMatrix unused_matrix;
-    if (alpha == 255) {
-      Raster(op, canvas, unused_matrix);
-    } else if (op->flags.SupportsFoldingAlpha()) {
-      PaintFlags flags = op->flags;
-      flags.setAlpha(SkMulDiv255Round(flags.getAlpha(), alpha));
-      op->RasterWithFlags(canvas, flags);
-    } else {
-      canvas->saveLayerAlpha(nullptr, alpha);
-      op->RasterWithFlags(canvas, op->flags);
-      canvas->restore();
-    }
-  }
-};
-
-template <>
-struct Rasterizer<SetMatrixOp, false> {
-  static void Raster(const SetMatrixOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    op->Raster(canvas, original_ctm);
-  }
-  static void RasterWithAlpha(const SetMatrixOp* op,
-                              SkCanvas* canvas,
-                              uint8_t alpha) {
-    NOTREACHED();
-  }
-};
-
-template <>
-struct Rasterizer<DrawRecordOp, false> {
-  static void Raster(const DrawRecordOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    op->Raster(canvas);
-  }
-  static void RasterWithAlpha(const DrawRecordOp* op,
-                              SkCanvas* canvas,
-                              uint8_t alpha) {
-    // This "looking into records" optimization is done here instead of
-    // in the PaintOpBuffer::Raster function as DisplayItemList calls
-    // into RasterWithAlpha directly.
-    if (op->record->approximateOpCount() == 1) {
-      op->record->GetFirstOp()->RasterWithAlpha(canvas, alpha);
-      return;
-    }
-
-    canvas->saveLayerAlpha(nullptr, alpha);
-    op->Raster(canvas);
-    canvas->restore();
-  }
-};
-
-// TODO(enne): partially specialize RasterWithAlpha for draw color?
-
-static constexpr size_t kNumOpTypes =
-    static_cast<size_t>(PaintOpType::LastPaintOpType) + 1;
-
-// Verify that every op is in the TYPES macro.
-#define M(T) +1
-static_assert(kNumOpTypes == TYPES(M), "Missing op in list");
-#undef M
-
-using RasterFunction = void (*)(const PaintOp* op,
-                                SkCanvas* canvas,
-                                const SkMatrix& original_ctm);
-#define M(T)                                                              \
-  [](const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm) { \
-    Rasterizer<T, T::kHasPaintFlags>::Raster(static_cast<const T*>(op),   \
-                                             canvas, original_ctm);       \
-  },
-static const RasterFunction g_raster_functions[kNumOpTypes] = {TYPES(M)};
-#undef M
-
-using RasterAlphaFunction = void (*)(const PaintOp* op,
-                                     SkCanvas* canvas,
-                                     uint8_t alpha);
-#define M(T) \
-  T::kIsDrawOp ? \
-  [](const PaintOp* op, SkCanvas* canvas, uint8_t alpha) { \
-    Rasterizer<T, T::kHasPaintFlags>::RasterWithAlpha( \
-        static_cast<const T*>(op), canvas, alpha); \
-  } : static_cast<RasterAlphaFunction>(nullptr),
-static const RasterAlphaFunction g_raster_alpha_functions[kNumOpTypes] = {
-    TYPES(M)};
-#undef M
-
-// Most state ops (matrix, clip, save, restore) have a trivial destructor.
-// TODO(enne): evaluate if we need the nullptr optimization or if
-// we even need to differentiate trivial destructors here.
-using VoidFunction = void (*)(PaintOp* op);
-#define M(T)                                           \
-  !std::is_trivially_destructible<T>::value            \
-      ? [](PaintOp* op) { static_cast<T*>(op)->~T(); } \
-      : static_cast<VoidFunction>(nullptr),
-static const VoidFunction g_destructor_functions[kNumOpTypes] = {TYPES(M)};
-#undef M
-
-#define M(T) T::kIsDrawOp,
-static bool g_is_draw_op[kNumOpTypes] = {TYPES(M)};
-#undef M
-
-#define M(T)                                         \
-  static_assert(sizeof(T) <= sizeof(LargestPaintOp), \
-                #T " must be no bigger than LargestPaintOp");
-TYPES(M);
-#undef M
-
-#undef TYPES
-
-SkRect PaintOp::kUnsetRect = {SK_ScalarInfinity, 0, 0, 0};
-
-void AnnotateOp::Raster(SkCanvas* canvas) const {
-  switch (annotation_type) {
-    case PaintCanvas::AnnotationType::URL:
-      SkAnnotateRectWithURL(canvas, rect, data.get());
-      break;
-    case PaintCanvas::AnnotationType::LINK_TO_DESTINATION:
-      SkAnnotateLinkToDestination(canvas, rect, data.get());
-      break;
-    case PaintCanvas::AnnotationType::NAMED_DESTINATION: {
-      SkPoint point = SkPoint::Make(rect.x(), rect.y());
-      SkAnnotateNamedDestination(canvas, point, data.get());
-      break;
-    }
-  }
-}
-
-void ClipPathOp::Raster(SkCanvas* canvas) const {
-  canvas->clipPath(path, op, antialias);
-}
-
-void ClipRectOp::Raster(SkCanvas* canvas) const {
-  canvas->clipRect(rect, op, antialias);
-}
-
-void ClipRRectOp::Raster(SkCanvas* canvas) const {
-  canvas->clipRRect(rrect, op, antialias);
-}
-
-void ConcatOp::Raster(SkCanvas* canvas) const {
-  canvas->concat(matrix);
-}
-
-void DrawArcOp::RasterWithFlags(SkCanvas* canvas,
-                                const PaintFlags& flags) const {
-  canvas->drawArc(oval, start_angle, sweep_angle, use_center, ToSkPaint(flags));
-}
-
-void DrawCircleOp::RasterWithFlags(SkCanvas* canvas,
-                                   const PaintFlags& flags) const {
-  canvas->drawCircle(cx, cy, radius, ToSkPaint(flags));
-}
-
-void DrawColorOp::Raster(SkCanvas* canvas) const {
-  canvas->drawColor(color, mode);
-}
-
-void DrawDisplayItemListOp::Raster(SkCanvas* canvas) const {
-  list->Raster(canvas, nullptr);
-}
-
-void DrawDRRectOp::RasterWithFlags(SkCanvas* canvas,
-                                   const PaintFlags& flags) const {
-  canvas->drawDRRect(outer, inner, ToSkPaint(flags));
-}
-
-void DrawImageOp::RasterWithFlags(SkCanvas* canvas,
-                                  const PaintFlags& flags) const {
-  canvas->drawImage(image.sk_image().get(), left, top, ToSkPaint(&flags));
-}
-
-void DrawImageRectOp::RasterWithFlags(SkCanvas* canvas,
-                                      const PaintFlags& flags) const {
-  // TODO(enne): Probably PaintCanvas should just use the skia enum directly.
-  SkCanvas::SrcRectConstraint skconstraint =
-      static_cast<SkCanvas::SrcRectConstraint>(constraint);
-  canvas->drawImageRect(image.sk_image().get(), src, dst, ToSkPaint(&flags),
-                        skconstraint);
-}
-
-void DrawIRectOp::RasterWithFlags(SkCanvas* canvas,
-                                  const PaintFlags& flags) const {
-  canvas->drawIRect(rect, ToSkPaint(flags));
-}
-
-void DrawLineOp::RasterWithFlags(SkCanvas* canvas,
-                                 const PaintFlags& flags) const {
-  canvas->drawLine(x0, y0, x1, y1, ToSkPaint(flags));
-}
-
-void DrawOvalOp::RasterWithFlags(SkCanvas* canvas,
-                                 const PaintFlags& flags) const {
-  canvas->drawOval(oval, ToSkPaint(flags));
-}
-
-void DrawPathOp::RasterWithFlags(SkCanvas* canvas,
-                                 const PaintFlags& flags) const {
-  canvas->drawPath(path, ToSkPaint(flags));
-}
-
-void DrawPosTextOp::RasterWithFlags(SkCanvas* canvas,
-                                    const PaintFlags& flags) const {
-  canvas->drawPosText(paint_op_data(this), bytes, paint_op_array<SkPoint>(this),
-                      ToSkPaint(flags));
-}
-
-void DrawRecordOp::Raster(SkCanvas* canvas) const {
-  record->playback(canvas);
-}
-
-void DrawRectOp::RasterWithFlags(SkCanvas* canvas,
-                                 const PaintFlags& flags) const {
-  canvas->drawRect(rect, ToSkPaint(flags));
-}
-
-void DrawRRectOp::RasterWithFlags(SkCanvas* canvas,
-                                  const PaintFlags& flags) const {
-  canvas->drawRRect(rrect, ToSkPaint(flags));
-}
-
-void DrawTextOp::RasterWithFlags(SkCanvas* canvas,
-                                 const PaintFlags& flags) const {
-  canvas->drawText(paint_op_data(this), bytes, x, y, ToSkPaint(flags));
-}
-
-void DrawTextBlobOp::RasterWithFlags(SkCanvas* canvas,
-                                     const PaintFlags& flags) const {
-  canvas->drawTextBlob(blob.get(), x, y, ToSkPaint(flags));
-}
-
-void RestoreOp::Raster(SkCanvas* canvas) const {
-  canvas->restore();
-}
-
-void RotateOp::Raster(SkCanvas* canvas) const {
-  canvas->rotate(degrees);
-}
-
-void SaveOp::Raster(SkCanvas* canvas) const {
-  canvas->save();
-}
-
-void SaveLayerOp::RasterWithFlags(SkCanvas* canvas,
-                                  const PaintFlags& flags) const {
-  // See PaintOp::kUnsetRect
-  bool unset = bounds.left() == SK_ScalarInfinity;
-
-  canvas->saveLayer(unset ? nullptr : &bounds, ToSkPaint(&flags));
-}
-
-void SaveLayerAlphaOp::Raster(SkCanvas* canvas) const {
-  // See PaintOp::kUnsetRect
-  bool unset = bounds.left() == SK_ScalarInfinity;
-  canvas->saveLayerAlpha(unset ? nullptr : &bounds, alpha);
-}
-
-void ScaleOp::Raster(SkCanvas* canvas) const {
-  canvas->scale(sx, sy);
-}
-
-void SetMatrixOp::Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const {
-  canvas->setMatrix(SkMatrix::Concat(original_ctm, matrix));
-}
-
-void TranslateOp::Raster(SkCanvas* canvas) const {
-  canvas->translate(dx, dy);
-}
-
-bool PaintOp::IsDrawOp() const {
-  return g_is_draw_op[type];
-}
-
-void PaintOp::Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const {
-  g_raster_functions[type](this, canvas, original_ctm);
-}
-
-void PaintOp::RasterWithAlpha(SkCanvas* canvas, uint8_t alpha) const {
-  g_raster_alpha_functions[type](this, canvas, alpha);
-}
-
-DrawDisplayItemListOp::DrawDisplayItemListOp(
-    scoped_refptr<DisplayItemList> list)
-    : list(list) {}
-
-size_t DrawDisplayItemListOp::AdditionalBytesUsed() const {
-  return list->ApproximateMemoryUsage();
-}
-
-int ClipPathOp::CountSlowPaths() const {
-  return antialias && !path.isConvex() ? 1 : 0;
-}
-
-int DrawLineOp::CountSlowPaths() const {
-  if (const SkPathEffect* effect = flags.getPathEffect()) {
-    SkPathEffect::DashInfo info;
-    SkPathEffect::DashType dashType = effect->asADash(&info);
-    if (flags.getStrokeCap() != PaintFlags::kRound_Cap &&
-        dashType == SkPathEffect::kDash_DashType && info.fCount == 2) {
-      // The PaintFlags will count this as 1, so uncount that here as
-      // this kind of line is special cased and not slow.
-      return -1;
-    }
-  }
-  return 0;
-}
-
-int DrawPathOp::CountSlowPaths() const {
-  // This logic is copied from SkPathCounter instead of attempting to expose
-  // that from Skia.
-  if (!flags.isAntiAlias() || path.isConvex())
-    return 0;
-
-  PaintFlags::Style paintStyle = flags.getStyle();
-  const SkRect& pathBounds = path.getBounds();
-  if (paintStyle == PaintFlags::kStroke_Style && flags.getStrokeWidth() == 0) {
-    // AA hairline concave path is not slow.
-    return 0;
-  } else if (paintStyle == PaintFlags::kFill_Style &&
-             pathBounds.width() < 64.f && pathBounds.height() < 64.f &&
-             !path.isVolatile()) {
-    // AADF eligible concave path is not slow.
-    return 0;
-  } else {
-    return 1;
-  }
-}
-
-AnnotateOp::AnnotateOp(PaintCanvas::AnnotationType annotation_type,
-                       const SkRect& rect,
-                       sk_sp<SkData> data)
-    : annotation_type(annotation_type), rect(rect), data(std::move(data)) {}
-
-AnnotateOp::~AnnotateOp() = default;
-
-DrawDisplayItemListOp::~DrawDisplayItemListOp() = default;
-
-DrawImageOp::DrawImageOp(const PaintImage& image,
-                         SkScalar left,
-                         SkScalar top,
-                         const PaintFlags* flags)
-    : image(image),
-      left(left),
-      top(top),
-      flags(flags ? *flags : PaintFlags()) {}
-
-DrawImageOp::~DrawImageOp() = default;
-
-DrawImageRectOp::DrawImageRectOp(const PaintImage& image,
-                                 const SkRect& src,
-                                 const SkRect& dst,
-                                 const PaintFlags* flags,
-                                 PaintCanvas::SrcRectConstraint constraint)
-    : image(image),
-      flags(flags ? *flags : PaintFlags()),
-      src(src),
-      dst(dst),
-      constraint(constraint) {}
-
-DrawImageRectOp::~DrawImageRectOp() = default;
-
-DrawPosTextOp::DrawPosTextOp(size_t bytes,
-                             size_t count,
-                             const PaintFlags& flags)
-    : PaintOpWithDataArray(bytes, count), flags(flags) {}
-
-DrawPosTextOp::~DrawPosTextOp() = default;
-
-DrawRecordOp::DrawRecordOp(sk_sp<const PaintRecord> record)
-    : record(std::move(record)) {}
-
-DrawRecordOp::~DrawRecordOp() = default;
-
-size_t DrawRecordOp::AdditionalBytesUsed() const {
-  return record->approximateBytesUsed();
-}
-
-DrawTextBlobOp::DrawTextBlobOp(sk_sp<SkTextBlob> blob,
-                               SkScalar x,
-                               SkScalar y,
-                               const PaintFlags& flags)
-    : blob(std::move(blob)), x(x), y(y), flags(flags) {}
-
-DrawTextBlobOp::~DrawTextBlobOp() = default;
-
-PaintOpBuffer::PaintOpBuffer() : cull_rect_(SkRect::MakeEmpty()) {}
-
-PaintOpBuffer::PaintOpBuffer(const SkRect& cull_rect) : cull_rect_(cull_rect) {}
-
-PaintOpBuffer::~PaintOpBuffer() {
-  Reset();
-}
-
-void PaintOpBuffer::Reset() {
-  for (auto* op : Iterator(this)) {
-    auto func = g_destructor_functions[op->type];
-    if (func)
-      func(op);
-  }
-
-  // Leave data_ allocated, reserved_ unchanged.
-  used_ = 0;
-  op_count_ = 0;
-  num_slow_paths_ = 0;
-}
-
-void PaintOpBuffer::playback(SkCanvas* canvas) const {
-  // TODO(enne): a PaintRecord that contains a SetMatrix assumes that the
-  // SetMatrix is local to that PaintRecord itself.  Said differently, if you
-  // translate(x, y), then draw a paint record with a SetMatrix(identity),
-  // the translation should be preserved instead of clobbering the top level
-  // transform.  This could probably be done more efficiently.
-  SkMatrix original = canvas->getTotalMatrix();
-
-  for (Iterator iter(this); iter; ++iter) {
-    // Optimize out save/restores or save/draw/restore that can be a single
-    // draw.  See also: similar code in SkRecordOpts and cc's DisplayItemList.
-    // TODO(enne): consider making this recursive?
-    const PaintOp* op = *iter;
-    if (op->GetType() == PaintOpType::SaveLayerAlpha) {
-      const PaintOp* second = iter.peek1();
-      if (second) {
-        if (second->GetType() == PaintOpType::Restore) {
-          ++iter;
-          continue;
-        }
-        if (second->IsDrawOp()) {
-          const PaintOp* third = iter.peek2();
-          if (third && third->GetType() == PaintOpType::Restore) {
-            const SaveLayerAlphaOp* save_op =
-                static_cast<const SaveLayerAlphaOp*>(op);
-            second->RasterWithAlpha(canvas, save_op->alpha);
-            ++iter;
-            ++iter;
-            continue;
-          }
-        }
-      }
-    }
-    // TODO(enne): skip SaveLayer followed by restore with nothing in
-    // between, however SaveLayer with image filters on it (or maybe
-    // other PaintFlags options) are not a noop.  Figure out what these
-    // are so we can skip them correctly.
-
-    op->Raster(canvas, original);
-  }
-}
-
-void PaintOpBuffer::playback(SkCanvas* canvas,
-                             SkPicture::AbortCallback* callback) const {
-  // The abort callback is only used for analysis, in general, so
-  // this playback code can be more straightforward and not do the
-  // optimizations in the other function.
-  if (!callback) {
-    playback(canvas);
-    return;
-  }
-
-  SkMatrix original = canvas->getTotalMatrix();
-
-  // TODO(enne): ideally callers would just iterate themselves and we
-  // can remove the entire notion of an abort callback.
-  for (auto* op : Iterator(this)) {
-    op->Raster(canvas, original);
-    if (callback && callback->abort())
-      return;
-  }
-}
-
-void PaintOpBuffer::ShrinkToFit() {
-  if (!used_ || used_ == reserved_)
-    return;
-  data_.realloc(used_);
-  reserved_ = used_;
-}
-
-}  // namespace cc
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
deleted file mode 100644
index 5075cf4..0000000
--- a/cc/paint/paint_op_buffer.h
+++ /dev/null
@@ -1,782 +0,0 @@
-// Copyright 2017 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_PAINT_PAINT_OP_BUFFER_H_
-#define CC_PAINT_PAINT_OP_BUFFER_H_
-
-#include <stdint.h>
-
-#include "base/logging.h"
-#include "cc/paint/paint_canvas.h"
-#include "cc/paint/paint_export.h"
-#include "cc/paint/paint_flags.h"
-#include "third_party/skia/include/core/SkPicture.h"
-#include "third_party/skia/include/core/SkRect.h"
-#include "third_party/skia/include/core/SkTextBlob.h"
-
-// PaintOpBuffer is a reimplementation of SkLiteDL.
-// See: third_party/skia/src/core/SkLiteDL.h.
-
-namespace cc {
-
-class DisplayItemList;
-
-class ThreadsafeMatrix : public SkMatrix {
- public:
-  explicit ThreadsafeMatrix(const SkMatrix& matrix) : SkMatrix(matrix) {
-    (void)getType();
-  }
-};
-
-class ThreadsafePath : public SkPath {
- public:
-  explicit ThreadsafePath(const SkPath& path) : SkPath(path) {
-    updateBoundsCache();
-  }
-};
-
-enum class PaintOpType : uint8_t {
-  Annotate,
-  ClipPath,
-  ClipRect,
-  ClipRRect,
-  Concat,
-  DrawArc,
-  DrawCircle,
-  DrawColor,
-  DrawDisplayItemList,
-  DrawDRRect,
-  DrawImage,
-  DrawImageRect,
-  DrawIRect,
-  DrawLine,
-  DrawOval,
-  DrawPath,
-  DrawPosText,
-  DrawRecord,
-  DrawRect,
-  DrawRRect,
-  DrawText,
-  DrawTextBlob,
-  Noop,
-  Restore,
-  Rotate,
-  Save,
-  SaveLayer,
-  SaveLayerAlpha,
-  Scale,
-  SetMatrix,
-  Translate,
-  LastPaintOpType = Translate,
-};
-
-struct CC_PAINT_EXPORT PaintOp {
-  uint32_t type : 8;
-  uint32_t skip : 24;
-
-  PaintOpType GetType() const { return static_cast<PaintOpType>(type); }
-
-  void Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const;
-  bool IsDrawOp() const;
-
-  // Only valid for draw ops.
-  void RasterWithAlpha(SkCanvas* canvas, uint8_t alpha) const;
-
-  int CountSlowPaths() const { return 0; }
-
-  // Returns the number of bytes used by this op in referenced sub records
-  // and display lists.  This doesn't count other objects like paths or blobs.
-  size_t AdditionalBytesUsed() const { return 0; }
-
-  static constexpr bool kIsDrawOp = false;
-  // If an op has |kHasPaintFlags| set to true, it must:
-  // (1) Provide a PaintFlags member called |flags|
-  // (2) Provide a RasterWithFlags function instead of a Raster function.
-  static constexpr bool kHasPaintFlags = false;
-  static SkRect kUnsetRect;
-};
-
-struct PaintOpWithData : PaintOp {
-  // Having data is just a helper for ops that have a varying amount of data and
-  // want a way to store that inline.  This is for ops that pass in a
-  // void* and a length.
-  explicit PaintOpWithData(size_t bytes) : bytes(bytes) {}
-
-  // Get data out by calling paint_op_data.  This can't be part of the class
-  // because it needs to know the size of the derived type.
-  size_t bytes;
-};
-
-template <typename T>
-const void* paint_op_data(const T* op) {
-  static_assert(std::is_convertible<T, PaintOpWithData>::value,
-                "T is not a PaintOpWithData");
-  // Arbitrary data for a PaintOp is stored after the PaintOp itself
-  // in the PaintOpBuffer.  Therefore, to access this data, it's
-  // pointer math to increment past the size of T.  Accessing the
-  // next op in the buffer is ((char*)op) + op->skip, with the data
-  // fitting between.
-  return op + 1;
-}
-
-template <typename T>
-void* paint_op_data(T* op) {
-  static_assert(std::is_convertible<T, PaintOpWithData>::value,
-                "T is not a PaintOpWithData");
-  return op + 1;
-}
-
-struct PaintOpWithDataArrayBase : PaintOpWithData {
-  // Helper class for static asserts in push functions.
-  using PaintOpWithData::PaintOpWithData;
-};
-
-template <typename T>
-struct PaintOpWithDataArray : PaintOpWithDataArrayBase {
-  // Paint op that has a T[count] and a char[bytes].
-  PaintOpWithDataArray(size_t bytes, size_t count)
-      : PaintOpWithDataArrayBase(bytes), count(count) {}
-  // Use paint_op_array to get array data.
-
-  size_t count;
-};
-
-template <typename M, typename T>
-const M* paint_op_array(const T* op) {
-  static_assert(std::is_convertible<T, PaintOpWithDataArrayBase>::value,
-                "T is not a PaintOpWithDataArray");
-  // See comment in paint_op_data.  Array data is stored after
-  // any void* data.  Memory layout here is: |op|data|array data|next op|
-  return SkTAddOffset<const M>(op + 1, op->bytes);
-}
-template <typename M, typename T>
-M* paint_op_array(T* op) {
-  static_assert(std::is_convertible<T, PaintOpWithDataArrayBase>::value,
-                "T is not a PaintOpWithDataArray");
-  return SkTAddOffset<M>(op + 1, op->bytes);
-}
-
-struct AnnotateOp final : PaintOp {
-  enum class AnnotationType {
-    URL,
-    LinkToDestination,
-    NamedDestination,
-  };
-
-  static constexpr PaintOpType kType = PaintOpType::Annotate;
-  AnnotateOp(PaintCanvas::AnnotationType annotation_type,
-             const SkRect& rect,
-             sk_sp<SkData> data);
-  ~AnnotateOp();
-  void Raster(SkCanvas* canvas) const;
-
-  PaintCanvas::AnnotationType annotation_type;
-  SkRect rect;
-  sk_sp<SkData> data;
-};
-
-struct ClipPathOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::ClipPath;
-  ClipPathOp(SkPath path, SkClipOp op, bool antialias)
-      : path(path), op(op), antialias(antialias) {}
-  void Raster(SkCanvas* canvas) const;
-  int CountSlowPaths() const;
-
-  ThreadsafePath path;
-  SkClipOp op;
-  bool antialias;
-};
-
-struct ClipRectOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::ClipRect;
-  ClipRectOp(const SkRect& rect, SkClipOp op, bool antialias)
-      : rect(rect), op(op), antialias(antialias) {}
-  void Raster(SkCanvas* canvas) const;
-
-  SkRect rect;
-  SkClipOp op;
-  bool antialias;
-};
-
-struct ClipRRectOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::ClipRRect;
-  ClipRRectOp(const SkRRect& rrect, SkClipOp op, bool antialias)
-      : rrect(rrect), op(op), antialias(antialias) {}
-  void Raster(SkCanvas* canvas) const;
-
-  SkRRect rrect;
-  SkClipOp op;
-  bool antialias;
-};
-
-struct ConcatOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::Concat;
-  explicit ConcatOp(const SkMatrix& matrix) : matrix(matrix) {}
-  void Raster(SkCanvas* canvas) const;
-
-  ThreadsafeMatrix matrix;
-};
-
-struct DrawArcOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawArc;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawArcOp(const SkRect& oval,
-            SkScalar start_angle,
-            SkScalar sweep_angle,
-            bool use_center,
-            const PaintFlags& flags)
-      : oval(oval),
-        start_angle(start_angle),
-        sweep_angle(sweep_angle),
-        use_center(use_center),
-        flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkRect oval;
-  SkScalar start_angle;
-  SkScalar sweep_angle;
-  bool use_center;
-  PaintFlags flags;
-};
-
-struct DrawCircleOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawCircle;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawCircleOp(SkScalar cx,
-               SkScalar cy,
-               SkScalar radius,
-               const PaintFlags& flags)
-      : cx(cx), cy(cy), radius(radius), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkScalar cx;
-  SkScalar cy;
-  SkScalar radius;
-  PaintFlags flags;
-};
-
-struct DrawColorOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawColor;
-  static constexpr bool kIsDrawOp = true;
-  DrawColorOp(SkColor color, SkBlendMode mode) : color(color), mode(mode) {}
-  void Raster(SkCanvas* canvas) const;
-
-  SkColor color;
-  SkBlendMode mode;
-};
-
-struct DrawDisplayItemListOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawDisplayItemList;
-  static constexpr bool kIsDrawOp = true;
-  explicit DrawDisplayItemListOp(scoped_refptr<DisplayItemList> list);
-  ~DrawDisplayItemListOp();
-  void Raster(SkCanvas* canvas) const;
-  size_t AdditionalBytesUsed() const;
-  // TODO(enne): DisplayItemList should know number of slow paths.
-
-  scoped_refptr<DisplayItemList> list;
-};
-
-struct DrawDRRectOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawDRRect;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawDRRectOp(const SkRRect& outer,
-               const SkRRect& inner,
-               const PaintFlags& flags)
-      : outer(outer), inner(inner), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkRRect outer;
-  SkRRect inner;
-  PaintFlags flags;
-};
-
-struct DrawImageOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawImage;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawImageOp(const PaintImage& image,
-              SkScalar left,
-              SkScalar top,
-              const PaintFlags* flags);
-  ~DrawImageOp();
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  PaintImage image;
-  SkScalar left;
-  SkScalar top;
-  PaintFlags flags;
-};
-
-struct DrawImageRectOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawImageRect;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawImageRectOp(const PaintImage& image,
-                  const SkRect& src,
-                  const SkRect& dst,
-                  const PaintFlags* flags,
-                  PaintCanvas::SrcRectConstraint constraint);
-  ~DrawImageRectOp();
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  PaintImage image;
-  PaintFlags flags;
-  SkRect src;
-  SkRect dst;
-  PaintCanvas::SrcRectConstraint constraint;
-};
-
-struct DrawIRectOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawIRect;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawIRectOp(const SkIRect& rect, const PaintFlags& flags)
-      : rect(rect), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkIRect rect;
-  PaintFlags flags;
-};
-
-struct DrawLineOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawLine;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawLineOp(SkScalar x0,
-             SkScalar y0,
-             SkScalar x1,
-             SkScalar y1,
-             const PaintFlags& flags)
-      : x0(x0), y0(y0), x1(x1), y1(y1), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-  int CountSlowPaths() const;
-
-  SkScalar x0;
-  SkScalar y0;
-  SkScalar x1;
-  SkScalar y1;
-  PaintFlags flags;
-};
-
-struct DrawOvalOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawOval;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawOvalOp(const SkRect& oval, const PaintFlags& flags)
-      : oval(oval), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkRect oval;
-  PaintFlags flags;
-};
-
-struct DrawPathOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawPath;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawPathOp(const SkPath& path, const PaintFlags& flags)
-      : path(path), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-  int CountSlowPaths() const;
-
-  ThreadsafePath path;
-  PaintFlags flags;
-};
-
-struct DrawPosTextOp final : PaintOpWithDataArray<SkPoint> {
-  static constexpr PaintOpType kType = PaintOpType::DrawPosText;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawPosTextOp(size_t bytes, size_t count, const PaintFlags& flags);
-  ~DrawPosTextOp();
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  PaintFlags flags;
-};
-
-struct DrawRecordOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawRecord;
-  static constexpr bool kIsDrawOp = true;
-  explicit DrawRecordOp(sk_sp<const PaintRecord> record);
-  ~DrawRecordOp();
-  void Raster(SkCanvas* canvas) const;
-  size_t AdditionalBytesUsed() const;
-
-  sk_sp<const PaintRecord> record;
-};
-
-struct DrawRectOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawRect;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawRectOp(const SkRect& rect, const PaintFlags& flags)
-      : rect(rect), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkRect rect;
-  PaintFlags flags;
-};
-
-struct DrawRRectOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawRRect;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawRRectOp(const SkRRect& rrect, const PaintFlags& flags)
-      : rrect(rrect), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkRRect rrect;
-  PaintFlags flags;
-};
-
-struct DrawTextOp final : PaintOpWithData {
-  static constexpr PaintOpType kType = PaintOpType::DrawText;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawTextOp(size_t bytes, SkScalar x, SkScalar y, const PaintFlags& flags)
-      : PaintOpWithData(bytes), x(x), y(y), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkScalar x;
-  SkScalar y;
-  PaintFlags flags;
-};
-
-struct DrawTextBlobOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawTextBlob;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawTextBlobOp(sk_sp<SkTextBlob> blob,
-                 SkScalar x,
-                 SkScalar y,
-                 const PaintFlags& flags);
-  ~DrawTextBlobOp();
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  sk_sp<SkTextBlob> blob;
-  SkScalar x;
-  SkScalar y;
-  PaintFlags flags;
-};
-
-struct NoopOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::Noop;
-  void Raster(SkCanvas* canvas) const {}
-};
-
-struct RestoreOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::Restore;
-  void Raster(SkCanvas* canvas) const;
-};
-
-struct RotateOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::Rotate;
-  explicit RotateOp(SkScalar degrees) : degrees(degrees) {}
-  void Raster(SkCanvas* canvas) const;
-
-  SkScalar degrees;
-};
-
-struct SaveOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::Save;
-  void Raster(SkCanvas* canvas) const;
-};
-
-struct SaveLayerOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::SaveLayer;
-  static constexpr bool kHasPaintFlags = true;
-  SaveLayerOp(const SkRect* bounds, const PaintFlags* flags)
-      : bounds(bounds ? *bounds : kUnsetRect) {
-    if (flags)
-      this->flags = *flags;
-  }
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkRect bounds;
-  PaintFlags flags;
-};
-
-struct SaveLayerAlphaOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::SaveLayerAlpha;
-  SaveLayerAlphaOp(const SkRect* bounds, uint8_t alpha)
-      : bounds(bounds ? *bounds : kUnsetRect), alpha(alpha) {}
-  void Raster(SkCanvas* canvas) const;
-
-  SkRect bounds;
-  uint8_t alpha;
-};
-
-struct ScaleOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::Scale;
-  ScaleOp(SkScalar sx, SkScalar sy) : sx(sx), sy(sy) {}
-  void Raster(SkCanvas* canvas) const;
-
-  SkScalar sx;
-  SkScalar sy;
-};
-
-struct SetMatrixOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::SetMatrix;
-  explicit SetMatrixOp(const SkMatrix& matrix) : matrix(matrix) {}
-  // This is the only op that needs the original ctm of the SkCanvas
-  // used for raster (since SetMatrix is relative to the recording origin and
-  // shouldn't clobber the SkCanvas raster origin).
-  //
-  // TODO(enne): Find some cleaner way to do this, possibly by making
-  // all SetMatrix calls Concat??
-  void Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const;
-
-  ThreadsafeMatrix matrix;
-};
-
-struct TranslateOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::Translate;
-  TranslateOp(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {}
-  void Raster(SkCanvas* canvas) const;
-
-  SkScalar dx;
-  SkScalar dy;
-};
-
-using LargestPaintOp = DrawDRRectOp;
-
-class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt {
- public:
-  enum { kPageSize = 4096 };
-
-  PaintOpBuffer();
-  explicit PaintOpBuffer(const SkRect& cull_rect);
-  ~PaintOpBuffer() override;
-
-  void Reset();
-
-  void playback(SkCanvas* canvas) const;
-  void playback(SkCanvas* canvas, SkPicture::AbortCallback* callback) const;
-
-  // TODO(enne): These are no longer approximate.  Rename these.
-  int approximateOpCount() const { return op_count_; }
-  size_t approximateBytesUsed() const {
-    return sizeof(*this) + reserved_ + subrecord_bytes_used_;
-  }
-  int numSlowPaths() const { return num_slow_paths_; }
-
-  // Resize the PaintOpBuffer to exactly fit the current amount of used space.
-  void ShrinkToFit();
-
-  const SkRect& cullRect() const { return cull_rect_; }
-
-  PaintOp* GetFirstOp() const {
-    return reinterpret_cast<PaintOp*>(const_cast<char*>(&first_op_[0]));
-  }
-
-  template <typename T, typename... Args>
-  void push(Args&&... args) {
-    static_assert(std::is_convertible<T, PaintOp>::value, "T not a PaintOp.");
-    static_assert(!std::is_convertible<T, PaintOpWithData>::value,
-                  "Type needs to use push_with_data");
-    push_internal<T>(0, std::forward<Args>(args)...);
-  }
-
-  template <typename T, typename... Args>
-  void push_with_data(const void* data, size_t bytes, Args&&... args) {
-    static_assert(std::is_convertible<T, PaintOpWithData>::value,
-                  "T is not a PaintOpWithData");
-#if !defined(OS_CHROMEOS)
-    // TODO(enne): non-linux chromeos builds think that DrawTextOp
-    // can be converted to a PaintOpWithDataArrayBase.  OOPS.
-    static_assert(!std::is_convertible<T, PaintOpWithDataArrayBase>::value,
-                  "Type needs to use push_with_data_array");
-#endif
-    DCHECK_GE(bytes, 0u);
-    T* op = push_internal<T>(bytes, bytes, std::forward<Args>(args)...);
-    memcpy(paint_op_data(op), data, bytes);
-
-#if DCHECK_IS_ON()
-    // Double check the data fits between op and next op and doesn't clobber.
-    char* op_start = reinterpret_cast<char*>(op);
-    char* op_end = op_start + sizeof(T);
-    char* next_op = op_start + op->skip;
-    char* data_start = reinterpret_cast<char*>(paint_op_data(op));
-    char* data_end = data_start + bytes;
-    DCHECK_GE(data_start, op_end);
-    DCHECK_LT(data_start, next_op);
-    DCHECK_LE(data_end, next_op);
-#endif
-  }
-
-  template <typename T, typename M, typename... Args>
-  void push_with_data_array(const void* data,
-                            size_t bytes,
-                            const M* array,
-                            size_t count,
-                            Args&&... args) {
-    static_assert(std::is_convertible<T, PaintOpWithDataArray<M>>::value,
-                  "T is not a PaintOpWithDataArray");
-    DCHECK_GE(bytes, 0u);
-    DCHECK_GE(count, 0u);
-    size_t array_size = sizeof(M) * count;
-    size_t total_size = bytes + array_size;
-    T* op =
-        push_internal<T>(total_size, bytes, count, std::forward<Args>(args)...);
-    memcpy(paint_op_data(op), data, bytes);
-    memcpy(paint_op_array<M>(op), array, array_size);
-
-#if DCHECK_IS_ON()
-    // Double check data and array don't clobber op, next op, or each other
-    char* op_start = reinterpret_cast<char*>(op);
-    char* op_end = op_start + sizeof(T);
-    char* next_op = op_start + op->skip;
-    char* data_start = reinterpret_cast<char*>(paint_op_data(op));
-    char* data_end = data_start + bytes;
-    char* array_start = reinterpret_cast<char*>(paint_op_array<M>(op));
-    char* array_end = array_start + array_size;
-    DCHECK_GE(data_start, op_end);
-    DCHECK_LE(data_start, array_start);
-    DCHECK_GE(array_start, data_end);
-    DCHECK_LE(array_end, next_op);
-#endif
-  }
-
-  class Iterator {
-   public:
-    explicit Iterator(const PaintOpBuffer* buffer)
-        : buffer_(buffer), ptr_(buffer_->data_.get()) {}
-
-    PaintOp* operator->() const {
-      return op_idx_ ? reinterpret_cast<PaintOp*>(ptr_) : buffer_->GetFirstOp();
-    }
-    PaintOp* operator*() const { return operator->(); }
-    Iterator begin() { return Iterator(buffer_, buffer_->data_.get(), 0); }
-    Iterator end() {
-      return Iterator(buffer_, buffer_->data_.get() + buffer_->used_,
-                      buffer_->approximateOpCount());
-    }
-    bool operator!=(const Iterator& other) {
-      // Not valid to compare iterators on different buffers.
-      DCHECK_EQ(other.buffer_, buffer_);
-      return other.op_idx_ != op_idx_;
-    }
-    Iterator& operator++() {
-      if (!op_idx_++)
-        return *this;
-      PaintOp* op = **this;
-      uint32_t type = op->type;
-      CHECK_LE(type, static_cast<uint32_t>(PaintOpType::LastPaintOpType));
-      ptr_ += op->skip;
-      return *this;
-    }
-    operator bool() const { return op_idx_ < buffer_->approximateOpCount(); }
-
-    int op_idx() const { return op_idx_; }
-
-    // Return the next op without advancing the iterator, or nullptr if none.
-    PaintOp* peek1() const {
-      if (op_idx_ + 1 >= buffer_->approximateOpCount())
-        return nullptr;
-      if (!op_idx_)
-        return reinterpret_cast<PaintOp*>(ptr_);
-      return reinterpret_cast<PaintOp*>(ptr_ + (*this)->skip);
-    }
-
-    // Return the op two ops ahead without advancing the iterator, or nullptr if
-    // none.
-    PaintOp* peek2() const {
-      if (op_idx_ + 2 >= buffer_->approximateOpCount())
-        return nullptr;
-      char* next = ptr_ + reinterpret_cast<PaintOp*>(ptr_)->skip;
-      PaintOp* next_op = reinterpret_cast<PaintOp*>(next);
-      if (!op_idx_)
-        return next_op;
-      return reinterpret_cast<PaintOp*>(next + next_op->skip);
-    }
-
-   private:
-    Iterator(const PaintOpBuffer* buffer, char* ptr, int op_idx)
-        : buffer_(buffer), ptr_(ptr), op_idx_(op_idx) {}
-
-    const PaintOpBuffer* buffer_ = nullptr;
-    char* ptr_ = nullptr;
-    int op_idx_ = 0;
-  };
-
- private:
-  template <typename T, bool HasFlags>
-  struct CountSlowPathsFromFlags {
-    static int Count(const T* op) { return 0; }
-  };
-
-  template <typename T>
-  struct CountSlowPathsFromFlags<T, true> {
-    static int Count(const T* op) { return op->flags.getPathEffect() ? 1 : 0; }
-  };
-
-  template <typename T, typename... Args>
-  T* push_internal(size_t bytes, Args&&... args) {
-    size_t skip = SkAlignPtr(sizeof(T) + bytes);
-    DCHECK_LT(skip, static_cast<size_t>(1) << 24);
-    if (used_ + skip > reserved_ || !op_count_) {
-      if (!op_count_) {
-        if (bytes) {
-          // Internal first_op buffer doesn't have room for extra data.
-          // If the op wants extra bytes, then we'll just store a Noop
-          // in the first_op and proceed from there.  This seems unlikely
-          // to be a common case.
-          push<NoopOp>();
-        } else {
-          T* op = reinterpret_cast<T*>(&first_op_[0]);
-          new (op) T{std::forward<Args>(args)...};
-          op->type = static_cast<uint32_t>(T::kType);
-          op->skip = 0;
-          op_count_++;
-          return op;
-        }
-      }
-
-      static_assert(SkIsPow2(kPageSize),
-                    "This math needs updating for non-pow2.");
-      // Next greater multiple of kPageSize.
-      reserved_ = (used_ + skip + kPageSize) & ~(kPageSize - 1);
-      data_.realloc(reserved_);
-    }
-    DCHECK_LE(used_ + skip, reserved_);
-
-    T* op = reinterpret_cast<T*>(data_.get() + used_);
-    used_ += skip;
-    new (op) T(std::forward<Args>(args)...);
-    op->type = static_cast<uint32_t>(T::kType);
-    op->skip = skip;
-    op_count_++;
-
-    num_slow_paths_ += CountSlowPathsFromFlags<T, T::kHasPaintFlags>::Count(op);
-    num_slow_paths_ += op->CountSlowPaths();
-
-    subrecord_bytes_used_ += op->AdditionalBytesUsed();
-
-    return op;
-  }
-
-  // As a performance optimization because n=1 is an extremely common case just
-  // store the first op in the PaintOpBuffer itself to avoid an extra alloc.
-  char first_op_[sizeof(LargestPaintOp)];
-  SkAutoTMalloc<char> data_;
-  size_t used_ = 0;
-  size_t reserved_ = 0;
-  int op_count_ = 0;
-
-  // Record paths for veto-to-msaa for gpu raster.
-  int num_slow_paths_ = 0;
-  // Record additional bytes used by referenced sub-records and display lists.
-  size_t subrecord_bytes_used_ = 0;
-  SkRect cull_rect_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintOpBuffer);
-};
-
-}  // namespace cc
-
-#endif  // CC_PAINT_PAINT_OP_BUFFER_H_
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc
deleted file mode 100644
index 5e0bf2aa..0000000
--- a/cc/paint/paint_op_buffer_unittest.cc
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2017 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/paint/paint_op_buffer.h"
-#include "cc/test/test_skcanvas.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-template <typename T>
-void CheckRefCnt(const T& obj, int32_t count) {
-// Skia doesn't define getRefCnt in all builds.
-#ifdef SK_DEBUG
-  EXPECT_EQ(obj->getRefCnt(), count);
-#endif
-}
-
-}  // namespace
-
-namespace cc {
-
-TEST(PaintOpBufferTest, Empty) {
-  PaintOpBuffer buffer;
-  EXPECT_EQ(buffer.approximateOpCount(), 0);
-  EXPECT_EQ(buffer.approximateBytesUsed(), sizeof(PaintOpBuffer));
-  EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false);
-
-  buffer.Reset();
-  EXPECT_EQ(buffer.approximateOpCount(), 0);
-  EXPECT_EQ(buffer.approximateBytesUsed(), sizeof(PaintOpBuffer));
-  EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false);
-}
-
-TEST(PaintOpBufferTest, SimpleAppend) {
-  SkRect rect = SkRect::MakeXYWH(2, 3, 4, 5);
-  PaintFlags flags;
-  flags.setColor(SK_ColorMAGENTA);
-  flags.setAlpha(100);
-  SkColor draw_color = SK_ColorRED;
-  SkBlendMode blend = SkBlendMode::kSrc;
-
-  PaintOpBuffer buffer;
-  buffer.push<SaveLayerOp>(&rect, &flags);
-  buffer.push<SaveOp>();
-  buffer.push<DrawColorOp>(draw_color, blend);
-  buffer.push<RestoreOp>();
-
-  EXPECT_EQ(buffer.approximateOpCount(), 4);
-
-  PaintOpBuffer::Iterator iter(&buffer);
-  ASSERT_EQ(iter->GetType(), PaintOpType::SaveLayer);
-  SaveLayerOp* save_op = static_cast<SaveLayerOp*>(*iter);
-  EXPECT_EQ(save_op->bounds, rect);
-  EXPECT_TRUE(save_op->flags == flags);
-  ++iter;
-
-  ASSERT_EQ(iter->GetType(), PaintOpType::Save);
-  ++iter;
-
-  ASSERT_EQ(iter->GetType(), PaintOpType::DrawColor);
-  DrawColorOp* op = static_cast<DrawColorOp*>(*iter);
-  EXPECT_EQ(op->color, draw_color);
-  EXPECT_EQ(op->mode, blend);
-  ++iter;
-
-  ASSERT_EQ(iter->GetType(), PaintOpType::Restore);
-  ++iter;
-
-  EXPECT_FALSE(iter);
-}
-
-// PaintOpBuffer has a special case for first ops stored locally, so
-// make sure that appending different kind of ops as a first op works
-// properly, as well as resetting and reusing the first local op.
-TEST(PaintOpBufferTest, FirstOpWithAndWithoutData) {
-  PaintOpBuffer buffer;
-  char text[] = "asdf";
-
-  // Use a color filter and its ref count to verify that the destructor
-  // is called on ops after reset.
-  PaintFlags flags;
-  sk_sp<SkColorFilter> filter =
-      SkColorFilter::MakeModeFilter(SK_ColorMAGENTA, SkBlendMode::kSrcOver);
-  flags.setColorFilter(filter);
-  CheckRefCnt(filter, 2);
-
-  buffer.push_with_data<DrawTextOp>(text, arraysize(text), 0.f, 0.f, flags);
-  CheckRefCnt(filter, 3);
-
-  // Verify that when the first op has data, which may not fit in the
-  // PaintRecord internal buffer, that it adds a noop as the first op
-  // and then appends the "op with data" into the heap buffer.
-  ASSERT_EQ(buffer.approximateOpCount(), 2);
-  EXPECT_EQ(buffer.GetFirstOp()->GetType(), PaintOpType::Noop);
-
-  // Verify iteration behavior and brief smoke test of op state.
-  {
-    PaintOpBuffer::Iterator iter(&buffer);
-    PaintOp* noop = *iter;
-    EXPECT_EQ(buffer.GetFirstOp(), noop);
-    ++iter;
-
-    PaintOp* op = *iter;
-    ASSERT_EQ(op->GetType(), PaintOpType::DrawText);
-    DrawTextOp* draw_text_op = static_cast<DrawTextOp*>(op);
-    EXPECT_EQ(draw_text_op->bytes, arraysize(text));
-
-    void* data = paint_op_data(draw_text_op);
-    EXPECT_EQ(memcmp(data, text, arraysize(text)), 0);
-
-    ++iter;
-    EXPECT_FALSE(iter);
-  }
-
-  // Reset, verify state, and append an op that will fit in the first slot.
-  buffer.Reset();
-  CheckRefCnt(filter, 2);
-
-  ASSERT_EQ(buffer.approximateOpCount(), 0);
-  EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false);
-
-  SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
-  buffer.push<DrawRectOp>(rect, flags);
-  CheckRefCnt(filter, 3);
-
-  ASSERT_EQ(buffer.approximateOpCount(), 1);
-  EXPECT_EQ(buffer.GetFirstOp()->GetType(), PaintOpType::DrawRect);
-
-  PaintOpBuffer::Iterator iter(&buffer);
-  ASSERT_EQ(iter->GetType(), PaintOpType::DrawRect);
-  DrawRectOp* draw_rect_op = static_cast<DrawRectOp*>(*iter);
-  EXPECT_EQ(draw_rect_op->rect, rect);
-
-  ++iter;
-  EXPECT_FALSE(iter);
-
-  buffer.Reset();
-  ASSERT_EQ(buffer.approximateOpCount(), 0);
-  CheckRefCnt(filter, 2);
-}
-
-TEST(PaintOpBufferTest, Peek) {
-  PaintOpBuffer buffer;
-
-  uint8_t alpha = 100;
-  buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
-  PaintFlags draw_flags;
-  buffer.push<DrawRectOp>(SkRect::MakeXYWH(1, 2, 3, 4), draw_flags);
-  buffer.push<RestoreOp>();
-  buffer.push<SaveOp>();
-  buffer.push<NoopOp>();
-  buffer.push<RestoreOp>();
-
-  PaintOpBuffer::Iterator init_iter(&buffer);
-  PaintOp* peek[2] = {*init_iter, init_iter.peek1()};
-
-  // Expect that while iterating that next = current.peek1() and that
-  // next.peek1() == current.peek2().
-  for (PaintOpBuffer::Iterator iter(&buffer); iter; ++iter) {
-    EXPECT_EQ(*iter, peek[0]) << iter.op_idx();
-    EXPECT_EQ(iter.peek1(), peek[1]) << iter.op_idx();
-
-    peek[0] = iter.peek1();
-    peek[1] = iter.peek2();
-  }
-}
-
-TEST(PaintOpBufferTest, PeekEmpty) {
-  PaintOpBuffer empty;
-  PaintOpBuffer::Iterator empty_iter(&empty);
-  EXPECT_EQ(nullptr, empty_iter.peek1());
-  EXPECT_EQ(nullptr, empty_iter.peek2());
-}
-
-// Verify that a SaveLayerAlpha / Draw / Restore can be optimized to just
-// a draw with opacity.
-TEST(PaintOpBufferTest, SaveDrawRestore) {
-  PaintOpBuffer buffer;
-
-  uint8_t alpha = 100;
-  buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
-
-  PaintFlags draw_flags;
-  draw_flags.setColor(SK_ColorMAGENTA);
-  draw_flags.setAlpha(50);
-  EXPECT_TRUE(draw_flags.SupportsFoldingAlpha());
-  SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
-  buffer.push<DrawRectOp>(rect, draw_flags);
-  buffer.push<RestoreOp>();
-
-  SaveCountingCanvas canvas;
-  buffer.playback(&canvas);
-
-  EXPECT_EQ(0, canvas.save_count_);
-  EXPECT_EQ(0, canvas.restore_count_);
-  EXPECT_EQ(rect, canvas.draw_rect_);
-
-  // Expect the alpha from the draw and the save layer to be folded together.
-  // Since alpha is stored in a uint8_t and gets rounded, so use tolerance.
-  float expected_alpha = alpha * 50 / 255.f;
-  EXPECT_LE(std::abs(expected_alpha - canvas.paint_.getAlpha()), 1.f);
-}
-
-// The same as SaveDrawRestore, but test that the optimization doesn't apply
-// when the drawing op's flags are not compatible with being folded into the
-// save layer with opacity.
-TEST(PaintOpBufferTest, SaveDrawRestoreFail_BadFlags) {
-  PaintOpBuffer buffer;
-
-  uint8_t alpha = 100;
-  buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
-
-  PaintFlags draw_flags;
-  draw_flags.setColor(SK_ColorMAGENTA);
-  draw_flags.setAlpha(50);
-  draw_flags.setBlendMode(SkBlendMode::kSrc);
-  EXPECT_FALSE(draw_flags.SupportsFoldingAlpha());
-  SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
-  buffer.push<DrawRectOp>(rect, draw_flags);
-  buffer.push<RestoreOp>();
-
-  SaveCountingCanvas canvas;
-  buffer.playback(&canvas);
-
-  EXPECT_EQ(1, canvas.save_count_);
-  EXPECT_EQ(1, canvas.restore_count_);
-  EXPECT_EQ(rect, canvas.draw_rect_);
-  EXPECT_EQ(draw_flags.getAlpha(), canvas.paint_.getAlpha());
-}
-
-// The same as SaveDrawRestore, but test that the optimization doesn't apply
-// when there are more than one ops between the save and restore.
-TEST(PaintOpBufferTest, SaveDrawRestoreFail_TooManyOps) {
-  PaintOpBuffer buffer;
-
-  uint8_t alpha = 100;
-  buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
-
-  PaintFlags draw_flags;
-  draw_flags.setColor(SK_ColorMAGENTA);
-  draw_flags.setAlpha(50);
-  draw_flags.setBlendMode(SkBlendMode::kSrcOver);
-  EXPECT_TRUE(draw_flags.SupportsFoldingAlpha());
-  SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
-  buffer.push<DrawRectOp>(rect, draw_flags);
-  buffer.push<NoopOp>();
-  buffer.push<RestoreOp>();
-
-  SaveCountingCanvas canvas;
-  buffer.playback(&canvas);
-
-  EXPECT_EQ(1, canvas.save_count_);
-  EXPECT_EQ(1, canvas.restore_count_);
-  EXPECT_EQ(rect, canvas.draw_rect_);
-  EXPECT_EQ(draw_flags.getAlpha(), canvas.paint_.getAlpha());
-}
-
-}  // namespace cc
diff --git a/cc/paint/paint_record.cc b/cc/paint/paint_record.cc
deleted file mode 100644
index 52cb2524..0000000
--- a/cc/paint/paint_record.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2017 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/paint/paint_record.h"
-
-#include "cc/paint/paint_op_buffer.h"
-#include "third_party/skia/include/core/SkPictureRecorder.h"
-
-namespace cc {
-
-sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record) {
-  SkPictureRecorder recorder;
-  SkCanvas* canvas = recorder.beginRecording(record->cullRect());
-  record->playback(canvas);
-  return recorder.finishRecordingAsPicture();
-}
-
-sk_sp<const SkPicture> ToSkPicture(sk_sp<const PaintRecord> record) {
-  SkPictureRecorder recorder;
-  SkCanvas* canvas = recorder.beginRecording(record->cullRect());
-  record->playback(canvas);
-  return recorder.finishRecordingAsPicture();
-}
-
-}  // namespace cc
diff --git a/cc/paint/paint_record.h b/cc/paint/paint_record.h
index daeee004..8506606b 100644
--- a/cc/paint/paint_record.h
+++ b/cc/paint/paint_record.h
@@ -5,22 +5,19 @@
 #ifndef CC_PAINT_PAINT_RECORD_H_
 #define CC_PAINT_PAINT_RECORD_H_
 
-#include "cc/paint/paint_export.h"
-#include "cc/paint/paint_op_buffer.h"
 #include "third_party/skia/include/core/SkPicture.h"
 
 namespace cc {
 
-// TODO(enne): Don't want to rename the world for this.  Using these as the
-// same types for now prevents an extra allocation.  Probably PaintRecord
-// will become an interface in the future.
-using PaintRecord = PaintOpBuffer;
+using PaintRecord = SkPicture;
 
-// TODO(enne): Remove these if possible, they are really expensive.
-CC_PAINT_EXPORT sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record);
+inline sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record) {
+  return record;
+}
 
-CC_PAINT_EXPORT sk_sp<const SkPicture> ToSkPicture(
-    sk_sp<const PaintRecord> record);
+inline sk_sp<const SkPicture> ToSkPicture(sk_sp<const PaintRecord> record) {
+  return record;
+}
 
 }  // namespace cc
 
diff --git a/cc/paint/paint_recorder.cc b/cc/paint/paint_recorder.cc
index c43f965..672f0712 100644
--- a/cc/paint/paint_recorder.cc
+++ b/cc/paint/paint_recorder.cc
@@ -4,36 +4,9 @@
 
 #include "cc/paint/paint_recorder.h"
 
-#include "cc/paint/paint_op_buffer.h"
-
 namespace cc {
 
 PaintRecorder::PaintRecorder() = default;
-
 PaintRecorder::~PaintRecorder() = default;
 
-PaintCanvas* PaintRecorder::beginRecording(const SkRect& bounds) {
-  buffer_.reset(new PaintOpBuffer(bounds));
-  canvas_.emplace(buffer_.get(), bounds);
-  return getRecordingCanvas();
-}
-
-sk_sp<PaintRecord> PaintRecorder::finishRecordingAsPicture() {
-  // SkPictureRecorder users expect that their saves are automatically
-  // closed for them.
-  //
-  // NOTE: Blink paint in general doesn't appear to need this, but the
-  // RecordingImageBufferSurface::fallBackToRasterCanvas finishing off the
-  // current frame depends on this.  Maybe we could remove this assumption and
-  // just have callers do it.
-  canvas_->restoreToCount(1);
-
-  // Some users (e.g. printing) use the existence of the recording canvas
-  // to know if recording is finished, so reset it here.
-  canvas_.reset();
-
-  buffer_->ShrinkToFit();
-  return std::move(buffer_);
-}
-
 }  // namespace cc
diff --git a/cc/paint/paint_recorder.h b/cc/paint/paint_recorder.h
index 7f582b85..2bbea83b 100644
--- a/cc/paint/paint_recorder.h
+++ b/cc/paint/paint_recorder.h
@@ -9,36 +9,47 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/optional.h"
+#include "cc/paint/paint_canvas.h"
 #include "cc/paint/paint_record.h"
-#include "cc/paint/record_paint_canvas.h"
+#include "cc/paint/skia_paint_canvas.h"
+#include "third_party/skia/include/core/SkPictureRecorder.h"
 
 namespace cc {
 
-class PaintOpBuffer;
-
 class CC_PAINT_EXPORT PaintRecorder {
  public:
   PaintRecorder();
   ~PaintRecorder();
 
-  PaintCanvas* beginRecording(const SkRect& bounds);
+  ALWAYS_INLINE PaintCanvas* beginRecording(const SkRect& bounds) {
+    uint32_t record_flags = 0;
+    canvas_.emplace(recorder_.beginRecording(bounds, nullptr, record_flags));
+    return getRecordingCanvas();
+  }
 
-  // TODO(enne): should make everything go through the non-rect version.
-  // See comments in RecordPaintCanvas ctor for why.
-  PaintCanvas* beginRecording(SkScalar width, SkScalar height) {
-    return beginRecording(SkRect::MakeWH(width, height));
+  ALWAYS_INLINE PaintCanvas* beginRecording(SkScalar width, SkScalar height) {
+    uint32_t record_flags = 0;
+    canvas_.emplace(
+        recorder_.beginRecording(width, height, nullptr, record_flags));
+    return getRecordingCanvas();
   }
 
   // Only valid between between and finish recording.
-  ALWAYS_INLINE RecordPaintCanvas* getRecordingCanvas() {
+  ALWAYS_INLINE PaintCanvas* getRecordingCanvas() {
     return canvas_.has_value() ? &canvas_.value() : nullptr;
   }
 
-  sk_sp<PaintRecord> finishRecordingAsPicture();
+  ALWAYS_INLINE sk_sp<PaintRecord> finishRecordingAsPicture() {
+    sk_sp<SkPicture> picture = recorder_.finishRecordingAsPicture();
+    // Some users (e.g. printing) use the existence of the recording canvas
+    // to know if recording is finished, so reset it here.
+    canvas_.reset();
+    return sk_ref_sp(static_cast<PaintRecord*>(picture.get()));
+  }
 
  private:
-  sk_sp<PaintOpBuffer> buffer_;
-  base::Optional<RecordPaintCanvas> canvas_;
+  SkPictureRecorder recorder_;
+  base::Optional<SkiaPaintCanvas> canvas_;
 
   DISALLOW_COPY_AND_ASSIGN(PaintRecorder);
 };
diff --git a/cc/paint/record_paint_canvas.cc b/cc/paint/record_paint_canvas.cc
deleted file mode 100644
index 7f2ba61..0000000
--- a/cc/paint/record_paint_canvas.cc
+++ /dev/null
@@ -1,384 +0,0 @@
-// Copyright 2017 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/paint/record_paint_canvas.h"
-
-#include "base/memory/ptr_util.h"
-#include "cc/paint/display_item_list.h"
-#include "cc/paint/paint_op_buffer.h"
-#include "cc/paint/paint_record.h"
-#include "cc/paint/paint_recorder.h"
-#include "third_party/skia/include/core/SkAnnotation.h"
-#include "third_party/skia/include/core/SkMetaData.h"
-#include "third_party/skia/include/utils/SkNWayCanvas.h"
-
-namespace cc {
-
-RecordPaintCanvas::RecordPaintCanvas(PaintOpBuffer* buffer,
-                                     const SkRect& cull_rect)
-    : buffer_(buffer),
-      canvas_(static_cast<int>(std::ceil(cull_rect.right())),
-              static_cast<int>(std::ceil(cull_rect.bottom()))) {
-  DCHECK(buffer_);
-
-  // This is part of the "recording canvases have a size, but why" dance.
-  // By creating a canvas of size (right x bottom) and then clipping it,
-  // It makes getDeviceClipBounds return the original cull rect, which code
-  // in GraphicsContextCanvas on Mac expects.  (Just creating an SkNoDrawCanvas
-  // with the cull_rect makes a canvas of size (width x height) instead
-  // which is incorrect.  SkRecorder cheats with private resetForNextCanvas.
-  canvas_.clipRect(SkRect::Make(cull_rect.roundOut()), SkClipOp::kIntersect,
-                   false);
-}
-
-RecordPaintCanvas::~RecordPaintCanvas() = default;
-
-SkMetaData& RecordPaintCanvas::getMetaData() {
-  // This could just be SkMetaData owned by RecordPaintCanvas, but since
-  // SkCanvas already has one, we might as well use it directly.
-  return canvas_.getMetaData();
-}
-
-SkImageInfo RecordPaintCanvas::imageInfo() const {
-  return canvas_.imageInfo();
-}
-
-void RecordPaintCanvas::flush() {
-  // This is a noop when recording.
-}
-
-SkISize RecordPaintCanvas::getBaseLayerSize() const {
-  return canvas_.getBaseLayerSize();
-}
-
-bool RecordPaintCanvas::writePixels(const SkImageInfo& info,
-                                    const void* pixels,
-                                    size_t row_bytes,
-                                    int x,
-                                    int y) {
-  NOTREACHED();
-  return false;
-}
-
-int RecordPaintCanvas::save() {
-  buffer_->push<SaveOp>();
-  return canvas_.save();
-}
-
-int RecordPaintCanvas::saveLayer(const SkRect* bounds,
-                                 const PaintFlags* flags) {
-  if (flags) {
-    if (flags->IsSimpleOpacity()) {
-      // TODO(enne): maybe more callers should know this and call
-      // saveLayerAlpha instead of needing to check here.
-      uint8_t alpha = SkColorGetA(flags->getColor());
-      return saveLayerAlpha(bounds, alpha);
-    }
-
-    // TODO(enne): it appears that image filters affect matrices and color
-    // matrices affect transparent flags on SkCanvas layers, but it's not clear
-    // whether those are actually needed and we could just skip ToSkPaint here.
-    buffer_->push<SaveLayerOp>(bounds, flags);
-    const SkPaint& paint = ToSkPaint(*flags);
-    return canvas_.saveLayer(bounds, &paint);
-  }
-  buffer_->push<SaveLayerOp>(bounds, flags);
-  return canvas_.saveLayer(bounds, nullptr);
-}
-
-int RecordPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) {
-  buffer_->push<SaveLayerAlphaOp>(bounds, alpha);
-  return canvas_.saveLayerAlpha(bounds, alpha);
-}
-
-void RecordPaintCanvas::restore() {
-  buffer_->push<RestoreOp>();
-  canvas_.restore();
-}
-
-int RecordPaintCanvas::getSaveCount() const {
-  return canvas_.getSaveCount();
-}
-
-void RecordPaintCanvas::restoreToCount(int save_count) {
-  DCHECK_GE(save_count, 1);
-  int diff = canvas_.getSaveCount() - save_count;
-  DCHECK_GE(diff, 0);
-  for (int i = 0; i < diff; ++i)
-    restore();
-}
-
-void RecordPaintCanvas::translate(SkScalar dx, SkScalar dy) {
-  buffer_->push<TranslateOp>(dx, dy);
-  canvas_.translate(dx, dy);
-}
-
-void RecordPaintCanvas::scale(SkScalar sx, SkScalar sy) {
-  buffer_->push<ScaleOp>(sx, sy);
-  canvas_.scale(sx, sy);
-}
-
-void RecordPaintCanvas::rotate(SkScalar degrees) {
-  buffer_->push<RotateOp>(degrees);
-  canvas_.rotate(degrees);
-}
-
-void RecordPaintCanvas::concat(const SkMatrix& matrix) {
-  buffer_->push<ConcatOp>(matrix);
-  canvas_.concat(matrix);
-}
-
-void RecordPaintCanvas::setMatrix(const SkMatrix& matrix) {
-  buffer_->push<SetMatrixOp>(matrix);
-  canvas_.setMatrix(matrix);
-}
-
-void RecordPaintCanvas::clipRect(const SkRect& rect,
-                                 SkClipOp op,
-                                 bool antialias) {
-  buffer_->push<ClipRectOp>(rect, op, antialias);
-  canvas_.clipRect(rect, op, antialias);
-}
-
-void RecordPaintCanvas::clipRRect(const SkRRect& rrect,
-                                  SkClipOp op,
-                                  bool antialias) {
-  // TODO(enne): does this happen? Should the caller know this?
-  if (rrect.isRect()) {
-    clipRect(rrect.getBounds(), op, antialias);
-    return;
-  }
-  buffer_->push<ClipRRectOp>(rrect, op, antialias);
-  canvas_.clipRRect(rrect, op, antialias);
-}
-
-void RecordPaintCanvas::clipPath(const SkPath& path,
-                                 SkClipOp op,
-                                 bool antialias) {
-  if (!path.isInverseFillType() && canvas_.getTotalMatrix().rectStaysRect()) {
-    // TODO(enne): do these cases happen? should the caller know that this isn't
-    // a path?
-    SkRect rect;
-    if (path.isRect(&rect)) {
-      clipRect(rect, op, antialias);
-      return;
-    }
-    SkRRect rrect;
-    if (path.isOval(&rect)) {
-      rrect.setOval(rect);
-      clipRRect(rrect, op, antialias);
-      return;
-    }
-    if (path.isRRect(&rrect)) {
-      clipRRect(rrect, op, antialias);
-      return;
-    }
-  }
-
-  buffer_->push<ClipPathOp>(path, op, antialias);
-  canvas_.clipPath(path, op, antialias);
-  return;
-}
-
-bool RecordPaintCanvas::quickReject(const SkRect& rect) const {
-  return canvas_.quickReject(rect);
-}
-
-bool RecordPaintCanvas::quickReject(const SkPath& path) const {
-  return canvas_.quickReject(path);
-}
-
-SkRect RecordPaintCanvas::getLocalClipBounds() const {
-  return canvas_.getLocalClipBounds();
-}
-
-bool RecordPaintCanvas::getLocalClipBounds(SkRect* bounds) const {
-  return canvas_.getLocalClipBounds(bounds);
-}
-
-SkIRect RecordPaintCanvas::getDeviceClipBounds() const {
-  return canvas_.getDeviceClipBounds();
-}
-
-bool RecordPaintCanvas::getDeviceClipBounds(SkIRect* bounds) const {
-  return canvas_.getDeviceClipBounds(bounds);
-}
-
-void RecordPaintCanvas::drawColor(SkColor color, SkBlendMode mode) {
-  buffer_->push<DrawColorOp>(color, mode);
-}
-
-void RecordPaintCanvas::clear(SkColor color) {
-  buffer_->push<DrawColorOp>(color, SkBlendMode::kSrc);
-}
-
-void RecordPaintCanvas::drawLine(SkScalar x0,
-                                 SkScalar y0,
-                                 SkScalar x1,
-                                 SkScalar y1,
-                                 const PaintFlags& flags) {
-  buffer_->push<DrawLineOp>(x0, y0, x1, y1, flags);
-}
-
-void RecordPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) {
-  buffer_->push<DrawRectOp>(rect, flags);
-}
-
-void RecordPaintCanvas::drawIRect(const SkIRect& rect,
-                                  const PaintFlags& flags) {
-  buffer_->push<DrawIRectOp>(rect, flags);
-}
-
-void RecordPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) {
-  buffer_->push<DrawOvalOp>(oval, flags);
-}
-
-void RecordPaintCanvas::drawRRect(const SkRRect& rrect,
-                                  const PaintFlags& flags) {
-  buffer_->push<DrawRRectOp>(rrect, flags);
-}
-
-void RecordPaintCanvas::drawDRRect(const SkRRect& outer,
-                                   const SkRRect& inner,
-                                   const PaintFlags& flags) {
-  if (outer.isEmpty())
-    return;
-  if (inner.isEmpty()) {
-    drawRRect(outer, flags);
-    return;
-  }
-  buffer_->push<DrawDRRectOp>(outer, inner, flags);
-}
-
-void RecordPaintCanvas::drawCircle(SkScalar cx,
-                                   SkScalar cy,
-                                   SkScalar radius,
-                                   const PaintFlags& flags) {
-  buffer_->push<DrawCircleOp>(cx, cy, radius, flags);
-}
-
-void RecordPaintCanvas::drawArc(const SkRect& oval,
-                                SkScalar start_angle,
-                                SkScalar sweep_angle,
-                                bool use_center,
-                                const PaintFlags& flags) {
-  buffer_->push<DrawArcOp>(oval, start_angle, sweep_angle, use_center, flags);
-}
-
-void RecordPaintCanvas::drawRoundRect(const SkRect& rect,
-                                      SkScalar rx,
-                                      SkScalar ry,
-                                      const PaintFlags& flags) {
-  // TODO(enne): move this into base class?
-  if (rx > 0 && ry > 0) {
-    SkRRect rrect;
-    rrect.setRectXY(rect, rx, ry);
-    drawRRect(rrect, flags);
-  } else {
-    drawRect(rect, flags);
-  }
-}
-
-void RecordPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) {
-  buffer_->push<DrawPathOp>(path, flags);
-}
-
-void RecordPaintCanvas::drawImage(const PaintImage& image,
-                                  SkScalar left,
-                                  SkScalar top,
-                                  const PaintFlags* flags) {
-  buffer_->push<DrawImageOp>(image, left, top, flags);
-}
-
-void RecordPaintCanvas::drawImageRect(const PaintImage& image,
-                                      const SkRect& src,
-                                      const SkRect& dst,
-                                      const PaintFlags* flags,
-                                      SrcRectConstraint constraint) {
-  buffer_->push<DrawImageRectOp>(image, src, dst, flags, constraint);
-}
-
-void RecordPaintCanvas::drawBitmap(const SkBitmap& bitmap,
-                                   SkScalar left,
-                                   SkScalar top,
-                                   const PaintFlags* flags) {
-  // TODO(enne): Move into base class?
-  if (bitmap.drawsNothing())
-    return;
-  drawImage(PaintImage(SkImage::MakeFromBitmap(bitmap),
-                       PaintImage::AnimationType::UNKNOWN,
-                       PaintImage::CompletionState::UNKNOWN),
-            left, top, flags);
-}
-
-void RecordPaintCanvas::drawText(const void* text,
-                                 size_t byte_length,
-                                 SkScalar x,
-                                 SkScalar y,
-                                 const PaintFlags& flags) {
-  buffer_->push_with_data<DrawTextOp>(text, byte_length, x, y, flags);
-}
-
-void RecordPaintCanvas::drawPosText(const void* text,
-                                    size_t byte_length,
-                                    const SkPoint pos[],
-                                    const PaintFlags& flags) {
-  size_t count = ToSkPaint(flags).countText(text, byte_length);
-  buffer_->push_with_data_array<DrawPosTextOp>(text, byte_length, pos, count,
-                                               flags);
-}
-
-void RecordPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob,
-                                     SkScalar x,
-                                     SkScalar y,
-                                     const PaintFlags& flags) {
-  buffer_->push<DrawTextBlobOp>(blob, x, y, flags);
-}
-
-void RecordPaintCanvas::drawDisplayItemList(
-    scoped_refptr<DisplayItemList> list) {
-  buffer_->push<DrawDisplayItemListOp>(list);
-}
-
-void RecordPaintCanvas::drawPicture(sk_sp<const PaintRecord> record) {
-  // TODO(enne): If this is small, maybe flatten it?
-  buffer_->push<DrawRecordOp>(record);
-}
-
-bool RecordPaintCanvas::isClipEmpty() const {
-  return canvas_.isClipEmpty();
-}
-
-bool RecordPaintCanvas::isClipRect() const {
-  return canvas_.isClipRect();
-}
-
-const SkMatrix& RecordPaintCanvas::getTotalMatrix() const {
-  return canvas_.getTotalMatrix();
-}
-
-void RecordPaintCanvas::temporary_internal_describeTopLayer(
-    SkMatrix* matrix,
-    SkIRect* clip_bounds) {
-  return canvas_.temporary_internal_describeTopLayer(matrix, clip_bounds);
-}
-
-bool RecordPaintCanvas::ToPixmap(SkPixmap* output) {
-  // TODO(enne): It'd be nice to make this NOTREACHED() or remove this from
-  // RecordPaintCanvas, but this is used by GraphicsContextCanvas for knowing
-  // whether or not it can raster directly into pixels with Cg.
-  return false;
-}
-
-void RecordPaintCanvas::Annotate(AnnotationType type,
-                                 const SkRect& rect,
-                                 sk_sp<SkData> data) {
-  buffer_->push<AnnotateOp>(type, rect, data);
-}
-
-void RecordPaintCanvas::PlaybackPaintRecord(sk_sp<const PaintRecord> record) {
-  drawPicture(record);
-}
-
-}  // namespace cc
diff --git a/cc/paint/record_paint_canvas.h b/cc/paint/record_paint_canvas.h
deleted file mode 100644
index 15f0102..0000000
--- a/cc/paint/record_paint_canvas.h
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2017 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_PAINT_RECORD_PAINT_CANVAS_H_
-#define CC_PAINT_RECORD_PAINT_CANVAS_H_
-
-#include <memory>
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "cc/paint/paint_canvas.h"
-#include "cc/paint/paint_flags.h"
-#include "cc/paint/paint_record.h"
-#include "third_party/skia/include/utils/SkNoDrawCanvas.h"
-
-namespace cc {
-
-class PaintOpBuffer;
-class PaintFlags;
-
-class CC_PAINT_EXPORT RecordPaintCanvas final : public PaintCanvas {
- public:
-  explicit RecordPaintCanvas(PaintOpBuffer* buffer, const SkRect& cull_rect);
-  ~RecordPaintCanvas() override;
-
-  SkMetaData& getMetaData() override;
-  SkImageInfo imageInfo() const override;
-
-  void flush() override;
-
-  SkISize getBaseLayerSize() const override;
-  bool writePixels(const SkImageInfo& info,
-                   const void* pixels,
-                   size_t row_bytes,
-                   int x,
-                   int y) override;
-  int save() override;
-  int saveLayer(const SkRect* bounds, const PaintFlags* flags) override;
-  int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) override;
-
-  void restore() override;
-  int getSaveCount() const override;
-  void restoreToCount(int save_count) override;
-  void translate(SkScalar dx, SkScalar dy) override;
-  void scale(SkScalar sx, SkScalar sy) override;
-  void rotate(SkScalar degrees) override;
-  void concat(const SkMatrix& matrix) override;
-  void setMatrix(const SkMatrix& matrix) override;
-
-  void clipRect(const SkRect& rect, SkClipOp op, bool antialias) override;
-  void clipRRect(const SkRRect& rrect, SkClipOp op, bool antialias) override;
-  void clipPath(const SkPath& path, SkClipOp op, bool antialias) override;
-  bool quickReject(const SkRect& rect) const override;
-  bool quickReject(const SkPath& path) const override;
-  SkRect getLocalClipBounds() const override;
-  bool getLocalClipBounds(SkRect* bounds) const override;
-  SkIRect getDeviceClipBounds() const override;
-  bool getDeviceClipBounds(SkIRect* bounds) const override;
-  void drawColor(SkColor color, SkBlendMode mode) override;
-  void clear(SkColor color) override;
-
-  void drawLine(SkScalar x0,
-                SkScalar y0,
-                SkScalar x1,
-                SkScalar y1,
-                const PaintFlags& flags) override;
-  void drawRect(const SkRect& rect, const PaintFlags& flags) override;
-  void drawIRect(const SkIRect& rect, const PaintFlags& flags) override;
-  void drawOval(const SkRect& oval, const PaintFlags& flags) override;
-  void drawRRect(const SkRRect& rrect, const PaintFlags& flags) override;
-  void drawDRRect(const SkRRect& outer,
-                  const SkRRect& inner,
-                  const PaintFlags& flags) override;
-  void drawCircle(SkScalar cx,
-                  SkScalar cy,
-                  SkScalar radius,
-                  const PaintFlags& flags) override;
-  void drawArc(const SkRect& oval,
-               SkScalar start_angle,
-               SkScalar sweep_angle,
-               bool use_center,
-               const PaintFlags& flags) override;
-  void drawRoundRect(const SkRect& rect,
-                     SkScalar rx,
-                     SkScalar ry,
-                     const PaintFlags& flags) override;
-  void drawPath(const SkPath& path, const PaintFlags& flags) override;
-  void drawImage(const PaintImage& image,
-                 SkScalar left,
-                 SkScalar top,
-                 const PaintFlags* flags) override;
-  void drawImageRect(const PaintImage& image,
-                     const SkRect& src,
-                     const SkRect& dst,
-                     const PaintFlags* flags,
-                     SrcRectConstraint constraint) override;
-  void drawBitmap(const SkBitmap& bitmap,
-                  SkScalar left,
-                  SkScalar top,
-                  const PaintFlags* flags) override;
-
-  void drawText(const void* text,
-                size_t byte_length,
-                SkScalar x,
-                SkScalar y,
-                const PaintFlags& flags) override;
-  void drawPosText(const void* text,
-                   size_t byte_length,
-                   const SkPoint pos[],
-                   const PaintFlags& flags) override;
-  void drawTextBlob(sk_sp<SkTextBlob> blob,
-                    SkScalar x,
-                    SkScalar y,
-                    const PaintFlags& flags) override;
-
-  void drawDisplayItemList(
-      scoped_refptr<DisplayItemList> display_item_list) override;
-
-  void drawPicture(sk_sp<const PaintRecord> record) override;
-
-  bool isClipEmpty() const override;
-  bool isClipRect() const override;
-  const SkMatrix& getTotalMatrix() const override;
-
-  void temporary_internal_describeTopLayer(SkMatrix* matrix,
-                                           SkIRect* clip_bounds) override;
-
-  bool ToPixmap(SkPixmap* output) override;
-  void Annotate(AnnotationType type,
-                const SkRect& rect,
-                sk_sp<SkData> data) override;
-
-  void PlaybackPaintRecord(sk_sp<const PaintRecord> record) override;
-
-  // Don't shadow non-virtual helper functions.
-  using PaintCanvas::clipRect;
-  using PaintCanvas::clipRRect;
-  using PaintCanvas::clipPath;
-  using PaintCanvas::drawBitmap;
-  using PaintCanvas::drawColor;
-  using PaintCanvas::drawImage;
-  using PaintCanvas::drawPicture;
-
- private:
-  PaintOpBuffer* buffer_;
-
-  // TODO(enne): Although RecordPaintCanvas is mostly a write-only interface
-  // where paint commands are stored, occasionally users of PaintCanvas want
-  // to ask stateful questions mid-stream of clip and transform state.
-  // To avoid duplicating all this code (for now?), just forward to an SkCanvas
-  // that's not backed by anything but can answer these questions.
-  SkNoDrawCanvas canvas_;
-};
-
-}  // namespace cc
-
-#endif  // CC_PAINT_RECORD_PAINT_CANVAS_H_
diff --git a/cc/paint/skia_paint_canvas.cc b/cc/paint/skia_paint_canvas.cc
index 501ccdf..bfc38b6 100644
--- a/cc/paint/skia_paint_canvas.cc
+++ b/cc/paint/skia_paint_canvas.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/paint/skia_paint_canvas.h"
+#include "cc/paint/paint_canvas.h"
 
 #include "base/memory/ptr_util.h"
 #include "cc/paint/display_item_list.h"
@@ -58,7 +58,7 @@
   return canvas_->saveLayer(bounds, ToSkPaint(flags));
 }
 
-int SkiaPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) {
+int SkiaPaintCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
   return canvas_->saveLayerAlpha(bounds, alpha);
 }
 
diff --git a/cc/paint/skia_paint_canvas.h b/cc/paint/skia_paint_canvas.h
index 1bd23f0..47dba86 100644
--- a/cc/paint/skia_paint_canvas.h
+++ b/cc/paint/skia_paint_canvas.h
@@ -46,7 +46,7 @@
                    int y) override;
   int save() override;
   int saveLayer(const SkRect* bounds, const PaintFlags* flags) override;
-  int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) override;
+  int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) override;
 
   void restore() override;
   int getSaveCount() const override;
diff --git a/cc/test/test_skcanvas.cc b/cc/test/test_skcanvas.cc
deleted file mode 100644
index e45f42de..0000000
--- a/cc/test/test_skcanvas.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2017 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/test/test_skcanvas.h"
-
-namespace cc {
-
-SaveCountingCanvas::SaveCountingCanvas() : SkNoDrawCanvas(100, 100) {}
-
-SkCanvas::SaveLayerStrategy SaveCountingCanvas::getSaveLayerStrategy(
-    const SaveLayerRec& rec) {
-  save_count_++;
-  return SkNoDrawCanvas::getSaveLayerStrategy(rec);
-}
-
-void SaveCountingCanvas::willRestore() {
-  restore_count_++;
-}
-
-void SaveCountingCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
-  draw_rect_ = rect;
-  paint_ = paint;
-}
-
-}  // namespace cc
diff --git a/cc/test/test_skcanvas.h b/cc/test/test_skcanvas.h
deleted file mode 100644
index 2b130a4..0000000
--- a/cc/test/test_skcanvas.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2017 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_TEST_TEST_SKCANVAS_H_
-#define CC_TEST_TEST_SKCANVAS_H_
-
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/utils/SkNoDrawCanvas.h"
-
-namespace cc {
-
-class SaveCountingCanvas : public SkNoDrawCanvas {
- public:
-  SaveCountingCanvas();
-
-  // Note: getSaveLayerStrategy is used as "willSave", as willSave
-  // is not always called.
-  SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override;
-  void willRestore() override;
-  void onDrawRect(const SkRect& rect, const SkPaint& paint) override;
-
-  int save_count_ = 0;
-  int restore_count_ = 0;
-  SkRect draw_rect_;
-  SkPaint paint_;
-};
-
-}  // namespace cc
-
-#endif  // CC_TEST_TEST_SKCANVAS_H_
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index aff7e4b..36ce866 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -596,7 +596,7 @@
             @Override
             public void onPageLoadFinished(Tab tab) {
                 postDeferredStartupIfNeeded();
-                OfflinePageUtils.showOfflineSnackbarIfNecessary(ChromeActivity.this, tab);
+                OfflinePageUtils.showOfflineSnackbarIfNecessary(tab);
             }
 
             @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java
index d017519..04015df1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java
@@ -4,17 +4,22 @@
 
 package org.chromium.chrome.browser.offlinepages;
 
-import android.content.Context;
+import android.app.Activity;
 
+import org.chromium.base.ActivityState;
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.ApplicationStatus.ActivityStateListener;
 import org.chromium.base.Log;
 import org.chromium.base.VisibleForTesting;
+import org.chromium.base.metrics.RecordUserAction;
+import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
-import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver;
 import org.chromium.net.NetworkChangeNotifier;
 
 import java.util.HashMap;
@@ -52,52 +57,50 @@
         }
     }
 
-    /** Class for observing TabModel without implementing a full interface. */
-    private class TabModelObserverImpl extends EmptyTabModelObserver {
-        public TabModelObserverImpl(TabModel model) {
-            if (model != null) {
-                model.addObserver(this);
-            }
-        }
+    private static Map<Activity, OfflinePageTabObserver> sObservers;
 
-        @Override
-        public void tabRemoved(Tab tab) {
-            Log.d(TAG, "tabRemoved");
-            OfflinePageTabObserver.this.stopObservingTab(tab);
-            OfflinePageTabObserver.this.mSnackbarManager.dismissSnackbars(mSnackbarController);
-        }
-    }
-
-    private Context mContext;
-    private SnackbarManager mSnackbarManager;
-    private SnackbarController mSnackbarController;
-    private TabModelObserverImpl mTabModelObserver;
-
+    private final SnackbarManager mSnackbarManager;
+    private final SnackbarController mSnackbarController;
+    private final TabModelSelector mTabModelSelector;
+    private final TabModelSelectorTabModelObserver mTabModelObserver;
     /** Map of observed tabs. */
     private final Map<Integer, TabState> mObservedTabs = new HashMap<>();
+
     private boolean mIsObservingNetworkChanges;
 
     /** Current tab, kept track of for the network change notification. */
     private Tab mCurrentTab;
 
-    private static OfflinePageTabObserver sInstance;
-
-    static void init(Context context, TabModel tabModel, SnackbarManager manager,
-            SnackbarController controller) {
-        if (sInstance == null) {
-            sInstance = new OfflinePageTabObserver(context, tabModel, manager, controller);
-            return;
+    static OfflinePageTabObserver getObserverForActivity(ChromeActivity activity) {
+        ensureObserverMapInitialized();
+        OfflinePageTabObserver observer = sObservers.get(activity);
+        if (observer == null) {
+            observer = new OfflinePageTabObserver(activity.getTabModelSelector(),
+                    activity.getSnackbarManager(),
+                    createReloadSnackbarController(activity.getTabModelSelector()));
+            sObservers.put(activity, observer);
         }
-        sInstance.reinitialize(context, tabModel, manager, controller);
+        return observer;
     }
 
-    static OfflinePageTabObserver getInstance() {
-        return sInstance;
+    private static void ensureObserverMapInitialized() {
+        if (sObservers != null) return;
+        sObservers = new HashMap<>();
+        ApplicationStatus.registerStateListenerForAllActivities(new ActivityStateListener() {
+            @Override
+            public void onActivityStateChange(Activity activity, int newState) {
+                if (newState != ActivityState.DESTROYED) return;
+                OfflinePageTabObserver observer = sObservers.remove(activity);
+                if (observer == null) return;
+                observer.destroy();
+            }
+        });
     }
 
     @VisibleForTesting
-    static void setInstanceForTesting(OfflinePageTabObserver instance) {
-        sInstance = instance;
+    static void setObserverForTesting(Activity activity, OfflinePageTabObserver observer) {
+        ensureObserverMapInitialized();
+        sObservers.put(activity, observer);
     }
 
     /**
@@ -105,22 +108,31 @@
      * @param tab The tab we are adding an observer for.
      */
     public static void addObserverForTab(Tab tab) {
-        assert getInstance() != null;
-        getInstance().startObservingTab(tab);
-        getInstance().maybeShowReloadSnackbar(tab, false);
+        OfflinePageTabObserver observer = getObserverForActivity(tab.getActivity());
+        assert observer != null;
+        observer.startObservingTab(tab);
+        observer.maybeShowReloadSnackbar(tab, false);
     }
 
     /**
      * Builds a new OfflinePageTabObserver.
-     * @param context Android context.
-     * @param tabModel Tab model managing the observerd tab.
+     * @param tabModelSelector Tab model selector for the activity.
      * @param snackbarManager The snackbar manager to show and dismiss snackbars.
      * @param snackbarController Controller to use to build the snackbar.
      */
-    OfflinePageTabObserver(Context context, TabModel tabModel, SnackbarManager snackbarManager,
+    OfflinePageTabObserver(TabModelSelector tabModelSelector, SnackbarManager snackbarManager,
             SnackbarController snackbarController) {
-        reinitialize(context, tabModel, snackbarManager, snackbarController);
-
+        mSnackbarManager = snackbarManager;
+        mSnackbarController = snackbarController;
+        mTabModelSelector = tabModelSelector;
+        mTabModelObserver = new TabModelSelectorTabModelObserver(tabModelSelector) {
+            @Override
+            public void tabRemoved(Tab tab) {
+                Log.d(TAG, "tabRemoved");
+                stopObservingTab(tab);
+                mSnackbarManager.dismissSnackbars(mSnackbarController);
+            }
+        };
         // The first time observer is created snackbar has net yet been shown.
         mIsObservingNetworkChanges = false;
     }
@@ -209,6 +221,22 @@
         }
     }
 
+    private void destroy() {
+        mTabModelObserver.destroy();
+        if (!mObservedTabs.isEmpty()) {
+            for (Integer tabId : mObservedTabs.keySet()) {
+                Tab tab = mTabModelSelector.getTabById(tabId);
+                if (tab == null) continue;
+                tab.removeObserver(this);
+            }
+            mObservedTabs.clear();
+        }
+        if (isObservingNetworkChanges()) {
+            stopObservingNetworkChanges();
+            mIsObservingNetworkChanges = false;
+        }
+    }
+
     // Methods from ConnectionTypeObserver.
     @Override
     public void onConnectionTypeChanged(int connectionType) {
@@ -273,7 +301,7 @@
     @VisibleForTesting
     void showReloadSnackbar(Tab tab) {
         OfflinePageUtils.showReloadSnackbar(
-                mContext, mSnackbarManager, mSnackbarController, tab.getId());
+                tab.getActivity(), mSnackbarManager, mSnackbarController, tab.getId());
     }
 
     @VisibleForTesting
@@ -291,15 +319,31 @@
         return mTabModelObserver;
     }
 
-    boolean isCurrentContext(Context context) {
-        return mContext == context;
-    }
+    /**
+     * Gets a snackbar controller that we can use to show our snackbar.
+     * @param tabModelSelector used to retrieve a tab by ID
+     */
+    private static SnackbarController createReloadSnackbarController(
+            final TabModelSelector tabModelSelector) {
+        Log.d(TAG, "building snackbar controller");
 
-    void reinitialize(Context context, TabModel tabModel, SnackbarManager manager,
-            SnackbarController controller) {
-        mContext = context;
-        mSnackbarManager = manager;
-        mSnackbarController = controller;
-        mTabModelObserver = this.new TabModelObserverImpl(tabModel);
+        return new SnackbarController() {
+            @Override
+            public void onAction(Object actionData) {
+                assert actionData != null;
+                int tabId = (int) actionData;
+                RecordUserAction.record("OfflinePages.ReloadButtonClicked");
+                Tab foundTab = tabModelSelector.getTabById(tabId);
+                if (foundTab == null) return;
+                // Delegates to Tab to reload the page. Tab will send the correct header in order to
+                // load the right page.
+                foundTab.reload();
+            }
+
+            @Override
+            public void onDismissNoAction(Object actionData) {
+                RecordUserAction.record("OfflinePages.ReloadButtonNotClicked");
+            }
+        };
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
index 17231325..47709b4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
@@ -18,7 +18,6 @@
 import org.chromium.base.StreamUtil;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.UrlConstants;
@@ -196,32 +195,9 @@
 
     /**
      * Shows the snackbar for the current tab to provide offline specific information if needed.
-     * @param activity The activity owning the tab.
      * @param tab The current tab.
      */
-    public static void showOfflineSnackbarIfNecessary(ChromeActivity activity, Tab tab) {
-        if (OfflinePageTabObserver.getInstance() == null
-                || !OfflinePageTabObserver.getInstance().isCurrentContext(
-                           activity.getBaseContext())) {
-            SnackbarController snackbarController =
-                    createReloadSnackbarController(activity.getTabModelSelector());
-            OfflinePageTabObserver.init(activity.getBaseContext(),
-                    activity.getTabModelSelector().getModel(false), activity.getSnackbarManager(),
-                    snackbarController);
-        }
-
-        showOfflineSnackbarIfNecessary(tab);
-    }
-
-    /**
-     * Shows the snackbar for the current tab to provide offline specific information if needed.
-     * This method is used by testing for dependency injecting a snackbar controller.
-     * @param context android context
-     * @param snackbarManager The snackbar manager to show and dismiss snackbars.
-     * @param tab The current tab.
-     * @param snackbarController The snackbar controller to control snackbar behavior.
-     */
-    static void showOfflineSnackbarIfNecessary(Tab tab) {
+    public static void showOfflineSnackbarIfNecessary(Tab tab) {
         // Set up the tab observer to watch for the tab being shown (not hidden) and a valid
         // connection. When both conditions are met a snackbar is shown.
         OfflinePageTabObserver.addObserverForTab(tab);
@@ -245,33 +221,6 @@
         snackbarManager.showSnackbar(snackbar);
     }
 
-    /**
-     * Gets a snackbar controller that we can use to show our snackbar.
-     * @param tabModelSelector used to retrieve a tab by ID
-     */
-    private static SnackbarController createReloadSnackbarController(
-            final TabModelSelector tabModelSelector) {
-        Log.d(TAG, "building snackbar controller");
-
-        return new SnackbarController() {
-            @Override
-            public void onAction(Object actionData) {
-                assert actionData != null;
-                int tabId = (int) actionData;
-                RecordUserAction.record("OfflinePages.ReloadButtonClicked");
-                Tab foundTab = tabModelSelector.getTabById(tabId);
-                if (foundTab == null) return;
-                // Delegates to Tab to reload the page. Tab will send the correct header in order to
-                // load the right page.
-                foundTab.reload();
-            }
-
-            @Override
-            public void onDismissNoAction(Object actionData) {
-                RecordUserAction.record("OfflinePages.ReloadButtonNotClicked");
-            }
-        };
-    }
 
     /**
      * Records UMA data when the Offline Pages Background Load service awakens.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
index 3904cf5..a08fc8f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -244,6 +244,16 @@
 
         @Override
         public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+            if (!canMoveSheet()) {
+                // Currently it's possible to enter the tab switcher after an onScroll() event has
+                // began. If that happens, reset the sheet offset and return false to end the scroll
+                // event.
+                // TODO(twellington): Remove this after it is no longer possible to close the NTP
+                // while moving the BottomSheet.
+                setSheetState(SHEET_STATE_PEEK, false);
+                return false;
+            }
+
             // Only start scrolling if the scroll is up or down. If the user is already scrolling,
             // continue moving the sheet.
             float slope = Math.abs(distanceX) > 0f ? Math.abs(distanceY) / Math.abs(distanceX) : 0f;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java
index 9e2cb362..43e5b9c9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java
@@ -168,9 +168,10 @@
         ThreadUtils.runOnUiThread(new Runnable() {
             @Override
             public void run() {
-                OfflinePageTabObserver.init(getActivity().getBaseContext(),
-                        getActivity().getTabModelSelector().getModel(false),
-                        getActivity().getSnackbarManager(), mockSnackbarController);
+                OfflinePageTabObserver offlineObserver =
+                        new OfflinePageTabObserver(getActivity().getTabModelSelector(),
+                                getActivity().getSnackbarManager(), mockSnackbarController);
+                OfflinePageTabObserver.setObserverForTesting(getActivity(), offlineObserver);
                 OfflinePageUtils.showOfflineSnackbarIfNecessary(getActivity().getActivityTab());
 
                 // Pretend that we went online, this should cause the snackbar to show.
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java
index de01ab6c..6eb6186 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java
@@ -6,20 +6,17 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.any;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import android.content.Context;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
@@ -27,10 +24,11 @@
 
 import org.chromium.base.BaseChromiumApplication;
 import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.testing.local.LocalRobolectricTestRunner;
 
 /**
@@ -43,16 +41,17 @@
     // Using a null tab, as it cannot be mocked. TabHelper will help return proper mocked responses.
     private static final int TAB_ID = 77;
 
-    @Mock private Context mContext;
     @Mock
-    private TabModel mTabModel;
+    private ChromeActivity mActivity;
+    @Mock
+    private TabModelSelector mTabModelSelector;
     @Mock private SnackbarManager mSnackbarManager;
     @Mock private SnackbarController mSnackbarController;
     @Mock private Tab mTab;
 
     private OfflinePageTabObserver createObserver() {
         OfflinePageTabObserver observer = spy(new OfflinePageTabObserver(
-                mContext, mTabModel, mSnackbarManager, mSnackbarController));
+                mTabModelSelector, mSnackbarManager, mSnackbarController));
         // Mocking out all of the calls that touch on NetworkChangeNotifier, which we cannot
         // directly mock out.
         doNothing().when(observer).startObservingNetworkChanges();
@@ -78,6 +77,7 @@
         doReturn(false).when(mTab).isFrozen();
         doReturn(false).when(mTab).isHidden();
         doReturn(true).when(mTab).isOfflinePage();
+        doReturn(mActivity).when(mTab).getActivity();
 
         // Setting up mock snackbar manager.
         doNothing().when(mSnackbarManager).dismissSnackbars(eq(mSnackbarController));
@@ -446,7 +446,7 @@
     @Feature({"OfflinePages"})
     public void testAddObserverForTab() {
         OfflinePageTabObserver observer = createObserver();
-        OfflinePageTabObserver.setInstanceForTesting(observer);
+        OfflinePageTabObserver.setObserverForTesting(mActivity, observer);
 
         disconnect(observer, false);
         showTab(null);
@@ -464,7 +464,7 @@
     @Feature({"OfflinePages"})
     public void testAddObserverForTab_whenConnected() {
         OfflinePageTabObserver observer = createObserver();
-        OfflinePageTabObserver.setInstanceForTesting(observer);
+        OfflinePageTabObserver.setObserverForTesting(mActivity, observer);
 
         connect(observer, false);
         showTab(null);
diff --git a/chrome/browser/chromeos/arc/arc_util.cc b/chrome/browser/chromeos/arc/arc_util.cc
index fc6ce1c..0153369 100644
--- a/chrome/browser/chromeos/arc/arc_util.cc
+++ b/chrome/browser/chromeos/arc/arc_util.cc
@@ -205,9 +205,13 @@
   return profile->GetPrefs()->IsManagedPreference(prefs::kArcEnabled);
 }
 
-void SetArcPlayStoreEnabledForProfile(Profile* profile, bool enabled) {
+bool SetArcPlayStoreEnabledForProfile(Profile* profile, bool enabled) {
   DCHECK(IsArcAllowedForProfile(profile));
   if (IsArcPlayStoreEnabledPreferenceManagedForProfile(profile)) {
+    if (enabled && !IsArcPlayStoreEnabledForProfile(profile)) {
+      LOG(WARNING) << "Attempt to enable disabled by policy ARC.";
+      return false;
+    }
     VLOG(1) << "Google-Play-Store-enabled pref is managed. Request to "
             << (enabled ? "enable" : "disable") << " Play Store is not stored";
     // Need update ARC session manager manually for managed case in order to
@@ -217,14 +221,15 @@
     ArcSessionManager* arc_session_manager = ArcSessionManager::Get();
     // |arc_session_manager| can be nullptr in unit_tests.
     if (!arc_session_manager)
-      return;
+      return false;
     if (enabled)
       arc_session_manager->RequestEnable();
     else
       arc_session_manager->RequestDisable();
-    return;
+    return true;
   }
   profile->GetPrefs()->SetBoolean(prefs::kArcEnabled, enabled);
+  return true;
 }
 
 bool AreArcAllOptInPreferencesManagedForProfile(const Profile* profile) {
diff --git a/chrome/browser/chromeos/arc/arc_util.h b/chrome/browser/chromeos/arc/arc_util.h
index 80b8a9f..d0da128 100644
--- a/chrome/browser/chromeos/arc/arc_util.h
+++ b/chrome/browser/chromeos/arc/arc_util.h
@@ -92,8 +92,9 @@
 // the given |profile|.
 // TODO(hidehiko): De-couple the concept to enable ARC system and opt-in
 // to use Google Play Store. Note that there is a plan to use ARC without
-// Google Play Store, then ARC can run without opt-in.
-void SetArcPlayStoreEnabledForProfile(Profile* profile, bool enabled);
+// Google Play Store, then ARC can run without opt-in. Returns false in case
+// enabled state of the Play Store cannot be changed.
+bool SetArcPlayStoreEnabledForProfile(Profile* profile, bool enabled);
 
 // Returns whether all ARC related OptIn preferences (i.e.
 // ArcBackupRestoreEnabled and ArcLocationServiceEnabled) are managed.
diff --git a/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc b/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
index e50590e4..bea0a0e8 100644
--- a/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
@@ -28,8 +28,10 @@
 #include "extensions/common/permissions/permissions_data.h"
 
 #if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/arc/arc_util.h"
 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
 #include "chrome/browser/chromeos/system/input_device_settings.h"
+#include "chrome/browser/profiles/profile_manager.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager_client.h"
 #include "components/user_manager/user.h"
@@ -380,6 +382,45 @@
   return RespondNow(OneArgument(std::move(values)));
 }
 
+ExtensionFunction::ResponseAction
+AutotestPrivateGetPlayStoreStateFunction::Run() {
+  DVLOG(1) << "AutotestPrivateGetPlayStoreStateFunction";
+  api::autotest_private::PlayStoreState play_store_state;
+  play_store_state.allowed = false;
+#if defined(OS_CHROMEOS)
+  Profile* profile = ProfileManager::GetActiveUserProfile();
+  if (arc::IsArcAllowedForProfile(profile)) {
+    play_store_state.allowed = true;
+    play_store_state.enabled =
+        base::MakeUnique<bool>(arc::IsArcPlayStoreEnabledForProfile(profile));
+    play_store_state.managed = base::MakeUnique<bool>(
+        arc::IsArcPlayStoreEnabledPreferenceManagedForProfile(profile));
+  }
+#endif
+  return RespondNow(OneArgument(play_store_state.ToValue()));
+}
+
+ExtensionFunction::ResponseAction
+AutotestPrivateSetPlayStoreEnabledFunction::Run() {
+  DVLOG(1) << "AutotestPrivateSetPlayStoreEnabledFunction";
+  std::unique_ptr<api::autotest_private::SetPlayStoreEnabled::Params> params(
+      api::autotest_private::SetPlayStoreEnabled::Params::Create(*args_));
+  EXTENSION_FUNCTION_VALIDATE(params);
+#if defined(OS_CHROMEOS)
+  Profile* profile = ProfileManager::GetActiveUserProfile();
+  if (arc::IsArcAllowedForProfile(profile)) {
+    if (!arc::SetArcPlayStoreEnabledForProfile(profile, params->enabled)) {
+      return RespondNow(
+          Error("ARC enabled state cannot be changed for the current user"));
+    }
+    return RespondNow(NoArguments());
+  } else {
+    return RespondNow(Error("ARC is not available for the current user"));
+  }
+#endif
+  return RespondNow(Error("ARC is not available for the current platform"));
+}
+
 static base::LazyInstance<BrowserContextKeyedAPIFactory<AutotestPrivateAPI>>::
     DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
 
diff --git a/chrome/browser/extensions/api/autotest_private/autotest_private_api.h b/chrome/browser/extensions/api/autotest_private/autotest_private_api.h
index a84c368..a70c709 100644
--- a/chrome/browser/extensions/api/autotest_private/autotest_private_api.h
+++ b/chrome/browser/extensions/api/autotest_private/autotest_private_api.h
@@ -172,6 +172,28 @@
   ResponseAction Run() override;
 };
 
+class AutotestPrivateGetPlayStoreStateFunction
+    : public UIThreadExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("autotestPrivate.getPlayStoreState",
+                             AUTOTESTPRIVATE_GETPLAYSTORESTATE)
+
+ private:
+  ~AutotestPrivateGetPlayStoreStateFunction() override {}
+  ResponseAction Run() override;
+};
+
+class AutotestPrivateSetPlayStoreEnabledFunction
+    : public UIThreadExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("autotestPrivate.setPlayStoreEnabled",
+                             AUTOTESTPRIVATE_SETPLAYSTOREENABLED)
+
+ private:
+  ~AutotestPrivateSetPlayStoreEnabledFunction() override {}
+  ResponseAction Run() override;
+};
+
 // Don't kill the browser when we're in a browser test.
 void SetAutotestPrivateTest();
 
diff --git a/chrome/browser/resources/plugin_metadata/plugins_linux.json b/chrome/browser/resources/plugin_metadata/plugins_linux.json
index 37a64d5..2931047 100644
--- a/chrome/browser/resources/plugin_metadata/plugins_linux.json
+++ b/chrome/browser/resources/plugin_metadata/plugins_linux.json
@@ -1,5 +1,5 @@
 {
-  "x-version": 20,
+  "x-version": 21,
   "google-talk": {
     "mime_types": [
     ],
@@ -80,9 +80,9 @@
     ],
     "versions": [
       {
-        "version": "24.0.0.221",
+        "version": "25.0.0.148",
         "status": "up_to_date",
-        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-04.html"
+        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-10.html"
       }
     ],
     "lang": "en-US",
diff --git a/chrome/browser/resources/plugin_metadata/plugins_mac.json b/chrome/browser/resources/plugin_metadata/plugins_mac.json
index 2543b4e..a07eb278 100644
--- a/chrome/browser/resources/plugin_metadata/plugins_mac.json
+++ b/chrome/browser/resources/plugin_metadata/plugins_mac.json
@@ -1,5 +1,5 @@
 {
-  "x-version": 26,
+  "x-version": 27,
   "google-talk": {
     "mime_types": [
     ],
@@ -115,9 +115,9 @@
     ],
     "versions": [
       {
-        "version": "24.0.0.221",
+        "version": "25.0.0.148",
         "status": "requires_authorization",
-        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-04.html"
+        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-10.html"
       }
     ],
     "lang": "en-US",
diff --git a/chrome/browser/resources/plugin_metadata/plugins_win.json b/chrome/browser/resources/plugin_metadata/plugins_win.json
index c005be2..0f4a928 100644
--- a/chrome/browser/resources/plugin_metadata/plugins_win.json
+++ b/chrome/browser/resources/plugin_metadata/plugins_win.json
@@ -1,5 +1,5 @@
 {
-  "x-version": 35,
+  "x-version": 36,
   "google-talk": {
     "mime_types": [
     ],
@@ -137,9 +137,9 @@
     ],
     "versions": [
       {
-        "version": "24.0.0.221",
+        "version": "25.0.0.148",
         "status": "requires_authorization",
-        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-04.html"
+        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-10.html"
       }
     ],
     "lang": "en-US",
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl
index be6901c..9f2191b 100644
--- a/chrome/common/extensions/api/autotest_private.idl
+++ b/chrome/common/extensions/api/autotest_private.idl
@@ -63,6 +63,18 @@
   };
   callback NotificationArrayCallback = void (Notification[] notifications);
 
+  dictionary PlayStoreState {
+    // Whether the Play Store allowed for the current user.
+    boolean allowed;
+    // Whether the Play Store currently enabled.
+    boolean? enabled;
+    // Whether the Play Store managed by policy.
+    boolean? managed;
+  };
+  callback PlayStoreStateCallback = void (PlayStoreState result);
+
+  callback VoidCallback = void ();
+
   interface Functions {
     // Logout of a user session.
     static void logout();
@@ -116,5 +128,13 @@
 
     // Get visible notifications on the system.
     static void getVisibleNotifications(NotificationArrayCallback callback);
+
+    // Get state of the Play Store.
+    static void getPlayStoreState(PlayStoreStateCallback callback);
+
+    // Enable/disable the Play Store.
+    // |enabled|: if set, enable the Play Store.
+    // |callback|: Called when the operation has completed.
+    static void setPlayStoreEnabled(boolean enabled, VoidCallback callback);
   };
 };
diff --git a/chrome/test/data/extensions/api_test/autotest_private/test.js b/chrome/test/data/extensions/api_test/autotest_private/test.js
index 30e470f..04998278 100644
--- a/chrome/test/data/extensions/api_test/autotest_private/test.js
+++ b/chrome/test/data/extensions/api_test/autotest_private/test.js
@@ -108,5 +108,22 @@
   function getVisibleNotifications() {
     chrome.autotestPrivate.getVisibleNotifications(function(){});
     chrome.test.succeed();
+  },
+  function getPlayStoreState() {
+    chrome.autotestPrivate.getPlayStoreState(function(state) {
+      // By default ARC is not available. Field allowed must be set to false;
+      // managed and enabled should be underfined.
+      chrome.test.assertFalse(state.allowed);
+      chrome.test.assertEq(undefined, state.enabled);
+      chrome.test.assertEq(undefined, state.managed);
+      chrome.test.succeed();
+    });
+  },
+  function setPlayStoreEnabled() {
+    chrome.autotestPrivate.setPlayStoreEnabled(false, function() {
+      // By default ARC is not available.
+      chrome.test.assertTrue(chrome.runtime.lastError != undefined);
+      chrome.test.succeed();
+    });
   }
 ]);
diff --git a/components/network_session_configurator/network_session_configurator.cc b/components/network_session_configurator/network_session_configurator.cc
index 00ab3d3..4f20674 100644
--- a/components/network_session_configurator/network_session_configurator.cc
+++ b/components/network_session_configurator/network_session_configurator.cc
@@ -332,6 +332,13 @@
       GetVariationParam(quic_trial_params, "quic_version"));
 }
 
+bool ShouldEnableServerPushCancelation(
+    const VariationParameters& quic_trial_params) {
+  return base::LowerCaseEqualsASCII(
+      GetVariationParam(quic_trial_params, "enable_server_push_cancellation"),
+      "true");
+}
+
 void ConfigureQuicParams(base::StringPiece quic_trial_group,
                          const VariationParameters& quic_trial_params,
                          bool is_quic_force_disabled,
@@ -343,6 +350,10 @@
       is_quic_force_enabled);
   params->mark_quic_broken_when_network_blackholes =
       ShouldMarkQuicBrokenWhenNetworkBlackholes(quic_trial_params);
+
+  params->enable_server_push_cancellation =
+      ShouldEnableServerPushCancelation(quic_trial_params);
+
   params->retry_without_alt_svc_on_quic_errors =
       ShouldRetryWithoutAltSvcOnQuicErrors(quic_trial_params);
   params->enable_quic_alternative_service_with_different_host =
diff --git a/components/network_session_configurator/network_session_configurator_unittest.cc b/components/network_session_configurator/network_session_configurator_unittest.cc
index 799f9ca4..aa9e4c6 100644
--- a/components/network_session_configurator/network_session_configurator_unittest.cc
+++ b/components/network_session_configurator/network_session_configurator_unittest.cc
@@ -75,6 +75,7 @@
   EXPECT_FALSE(params_.quic_disable_connection_pooling);
   EXPECT_EQ(0.25f, params_.quic_load_server_info_timeout_srtt_multiplier);
   EXPECT_FALSE(params_.quic_enable_connection_racing);
+  EXPECT_FALSE(params_.enable_server_push_cancellation);
   EXPECT_FALSE(params_.quic_enable_non_blocking_io);
   EXPECT_FALSE(params_.quic_disable_disk_cache);
   EXPECT_FALSE(params_.quic_prefer_aes);
@@ -222,6 +223,17 @@
   EXPECT_TRUE(params_.quic_race_cert_verification);
 }
 
+TEST_F(NetworkSessionConfiguratorTest, EnableServerPushCancellation) {
+  std::map<std::string, std::string> field_trial_params;
+  field_trial_params["enable_server_push_cancellation"] = "true";
+  variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
+  base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled");
+
+  ParseFieldTrials();
+
+  EXPECT_TRUE(params_.enable_server_push_cancellation);
+}
+
 TEST_F(NetworkSessionConfiguratorTest, QuicDoNotFragment) {
   std::map<std::string, std::string> field_trial_params;
   field_trial_params["do_not_fragment"] = "true";
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc
index 0f2e8e4..b3ffa387 100644
--- a/components/translate/core/browser/translate_manager.cc
+++ b/components/translate/core/browser/translate_manager.cc
@@ -514,6 +514,8 @@
     // Get the browser's user interface language.
     language = TranslateDownloadManager::GetLanguageCode(
         TranslateDownloadManager::GetInstance()->application_locale());
+    // Map 'he', 'nb', 'fil' back to 'iw', 'no', 'tl'
+    translate::ToTranslateLanguageSynonym(&language);
   }
   if (TranslateDownloadManager::IsSupportedLanguage(language))
     return language;
diff --git a/components/translate/core/browser/translate_manager_unittest.cc b/components/translate/core/browser/translate_manager_unittest.cc
index cf28987..3efddaf 100644
--- a/components/translate/core/browser/translate_manager_unittest.cc
+++ b/components/translate/core/browser/translate_manager_unittest.cc
@@ -254,6 +254,23 @@
   ASSERT_TRUE(TranslateDownloadManager::IsSupportedLanguage("de"));
   manager_->set_application_locale("de");
   EXPECT_EQ("de", TranslateManager::GetTargetLanguage(&translate_prefs_));
+
+  // Try a those case of non standard code.
+  // 'he', 'fil', 'nb' => 'iw', 'tl', 'no'
+  ASSERT_TRUE(TranslateDownloadManager::IsSupportedLanguage("iw"));
+  ASSERT_FALSE(TranslateDownloadManager::IsSupportedLanguage("he"));
+  manager_->set_application_locale("he");
+  EXPECT_EQ("iw", TranslateManager::GetTargetLanguage(&translate_prefs_));
+
+  ASSERT_TRUE(TranslateDownloadManager::IsSupportedLanguage("tl"));
+  ASSERT_FALSE(TranslateDownloadManager::IsSupportedLanguage("fil"));
+  manager_->set_application_locale("fil");
+  EXPECT_EQ("tl", TranslateManager::GetTargetLanguage(&translate_prefs_));
+
+  ASSERT_TRUE(TranslateDownloadManager::IsSupportedLanguage("no"));
+  ASSERT_FALSE(TranslateDownloadManager::IsSupportedLanguage("nb"));
+  manager_->set_application_locale("nb");
+  EXPECT_EQ("no", TranslateManager::GetTargetLanguage(&translate_prefs_));
 }
 
 // If the application locale's language is not supported, the target language
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index ef4dfc9..004de515 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -330,6 +330,8 @@
     "audio_manager_thread.h",
     "background_fetch/background_fetch_context.cc",
     "background_fetch/background_fetch_context.h",
+    "background_fetch/background_fetch_cross_origin_filter.cc",
+    "background_fetch/background_fetch_cross_origin_filter.h",
     "background_fetch/background_fetch_data_manager.cc",
     "background_fetch/background_fetch_data_manager.h",
     "background_fetch/background_fetch_event_dispatcher.cc",
diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc
index 151aa68..ed2742c0 100644
--- a/content/browser/accessibility/browser_accessibility_win.cc
+++ b/content/browser/accessibility/browser_accessibility_win.cc
@@ -5467,9 +5467,12 @@
         ia_role = ROLE_SYSTEM_PANE;
       }
       break;
-    case ui::AX_ROLE_ROW:
-      ia_role = ROLE_SYSTEM_ROW;
+    case ui::AX_ROLE_ROW: {
+      // Role changes depending on whether row is inside a treegrid
+      // https://www.w3.org/TR/core-aam-1.1/#role-map-row
+      ia_role = IsInTreeGrid(this) ? ROLE_SYSTEM_OUTLINEITEM : ROLE_SYSTEM_ROW;
       break;
+    }
     case ui::AX_ROLE_ROW_HEADER:
       ia_role = ROLE_SYSTEM_ROWHEADER;
       break;
@@ -5645,6 +5648,23 @@
   win_attributes_->ia2_state = ia2_state;
 }
 
+bool BrowserAccessibilityWin::IsInTreeGrid(const BrowserAccessibility* item) {
+  BrowserAccessibility* container = item->PlatformGetParent();
+  if (container && container->GetRole() == ui::AX_ROLE_GROUP) {
+    // If parent was a rowgroup, we need to look at the grandparent
+    container = container->PlatformGetParent();
+  }
+
+  if (!container) {
+    return false;
+  }
+
+  const ui::AXRole role = container->GetRole();
+  return role == ui::AX_ROLE_TREE_GRID ||
+         (role == ui::AX_ROLE_TABLE &&
+          container->GetString16Attribute(ui::AX_ATTR_ROLE) == L"treegrid");
+}
+
 BrowserAccessibilityWin* ToBrowserAccessibilityWin(BrowserAccessibility* obj) {
   DCHECK(!obj || obj->IsNative());
   return static_cast<BrowserAccessibilityWin*>(obj);
diff --git a/content/browser/accessibility/browser_accessibility_win.h b/content/browser/accessibility/browser_accessibility_win.h
index a9f1f9cf..ccc8567 100644
--- a/content/browser/accessibility/browser_accessibility_win.h
+++ b/content/browser/accessibility/browser_accessibility_win.h
@@ -920,6 +920,8 @@
 
   ui::AXPlatformNodeWin* GetPlatformNodeWin() const;
 
+  static bool IsInTreeGrid(const BrowserAccessibility* item);
+
   struct WinAttributes {
     WinAttributes();
     ~WinAttributes();
diff --git a/content/browser/background_fetch/background_fetch_cross_origin_filter.cc b/content/browser/background_fetch/background_fetch_cross_origin_filter.cc
new file mode 100644
index 0000000..125a4fa
--- /dev/null
+++ b/content/browser/background_fetch/background_fetch_cross_origin_filter.cc
@@ -0,0 +1,99 @@
+// Copyright 2017 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/background_fetch/background_fetch_cross_origin_filter.h"
+
+#include <set>
+
+#include "base/strings/string_split.h"
+#include "content/browser/background_fetch/background_fetch_request_info.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+const char kAccessControlAllowOriginHeader[] = "access-control-allow-origin";
+const char kAnyOriginValue[] = "*";
+
+// Parses the header list (including "any origin") value from a given response
+// header value, writing the results in |*any_origin| or |*origins|. Returns
+// whether all values included in the the |value| is valid.
+bool ParseOriginListHeader(const std::string& value,
+                           bool* any_origin,
+                           std::set<url::Origin>* origins) {
+  DCHECK(any_origin);
+  DCHECK(origins);
+
+  if (value == kAnyOriginValue) {
+    *any_origin = true;
+    return true;
+  }
+
+  std::set<url::Origin> candidate_origins;
+  std::vector<std::string> origin_vector = base::SplitString(
+      value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+
+  for (const std::string& origin_string : origin_vector) {
+    url::Origin origin = url::Origin(GURL(origin_string));
+    if (origin.unique())
+      return false;
+
+    candidate_origins.insert(origin);
+  }
+
+  origins->swap(candidate_origins);
+  return !origins->empty();
+}
+
+}  // namespace
+
+BackgroundFetchCrossOriginFilter::BackgroundFetchCrossOriginFilter(
+    const url::Origin& source_origin,
+    const BackgroundFetchRequestInfo& request) {
+  DCHECK(!request.GetURLChain().empty());
+
+  const GURL& final_url = request.GetURLChain().back();
+  const auto& response_header_map = request.GetResponseHeaders();
+
+  // True iff |source_origin| is the same origin as the original request URL.
+  is_same_origin_ = source_origin.IsSameOriginWith(url::Origin(final_url));
+
+  // Access-Control-Allow-Origin checks. The header's values must be valid for
+  // it to not be completely discarded.
+  auto access_control_allow_origin_iter =
+      response_header_map.find(kAccessControlAllowOriginHeader);
+
+  if (access_control_allow_origin_iter != response_header_map.end()) {
+    bool access_control_allow_any_origin = false;
+    std::set<url::Origin> access_control_allow_origins;
+
+    if (ParseOriginListHeader(access_control_allow_origin_iter->second,
+                              &access_control_allow_any_origin,
+                              &access_control_allow_origins)) {
+      access_control_allow_origin_ =
+          access_control_allow_any_origin ||
+          access_control_allow_origins.count(source_origin) == 1;
+    }
+  }
+
+  // TODO(crbug.com/711354): Consider the Access-Control-Allow-Credentials
+  //                         header.
+  // TODO(crbug.com/711354): Consider the Access-Control-Allow-Headers header.
+  // TODO(crbug.com/711354): Consider the Access-Control-Allow-Methods header.
+  // TODO(crbug.com/711354): Consider the Access-Control-Expose-Headers header.
+}
+
+BackgroundFetchCrossOriginFilter::~BackgroundFetchCrossOriginFilter() = default;
+
+bool BackgroundFetchCrossOriginFilter::CanPopulateBody() const {
+  // The body will be populated if:
+  //   (1) The source and the response share their origin.
+  //   (2) The Access-Control-Allow-Origin method allows any origin.
+  //   (3) The Access-Control-Allow-Origin method allows the source origin.
+
+  return is_same_origin_ || access_control_allow_origin_;
+}
+
+}  // namespace content
diff --git a/content/browser/background_fetch/background_fetch_cross_origin_filter.h b/content/browser/background_fetch/background_fetch_cross_origin_filter.h
new file mode 100644
index 0000000..6fb1c499
--- /dev/null
+++ b/content/browser/background_fetch/background_fetch_cross_origin_filter.h
@@ -0,0 +1,43 @@
+// Copyright 2017 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_BACKGROUND_FETCH_BACKGROUND_FETCH_CROSS_ORIGIN_FILTER_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_CROSS_ORIGIN_FILTER_H_
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+
+namespace url {
+class Origin;
+}
+
+namespace content {
+
+class BackgroundFetchRequestInfo;
+
+// A filter that decides the CORS rules based on the source of a request and the
+// response URL and headers included in the |request| info.
+class CONTENT_EXPORT BackgroundFetchCrossOriginFilter {
+ public:
+  BackgroundFetchCrossOriginFilter(const url::Origin& source_origin,
+                                   const BackgroundFetchRequestInfo& request);
+  ~BackgroundFetchCrossOriginFilter();
+
+  // Returns whether the Response object passed to the Service Worker event
+  // should include the body included in the response.
+  bool CanPopulateBody() const;
+
+ private:
+  // Whether the response comes from the same origin as the requester.
+  bool is_same_origin_ = false;
+
+  // Whether the Access-Control-Allow-Origin header includes the source origin.
+  bool access_control_allow_origin_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(BackgroundFetchCrossOriginFilter);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_CROSS_ORIGIN_FILTER_H_
diff --git a/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc b/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc
new file mode 100644
index 0000000..0d6eb0c
--- /dev/null
+++ b/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc
@@ -0,0 +1,111 @@
+// Copyright 2017 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/background_fetch/background_fetch_cross_origin_filter.h"
+
+#include "base/macros.h"
+#include "content/browser/background_fetch/background_fetch_request_info.h"
+#include "content/common/service_worker/service_worker_types.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+const char kFirstOrigin[] = "https://example.com";
+const char kFirstOriginFile[] = "https://example.com/cat.jpg";
+const char kSecondOriginFile[] = "https://chrome.com/cat.jpg";
+
+const char kAccessControlAllowOriginHeader[] = "access-control-allow-origin";
+
+class BackgroundFetchCrossOriginFilterTest : public ::testing::Test {
+ public:
+  BackgroundFetchCrossOriginFilterTest()
+      : source_(url::Origin(GURL(kFirstOrigin))) {}
+  ~BackgroundFetchCrossOriginFilterTest() override = default;
+
+  // Creates a BackgroundFetchRequestInfo instance filled with the information
+  // required for the cross-origin filter to work. This method takes a
+  // |response_url| and an initializer list for key => value header pairs.
+  scoped_refptr<BackgroundFetchRequestInfo> CreateRequestInfo(
+      const char* response_url,
+      std::initializer_list<
+          typename std::map<std::string, std::string>::value_type>
+          response_headers) {
+    scoped_refptr<BackgroundFetchRequestInfo> request_info =
+        make_scoped_refptr(new BackgroundFetchRequestInfo(
+            0 /* request_info */, ServiceWorkerFetchRequest()));
+
+    request_info->download_state_populated_ = true;
+    request_info->response_headers_ = response_headers;
+
+    request_info->response_data_populated_ = true;
+    request_info->url_chain_ = {GURL(response_url)};
+
+    return request_info;
+  }
+
+ protected:
+  url::Origin source_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BackgroundFetchCrossOriginFilterTest);
+};
+
+TEST_F(BackgroundFetchCrossOriginFilterTest, SameOrigin) {
+  auto same_origin_response = CreateRequestInfo(kFirstOriginFile, {});
+
+  BackgroundFetchCrossOriginFilter filter(source_, *same_origin_response);
+  EXPECT_TRUE(filter.CanPopulateBody());
+}
+
+TEST_F(BackgroundFetchCrossOriginFilterTest, CrossOrigin) {
+  auto cross_origin_response = CreateRequestInfo(kSecondOriginFile, {});
+
+  BackgroundFetchCrossOriginFilter filter(source_, *cross_origin_response);
+  EXPECT_FALSE(filter.CanPopulateBody());
+}
+
+TEST_F(BackgroundFetchCrossOriginFilterTest, CrossOriginAllowAllOrigins) {
+  auto cross_origin_response = CreateRequestInfo(
+      kSecondOriginFile, {{kAccessControlAllowOriginHeader, "*"}});
+
+  BackgroundFetchCrossOriginFilter filter(source_, *cross_origin_response);
+  EXPECT_TRUE(filter.CanPopulateBody());
+}
+
+TEST_F(BackgroundFetchCrossOriginFilterTest, CrossOriginAllowSpecificOrigin) {
+  // With a single origin in the Access-Control-Allow-Origin header.
+  {
+    auto cross_origin_response = CreateRequestInfo(
+        kSecondOriginFile, {{kAccessControlAllowOriginHeader, kFirstOrigin}});
+
+    BackgroundFetchCrossOriginFilter filter(source_, *cross_origin_response);
+    EXPECT_TRUE(filter.CanPopulateBody());
+  }
+
+  // With multiple origins in the Access-Control-Allow-Origin header.
+  {
+    const char kOriginList[] =
+        "https://foo.com, https://example.com, https://bar.com:1500";
+
+    auto cross_origin_response = CreateRequestInfo(
+        kSecondOriginFile, {{kAccessControlAllowOriginHeader, kOriginList}});
+
+    BackgroundFetchCrossOriginFilter filter(source_, *cross_origin_response);
+    EXPECT_TRUE(filter.CanPopulateBody());
+  }
+
+  // With an invalid value included in the Access-Control-Allow-Origin header.
+  {
+    const char kOriginList[] =
+        "https://foo.com, https://example.com, INVALID, https://bar.com:1500";
+
+    auto cross_origin_response = CreateRequestInfo(
+        kSecondOriginFile, {{kAccessControlAllowOriginHeader, kOriginList}});
+
+    BackgroundFetchCrossOriginFilter filter(source_, *cross_origin_response);
+    EXPECT_FALSE(filter.CanPopulateBody());
+  }
+}
+
+}  // namespace content
diff --git a/content/browser/background_fetch/background_fetch_data_manager.cc b/content/browser/background_fetch/background_fetch_data_manager.cc
index bc8210ed..83e7509 100644
--- a/content/browser/background_fetch/background_fetch_data_manager.cc
+++ b/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -10,6 +10,7 @@
 #include "base/memory/ptr_util.h"
 #include "content/browser/background_fetch/background_fetch_constants.h"
 #include "content/browser/background_fetch/background_fetch_context.h"
+#include "content/browser/background_fetch/background_fetch_cross_origin_filter.h"
 #include "content/browser/background_fetch/background_fetch_request_info.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
 #include "content/public/browser/blob_handle.h"
@@ -206,22 +207,22 @@
     BackgroundFetchSettledFetch settled_fetch;
     settled_fetch.request = request->fetch_request();
 
-    // TODO(peter): Find the appropriate way to generalize CORS security checks.
-    const bool opaque = !registration_id.origin().IsSameOriginWith(
-        url::Origin(request->GetURLChain().back().GetOrigin()));
+    // The |filter| decides which values can be passed on to the Service Worker.
+    BackgroundFetchCrossOriginFilter filter(registration_id.origin(), *request);
 
     settled_fetch.response.url_list = request->GetURLChain();
     settled_fetch.response.response_type =
         blink::kWebServiceWorkerResponseTypeDefault;
 
-    if (!opaque) {
+    // Include the status code, status text and the response's body as a blob
+    // when this is allowed by the CORS protocol.
+    if (filter.CanPopulateBody()) {
       settled_fetch.response.status_code = request->GetResponseCode();
       settled_fetch.response.status_text = request->GetResponseText();
       settled_fetch.response.headers.insert(
           request->GetResponseHeaders().begin(),
           request->GetResponseHeaders().end());
 
-      // Include the response data as a blob backed by the downloaded file.
       if (request->GetFileSize() > 0) {
         DCHECK(!request->GetFilePath().empty());
         std::unique_ptr<BlobHandle> blob_handle =
diff --git a/content/browser/background_fetch/background_fetch_request_info.cc b/content/browser/background_fetch/background_fetch_request_info.cc
index e3f9608..1973d35 100644
--- a/content/browser/background_fetch/background_fetch_request_info.cc
+++ b/content/browser/background_fetch/background_fetch_request_info.cc
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include "base/strings/string_util.h"
 #include "content/public/browser/download_item.h"
 #include "net/http/http_response_headers.h"
 
@@ -38,7 +39,7 @@
     std::string name, value;
 
     while (headers->EnumerateHeaderLines(&iter, &name, &value))
-      response_headers_[name] = value;
+      response_headers_[base::ToLowerASCII(name)] = value;
   }
 
   download_state_populated_ = true;
diff --git a/content/browser/background_fetch/background_fetch_request_info.h b/content/browser/background_fetch/background_fetch_request_info.h
index f01d321..e3c49f89 100644
--- a/content/browser/background_fetch/background_fetch_request_info.h
+++ b/content/browser/background_fetch/background_fetch_request_info.h
@@ -74,6 +74,7 @@
 
  private:
   friend class base::RefCountedThreadSafe<BackgroundFetchRequestInfo>;
+  friend class BackgroundFetchCrossOriginFilterTest;
 
   ~BackgroundFetchRequestInfo();
 
diff --git a/content/browser/bluetooth/tools/BUILD.gn b/content/browser/bluetooth/tools/BUILD.gn
index 4971caa..4feb959 100644
--- a/content/browser/bluetooth/tools/BUILD.gn
+++ b/content/browser/bluetooth/tools/BUILD.gn
@@ -9,6 +9,7 @@
 
   deps = [
     "//base",
+    "//build/config/sanitizers:deps",
     "//build/win:default_exe_manifest",
     "//device/bluetooth",
   ]
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 5b0a162..58969065 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1026,6 +1026,7 @@
     "../browser/appcache/mock_appcache_storage.cc",
     "../browser/appcache/mock_appcache_storage.h",
     "../browser/appcache/mock_appcache_storage_unittest.cc",
+    "../browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc",
     "../browser/background_fetch/background_fetch_data_manager_unittest.cc",
     "../browser/background_fetch/background_fetch_event_dispatcher_unittest.cc",
     "../browser/background_fetch/background_fetch_job_controller_unittest.cc",
diff --git a/content/test/data/accessibility/aria/aria-level-expected-win.txt b/content/test/data/accessibility/aria/aria-level-expected-win.txt
index b10d0bb..97f6f26 100644
--- a/content/test/data/accessibility/aria/aria-level-expected-win.txt
+++ b/content/test/data/accessibility/aria/aria-level-expected-win.txt
@@ -21,10 +21,10 @@
 ++++ROLE_SYSTEM_OUTLINEITEM name='Tree item at level 3' level:3
 ++++++ROLE_SYSTEM_STATICTEXT name='Tree item at level 3'
 ++ROLE_SYSTEM_OUTLINE
-++++ROLE_SYSTEM_ROW level:1
+++++ROLE_SYSTEM_OUTLINEITEM level:1
 ++++++ROLE_SYSTEM_CELL name='Cell at level 1'
 ++++++++ROLE_SYSTEM_STATICTEXT name='Cell at level 1'
-++++ROLE_SYSTEM_ROW level:2
+++++ROLE_SYSTEM_OUTLINEITEM level:2
 ++++++ROLE_SYSTEM_CELL name='Cell at level 2'
 ++++++++ROLE_SYSTEM_STATICTEXT name='Cell at level 2'
 ++++ROLE_SYSTEM_COLUMN
diff --git a/content/test/data/accessibility/aria/aria-treegrid-expected-android.txt b/content/test/data/accessibility/aria/aria-treegrid-expected-android.txt
index fa02c5ff..c703016 100644
--- a/content/test/data/accessibility/aria/aria-treegrid-expected-android.txt
+++ b/content/test/data/accessibility/aria/aria-treegrid-expected-android.txt
@@ -5,4 +5,9 @@
 ++++android.view.View
 ++++++android.view.View role_description='cell' collection_item name='Cell at level 2' row_index=1 row_span=1 column_span=1
 ++++android.view.View
-++++android.view.View
\ No newline at end of file
+++++android.view.View
+++android.widget.GridView role_description='table' collection row_count=1 column_count=1
+++++android.view.View
+++++++android.view.View role_description='cell' collection_item name='Cell at level 1' row_span=1 column_span=1
+++++android.view.View
+++++android.view.View
diff --git a/content/test/data/accessibility/aria/aria-treegrid-expected-mac.txt b/content/test/data/accessibility/aria/aria-treegrid-expected-mac.txt
index feee33b..1dabc16 100644
--- a/content/test/data/accessibility/aria/aria-treegrid-expected-mac.txt
+++ b/content/test/data/accessibility/aria/aria-treegrid-expected-mac.txt
@@ -8,3 +8,9 @@
 ++++++++AXStaticText AXValue='Cell at level 2'
 ++++AXColumn
 ++++AXGroup
+++AXTable
+++++AXRow AXDisclosureLevel='0'
+++++++AXCell AXTitle='Cell at level 1'
+++++++++AXStaticText AXValue='Cell at level 1'
+++++AXColumn
+++++AXGroup
diff --git a/content/test/data/accessibility/aria/aria-treegrid-expected-win.txt b/content/test/data/accessibility/aria/aria-treegrid-expected-win.txt
index d9d10f540..1edaf72d 100644
--- a/content/test/data/accessibility/aria/aria-treegrid-expected-win.txt
+++ b/content/test/data/accessibility/aria/aria-treegrid-expected-win.txt
@@ -1,10 +1,16 @@
 ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
 ++ROLE_SYSTEM_OUTLINE xml-roles:treegrid
-++++ROLE_SYSTEM_ROW xml-roles:row level:1
+++++ROLE_SYSTEM_OUTLINEITEM xml-roles:row level:1
 ++++++ROLE_SYSTEM_CELL name='Cell at level 1' xml-roles:gridcell
 ++++++++ROLE_SYSTEM_STATICTEXT name='Cell at level 1'
-++++ROLE_SYSTEM_ROW xml-roles:row level:2
+++++ROLE_SYSTEM_OUTLINEITEM xml-roles:row level:2
 ++++++ROLE_SYSTEM_CELL name='Cell at level 2' xml-roles:gridcell
 ++++++++ROLE_SYSTEM_STATICTEXT name='Cell at level 2'
 ++++ROLE_SYSTEM_COLUMN
 ++++IA2_ROLE_SECTION
+++ROLE_SYSTEM_OUTLINE xml-roles:treegrid
+++++ROLE_SYSTEM_OUTLINEITEM xml-roles:row level:1
+++++++ROLE_SYSTEM_CELL name='Cell at level 1' xml-roles:gridcell
+++++++++ROLE_SYSTEM_STATICTEXT name='Cell at level 1'
+++++ROLE_SYSTEM_COLUMN
+++++IA2_ROLE_SECTION
diff --git a/content/test/data/accessibility/aria/aria-treegrid.html b/content/test/data/accessibility/aria/aria-treegrid.html
index b5923c5f..18136c3 100644
--- a/content/test/data/accessibility/aria/aria-treegrid.html
+++ b/content/test/data/accessibility/aria/aria-treegrid.html
@@ -14,6 +14,13 @@
   <tr role="row" aria-level="2">
     <td role="gridcell">Cell at level 2</td>
   </tr>
-</table>
+  </table>
+  <table role="treegrid">
+    <tbody role="rowgroup">
+      <tr role="row" aria-level="1">
+        <td role="gridcell">Cell at level 1</td>
+      </tr>
+    </tbody>
+  </table>
 </body>
 </html>
diff --git a/device/gamepad/gamepad_provider_unittest.cc b/device/gamepad/gamepad_provider_unittest.cc
index 2f1633e..cef3355 100644
--- a/device/gamepad/gamepad_provider_unittest.cc
+++ b/device/gamepad/gamepad_provider_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
+#include "base/threading/platform_thread.h"
 #include "build/build_config.h"
 #include "device/gamepad/gamepad_data_fetcher.h"
 #include "device/gamepad/gamepad_test_helpers.h"
@@ -49,6 +50,28 @@
     return provider_.get();
   }
 
+  // Sleep until the shared memory buffer's seqlock advances the buffer version,
+  // indicating that the gamepad provider has written to it after polling the
+  // gamepad fetchers. The buffer will report an odd value for the version if
+  // the buffer is not in a consistent state, so we also require that the value
+  // is even before continuing.
+  void WaitForData(GamepadHardwareBuffer* buffer) {
+    const base::subtle::Atomic32 initial_version = buffer->seqlock.ReadBegin();
+    base::subtle::Atomic32 current_version;
+    do {
+      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
+      current_version = buffer->seqlock.ReadBegin();
+    } while (current_version % 2 || current_version == initial_version);
+  }
+
+  // The provider polls the data on the background thread and then issues
+  // the callback on the client thread. Waiting for it to poll twice ensures
+  // that it was able to issue callbacks for the first poll.
+  void WaitForDataAndCallbacksIssued(GamepadHardwareBuffer* buffer) {
+    WaitForData(buffer);
+    WaitForData(buffer);
+  }
+
   void ReadGamepadHardwareBuffer(GamepadHardwareBuffer* buffer,
                                  WebGamepads* output) {
     memset(output, 0, sizeof(WebGamepads));
@@ -70,8 +93,7 @@
   DISALLOW_COPY_AND_ASSIGN(GamepadProviderTest);
 };
 
-// Test is flaky. crbug.com/705367
-TEST_F(GamepadProviderTest, DISABLED_PollingAccess) {
+TEST_F(GamepadProviderTest, PollingAccess) {
   WebGamepads test_data;
   memset(&test_data, 0, sizeof(WebGamepads));
   test_data.items[0].connected = true;
@@ -89,8 +111,6 @@
 
   base::RunLoop().RunUntilIdle();
 
-  mock_data_fetcher_->WaitForDataRead();
-
   // Renderer-side, pull data out of poll buffer.
   base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess(
       base::GetCurrentProcessHandle());
@@ -100,6 +120,10 @@
 
   GamepadHardwareBuffer* buffer =
       static_cast<GamepadHardwareBuffer*>(shared_memory->memory());
+
+  // Wait until the shared memory buffer has been written at least once.
+  WaitForData(buffer);
+
   WebGamepads output;
   ReadGamepadHardwareBuffer(buffer, &output);
 
@@ -111,8 +135,7 @@
   EXPECT_EQ(0.5f, output.items[0].axes[1]);
 }
 
-// Flaky on all platforms: http://crbug.com/692219
-TEST_F(GamepadProviderTest, DISABLED_ConnectDisconnectMultiple) {
+TEST_F(GamepadProviderTest, ConnectDisconnectMultiple) {
   WebGamepads test_data;
   test_data.items[0].connected = true;
   test_data.items[0].timestamp = 0;
@@ -139,8 +162,6 @@
 
   base::RunLoop().RunUntilIdle();
 
-  mock_data_fetcher_->WaitForDataRead();
-
   // Renderer-side, pull data out of poll buffer.
   base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess(
       base::GetCurrentProcessHandle());
@@ -150,6 +171,10 @@
 
   GamepadHardwareBuffer* buffer =
       static_cast<GamepadHardwareBuffer*>(shared_memory->memory());
+
+  // Wait until the shared memory buffer has been written at least once.
+  WaitForData(buffer);
+
   WebGamepads output;
   ReadGamepadHardwareBuffer(buffer, &output);
 
@@ -161,7 +186,9 @@
   EXPECT_EQ(-0.5f, output.items[1].axes[1]);
 
   mock_data_fetcher_->SetTestData(test_data_onedisconnected);
-  mock_data_fetcher_->WaitForDataReadAndCallbacksIssued();
+
+  WaitForDataAndCallbacksIssued(buffer);
+
   ReadGamepadHardwareBuffer(buffer, &output);
 
   EXPECT_EQ(0u, output.items[0].axes_length);
@@ -192,29 +219,39 @@
   provider->Resume();
 
   provider->RegisterForUserGesture(listener.GetClosure());
-  mock_data_fetcher_->WaitForDataReadAndCallbacksIssued();
+
+  base::RunLoop().RunUntilIdle();
+
+  // Renderer-side, pull data out of poll buffer.
+  base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess(
+      base::GetCurrentProcessHandle());
+  std::unique_ptr<base::SharedMemory> shared_memory(
+      new base::SharedMemory(handle, true));
+  EXPECT_TRUE(shared_memory->Map(sizeof(GamepadHardwareBuffer)));
+
+  GamepadHardwareBuffer* buffer =
+      static_cast<GamepadHardwareBuffer*>(shared_memory->memory());
+
+  // Wait until the shared memory buffer has been written at least once.
+  WaitForData(buffer);
 
   // It should not have issued our callback.
-  base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(listener.has_user_gesture());
 
-  // Set a button down and wait for it to be read twice.
+  // Set a button down.
   mock_data_fetcher_->SetTestData(button_down_data);
-  mock_data_fetcher_->WaitForDataReadAndCallbacksIssued();
+
+  // The user gesture listener callback is not called until after the buffer has
+  // been updated. Wait for the second update to ensure callbacks have fired.
+  WaitForDataAndCallbacksIssued(buffer);
 
   // It should have issued our callback.
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(listener.has_user_gesture());
 }
 
-// Flaky on CrOS and Linux: http://crbug.com/640086, https://crbug.com/702712
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
-#define MAYBE_Sanitization DISABLED_Sanitization
-#else
-#define MAYBE_Sanitization Sanitization
-#endif
 // Tests that waiting for a user gesture works properly.
-TEST_F(GamepadProviderTest, MAYBE_Sanitization) {
+TEST_F(GamepadProviderTest, Sanitization) {
   WebGamepads active_data;
   active_data.items[0].connected = true;
   active_data.items[0].timestamp = 0;
@@ -240,8 +277,6 @@
 
   base::RunLoop().RunUntilIdle();
 
-  mock_data_fetcher_->WaitForDataRead();
-
   // Renderer-side, pull data out of poll buffer.
   base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess(
       base::GetCurrentProcessHandle());
@@ -251,6 +286,10 @@
 
   GamepadHardwareBuffer* buffer =
       static_cast<GamepadHardwareBuffer*>(shared_memory->memory());
+
+  // Wait until the shared memory buffer has been written at least once.
+  WaitForData(buffer);
+
   WebGamepads output;
   ReadGamepadHardwareBuffer(buffer, &output);
 
@@ -264,7 +303,8 @@
 
   // Zero out the inputs
   mock_data_fetcher_->SetTestData(zero_data);
-  mock_data_fetcher_->WaitForDataReadAndCallbacksIssued();
+
+  WaitForDataAndCallbacksIssued(buffer);
 
   // Read updated data from shared memory
   ReadGamepadHardwareBuffer(buffer, &output);
@@ -278,7 +318,8 @@
 
   // Re-set the active inputs
   mock_data_fetcher_->SetTestData(active_data);
-  mock_data_fetcher_->WaitForDataReadAndCallbacksIssued();
+
+  WaitForDataAndCallbacksIssued(buffer);
 
   // Read updated data from shared memory
   ReadGamepadHardwareBuffer(buffer, &output);
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index 531937e..d8a35fad 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1231,6 +1231,8 @@
   // This does not follow the naming convesion, but follows the other APIs in
   // webrtcAudioPrivate.
   WEBRTC_AUDIO_PRIVATE_SET_AUDIO_EXPERIMENTS,
+  AUTOTESTPRIVATE_GETPLAYSTORESTATE,
+  AUTOTESTPRIVATE_SETPLAYSTOREENABLED,
   // Last entry: Add new entries above, then run:
   // python tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/ios/clean/chrome/browser/ui/root/BUILD.gn b/ios/clean/chrome/browser/ui/root/BUILD.gn
index 1eaadd7d..19133fb1 100644
--- a/ios/clean/chrome/browser/ui/root/BUILD.gn
+++ b/ios/clean/chrome/browser/ui/root/BUILD.gn
@@ -27,6 +27,7 @@
   deps = [
     "//base",
     "//ios/clean/chrome/browser/ui/animators",
+    "//ios/clean/chrome/browser/ui/presenters",
   ]
   configs += [ "//build/config/compiler:enable_arc" ]
 }
diff --git a/ios/clean/chrome/browser/ui/root/root_container_view_controller.h b/ios/clean/chrome/browser/ui/root/root_container_view_controller.h
index f0693941..0f3ffe0 100644
--- a/ios/clean/chrome/browser/ui/root/root_container_view_controller.h
+++ b/ios/clean/chrome/browser/ui/root/root_container_view_controller.h
@@ -8,10 +8,11 @@
 #import <UIKit/UIKit.h>
 
 #import "ios/clean/chrome/browser/ui/animators/zoom_transition_delegate.h"
+#import "ios/clean/chrome/browser/ui/presenters/menu_presentation_delegate.h"
 
 // View controller that wholly contains a content view controller.
 @interface RootContainerViewController
-    : UIViewController<ZoomTransitionDelegate>
+    : UIViewController<MenuPresentationDelegate, ZoomTransitionDelegate>
 
 // View controller showing the main content.
 @property(nonatomic, strong) UIViewController* contentViewController;
diff --git a/ios/clean/chrome/browser/ui/root/root_container_view_controller.mm b/ios/clean/chrome/browser/ui/root/root_container_view_controller.mm
index 8a7467b..9c44ebb 100644
--- a/ios/clean/chrome/browser/ui/root/root_container_view_controller.mm
+++ b/ios/clean/chrome/browser/ui/root/root_container_view_controller.mm
@@ -69,4 +69,39 @@
   return CGRectNull;
 }
 
+#pragma mark - MenuPresentationDelegate
+
+- (CGRect)frameForMenuPresentation:(UIPresentationController*)presentation {
+  CGSize menuSize = presentation.presentedView.frame.size;
+  CGRect menuRect;
+  menuRect.size = menuSize;
+
+  CGRect menuOriginRect = [self rectForZoomWithKey:nil inView:self.view];
+  if (CGRectIsNull(menuOriginRect)) {
+    menuRect.origin = CGPointMake(50, 50);
+    return menuRect;
+  }
+  // Calculate which corner of the menu the origin rect is in. This is
+  // determined by comparing frames, and thus is RTL-independent.
+  if (CGRectGetMinX(menuOriginRect) - CGRectGetMinX(self.view.bounds) <
+      CGRectGetMaxX(self.view.bounds) - CGRectGetMaxX(menuOriginRect)) {
+    // Origin rect is closer to the left edge of |self.view| than to the right.
+    menuRect.origin.x = CGRectGetMinX(menuOriginRect);
+  } else {
+    // Origin rect is closer to the right edge of |self.view| than to the left.
+    menuRect.origin.x = CGRectGetMaxX(menuOriginRect) - menuSize.width;
+  }
+
+  if (CGRectGetMinY(menuOriginRect) - CGRectGetMinY(self.view.bounds) <
+      CGRectGetMaxY(self.view.bounds) - CGRectGetMaxY(menuOriginRect)) {
+    // Origin rect is closer to the top edge of |self.view| than to the bottom.
+    menuRect.origin.y = CGRectGetMinY(menuOriginRect);
+  } else {
+    // Origin rect is closer to the bottom edge of |self.view| than to the top.
+    menuRect.origin.y = CGRectGetMaxY(menuOriginRect) - menuSize.height;
+  }
+
+  return menuRect;
+}
+
 @end
diff --git a/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn b/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn
index 7c35b5f..6f271877 100644
--- a/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn
+++ b/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn
@@ -61,7 +61,6 @@
     "//ios/clean/chrome/browser/ui/actions",
     "//ios/clean/chrome/browser/ui/animators",
     "//ios/clean/chrome/browser/ui/commands",
-    "//ios/clean/chrome/browser/ui/presenters",
     "//ios/clean/chrome/browser/ui/tab_collection:tab_collection_ui",
     "//ios/third_party/material_components_ios:material_components_ios",
     "//ui/base",
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
index bfdc1c50..be61ce7 100644
--- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
+++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -196,6 +196,8 @@
 }
 
 - (void)registerForTabGridCommands {
+  [self.browser->dispatcher() startDispatchingToTarget:self
+                                           forSelector:@selector(showTabGrid)];
   [self.browser->dispatcher()
       startDispatchingToTarget:self
                    forSelector:@selector(showTabGridTabAtIndex:)];
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.h b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.h
index 49fd2d1..b9a104e 100644
--- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.h
+++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.h
@@ -8,7 +8,6 @@
 #import "ios/clean/chrome/browser/ui/tab_collection/tab_collection_view_controller.h"
 
 #import "ios/clean/chrome/browser/ui/animators/zoom_transition_delegate.h"
-#import "ios/clean/chrome/browser/ui/presenters/menu_presentation_delegate.h"
 #import "ios/clean/chrome/browser/ui/tab_grid/tab_grid_consumer.h"
 
 @protocol SettingsCommands;
@@ -17,9 +16,7 @@
 
 // View controller with a grid of tabs.
 @interface TabGridViewController
-    : TabCollectionViewController<MenuPresentationDelegate,
-                                  TabGridConsumer,
-                                  ZoomTransitionDelegate>
+    : TabCollectionViewController<TabGridConsumer, ZoomTransitionDelegate>
 // Dispatcher to handle commands.
 @property(nonatomic, weak)
     id<SettingsCommands, TabGridCommands, ToolsMenuCommands>
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index dc0f9be..bdfcad6 100644
--- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -122,41 +122,6 @@
   return [view convertRect:cell.bounds fromView:cell];
 }
 
-#pragma mark - MenuPresentationDelegate
-
-- (CGRect)frameForMenuPresentation:(UIPresentationController*)presentation {
-  CGSize menuSize = presentation.presentedView.frame.size;
-  CGRect menuRect;
-  menuRect.size = menuSize;
-
-  CGRect menuOriginRect = [self rectForZoomWithKey:nil inView:self.view];
-  if (CGRectIsNull(menuOriginRect)) {
-    menuRect.origin = CGPointMake(50, 50);
-    return menuRect;
-  }
-  // Calculate which corner of the menu the origin rect is in. This is
-  // determined by comparing frames, and thus is RTL-independent.
-  if (CGRectGetMinX(menuOriginRect) - CGRectGetMinX(self.view.bounds) <
-      CGRectGetMaxX(self.view.bounds) - CGRectGetMaxX(menuOriginRect)) {
-    // Origin rect is closer to the left edge of |self.view| than to the right.
-    menuRect.origin.x = CGRectGetMinX(menuOriginRect);
-  } else {
-    // Origin rect is closer to the right edge of |self.view| than to the left.
-    menuRect.origin.x = CGRectGetMaxX(menuOriginRect) - menuSize.width;
-  }
-
-  if (CGRectGetMinY(menuOriginRect) - CGRectGetMinY(self.view.bounds) <
-      CGRectGetMaxY(self.view.bounds) - CGRectGetMaxY(menuOriginRect)) {
-    // Origin rect is closer to the top edge of |self.view| than to the bottom.
-    menuRect.origin.y = CGRectGetMinY(menuOriginRect);
-  } else {
-    // Origin rect is closer to the bottom edge of |self.view| than to the top.
-    menuRect.origin.y = CGRectGetMaxY(menuOriginRect) - menuSize.height;
-  }
-
-  return menuRect;
-}
-
 #pragma mark - TabGridConsumer methods
 
 - (void)addNoTabsOverlay {
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h
index dc1a791..7ddcd6e9 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h
@@ -10,8 +10,9 @@
 #import "ios/clean/chrome/browser/ui/animators/zoom_transition_delegate.h"
 #import "ios/clean/chrome/browser/ui/toolbar/toolbar_consumer.h"
 
-@protocol ToolsMenuCommands;
 @protocol NavigationCommands;
+@protocol TabGridCommands;
+@protocol ToolsMenuCommands;
 
 // View controller for a toolbar, which will show a horizontal row of
 // controls and/or labels.
@@ -22,7 +23,9 @@
     : UIViewController<ZoomTransitionDelegate, ToolbarConsumer>
 
 // The dispatcher for this view controller
-@property(nonatomic, weak) id<ToolsMenuCommands, NavigationCommands> dispatcher;
+@property(nonatomic, weak)
+    id<NavigationCommands, TabGridCommands, ToolsMenuCommands>
+        dispatcher;
 
 @property(nonatomic, strong) UIViewController* locationBarViewController;
 
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
index 3fed575a..4800384 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
@@ -5,9 +5,9 @@
 #import "ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h"
 
 #import "base/mac/foundation_util.h"
-#import "ios/clean/chrome/browser/ui/actions/tab_grid_actions.h"
 #import "ios/clean/chrome/browser/ui/actions/tab_strip_actions.h"
 #import "ios/clean/chrome/browser/ui/commands/navigation_commands.h"
+#import "ios/clean/chrome/browser/ui/commands/tab_grid_commands.h"
 #import "ios/clean/chrome/browser/ui/commands/tools_menu_commands.h"
 #import "ios/clean/chrome/browser/ui/toolbar/toolbar_button+factory.h"
 #import "ios/clean/chrome/browser/ui/toolbar/toolbar_component_options.h"
@@ -128,7 +128,7 @@
   self.tabSwitchGridButton.visibilityMask =
       ToolbarComponentVisibilityCompactWidth |
       ToolbarComponentVisibilityRegularWidth;
-  [self.tabSwitchGridButton addTarget:nil
+  [self.tabSwitchGridButton addTarget:self
                                action:@selector(showTabGrid:)
                      forControlEvents:UIControlEventTouchUpInside];
   self.tabSwitchGridButton.hiddenInCurrentState = YES;
@@ -283,6 +283,10 @@
   [self.dispatcher reloadPage];
 }
 
+- (void)showTabGrid:(id)sender {
+  [self.dispatcher showTabGrid];
+}
+
 #pragma mark - TabStripEvents
 
 - (void)tabStripDidShow:(id)sender {
diff --git a/ios/showcase/toolbar/sc_toolbar_coordinator.mm b/ios/showcase/toolbar/sc_toolbar_coordinator.mm
index 312aeab..21972f9 100644
--- a/ios/showcase/toolbar/sc_toolbar_coordinator.mm
+++ b/ios/showcase/toolbar/sc_toolbar_coordinator.mm
@@ -5,6 +5,7 @@
 #import "ios/showcase/toolbar/sc_toolbar_coordinator.h"
 
 #import "ios/clean/chrome/browser/ui/commands/navigation_commands.h"
+#import "ios/clean/chrome/browser/ui/commands/tab_grid_commands.h"
 #import "ios/clean/chrome/browser/ui/commands/tools_menu_commands.h"
 #import "ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h"
 #import "ios/showcase/common/protocol_alerter.h"
@@ -28,7 +29,8 @@
 
 - (void)start {
   self.alerter = [[ProtocolAlerter alloc] initWithProtocols:@[
-    @protocol(ToolsMenuCommands), @protocol(NavigationCommands)
+    @protocol(NavigationCommands), @protocol(TabGridCommands),
+    @protocol(ToolsMenuCommands)
   ]];
   self.alerter.baseViewController = self.baseViewController;
 
@@ -44,7 +46,8 @@
   ToolbarViewController* toolbarViewController =
       [[ToolbarViewController alloc] init];
   toolbarViewController.dispatcher =
-      static_cast<id<ToolsMenuCommands, NavigationCommands>>(self.alerter);
+      static_cast<id<NavigationCommands, TabGridCommands, ToolsMenuCommands>>(
+          self.alerter);
   [containerViewController addChildViewController:toolbarViewController];
   toolbarViewController.view.frame = containerView.frame;
   [containerView addSubview:toolbarViewController.view];
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 3adf06d..58eddf6 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -2200,6 +2200,10 @@
   visibility = [ ":test_support" ]
   testonly = true
   sources = [
+    "data/quic_http_response_cache_data_with_push/test.example.com/favicon.ico",
+    "data/quic_http_response_cache_data_with_push/test.example.com/index.html",
+    "data/quic_http_response_cache_data_with_push/test.example.com/index2.html",
+    "data/quic_http_response_cache_data_with_push/test.example.com/kitten-1.jpg",
     "data/ssl/certificates/1024-rsa-ee-by-1024-rsa-intermediate.pem",
     "data/ssl/certificates/1024-rsa-ee-by-2048-rsa-intermediate.pem",
     "data/ssl/certificates/1024-rsa-ee-by-768-rsa-intermediate.pem",
diff --git a/net/disk_cache/simple/simple_index.cc b/net/disk_cache/simple/simple_index.cc
index 4e5c833d..43869ef4 100644
--- a/net/disk_cache/simple/simple_index.cc
+++ b/net/disk_cache/simple/simple_index.cc
@@ -139,7 +139,7 @@
       app_on_background_(false) {}
 
 SimpleIndex::~SimpleIndex() {
-  DCHECK(io_thread_checker_.CalledOnValidThread());
+  CHECK(io_thread_checker_.CalledOnValidThread());
 
   // Fail all callbacks waiting for the index to come up.
   for (CallbackList::iterator it = to_run_when_initialized_.begin(),
@@ -149,7 +149,7 @@
 }
 
 void SimpleIndex::Initialize(base::Time cache_mtime) {
-  DCHECK(io_thread_checker_.CalledOnValidThread());
+  CHECK(io_thread_checker_.CalledOnValidThread());
 
 #if defined(OS_ANDROID)
   if (base::android::IsVMInitialized()) {
@@ -177,7 +177,7 @@
 }
 
 int SimpleIndex::ExecuteWhenReady(const net::CompletionCallback& task) {
-  DCHECK(io_thread_checker_.CalledOnValidThread());
+  CHECK(io_thread_checker_.CalledOnValidThread());
   if (initialized_)
     io_thread_->PostTask(FROM_HERE, base::Bind(task, net::OK));
   else
@@ -250,7 +250,7 @@
 }
 
 void SimpleIndex::Insert(uint64_t entry_hash) {
-  DCHECK(io_thread_checker_.CalledOnValidThread());
+  CHECK(io_thread_checker_.CalledOnValidThread());
   // Upon insert we don't know yet the size of the entry.
   // It will be updated later when the SimpleEntryImpl finishes opening or
   // creating the new entry, and then UpdateEntrySize will be called.
@@ -262,7 +262,7 @@
 }
 
 void SimpleIndex::Remove(uint64_t entry_hash) {
-  DCHECK(io_thread_checker_.CalledOnValidThread());
+  CHECK(io_thread_checker_.CalledOnValidThread());
   EntrySet::iterator it = entries_set_.find(entry_hash);
   if (it != entries_set_.end()) {
     UpdateEntryIteratorSize(&it, 0u);
@@ -281,7 +281,7 @@
 }
 
 bool SimpleIndex::UseIfExists(uint64_t entry_hash) {
-  DCHECK(io_thread_checker_.CalledOnValidThread());
+  CHECK(io_thread_checker_.CalledOnValidThread());
   // Always update the last used time, even if it is during initialization.
   // It will be merged later.
   EntrySet::iterator it = entries_set_.find(entry_hash);
@@ -294,7 +294,7 @@
 }
 
 void SimpleIndex::StartEvictionIfNeeded() {
-  DCHECK(io_thread_checker_.CalledOnValidThread());
+  CHECK(io_thread_checker_.CalledOnValidThread());
   if (eviction_in_progress_ || cache_size_ <= high_watermark_)
     return;
   // Take all live key hashes from the index and sort them by time.
@@ -351,7 +351,7 @@
 
 bool SimpleIndex::UpdateEntrySize(uint64_t entry_hash,
                                   base::StrictNumeric<uint32_t> entry_size) {
-  DCHECK(io_thread_checker_.CalledOnValidThread());
+  CHECK(io_thread_checker_.CalledOnValidThread());
   EntrySet::iterator it = entries_set_.find(entry_hash);
   if (it == entries_set_.end())
     return false;
@@ -363,7 +363,7 @@
 }
 
 void SimpleIndex::EvictionDone(int result) {
-  DCHECK(io_thread_checker_.CalledOnValidThread());
+  CHECK(io_thread_checker_.CalledOnValidThread());
 
   // Ignore the result of eviction. We did our best.
   eviction_in_progress_ = false;
@@ -415,7 +415,7 @@
 
 void SimpleIndex::MergeInitializingSet(
     std::unique_ptr<SimpleIndexLoadResult> load_result) {
-  DCHECK(io_thread_checker_.CalledOnValidThread());
+  CHECK(io_thread_checker_.CalledOnValidThread());
   DCHECK(load_result->did_load);
 
   EntrySet* index_file_entries = &load_result->entries;
@@ -481,7 +481,7 @@
 #if defined(OS_ANDROID)
 void SimpleIndex::OnApplicationStateChange(
     base::android::ApplicationState state) {
-  DCHECK(io_thread_checker_.CalledOnValidThread());
+  CHECK(io_thread_checker_.CalledOnValidThread());
   // For more info about android activities, see:
   // developer.android.com/training/basics/activity-lifecycle/pausing.html
   if (state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES) {
@@ -495,7 +495,7 @@
 #endif
 
 void SimpleIndex::WriteToDisk(IndexWriteToDiskReason reason) {
-  DCHECK(io_thread_checker_.CalledOnValidThread());
+  CHECK(io_thread_checker_.CalledOnValidThread());
   if (!initialized_)
     return;
   SIMPLE_CACHE_UMA(CUSTOM_COUNTS,
diff --git a/net/disk_cache/simple/simple_index.h b/net/disk_cache/simple/simple_index.h
index 2fd3e1f..b573e4b 100644
--- a/net/disk_cache/simple/simple_index.h
+++ b/net/disk_cache/simple/simple_index.h
@@ -228,7 +228,9 @@
 
   // All nonstatic SimpleEntryImpl methods should always be called on the IO
   // thread, in all cases. |io_thread_checker_| documents and enforces this.
-  base::ThreadChecker io_thread_checker_;
+  // NOTE: Temporarily forced on to chase a crash, https://crbug.com/710994,
+  // turn off by 2017-04-21, also going back CHECK -> DCHECK in the impl.
+  base::ThreadCheckerImpl io_thread_checker_;
 
   // Timestamp of the last time we wrote the index to disk.
   // PostponeWritingToDisk() may give up postponing and allow the write if it
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index bf423ec..93d39cc 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -38,6 +38,7 @@
 #include "net/base/upload_data_stream.h"
 #include "net/disk_cache/disk_cache.h"
 #include "net/http/disk_cache_based_quic_server_info.h"
+#include "net/http/http_cache_lookup_manager.h"
 #include "net/http/http_cache_transaction.h"
 #include "net/http/http_network_layer.h"
 #include "net/http/http_network_session.h"
@@ -343,14 +344,20 @@
   // Session may be NULL in unittests.
   // TODO(mmenke): Seems like tests could be changed to provide a session,
   // rather than having logic only used in unit tests here.
-  if (session) {
-    net_log_ = session->net_log();
-    if (is_main_cache &&
-        !session->quic_stream_factory()->has_quic_server_info_factory()) {
-      // QuicStreamFactory takes ownership of QuicServerInfoFactoryAdaptor.
-      session->quic_stream_factory()->set_quic_server_info_factory(
-          new QuicServerInfoFactoryAdaptor(this));
-    }
+  if (!session)
+    return;
+
+  net_log_ = session->net_log();
+  if (!is_main_cache)
+    return;
+
+  session->SetServerPushDelegate(
+      base::MakeUnique<HttpCacheLookupManager>(this));
+
+  if (!session->quic_stream_factory()->has_quic_server_info_factory()) {
+    // QuicStreamFactory takes ownership of QuicServerInfoFactoryAdaptor.
+    session->quic_stream_factory()->set_quic_server_info_factory(
+        new QuicServerInfoFactoryAdaptor(this));
   }
 }
 
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 4b7bcd3..361156b 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -105,6 +105,7 @@
     : client_socket_factory(nullptr),
       host_resolver(nullptr),
       cert_verifier(nullptr),
+      enable_server_push_cancellation(false),
       channel_id_service(nullptr),
       transport_security_state(nullptr),
       cert_transparency_verifier(nullptr),
@@ -396,7 +397,9 @@
 
 void HttpNetworkSession::SetServerPushDelegate(
     std::unique_ptr<ServerPushDelegate> push_delegate) {
-  DCHECK(!push_delegate_ && push_delegate);
+  DCHECK(push_delegate);
+  if (!params_.enable_server_push_cancellation || push_delegate_)
+    return;
 
   push_delegate_ = std::move(push_delegate);
   spdy_session_pool_.set_server_push_delegate(push_delegate_.get());
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index afa78179..6adf6e4 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -85,6 +85,7 @@
     ClientSocketFactory* client_socket_factory;
     HostResolver* host_resolver;
     CertVerifier* cert_verifier;
+    bool enable_server_push_cancellation;
     ChannelIDService* channel_id_service;
     TransportSecurityState* transport_security_state;
     CTVerifier* cert_transparency_verifier;
diff --git a/net/quic/core/quic_server_session_base_test.cc b/net/quic/core/quic_server_session_base_test.cc
index cbd1303..8002891 100644
--- a/net/quic/core/quic_server_session_base_test.cc
+++ b/net/quic/core/quic_server_session_base_test.cc
@@ -210,6 +210,7 @@
   // Send a reset (and expect the peer to send a RST in response).
   QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM,
                           0);
+  EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
   EXPECT_CALL(*connection_,
               SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0));
   visitor_->OnRstStream(rst1);
@@ -227,6 +228,7 @@
   // Send a reset (and expect the peer to send a RST in response).
   QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM,
                           0);
+  EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
   EXPECT_CALL(*connection_,
               SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0));
   visitor_->OnRstStream(rst1);
@@ -253,6 +255,7 @@
 
   // Send a reset (and expect the peer to send a RST in response).
   QuicRstStreamFrame rst(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, 0);
+  EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
   EXPECT_CALL(*connection_,
               SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0));
   visitor_->OnRstStream(rst);
diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc
index 5f106f20..ab7c9b35 100644
--- a/net/quic/core/quic_session.cc
+++ b/net/quic/core/quic_session.cc
@@ -94,6 +94,10 @@
     return;
   }
 
+  if (visitor_) {
+    visitor_->OnRstStreamReceived(frame);
+  }
+
   QuicStream* stream = GetOrCreateDynamicStream(frame.stream_id);
   if (!stream) {
     HandleRstOnValidNonexistentStream(frame);
diff --git a/net/quic/core/quic_session.h b/net/quic/core/quic_session.h
index cba66a0..d3f8dda 100644
--- a/net/quic/core/quic_session.h
+++ b/net/quic/core/quic_session.h
@@ -52,6 +52,9 @@
 
     // Called when the session has become write blocked.
     virtual void OnWriteBlocked(QuicBlockedWriterInterface* blocked_writer) = 0;
+
+    // Called when the session receives reset on a stream from the peer.
+    virtual void OnRstStreamReceived(const QuicRstStreamFrame& frame) = 0;
   };
 
   // CryptoHandshakeEvent enumerates the events generated by a QuicCryptoStream.
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc
index d20b365..4f12a2f 100644
--- a/net/spdy/spdy_session_pool.cc
+++ b/net/spdy/spdy_session_pool.cc
@@ -271,8 +271,7 @@
   DCHECK(!IsSessionAvailable(unavailable_session));
 
   unavailable_session->net_log().AddEvent(
-      NetLogEventType::HTTP2_SESSION_POOL_REMOVE_SESSION,
-      unavailable_session->net_log().source().ToEventParametersCallback());
+      NetLogEventType::HTTP2_SESSION_POOL_REMOVE_SESSION);
 
   SessionSet::iterator it = sessions_.find(unavailable_session.get());
   CHECK(it != sessions_.end());
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index ecc0ad65..e3cd37a 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -146,6 +146,7 @@
     g_time_delta = base::TimeDelta();
     g_time_now = base::TimeTicks::Now();
     session_deps_.net_log = log_.bound().net_log();
+    session_deps_.enable_server_push_cancellation = true;
   }
 
   void CreateNetworkSession() {
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc
index a7df840..6cb1d0c 100644
--- a/net/spdy/spdy_test_util_common.cc
+++ b/net/spdy/spdy_test_util_common.cc
@@ -344,6 +344,7 @@
       enable_ping(false),
       enable_user_alternate_protocol_ports(false),
       enable_quic(false),
+      enable_server_push_cancellation(false),
       session_max_recv_window_size(kDefaultInitialWindowSize),
       time_func(&base::TimeTicks::Now),
       enable_http2_alternative_service_with_different_host(false),
@@ -405,6 +406,8 @@
   params.enable_user_alternate_protocol_ports =
       session_deps->enable_user_alternate_protocol_ports;
   params.enable_quic = session_deps->enable_quic;
+  params.enable_server_push_cancellation =
+      session_deps->enable_server_push_cancellation;
   params.spdy_session_max_recv_window_size =
       session_deps->session_max_recv_window_size;
   params.http2_settings = session_deps->http2_settings;
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h
index d2712f8..2f104755 100644
--- a/net/spdy/spdy_test_util_common.h
+++ b/net/spdy/spdy_test_util_common.h
@@ -208,6 +208,7 @@
   bool enable_ping;
   bool enable_user_alternate_protocol_ports;
   bool enable_quic;
+  bool enable_server_push_cancellation;
   size_t session_max_recv_window_size;
   SettingsMap http2_settings;
   SpdySession::TimeFunc time_func;
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc
index bd691ce..7731031e 100644
--- a/net/tools/quic/quic_dispatcher.cc
+++ b/net/tools/quic/quic_dispatcher.cc
@@ -524,6 +524,8 @@
   write_blocked_list_.insert(std::make_pair(blocked_writer, true));
 }
 
+void QuicDispatcher::OnRstStreamReceived(const QuicRstStreamFrame& frame) {}
+
 void QuicDispatcher::OnConnectionAddedToTimeWaitList(
     QuicConnectionId connection_id) {
   QUIC_DLOG(INFO) << "Connection " << connection_id
diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h
index 50d754f..0edcf78 100644
--- a/net/tools/quic/quic_dispatcher.h
+++ b/net/tools/quic/quic_dispatcher.h
@@ -85,6 +85,11 @@
   // Queues the blocked writer for later resumption.
   void OnWriteBlocked(QuicBlockedWriterInterface* blocked_writer) override;
 
+  // QuicSession::Visitor interface implementation (via inheritance of
+  // QuicTimeWaitListManager::Visitor):
+  // Collects reset error code received on streams.
+  void OnRstStreamReceived(const QuicRstStreamFrame& frame) override;
+
   // QuicTimeWaitListManager::Visitor interface implementation
   // Called whenever the time wait list manager adds a new connection to the
   // time-wait list.
diff --git a/net/tools/quic/quic_simple_dispatcher.cc b/net/tools/quic/quic_simple_dispatcher.cc
index cab2925..e173624 100644
--- a/net/tools/quic/quic_simple_dispatcher.cc
+++ b/net/tools/quic/quic_simple_dispatcher.cc
@@ -26,6 +26,26 @@
 
 QuicSimpleDispatcher::~QuicSimpleDispatcher() {}
 
+int QuicSimpleDispatcher::GetRstErrorCount(
+    QuicRstStreamErrorCode error_code) const {
+  auto it = rst_error_map_.find(error_code);
+  if (it == rst_error_map_.end()) {
+    return 0;
+  } else {
+    return it->second;
+  }
+}
+
+void QuicSimpleDispatcher::OnRstStreamReceived(
+    const QuicRstStreamFrame& frame) {
+  auto it = rst_error_map_.find(frame.error_code);
+  if (it == rst_error_map_.end()) {
+    rst_error_map_.insert(std::make_pair(frame.error_code, 1));
+  } else {
+    it->second++;
+  }
+}
+
 QuicServerSessionBase* QuicSimpleDispatcher::CreateQuicSession(
     QuicConnectionId connection_id,
     const QuicSocketAddress& client_address) {
diff --git a/net/tools/quic/quic_simple_dispatcher.h b/net/tools/quic/quic_simple_dispatcher.h
index b9df6d9..41d24cf 100644
--- a/net/tools/quic/quic_simple_dispatcher.h
+++ b/net/tools/quic/quic_simple_dispatcher.h
@@ -24,6 +24,10 @@
 
   ~QuicSimpleDispatcher() override;
 
+  int GetRstErrorCount(QuicRstStreamErrorCode rst_error_code) const;
+
+  void OnRstStreamReceived(const QuicRstStreamFrame& frame) override;
+
  protected:
   QuicServerSessionBase* CreateQuicSession(
       QuicConnectionId connection_id,
@@ -33,6 +37,9 @@
 
  private:
   QuicHttpResponseCache* response_cache_;  // Unowned.
+
+  // The map of the reset error code with its counter.
+  std::map<QuicRstStreamErrorCode, int> rst_error_map_;
 };
 
 }  // namespace net
diff --git a/net/tools/quic/quic_simple_server_session_test.cc b/net/tools/quic/quic_simple_server_session_test.cc
index 2d90c26b..4cc0329 100644
--- a/net/tools/quic/quic_simple_server_session_test.cc
+++ b/net/tools/quic/quic_simple_server_session_test.cc
@@ -236,6 +236,7 @@
   // Receive a reset (and send a RST in response).
   QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM,
                           0);
+  EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
   EXPECT_CALL(*connection_,
               SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0));
   visitor_->OnRstStream(rst1);
@@ -253,6 +254,7 @@
   // Send a reset (and expect the peer to send a RST in response).
   QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM,
                           0);
+  EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
   EXPECT_CALL(*connection_,
               SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0));
   visitor_->OnRstStream(rst1);
@@ -279,6 +281,7 @@
 
   // Send a reset (and expect the peer to send a RST in response).
   QuicRstStreamFrame rst(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, 0);
+  EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
   EXPECT_CALL(*connection_,
               SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0));
   visitor_->OnRstStream(rst);
@@ -570,6 +573,7 @@
   // Reset the last stream in the queue. It should be marked cancelled.
   QuicStreamId stream_got_reset = num_resources * 2;
   QuicRstStreamFrame rst(stream_got_reset, QUIC_STREAM_CANCELLED, 0);
+  EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
   EXPECT_CALL(*connection_,
               SendRstStream(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT, 0));
   visitor_->OnRstStream(rst);
@@ -614,6 +618,7 @@
       .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false)));
 
   EXPECT_CALL(*connection_, SendBlocked(stream_to_open));
+  EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
   QuicRstStreamFrame rst(stream_got_reset, QUIC_STREAM_CANCELLED, 0);
   visitor_->OnRstStream(rst);
 }
diff --git a/net/tools/quic/test_tools/mock_quic_session_visitor.h b/net/tools/quic/test_tools/mock_quic_session_visitor.h
index ee1a6c7..793be8d4 100644
--- a/net/tools/quic/test_tools/mock_quic_session_visitor.h
+++ b/net/tools/quic/test_tools/mock_quic_session_visitor.h
@@ -23,6 +23,7 @@
                     const std::string& error_details));
   MOCK_METHOD1(OnWriteBlocked,
                void(QuicBlockedWriterInterface* blocked_writer));
+  MOCK_METHOD1(OnRstStreamReceived, void(const QuicRstStreamFrame& frame));
   MOCK_METHOD1(OnConnectionAddedToTimeWaitList,
                void(QuicConnectionId connection_id));
 
diff --git a/net/tools/transport_security_state_generator/BUILD.gn b/net/tools/transport_security_state_generator/BUILD.gn
index 06bfd8b..52ade36 100644
--- a/net/tools/transport_security_state_generator/BUILD.gn
+++ b/net/tools/transport_security_state_generator/BUILD.gn
@@ -62,6 +62,7 @@
   deps = [
     ":transport_security_state_generator_sources",
     "//base",
+    "//build/config/sanitizers:deps",
     "//crypto",
     "//third_party/boringssl",
   ]
diff --git a/net/url_request/url_request_quic_unittest.cc b/net/url_request/url_request_quic_unittest.cc
index 7532196..ff887060 100644
--- a/net/url_request/url_request_quic_unittest.cc
+++ b/net/url_request/url_request_quic_unittest.cc
@@ -15,12 +15,17 @@
 #include "net/cert/mock_cert_verifier.h"
 #include "net/dns/mapped_host_resolver.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/log/net_log_event_type.h"
+#include "net/log/test_net_log.h"
+#include "net/log/test_net_log_entry.h"
 #include "net/quic/chromium/crypto/proof_source_chromium.h"
 #include "net/quic/test_tools/crypto_test_utils.h"
 #include "net/test/cert_test_util.h"
 #include "net/test/gtest_util.h"
 #include "net/test/test_data_directory.h"
+#include "net/tools/quic/quic_dispatcher.h"
 #include "net/tools/quic/quic_http_response_cache.h"
+#include "net/tools/quic/quic_simple_dispatcher.h"
 #include "net/tools/quic/quic_simple_server.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_test_util.h"
@@ -64,14 +69,20 @@
     params->origins_to_force_quic_on.insert(HostPortPair(kTestServerHost, 443));
     params->cert_verifier = &cert_verifier_;
     params->enable_quic = true;
+    params->enable_server_push_cancellation = true;
     context_->set_host_resolver(host_resolver_.get());
     context_->set_http_network_session_params(std::move(params));
     context_->set_cert_verifier(&cert_verifier_);
+    context_->set_net_log(&net_log_);
   }
 
   void TearDown() override {
-    if (server_)
+    if (server_) {
       server_->Shutdown();
+      // If possible, deliver the conncetion close packet to the client before
+      // destruct the TestURLRequestContext.
+      base::RunLoop().RunUntilIdle();
+    }
   }
 
   // Sets a NetworkDelegate to use for |context_|. Must be done before Init().
@@ -88,11 +99,29 @@
     return context_->CreateRequest(url, priority, delegate);
   }
 
+  void ExtractNetLog(NetLogEventType type,
+                     TestNetLogEntry::List* entry_list) const {
+    net::TestNetLogEntry::List entries;
+    net_log_.GetEntries(&entries);
+
+    for (const auto& entry : entries) {
+      if (entry.type == type)
+        entry_list->push_back(entry);
+    }
+  }
+
+  unsigned int GetRstErrorCountReceivedByServer(
+      QuicRstStreamErrorCode error_code) const {
+    return (static_cast<QuicSimpleDispatcher*>(server_->dispatcher()))
+        ->GetRstErrorCount(error_code);
+  }
+
  private:
   void StartQuicServer() {
     // Set up in-memory cache.
     response_cache_.AddSimpleResponse(kTestServerHost, kHelloPath, kHelloStatus,
                                       kHelloBodyValue);
+    response_cache_.InitializeFromDirectory(ServerPushCacheDirectory());
     net::QuicConfig config;
     // Set up server certs.
     std::unique_ptr<net::ProofSourceChromium> proof_source(
@@ -120,9 +149,19 @@
     EXPECT_TRUE(host_resolver_->AddRuleFromString(map_rule));
   }
 
+  std::string ServerPushCacheDirectory() {
+    base::FilePath path;
+    PathService::Get(base::DIR_SOURCE_ROOT, &path);
+    path = path.AppendASCII("net").AppendASCII("data").AppendASCII(
+        "quic_http_response_cache_data_with_push");
+    // The file path is known to be an ascii string.
+    return path.MaybeAsASCII();
+  }
+
   std::unique_ptr<MappedHostResolver> host_resolver_;
   std::unique_ptr<QuicSimpleServer> server_;
   std::unique_ptr<TestURLRequestContext> context_;
+  TestNetLog net_log_;
   QuicHttpResponseCache response_cache_;
   MockCertVerifier cert_verifier_;
 };
@@ -211,6 +250,208 @@
   EXPECT_EQ(kHelloBodyValue, delegate.data_received());
 }
 
+TEST_F(URLRequestQuicTest, CancelPushIfCached) {
+  base::RunLoop run_loop;
+  Init();
+
+  // Send a request to the pushed url: /kitten-1.jpg to pull the resource into
+  // cache.
+  CheckLoadTimingDelegate delegate_0(false);
+  std::string url_0 =
+      base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg");
+  std::unique_ptr<URLRequest> request_0 =
+      CreateRequest(GURL(url_0), DEFAULT_PRIORITY, &delegate_0);
+
+  request_0->Start();
+  ASSERT_TRUE(request_0->is_pending());
+
+  // Spin the message loop until the client receives the response for the first
+  // request.
+  do {
+    base::RunLoop().RunUntilIdle();
+  } while (request_0->status().is_io_pending());
+  EXPECT_TRUE(request_0->status().is_success());
+
+  // Send a request to /index2.html which pushes /kitten-1.jpg and /favicon.ico.
+  // Should cancel push for /kitten-1.jpg.
+  CheckLoadTimingDelegate delegate(true);
+  std::string url =
+      base::StringPrintf("https://%s%s", kTestServerHost, "/index2.html");
+  std::unique_ptr<URLRequest> request =
+      CreateRequest(GURL(url), DEFAULT_PRIORITY, &delegate);
+
+  request->Start();
+  ASSERT_TRUE(request->is_pending());
+
+  // Spin the message loop until the client receives the response for the second
+  // request.
+  do {
+    base::RunLoop().RunUntilIdle();
+  } while (request->status().is_io_pending());
+  EXPECT_TRUE(request->status().is_success());
+
+  // Extract net logs on client side to verify push lookup transactions.
+  net::TestNetLogEntry::List entries;
+  ExtractNetLog(NetLogEventType::SERVER_PUSH_LOOKUP_TRANSACTION, &entries);
+
+  EXPECT_EQ(4u, entries.size());
+
+  std::string value;
+  int net_error;
+  std::string push_url_1 =
+      base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg");
+  std::string push_url_2 =
+      base::StringPrintf("https://%s%s", kTestServerHost, "/favicon.ico");
+
+  EXPECT_TRUE(entries[0].GetStringValue("push_url", &value));
+  EXPECT_EQ(value, push_url_1);
+  // No net error code for this lookup transaction, the push is found.
+  EXPECT_FALSE(entries[1].GetIntegerValue("net_error", &net_error));
+
+  EXPECT_TRUE(entries[2].GetStringValue("push_url", &value));
+  EXPECT_EQ(value, push_url_2);
+  // Net error code -400 is found for this lookup transaction, the push is not
+  // found in the cache.
+  EXPECT_TRUE(entries[3].GetIntegerValue("net_error", &net_error));
+  EXPECT_EQ(net_error, -400);
+
+  // Verify the reset error count received on the server side.
+  EXPECT_LE(1u, GetRstErrorCountReceivedByServer(QUIC_STREAM_CANCELLED));
+}
+
+TEST_F(URLRequestQuicTest, CancelPushIfCached2) {
+  base::RunLoop run_loop;
+  Init();
+
+  // Send a request to the pushed url: /kitten-1.jpg to pull the resource into
+  // cache.
+  CheckLoadTimingDelegate delegate_0(false);
+  std::string url_0 =
+      base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg");
+  std::unique_ptr<URLRequest> request_0 =
+      CreateRequest(GURL(url_0), DEFAULT_PRIORITY, &delegate_0);
+
+  request_0->Start();
+  ASSERT_TRUE(request_0->is_pending());
+
+  // Spin the message loop until the client receives the response for the first
+  // request.
+  do {
+    base::RunLoop().RunUntilIdle();
+  } while (request_0->status().is_io_pending());
+  EXPECT_TRUE(request_0->status().is_success());
+
+  // Send a request to the pushed url: /favicon.ico to pull the resource into
+  // cache.
+  CheckLoadTimingDelegate delegate_1(true);
+  std::string url_1 =
+      base::StringPrintf("https://%s%s", kTestServerHost, "/favicon.ico");
+  std::unique_ptr<URLRequest> request_1 =
+      CreateRequest(GURL(url_1), DEFAULT_PRIORITY, &delegate_1);
+
+  request_1->Start();
+  ASSERT_TRUE(request_1->is_pending());
+
+  // Spin the message loop until the client receives the response for the second
+  // request.
+  do {
+    base::RunLoop().RunUntilIdle();
+  } while (request_1->status().is_io_pending());
+  EXPECT_TRUE(request_1->status().is_success());
+
+  // Send a request to /index2.html which pushes /kitten-1.jpg and /favicon.ico.
+  // Should cancel push for /kitten-1.jpg.
+  CheckLoadTimingDelegate delegate(true);
+  std::string url =
+      base::StringPrintf("https://%s%s", kTestServerHost, "/index2.html");
+  std::unique_ptr<URLRequest> request =
+      CreateRequest(GURL(url), DEFAULT_PRIORITY, &delegate);
+
+  request->Start();
+  ASSERT_TRUE(request->is_pending());
+
+  // Spin the message loop until the client receives the response for the third
+  // request.
+  do {
+    base::RunLoop().RunUntilIdle();
+  } while (request->status().is_io_pending());
+  EXPECT_TRUE(request->status().is_success());
+
+  // Extract net logs on client side to verify push lookup transactions.
+  net::TestNetLogEntry::List entries;
+  ExtractNetLog(NetLogEventType::SERVER_PUSH_LOOKUP_TRANSACTION, &entries);
+
+  EXPECT_EQ(4u, entries.size());
+
+  std::string value;
+  int net_error;
+  std::string push_url_1 =
+      base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg");
+  std::string push_url_2 =
+      base::StringPrintf("https://%s%s", kTestServerHost, "/favicon.ico");
+
+  EXPECT_TRUE(entries[0].GetStringValue("push_url", &value));
+  EXPECT_EQ(value, push_url_1);
+  // No net error code for this lookup transaction, the push is found.
+  EXPECT_FALSE(entries[1].GetIntegerValue("net_error", &net_error));
+
+  EXPECT_TRUE(entries[2].GetStringValue("push_url", &value));
+  EXPECT_EQ(value, push_url_2);
+  // No net error code for this lookup transaction, the push is found.
+  EXPECT_FALSE(entries[3].GetIntegerValue("net_error", &net_error));
+
+  // Verify the reset error count received on the server side.
+  EXPECT_LE(2u, GetRstErrorCountReceivedByServer(QUIC_STREAM_CANCELLED));
+}
+
+TEST_F(URLRequestQuicTest, DoNotCancelPushIfNotFoundInCache) {
+  base::RunLoop run_loop;
+  Init();
+
+  // Send a request to /index2.hmtl which pushes /kitten-1.jpg and /favicon.ico
+  // and shouldn't cancel any since neither is in cache.
+  CheckLoadTimingDelegate delegate(false);
+  std::string url =
+      base::StringPrintf("https://%s%s", kTestServerHost, "/index2.html");
+  std::unique_ptr<URLRequest> request =
+      CreateRequest(GURL(url), DEFAULT_PRIORITY, &delegate);
+
+  request->Start();
+  ASSERT_TRUE(request->is_pending());
+
+  // Spin the message loop until the client receives response.
+  do {
+    base::RunLoop().RunUntilIdle();
+  } while (request->status().is_io_pending());
+  EXPECT_TRUE(request->status().is_success());
+
+  // Extract net logs on client side to verify push lookup transactions.
+  net::TestNetLogEntry::List entries;
+  ExtractNetLog(NetLogEventType::SERVER_PUSH_LOOKUP_TRANSACTION, &entries);
+
+  EXPECT_EQ(4u, entries.size());
+
+  std::string value;
+  int net_error;
+  std::string push_url_1 =
+      base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg");
+  std::string push_url_2 =
+      base::StringPrintf("https://%s%s", kTestServerHost, "/favicon.ico");
+
+  EXPECT_TRUE(entries[0].GetStringValue("push_url", &value));
+  EXPECT_EQ(value, push_url_1);
+  EXPECT_TRUE(entries[1].GetIntegerValue("net_error", &net_error));
+  EXPECT_EQ(net_error, -400);
+
+  EXPECT_TRUE(entries[2].GetStringValue("push_url", &value));
+  EXPECT_EQ(value, push_url_2);
+  EXPECT_TRUE(entries[3].GetIntegerValue("net_error", &net_error));
+  EXPECT_EQ(net_error, -400);
+
+  // Verify the reset error count received on the server side.
+  EXPECT_EQ(0u, GetRstErrorCountReceivedByServer(QUIC_STREAM_CANCELLED));
+}
+
 // Tests that if two requests use the same QUIC session, the second request
 // should not have |LoadTimingInfo::connect_timing|.
 TEST_F(URLRequestQuicTest, TestTwoRequests) {
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc
index 1e905fd..5f7f123 100644
--- a/net/url_request/url_request_test_util.cc
+++ b/net/url_request/url_request_test_util.cc
@@ -135,7 +135,7 @@
         base::MakeUnique<HttpNetworkSession>(params));
     context_storage_.set_http_transaction_factory(base::MakeUnique<HttpCache>(
         context_storage_.http_network_session(),
-        HttpCache::DefaultBackend::InMemory(0), false));
+        HttpCache::DefaultBackend::InMemory(0), true /* is_main_cache */));
   }
   if (!http_user_agent_settings()) {
     context_storage_.set_http_user_agent_settings(
diff --git a/printing/pdf_metafile_skia.cc b/printing/pdf_metafile_skia.cc
index aec4d3f..b2e914b3 100644
--- a/printing/pdf_metafile_skia.cc
+++ b/printing/pdf_metafile_skia.cc
@@ -12,9 +12,9 @@
 #include "base/files/file.h"
 #include "base/memory/ptr_util.h"
 #include "base/time/time.h"
+#include "cc/paint/paint_canvas.h"
 #include "cc/paint/paint_record.h"
 #include "cc/paint/paint_recorder.h"
-#include "cc/paint/skia_paint_canvas.h"
 #include "printing/print_settings.h"
 #include "third_party/skia/include/core/SkDocument.h"
 #include "third_party/skia/include/core/SkStream.h"
diff --git a/remoting/host/linux/BUILD.gn b/remoting/host/linux/BUILD.gn
index 4315e87..0c7ed70e 100644
--- a/remoting/host/linux/BUILD.gn
+++ b/remoting/host/linux/BUILD.gn
@@ -16,6 +16,7 @@
 
     deps = [
       "//base",
+      "//build/config/sanitizers:deps",
     ]
 
     libs = [ "pam" ]
diff --git a/services/service_manager/tests/connect/BUILD.gn b/services/service_manager/tests/connect/BUILD.gn
index 38aa864..6fd272a4 100644
--- a/services/service_manager/tests/connect/BUILD.gn
+++ b/services/service_manager/tests/connect/BUILD.gn
@@ -144,6 +144,7 @@
   deps = [
     ":interfaces",
     "//base",
+    "//build/config/sanitizers:deps",
     "//build/win:default_exe_manifest",
     "//services/service_manager/public/cpp",
     "//services/service_manager/public/cpp/standalone_service:main",
diff --git a/services/service_manager/tests/lifecycle/BUILD.gn b/services/service_manager/tests/lifecycle/BUILD.gn
index faf41b14..403ac50c 100644
--- a/services/service_manager/tests/lifecycle/BUILD.gn
+++ b/services/service_manager/tests/lifecycle/BUILD.gn
@@ -132,6 +132,7 @@
   deps = [
     ":app_client",
     "//base",
+    "//build/config/sanitizers:deps",
     "//build/win:default_exe_manifest",
     "//services/service_manager/public/cpp:sources",
     "//services/service_manager/public/cpp/standalone_service:main",
diff --git a/services/service_manager/tests/service_manager/BUILD.gn b/services/service_manager/tests/service_manager/BUILD.gn
index 3a34cf5..8dee88f 100644
--- a/services/service_manager/tests/service_manager/BUILD.gn
+++ b/services/service_manager/tests/service_manager/BUILD.gn
@@ -57,6 +57,7 @@
   deps = [
     ":interfaces",
     "//base",
+    "//build/config/sanitizers:deps",
     "//build/win:default_exe_manifest",
     "//services/service_manager/public/cpp",
     "//services/service_manager/public/cpp/standalone_service:main",
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 7ee554e..c3d7cab 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2786,3 +2786,7 @@
 crbug.com/682753 fast/canvas-experimental [ Skip ]
 
 crbug.com/708934 fast/backgrounds/background-image-relative-url-in-iframe.html [ Failure Pass ]
+
+# Sheriff failures 2017-04-14
+crbug.com/711689 [ Mac ] paint/invalidation/text-match-document-change.html [ Failure ]
+crbug.com/711689 [ Mac ] virtual/disable-spinvalidation/paint/invalidation/text-match-document-change.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/layers-in-multicol-expected.html b/third_party/WebKit/LayoutTests/fast/multicol/layers-in-multicol-expected.html
new file mode 100644
index 0000000..97d5761f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/multicol/layers-in-multicol-expected.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<style>
+    .multicol {
+        width: 300px;
+        height: 100px;
+        line-height: 20px;
+        border: 5px solid maroon;
+    }
+    .column {
+        width: 100px;
+        float: left;
+    }
+    .multicol[dir="rtl"] > .column {
+        float: right;
+    }
+    .block {
+        display: inline-block;
+        width: 1em;
+        height: 10px;
+        background-color: green;
+    }
+    .opacity {
+        opacity: 0.5;
+        color: green;
+    }
+    .relative {
+        position: relative;
+        top: -4px;
+        color: green;
+    }
+</style>
+<p>
+    Test layers which are fully contained within a single column.
+</p>
+LTR:
+<div class="multicol">
+    <div class="column">
+        line1<br>
+        line2<br>
+        line3<br>
+        line4<br>
+        line5<br>
+    </div>
+    <div class="column">
+        line6<br>
+        <div class="block"></div> line7<br>
+        line8<br>
+        <span class="relative">relative9</span><br>
+        line10<br>
+    </div>
+    <div class="column">
+        line11<br>
+        line12<br>
+        <!-- The extra inner span below forces the creation of a transparency layer in Skia to work
+             around optimizations that would cause blending differences between the test and the
+             expectation. -->
+        <span class="opacity">opacity<span>13</span></span><br>
+        line14
+    </div>
+</div>
+
+RTL:
+<div class="multicol" dir="rtl">
+    <div class="column">
+        line1<br>
+        line2<br>
+        line3<br>
+        line4<br>
+        line5<br>
+    </div>
+    <div class="column">
+        line6<br>
+        <div class="block"></div> line7<br>
+        line8<br>
+        <span class="relative">relative9</span><br>
+        line10<br>
+    </div>
+    <div class="column">
+        line11<br>
+        line12<br>
+        <!-- The extra inner span below forces the creation of a transparency layer in Skia to work
+             around optimizations that would cause blending differences between the test and the
+             expectation. -->
+        <span class="opacity">opacity<span>13</span></span><br>
+        line14
+    </div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/layers-split-across-columns-expected.html b/third_party/WebKit/LayoutTests/fast/multicol/layers-split-across-columns-expected.html
new file mode 100644
index 0000000..8bbd920
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/multicol/layers-split-across-columns-expected.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<style>
+    .container {
+        margin-right: 4px;
+        position: absolute;
+    }
+    .multicol {
+        width: 110px;
+        height: 150px;
+        border: 5px solid black;
+    }
+    .multicol > div {
+        float: left;
+        width: 50px;
+        height: 50px;
+    }
+
+    .row1_left { background-color: black; }
+    .row1_right { background-color: #0000b0; }
+    .row2_left { background-color: #0000f0; }
+    .row2_right { background-color: #000090; }
+    .row3_left { background-color: #0000d0; }
+    .row3_right { background-color: black; }
+
+    .row1_right,
+    .row2_right,
+    .row3_right {
+        margin-left: 10px;
+    }
+
+    #opacity .row1_right,
+    #opacity .row2_left,
+    #opacity .row2_right,
+    #opacity .row3_left {
+        opacity: 0.99;
+    }
+
+    .pos1 { left: 10px; top: 10px; }
+    .pos2 { left: 150px; top: 10px; }
+    .pos3 { left: 10px; top: 200px; }
+    .pos4 { left: 150px; top: 200px; }
+
+</style>
+<div class="container pos1">
+    Overflow:
+    <div class="multicol">
+        <div class="row1_left"></div>
+        <div class="row1_right"></div>
+        <div class="row2_left"></div>
+        <div class="row2_right"></div>
+        <div class="row3_left"></div>
+        <div class="row3_right"></div>
+    </div>
+</div>
+<div class="container pos2">
+    Transforms:
+    <div class="multicol">
+        <div class="row1_left"></div>
+        <div class="row1_right"></div>
+        <div class="row2_left"></div>
+        <div class="row2_right"></div>
+        <div class="row3_left"></div>
+        <div class="row3_right"></div>
+    </div>
+</div>
+<div class="container pos3">
+    Relative Pos.:
+    <div class="multicol">
+        <div class="row1_left"></div>
+        <div class="row1_right"></div>
+        <div class="row2_left"></div>
+        <div class="row2_right"></div>
+        <div class="row3_left"></div>
+        <div class="row3_right"></div>
+    </div>
+</div>
+<div class="container pos4" id="opacity">
+    Opacity:
+    <div class="multicol">
+        <div class="row1_left"></div>
+        <!-- The extra &nbsp;s below force the creation of transparency layers in Skia to work
+             around optimizations that would cause blending differences between the test and the
+             expectation. -->
+        <div class="row1_right">&nbsp;</div>
+        <div class="row2_left">&nbsp;</div>
+        <div class="row2_right">&nbsp;</div>
+        <div class="row3_left">&nbsp;</div>
+        <div class="row3_right"></div>
+    </div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.html b/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.html
new file mode 100644
index 0000000..0b67873
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.html
@@ -0,0 +1,6 @@
+<div style="position:relative; width:420px;border:2px solid black; height:200px">
+<!-- The extra &nbsp; below forces the creation of a transparency layer in Skia to work around
+     optimizations that would cause blending differences between the test and the expectation. -->
+<div style="opacity:0.5; position:absolute;width:200px;height:100px;background-color:green;right:0;top:0">&nbsp;</div>
+</div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.png b/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.png
deleted file mode 100644
index 1ebb6e8..0000000
--- a/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-cross-origin-iframe-logging.html b/third_party/WebKit/LayoutTests/http/tests/inspector/console-cross-origin-iframe-logging.html
index 950a8cf7..42515561 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-cross-origin-iframe-logging.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-cross-origin-iframe-logging.html
@@ -23,12 +23,8 @@
 {
     var finishAttemptsLeft = 2;
     InspectorTest.addConsoleSniffer(maybeFinish, true);
-    InspectorTest.NetworkAgent.setMonitoringXHREnabled(true, step1);
-
-    function step1()
-    {
-        InspectorTest.evaluateInPage("accessFrame()", maybeFinish);
-    }
+    Common.settingForTest('monitoringXHREnabled').set(true);
+    InspectorTest.evaluateInPage("accessFrame()", maybeFinish);
 
     function maybeFinish()
     {
@@ -36,11 +32,7 @@
         if (finishAttemptsLeft)
             return;
 
-        InspectorTest.NetworkAgent.setMonitoringXHREnabled(false, finish);
-    }
-
-    function finish()
-    {
+        Common.settingForTest('monitoringXHREnabled').set(false);
         InspectorTest.dumpConsoleMessages();
         InspectorTest.completeTest();
     }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-fetch-logging.html b/third_party/WebKit/LayoutTests/http/tests/inspector/console-fetch-logging.html
index 6ec9885..04e70bc 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-fetch-logging.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-fetch-logging.html
@@ -54,20 +54,14 @@
 
     function step1()
     {
-        function callback()
-        {
-            InspectorTest.callFunctionInPageAsync("makeRequests").then(step2);
-        }
-        InspectorTest.NetworkAgent.setMonitoringXHREnabled(true, callback);
+        Common.settingForTest('monitoringXHREnabled').set(true);
+        InspectorTest.callFunctionInPageAsync("makeRequests").then(step2);
     }
 
     function step2()
     {
-        function callback()
-        {
-            InspectorTest.callFunctionInPageAsync("makeRequests").then(step3);
-        }
-        InspectorTest.NetworkAgent.setMonitoringXHREnabled(false, callback);
+        Common.settingForTest('monitoringXHREnabled').set(false);
+        InspectorTest.callFunctionInPageAsync("makeRequests").then(step3);
     }
 
     function step3()
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async-expected.txt
index 78f8410..7604d45 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async-expected.txt
@@ -3,10 +3,10 @@
 Tests that XMLHttpRequest Logging works when Enabled and doesn't show logs when Disabled for asynchronous XHRs.
 
 Bug 79229
+network-test.js:6 XHR loaded: 1
 network-test.js:37 XHR finished loading: GET "http://127.0.0.1:8000/inspector/resources/xhr-exists.html".
 makeXHR @ network-test.js:37
 makeXHRForJSONArguments @ network-test.js:43
 (anonymous) @ VM:1
-network-test.js:6 XHR loaded: 1
 network-test.js:6 XHR loaded: 2
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async.html b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async.html
index 280d809c..b759e5be 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async.html
@@ -15,22 +15,14 @@
 
     function step1()
     {
-        function callback()
-        {
-            makeRequest(step2);
-        }
-
-        InspectorTest.NetworkAgent.setMonitoringXHREnabled(true, callback);
+        Common.settingForTest('monitoringXHREnabled').set(true);
+        makeRequest(step2);
     }
 
     function step2()
     {
-        function callback()
-        {
-            makeRequest(step3);
-        }
-
-        InspectorTest.NetworkAgent.setMonitoringXHREnabled(false, callback);
+        Common.settingForTest('monitoringXHREnabled').set(false);
+        makeRequest(step3);
     }
 
     function step3()
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-expected.txt
index bb38e6e5..dd9ac27 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-expected.txt
@@ -17,14 +17,12 @@
 makeSimpleXHRWithPayload @ network-test.js:16
 makeSimpleXHR @ network-test.js:11
 requestHelper @ console-xhr-logging.html:6
-makeRequests @ console-xhr-logging.html:12
 (anonymous) @ VM:1
 network-test.js:37 XHR finished loading: GET "http://127.0.0.1:8000/inspector/resources/xhr-exists.html".
 makeXHR @ network-test.js:37
 makeSimpleXHRWithPayload @ network-test.js:16
 makeSimpleXHR @ network-test.js:11
 requestHelper @ console-xhr-logging.html:6
-makeRequests @ console-xhr-logging.html:12
 (anonymous) @ VM:1
 console-xhr-logging.html:5 sending a GET request to resources/xhr-does-not-exist.html
 network-test.js:37 GET http://127.0.0.1:8000/inspector/resources/xhr-does-not-exist.html 404 (Not Found)
@@ -32,14 +30,12 @@
 makeSimpleXHRWithPayload @ network-test.js:16
 makeSimpleXHR @ network-test.js:11
 requestHelper @ console-xhr-logging.html:6
-makeRequests @ console-xhr-logging.html:14
 (anonymous) @ VM:1
-network-test.js:37 XHR finished loading: GET "http://127.0.0.1:8000/inspector/resources/xhr-does-not-exist.html".
+network-test.js:37 XHR failed loading: GET "http://127.0.0.1:8000/inspector/resources/xhr-does-not-exist.html".
 makeXHR @ network-test.js:37
 makeSimpleXHRWithPayload @ network-test.js:16
 makeSimpleXHR @ network-test.js:11
 requestHelper @ console-xhr-logging.html:6
-makeRequests @ console-xhr-logging.html:14
 (anonymous) @ VM:1
 console-xhr-logging.html:5 sending a POST request to resources/post-target.cgi
 network-test.js:37 XHR finished loading: POST "http://127.0.0.1:8000/inspector/resources/post-target.cgi".
@@ -47,7 +43,6 @@
 makeSimpleXHRWithPayload @ network-test.js:16
 makeSimpleXHR @ network-test.js:11
 requestHelper @ console-xhr-logging.html:6
-makeRequests @ console-xhr-logging.html:16
 (anonymous) @ VM:1
 console-xhr-logging.html:5 sending a GET request to http://localhost:8000/inspector/resources/xhr-exists.html
 network-test.js:37 XMLHttpRequest cannot load http://localhost:8000/inspector/resources/xhr-exists.html. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8000' is therefore not allowed access.
@@ -55,14 +50,12 @@
 makeSimpleXHRWithPayload @ network-test.js:16
 makeSimpleXHR @ network-test.js:11
 requestHelper @ console-xhr-logging.html:6
-makeRequests @ console-xhr-logging.html:18
 (anonymous) @ VM:1
-network-test.js:37 XHR failed loading: GET "http://localhost:8000/inspector/resources/xhr-exists.html".
+network-test.js:37 XHR finished loading: GET "http://localhost:8000/inspector/resources/xhr-exists.html".
 makeXHR @ network-test.js:37
 makeSimpleXHRWithPayload @ network-test.js:16
 makeSimpleXHR @ network-test.js:11
 requestHelper @ console-xhr-logging.html:6
-makeRequests @ console-xhr-logging.html:18
 (anonymous) @ VM:1
 console-xhr-logging.html:5 sending a GET request to resources/xhr-exists.html
 console-xhr-logging.html:5 sending a GET request to resources/xhr-does-not-exist.html
@@ -71,7 +64,6 @@
 makeSimpleXHRWithPayload @ network-test.js:16
 makeSimpleXHR @ network-test.js:11
 requestHelper @ console-xhr-logging.html:6
-makeRequests @ console-xhr-logging.html:14
 (anonymous) @ VM:1
 console-xhr-logging.html:5 sending a POST request to resources/post-target.cgi
 console-xhr-logging.html:5 sending a GET request to http://localhost:8000/inspector/resources/xhr-exists.html
@@ -80,6 +72,5 @@
 makeSimpleXHRWithPayload @ network-test.js:16
 makeSimpleXHR @ network-test.js:11
 requestHelper @ console-xhr-logging.html:6
-makeRequests @ console-xhr-logging.html:18
 (anonymous) @ VM:1
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging.html b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging.html
index da78e725..9bd30b4 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging.html
@@ -11,49 +11,23 @@
     makeSimpleXHR(method, url, false);
 }
 
-function makeRequests()
+async function test()
 {
-    // 1. Page that exists.
-    requestHelper("GET", "resources/xhr-exists.html");
-    // 2. Page that doesn't exist.
-    requestHelper("GET", "resources/xhr-does-not-exist.html");
-    // 3. POST to a page.
-    requestHelper("POST", "resources/post-target.cgi");
-    // 4. Cross-origin request
-    requestHelper("GET", "http://localhost:8000/inspector/resources/xhr-exists.html");
-}
+    Common.settingForTest('monitoringXHREnabled').set(true);
+    await InspectorTest.evaluateInPagePromise("requestHelper('GET', 'resources/xhr-exists.html')");
+    await InspectorTest.evaluateInPagePromise("requestHelper('GET', 'resources/xhr-does-not-exist.html')");
+    await InspectorTest.evaluateInPagePromise("requestHelper('POST', 'resources/post-target.cgi')");
+    await InspectorTest.evaluateInPagePromise("requestHelper('GET', 'http://localhost:8000/inspector/resources/xhr-exists.html')");
+    Common.settingForTest('monitoringXHREnabled').set(false);
+    await InspectorTest.evaluateInPagePromise("requestHelper('GET', 'resources/xhr-exists.html')");
+    await InspectorTest.evaluateInPagePromise("requestHelper('GET', 'resources/xhr-does-not-exist.html')");
+    await InspectorTest.evaluateInPagePromise("requestHelper('POST', 'resources/post-target.cgi')");
+    await InspectorTest.evaluateInPagePromise("requestHelper('GET', 'http://localhost:8000/inspector/resources/xhr-exists.html')");
 
-function test()
-{
-    step1();
-
-    function step1()
-    {
-        function callback()
-        {
-            InspectorTest.evaluateInPage("makeRequests()", step2);
-        }
-        InspectorTest.NetworkAgent.setMonitoringXHREnabled(true, callback);
-    }
-
-    function step2()
-    {
-        function callback()
-        {
-            InspectorTest.evaluateInPage("makeRequests()", step3);
-        }
-        InspectorTest.NetworkAgent.setMonitoringXHREnabled(false, callback);
-    }
-
-    function step3()
-    {
-        function finish()
-        {
-            InspectorTest.dumpConsoleMessages();
-            InspectorTest.completeTest();
-        }
-        InspectorTest.deprecatedRunAfterPendingDispatches(finish);
-    }
+    InspectorTest.deprecatedRunAfterPendingDispatches(() => {
+      InspectorTest.dumpConsoleMessages();
+      InspectorTest.completeTest();
+    });
 }
 //# sourceURL=console-xhr-logging.html
 </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/report-API-errors-expected.txt b/third_party/WebKit/LayoutTests/inspector/report-API-errors-expected.txt
index 0f9a07cf5..667528b 100644
--- a/third_party/WebKit/LayoutTests/inspector/report-API-errors-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/report-API-errors-expected.txt
@@ -1,8 +1,8 @@
 Tests that InspectorBackendStub is catching incorrect arguments.
 
-Protocol Error: Invalid type of argument 'enabled' for method 'Network.setMonitoringXHREnabled' call. It must be 'boolean' but it is 'number'.
-Protocol Error: Invalid number of arguments for method 'Network.setMonitoringXHREnabled' call. It must have the following arguments '[{"name":"enabled","type":"boolean","optional":false}]'.
-Protocol Error: Optional callback argument for method 'Network.setMonitoringXHREnabled' call must be a function but its type is 'string'.
+Protocol Error: Invalid type of argument 'userAgent' for method 'Network.setUserAgentOverride' call. It must be 'string' but it is 'number'.
+Protocol Error: Invalid number of arguments for method 'Network.setUserAgentOverride' call. It must have the following arguments '[{"name":"userAgent","type":"string","optional":false}]'.
+Protocol Error: Optional callback argument for method 'Network.setUserAgentOverride' call must be a function but its type is 'string'.
 Protocol Error: the message wrongDomain.something-strange is for non-existing domain 'wrongDomain': {"method":"wrongDomain.something-strange","params":{}}
 Protocol Error: Attempted to dispatch an unspecified method 'Inspector.something-strange': {"method":"Inspector.something-strange","params":{}}
 
diff --git a/third_party/WebKit/LayoutTests/inspector/report-API-errors.html b/third_party/WebKit/LayoutTests/inspector/report-API-errors.html
index b9e40bf2..a60e7ad 100644
--- a/third_party/WebKit/LayoutTests/inspector/report-API-errors.html
+++ b/third_party/WebKit/LayoutTests/inspector/report-API-errors.html
@@ -11,10 +11,10 @@
         InspectorTest.addResult(String.sprintf.apply(this, arguments));
     }
 
-    InspectorTest.NetworkAgent.setMonitoringXHREnabled(1);
-    InspectorTest.NetworkAgent.setMonitoringXHREnabled();
-    InspectorTest.NetworkAgent.setMonitoringXHREnabled(false, "not a function");
-    InspectorTest.NetworkAgent.setMonitoringXHREnabled(false, undefined);
+    InspectorTest.NetworkAgent.setUserAgentOverride(1);
+    InspectorTest.NetworkAgent.setUserAgentOverride();
+    InspectorTest.NetworkAgent.setUserAgentOverride("123", "not a function");
+    InspectorTest.NetworkAgent.setUserAgentOverride("123", undefined);
     InspectorTest.RuntimeAgent.evaluate("true", "test");
     InspectorTest.RuntimeAgent.evaluate("true", "test", function(){});
     InspectorTest.RuntimeAgent.evaluate("true", "test", undefined, function(){});
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.png b/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.png
index c6cabcbb..a92e6a8 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.png
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-in-multicol-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-in-multicol-expected.png
deleted file mode 100644
index 44fc4a4..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-in-multicol-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-split-across-columns-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-split-across-columns-expected.png
deleted file mode 100644
index 27fbf58..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-split-across-columns-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 5e1fff8..b024e71 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png
index 6f98684..8d5f6fd3 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 5e1fff8..b024e71 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png
index 0acea10..3a881330 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 991aaf7a..07e019c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/2d/hindi-rotated-expected.png
index 84b89da..11b5d71 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/transformed-focused-text-input-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/transformed-focused-text-input-expected.png
index 1693941..f409f9e 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/transformed-focused-text-input-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/transformed-focused-text-input-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 991aaf7a..07e019c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-in-multicol-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-in-multicol-expected.png
deleted file mode 100644
index 9243efa..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-in-multicol-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.png
deleted file mode 100644
index 86cf379..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index af00c64c0..56d7e380c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
index 31dd704..ab426ac 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
index 98ce8c5..7e1243a1 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
index 556507c..8938c8b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png
index 70f55312..497919fc 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-focused-text-input-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-focused-text-input-expected.png
index c57f417b..38e6870 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-focused-text-input-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-focused-text-input-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index af00c64c0..56d7e380c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-in-multicol-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-in-multicol-expected.png
deleted file mode 100644
index 62b98ea..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-in-multicol-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-split-across-columns-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-split-across-columns-expected.png
deleted file mode 100644
index 608b610..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-split-across-columns-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 6eb1bf6..8829276ef 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png
index 5b597ed..6837fed 100644
--- a/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 6eb1bf6..8829276ef 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 27dad6f..bbb8278 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/win7/transforms/2d/hindi-rotated-expected.png
index 855bfdf8..7e9778db 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win7/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 27dad6f..bbb8278 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win7/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/Source/core/animation/AnimationTimeline.idl b/third_party/WebKit/Source/core/animation/AnimationTimeline.idl
index d43ebba4..79726c0 100644
--- a/third_party/WebKit/Source/core/animation/AnimationTimeline.idl
+++ b/third_party/WebKit/Source/core/animation/AnimationTimeline.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// http://www.w3.org/TR/web-animations/#the-animationtimeline-interface
+// https://w3c.github.io/web-animations/#the-animationtimeline-interface
 
 [
     RuntimeEnabled=WebAnimationsAPI,
diff --git a/third_party/WebKit/Source/core/animation/DocumentTimeline.idl b/third_party/WebKit/Source/core/animation/DocumentTimeline.idl
index 62d7b8b8..ba3ba5b 100644
--- a/third_party/WebKit/Source/core/animation/DocumentTimeline.idl
+++ b/third_party/WebKit/Source/core/animation/DocumentTimeline.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// http://www.w3.org/TR/web-animations/#the-documenttimeline-interface
+// https://w3c.github.io/web-animations/#the-documenttimeline-interface
 
 [
     RuntimeEnabled=WebAnimationsAPI,
diff --git a/third_party/WebKit/Source/core/animation/ElementAnimation.idl b/third_party/WebKit/Source/core/animation/ElementAnimation.idl
index 018a7af..025edd4 100644
--- a/third_party/WebKit/Source/core/animation/ElementAnimation.idl
+++ b/third_party/WebKit/Source/core/animation/ElementAnimation.idl
@@ -28,14 +28,14 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// http://www.w3.org/TR/web-animations/#the-animatable-interface
-// http://www.w3.org/TR/web-animations/#extensions-to-the-element-interface
+// https://w3c.github.io/web-animations/#the-animatable-interface
+// https://w3c.github.io/web-animations/#extensions-to-the-element-interface
 
 // TODO(dstockwell): This should be an Animatable interface, where Element
-// implements Animatable. The interface also has several changes:
-// https://w3c.github.io/web-animations/#the-animatable-interface
+// implements Animatable.
 
 partial interface Element {
+    // TODO(dstockwell): The argument types do not match the spec.
     [CallWith=ScriptState, Measure, RaisesException] Animation animate((sequence<Dictionary> or Dictionary)? effect, optional (unrestricted double or KeyframeEffectOptions) options);
     [RuntimeEnabled=WebAnimationsAPI] sequence<Animation> getAnimations();
 };
diff --git a/third_party/WebKit/Source/core/css/CSSFontFaceRule.idl b/third_party/WebKit/Source/core/css/CSSFontFaceRule.idl
index 480d556..88f4e8d 100644
--- a/third_party/WebKit/Source/core/css/CSSFontFaceRule.idl
+++ b/third_party/WebKit/Source/core/css/CSSFontFaceRule.idl
@@ -23,8 +23,9 @@
 // https://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSFontFaceRule
 // https://dev.w3.org/csswg/css-fonts/#om-fontface
 //
-// The interface from DOM Level 2 Style is implemented here.
-// TODO(foolip): Implement the interface from CSS Fonts.
+// TODO(foolip): Make CSSFontFaceRule match new spec and/or change spec to match
+// what's implemented. https://crbug.com/709013
+// https://github.com/w3c/csswg-drafts/issues/825
 
 interface CSSFontFaceRule : CSSRule {
     [Measure] readonly attribute CSSStyleDeclaration style;
diff --git a/third_party/WebKit/Source/core/css/StyleMedia.idl b/third_party/WebKit/Source/core/css/StyleMedia.idl
index 52b6412..7ac7b727 100644
--- a/third_party/WebKit/Source/core/css/StyleMedia.idl
+++ b/third_party/WebKit/Source/core/css/StyleMedia.idl
@@ -29,7 +29,7 @@
 // https://www.w3.org/TR/2009/WD-cssom-view-20090804/#the-media-interface
 // https://web.archive.org/web/20100206142043/http://dev.w3.org/csswg/cssom-view#the-stylemedia-interface
 //
-// TODO(foolip): Remove this interface.
+// TODO(foolip): Remove this interface. https://crbug.com/692839
 
 [
     NoInterfaceObject,
diff --git a/third_party/WebKit/Source/core/dom/Document.idl b/third_party/WebKit/Source/core/dom/Document.idl
index 575e640..41e4115 100644
--- a/third_party/WebKit/Source/core/dom/Document.idl
+++ b/third_party/WebKit/Source/core/dom/Document.idl
@@ -180,7 +180,7 @@
     [CustomElementCallbacks, RaisesException] Element createElementNS(DOMString? namespaceURI, DOMString qualifiedName, (DOMString or Dictionary)? options);
 
     // Page Visibility
-    // https://www.w3.org/TR/page-visibility/#sec-document-interface
+    // https://w3c.github.io/page-visibility/#extensions-to-the-document-interface
     readonly attribute boolean hidden;
     readonly attribute VisibilityState visibilityState;
 
diff --git a/third_party/WebKit/Source/core/dom/FrameRequestCallback.idl b/third_party/WebKit/Source/core/dom/FrameRequestCallback.idl
index 1e3e8a48..66dbef1 100644
--- a/third_party/WebKit/Source/core/dom/FrameRequestCallback.idl
+++ b/third_party/WebKit/Source/core/dom/FrameRequestCallback.idl
@@ -32,6 +32,6 @@
 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=28152
 callback interface FrameRequestCallback {
     // highResTime is passed as high resolution timestamp, see
-    // http://www.w3.org/TR/hr-time/ for details.
+    // https://w3c.github.io/hr-time/ for details.
     void handleEvent(double highResTime);
 };
diff --git a/third_party/WebKit/Source/core/events/InputEvent.idl b/third_party/WebKit/Source/core/events/InputEvent.idl
index 6db312ae..d2574da 100644
--- a/third_party/WebKit/Source/core/events/InputEvent.idl
+++ b/third_party/WebKit/Source/core/events/InputEvent.idl
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// UI Events
+// https://w3c.github.io/uievents/#idl-inputevent
+
 [
     Constructor(DOMString type, optional InputEventInit eventInitDict),
     RuntimeEnabled=InputEvent,
 ] interface InputEvent : UIEvent {
-    // UI Events
-    // https://w3c.github.io/uievents/#idl-inputevent
     readonly attribute DOMString? data;
     readonly attribute boolean isComposing;
 
diff --git a/third_party/WebKit/Source/core/events/InputEventInit.idl b/third_party/WebKit/Source/core/events/InputEventInit.idl
index 81d0375c..9f59850 100644
--- a/third_party/WebKit/Source/core/events/InputEventInit.idl
+++ b/third_party/WebKit/Source/core/events/InputEventInit.idl
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// UI Events
+// https://w3c.github.io/uievents/#idl-inputeventinit
+
 dictionary InputEventInit : UIEventInit {
-    // UI Events
-    // https://w3c.github.io/uievents/#idl-inputeventinit
     DOMString? data;
     boolean isComposing = false;
 
diff --git a/third_party/WebKit/Source/core/events/TextEvent.idl b/third_party/WebKit/Source/core/events/TextEvent.idl
index 84d278a..2ae52eb 100644
--- a/third_party/WebKit/Source/core/events/TextEvent.idl
+++ b/third_party/WebKit/Source/core/events/TextEvent.idl
@@ -25,8 +25,9 @@
 
 // http://www.w3.org/TR/2011/WD-DOM-Level-3-Events-20110531/#webidl-events-TextEvent
 
-// TODO(foolip): Remove the textinput event and the TextEvent interface. They
-// were removed from the spec in 2012:
+// TODO(foolip): Remove the textinput event and the TextEvent interface.
+// https://crbug.com/701480
+// They were removed from the spec in 2012:
 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=12958
 // https://github.com/w3c/uievents/commit/1a2aa02b474fd4feaf43fdced06e6fd7214196a4
 
diff --git a/third_party/WebKit/Source/core/html/media/MediaControls.h b/third_party/WebKit/Source/core/html/media/MediaControls.h
index 1fe48e7b..8fecb61d 100644
--- a/third_party/WebKit/Source/core/html/media/MediaControls.h
+++ b/third_party/WebKit/Source/core/html/media/MediaControls.h
@@ -77,12 +77,6 @@
   virtual void BeginScrubbing() = 0;
   virtual void EndScrubbing() = 0;
   virtual void UpdateCurrentTimeDisplay() = 0;
-  virtual void ToggleTextTrackList() = 0;
-  virtual void ShowTextTrackAtIndex(unsigned) = 0;
-  virtual void DisableShowingTextTracks() = 0;
-  virtual void EnterFullscreen() = 0;
-  virtual void ExitFullscreen() = 0;
-  virtual void ToggleOverflowMenu() = 0;
   virtual bool OverflowMenuVisible() = 0;
   virtual void OnMediaControlsEnabledChange() = 0;
 
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp
index c5fe80b..d5e8d49 100644
--- a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp
+++ b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp
@@ -38,13 +38,9 @@
 #include "core/events/KeyboardEvent.h"
 #include "core/events/MouseEvent.h"
 #include "core/frame/LocalFrame.h"
-#include "core/frame/Settings.h"
 #include "core/frame/UseCounter.h"
-#include "core/html/HTMLAnchorElement.h"
 #include "core/html/HTMLVideoElement.h"
 #include "core/html/TimeRanges.h"
-#include "core/html/media/HTMLMediaElementControlsList.h"
-#include "core/html/media/HTMLMediaSource.h"
 #include "core/html/media/MediaControls.h"
 #include "core/html/shadow/ShadowElementNames.h"
 #include "core/html/track/TextTrackList.h"
@@ -52,7 +48,6 @@
 #include "core/layout/LayoutBoxModelObject.h"
 #include "core/layout/api/LayoutSliderItem.h"
 #include "core/page/ChromeClient.h"
-#include "core/page/Page.h"
 #include "platform/Histogram.h"
 #include "platform/RuntimeEnabledFeatures.h"
 #include "public/platform/Platform.h"
@@ -99,308 +94,8 @@
          type == EventTypeNames::pointermove;
 }
 
-Element* ElementFromCenter(Element& element) {
-  ClientRect* client_rect = element.getBoundingClientRect();
-  int center_x =
-      static_cast<int>((client_rect->left() + client_rect->right()) / 2);
-  int center_y =
-      static_cast<int>((client_rect->top() + client_rect->bottom()) / 2);
-
-  return element.GetDocument().ElementFromPoint(center_x, center_y);
-}
-
 }  // anonymous namespace
 
-MediaControlPlayButtonElement::MediaControlPlayButtonElement(
-    MediaControls& media_controls)
-    : MediaControlInputElement(media_controls, kMediaPlayButton) {}
-
-MediaControlPlayButtonElement* MediaControlPlayButtonElement::Create(
-    MediaControls& media_controls) {
-  MediaControlPlayButtonElement* button =
-      new MediaControlPlayButtonElement(media_controls);
-  button->EnsureUserAgentShadowRoot();
-  button->setType(InputTypeNames::button);
-  button->SetShadowPseudoId(AtomicString("-webkit-media-controls-play-button"));
-  return button;
-}
-
-void MediaControlPlayButtonElement::DefaultEventHandler(Event* event) {
-  if (event->type() == EventTypeNames::click) {
-    if (MediaElement().paused())
-      Platform::Current()->RecordAction(
-          UserMetricsAction("Media.Controls.Play"));
-    else
-      Platform::Current()->RecordAction(
-          UserMetricsAction("Media.Controls.Pause"));
-
-    // Allow play attempts for plain src= media to force a reload in the error
-    // state. This allows potential recovery for transient network and decoder
-    // resource issues.
-    const String& url = MediaElement().currentSrc().GetString();
-    if (MediaElement().error() && !HTMLMediaElement::IsMediaStreamURL(url) &&
-        !HTMLMediaSource::Lookup(url))
-      MediaElement().load();
-
-    MediaElement().TogglePlayState();
-    UpdateDisplayType();
-    event->SetDefaultHandled();
-  }
-  MediaControlInputElement::DefaultEventHandler(event);
-}
-
-void MediaControlPlayButtonElement::UpdateDisplayType() {
-  SetDisplayType(MediaElement().paused() ? kMediaPlayButton
-                                         : kMediaPauseButton);
-  UpdateOverflowString();
-}
-
-WebLocalizedString::Name
-MediaControlPlayButtonElement::GetOverflowStringName() {
-  if (MediaElement().paused())
-    return WebLocalizedString::kOverflowMenuPlay;
-  return WebLocalizedString::kOverflowMenuPause;
-}
-
-// ----------------------------
-
-MediaControlOverlayPlayButtonElement::MediaControlOverlayPlayButtonElement(
-    MediaControls& media_controls)
-    : MediaControlInputElement(media_controls, kMediaOverlayPlayButton) {}
-
-MediaControlOverlayPlayButtonElement*
-MediaControlOverlayPlayButtonElement::Create(MediaControls& media_controls) {
-  MediaControlOverlayPlayButtonElement* button =
-      new MediaControlOverlayPlayButtonElement(media_controls);
-  button->EnsureUserAgentShadowRoot();
-  button->setType(InputTypeNames::button);
-  button->SetShadowPseudoId(
-      AtomicString("-webkit-media-controls-overlay-play-button"));
-  return button;
-}
-
-void MediaControlOverlayPlayButtonElement::DefaultEventHandler(Event* event) {
-  if (event->type() == EventTypeNames::click && MediaElement().paused()) {
-    Platform::Current()->RecordAction(
-        UserMetricsAction("Media.Controls.PlayOverlay"));
-    MediaElement().Play();
-    UpdateDisplayType();
-    event->SetDefaultHandled();
-  }
-}
-
-void MediaControlOverlayPlayButtonElement::UpdateDisplayType() {
-  SetIsWanted(MediaElement().ShouldShowControls() && MediaElement().paused());
-}
-
-bool MediaControlOverlayPlayButtonElement::KeepEventInNode(Event* event) {
-  return IsUserInteractionEvent(event);
-}
-
-// ----------------------------
-
-MediaControlToggleClosedCaptionsButtonElement::
-    MediaControlToggleClosedCaptionsButtonElement(MediaControls& media_controls)
-    : MediaControlInputElement(media_controls, kMediaShowClosedCaptionsButton) {
-}
-
-MediaControlToggleClosedCaptionsButtonElement*
-MediaControlToggleClosedCaptionsButtonElement::Create(
-    MediaControls& media_controls) {
-  MediaControlToggleClosedCaptionsButtonElement* button =
-      new MediaControlToggleClosedCaptionsButtonElement(media_controls);
-  button->EnsureUserAgentShadowRoot();
-  button->setType(InputTypeNames::button);
-  button->SetShadowPseudoId(
-      AtomicString("-webkit-media-controls-toggle-closed-captions-button"));
-  button->SetIsWanted(false);
-  return button;
-}
-
-void MediaControlToggleClosedCaptionsButtonElement::UpdateDisplayType() {
-  bool captions_visible = MediaElement().TextTracksVisible();
-  SetDisplayType(captions_visible ? kMediaHideClosedCaptionsButton
-                                  : kMediaShowClosedCaptionsButton);
-}
-
-void MediaControlToggleClosedCaptionsButtonElement::DefaultEventHandler(
-    Event* event) {
-  if (event->type() == EventTypeNames::click) {
-    if (MediaElement().textTracks()->length() == 1) {
-      // If only one track exists, toggle it on/off
-      if (MediaElement().textTracks()->HasShowingTracks()) {
-        GetMediaControls().DisableShowingTextTracks();
-      } else {
-        GetMediaControls().ShowTextTrackAtIndex(0);
-      }
-    } else {
-      GetMediaControls().ToggleTextTrackList();
-    }
-
-    UpdateDisplayType();
-    event->SetDefaultHandled();
-  }
-
-  MediaControlInputElement::DefaultEventHandler(event);
-}
-
-WebLocalizedString::Name
-MediaControlToggleClosedCaptionsButtonElement::GetOverflowStringName() {
-  return WebLocalizedString::kOverflowMenuCaptions;
-}
-
-// ----------------------------
-
-MediaControlOverflowMenuButtonElement::MediaControlOverflowMenuButtonElement(
-    MediaControls& media_controls)
-    : MediaControlInputElement(media_controls, kMediaOverflowButton) {}
-
-MediaControlOverflowMenuButtonElement*
-MediaControlOverflowMenuButtonElement::Create(MediaControls& media_controls) {
-  MediaControlOverflowMenuButtonElement* button =
-      new MediaControlOverflowMenuButtonElement(media_controls);
-  button->EnsureUserAgentShadowRoot();
-  button->setType(InputTypeNames::button);
-  button->SetShadowPseudoId(
-      AtomicString("-internal-media-controls-overflow-button"));
-  button->SetIsWanted(false);
-  return button;
-}
-
-void MediaControlOverflowMenuButtonElement::DefaultEventHandler(Event* event) {
-  if (event->type() == EventTypeNames::click) {
-    if (GetMediaControls().OverflowMenuVisible())
-      Platform::Current()->RecordAction(
-          UserMetricsAction("Media.Controls.OverflowClose"));
-    else
-      Platform::Current()->RecordAction(
-          UserMetricsAction("Media.Controls.OverflowOpen"));
-
-    GetMediaControls().ToggleOverflowMenu();
-    event->SetDefaultHandled();
-  }
-
-  MediaControlInputElement::DefaultEventHandler(event);
-}
-
-// ----------------------------
-MediaControlDownloadButtonElement::MediaControlDownloadButtonElement(
-    MediaControls& media_controls)
-    : MediaControlInputElement(media_controls, kMediaDownloadButton) {}
-
-MediaControlDownloadButtonElement* MediaControlDownloadButtonElement::Create(
-    MediaControls& media_controls) {
-  MediaControlDownloadButtonElement* button =
-      new MediaControlDownloadButtonElement(media_controls);
-  button->EnsureUserAgentShadowRoot();
-  button->setType(InputTypeNames::button);
-  button->SetShadowPseudoId(
-      AtomicString("-internal-media-controls-download-button"));
-  button->SetIsWanted(false);
-  return button;
-}
-
-WebLocalizedString::Name
-MediaControlDownloadButtonElement::GetOverflowStringName() {
-  return WebLocalizedString::kOverflowMenuDownload;
-}
-
-bool MediaControlDownloadButtonElement::ShouldDisplayDownloadButton() {
-  const KURL& url = MediaElement().currentSrc();
-
-  // Check page settings to see if download is disabled.
-  if (GetDocument().GetPage() &&
-      GetDocument().GetPage()->GetSettings().GetHideDownloadUI())
-    return false;
-
-  // URLs that lead to nowhere are ignored.
-  if (url.IsNull() || url.IsEmpty())
-    return false;
-
-  // If we have no source, we can't download.
-  if (MediaElement().getNetworkState() == HTMLMediaElement::kNetworkEmpty ||
-      MediaElement().getNetworkState() == HTMLMediaElement::kNetworkNoSource) {
-    return false;
-  }
-
-  // Local files and blobs (including MSE) should not have a download button.
-  if (url.IsLocalFile() || url.ProtocolIs("blob"))
-    return false;
-
-  // MediaStream can't be downloaded.
-  if (HTMLMediaElement::IsMediaStreamURL(url.GetString()))
-    return false;
-
-  // MediaSource can't be downloaded.
-  if (HTMLMediaSource::Lookup(url))
-    return false;
-
-  // HLS stream shouldn't have a download button.
-  if (HTMLMediaElement::IsHLSURL(url))
-    return false;
-
-  // Infinite streams don't have a clear end at which to finish the download
-  // (would require adding UI to prompt for the duration to download).
-  if (MediaElement().duration() == std::numeric_limits<double>::infinity())
-    return false;
-
-  // The attribute disables the download button.
-  if (MediaElement().ControlsListInternal()->ShouldHideDownload()) {
-    UseCounter::Count(MediaElement().GetDocument(),
-                      UseCounter::kHTMLMediaElementControlsListNoDownload);
-    return false;
-  }
-
-  return true;
-}
-
-void MediaControlDownloadButtonElement::SetIsWanted(bool wanted) {
-  MediaControlElement::SetIsWanted(wanted);
-
-  if (!IsWanted())
-    return;
-
-  DCHECK(IsWanted());
-  if (!show_use_counted_) {
-    show_use_counted_ = true;
-    RecordMetrics(DownloadActionMetrics::kShown);
-  }
-}
-
-void MediaControlDownloadButtonElement::DefaultEventHandler(Event* event) {
-  const KURL& url = MediaElement().currentSrc();
-  if (event->type() == EventTypeNames::click &&
-      !(url.IsNull() || url.IsEmpty())) {
-    Platform::Current()->RecordAction(
-        UserMetricsAction("Media.Controls.Download"));
-    if (!click_use_counted_) {
-      click_use_counted_ = true;
-      RecordMetrics(DownloadActionMetrics::kClicked);
-    }
-    if (!anchor_) {
-      HTMLAnchorElement* anchor = HTMLAnchorElement::Create(GetDocument());
-      anchor->setAttribute(HTMLNames::downloadAttr, "");
-      anchor_ = anchor;
-    }
-    anchor_->SetURL(url);
-    anchor_->DispatchSimulatedClick(event);
-  }
-  MediaControlInputElement::DefaultEventHandler(event);
-}
-
-DEFINE_TRACE(MediaControlDownloadButtonElement) {
-  visitor->Trace(anchor_);
-  MediaControlInputElement::Trace(visitor);
-}
-
-void MediaControlDownloadButtonElement::RecordMetrics(
-    DownloadActionMetrics metric) {
-  DEFINE_STATIC_LOCAL(EnumerationHistogram, download_action_histogram,
-                      ("Media.Controls.Download",
-                       static_cast<int>(DownloadActionMetrics::kCount)));
-  download_action_histogram.Count(static_cast<int>(metric));
-}
-
 // ----------------------------
 
 MediaControlTimelineElement::MediaControlTimelineElement(
@@ -593,162 +288,4 @@
   return IsUserInteractionEventForSlider(event, GetLayoutObject());
 }
 
-// ----------------------------
-
-MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(
-    MediaControls& media_controls)
-    : MediaControlInputElement(media_controls, kMediaEnterFullscreenButton) {}
-
-MediaControlFullscreenButtonElement*
-MediaControlFullscreenButtonElement::Create(MediaControls& media_controls) {
-  MediaControlFullscreenButtonElement* button =
-      new MediaControlFullscreenButtonElement(media_controls);
-  button->EnsureUserAgentShadowRoot();
-  button->setType(InputTypeNames::button);
-  button->SetShadowPseudoId(
-      AtomicString("-webkit-media-controls-fullscreen-button"));
-  button->SetIsFullscreen(media_controls.MediaElement().IsFullscreen());
-  button->SetIsWanted(false);
-  return button;
-}
-
-void MediaControlFullscreenButtonElement::DefaultEventHandler(Event* event) {
-  if (event->type() == EventTypeNames::click) {
-    bool is_embedded_experience_enabled =
-        GetDocument().GetSettings() &&
-        GetDocument().GetSettings()->GetEmbeddedMediaExperienceEnabled();
-    if (MediaElement().IsFullscreen()) {
-      Platform::Current()->RecordAction(
-          UserMetricsAction("Media.Controls.ExitFullscreen"));
-      if (is_embedded_experience_enabled) {
-        Platform::Current()->RecordAction(UserMetricsAction(
-            "Media.Controls.ExitFullscreen.EmbeddedExperience"));
-      }
-      GetMediaControls().ExitFullscreen();
-    } else {
-      Platform::Current()->RecordAction(
-          UserMetricsAction("Media.Controls.EnterFullscreen"));
-      if (is_embedded_experience_enabled) {
-        Platform::Current()->RecordAction(UserMetricsAction(
-            "Media.Controls.EnterFullscreen.EmbeddedExperience"));
-      }
-      GetMediaControls().EnterFullscreen();
-    }
-    event->SetDefaultHandled();
-  }
-  MediaControlInputElement::DefaultEventHandler(event);
-}
-
-void MediaControlFullscreenButtonElement::SetIsFullscreen(bool is_fullscreen) {
-  SetDisplayType(is_fullscreen ? kMediaExitFullscreenButton
-                               : kMediaEnterFullscreenButton);
-}
-
-WebLocalizedString::Name
-MediaControlFullscreenButtonElement::GetOverflowStringName() {
-  if (MediaElement().IsFullscreen())
-    return WebLocalizedString::kOverflowMenuExitFullscreen;
-  return WebLocalizedString::kOverflowMenuEnterFullscreen;
-}
-
-// ----------------------------
-
-MediaControlCastButtonElement::MediaControlCastButtonElement(
-    MediaControls& media_controls,
-    bool is_overlay_button)
-    : MediaControlInputElement(media_controls, kMediaCastOnButton),
-      is_overlay_button_(is_overlay_button) {
-  if (is_overlay_button_)
-    RecordMetrics(CastOverlayMetrics::kCreated);
-  SetIsPlayingRemotely(false);
-}
-
-MediaControlCastButtonElement* MediaControlCastButtonElement::Create(
-    MediaControls& media_controls,
-    bool is_overlay_button) {
-  MediaControlCastButtonElement* button =
-      new MediaControlCastButtonElement(media_controls, is_overlay_button);
-  button->EnsureUserAgentShadowRoot();
-  button->SetShadowPseudoId(is_overlay_button
-                                ? "-internal-media-controls-overlay-cast-button"
-                                : "-internal-media-controls-cast-button");
-  button->setType(InputTypeNames::button);
-  return button;
-}
-
-void MediaControlCastButtonElement::DefaultEventHandler(Event* event) {
-  if (event->type() == EventTypeNames::click) {
-    if (is_overlay_button_)
-      Platform::Current()->RecordAction(
-          UserMetricsAction("Media.Controls.CastOverlay"));
-    else
-      Platform::Current()->RecordAction(
-          UserMetricsAction("Media.Controls.Cast"));
-
-    if (is_overlay_button_ && !click_use_counted_) {
-      click_use_counted_ = true;
-      RecordMetrics(CastOverlayMetrics::kClicked);
-    }
-    if (MediaElement().IsPlayingRemotely()) {
-      MediaElement().RequestRemotePlaybackControl();
-    } else {
-      MediaElement().RequestRemotePlayback();
-    }
-  }
-  MediaControlInputElement::DefaultEventHandler(event);
-}
-
-void MediaControlCastButtonElement::SetIsPlayingRemotely(
-    bool is_playing_remotely) {
-  if (is_playing_remotely) {
-    if (is_overlay_button_) {
-      SetDisplayType(kMediaOverlayCastOnButton);
-    } else {
-      SetDisplayType(kMediaCastOnButton);
-    }
-  } else {
-    if (is_overlay_button_) {
-      SetDisplayType(kMediaOverlayCastOffButton);
-    } else {
-      SetDisplayType(kMediaCastOffButton);
-    }
-  }
-  UpdateOverflowString();
-}
-
-WebLocalizedString::Name
-MediaControlCastButtonElement::GetOverflowStringName() {
-  if (MediaElement().IsPlayingRemotely())
-    return WebLocalizedString::kOverflowMenuStopCast;
-  return WebLocalizedString::kOverflowMenuCast;
-}
-
-void MediaControlCastButtonElement::TryShowOverlay() {
-  DCHECK(is_overlay_button_);
-
-  SetIsWanted(true);
-  if (ElementFromCenter(*this) != &MediaElement()) {
-    SetIsWanted(false);
-    return;
-  }
-
-  DCHECK(IsWanted());
-  if (!show_use_counted_) {
-    show_use_counted_ = true;
-    RecordMetrics(CastOverlayMetrics::kShown);
-  }
-}
-
-bool MediaControlCastButtonElement::KeepEventInNode(Event* event) {
-  return IsUserInteractionEvent(event);
-}
-
-void MediaControlCastButtonElement::RecordMetrics(CastOverlayMetrics metric) {
-  DCHECK(is_overlay_button_);
-  DEFINE_STATIC_LOCAL(
-      EnumerationHistogram, overlay_histogram,
-      ("Cast.Sender.Overlay", static_cast<int>(CastOverlayMetrics::kCount)));
-  overlay_histogram.Count(static_cast<int>(metric));
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h
index df74742e..de59f4b 100644
--- a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h
+++ b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h
@@ -32,129 +32,9 @@
 
 #include "core/html/shadow/MediaControlElementTypes.h"
 #include "core/html/shadow/MediaControlTimelineMetrics.h"
-#include "public/platform/WebLocalizedString.h"
 
 namespace blink {
 
-// ----------------------------
-
-class CORE_EXPORT MediaControlPlayButtonElement final
-    : public MediaControlInputElement {
- public:
-  static MediaControlPlayButtonElement* Create(MediaControls&);
-
-  bool WillRespondToMouseClickEvents() override { return true; }
-  void UpdateDisplayType() override;
-
-  WebLocalizedString::Name GetOverflowStringName() override;
-
-  bool HasOverflowButton() override { return true; }
-
- private:
-  explicit MediaControlPlayButtonElement(MediaControls&);
-
-  void DefaultEventHandler(Event*) override;
-};
-
-// ----------------------------
-
-class CORE_EXPORT MediaControlOverlayPlayButtonElement final
-    : public MediaControlInputElement {
- public:
-  static MediaControlOverlayPlayButtonElement* Create(MediaControls&);
-
-  void UpdateDisplayType() override;
-
- private:
-  explicit MediaControlOverlayPlayButtonElement(MediaControls&);
-
-  void DefaultEventHandler(Event*) override;
-  bool KeepEventInNode(Event*) override;
-};
-
-// ----------------------------
-
-class CORE_EXPORT MediaControlToggleClosedCaptionsButtonElement final
-    : public MediaControlInputElement {
- public:
-  static MediaControlToggleClosedCaptionsButtonElement* Create(MediaControls&);
-
-  bool WillRespondToMouseClickEvents() override { return true; }
-
-  void UpdateDisplayType() override;
-
-  WebLocalizedString::Name GetOverflowStringName() override;
-
-  bool HasOverflowButton() override { return true; }
-
- private:
-  explicit MediaControlToggleClosedCaptionsButtonElement(MediaControls&);
-
-  void DefaultEventHandler(Event*) override;
-};
-
-// ----------------------------
-
-// Represents the overflow menu which is displayed when the width of the media
-// player is small enough that at least two buttons are no longer visible.
-class CORE_EXPORT MediaControlOverflowMenuButtonElement final
-    : public MediaControlInputElement {
- public:
-  static MediaControlOverflowMenuButtonElement* Create(MediaControls&);
-
-  // The overflow button should respond to mouse clicks since we want a click
-  // to open up the menu.
-  bool WillRespondToMouseClickEvents() override { return true; }
-
- private:
-  explicit MediaControlOverflowMenuButtonElement(MediaControls&);
-
-  void DefaultEventHandler(Event*) override;
-};
-
-// ----------------------------
-// Represents a button that allows users to download media if the file is
-// downloadable.
-class CORE_EXPORT MediaControlDownloadButtonElement final
-    : public MediaControlInputElement {
- public:
-  static MediaControlDownloadButtonElement* Create(MediaControls&);
-
-  WebLocalizedString::Name GetOverflowStringName() override;
-
-  bool HasOverflowButton() override { return true; }
-
-  // Returns true if the download button should be shown. We should
-  // show the button for only non-MSE, non-EME, and non-MediaStream content.
-  bool ShouldDisplayDownloadButton();
-
-  void SetIsWanted(bool) override;
-
-  DECLARE_VIRTUAL_TRACE();
-
- private:
-  explicit MediaControlDownloadButtonElement(MediaControls&);
-
-  void DefaultEventHandler(Event*) override;
-
-  // Points to an anchor element that contains the URL of the media file.
-  Member<HTMLAnchorElement> anchor_;
-
-  // This is used for UMA histogram (Media.Controls.Download). New values should
-  // be appended only and must be added before |Count|.
-  enum class DownloadActionMetrics {
-    kShown = 0,
-    kClicked,
-    kCount  // Keep last.
-  };
-  void RecordMetrics(DownloadActionMetrics);
-
-  // UMA related boolean. They are used to prevent counting something twice
-  // for the same media element.
-  bool click_use_counted_ = false;
-  bool show_use_counted_ = false;
-};
-
 class CORE_EXPORT MediaControlTimelineElement final
     : public MediaControlInputElement {
  public:
@@ -184,72 +64,6 @@
 
 // ----------------------------
 
-class CORE_EXPORT MediaControlFullscreenButtonElement final
-    : public MediaControlInputElement {
- public:
-  static MediaControlFullscreenButtonElement* Create(MediaControls&);
-
-  bool WillRespondToMouseClickEvents() override { return true; }
-
-  void SetIsFullscreen(bool);
-
-  WebLocalizedString::Name GetOverflowStringName() override;
-
-  bool HasOverflowButton() override { return true; }
-
- private:
-  explicit MediaControlFullscreenButtonElement(MediaControls&);
-
-  void DefaultEventHandler(Event*) override;
-};
-
-// ----------------------------
-
-class CORE_EXPORT MediaControlCastButtonElement final
-    : public MediaControlInputElement {
- public:
-  static MediaControlCastButtonElement* Create(MediaControls&,
-                                               bool is_overlay_button);
-
-  bool WillRespondToMouseClickEvents() override { return true; }
-
-  void SetIsPlayingRemotely(bool);
-
-  WebLocalizedString::Name GetOverflowStringName() override;
-
-  bool HasOverflowButton() override { return true; }
-
-  // This will show a cast button if it is not covered by another element.
-  // This MUST be called for cast button elements that are overlay elements.
-  void TryShowOverlay();
-
- private:
-  explicit MediaControlCastButtonElement(MediaControls&,
-                                         bool is_overlay_button);
-
-  void DefaultEventHandler(Event*) override;
-  bool KeepEventInNode(Event*) override;
-
-  bool is_overlay_button_;
-
-  // This is used for UMA histogram (Cast.Sender.Overlay). New values should
-  // be appended only and must be added before |Count|.
-  enum class CastOverlayMetrics {
-    kCreated = 0,
-    kShown,
-    kClicked,
-    kCount  // Keep last.
-  };
-  void RecordMetrics(CastOverlayMetrics);
-
-  // UMA related boolean. They are used to prevent counting something twice
-  // for the same media element.
-  bool click_use_counted_ = false;
-  bool show_use_counted_ = false;
-};
-
-// ----------------------------
-
 class CORE_EXPORT MediaControlVolumeSliderElement final
     : public MediaControlInputElement {
  public:
diff --git a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
index 23e8ea41..ce8c924 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
@@ -91,7 +91,6 @@
 static const char kCacheDisabled[] = "cacheDisabled";
 static const char kBypassServiceWorker[] = "bypassServiceWorker";
 static const char kUserAgentOverride[] = "userAgentOverride";
-static const char kMonitoringXHR[] = "monitoringXHR";
 static const char kBlockedURLs[] = "blockedURLs";
 static const char kTotalBufferSize[] = "totalBufferSize";
 static const char kResourceBufferSize[] = "resourceBufferSize";
@@ -976,15 +975,6 @@
       known_request_id_map_.Find(client);
   if (it == known_request_id_map_.end())
     return;
-
-  if (state_->booleanProperty(NetworkAgentState::kMonitoringXHR, false)) {
-    String message =
-        (success ? "XHR finished loading: " : "XHR failed loading: ") + method +
-        " \"" + url + "\".";
-    ConsoleMessage* console_message = ConsoleMessage::CreateForRequest(
-        kNetworkMessageSource, kInfoMessageLevel, message, url, it->value);
-    inspected_frames_->Root()->Console().AddMessageToStorage(console_message);
-  }
   known_request_id_map_.erase(client);
 }
 
@@ -1006,13 +996,6 @@
       known_request_id_map_.Find(client);
   if (it == known_request_id_map_.end())
     return;
-
-  if (state_->booleanProperty(NetworkAgentState::kMonitoringXHR, false)) {
-    String message = "Fetch complete: " + method + " \"" + url + "\".";
-    ConsoleMessage* console_message = ConsoleMessage::CreateForRequest(
-        kNetworkMessageSource, kInfoMessageLevel, message, url, it->value);
-    inspected_frames_->Root()->Console().AddMessageToStorage(console_message);
-  }
   known_request_id_map_.erase(client);
 }
 
@@ -1391,11 +1374,6 @@
   return Response::OK();
 }
 
-Response InspectorNetworkAgent::setMonitoringXHREnabled(bool enabled) {
-  state_->setBoolean(NetworkAgentState::kMonitoringXHR, enabled);
-  return Response::OK();
-}
-
 Response InspectorNetworkAgent::canClearBrowserCache(bool* result) {
   *result = true;
   return Response::OK();
diff --git a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h
index 63cd0216..33c7cff 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h
@@ -205,7 +205,6 @@
   protocol::Response setBlockedURLs(
       std::unique_ptr<protocol::Array<String>> urls) override;
   protocol::Response replayXHR(const String& request_id) override;
-  protocol::Response setMonitoringXHREnabled(bool) override;
   protocol::Response canClearBrowserCache(bool* result) override;
   protocol::Response canClearBrowserCookies(bool* result) override;
   protocol::Response emulateNetworkConditions(
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json
index c46593db..bf78f2e 100644
--- a/third_party/WebKit/Source/core/inspector/browser_protocol.json
+++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -1247,14 +1247,6 @@
                 "experimental": true
             },
             {
-                "name": "setMonitoringXHREnabled",
-                "parameters": [
-                    { "name": "enabled", "type": "boolean", "description": "Monitoring enabled state." }
-                ],
-                "description": "Toggles monitoring of XMLHttpRequest. If <code>true</code>, console will receive messages upon each XHR issued.",
-                "experimental": true
-            },
-            {
                 "name": "canClearBrowserCache",
                 "description": "Tells whether clearing browser cache is supported.",
                 "returns": [
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc
index d4e51241..dd3757ec 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc
@@ -142,7 +142,7 @@
 
   if (!layout_opp_iter_) {
     layout_opp_iter_ = WTF::MakeUnique<NGLayoutOpportunityIterator>(
-        this, AvailableSize(), iter_offset);
+        Exclusions().get(), AvailableSize(), iter_offset);
   }
   return layout_opp_iter_.get();
 }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_test.cc
index bd57c50d..a3217b6 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_test.cc
@@ -36,7 +36,8 @@
   RefPtr<NGConstraintSpace> space =
       ConstructConstraintSpace(kHorizontalTopBottom, TextDirection::kLtr, size);
 
-  NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize());
+  NGLayoutOpportunityIterator iterator(
+      space->Exclusions().get(), space->AvailableSize(), NGLogicalOffset());
   // 600x400 at (0,0)
   NGLayoutOpportunity opp1 = {{}, {LayoutUnit(600), LayoutUnit(400)}};
   EXPECT_EQ(opp1, iterator.Next());
@@ -56,7 +57,8 @@
   exclusion.rect.offset = {LayoutUnit(500), LayoutUnit()};
   space->AddExclusion(exclusion);
 
-  NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize());
+  NGLayoutOpportunityIterator iterator(
+      space->Exclusions().get(), space->AvailableSize(), NGLogicalOffset());
 
   // First opportunity should be to the left of the exclusion: 500x400 at (0,0)
   NGLayoutOpportunity opp1 = {{}, {LayoutUnit(500), LayoutUnit(400)}};
@@ -81,7 +83,8 @@
   exclusion.rect.size = {LayoutUnit(100), LayoutUnit(100)};
   space->AddExclusion(exclusion);
 
-  NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize());
+  NGLayoutOpportunityIterator iterator(
+      space->Exclusions().get(), space->AvailableSize(), NGLogicalOffset());
   // First opportunity should be to the right of the exclusion:
   // 500x400 at (100, 0)
   NGLayoutOpportunity opp1 = {{LayoutUnit(100), LayoutUnit()},
@@ -135,7 +138,8 @@
   exclusion2.rect.offset = {LayoutUnit(500), LayoutUnit(350)};
   space->AddExclusion(exclusion2);
 
-  NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize());
+  NGLayoutOpportunityIterator iterator(
+      space->Exclusions().get(), space->AvailableSize(), NGLogicalOffset());
   NGLogicalOffset start_point1;
   // 600x200 at (0,0)
   NGLayoutOpportunity opp1 = {start_point1, {LayoutUnit(600), LayoutUnit(200)}};
@@ -168,74 +172,6 @@
   EXPECT_EQ(NGLayoutOpportunity(), iterator.Next());
 }
 
-// This test is the same as LayoutOpportunitiesTwoInMiddle with the only
-// difference that NGLayoutOpportunityIterator takes 2 additional arguments:
-// - origin_point that changes the iterator to return Layout Opportunities that
-// lay after the origin point.
-// - leader_point that together with origin_point creates a temporary exclusion
-//
-// Expected:
-//   Layout opportunity iterator generates the next opportunities:
-//   - 1st Start Point (0, 200): 350x150, 250x400
-//   - 3rd Start Point (550, 200): 50x400
-//   - 4th Start Point (0, 300): 600x50, 500x300
-//   - 5th Start Point (0, 400): 600x200
-//   All other opportunities that are located before the origin point should be
-//   filtered out.
-TEST(NGConstraintSpaceTest, LayoutOpportunitiesTwoInMiddleWithOriginAndLeader) {
-  NGLogicalSize size;
-  size.inline_size = LayoutUnit(600);
-  size.block_size = LayoutUnit(400);
-  RefPtr<NGConstraintSpace> space =
-      ConstructConstraintSpace(kHorizontalTopBottom, TextDirection::kLtr, size);
-  // Add exclusions
-  NGExclusion exclusion1;
-  exclusion1.rect.size = {LayoutUnit(100), LayoutUnit(100)};
-  exclusion1.rect.offset = {LayoutUnit(150), LayoutUnit(200)};
-  space->AddExclusion(exclusion1);
-  NGExclusion exclusion2;
-  exclusion2.rect.size = {LayoutUnit(50), LayoutUnit(50)};
-  exclusion2.rect.offset = {LayoutUnit(500), LayoutUnit(350)};
-  space->AddExclusion(exclusion2);
-
-  const NGLogicalOffset origin_point = {LayoutUnit(), LayoutUnit(200)};
-  const NGLogicalOffset leader_point = {LayoutUnit(250), LayoutUnit(300)};
-  NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize(),
-                                       origin_point, leader_point);
-
-  NGLogicalOffset start_point1 = {LayoutUnit(250), LayoutUnit(200)};
-  // 350x150 at (250,200)
-  NGLayoutOpportunity opp1 = {start_point1, {LayoutUnit(350), LayoutUnit(150)}};
-  EXPECT_EQ(opp1, iterator.Next());
-  // 250x400 at (250,200)
-  NGLayoutOpportunity opp2 = {start_point1, {LayoutUnit(250), LayoutUnit(400)}};
-  EXPECT_EQ(opp2, iterator.Next());
-
-  NGLogicalOffset start_point2 = {LayoutUnit(550), LayoutUnit(200)};
-  // 50x400 at (550,200)
-  NGLayoutOpportunity opp3 = {start_point2, {LayoutUnit(50), LayoutUnit(400)}};
-  EXPECT_EQ(opp3, iterator.Next());
-
-  NGLogicalOffset start_point3 = {LayoutUnit(), LayoutUnit(300)};
-  // 600x50 at (0,300)
-  NGLayoutOpportunity opp4 = {start_point3, {LayoutUnit(600), LayoutUnit(50)}};
-  EXPECT_EQ(opp4, iterator.Next());
-  // 500x300 at (0,300)
-  NGLayoutOpportunity opp5 = {start_point3, {LayoutUnit(500), LayoutUnit(300)}};
-  EXPECT_EQ(opp5, iterator.Next());
-
-  // 4th Start Point
-  NGLogicalOffset start_point4 = {LayoutUnit(), LayoutUnit(400)};
-  // 600x200 at (0,400)
-  NGLayoutOpportunity opp6 = {start_point4, {LayoutUnit(600), LayoutUnit(200)}};
-  EXPECT_EQ(opp6, iterator.Next());
-
-  // TODO(glebl): The opportunity below should not be generated.
-  EXPECT_EQ("350x200 at (250,400)", iterator.Next().ToString());
-
-  EXPECT_EQ(NGLayoutOpportunity(), iterator.Next());
-}
-
 // Verifies that Layout Opportunity iterator ignores the exclusion that is not
 // within constraint space.
 //
@@ -260,7 +196,8 @@
   exclusion.rect.offset = {LayoutUnit(), LayoutUnit(150)};
   space->AddExclusion(exclusion);
 
-  NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize());
+  NGLayoutOpportunityIterator iterator(
+      space->Exclusions().get(), space->AvailableSize(), NGLogicalOffset());
   // 600x100 at (0,0)
   NGLayoutOpportunity opp = {{}, size};
   EXPECT_EQ(opp, iterator.Next());
@@ -288,8 +225,8 @@
   big_left.type = NGExclusion::kFloatLeft;
   space->AddExclusion(big_left);
 
-  NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize(),
-                                       bfc_offset);
+  NGLayoutOpportunityIterator iterator(space->Exclusions().get(),
+                                       space->AvailableSize(), bfc_offset);
 
   NGLogicalOffset start_point1 = bfc_offset;
   start_point1.inline_offset +=
@@ -334,8 +271,8 @@
   big_right.type = NGExclusion::kFloatRight;
   space->AddExclusion(big_right);
 
-  NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize(),
-                                       bfc_offset);
+  NGLayoutOpportunityIterator iterator(space->Exclusions().get(),
+                                       space->AvailableSize(), bfc_offset);
 
   NGLogicalOffset start_point1 = bfc_offset;
   // 170x200 at (8, 8)
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc b/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc
index d1519fd..2f77bb3 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc
@@ -46,8 +46,9 @@
   NGLogicalOffset adjusted_origin_point =
       AdjustToTopEdgeAlignmentRule(*space, floating_object->origin_offset);
 
-  NGLayoutOpportunityIterator opportunity_iter(
-      space, floating_object->available_size, adjusted_origin_point);
+  NGLayoutOpportunityIterator opportunity_iter(space->Exclusions().get(),
+                                               floating_object->available_size,
+                                               adjusted_origin_point);
   NGLayoutOpportunity opportunity;
   NGLayoutOpportunity opportunity_candidate = opportunity_iter.Next();
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc b/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc
index bb84c83e..de08081 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc
@@ -53,8 +53,8 @@
   CollectAllOpportunities(node->right.get(), opportunities);
 }
 
-// Creates layout opportunity from the provided space and the origin point.
-NGLayoutOpportunity CreateLayoutOpportunityFromConstraintSpace(
+// Creates layout opportunity from the provided size and the origin point.
+NGLayoutOpportunity CreateInitialOpportunity(
     const NGLogicalSize& size,
     const NGLogicalOffset& origin_point) {
   NGLayoutOpportunity opportunity;
@@ -257,46 +257,23 @@
   // TOP and LEFT are the same -> Sort by width
   return rhs.size.inline_size < lhs.size.inline_size;
 }
-
-NGExclusion ToLeaderExclusion(const NGLogicalOffset& origin_point,
-                              const NGLogicalOffset& leader_point) {
-  LayoutUnit inline_size =
-      leader_point.inline_offset - origin_point.inline_offset;
-  LayoutUnit block_size = leader_point.block_offset - origin_point.block_offset;
-
-  NGExclusion leader_exclusion;
-  leader_exclusion.rect.offset = origin_point;
-  leader_exclusion.rect.size = {inline_size, block_size};
-  return leader_exclusion;
-}
-
 }  // namespace
 
 NGLayoutOpportunityIterator::NGLayoutOpportunityIterator(
-    const NGConstraintSpace* space,
+    const NGExclusions* exclusions,
     const NGLogicalSize& available_size,
-    const WTF::Optional<NGLogicalOffset>& opt_offset,
-    const WTF::Optional<NGLogicalOffset>& opt_leader_point)
-    : constraint_space_(space),
-      offset_(opt_offset ? opt_offset.value() : space->BfcOffset()) {
-  // TODO(chrome-layout-team): Combine exclusions that shadow each other.
-  auto& exclusions = constraint_space_->Exclusions();
+    const NGLogicalOffset& offset)
+    : offset_(offset) {
+  DCHECK(exclusions);
   DCHECK(std::is_sorted(exclusions->storage.begin(), exclusions->storage.end(),
                         &CompareNGExclusionsByTopAsc))
       << "Exclusions are expected to be sorted by TOP";
 
   NGLayoutOpportunity initial_opportunity =
-      CreateLayoutOpportunityFromConstraintSpace(available_size, Offset());
+      CreateInitialOpportunity(available_size, Offset());
   opportunity_tree_root_.reset(
       new NGLayoutOpportunityTreeNode(initial_opportunity));
 
-  if (opt_leader_point) {
-    const NGExclusion leader_exclusion =
-        ToLeaderExclusion(Offset(), opt_leader_point.value());
-    InsertExclusion(MutableOpportunityTreeRoot(), &leader_exclusion,
-                    opportunities_);
-  }
-
   for (const auto& exclusion : exclusions->storage) {
     InsertExclusion(MutableOpportunityTreeRoot(), exclusion.get(),
                     opportunities_);
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.h b/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.h
index 4226937..24e8941 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.h
@@ -6,14 +6,13 @@
 #define NGLayoutOpportunityIterator_h
 
 #include "core/CoreExport.h"
+#include "core/layout/ng/ng_exclusion.h"
 #include "core/layout/ng/ng_layout_opportunity_tree_node.h"
-#include "platform/wtf/Optional.h"
 #include "platform/wtf/Vector.h"
 #include "platform/wtf/text/StringBuilder.h"
 
 namespace blink {
 
-class NGConstraintSpace;
 typedef NGLogicalRect NGLayoutOpportunity;
 typedef Vector<NGLayoutOpportunity> NGLayoutOpportunities;
 
@@ -21,19 +20,15 @@
  public:
   // Default constructor.
   //
-  // @param space Constraint space with exclusions for which this iterator needs
-  //              to generate layout opportunities.
-  // @param opt_offset Optional offset parameter that is used as a
-  //                   default start point for layout opportunities.
-  // @param opt_leader_point Optional 'leader' parameter that is used to specify
-  //                         the ending point of temporary excluded rectangle
-  //                         which starts from 'origin'. This rectangle may
-  //                         represent a text fragment for example.
-  NGLayoutOpportunityIterator(
-      const NGConstraintSpace* space,
-      const NGLogicalSize& available_size,
-      const WTF::Optional<NGLogicalOffset>& opt_offset = WTF::kNullopt,
-      const WTF::Optional<NGLogicalOffset>& opt_leader_point = WTF::kNullopt);
+  // @param exclusions List of exclusions that should be avoided by this
+  //                   iterator while generating layout opportunities.
+  // @param available_size Available size that represents a rectangle where this
+  //                       iterator searches layout opportunities.
+  // @param offset Offset used as a default starting point for layout
+  //               opportunities.
+  NGLayoutOpportunityIterator(const NGExclusions* exclusions,
+                              const NGLogicalSize& available_size,
+                              const NGLogicalOffset& offset);
 
   // Gets the next Layout Opportunity or empty one if the search is exhausted.
   // TODO(chrome-layout-team): Refactor with using C++ <iterator> library.
@@ -60,8 +55,6 @@
     return opportunity_tree_root_.get();
   }
 
-  const NGConstraintSpace* constraint_space_;
-
   NGLayoutOpportunities opportunities_;
   NGLayoutOpportunities::const_iterator opportunity_iter_;
   std::unique_ptr<NGLayoutOpportunityTreeNode> opportunity_tree_root_;
diff --git a/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.idl b/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.idl
index c4fb17b9..cbcef45 100644
--- a/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.idl
+++ b/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.idl
@@ -46,9 +46,9 @@
     [MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber kernelUnitLengthX;
     [MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber kernelUnitLengthY;
 
-    // TODO(foolip): The following was part of SVG 1.1:
+    // TODO(foolip): The following was part of SVG 1.1. https://crbug.com/695977
     // http://www.w3.org/TR/SVG11/filters.html#InterfaceSVGFEConvolveMatrixElement
-    // https://www.w3.org/Bugs/Public/show_bug.cgi?id=28703
+    // https://github.com/w3c/fxtf-drafts/issues/114
     [Measure] readonly attribute SVGAnimatedBoolean preserveAlpha;
 };
 
diff --git a/third_party/WebKit/Source/core/svg/SVGGraphicsElement.idl b/third_party/WebKit/Source/core/svg/SVGGraphicsElement.idl
index 508de310..6b28612 100644
--- a/third_party/WebKit/Source/core/svg/SVGGraphicsElement.idl
+++ b/third_party/WebKit/Source/core/svg/SVGGraphicsElement.idl
@@ -37,8 +37,8 @@
     [ImplementedAs=getCTMFromJavascript] SVGMatrix getCTM();
     [ImplementedAs=getScreenCTMFromJavascript] SVGMatrix getScreenCTM();
 
-    // The following two properties existed on SVGLocatable in SVG
-    // 1.1, but was removed in SVG2.
+    // TODO(foolip): The following two properties existed on SVGLocatable in SVG
+    // 1.1, but were removed in SVG2. https://crbug.com/695981
     // https://www.w3.org/TR/SVG11/types.html#InterfaceSVGLocatable
     [MeasureAs=SVGLocatableNearestViewportElement] readonly attribute SVGElement nearestViewportElement;
     [MeasureAs=SVGLocatableFarthestViewportElement] readonly attribute SVGElement farthestViewportElement;
diff --git a/third_party/WebKit/Source/core/svg/SVGMaskElement.idl b/third_party/WebKit/Source/core/svg/SVGMaskElement.idl
index f787110c..7af69009 100644
--- a/third_party/WebKit/Source/core/svg/SVGMaskElement.idl
+++ b/third_party/WebKit/Source/core/svg/SVGMaskElement.idl
@@ -36,5 +36,5 @@
 
 // SVGMaskElement implements SVGUnitTypes;
 
-// TODO(foolip): The following is not part of any spec:
+// TODO(foolip): The following is not part of any spec. https://crbug.com/701893
 SVGMaskElement implements SVGTests;
diff --git a/third_party/WebKit/Source/core/svg/SVGMatrix.idl b/third_party/WebKit/Source/core/svg/SVGMatrix.idl
index afdc651..30518786 100644
--- a/third_party/WebKit/Source/core/svg/SVGMatrix.idl
+++ b/third_party/WebKit/Source/core/svg/SVGMatrix.idl
@@ -23,6 +23,7 @@
 // http://www.w3.org/TR/SVG11/coords.html#InterfaceSVGMatrix
 
 // TODO(foolip): SVGMatrix is gone from SVG 2, replaced by DOMMatrix.
+// https://crbug.com/709001
 [
     DependentLifetime,
     ImplementedAs=SVGMatrixTearOff,
diff --git a/third_party/WebKit/Source/core/svg/SVGPatternElement.idl b/third_party/WebKit/Source/core/svg/SVGPatternElement.idl
index f8329d2..fba4f7b 100644
--- a/third_party/WebKit/Source/core/svg/SVGPatternElement.idl
+++ b/third_party/WebKit/Source/core/svg/SVGPatternElement.idl
@@ -39,6 +39,6 @@
 SVGPatternElement implements SVGURIReference;
 // SVGPatternElement implements SVGUnitTypes;
 
-// TODO(foolip): The following was part of SVG 1.1:
+// TODO(foolip): The following was part of SVG 1.1. https://crbug.com/701893
 // http://www.w3.org/TR/SVG11/pservers.html#InterfaceSVGPatternElement
 SVGPatternElement implements SVGTests;
diff --git a/third_party/WebKit/Source/core/svg/SVGPoint.idl b/third_party/WebKit/Source/core/svg/SVGPoint.idl
index 34b2810..6cb1acf 100644
--- a/third_party/WebKit/Source/core/svg/SVGPoint.idl
+++ b/third_party/WebKit/Source/core/svg/SVGPoint.idl
@@ -23,6 +23,7 @@
 // http://www.w3.org/TR/SVG11/coords.html#InterfaceSVGPoint
 
 // TODO(foolip): SVGPoint is gone from SVG 2, replaced by DOMPoint.
+// https://crbug.com/709001
 [
     DependentLifetime,
     ImplementedAs=SVGPointTearOff,
diff --git a/third_party/WebKit/Source/core/svg/SVGRect.idl b/third_party/WebKit/Source/core/svg/SVGRect.idl
index 4868b15..fc012db 100644
--- a/third_party/WebKit/Source/core/svg/SVGRect.idl
+++ b/third_party/WebKit/Source/core/svg/SVGRect.idl
@@ -23,6 +23,7 @@
 // http://www.w3.org/TR/SVG11/types.html#InterfaceSVGRect
 
 // TODO(foolip): SVGRect is gone from SVG 2, replaced by DOMRect.
+// https://crbug.com/709001
 [
     DependentLifetime,
     ImplementedAs=SVGRectTearOff,
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
index 39564a8..445cfe074 100644
--- a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
+++ b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
@@ -365,7 +365,7 @@
   FloatRect float_bounds(FloatPoint(), size);
   const SkRect bounds(float_bounds);
 
-  flags.setShader(MakePaintShaderRecord(
+  flags.setShader(SkShader::MakePictureShader(
       PaintRecordForCurrentFrame(float_bounds, url), SkShader::kRepeat_TileMode,
       SkShader::kRepeat_TileMode, &local_matrix, &bounds));
 
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
index 62a38991..8ecd437 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
@@ -136,7 +136,6 @@
     this._registerShortcuts();
 
     this._messagesElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), false);
-    monitoringXHREnabledSetting.addChangeListener(this._monitoringXHREnabledSettingChanged, this);
 
     this._linkifier = new Components.Linkifier();
 
@@ -665,16 +664,6 @@
   }
 
   /**
-   * @param {!Common.Event} event
-   */
-  _monitoringXHREnabledSettingChanged(event) {
-    var enabled = /** @type {boolean} */ (event.data);
-    SDK.targetManager.targets().forEach(function(target) {
-      target.networkAgent().setMonitoringXHREnabled(enabled);
-    });
-  }
-
-  /**
    * @param {!Event} event
    */
   _messagesClicked(event) {
diff --git a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
index 01e7b315..925952e 100644
--- a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
@@ -102,7 +102,7 @@
     var networkManager = target.model(SDK.NetworkManager);
     if (networkManager) {
       eventListeners.push(networkManager.addEventListener(
-          SDK.NetworkManager.Events.WarningGenerated, this._networkWarningGenerated.bind(this, networkManager)));
+          SDK.NetworkManager.Events.MessageGenerated, this._networkMessageGenerated.bind(this, networkManager)));
     }
 
     target[ConsoleModel.ConsoleModel._events] = eventListeners;
@@ -337,12 +337,13 @@
    * @param {!SDK.NetworkManager} networkManager
    * @param {!Common.Event} event
    */
-  _networkWarningGenerated(networkManager, event) {
-    var warning = /** @type {!SDK.NetworkManager.Warning} */ (event.data);
+  _networkMessageGenerated(networkManager, event) {
+    var message = /** @type {!SDK.NetworkManager.Message} */ (event.data);
     this.addMessage(new ConsoleModel.ConsoleMessage(
         networkManager.target().model(SDK.RuntimeModel), ConsoleModel.ConsoleMessage.MessageSource.Network,
-        ConsoleModel.ConsoleMessage.MessageLevel.Warning, warning.message, undefined, undefined, undefined, undefined,
-        warning.requestId));
+        message.warning ? ConsoleModel.ConsoleMessage.MessageLevel.Warning :
+                          ConsoleModel.ConsoleMessage.MessageLevel.Info,
+        message.message, undefined, undefined, undefined, undefined, message.requestId));
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
index ad4ada9e..beaefd45 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
@@ -42,8 +42,6 @@
     target.registerNetworkDispatcher(this._dispatcher);
     if (Common.moduleSetting('cacheDisabled').get())
       this._networkAgent.setCacheDisabled(true);
-    if (Common.moduleSetting('monitoringXHREnabled').get())
-      this._networkAgent.setMonitoringXHREnabled(true);
 
     // Limit buffer when talking to a remote device.
     if (Runtime.queryParam('remoteFrontend') || Runtime.queryParam('ws'))
@@ -122,12 +120,12 @@
   RequestFinished: Symbol('RequestFinished'),
   RequestUpdateDropped: Symbol('RequestUpdateDropped'),
   ResponseReceived: Symbol('ResponseReceived'),
-  WarningGenerated: Symbol('WarningGenerated'),
+  MessageGenerated: Symbol('MessageGenerated'),
   RequestRedirected: Symbol('RequestRedirected'),
 };
 
-/** @typedef {{message: string, requestId: string}} */
-SDK.NetworkManager.Warning;
+/** @typedef {{message: string, requestId: string, warning: boolean}} */
+SDK.NetworkManager.Message;
 
 SDK.NetworkManager._MIMETypes = {
   'text/html': {'document': true},
@@ -242,7 +240,8 @@
           'Resource interpreted as %s but transferred with MIME type %s: "%s".', networkRequest.resourceType().title(),
           networkRequest.mimeType, networkRequest.url());
       this._manager.dispatchEventToListeners(
-          SDK.NetworkManager.Events.WarningGenerated, {message: message, requestId: networkRequest.requestId()});
+          SDK.NetworkManager.Events.MessageGenerated,
+          {message: message, requestId: networkRequest.requestId(), warning: true});
     }
 
     if (response.securityDetails)
@@ -380,7 +379,7 @@
           'Set-Cookie header is ignored in response from url: %s. Cookie length should be less than or equal to 4096 characters.',
           response.url);
       this._manager.dispatchEventToListeners(
-          SDK.NetworkManager.Events.WarningGenerated, {message: message, requestId: requestId});
+          SDK.NetworkManager.Events.MessageGenerated, {message: message, requestId: requestId, warning: true});
     }
 
     this._updateNetworkRequestWithResponse(networkRequest, response);
@@ -444,7 +443,7 @@
       if (blockedReason === Protocol.Network.BlockedReason.Inspector) {
         var message = Common.UIString('Request was blocked by DevTools: "%s".', networkRequest.url());
         this._manager.dispatchEventToListeners(
-            SDK.NetworkManager.Events.WarningGenerated, {message: message, requestId: requestId});
+            SDK.NetworkManager.Events.MessageGenerated, {message: message, requestId: requestId, warning: true});
       }
     }
     networkRequest.localizedFailDescription = localizedDescription;
@@ -635,6 +634,17 @@
     this._manager.dispatchEventToListeners(SDK.NetworkManager.Events.RequestFinished, networkRequest);
     delete this._inflightRequestsById[networkRequest.requestId()];
     delete this._inflightRequestsByURL[networkRequest.url()];
+
+    if (Common.moduleSetting('monitoringXHREnabled').get() &&
+        networkRequest.resourceType().category() === Common.resourceCategories.XHR) {
+      var message = Common.UIString(
+          (networkRequest.failed || networkRequest.hasErrorStatusCode()) ? '%s failed loading: %s "%s".' :
+                                                                           '%s finished loading: %s "%s".',
+          networkRequest.resourceType().title(), networkRequest.requestMethod, networkRequest.url());
+      this._manager.dispatchEventToListeners(
+          SDK.NetworkManager.Events.MessageGenerated,
+          {message: message, requestId: networkRequest.requestId(), warning: false});
+    }
   }
 
   /**
diff --git a/third_party/WebKit/Source/modules/crypto/SubtleCrypto.idl b/third_party/WebKit/Source/modules/crypto/SubtleCrypto.idl
index e3947bbd1..e9807d9 100644
--- a/third_party/WebKit/Source/modules/crypto/SubtleCrypto.idl
+++ b/third_party/WebKit/Source/modules/crypto/SubtleCrypto.idl
@@ -28,7 +28,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// http://www.w3.org/TR/WebCryptoAPI/#subtlecrypto-interface
+// https://w3c.github.io/webcrypto/Overview.html#subtlecrypto-interface
 
 typedef DOMString KeyFormat;
 typedef DOMString KeyUsage;
diff --git a/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.idl b/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.idl
index 19aebde..31b60805 100644
--- a/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.idl
+++ b/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.idl
@@ -4,6 +4,8 @@
 
 // https://www.w3.org/TR/2015/WD-ambient-light-20150903/#devicelightevent-interface
 
+// TODO(foolip): Remove DeviceLightEvent. https://crbug.com/711577
+
 [
     RuntimeEnabled=DeviceLight,
     Constructor(DOMString type, optional DeviceLightEventInit eventInitDict),
diff --git a/third_party/WebKit/Source/modules/device_light/DeviceLightEventInit.idl b/third_party/WebKit/Source/modules/device_light/DeviceLightEventInit.idl
index 14a9098..4d11872a 100644
--- a/third_party/WebKit/Source/modules/device_light/DeviceLightEventInit.idl
+++ b/third_party/WebKit/Source/modules/device_light/DeviceLightEventInit.idl
@@ -4,6 +4,8 @@
 
 // https://www.w3.org/TR/2015/WD-ambient-light-20150903/#devicelightevent-interface
 
+// TODO(foolip): Remove DeviceLightEvent. https://crbug.com/711577
+
 dictionary DeviceLightEventInit : EventInit {
     unrestricted double value;
 };
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceAccelerationInit.idl b/third_party/WebKit/Source/modules/device_orientation/DeviceAccelerationInit.idl
index 7276e85..85ece50 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceAccelerationInit.idl
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceAccelerationInit.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// https://www.w3.org/TR/2016/CR-orientation-event-20160818/#devicemotion
+// https://w3c.github.io/deviceorientation/spec-source-orientation.html#devicemotion
 
 dictionary DeviceAccelerationInit {
   double? x = null;
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.idl b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.idl
index e105520..9d4636b3 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.idl
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.idl
@@ -23,7 +23,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// https://www.w3.org/TR/2016/CR-orientation-event-20160818/#devicemotion
+// https://w3c.github.io/deviceorientation/spec-source-orientation.html#devicemotion
 
 [Constructor(DOMString type, optional DeviceMotionEventInit eventInitDict)]
 interface DeviceMotionEvent : Event {
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEventInit.idl b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEventInit.idl
index 36411c93..5995c967 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEventInit.idl
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEventInit.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// https://www.w3.org/TR/2016/CR-orientation-event-20160818/#devicemotion
+// https://w3c.github.io/deviceorientation/spec-source-orientation.html#devicemotion
 
 dictionary DeviceMotionEventInit : EventInit {
   DeviceAccelerationInit? acceleration;
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.idl b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.idl
index 0b9207ab..14a53d6b 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.idl
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.idl
@@ -23,7 +23,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// https://www.w3.org/TR/2016/CR-orientation-event-20160818/#deviceorientation
+// https://w3c.github.io/deviceorientation/spec-source-orientation.html#deviceorientation
 
 [Constructor(DOMString type, optional DeviceOrientationEventInit eventInitDict)]
 interface DeviceOrientationEvent : Event {
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEventInit.idl b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEventInit.idl
index 7b76ced..12d5761 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEventInit.idl
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEventInit.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// https://www.w3.org/TR/2016/CR-orientation-event-20160818/#deviceorientation
+// https://w3c.github.io/deviceorientation/spec-source-orientation.html#deviceorientation
 
 dictionary DeviceOrientationEventInit : EventInit {
   double? alpha = null;
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRateInit.idl b/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRateInit.idl
index 00fc4a31..e08ef7e9 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRateInit.idl
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRateInit.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// https://www.w3.org/TR/2016/CR-orientation-event-20160818/#devicemotion
+// https://w3c.github.io/deviceorientation/spec-source-orientation.html#deviceorientation
 
 dictionary DeviceRotationRateInit {
   double? alpha = null;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.idl b/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.idl
index b9887cd1..7755c394 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.idl
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.idl
@@ -23,7 +23,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// http://www.w3.org/TR/IndexedDB/#idl-def-IDBCursorWithValue
+// https://w3c.github.io/IndexedDB/#idbcursorwithvalue
 
 [
     Exposed=(Window,Worker)
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBFactory.idl b/third_party/WebKit/Source/modules/indexeddb/IDBFactory.idl
index 5e94641..7ba7cfc 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBFactory.idl
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBFactory.idl
@@ -23,7 +23,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// http://www.w3.org/TR/IndexedDB/#idl-def-IDBFactory
+// https://w3c.github.io/IndexedDB/#idbfactory
 
 [
     Exposed=(Window,Worker),
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBIndexParameters.idl b/third_party/WebKit/Source/modules/indexeddb/IDBIndexParameters.idl
index c6f07bac..33bd1833 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBIndexParameters.idl
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBIndexParameters.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// http://www.w3.org/TR/IndexedDB/#idl-def-IDBIndexParameters
+// https://w3c.github.io/IndexedDB/#dictdef-idbindexparameters
 
 dictionary IDBIndexParameters {
     boolean unique = false;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.idl b/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.idl
index aae8b02..2f34914 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.idl
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.idl
@@ -23,7 +23,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// http://www.w3.org/TR/IndexedDB/#idl-def-IDBKeyRange
+// https://w3c.github.io/IndexedDB/#idbkeyrange
 
 [
     Exposed=(Window,Worker),
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBObjectStoreParameters.idl b/third_party/WebKit/Source/modules/indexeddb/IDBObjectStoreParameters.idl
index cd494593..32d9fff 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBObjectStoreParameters.idl
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBObjectStoreParameters.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// http://www.w3.org/TR/IndexedDB/#idl-def-IDBObjectStoreParameters
+// https://w3c.github.io/IndexedDB/#dictdef-idbobjectstoreparameters
 
 dictionary IDBObjectStoreParameters {
     (DOMString or sequence<DOMString>)? keyPath = null;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.idl b/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.idl
index dbb23133..9594c8a 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.idl
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.idl
@@ -23,7 +23,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// http://www.w3.org/TR/IndexedDB/#idl-def-IDBOpenDBRequest
+// https://w3c.github.io/IndexedDB/#idbopendbrequest
 
 [
     Exposed=(Window,Worker)
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl
index d9f5b19..7fbbbc04 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl
@@ -27,14 +27,14 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// http://www.w3.org/TR/IndexedDB/#idl-def-IDBRequestReadyState
+// https://w3c.github.io/IndexedDB/#enumdef-idbrequestreadystate
 
 enum IDBRequestReadyState {
     "pending",
     "done"
 };
 
-// http://www.w3.org/TR/IndexedDB/#idl-def-IDBRequest
+// https://w3c.github.io/IndexedDB/#idbrequest
 
 [
     ActiveScriptWrappable,
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.idl b/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.idl
index b6656a7..b3bdfbb 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.idl
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.idl
@@ -23,11 +23,11 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// http://www.w3.org/TR/IndexedDB/#idl-def-IDBVersionChangeEvent
+// https://w3c.github.io/IndexedDB/#events
 
-// FIXME: This enum is non-standard, see
-// https://www.w3.org/Bugs/Public/show_bug.cgi?id=22370
+// FIXME: This enum is non-standard, see https://crbug.com/711586
 enum IDBDataLossAmount { "none", "total" };
+
 [
     Exposed=(Window,Worker),
     Constructor(DOMString type, optional IDBVersionChangeEventInit eventInitDict)
@@ -35,8 +35,7 @@
     readonly attribute unsigned long long oldVersion;
     readonly attribute unsigned long long? newVersion;
 
-    // FIXME: These are non-standard, see
-    // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22370
+    // FIXME: These are non-standard, see https://crbug.com/711586
     readonly attribute IDBDataLossAmount dataLoss;
     readonly attribute DOMString dataLossMessage;
 };
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEventInit.idl b/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEventInit.idl
index 1ee4c859..1742fae 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEventInit.idl
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEventInit.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// http://www.w3.org/TR/IndexedDB/#idl-def-IDBVersionChangeEventInit
+// https://w3c.github.io/IndexedDB/#events
 
 dictionary IDBVersionChangeEventInit : EventInit {
     unsigned long long  oldVersion = 0;
diff --git a/third_party/WebKit/Source/modules/media_controls/BUILD.gn b/third_party/WebKit/Source/modules/media_controls/BUILD.gn
index fdfc1e2..7ebea559 100644
--- a/third_party/WebKit/Source/modules/media_controls/BUILD.gn
+++ b/third_party/WebKit/Source/modules/media_controls/BUILD.gn
@@ -14,23 +14,37 @@
     "MediaControlsOrientationLockDelegate.h",
     "MediaControlsWindowEventListener.cpp",
     "MediaControlsWindowEventListener.h",
+    "elements/MediaControlCastButtonElement.cpp",
+    "elements/MediaControlCastButtonElement.h",
     "elements/MediaControlCurrentTimeDisplayElement.cpp",
     "elements/MediaControlCurrentTimeDisplayElement.h",
+    "elements/MediaControlDownloadButtonElement.cpp",
+    "elements/MediaControlDownloadButtonElement.h",
     "elements/MediaControlElementsHelper.cpp",
     "elements/MediaControlElementsHelper.h",
+    "elements/MediaControlFullscreenButtonElement.cpp",
+    "elements/MediaControlFullscreenButtonElement.h",
     "elements/MediaControlMuteButtonElement.cpp",
     "elements/MediaControlMuteButtonElement.h",
+    "elements/MediaControlOverflowMenuButtonElement.cpp",
+    "elements/MediaControlOverflowMenuButtonElement.h",
     "elements/MediaControlOverflowMenuListElement.cpp",
     "elements/MediaControlOverflowMenuListElement.h",
     "elements/MediaControlOverlayEnclosureElement.cpp",
     "elements/MediaControlOverlayEnclosureElement.h",
+    "elements/MediaControlOverlayPlayButtonElement.cpp",
+    "elements/MediaControlOverlayPlayButtonElement.h",
     "elements/MediaControlPanelElement.cpp",
     "elements/MediaControlPanelElement.h",
     "elements/MediaControlPanelEnclosureElement.cpp",
     "elements/MediaControlPanelEnclosureElement.h",
+    "elements/MediaControlPlayButtonElement.cpp",
+    "elements/MediaControlPlayButtonElement.h",
     "elements/MediaControlRemainingTimeDisplayElement.cpp",
     "elements/MediaControlRemainingTimeDisplayElement.h",
     "elements/MediaControlTextTrackListElement.cpp",
     "elements/MediaControlTextTrackListElement.h",
+    "elements/MediaControlToggleClosedCaptionsButtonElement.cpp",
+    "elements/MediaControlToggleClosedCaptionsButtonElement.h",
   ]
 }
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
index becfd255a..227a699e5 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
@@ -46,14 +46,21 @@
 #include "modules/media_controls/MediaControlsMediaEventListener.h"
 #include "modules/media_controls/MediaControlsOrientationLockDelegate.h"
 #include "modules/media_controls/MediaControlsWindowEventListener.h"
+#include "modules/media_controls/elements/MediaControlCastButtonElement.h"
 #include "modules/media_controls/elements/MediaControlCurrentTimeDisplayElement.h"
+#include "modules/media_controls/elements/MediaControlDownloadButtonElement.h"
+#include "modules/media_controls/elements/MediaControlFullscreenButtonElement.h"
 #include "modules/media_controls/elements/MediaControlMuteButtonElement.h"
+#include "modules/media_controls/elements/MediaControlOverflowMenuButtonElement.h"
 #include "modules/media_controls/elements/MediaControlOverflowMenuListElement.h"
 #include "modules/media_controls/elements/MediaControlOverlayEnclosureElement.h"
+#include "modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h"
 #include "modules/media_controls/elements/MediaControlPanelElement.h"
 #include "modules/media_controls/elements/MediaControlPanelEnclosureElement.h"
+#include "modules/media_controls/elements/MediaControlPlayButtonElement.h"
 #include "modules/media_controls/elements/MediaControlRemainingTimeDisplayElement.h"
 #include "modules/media_controls/elements/MediaControlTextTrackListElement.h"
+#include "modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.h"
 #include "platform/EventDispatchForbiddenScope.h"
 
 namespace blink {
@@ -305,16 +312,12 @@
   overlay_enclosure_ = new MediaControlOverlayEnclosureElement(*this);
 
   if (RuntimeEnabledFeatures::mediaControlsOverlayPlayButtonEnabled()) {
-    MediaControlOverlayPlayButtonElement* overlay_play_button =
-        MediaControlOverlayPlayButtonElement::Create(*this);
-    overlay_play_button_ = overlay_play_button;
-    overlay_enclosure_->AppendChild(overlay_play_button);
+    overlay_play_button_ = new MediaControlOverlayPlayButtonElement(*this);
+    overlay_enclosure_->AppendChild(overlay_play_button_);
   }
 
-  MediaControlCastButtonElement* overlay_cast_button =
-      MediaControlCastButtonElement::Create(*this, true);
-  overlay_cast_button_ = overlay_cast_button;
-  overlay_enclosure_->AppendChild(overlay_cast_button);
+  overlay_cast_button_ = new MediaControlCastButtonElement(*this, true);
+  overlay_enclosure_->AppendChild(overlay_cast_button_);
 
   AppendChild(overlay_enclosure_);
 
@@ -324,10 +327,8 @@
 
   panel_ = new MediaControlPanelElement(*this);
 
-  MediaControlPlayButtonElement* play_button =
-      MediaControlPlayButtonElement::Create(*this);
-  play_button_ = play_button;
-  panel_->AppendChild(play_button);
+  play_button_ = new MediaControlPlayButtonElement(*this);
+  panel_->AppendChild(play_button_);
 
   current_time_display_ = new MediaControlCurrentTimeDisplayElement(*this);
   current_time_display_->SetIsWanted(true);
@@ -351,25 +352,18 @@
   if (PreferHiddenVolumeControls(GetDocument()))
     volume_slider_->SetIsWanted(false);
 
-  MediaControlFullscreenButtonElement* fullscreen_button =
-      MediaControlFullscreenButtonElement::Create(*this);
-  fullscreen_button_ = fullscreen_button;
-  panel_->AppendChild(fullscreen_button);
+  fullscreen_button_ = new MediaControlFullscreenButtonElement(*this);
+  panel_->AppendChild(fullscreen_button_);
 
-  MediaControlDownloadButtonElement* download_button =
-      MediaControlDownloadButtonElement::Create(*this);
-  download_button_ = download_button;
-  panel_->AppendChild(download_button);
+  download_button_ = new MediaControlDownloadButtonElement(*this);
+  panel_->AppendChild(download_button_);
 
-  MediaControlCastButtonElement* cast_button =
-      MediaControlCastButtonElement::Create(*this, false);
-  cast_button_ = cast_button;
-  panel_->AppendChild(cast_button);
+  cast_button_ = new MediaControlCastButtonElement(*this, false);
+  panel_->AppendChild(cast_button_);
 
-  MediaControlToggleClosedCaptionsButtonElement* toggle_closed_captions_button =
-      MediaControlToggleClosedCaptionsButtonElement::Create(*this);
-  toggle_closed_captions_button_ = toggle_closed_captions_button;
-  panel_->AppendChild(toggle_closed_captions_button);
+  toggle_closed_captions_button_ =
+      new MediaControlToggleClosedCaptionsButtonElement(*this);
+  panel_->AppendChild(toggle_closed_captions_button_);
 
   enclosure_->AppendChild(panel_);
 
@@ -378,10 +372,8 @@
   text_track_list_ = new MediaControlTextTrackListElement(*this);
   AppendChild(text_track_list_);
 
-  MediaControlOverflowMenuButtonElement* overflow_menu =
-      MediaControlOverflowMenuButtonElement::Create(*this);
-  overflow_menu_ = overflow_menu;
-  panel_->AppendChild(overflow_menu);
+  overflow_menu_ = new MediaControlOverflowMenuButtonElement(*this);
+  panel_->AppendChild(overflow_menu_);
 
   overflow_list_ = new MediaControlOverflowMenuListElement(*this);
   AppendChild(overflow_list_);
@@ -391,18 +383,18 @@
   // relative to each other.  The first item appended appears at the top of the
   // overflow menu.
   overflow_list_->AppendChild(play_button_->CreateOverflowElement(
-      *this, MediaControlPlayButtonElement::Create(*this)));
+      *this, new MediaControlPlayButtonElement(*this)));
   overflow_list_->AppendChild(fullscreen_button_->CreateOverflowElement(
-      *this, MediaControlFullscreenButtonElement::Create(*this)));
+      *this, new MediaControlFullscreenButtonElement(*this)));
   overflow_list_->AppendChild(download_button_->CreateOverflowElement(
-      *this, MediaControlDownloadButtonElement::Create(*this)));
+      *this, new MediaControlDownloadButtonElement(*this)));
   overflow_list_->AppendChild(mute_button_->CreateOverflowElement(
       *this, new MediaControlMuteButtonElement(*this)));
   overflow_list_->AppendChild(cast_button_->CreateOverflowElement(
-      *this, MediaControlCastButtonElement::Create(*this, false)));
+      *this, new MediaControlCastButtonElement(*this, false)));
   overflow_list_->AppendChild(
       toggle_closed_captions_button_->CreateOverflowElement(
-          *this, MediaControlToggleClosedCaptionsButtonElement::Create(*this)));
+          *this, new MediaControlToggleClosedCaptionsButtonElement(*this)));
 }
 
 Node::InsertionNotificationRequest MediaControlsImpl::InsertedInto(
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h
index 5271632..d761f23 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h
@@ -38,14 +38,21 @@
 class MediaControlsMediaEventListener;
 class MediaControlsOrientationLockDelegate;
 class MediaControlsWindowEventListener;
+class MediaControlCastButtonElement;
 class MediaControlCurrentTimeDisplayElement;
+class MediaControlDownloadButtonElement;
+class MediaControlFullscreenButtonElement;
 class MediaControlMuteButtonElement;
+class MediaControlOverflowMenuButtonElement;
 class MediaControlOverflowMenuListElement;
 class MediaControlOverlayEnclosureElement;
+class MediaControlOverlayPlayButtonElement;
 class MediaControlPanelElement;
 class MediaControlPanelEnclosureElement;
+class MediaControlPlayButtonElement;
 class MediaControlRemainingTimeDisplayElement;
 class MediaControlTextTrackListElement;
+class MediaControlToggleClosedCaptionsButtonElement;
 class ShadowRoot;
 
 // Default implementation of the core/ MediaControls interface used by
@@ -98,13 +105,6 @@
   void BeginScrubbing() override;
   void EndScrubbing() override;
   void UpdateCurrentTimeDisplay() override;
-  void ToggleTextTrackList() override;
-  void ShowTextTrackAtIndex(unsigned) override;
-  void DisableShowingTextTracks() override;
-  // Called by the fullscreen buttons to toggle fulllscreen on/off.
-  void EnterFullscreen() override;
-  void ExitFullscreen() override;
-  void ToggleOverflowMenu() override;
   bool OverflowMenuVisible() override;
   // TODO(mlamouri): this method is needed in order to notify the controls that
   // the `MediaControlsEnabled` setting has changed.
@@ -114,6 +114,18 @@
   }
   Document& OwnerDocument() { return GetDocument(); }
 
+  // Called by the fullscreen buttons to toggle fulllscreen on/off.
+  void EnterFullscreen();
+  void ExitFullscreen();
+
+  // Text track related methods exposed to components handling closed captions.
+  void ToggleTextTrackList();
+  void ShowTextTrackAtIndex(unsigned);
+  void DisableShowingTextTracks();
+
+  // Toggle the overflow menu visibility.
+  void ToggleOverflowMenu();
+
   void ShowOverlayCastButtonIfNeeded();
 
   DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
index 9850df1..d54964c 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
@@ -22,6 +22,7 @@
 #include "core/loader/EmptyClients.h"
 #include "core/testing/DummyPageHolder.h"
 #include "modules/media_controls/elements/MediaControlCurrentTimeDisplayElement.h"
+#include "modules/media_controls/elements/MediaControlDownloadButtonElement.h"
 #include "platform/heap/Handle.h"
 #include "platform/testing/EmptyWebMediaPlayer.h"
 #include "platform/testing/HistogramTester.h"
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsWindowEventListener.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsWindowEventListener.cpp
index f8c2506..23ec9772 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsWindowEventListener.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsWindowEventListener.cpp
@@ -8,6 +8,7 @@
 #include "core/frame/LocalDOMWindow.h"
 #include "core/html/shadow/MediaControlElements.h"
 #include "modules/media_controls/MediaControlsImpl.h"
+#include "modules/media_controls/elements/MediaControlCastButtonElement.h"
 #include "modules/media_controls/elements/MediaControlPanelElement.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp
new file mode 100644
index 0000000..2e0c50d99
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp
@@ -0,0 +1,131 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/media_controls/elements/MediaControlCastButtonElement.h"
+
+#include "core/InputTypeNames.h"
+#include "core/dom/ClientRect.h"
+#include "core/events/Event.h"
+#include "core/html/HTMLMediaElement.h"
+#include "modules/media_controls/MediaControlsImpl.h"
+#include "modules/media_controls/elements/MediaControlElementsHelper.h"
+#include "public/platform/Platform.h"
+
+namespace blink {
+
+namespace {
+
+Element* ElementFromCenter(Element& element) {
+  ClientRect* client_rect = element.getBoundingClientRect();
+  int center_x =
+      static_cast<int>((client_rect->left() + client_rect->right()) / 2);
+  int center_y =
+      static_cast<int>((client_rect->top() + client_rect->bottom()) / 2);
+
+  return element.GetDocument().ElementFromPoint(center_x, center_y);
+}
+
+}  // anonymous namespace
+
+MediaControlCastButtonElement::MediaControlCastButtonElement(
+    MediaControlsImpl& media_controls,
+    bool is_overlay_button)
+    : MediaControlInputElement(media_controls, kMediaCastOnButton),
+      is_overlay_button_(is_overlay_button) {
+  EnsureUserAgentShadowRoot();
+  SetShadowPseudoId(is_overlay_button
+                        ? "-internal-media-controls-overlay-cast-button"
+                        : "-internal-media-controls-cast-button");
+  setType(InputTypeNames::button);
+
+  if (is_overlay_button_)
+    RecordMetrics(CastOverlayMetrics::kCreated);
+  SetIsPlayingRemotely(false);
+}
+
+void MediaControlCastButtonElement::TryShowOverlay() {
+  DCHECK(is_overlay_button_);
+
+  SetIsWanted(true);
+  if (ElementFromCenter(*this) != &MediaElement()) {
+    SetIsWanted(false);
+    return;
+  }
+
+  DCHECK(IsWanted());
+  if (!show_use_counted_) {
+    show_use_counted_ = true;
+    RecordMetrics(CastOverlayMetrics::kShown);
+  }
+}
+
+void MediaControlCastButtonElement::SetIsPlayingRemotely(
+    bool is_playing_remotely) {
+  if (is_playing_remotely) {
+    if (is_overlay_button_) {
+      SetDisplayType(kMediaOverlayCastOnButton);
+    } else {
+      SetDisplayType(kMediaCastOnButton);
+    }
+  } else {
+    if (is_overlay_button_) {
+      SetDisplayType(kMediaOverlayCastOffButton);
+    } else {
+      SetDisplayType(kMediaCastOffButton);
+    }
+  }
+  UpdateOverflowString();
+}
+
+bool MediaControlCastButtonElement::WillRespondToMouseClickEvents() {
+  return true;
+}
+
+WebLocalizedString::Name
+MediaControlCastButtonElement::GetOverflowStringName() {
+  if (MediaElement().IsPlayingRemotely())
+    return WebLocalizedString::kOverflowMenuStopCast;
+  return WebLocalizedString::kOverflowMenuCast;
+}
+
+bool MediaControlCastButtonElement::HasOverflowButton() {
+  return true;
+}
+
+void MediaControlCastButtonElement::DefaultEventHandler(Event* event) {
+  if (event->type() == EventTypeNames::click) {
+    if (is_overlay_button_) {
+      Platform::Current()->RecordAction(
+          UserMetricsAction("Media.Controls.CastOverlay"));
+    } else {
+      Platform::Current()->RecordAction(
+          UserMetricsAction("Media.Controls.Cast"));
+    }
+
+    if (is_overlay_button_ && !click_use_counted_) {
+      click_use_counted_ = true;
+      RecordMetrics(CastOverlayMetrics::kClicked);
+    }
+    if (MediaElement().IsPlayingRemotely()) {
+      MediaElement().RequestRemotePlaybackControl();
+    } else {
+      MediaElement().RequestRemotePlayback();
+    }
+  }
+  MediaControlInputElement::DefaultEventHandler(event);
+}
+
+bool MediaControlCastButtonElement::KeepEventInNode(Event* event) {
+  return MediaControlElementsHelper::IsUserInteractionEvent(event);
+}
+
+void MediaControlCastButtonElement::RecordMetrics(CastOverlayMetrics metric) {
+  DCHECK(is_overlay_button_);
+  DEFINE_STATIC_LOCAL(
+      EnumerationHistogram, overlay_histogram,
+      ("Cast.Sender.Overlay", static_cast<int>(CastOverlayMetrics::kCount)));
+  overlay_histogram.Count(static_cast<int>(metric));
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.h
new file mode 100644
index 0000000..c640a8e
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.h
@@ -0,0 +1,55 @@
+// Copyright 2017 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 MediaControlCastButtonElement_h
+#define MediaControlCastButtonElement_h
+
+#include "core/html/shadow/MediaControlElementTypes.h"
+
+namespace blink {
+
+class Event;
+class MediaControlsImpl;
+
+class MediaControlCastButtonElement final : public MediaControlInputElement {
+ public:
+  MediaControlCastButtonElement(MediaControlsImpl&, bool is_overlay_button);
+
+  // This will show a cast button if it is not covered by another element.
+  // This MUST be called for cast button elements that are overlay elements.
+  void TryShowOverlay();
+
+  void SetIsPlayingRemotely(bool);
+
+  // MediaControlInputElement overrides.
+  bool WillRespondToMouseClickEvents() override;
+  WebLocalizedString::Name GetOverflowStringName() override;
+  bool HasOverflowButton() override;
+
+ private:
+  // This is used for UMA histogram (Cast.Sender.Overlay). New values should
+  // be appended only and must be added before |Count|.
+  enum class CastOverlayMetrics {
+    kCreated = 0,
+    kShown,
+    kClicked,
+    kCount  // Keep last.
+  };
+
+  void DefaultEventHandler(Event*) override;
+  bool KeepEventInNode(Event*) override;
+
+  void RecordMetrics(CastOverlayMetrics);
+
+  bool is_overlay_button_;
+
+  // UMA related boolean. They are used to prevent counting something twice
+  // for the same media element.
+  bool click_use_counted_ = false;
+  bool show_use_counted_ = false;
+};
+
+}  // namespace blink
+
+#endif  // MediaControlCastButtonElement_h
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.cpp
new file mode 100644
index 0000000..fb1cbdba
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.cpp
@@ -0,0 +1,134 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/media_controls/elements/MediaControlDownloadButtonElement.h"
+
+#include "core/InputTypeNames.h"
+#include "core/events/Event.h"
+#include "core/frame/Settings.h"
+#include "core/html/HTMLAnchorElement.h"
+#include "core/html/HTMLMediaElement.h"
+#include "core/html/media/HTMLMediaElementControlsList.h"
+#include "core/html/media/HTMLMediaSource.h"
+#include "core/page/Page.h"
+#include "modules/media_controls/MediaControlsImpl.h"
+#include "public/platform/Platform.h"
+
+namespace blink {
+
+MediaControlDownloadButtonElement::MediaControlDownloadButtonElement(
+    MediaControlsImpl& media_controls)
+    : MediaControlInputElement(media_controls, kMediaDownloadButton) {
+  EnsureUserAgentShadowRoot();
+  setType(InputTypeNames::button);
+  SetShadowPseudoId(AtomicString("-internal-media-controls-download-button"));
+  SetIsWanted(false);
+}
+
+bool MediaControlDownloadButtonElement::ShouldDisplayDownloadButton() {
+  const KURL& url = MediaElement().currentSrc();
+
+  // Check page settings to see if download is disabled.
+  if (GetDocument().GetPage() &&
+      GetDocument().GetPage()->GetSettings().GetHideDownloadUI())
+    return false;
+
+  // URLs that lead to nowhere are ignored.
+  if (url.IsNull() || url.IsEmpty())
+    return false;
+
+  // If we have no source, we can't download.
+  if (MediaElement().getNetworkState() == HTMLMediaElement::kNetworkEmpty ||
+      MediaElement().getNetworkState() == HTMLMediaElement::kNetworkNoSource) {
+    return false;
+  }
+
+  // Local files and blobs (including MSE) should not have a download button.
+  if (url.IsLocalFile() || url.ProtocolIs("blob"))
+    return false;
+
+  // MediaStream can't be downloaded.
+  if (HTMLMediaElement::IsMediaStreamURL(url.GetString()))
+    return false;
+
+  // MediaSource can't be downloaded.
+  if (HTMLMediaSource::Lookup(url))
+    return false;
+
+  // HLS stream shouldn't have a download button.
+  if (HTMLMediaElement::IsHLSURL(url))
+    return false;
+
+  // Infinite streams don't have a clear end at which to finish the download
+  // (would require adding UI to prompt for the duration to download).
+  if (MediaElement().duration() == std::numeric_limits<double>::infinity())
+    return false;
+
+  // The attribute disables the download button.
+  if (MediaElement().ControlsListInternal()->ShouldHideDownload()) {
+    UseCounter::Count(MediaElement().GetDocument(),
+                      UseCounter::kHTMLMediaElementControlsListNoDownload);
+    return false;
+  }
+
+  return true;
+}
+
+WebLocalizedString::Name
+MediaControlDownloadButtonElement::GetOverflowStringName() {
+  return WebLocalizedString::kOverflowMenuDownload;
+}
+
+bool MediaControlDownloadButtonElement::HasOverflowButton() {
+  return true;
+}
+
+void MediaControlDownloadButtonElement::SetIsWanted(bool wanted) {
+  MediaControlElement::SetIsWanted(wanted);
+
+  if (!IsWanted())
+    return;
+
+  DCHECK(IsWanted());
+  if (!show_use_counted_) {
+    show_use_counted_ = true;
+    RecordMetrics(DownloadActionMetrics::kShown);
+  }
+}
+
+DEFINE_TRACE(MediaControlDownloadButtonElement) {
+  visitor->Trace(anchor_);
+  MediaControlInputElement::Trace(visitor);
+}
+
+void MediaControlDownloadButtonElement::DefaultEventHandler(Event* event) {
+  const KURL& url = MediaElement().currentSrc();
+  if (event->type() == EventTypeNames::click &&
+      !(url.IsNull() || url.IsEmpty())) {
+    Platform::Current()->RecordAction(
+        UserMetricsAction("Media.Controls.Download"));
+    if (!click_use_counted_) {
+      click_use_counted_ = true;
+      RecordMetrics(DownloadActionMetrics::kClicked);
+    }
+    if (!anchor_) {
+      HTMLAnchorElement* anchor = HTMLAnchorElement::Create(GetDocument());
+      anchor->setAttribute(HTMLNames::downloadAttr, "");
+      anchor_ = anchor;
+    }
+    anchor_->SetURL(url);
+    anchor_->DispatchSimulatedClick(event);
+  }
+  MediaControlInputElement::DefaultEventHandler(event);
+}
+
+void MediaControlDownloadButtonElement::RecordMetrics(
+    DownloadActionMetrics metric) {
+  DEFINE_STATIC_LOCAL(EnumerationHistogram, download_action_histogram,
+                      ("Media.Controls.Download",
+                       static_cast<int>(DownloadActionMetrics::kCount)));
+  download_action_histogram.Count(static_cast<int>(metric));
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.h
new file mode 100644
index 0000000..da1f7e08
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.h
@@ -0,0 +1,56 @@
+// Copyright 2017 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 MediaControlDownloadButtonElement_h
+#define MediaControlDownloadButtonElement_h
+
+#include "core/html/shadow/MediaControlElementTypes.h"
+
+namespace blink {
+
+class Event;
+class MediaControlsImpl;
+
+class MediaControlDownloadButtonElement final
+    : public MediaControlInputElement {
+ public:
+  explicit MediaControlDownloadButtonElement(MediaControlsImpl&);
+
+  // Returns true if the download button should be shown. We should
+  // show the button for only non-MSE, non-EME, and non-MediaStream content.
+  bool ShouldDisplayDownloadButton();
+
+  // MediaControlInputElement overrides.
+  // TODO(mlamouri): add WillRespondToMouseClickEvents
+  WebLocalizedString::Name GetOverflowStringName() override;
+  bool HasOverflowButton() override;
+  void SetIsWanted(bool) override;
+
+  DECLARE_VIRTUAL_TRACE();
+
+ private:
+  // This is used for UMA histogram (Media.Controls.Download). New values should
+  // be appended only and must be added before |Count|.
+  enum class DownloadActionMetrics {
+    kShown = 0,
+    kClicked,
+    kCount  // Keep last.
+  };
+
+  void DefaultEventHandler(Event*) override;
+
+  void RecordMetrics(DownloadActionMetrics);
+
+  // Points to an anchor element that contains the URL of the media file.
+  Member<HTMLAnchorElement> anchor_;
+
+  // UMA related boolean. They are used to prevent counting something twice
+  // for the same media element.
+  bool click_use_counted_ = false;
+  bool show_use_counted_ = false;
+};
+
+}  // namespace blink
+
+#endif  // MediaControlDownloadButtonElement_h
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.cpp
new file mode 100644
index 0000000..d47c72f
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.cpp
@@ -0,0 +1,80 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/media_controls/elements/MediaControlFullscreenButtonElement.h"
+
+#include "core/InputTypeNames.h"
+#include "core/events/Event.h"
+#include "core/frame/Settings.h"
+#include "core/html/HTMLMediaElement.h"
+#include "modules/media_controls/MediaControlsImpl.h"
+#include "public/platform/Platform.h"
+
+namespace blink {
+
+MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(
+    MediaControlsImpl& media_controls)
+    : MediaControlInputElement(media_controls, kMediaEnterFullscreenButton) {
+  EnsureUserAgentShadowRoot();
+  setType(InputTypeNames::button);
+  SetShadowPseudoId(AtomicString("-webkit-media-controls-fullscreen-button"));
+  SetIsFullscreen(MediaElement().IsFullscreen());
+  SetIsWanted(false);
+}
+
+void MediaControlFullscreenButtonElement::SetIsFullscreen(bool is_fullscreen) {
+  SetDisplayType(is_fullscreen ? kMediaExitFullscreenButton
+                               : kMediaEnterFullscreenButton);
+}
+
+bool MediaControlFullscreenButtonElement::WillRespondToMouseClickEvents() {
+  return true;
+}
+
+WebLocalizedString::Name
+MediaControlFullscreenButtonElement::GetOverflowStringName() {
+  if (MediaElement().IsFullscreen())
+    return WebLocalizedString::kOverflowMenuExitFullscreen;
+  return WebLocalizedString::kOverflowMenuEnterFullscreen;
+}
+
+bool MediaControlFullscreenButtonElement::HasOverflowButton() {
+  return true;
+}
+
+void MediaControlFullscreenButtonElement::DefaultEventHandler(Event* event) {
+  if (event->type() == EventTypeNames::click) {
+    RecordClickMetrics();
+    if (MediaElement().IsFullscreen())
+      static_cast<MediaControlsImpl&>(GetMediaControls()).ExitFullscreen();
+    else
+      static_cast<MediaControlsImpl&>(GetMediaControls()).EnterFullscreen();
+    event->SetDefaultHandled();
+  }
+  MediaControlInputElement::DefaultEventHandler(event);
+}
+
+void MediaControlFullscreenButtonElement::RecordClickMetrics() {
+  bool is_embedded_experience_enabled =
+      GetDocument().GetSettings() &&
+      GetDocument().GetSettings()->GetEmbeddedMediaExperienceEnabled();
+
+  if (MediaElement().IsFullscreen()) {
+    Platform::Current()->RecordAction(
+        UserMetricsAction("Media.Controls.ExitFullscreen"));
+    if (is_embedded_experience_enabled) {
+      Platform::Current()->RecordAction(UserMetricsAction(
+          "Media.Controls.ExitFullscreen.EmbeddedExperience"));
+    }
+  } else {
+    Platform::Current()->RecordAction(
+        UserMetricsAction("Media.Controls.EnterFullscreen"));
+    if (is_embedded_experience_enabled) {
+      Platform::Current()->RecordAction(UserMetricsAction(
+          "Media.Controls.EnterFullscreen.EmbeddedExperience"));
+    }
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.h
new file mode 100644
index 0000000..ca4d990
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.h
@@ -0,0 +1,35 @@
+// Copyright 2017 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 MediaControlFullscreenButtonElement_h
+#define MediaControlFullscreenButtonElement_h
+
+#include "core/html/shadow/MediaControlElementTypes.h"
+
+namespace blink {
+
+class Event;
+class MediaControlsImpl;
+
+class MediaControlFullscreenButtonElement final
+    : public MediaControlInputElement {
+ public:
+  explicit MediaControlFullscreenButtonElement(MediaControlsImpl&);
+
+  // TODO(mlamouri): this should be changed to UpdateDisplayType().
+  void SetIsFullscreen(bool);
+
+  // MediaControlInputElement overrides.
+  bool WillRespondToMouseClickEvents() override;
+  WebLocalizedString::Name GetOverflowStringName() override;
+  bool HasOverflowButton() override;
+
+ private:
+  void DefaultEventHandler(Event*) override;
+  void RecordClickMetrics();
+};
+
+}  // namespace blink
+
+#endif  // MediaControlFullscreenButtonElement_h
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverflowMenuButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverflowMenuButtonElement.cpp
new file mode 100644
index 0000000..08f93a3
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverflowMenuButtonElement.cpp
@@ -0,0 +1,44 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/media_controls/elements/MediaControlOverflowMenuButtonElement.h"
+
+#include "core/InputTypeNames.h"
+#include "core/events/Event.h"
+#include "modules/media_controls/MediaControlsImpl.h"
+#include "public/platform/Platform.h"
+
+namespace blink {
+
+MediaControlOverflowMenuButtonElement::MediaControlOverflowMenuButtonElement(
+    MediaControlsImpl& media_controls)
+    : MediaControlInputElement(media_controls, kMediaOverflowButton) {
+  EnsureUserAgentShadowRoot();
+  setType(InputTypeNames::button);
+  SetShadowPseudoId(AtomicString("-internal-media-controls-overflow-button"));
+  SetIsWanted(false);
+}
+
+bool MediaControlOverflowMenuButtonElement::WillRespondToMouseClickEvents() {
+  return true;
+}
+
+void MediaControlOverflowMenuButtonElement::DefaultEventHandler(Event* event) {
+  if (event->type() == EventTypeNames::click) {
+    if (GetMediaControls().OverflowMenuVisible()) {
+      Platform::Current()->RecordAction(
+          UserMetricsAction("Media.Controls.OverflowClose"));
+    } else {
+      Platform::Current()->RecordAction(
+          UserMetricsAction("Media.Controls.OverflowOpen"));
+    }
+
+    static_cast<MediaControlsImpl&>(GetMediaControls()).ToggleOverflowMenu();
+    event->SetDefaultHandled();
+  }
+
+  MediaControlInputElement::DefaultEventHandler(event);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverflowMenuButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverflowMenuButtonElement.h
new file mode 100644
index 0000000..846e4f7
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverflowMenuButtonElement.h
@@ -0,0 +1,31 @@
+// Copyright 2017 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 MediaControlOverflowMenuButtonElement_h
+#define MediaControlOverflowMenuButtonElement_h
+
+#include "core/html/shadow/MediaControlElementTypes.h"
+
+namespace blink {
+
+class Event;
+class MediaControlsImpl;
+
+// Represents the overflow menu which is displayed when the width of the media
+// player is small enough that at least two buttons are no longer visible.
+class MediaControlOverflowMenuButtonElement final
+    : public MediaControlInputElement {
+ public:
+  explicit MediaControlOverflowMenuButtonElement(MediaControlsImpl&);
+
+  // MediaControlInputElement overrides.
+  bool WillRespondToMouseClickEvents() override;
+
+ private:
+  void DefaultEventHandler(Event*) override;
+};
+
+}  // namespace blink
+
+#endif  // MediaControlOverflowMenuButtonElement_h
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
new file mode 100644
index 0000000..b9a5e90
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
@@ -0,0 +1,43 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h"
+
+#include "core/InputTypeNames.h"
+#include "core/events/Event.h"
+#include "core/html/HTMLMediaElement.h"
+#include "modules/media_controls/MediaControlsImpl.h"
+#include "modules/media_controls/elements/MediaControlElementsHelper.h"
+#include "public/platform/Platform.h"
+
+namespace blink {
+
+MediaControlOverlayPlayButtonElement::MediaControlOverlayPlayButtonElement(
+    MediaControlsImpl& media_controls)
+    : MediaControlInputElement(media_controls, kMediaOverlayPlayButton) {
+  EnsureUserAgentShadowRoot();
+  setType(InputTypeNames::button);
+  SetShadowPseudoId(AtomicString("-webkit-media-controls-overlay-play-button"));
+}
+
+void MediaControlOverlayPlayButtonElement::UpdateDisplayType() {
+  SetIsWanted(MediaElement().ShouldShowControls() && MediaElement().paused());
+}
+
+void MediaControlOverlayPlayButtonElement::DefaultEventHandler(Event* event) {
+  if (event->type() == EventTypeNames::click && MediaElement().paused()) {
+    Platform::Current()->RecordAction(
+        UserMetricsAction("Media.Controls.PlayOverlay"));
+    MediaElement().Play();
+    UpdateDisplayType();
+    event->SetDefaultHandled();
+  }
+  // TODO(mlamouri): should call MediaControlInputElement::DefaultEventHandler.
+}
+
+bool MediaControlOverlayPlayButtonElement::KeepEventInNode(Event* event) {
+  return MediaControlElementsHelper::IsUserInteractionEvent(event);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h
new file mode 100644
index 0000000..0e6b35f
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h
@@ -0,0 +1,30 @@
+// Copyright 2017 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 MediaControlOverlayPlayButtonElement_h
+#define MediaControlOverlayPlayButtonElement_h
+
+#include "core/html/shadow/MediaControlElementTypes.h"
+
+namespace blink {
+
+class Event;
+class MediaControlsImpl;
+
+class MediaControlOverlayPlayButtonElement final
+    : public MediaControlInputElement {
+ public:
+  explicit MediaControlOverlayPlayButtonElement(MediaControlsImpl&);
+
+  // MediaControlInputElement overrides.
+  void UpdateDisplayType() override;
+
+ private:
+  void DefaultEventHandler(Event*) override;
+  bool KeepEventInNode(Event*) override;
+};
+
+}  // namespace blink
+
+#endif  // MediaControlOverlayPlayButtonElement_h
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.cpp
new file mode 100644
index 0000000..d7e14b7
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.cpp
@@ -0,0 +1,70 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/media_controls/elements/MediaControlPlayButtonElement.h"
+
+#include "core/InputTypeNames.h"
+#include "core/events/Event.h"
+#include "core/html/HTMLMediaElement.h"
+#include "core/html/media/HTMLMediaSource.h"
+#include "modules/media_controls/MediaControlsImpl.h"
+#include "public/platform/Platform.h"
+
+namespace blink {
+
+MediaControlPlayButtonElement::MediaControlPlayButtonElement(
+    MediaControlsImpl& media_controls)
+    : MediaControlInputElement(media_controls, kMediaPlayButton) {
+  EnsureUserAgentShadowRoot();
+  setType(InputTypeNames::button);
+  SetShadowPseudoId(AtomicString("-webkit-media-controls-play-button"));
+}
+
+bool MediaControlPlayButtonElement::WillRespondToMouseClickEvents() {
+  return true;
+}
+
+void MediaControlPlayButtonElement::UpdateDisplayType() {
+  SetDisplayType(MediaElement().paused() ? kMediaPlayButton
+                                         : kMediaPauseButton);
+  UpdateOverflowString();
+}
+
+WebLocalizedString::Name
+MediaControlPlayButtonElement::GetOverflowStringName() {
+  if (MediaElement().paused())
+    return WebLocalizedString::kOverflowMenuPlay;
+  return WebLocalizedString::kOverflowMenuPause;
+}
+
+bool MediaControlPlayButtonElement::HasOverflowButton() {
+  return true;
+}
+
+void MediaControlPlayButtonElement::DefaultEventHandler(Event* event) {
+  if (event->type() == EventTypeNames::click) {
+    if (MediaElement().paused()) {
+      Platform::Current()->RecordAction(
+          UserMetricsAction("Media.Controls.Play"));
+    } else {
+      Platform::Current()->RecordAction(
+          UserMetricsAction("Media.Controls.Pause"));
+    }
+
+    // Allow play attempts for plain src= media to force a reload in the error
+    // state. This allows potential recovery for transient network and decoder
+    // resource issues.
+    const String& url = MediaElement().currentSrc().GetString();
+    if (MediaElement().error() && !HTMLMediaElement::IsMediaStreamURL(url) &&
+        !HTMLMediaSource::Lookup(url))
+      MediaElement().load();
+
+    MediaElement().TogglePlayState();
+    UpdateDisplayType();
+    event->SetDefaultHandled();
+  }
+  MediaControlInputElement::DefaultEventHandler(event);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.h
new file mode 100644
index 0000000..b9e75df
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.h
@@ -0,0 +1,31 @@
+// Copyright 2017 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 MediaControlPlayButtonElement_h
+#define MediaControlPlayButtonElement_h
+
+#include "core/html/shadow/MediaControlElementTypes.h"
+
+namespace blink {
+
+class Event;
+class MediaControlsImpl;
+
+class MediaControlPlayButtonElement final : public MediaControlInputElement {
+ public:
+  explicit MediaControlPlayButtonElement(MediaControlsImpl&);
+
+  // MediaControlInputElement overrides.
+  bool WillRespondToMouseClickEvents() override;
+  void UpdateDisplayType() override;
+  WebLocalizedString::Name GetOverflowStringName() override;
+  bool HasOverflowButton() override;
+
+ private:
+  void DefaultEventHandler(Event*) override;
+};
+
+}  // namespace blink
+
+#endif  // MediaControlPlayButtonElement_h
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.cpp
new file mode 100644
index 0000000..e774df1
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.cpp
@@ -0,0 +1,68 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.h"
+
+#include "core/InputTypeNames.h"
+#include "core/events/Event.h"
+#include "core/html/HTMLMediaElement.h"
+#include "core/html/track/TextTrackList.h"
+#include "modules/media_controls/MediaControlsImpl.h"
+
+namespace blink {
+
+MediaControlToggleClosedCaptionsButtonElement::
+    MediaControlToggleClosedCaptionsButtonElement(
+        MediaControlsImpl& media_controls)
+    : MediaControlInputElement(media_controls, kMediaShowClosedCaptionsButton) {
+  EnsureUserAgentShadowRoot();
+  setType(InputTypeNames::button);
+  SetShadowPseudoId(
+      AtomicString("-webkit-media-controls-toggle-closed-captions-button"));
+}
+
+bool MediaControlToggleClosedCaptionsButtonElement::
+    WillRespondToMouseClickEvents() {
+  return true;
+}
+
+void MediaControlToggleClosedCaptionsButtonElement::UpdateDisplayType() {
+  bool captions_visible = MediaElement().TextTracksVisible();
+  SetDisplayType(captions_visible ? kMediaHideClosedCaptionsButton
+                                  : kMediaShowClosedCaptionsButton);
+}
+
+WebLocalizedString::Name
+MediaControlToggleClosedCaptionsButtonElement::GetOverflowStringName() {
+  return WebLocalizedString::kOverflowMenuCaptions;
+}
+
+bool MediaControlToggleClosedCaptionsButtonElement::HasOverflowButton() {
+  return true;
+}
+
+void MediaControlToggleClosedCaptionsButtonElement::DefaultEventHandler(
+    Event* event) {
+  if (event->type() == EventTypeNames::click) {
+    if (MediaElement().textTracks()->length() == 1) {
+      // If only one track exists, toggle it on/off
+      if (MediaElement().textTracks()->HasShowingTracks()) {
+        static_cast<MediaControlsImpl&>(GetMediaControls())
+            .DisableShowingTextTracks();
+      } else {
+        static_cast<MediaControlsImpl&>(GetMediaControls())
+            .ShowTextTrackAtIndex(0);
+      }
+    } else {
+      static_cast<MediaControlsImpl&>(GetMediaControls()).ToggleTextTrackList();
+    }
+
+    UpdateDisplayType();
+    event->SetDefaultHandled();
+  }
+
+  MediaControlInputElement::DefaultEventHandler(event);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.h
new file mode 100644
index 0000000..e648a95
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.h
@@ -0,0 +1,32 @@
+// Copyright 2017 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 MediaControlToggleClosedCaptionsButtonElement_h
+#define MediaControlToggleClosedCaptionsButtonElement_h
+
+#include "core/html/shadow/MediaControlElementTypes.h"
+
+namespace blink {
+
+class Event;
+class MediaControlsImpl;
+
+class MediaControlToggleClosedCaptionsButtonElement final
+    : public MediaControlInputElement {
+ public:
+  explicit MediaControlToggleClosedCaptionsButtonElement(MediaControlsImpl&);
+
+  // MediaControlInputElement overrides.
+  bool WillRespondToMouseClickEvents() override;
+  void UpdateDisplayType() override;
+  WebLocalizedString::Name GetOverflowStringName() override;
+  bool HasOverflowButton() override;
+
+ private:
+  void DefaultEventHandler(Event*) override;
+};
+
+}  // namespace blink
+
+#endif  // MediaControlToggleClosedCaptionsButtonElement_h
diff --git a/third_party/WebKit/Source/modules/mediasource/MediaSource.idl b/third_party/WebKit/Source/modules/mediasource/MediaSource.idl
index 8b23fd3..28f118d1 100644
--- a/third_party/WebKit/Source/modules/mediasource/MediaSource.idl
+++ b/third_party/WebKit/Source/modules/mediasource/MediaSource.idl
@@ -28,7 +28,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// https://www.w3.org/TR/media-source/#idl-def-MediaSource
+// https://w3c.github.io/media-source/#idl-def-mediasource
 
 enum EndOfStreamError {
     "network",
diff --git a/third_party/WebKit/Source/modules/mediasource/SourceBuffer.idl b/third_party/WebKit/Source/modules/mediasource/SourceBuffer.idl
index 193360b..07f46e03 100644
--- a/third_party/WebKit/Source/modules/mediasource/SourceBuffer.idl
+++ b/third_party/WebKit/Source/modules/mediasource/SourceBuffer.idl
@@ -28,7 +28,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// https://www.w3.org/TR/media-source/#idl-def-SourceBuffer
+// https://w3c.github.io/media-source/#idl-def-sourcebuffer
 
 enum AppendMode {
     "segments",
diff --git a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.idl b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.idl
index 03b43ee..49e3fcb 100644
--- a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.idl
+++ b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.idl
@@ -18,7 +18,8 @@
     Boston, MA 02110-1301, USA.
 */
 
-// https://www.w3.org/TR/html5/webappapis.html#navigatorcontentutils
+// https://html.spec.whatwg.org/multipage/webappapis.html#custom-handlers
+
 partial interface Navigator {
     [RuntimeEnabled=NavigatorContentUtils, RaisesException] void registerProtocolHandler(DOMString scheme, DOMString url, DOMString title);
     [RuntimeEnabled=CustomSchemeHandler, RaisesException] DOMString isProtocolHandlerRegistered(DOMString scheme, DOMString url);
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEvent.idl b/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEvent.idl
index 15b64ac..d3a24c44 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEvent.idl
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEvent.idl
@@ -23,7 +23,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// http://www.w3.org/TR/webrtc/#rtcdtmftonechangeevent
+// https://w3c.github.io/webrtc-pc/#rtcdtmftonechangeevent
 
 [
     NoInterfaceObject,
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEventInit.idl b/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEventInit.idl
index a070229..82b8213 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEventInit.idl
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEventInit.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// http://www.w3.org/TR/webrtc/#rtcdtmftonechangeevent
+// https://w3c.github.io/webrtc-pc/#rtcdtmftonechangeevent
 
 dictionary RTCDTMFToneChangeEventInit : EventInit {
     DOMString tone;
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCIceCandidateInit.idl b/third_party/WebKit/Source/modules/peerconnection/RTCIceCandidateInit.idl
index e5a883e7..76c5bc19 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCIceCandidateInit.idl
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCIceCandidateInit.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// http://www.w3.org/TR/webrtc/#idl-def-RTCIceCandidateInit
+// https://w3c.github.io/webrtc-pc/#idl-def-rtcicecandidateinit
 
 dictionary RTCIceCandidateInit {
     DOMString candidate;
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp
index a215a535..75f9fdd2 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp
@@ -23,12 +23,11 @@
   list->AppendClipPathItem(clip_path_, true);
 }
 
-int BeginClipPathDisplayItem::NumberOfSlowPaths() const {
+void BeginClipPathDisplayItem::AnalyzeForGpuRasterization(
+    SkPictureGpuAnalyzer& analyzer) const {
   // Temporarily disabled (pref regressions due to GPU veto stickiness:
   // http://crbug.com/603969).
   // analyzer.analyzeClipPath(m_clipPath, SkRegion::kIntersect_Op, true);
-  // TODO(enne): fixup this code to return an int.
-  return 0;
 }
 
 void EndClipPathDisplayItem::Replay(GraphicsContext& context) const {
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h
index 3952c87..42434ae 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h
@@ -24,7 +24,7 @@
   void AppendToWebDisplayItemList(const IntRect&,
                                   WebDisplayItemList*) const override;
 
-  int NumberOfSlowPaths() const override;
+  void AnalyzeForGpuRasterization(SkPictureGpuAnalyzer&) const override;
 
  private:
 #ifndef NDEBUG
diff --git a/third_party/WebKit/Source/platform/graphics/paint/CompositingRecorder.cpp b/third_party/WebKit/Source/platform/graphics/paint/CompositingRecorder.cpp
index 7eac3491..cdcd8fd 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/CompositingRecorder.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/CompositingRecorder.cpp
@@ -29,8 +29,58 @@
 CompositingRecorder::~CompositingRecorder() {
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
     return;
-  graphics_context_.GetPaintController().EndItem<EndCompositingDisplayItem>(
-      client_);
+  // If the end of the current display list is of the form
+  // [BeginCompositingDisplayItem] [DrawingDisplayItem], then fold the
+  // BeginCompositingDisplayItem into a new DrawingDisplayItem that replaces
+  // them both. This allows Skia to optimize for the case when the
+  // BeginCompositingDisplayItem represents a simple opacity/color that can be
+  // merged into the opacity/color of the drawing. See crbug.com/628831 for more
+  // details.
+  PaintController& paint_controller = graphics_context_.GetPaintController();
+  const DisplayItem* last_display_item = paint_controller.LastDisplayItem(0);
+  const DisplayItem* second_to_last_display_item =
+      paint_controller.LastDisplayItem(1);
+  // TODO(chrishtr): remove the call to LastDisplayItemIsSubsequenceEnd when
+  // https://codereview.chromium.org/2768143002 lands.
+  if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && last_display_item &&
+      second_to_last_display_item && last_display_item->DrawsContent() &&
+      second_to_last_display_item->GetType() ==
+          DisplayItem::kBeginCompositing &&
+      !paint_controller.LastDisplayItemIsSubsequenceEnd()) {
+    FloatRect cull_rect(
+        ((DrawingDisplayItem*)last_display_item)->GetPaintRecord()->cullRect());
+    const DisplayItemClient& display_item_client = last_display_item->Client();
+    DisplayItem::Type display_item_type = last_display_item->GetType();
+
+    // Re-record the last two DisplayItems into a new drawing. The new item
+    // cannot be cached, because it is a mutation of the DisplayItem the client
+    // thought it was painting.
+    paint_controller.BeginSkippingCache();
+    {
+#if DCHECK_IS_ON()
+      // In the recorder's scope we remove the last two display items which
+      // are combined into a new drawing.
+      DisableListModificationCheck disabler;
+#endif
+      DrawingRecorder new_recorder(graphics_context_, display_item_client,
+                                   display_item_type, cull_rect);
+      DCHECK(!DrawingRecorder::UseCachedDrawingIfPossible(
+          graphics_context_, display_item_client, display_item_type));
+
+      second_to_last_display_item->Replay(graphics_context_);
+      last_display_item->Replay(graphics_context_);
+      EndCompositingDisplayItem(client_).Replay(graphics_context_);
+
+      // Remove the DrawingDisplayItem.
+      paint_controller.RemoveLastDisplayItem();
+      // Remove the BeginCompositingDisplayItem.
+      paint_controller.RemoveLastDisplayItem();
+    }
+    paint_controller.EndSkippingCache();
+  } else {
+    graphics_context_.GetPaintController().EndItem<EndCompositingDisplayItem>(
+        client_);
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
index d5f344e6..a9afcd1 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
@@ -17,6 +17,8 @@
 #include "platform/wtf/text/WTFString.h"
 #endif
 
+class SkPictureGpuAnalyzer;
+
 namespace blink {
 
 class GraphicsContext;
@@ -335,7 +337,7 @@
   virtual bool DrawsContent() const { return false; }
 
   // Override to implement specific analysis strategies.
-  virtual int NumberOfSlowPaths() const { return 0; }
+  virtual void AnalyzeForGpuRasterization(SkPictureGpuAnalyzer&) const {}
 
 #ifndef NDEBUG
   static WTF::String TypeAsDebugString(DisplayItem::Type);
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
index 4fe7853..474a7d12 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
@@ -7,6 +7,7 @@
 #include "platform/graphics/LoggingCanvas.h"
 #include "platform/graphics/paint/DrawingDisplayItem.h"
 #include "platform/graphics/paint/PaintChunk.h"
+#include "third_party/skia/include/core/SkPictureAnalyzer.h"
 
 #ifndef NDEBUG
 #include "platform/wtf/text/WTFString.h"
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp
index 7c14717..2a17f3d 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp
@@ -10,6 +10,7 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkData.h"
+#include "third_party/skia/include/core/SkPictureAnalyzer.h"
 
 namespace blink {
 
@@ -29,8 +30,14 @@
   return record_.get();
 }
 
-int DrawingDisplayItem::NumberOfSlowPaths() const {
-  return record_ ? record_->numSlowPaths() : 0;
+void DrawingDisplayItem::AnalyzeForGpuRasterization(
+    SkPictureGpuAnalyzer& analyzer) const {
+  // TODO(enne): Need an SkPictureGpuAnalyzer on PictureRecord.
+  // This is a bit overkill to ToSkPicture a record just to get
+  // numSlowPaths.
+  if (!record_)
+    return;
+  analyzer.analyzePicture(ToSkPicture(record_).get());
 }
 
 #ifndef NDEBUG
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h
index 3dedbcbd..e5f989f8 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h
@@ -41,7 +41,7 @@
     return known_to_be_opaque_;
   }
 
-  int NumberOfSlowPaths() const override;
+  void AnalyzeForGpuRasterization(SkPictureGpuAnalyzer&) const override;
 
  private:
 #ifndef NDEBUG
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
index d3b7553..e26681df 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
@@ -16,8 +16,6 @@
 #include <stdio.h>
 #endif
 
-static constexpr int kMaxNumberOfSlowPathsBeforeVeto = 5;
-
 namespace blink {
 
 void PaintController::SetTracksRasterInvalidations(bool value) {
@@ -537,7 +535,7 @@
       !new_display_item_list_.IsEmpty())
     GenerateChunkRasterInvalidationRects(new_paint_chunks_.LastChunk());
 
-  int num_slow_paths = 0;
+  SkPictureGpuAnalyzer gpu_analyzer;
 
   current_cache_generation_ =
       DisplayItemClient::CacheGenerationOrInvalidationReason::Next();
@@ -556,8 +554,8 @@
   Vector<const DisplayItemClient*> skipped_cache_clients;
   for (const auto& item : new_display_item_list_) {
     // No reason to continue the analysis once we have a veto.
-    if (num_slow_paths <= kMaxNumberOfSlowPathsBeforeVeto)
-      num_slow_paths += item.NumberOfSlowPaths();
+    if (gpu_analyzer.suitableForGpuRasterization())
+      item.AnalyzeForGpuRasterization(gpu_analyzer);
 
     // TODO(wkorman): Only compute and append visual rect for drawings.
     new_display_item_list_.AppendVisualRect(
@@ -595,7 +593,7 @@
   new_display_item_list_.ShrinkToFit();
   current_paint_artifact_ = PaintArtifact(
       std::move(new_display_item_list_), new_paint_chunks_.ReleasePaintChunks(),
-      num_slow_paths <= kMaxNumberOfSlowPathsBeforeVeto);
+      gpu_analyzer.suitableForGpuRasterization());
   ResetCurrentListIndices();
   out_of_order_item_indices_.Clear();
   out_of_order_chunk_indices_.Clear();
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
index 038f0bd..f4e0aae 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
@@ -2273,10 +2273,44 @@
     DisplayItemClient::EndShouldKeepAliveAllClients();
 #endif
   }
+
+  void TestFoldCompositingDrawingInSubsequence() {
+    FakeDisplayItemClient container("container");
+    FakeDisplayItemClient content("content");
+    GraphicsContext context(GetPaintController());
+
+    {
+      SubsequenceRecorder subsequence(context, container);
+      CompositingRecorder compositing(context, content, SkBlendMode::kSrc, 0.5);
+      DrawRect(context, content, kBackgroundDrawingType,
+               FloatRect(100, 100, 300, 300));
+    }
+    GetPaintController().CommitNewDisplayItems();
+    EXPECT_EQ(
+        1u,
+        GetPaintController().GetPaintArtifact().GetDisplayItemList().size());
+
+    {
+      EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+          context, container));
+      SubsequenceRecorder subsequence(context, container);
+      CompositingRecorder compositing(context, content, SkBlendMode::kSrc, 0.5);
+      DrawRect(context, content, kBackgroundDrawingType,
+               FloatRect(100, 100, 300, 300));
+    }
+    GetPaintController().CommitNewDisplayItems();
+    EXPECT_EQ(
+        1u,
+        GetPaintController().GetPaintArtifact().GetDisplayItemList().size());
+
+#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
+    DisplayItemClient::EndShouldKeepAliveAllClients();
+#endif
+  }
 };
 
 TEST_F(PaintControllerUnderInvalidationTest, ChangeDrawing) {
-  EXPECT_DEATH(TestChangeDrawing(), "under-invalidation: display item changed");
+  EXPECT_DEATH(TestChangeDrawing(), "");
 }
 
 TEST_F(PaintControllerUnderInvalidationTest, MoreDrawing) {
@@ -2297,29 +2331,22 @@
 }
 
 TEST_F(PaintControllerUnderInvalidationTest, ChangeDrawingInSubsequence) {
-  EXPECT_DEATH(TestChangeDrawingInSubsequence(),
-               "\"\\(In cached subsequence of first\\)\" under-invalidation: "
-               "display item changed");
+  EXPECT_DEATH(TestChangeDrawingInSubsequence(), "");
 }
 
 TEST_F(PaintControllerUnderInvalidationTest, MoreDrawingInSubsequence) {
-  EXPECT_DEATH(TestMoreDrawingInSubsequence(),
-               "Check failed: false. Can't find cached display item");
+  EXPECT_DEATH(TestMoreDrawingInSubsequence(), "");
 }
 
 TEST_F(PaintControllerUnderInvalidationTest, LessDrawingInSubsequence) {
   // We allow invalidated display item clients as long as they would produce the
   // same display items. The cases of changed display items are tested by other
   // test cases.
-  EXPECT_DEATH(TestLessDrawingInSubsequence(),
-               "\"\\(In cached subsequence of first\\)\" under-invalidation: "
-               "new subsequence wrong length");
+  EXPECT_DEATH(TestLessDrawingInSubsequence(), "");
 }
 
 TEST_F(PaintControllerUnderInvalidationTest, ChangeNonCacheableInSubsequence) {
-  EXPECT_DEATH(TestChangeNonCacheableInSubsequence(),
-               "\"\\(In cached subsequence of container\\)\" "
-               "under-invalidation: display item changed");
+  EXPECT_DEATH(TestChangeNonCacheableInSubsequence(), "");
 }
 
 TEST_F(PaintControllerUnderInvalidationTest, InvalidationInSubsequence) {
@@ -2329,6 +2356,11 @@
   TestInvalidationInSubsequence();
 }
 
+TEST_F(PaintControllerUnderInvalidationTest,
+       FoldCompositingDrawingInSubsequence) {
+  TestFoldCompositingDrawingInSubsequence();
+}
+
 #endif  // defined(GTEST_HAS_DEATH_TEST) && !OS(ANDROID)
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm b/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm
index e3eada5..6379d6a 100644
--- a/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm
+++ b/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm
@@ -24,7 +24,6 @@
 #include "platform/graphics/paint/PaintCanvas.h"
 #include "platform/mac/ThemeMac.h"
 #include "platform_canvas.h"
-#include "third_party/skia/include/core/SkRegion.h"
 
 namespace blink {
 
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath
index 16e16cc..f3f4661 100644
--- a/tools/android/eclipse/.classpath
+++ b/tools/android/eclipse/.classpath
@@ -122,6 +122,7 @@
     <classpathentry kind="src" path="third_party/mockito/src/src/main/java"/>
     <classpathentry kind="src" path="third_party/robolectric/robolectric/robolectric-annotations/src/main/java"/>
     <classpathentry kind="src" path="third_party/robolectric/robolectric/robolectric-resources/src/main/java"/>
+    <classpathentry kind="src" path="third_party/robolectric/robolectric/robolectric-shadows/shadows-multidex/src/main/java"/>
     <classpathentry kind="src" path="tools/android/findbugs_plugin/src"/>
     <classpathentry kind="src" path="tools/android/findbugs_plugin/test/java/src"/>
     <classpathentry kind="src" path="tools/android/memconsumer/java/src"/>
diff --git a/tools/battor_agent/BUILD.gn b/tools/battor_agent/BUILD.gn
index 065ee03..fe2ce233 100644
--- a/tools/battor_agent/BUILD.gn
+++ b/tools/battor_agent/BUILD.gn
@@ -14,6 +14,7 @@
   deps = [
     ":battor_agent_lib",
     "//base",
+    "//build/config/sanitizers:deps",
     "//build/win:default_exe_manifest",
     "//device/serial",
   ]
diff --git a/tools/bisect-builds.py b/tools/bisect-builds.py
index 442f399..2586814 100755
--- a/tools/bisect-builds.py
+++ b/tools/bisect-builds.py
@@ -1001,6 +1001,11 @@
   print ('  ' + CHANGELOG_URL % (GetGitHashFromSVNRevision(min_chromium_rev),
          GetGitHashFromSVNRevision(max_chromium_rev)))
 
+def error_internal_option(option, opt, value, parser):
+   raise optparse.OptionValueError(
+         'The -o and -r options are only\navailable in the internal version of '
+         'this script. Google\nemployees should visit http://go/bisect-builds '
+         'for\nconfiguration instructions.')
 
 def main():
   usage = ('%prog [options] [-- chromium-options]\n'
@@ -1086,6 +1091,8 @@
                     default=False,
                     help='Test the first and last revisions in the range ' +
                          'before proceeding with the bisect.')
+  parser.add_option("-r", action="callback", callback=error_internal_option)
+  parser.add_option("-o", action="callback", callback=error_internal_option)
 
   (opts, args) = parser.parse_args()
 
diff --git a/tools/gn/visual_studio_writer.cc b/tools/gn/visual_studio_writer.cc
index 76ebc562..aa01d821 100644
--- a/tools/gn/visual_studio_writer.cc
+++ b/tools/gn/visual_studio_writer.cc
@@ -37,41 +37,9 @@
 
 namespace {
 
-std::string EscapeString(const std::string& value) {
-  std::string result;
-  for (char c : value) {
-    switch (c) {
-      case '\n':
-        result += "&#10;";
-        break;
-      case '\r':
-        result += "&#13;";
-        break;
-      case '\t':
-        result += "&#9;";
-        break;
-      case '"':
-        result += "&quot;";
-        break;
-      case '<':
-        result += "&lt;";
-        break;
-      case '>':
-        result += "&gt;";
-        break;
-      case '&':
-        result += "&amp;";
-        break;
-      default:
-        result += c;
-    }
-  }
-  return result;
-}
-
 struct SemicolonSeparatedWriter {
   void operator()(const std::string& value, std::ostream& out) const {
-    out << EscapeString(value) + ';';
+    out << XmlEscape(value) + ';';
   }
 };
 
diff --git a/tools/gn/xml_element_writer.cc b/tools/gn/xml_element_writer.cc
index fcf34b28..bb0d232 100644
--- a/tools/gn/xml_element_writer.cc
+++ b/tools/gn/xml_element_writer.cc
@@ -81,3 +81,35 @@
 
   return out_;
 }
+
+std::string XmlEscape(const std::string& value) {
+  std::string result;
+  for (char c : value) {
+    switch (c) {
+      case '\n':
+        result += "&#10;";
+        break;
+      case '\r':
+        result += "&#13;";
+        break;
+      case '\t':
+        result += "&#9;";
+        break;
+      case '"':
+        result += "&quot;";
+        break;
+      case '<':
+        result += "&lt;";
+        break;
+      case '>':
+        result += "&gt;";
+        break;
+      case '&':
+        result += "&amp;";
+        break;
+      default:
+        result += c;
+    }
+  }
+  return result;
+}
diff --git a/tools/gn/xml_element_writer.h b/tools/gn/xml_element_writer.h
index 8a83df0a..01346d23 100644
--- a/tools/gn/xml_element_writer.h
+++ b/tools/gn/xml_element_writer.h
@@ -120,4 +120,6 @@
       out_, tag, attribute_name, attribute_value_writer, indent_ + 2));
 }
 
+std::string XmlEscape(const std::string& value);
+
 #endif  // TOOLS_GN_XML_ELEMENT_WRITER_H_
diff --git a/tools/gn/xml_element_writer_unittest.cc b/tools/gn/xml_element_writer_unittest.cc
index 93dfd47..cc21c4bb 100644
--- a/tools/gn/xml_element_writer_unittest.cc
+++ b/tools/gn/xml_element_writer_unittest.cc
@@ -84,3 +84,10 @@
   }
   EXPECT_EQ("<foo bar=\"baz\">Hello world!</foo>\n", out.str());
 }
+
+TEST(XmlElementWriter, TestXmlEscape) {
+  std::string input = "\r \n \t & < > \"";
+  std::string output = XmlEscape(input);
+  std::string expected = "&#13; &#10; &#9; &amp; &lt; &gt; &quot;";
+  EXPECT_EQ(expected, output);
+}
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 4b5f27c4..4ac7a30 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -92947,6 +92947,8 @@
   <int value="1168" label="NETWORKINGCASTPRIVATE_GETWIFITDLSSTATUS"/>
   <int value="1169" label="ACCESSIBILITY_PRIVATE_DARKENSCREEN"/>
   <int value="1170" label="WEBRTC_AUDIO_PRIVATE_SET_AUDIO_EXPERIMENTS"/>
+  <int value="1171" label="AUTOTESTPRIVATE_GETPLAYSTORESTATE"/>
+  <int value="1172" label="AUTOTESTPRIVATE_SETPLAYSTOREENABLED"/>
 </enum>
 
 <enum name="ExtensionIconState" type="int">
diff --git a/ui/base/template_expressions.cc b/ui/base/template_expressions.cc
index c8d49a9..14b638e 100644
--- a/ui/base/template_expressions.cc
+++ b/ui/base/template_expressions.cc
@@ -31,6 +31,9 @@
       case '"':
         out.append("\\\"");
         break;
+      case ',':
+        out.append("\\,");
+        break;
       default:
         out += c;
     }
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc
index d56eb1d..d517f07 100644
--- a/ui/keyboard/keyboard_controller.cc
+++ b/ui/keyboard/keyboard_controller.cc
@@ -411,8 +411,9 @@
 }
 
 void KeyboardController::ShowKeyboardInternal(int64_t display_id) {
-  if (!container_.get())
-    return;
+  // The container window should have been created already when
+  // |Shell::CreateKeyboard| is called.
+  DCHECK(container_.get());
 
   if (container_->children().empty()) {
     keyboard::MarkKeyboardLoadStarted();
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc
index bf3df7e..1a3ae27 100644
--- a/ui/views/bubble/bubble_frame_view.cc
+++ b/ui/views/bubble/bubble_frame_view.cc
@@ -257,7 +257,8 @@
   const int title_height = std::max(icon_height, label_height) + title_padding;
   const int close_height =
       GetWidget()->widget_delegate()->ShouldShowCloseButton()
-          ? close_->height()
+          ? close_->height() + LayoutProvider::Get()->GetDistanceMetric(
+                                   DISTANCE_CLOSE_BUTTON_MARGIN)
           : 0;
   insets += gfx::Insets(std::max(title_height, close_height), 0, 0, 0);
   return insets;
diff --git a/ui/views/bubble/bubble_frame_view_unittest.cc b/ui/views/bubble/bubble_frame_view_unittest.cc
index bf955dd..3474899 100644
--- a/ui/views/bubble/bubble_frame_view_unittest.cc
+++ b/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -145,12 +145,12 @@
   EXPECT_EQ(kArrow, frame.bubble_border()->arrow());
   EXPECT_EQ(kColor, frame.bubble_border()->background_color());
 
-  int margin_x = frame.content_margins().left();
-  int margin_y = frame.content_margins().top() +
-                 frame.GetCloseButtonForTest()->height();
-  gfx::Insets insets = frame.bubble_border()->GetInsets();
-  EXPECT_EQ(insets.left() + margin_x, frame.GetBoundsForClientView().x());
-  EXPECT_EQ(insets.top() + margin_y, frame.GetBoundsForClientView().y());
+  gfx::Insets frame_insets = frame.GetInsets();
+  gfx::Insets border_insets = frame.bubble_border()->GetInsets();
+  EXPECT_EQ(border_insets.left() + frame_insets.left(),
+            frame.GetBoundsForClientView().x());
+  EXPECT_EQ(border_insets.top() + frame_insets.top(),
+            frame.GetBoundsForClientView().y());
 }
 
 // Tests that the arrow is mirrored as needed to better fit the screen.
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
index ce75522..c77bdf4 100644
--- a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
+++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
@@ -5,7 +5,6 @@
 #import "ui/views/controls/scrollbar/cocoa_scroll_bar.h"
 
 #import "base/mac/sdk_forward_declarations.h"
-#include "cc/paint/paint_shader.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
 #include "ui/compositor/layer.h"
diff --git a/ui/views/window/dialog_delegate_unittest.cc b/ui/views/window/dialog_delegate_unittest.cc
index d11cfddd..3cfa829 100644
--- a/ui/views/window/dialog_delegate_unittest.cc
+++ b/ui/views/window/dialog_delegate_unittest.cc
@@ -28,15 +28,7 @@
 
 class TestDialog : public DialogDelegateView {
  public:
-  TestDialog()
-      : input_(new views::Textfield()),
-        canceled_(false),
-        accepted_(false),
-        closed_(false),
-        closeable_(false),
-        should_handle_escape_(false) {
-    AddChildView(input_);
-  }
+  TestDialog() : input_(new views::Textfield()) { AddChildView(input_); }
   ~TestDialog() override {}
 
   void Init() {
@@ -51,6 +43,7 @@
   bool ShouldShowWindowTitle() const override {
     return !title_.empty();
   }
+  bool ShouldShowCloseButton() const override { return show_close_button_; }
 
   // DialogDelegateView overrides:
   bool Cancel() override {
@@ -66,7 +59,6 @@
     return closeable_;
   }
 
-  // DialogDelegateView overrides:
   gfx::Size GetPreferredSize() const override { return gfx::Size(200, 200); }
   bool AcceleratorPressed(const ui::Accelerator& accelerator) override {
     return should_handle_escape_;
@@ -92,6 +84,9 @@
   }
 
   void set_title(const base::string16& title) { title_ = title; }
+  void set_show_close_button(bool show_close) {
+    show_close_button_ = show_close;
+  }
   void set_should_handle_escape(bool should_handle_escape) {
     should_handle_escape_ = should_handle_escape;
   }
@@ -100,13 +95,14 @@
 
  private:
   views::Textfield* input_;
-  bool canceled_;
-  bool accepted_;
-  bool closed_;
+  bool canceled_ = false;
+  bool accepted_ = false;
+  bool closed_ = false;
   // Prevent the dialog from closing, for repeated ok and cancel button clicks.
   bool closeable_;
   base::string16 title_;
-  bool should_handle_escape_;
+  bool show_close_button_ = true;
+  bool should_handle_escape_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(TestDialog);
 };
@@ -118,9 +114,8 @@
 
   void SetUp() override {
     ViewsTestBase::SetUp();
-    dialog_ = new TestDialog();
-    dialog_->Init();
-    DialogDelegate::CreateDialogWidget(dialog_, GetContext(), nullptr)->Show();
+    InitializeDialog();
+    ShowDialog();
   }
 
   void TearDown() override {
@@ -128,6 +123,18 @@
     ViewsTestBase::TearDown();
   }
 
+  void InitializeDialog() {
+    if (dialog_)
+      dialog_->TearDown();
+
+    dialog_ = new TestDialog();
+    dialog_->Init();
+  }
+
+  void ShowDialog() {
+    DialogDelegate::CreateDialogWidget(dialog_, GetContext(), nullptr)->Show();
+  }
+
   void SimulateKeyEvent(const ui::KeyEvent& event) {
     ui::KeyEvent event_copy = event;
     if (dialog()->GetFocusManager()->OnKeyEvent(event_copy))
@@ -208,12 +215,38 @@
     const int point;
     const int hit;
   } cases[] = {
-    { border,      HTSYSMENU },
-    { border + 10, HTSYSMENU },
-    { border + 20, HTCLIENT  },
-    { border + 50, HTCLIENT  },
-    { border + 60, HTCLIENT  },
-    { 1000,        HTNOWHERE },
+      {border, HTSYSMENU},
+      {border + 10, HTSYSMENU},
+      {border + 20, HTNOWHERE},
+      {border + 50, HTCLIENT /* Space is reserved for the close button. */},
+      {border + 60, HTCLIENT},
+      {1000, HTNOWHERE},
+  };
+
+  for (size_t i = 0; i < arraysize(cases); ++i) {
+    gfx::Point point(cases[i].point, cases[i].point);
+    EXPECT_EQ(cases[i].hit, frame->NonClientHitTest(point))
+        << " case " << i << " with border: " << border << ", at point "
+        << cases[i].point;
+  }
+}
+
+TEST_F(DialogTest, HitTest_HiddenTitleNoCloseButton) {
+  InitializeDialog();
+  dialog()->set_show_close_button(false);
+  ShowDialog();
+
+  const NonClientView* view = dialog()->GetWidget()->non_client_view();
+  BubbleFrameView* frame = static_cast<BubbleFrameView*>(view->frame_view());
+  const int border = frame->bubble_border()->GetBorderThickness();
+
+  struct {
+    const int point;
+    const int hit;
+  } cases[] = {
+      {border, HTSYSMENU},     {border + 10, HTSYSMENU},
+      {border + 20, HTCLIENT}, {border + 50, HTCLIENT},
+      {border + 60, HTCLIENT}, {1000, HTNOWHERE},
   };
 
   for (size_t i = 0; i < arraysize(cases); ++i) {