diff --git a/BUILD.gn b/BUILD.gn
index 12d323d9..cbe07a0e 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -908,7 +908,6 @@
       "//content/shell:content_shell",
       "//content/test:mojo_layouttest_bindings_js_data_deps",
       "//device/bluetooth/public/interfaces:fake_bluetooth_interfaces_js_data_deps",
-      "//device/geolocation/public/interfaces:interfaces_js_data_deps",
       "//device/usb/public/interfaces:interfaces_js_data_deps",
       "//device/vr:mojo_bindings_js_data_deps",
       "//media/capture/mojo:image_capture_js_data_deps",
diff --git a/DEPS b/DEPS
index bb38e47a..8583baf 100644
--- a/DEPS
+++ b/DEPS
@@ -79,11 +79,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '52247db04476e9c4751e84bad1bedb091785cb86',
+  'skia_revision': '3da15bb1c813d7a3c563c372fbfb3931e5b6c27c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '6785ab9c7f35a875c3a6119ab772c0e985bd9f8e',
+  'v8_revision': 'daa444e4ac13f5ab5d371ee5d796b593c1286279',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -91,7 +91,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'd66e193930ddc74f09c0ed51275f4dc564a41a02',
+  'angle_revision': '379681336ba11f33b95b337b7fa324e6336a780e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -103,7 +103,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '9b85f4ba6fdd86c488498003a2db5854d4ece036',
+  'pdfium_revision': '003e96c7c3e15afd2969d33bc91ca459bb73a3b5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -135,7 +135,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': '296e7c3a900bec6123d48cda8436a31b382d0ffe',
+  'catapult_revision': '20b4aa3deae83d8f689859aebd27601056403c82',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -333,7 +333,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0f7b2007a53d5158e42e97b938fd03f57cdf9786',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'fd4ad2416554c43f6ecd2c9c62ab5914f521c9ad',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -672,7 +672,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@5f3809d09f6b7fbafe6240188197ce3438ad44a2',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@6f8e8f899c7a39dc4031c28bc76cd358a74ee788',
     'condition': 'checkout_src_internal',
   },
 }
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index c986d862..13c7451 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//android_webview/system_webview_apk_tmpl.gni")
 import("//android_webview/webview_repack_locales.gni")
+import("//android_webview/variables.gni")
 import("//build/config/android/config.gni")
 import("//build/config/android/rules.gni")
 import("//build/config/locales.gni")
@@ -21,9 +22,6 @@
       "$target_gen_dir/system_webview_pak_whitelist.txt"
 }
 
-system_webview_android_manifest =
-    "$target_gen_dir/system_webview_apk/AndroidManifest.xml"
-
 group("android_webview") {
   if (public_android_sdk) {
     deps = [
diff --git a/android_webview/glue/BUILD.gn b/android_webview/glue/BUILD.gn
index 2d94368..a471988 100644
--- a/android_webview/glue/BUILD.gn
+++ b/android_webview/glue/BUILD.gn
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//android_webview/system_webview_apk_tmpl.gni")
+import("//android_webview/variables.gni")
 import("//build/config/android/config.gni")
 import("//build/config/android/rules.gni")
 import("generate_resource_rewriter.gni")
@@ -55,4 +57,6 @@
     "java/src/com/android/webview/chromium/WebViewDatabaseAdapter.java",
     "java/src/com/android/webview/chromium/WebViewDelegateFactory.java",
   ]
+
+  android_manifest_for_lint = system_webview_android_manifest
 }
diff --git a/android_webview/glue/glue.gni b/android_webview/glue/glue.gni
index cdc293d4..1bcaa68 100644
--- a/android_webview/glue/glue.gni
+++ b/android_webview/glue/glue.gni
@@ -8,6 +8,7 @@
   "//android_webview:android_webview_java",
   "//android_webview:android_webview_commandline_java",
   "//android_webview:android_webview_platform_services_java",
+  "//android_webview:system_webview_manifest",
   "//base:base_java",
   "//components/autofill/android:autofill_java",
   "//components/autofill/android:provider_java",
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/ServiceWorkerControllerAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/ServiceWorkerControllerAdapter.java
index 03d04d6..3f930c75 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/ServiceWorkerControllerAdapter.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/ServiceWorkerControllerAdapter.java
@@ -4,6 +4,8 @@
 
 package com.android.webview.chromium;
 
+import android.annotation.TargetApi;
+import android.os.Build;
 import android.webkit.ServiceWorkerClient;
 import android.webkit.ServiceWorkerController;
 import android.webkit.ServiceWorkerWebSettings;
@@ -14,8 +16,8 @@
  * Chromium implementation of ServiceWorkerController -- forwards calls to
  * the chromium internal implementation.
  */
+@TargetApi(Build.VERSION_CODES.N)
 public class ServiceWorkerControllerAdapter extends ServiceWorkerController {
-
     private AwServiceWorkerController mAwServiceWorkerController;
 
     public ServiceWorkerControllerAdapter(AwServiceWorkerController controller) {
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/ServiceWorkerSettingsAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/ServiceWorkerSettingsAdapter.java
index 4bb4cc57..245134b 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/ServiceWorkerSettingsAdapter.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/ServiceWorkerSettingsAdapter.java
@@ -4,6 +4,9 @@
 
 package com.android.webview.chromium;
 
+import android.annotation.TargetApi;
+import android.os.Build;
+
 import org.chromium.android_webview.AwServiceWorkerSettings;
 
 /**
@@ -11,6 +14,7 @@
  * and {@link org.chromium.android_webview.AwServiceWorkerSettings}.
  */
 @SuppressWarnings("NoSynchronizedMethodCheck")
+@TargetApi(Build.VERSION_CODES.N)
 public class ServiceWorkerSettingsAdapter extends android.webkit.ServiceWorkerWebSettings {
     private AwServiceWorkerSettings mAwServiceWorkerSettings;
 
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
index eccfbe1c..1617bea 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
@@ -776,6 +776,7 @@
     }
 
     @Override
+    @TargetApi(Build.VERSION_CODES.M)
     public void insertVisualStateCallback(
             final long requestId, final VisualStateCallback callback) {
         if (checkNeedsPost()) {
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
index 1e6ef11..ce22cbd1 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
@@ -5,6 +5,7 @@
 package com.android.webview.chromium;
 
 import android.Manifest;
+import android.annotation.TargetApi;
 import android.app.ActivityManager;
 import android.content.ComponentCallbacks2;
 import android.content.Context;
@@ -177,6 +178,7 @@
         initialize(delegate);
     }
 
+    @TargetApi(Build.VERSION_CODES.N) // For getSystemService() and isUserUnlocked().
     private void initialize(WebViewDelegate webViewDelegate) {
         mWebViewDelegate = webViewDelegate;
         Context ctx = mWebViewDelegate.getApplication().getApplicationContext();
@@ -185,6 +187,7 @@
         try {
             checkStorageIsNotDeviceProtected(mWebViewDelegate.getApplication());
         } catch (IllegalArgumentException e) {
+            assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
             if (!ctx.getSystemService(UserManager.class).isUserUnlocked()) {
                 throw e;
             }
@@ -249,7 +252,7 @@
         // Now safe to use WebView data directory.
     }
 
-    static void checkStorageIsNotDeviceProtected(Context context) {
+    /* package */ static void checkStorageIsNotDeviceProtected(Context context) {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && context.isDeviceProtectedStorage()) {
             throw new IllegalArgumentException(
                     "WebView cannot be used with device protected storage");
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
index 011159b..4d732c5 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
@@ -642,35 +642,44 @@
         }
     }
 
-    @SuppressLint({"NewApi", "Override"})
+    // TODO(ntfschr): remove @SuppressLint once lint uses 27 for targetSdk (this is needed to
+    // subclass SafeBrowsingResponse)
+    @SuppressLint({"Override"})
     @Override
+    @TargetApi(Build.VERSION_CODES.O_MR1)
     public void onSafeBrowsingHit(AwWebResourceRequest request, int threatType,
             final Callback<AwSafeBrowsingResponse> callback) {
+        // WebViewClient.onSafeBrowsingHit was added in O_MR1.
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) {
             callback.onResult(new AwSafeBrowsingResponse(SafeBrowsingAction.SHOW_INTERSTITIAL,
                     /* reporting */ true));
             return;
         }
-        mWebViewClient.onSafeBrowsingHit(mWebView, new WebResourceRequestImpl(request), threatType,
-                new SafeBrowsingResponse() {
-                    @Override
-                    public void showInterstitial(boolean allowReporting) {
-                        callback.onResult(new AwSafeBrowsingResponse(
-                                SafeBrowsingAction.SHOW_INTERSTITIAL, allowReporting));
-                    }
+        try {
+            TraceEvent.begin("WebViewContentsClientAdapter.onSafeBrowsingHit");
+            mWebViewClient.onSafeBrowsingHit(mWebView, new WebResourceRequestImpl(request),
+                    threatType, new SafeBrowsingResponse() {
+                        @Override
+                        public void showInterstitial(boolean allowReporting) {
+                            callback.onResult(new AwSafeBrowsingResponse(
+                                    SafeBrowsingAction.SHOW_INTERSTITIAL, allowReporting));
+                        }
 
-                    @Override
-                    public void proceed(boolean report) {
-                        callback.onResult(
-                                new AwSafeBrowsingResponse(SafeBrowsingAction.PROCEED, report));
-                    }
+                        @Override
+                        public void proceed(boolean report) {
+                            callback.onResult(
+                                    new AwSafeBrowsingResponse(SafeBrowsingAction.PROCEED, report));
+                        }
 
-                    @Override
-                    public void backToSafety(boolean report) {
-                        callback.onResult(new AwSafeBrowsingResponse(
-                                SafeBrowsingAction.BACK_TO_SAFETY, report));
-                    }
-                });
+                        @Override
+                        public void backToSafety(boolean report) {
+                            callback.onResult(new AwSafeBrowsingResponse(
+                                    SafeBrowsingAction.BACK_TO_SAFETY, report));
+                        }
+                    });
+        } finally {
+            TraceEvent.end("WebViewContentsClientAdapter.onRenderProcessGone");
+        }
     }
 
     @Override
diff --git a/android_webview/variables.gni b/android_webview/variables.gni
new file mode 100644
index 0000000..656c14fb
--- /dev/null
+++ b/android_webview/variables.gni
@@ -0,0 +1,6 @@
+# Copyright 2018 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.
+
+system_webview_android_manifest =
+    "$root_gen_dir/android_webview/system_webview_apk/AndroidManifest.xml"
diff --git a/ash/app_list/model/app_list_model.cc b/ash/app_list/model/app_list_model.cc
index 129442d..744dc5f5 100644
--- a/ash/app_list/model/app_list_model.cc
+++ b/ash/app_list/model/app_list_model.cc
@@ -39,7 +39,7 @@
     observer.OnAppListModelStatusChanged();
 }
 
-void AppListModel::SetState(State state) {
+void AppListModel::SetState(ash::AppListState state) {
   state_ = state;
 }
 
diff --git a/ash/app_list/model/app_list_model.h b/ash/app_list/model/app_list_model.h
index 586c37d..b18b8ec 100644
--- a/ash/app_list/model/app_list_model.h
+++ b/ash/app_list/model/app_list_model.h
@@ -15,6 +15,7 @@
 #include "ash/app_list/model/app_list_item_list_observer.h"
 #include "ash/app_list/model/app_list_model_export.h"
 #include "ash/app_list/model/app_list_view_state.h"
+#include "ash/public/interfaces/app_list.mojom.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
 
@@ -37,18 +38,6 @@
     STATUS_SYNCING,  // Syncing apps or installing synced apps.
   };
 
-  // Do not change the order of these as they are used for metrics.
-  enum State {
-    STATE_APPS = 0,
-    STATE_SEARCH_RESULTS,
-    STATE_START,
-    STATE_CUSTOM_LAUNCHER_PAGE_DEPRECATED,
-    // Add new values here.
-
-    INVALID_STATE,
-    STATE_LAST = INVALID_STATE,
-  };
-
   AppListModel();
   ~AppListModel() override;
 
@@ -57,8 +46,8 @@
 
   void SetStatus(Status status);
 
-  void SetState(State state);
-  State state() const { return state_; }
+  void SetState(ash::AppListState state);
+  ash::AppListState state() const { return state_; }
 
   // The current state of the AppListView. Controlled by AppListView.
   void SetStateFullscreen(AppListViewState state);
@@ -171,7 +160,7 @@
   std::unique_ptr<AppListItemList> top_level_item_list_;
 
   Status status_ = STATUS_NORMAL;
-  State state_ = INVALID_STATE;
+  ash::AppListState state_ = ash::AppListState::kInvalidState;
   // The AppListView state. Controlled by the AppListView.
   AppListViewState state_fullscreen_ = AppListViewState::CLOSED;
   base::ObserverList<AppListModelObserver, true> observers_;
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index 2f64e93..49e343a 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -8,6 +8,7 @@
 component("cpp") {
   sources = [
     "accessibility_types.h",
+    "app_list/app_list_types.h",
     "app_list/term_break_iterator.cc",
     "app_list/term_break_iterator.h",
     "app_list/tokenized_string.cc",
diff --git a/ash/public/cpp/app_list/OWNERS b/ash/public/cpp/app_list/OWNERS
new file mode 100644
index 0000000..730511a
--- /dev/null
+++ b/ash/public/cpp/app_list/OWNERS
@@ -0,0 +1,4 @@
+xiyuan@chromium.org
+
+per-file *_struct_traits*.*=set noparent
+per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/ash/public/cpp/app_list/app_list_struct_traits.h b/ash/public/cpp/app_list/app_list_struct_traits.h
new file mode 100644
index 0000000..809066e
--- /dev/null
+++ b/ash/public/cpp/app_list/app_list_struct_traits.h
@@ -0,0 +1,52 @@
+// Copyright 2018 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 ASH_PUBLIC_CPP_APP_LIST_APP_LIST_STRUCT_TRAITS_H_
+#define ASH_PUBLIC_CPP_APP_LIST_APP_LIST_STRUCT_TRAITS_H_
+
+#include "ash/public/cpp/app_list/app_list_types.h"
+#include "ash/public/cpp/ash_public_export.h"
+#include "ash/public/interfaces/app_list.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct EnumTraits<ash::mojom::AppListState, ash::AppListState> {
+  static ash::mojom::AppListState ToMojom(ash::AppListState input) {
+    switch (input) {
+      case ash::AppListState::kStateApps:
+        return ash::mojom::AppListState::kStateApps;
+      case ash::AppListState::kStateSearchResults:
+        return ash::mojom::AppListState::kStateSearchResults;
+      case ash::AppListState::kStateStart:
+        return ash::mojom::AppListState::kStateStart;
+      case ash::AppListState::kStateCustomLauncherPageDeprecated:
+      case ash::AppListState::kInvalidState:
+        break;
+    }
+    NOTREACHED();
+    return ash::mojom::AppListState::kStateApps;
+  }
+
+  static bool FromMojom(ash::mojom::AppListState input,
+                        ash::AppListState* out) {
+    switch (input) {
+      case ash::mojom::AppListState::kStateApps:
+        *out = ash::AppListState::kStateApps;
+        return true;
+      case ash::mojom::AppListState::kStateSearchResults:
+        *out = ash::AppListState::kStateSearchResults;
+        return true;
+      case ash::mojom::AppListState::kStateStart:
+        *out = ash::AppListState::kStateStart;
+        return true;
+    }
+    NOTREACHED();
+    return false;
+  }
+};
+
+}  // namespace mojo
+
+#endif  // ASH_PUBLIC_CPP_APP_LIST_APP_LIST_STRUCT_TRAITS_H_
diff --git a/ash/public/cpp/app_list/app_list_types.h b/ash/public/cpp/app_list/app_list_types.h
new file mode 100644
index 0000000..3563b34
--- /dev/null
+++ b/ash/public/cpp/app_list/app_list_types.h
@@ -0,0 +1,27 @@
+// Copyright 2018 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 ASH_PUBLIC_CPP_APP_LIST_APP_LIST_TYPES_H_
+#define ASH_PUBLIC_CPP_APP_LIST_APP_LIST_TYPES_H_
+
+#include "ash/public/cpp/ash_public_export.h"
+
+namespace ash {
+
+// All possible states of the app list.
+// Note: Do not change the order of these as they are used for metrics.
+enum class ASH_PUBLIC_EXPORT AppListState {
+  kStateApps = 0,
+  kStateSearchResults,
+  kStateStart,
+  kStateCustomLauncherPageDeprecated,  // Don't use over IPC
+  // Add new values here.
+
+  kInvalidState,               // Don't use over IPC
+  kStateLast = kInvalidState,  // Don't use over IPC
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_APP_LIST_APP_LIST_TYPES_H_
diff --git a/ash/public/interfaces/app_list.mojom b/ash/public/interfaces/app_list.mojom
index 066dd377..30617da 100644
--- a/ash/public/interfaces/app_list.mojom
+++ b/ash/public/interfaces/app_list.mojom
@@ -19,3 +19,9 @@
   bool is_folder;   // Whether this item is a folder.
 };
 
+// All possible states of the app list.
+enum AppListState {
+  kStateApps = 0,
+  kStateSearchResults,
+  kStateStart,
+};
diff --git a/ash/public/interfaces/app_list.typemap b/ash/public/interfaces/app_list.typemap
new file mode 100644
index 0000000..2af75bd
--- /dev/null
+++ b/ash/public/interfaces/app_list.typemap
@@ -0,0 +1,8 @@
+# Copyright 2018 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.
+
+mojom = "//ash/public/interfaces/app_list.mojom"
+public_headers = [ "//ash/public/cpp/app_list/app_list_types.h" ]
+traits_headers = [ "//ash/public/cpp/app_list/app_list_struct_traits.h" ]
+type_mappings = [ "ash.mojom.AppListState=ash::AppListState" ]
diff --git a/ash/public/interfaces/typemaps.gni b/ash/public/interfaces/typemaps.gni
index ac3500d5..41476e5 100644
--- a/ash/public/interfaces/typemaps.gni
+++ b/ash/public/interfaces/typemaps.gni
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 typemaps = [
+  "//ash/public/interfaces/app_list.typemap",
   "//ash/public/interfaces/session_controller.typemap",
   "//ash/public/interfaces/shelf.typemap",
   "//ash/public/interfaces/user_info.typemap",
diff --git a/ash/wm/overview/scoped_transform_overview_window.cc b/ash/wm/overview/scoped_transform_overview_window.cc
index 0a24953..5c9308d 100644
--- a/ash/wm/overview/scoped_transform_overview_window.cc
+++ b/ash/wm/overview/scoped_transform_overview_window.cc
@@ -8,6 +8,7 @@
 #include <memory>
 #include <vector>
 
+#include "ash/wm/overview/overview_utils.h"
 #include "ash/wm/overview/scoped_overview_animation_settings.h"
 #include "ash/wm/overview/window_selector_item.h"
 #include "ash/wm/splitview/split_view_controller.h"
@@ -21,6 +22,7 @@
 #include "ui/aura/window.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_observer.h"
+#include "ui/compositor/paint_recorder.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/safe_integer_conversions.h"
 #include "ui/gfx/transform_util.h"
@@ -37,7 +39,10 @@
 bool immediate_close_for_tests = false;
 
 // Delay closing window to allow it to shrink and fade out.
-const int kCloseWindowDelayInMilliseconds = 150;
+constexpr int kCloseWindowDelayInMilliseconds = 150;
+
+// The amount of rounding on window edges in overview mode.
+constexpr int kOverviewWindowRoundingDp = 4;
 
 aura::Window* GetTransientRoot(aura::Window* window) {
   while (window && ::wm::GetTransientParent(window))
@@ -194,6 +199,59 @@
   DISALLOW_COPY_AND_ASSIGN(LayerCachingAndFilteringObserver);
 };
 
+// WindowMask is applied to overview windows to give them rounded edges while
+// they are in overview mode.
+class ScopedTransformOverviewWindow::WindowMask : public ui::LayerDelegate {
+ public:
+  explicit WindowMask(aura::Window* window)
+      : layer_(ui::LAYER_TEXTURED), window_(window) {
+    layer_.set_delegate(this);
+    layer_.SetFillsBoundsOpaquely(false);
+  }
+
+  ~WindowMask() override { layer_.set_delegate(nullptr); }
+
+  void set_top_inset(int top_inset) { top_inset_ = top_inset; }
+  ui::Layer* layer() { return &layer_; }
+
+ private:
+  // ui::LayerDelegate:
+  void OnPaintLayer(const ui::PaintContext& context) override {
+    cc::PaintFlags flags;
+    flags.setAlpha(255);
+    flags.setAntiAlias(true);
+    flags.setStyle(cc::PaintFlags::kFill_Style);
+
+    // The amount of round applied on the mask gets scaled as |window_| gets
+    // transformed, so reverse the transform so the final scaled round matches
+    // |kOverviewWindowRoundingDp|.
+    const gfx::Vector2dF scale = window_->transform().Scale2d();
+    const SkScalar r_x =
+        SkIntToScalar(std::round(kOverviewWindowRoundingDp / scale.x()));
+    const SkScalar r_y =
+        SkIntToScalar(std::round(kOverviewWindowRoundingDp / scale.y()));
+
+    SkPath path;
+    SkScalar radii[8] = {r_x, r_y, r_x, r_y, r_x, r_y, r_x, r_y};
+    gfx::Rect bounds(layer()->size());
+    bounds.Inset(0, top_inset_, 0, 0);
+    path.addRoundRect(gfx::RectToSkRect(bounds), radii);
+
+    ui::PaintRecorder recorder(context, layer()->size());
+    recorder.canvas()->DrawPath(path, flags);
+  }
+
+  void OnDeviceScaleFactorChanged(float old_device_scale_factor,
+                                  float new_device_scale_factor) override {}
+
+  ui::Layer layer_;
+  int top_inset_ = 0;
+  // Pointer to the window of which this is a mask to.
+  aura::Window* window_;
+
+  DISALLOW_COPY_AND_ASSIGN(WindowMask);
+};
+
 ScopedTransformOverviewWindow::ScopedTransformOverviewWindow(
     WindowSelectorItem* selector_item,
     aura::Window* window)
@@ -212,6 +270,7 @@
 
   wm::GetWindowState(window_)->set_ignored_by_shelf(ignored_by_shelf_);
   if (minimized_widget_) {
+    mask_.reset();
     // TODO(oshima): Use unminimize animation instead of hiding animation.
     minimized_widget_->CloseNow();
     minimized_widget_.reset();
@@ -238,12 +297,28 @@
 void ScopedTransformOverviewWindow::BeginScopedAnimation(
     OverviewAnimationType animation_type,
     ScopedAnimationSettings* animation_settings) {
+  // Remove the mask before animating because masks affect animation
+  // performance. Observe the animation and add the mask after animating if the
+  // animation type is layouting selector items.
+  if (IsNewOverviewUi()) {
+    mask_.reset();
+    if (window_->GetProperty(aura::client::kShowStateKey) !=
+        ui::SHOW_STATE_MINIMIZED) {
+      window_->layer()->SetMaskLayer(original_mask_layer_);
+    }
+  }
   for (auto* window : GetTransientTreeIterator(GetOverviewWindow())) {
     auto settings = std::make_unique<ScopedOverviewAnimationSettings>(
         animation_type, window);
     settings->DeferPaint();
     animation_settings->push_back(std::move(settings));
   }
+
+  if (IsNewOverviewUi() &&
+      animation_type == OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS) {
+    if (animation_settings->size() > 0u)
+      animation_settings->front()->AddObserver(this);
+  }
 }
 
 bool ScopedTransformOverviewWindow::Contains(const aura::Window* target) const {
@@ -439,6 +514,7 @@
       ui::SHOW_STATE_MINIMIZED) {
     CreateMirrorWindowForMinimizedState();
   }
+
   // Add requests to cache render surface and perform trilinear filtering. The
   // requests will be removed in dctor. So the requests will be valid during the
   // enter animation and the whole time during overview mode. For the exit
@@ -528,6 +604,19 @@
   }
 }
 
+void ScopedTransformOverviewWindow::OnImplicitAnimationsCompleted() {
+  // Add the mask which gives the window selector items rounded corners.
+  ui::Layer* layer = minimized_widget_
+                         ? minimized_widget_->GetContentsView()->layer()
+                         : window_->layer();
+  if (!minimized_widget_)
+    original_mask_layer_ = window_->layer()->layer_mask_layer();
+  mask_ = std::make_unique<WindowMask>(GetOverviewWindow());
+  mask_->layer()->SetBounds(layer->bounds());
+  mask_->set_top_inset(GetTopInset());
+  layer->SetMaskLayer(mask_->layer());
+}
+
 aura::Window*
 ScopedTransformOverviewWindow::GetOverviewWindowForMinimizedState() const {
   return minimized_widget_ ? minimized_widget_->GetNativeWindow() : nullptr;
diff --git a/ash/wm/overview/scoped_transform_overview_window.h b/ash/wm/overview/scoped_transform_overview_window.h
index 9458a38..0b67117 100644
--- a/ash/wm/overview/scoped_transform_overview_window.h
+++ b/ash/wm/overview/scoped_transform_overview_window.h
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/compositor/layer_animation_observer.h"
 #include "ui/events/event_handler.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/transform.h"
@@ -25,6 +26,10 @@
 class Rect;
 }
 
+namespace ui {
+class Layer;
+}
+
 namespace views {
 class Widget;
 }
@@ -42,7 +47,9 @@
 // class allows transforming the windows with a helper to determine the best
 // fit in certain bounds. The window's state is restored when this object is
 // destroyed.
-class ASH_EXPORT ScopedTransformOverviewWindow : public ui::EventHandler {
+class ASH_EXPORT ScopedTransformOverviewWindow
+    : public ui::EventHandler,
+      public ui::ImplicitAnimationObserver {
  public:
   class OverviewContentMask;
   using ShapeRects = std::vector<gfx::Rect>;
@@ -152,9 +159,13 @@
   void OnGestureEvent(ui::GestureEvent* event) override;
   void OnMouseEvent(ui::MouseEvent* event) override;
 
+  // ui::ImplicitAnimationObserver:
+  void OnImplicitAnimationsCompleted() override;
+
  private:
   friend class WindowSelectorTest;
   class LayerCachingAndFilteringObserver;
+  class WindowMask;
 
   // Closes the window managed by |this|.
   void CloseWidget();
@@ -191,6 +202,13 @@
   std::vector<std::unique_ptr<LayerCachingAndFilteringObserver>>
       cached_and_filtered_layer_observers_;
 
+  // A mask to be applied on |window_|. This will give |window_| rounded edges
+  // while in overview.
+  std::unique_ptr<WindowMask> mask_;
+
+  // The original mask layer of the window before entering overview mode.
+  ui::Layer* original_mask_layer_ = nullptr;
+
   ::wm::ShadowElevation original_shadow_elevation_;
 
   base::WeakPtrFactory<ScopedTransformOverviewWindow> weak_ptr_factory_;
diff --git a/base/path_service_unittest.cc b/base/path_service_unittest.cc
index 9b81aee..b86b63d0 100644
--- a/base/path_service_unittest.cc
+++ b/base/path_service_unittest.cc
@@ -86,8 +86,8 @@
     if (key == DIR_USER_DESKTOP)
       continue;  // iOS doesn't implement DIR_USER_DESKTOP.
 #elif defined(OS_FUCHSIA)
-    if (key == DIR_USER_DESKTOP)
-      continue;  // Fuchsia doesn't implement DIR_USER_DESKTOP.
+    if (key == DIR_USER_DESKTOP || key == FILE_MODULE)
+      continue;  // Fuchsia doesn't implement DIR_USER_DESKTOP or FILE_MODULE.
 #endif
     EXPECT_PRED1(ReturnsValidPath, key);
   }
diff --git a/base/profiler/stack_sampling_profiler.cc b/base/profiler/stack_sampling_profiler.cc
index 35e60581..86e7dd0 100644
--- a/base/profiler/stack_sampling_profiler.cc
+++ b/base/profiler/stack_sampling_profiler.cc
@@ -29,6 +29,12 @@
 
 namespace {
 
+// This value is used to initialize the WaitableEvent object. This MUST BE set
+// to MANUAL for correct operation of the IsSignaled() call in Start(). See the
+// comment there for why.
+constexpr WaitableEvent::ResetPolicy kResetPolicy =
+    WaitableEvent::ResetPolicy::MANUAL;
+
 // This value is used when there is no collection in progress and thus no ID
 // for referencing the active collection to the SamplingThread.
 const int NULL_PROFILER_ID = -1;
@@ -779,8 +785,7 @@
       completed_callback_(callback),
       // The event starts "signaled" so code knows it's safe to start thread
       // and "manual" so that it can be waited in multiple places.
-      profiling_inactive_(WaitableEvent::ResetPolicy::MANUAL,
-                          WaitableEvent::InitialState::SIGNALED),
+      profiling_inactive_(kResetPolicy, WaitableEvent::InitialState::SIGNALED),
       profiler_id_(NULL_PROFILER_ID),
       test_delegate_(test_delegate) {}
 
@@ -814,8 +819,16 @@
   if (!native_sampler)
     return;
 
-  // Wait for profiling to be "inactive", then reset it for the upcoming run.
-  profiling_inactive_.Wait();
+  // The IsSignaled() check below requires that the WaitableEvent be manually
+  // reset, to avoid signaling the event in IsSignaled() itself.
+  static_assert(kResetPolicy == WaitableEvent::ResetPolicy::MANUAL,
+                "The reset policy must be set to MANUAL");
+
+  // If a previous profiling phase is still winding down, wait for it to
+  // complete. We can't use task posting for this coordination because the
+  // thread owning the profiler may not have a message loop.
+  if (!profiling_inactive_.IsSignaled())
+    profiling_inactive_.Wait();
   profiling_inactive_.Reset();
 
   DCHECK_EQ(NULL_PROFILER_ID, profiler_id_);
diff --git a/base/profiler/stack_sampling_profiler.h b/base/profiler/stack_sampling_profiler.h
index c2c89dd..c0493cf 100644
--- a/base/profiler/stack_sampling_profiler.h
+++ b/base/profiler/stack_sampling_profiler.h
@@ -254,7 +254,9 @@
   // but not already finished.
   ~StackSamplingProfiler();
 
-  // Initializes the profiler and starts sampling.
+  // Initializes the profiler and starts sampling. Might block on a
+  // WaitableEvent if this StackSamplingProfiler was previously started and
+  // recently stopped, while the previous profiling phase winds down.
   void Start();
 
   // Stops the profiler and any ongoing sampling. This method will return
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py
index 46e9ec3..58ba2ed4 100755
--- a/build/android/gyp/javac.py
+++ b/build/android/gyp/javac.py
@@ -65,6 +65,8 @@
   # Alias of ParameterName warning.
   'NamedParameters',
   # Low priority corner cases with String.split.
+  # Linking Guava and using Splitter was rejected
+  # in the https://chromium-review.googlesource.com/c/chromium/src/+/871630.
   'StringSplitter',
   # Preferred to use another method since it propagates exceptions better.
   'ClassNewInstance',
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index bbaa4b5..909949e 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -44,9 +44,7 @@
   # This is the result of profiling Chromium. Blindly applying it to arbitrary
   # downstream projects and hoping it'll grant a speedup seems fragile. (Not
   # to mention that it resides in a Chromium-specific directory.)
-  # FIXME(gbiv): remove the !defined() check after removing custom profiling
-  # logic from //clank.
-  if (!defined(clang_default_afdo_profile) && build_with_chromium) {
+  if (build_with_chromium) {
     clang_default_afdo_profile =
         rebase_path("//chrome/android/profiles/afdo.prof")
   }
diff --git a/chrome/VERSION b/chrome/VERSION
index 8df5c0c..70f0ce5 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=66
 MINOR=0
-BUILD=3330
+BUILD=3331
 PATCH=0
diff --git a/chrome/android/java/res/xml/file_paths.xml b/chrome/android/java/res/xml/file_paths.xml
index 458f4a40..fbe8d24 100644
--- a/chrome/android/java/res/xml/file_paths.xml
+++ b/chrome/android/java/res/xml/file_paths.xml
@@ -9,6 +9,7 @@
 <paths xmlns:android="http://schemas.android.com/apk/res/android">
     <files-path name="images" path="images/"/>
     <cache-path name="cache" path="net-export/"/>
+    <cache-path name="passwords" path="passwords/"/>
     <cache-path name="webapk" path="webapks/" />
     <cache-path name="offline-cache" path="Offline Pages/archives/" />
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
index ef3c248..5cd5768 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
@@ -17,6 +17,7 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.blink.mojom.MediaSessionAction;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.favicon.LargeIconBridge;
 import org.chromium.chrome.browser.metrics.MediaNotificationUma;
 import org.chromium.chrome.browser.metrics.MediaSessionUMA;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
@@ -153,6 +154,7 @@
         mHandler.postDelayed(mHideNotificationDelayedTask, HIDE_NOTIFICATION_DELAY_MILLIS);
 
         mNotificationInfoBuilder = null;
+        mFavicon = null;
     }
 
     private void hideNotificationImmediately() {
@@ -286,9 +288,11 @@
         public void onFaviconUpdated(Tab tab, Bitmap icon) {
             assert tab == mTab;
 
+            // Store the favicon only if notification is being shown. Otherwise the favicon is
+            // obtained from large icon bridge when needed.
+            if (isNotificationHiddingOrHidden() || mPageMediaImage != null) return;
             if (!updateFavicon(icon)) return;
-
-            updateNotificationImage();
+            updateNotificationImage(mFavicon);
         }
 
         @Override
@@ -495,11 +499,11 @@
     @Override
     public void onImageDownloaded(Bitmap image) {
         mPageMediaImage = MediaNotificationManager.downscaleIconToIdealSize(image);
-        updateNotificationImage();
+        mFavicon = null;
+        updateNotificationImage(mPageMediaImage);
     }
 
-    private void updateNotificationImage() {
-        Bitmap newMediaImage = getNotificationImage();
+    private void updateNotificationImage(Bitmap newMediaImage) {
         if (mCurrentMediaImage == newMediaImage) return;
 
         mCurrentMediaImage = newMediaImage;
@@ -511,7 +515,31 @@
     }
 
     private Bitmap getNotificationImage() {
-        return (mPageMediaImage != null) ? mPageMediaImage : mFavicon;
+        if (mPageMediaImage != null) return mPageMediaImage;
+        if (mFavicon != null) return mFavicon;
+
+        // Fetch favicon image and update the notification when available.
+        if (mTab == null) return null;
+        WebContents webContents = mTab.getWebContents();
+        if (webContents == null) return null;
+        String pageUrl = webContents.getLastCommittedUrl();
+        int size = MediaNotificationManager.MINIMAL_MEDIA_IMAGE_SIZE_PX;
+        if (mTab.getProfile() == null) return null;
+        LargeIconBridge bridge = new LargeIconBridge(mTab.getProfile());
+        LargeIconBridge.LargeIconCallback callback = new LargeIconBridge.LargeIconCallback() {
+            @Override
+            public void onLargeIconAvailable(
+                    Bitmap icon, int fallbackColor, boolean isFallbackColorDefault, int iconType) {
+                if (isNotificationHiddingOrHidden() || mPageMediaImage != null) return;
+                if (updateFavicon(icon)) {
+                    updateNotificationImage(mFavicon);
+                }
+                bridge.destroy();
+            }
+        };
+        if (!bridge.getLargeIconForUrl(pageUrl, size, callback)) bridge.destroy();
+
+        return null;
     }
 
     private boolean isNotificationHiddingOrHidden() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationConstants.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationConstants.java
index c45de4b..09a65858 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationConstants.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationConstants.java
@@ -35,7 +35,6 @@
     static final String EXTRA_NOTIFICATION_INFO_PROFILE_ID = "notification_info_profile_id";
     static final String EXTRA_NOTIFICATION_INFO_PROFILE_INCOGNITO =
             "notification_info_profile_incognito";
-    static final String EXTRA_NOTIFICATION_INFO_TAG = "notification_info_tag";
     static final String EXTRA_NOTIFICATION_INFO_ACTION_INDEX = "notification_info_action_index";
     static final String EXTRA_NOTIFICATION_INFO_WEBAPK_PACKAGE = "notification_info_webapk_package";
     static final String EXTRA_NOTIFICATION_REPLY = "notification_reply";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java
index 61b0917..f3b153b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java
@@ -32,8 +32,6 @@
         bundle.putBoolean(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_INCOGNITO,
                 intent.getBooleanExtra(
                         NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_INCOGNITO, false));
-        bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_TAG,
-                intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_TAG));
         bundle.putInt(NotificationConstants.EXTRA_NOTIFICATION_INFO_ACTION_INDEX,
                 intent.getIntExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ACTION_INDEX, -1));
         bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_WEBAPK_PACKAGE,
@@ -61,8 +59,7 @@
         PersistableBundle extras = params.getExtras();
         putJobStartedTimeInExtras(extras);
         if (!extras.containsKey(NotificationConstants.EXTRA_NOTIFICATION_ID)
-                || !extras.containsKey(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN)
-                || !extras.containsKey(NotificationConstants.EXTRA_NOTIFICATION_INFO_TAG)) {
+                || !extras.containsKey(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN)) {
             return false;
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
index de56332..4717ee79 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
@@ -173,7 +173,6 @@
                 intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID);
         boolean incognito = intent.getBooleanExtra(
                 NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_INCOGNITO, false);
-        String tag = intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_TAG);
 
         Log.i(TAG, "Dispatching notification event to native: " + notificationId);
 
@@ -186,14 +185,14 @@
             int actionIndex = intent.getIntExtra(
                     NotificationConstants.EXTRA_NOTIFICATION_INFO_ACTION_INDEX, -1);
             sInstance.onNotificationClicked(notificationId, origin, scopeUrl, profileId, incognito,
-                    tag, webApkPackage, actionIndex, getNotificationReply(intent));
+                    webApkPackage, actionIndex, getNotificationReply(intent));
             return true;
         } else if (NotificationConstants.ACTION_CLOSE_NOTIFICATION.equals(intent.getAction())) {
             // Notification deleteIntent is executed only "when the notification is explicitly
             // dismissed by the user, either with the 'Clear All' button or by swiping it away
             // individually" (though a third-party NotificationListenerService may also trigger it).
             sInstance.onNotificationClosed(
-                    notificationId, origin, profileId, incognito, tag, true /* byUser */);
+                    notificationId, origin, profileId, incognito, true /* byUser */);
             return true;
         }
 
@@ -325,14 +324,13 @@
      *                 comes from.
      * @param profileId Id of the profile to which the notification belongs.
      * @param incognito Whether the profile was in incognito mode.
-     * @param tag The tag of the notification. May be NULL.
      * @param webApkPackage The package of the WebAPK associated with the notification. Empty if
      *        the notification is not associated with a WebAPK.
      * @param actionIndex The zero-based index of the action button, or -1 if not applicable.
      */
     private PendingIntent makePendingIntent(Context context, String action, String notificationId,
             String origin, String scopeUrl, String profileId, boolean incognito,
-            @Nullable String tag, String webApkPackage, int actionIndex) {
+            String webApkPackage, int actionIndex) {
         Uri intentData = makeIntentData(notificationId, origin, actionIndex);
         Intent intent = new Intent(action, intentData);
         intent.setClass(context, NotificationService.Receiver.class);
@@ -341,7 +339,6 @@
         intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_SCOPE, scopeUrl);
         intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID, profileId);
         intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_INCOGNITO, incognito);
-        intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_TAG, tag);
         intent.putExtra(
                 NotificationConstants.EXTRA_NOTIFICATION_INFO_WEBAPK_PACKAGE, webApkPackage);
         intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ACTION_INDEX, actionIndex);
@@ -477,10 +474,6 @@
      *                 comes from.
      * @param profileId Id of the profile that showed the notification.
      * @param incognito if the session of the profile is an off the record one.
-     * @param tag A string identifier for this notification. If the tag is not empty, the new
-     *            notification will replace the previous notification with the same tag and origin,
-     *            if present. If no matching previous notification is present, the new one will just
-     *            be added.
      * @param title Title to be displayed in the notification.
      * @param body Message to be displayed in the notification. Will be trimmed to one line of
      *             text by the Android notification system.
@@ -501,10 +494,9 @@
     @CalledByNative
     private void displayNotification(final String notificationId, final String origin,
             final String scopeUrl, final String profileId, final boolean incognito,
-            final String tag, final String title, final String body, final Bitmap image,
-            final Bitmap icon, final Bitmap badge, final int[] vibrationPattern,
-            final long timestamp, final boolean renotify, final boolean silent,
-            final ActionInfo[] actions) {
+            final String title, final String body, final Bitmap image, final Bitmap icon,
+            final Bitmap badge, final int[] vibrationPattern, final long timestamp,
+            final boolean renotify, final boolean silent, final ActionInfo[] actions) {
         final String webApkPackage =
                 WebApkValidator.queryWebApkPackage(ContextUtils.getApplicationContext(), scopeUrl);
         if (webApkPackage != null) {
@@ -513,8 +505,8 @@
                         @Override
                         public void onChecked(boolean doesBrowserBackWebApk) {
                             displayNotificationInternal(notificationId, origin, scopeUrl, profileId,
-                                    incognito, tag, title, body, image, icon, badge,
-                                    vibrationPattern, timestamp, renotify, silent, actions,
+                                    incognito, title, body, image, icon, badge, vibrationPattern,
+                                    timestamp, renotify, silent, actions,
                                     doesBrowserBackWebApk ? webApkPackage : "");
                         }
                     };
@@ -522,16 +514,16 @@
             return;
         }
 
-        displayNotificationInternal(notificationId, origin, scopeUrl, profileId, incognito, tag,
-                title, body, image, icon, badge, vibrationPattern, timestamp, renotify, silent,
-                actions, "");
+        displayNotificationInternal(notificationId, origin, scopeUrl, profileId, incognito, title,
+                body, image, icon, badge, vibrationPattern, timestamp, renotify, silent, actions,
+                "");
     }
 
     /** Called after querying whether the browser backs the given WebAPK. */
     private void displayNotificationInternal(String notificationId, String origin, String scopeUrl,
-            String profileId, boolean incognito, String tag, String title, String body,
-            Bitmap image, Bitmap icon, Bitmap badge, int[] vibrationPattern, long timestamp,
-            boolean renotify, boolean silent, ActionInfo[] actions, String webApkPackage) {
+            String profileId, boolean incognito, String title, String body, Bitmap image,
+            Bitmap icon, Bitmap badge, int[] vibrationPattern, long timestamp, boolean renotify,
+            boolean silent, ActionInfo[] actions, String webApkPackage) {
         nativeStoreCachedWebApkPackageForNotificationId(
                 mNativeNotificationPlatformBridge, notificationId, webApkPackage);
 
@@ -545,10 +537,10 @@
 
         PendingIntent clickIntent = makePendingIntent(context,
                 NotificationConstants.ACTION_CLICK_NOTIFICATION, notificationId, origin, scopeUrl,
-                profileId, incognito, tag, webApkPackage, -1 /* actionIndex */);
+                profileId, incognito, webApkPackage, -1 /* actionIndex */);
         PendingIntent closeIntent = makePendingIntent(context,
                 NotificationConstants.ACTION_CLOSE_NOTIFICATION, notificationId, origin, scopeUrl,
-                profileId, incognito, tag, webApkPackage, -1 /* actionIndex */);
+                profileId, incognito, webApkPackage, -1 /* actionIndex */);
 
         boolean hasImage = image != null;
         boolean forWebApk = !webApkPackage.isEmpty();
@@ -581,7 +573,7 @@
         for (int actionIndex = 0; actionIndex < actions.length; actionIndex++) {
             PendingIntent intent = makePendingIntent(context,
                     NotificationConstants.ACTION_CLICK_NOTIFICATION, notificationId, origin,
-                    scopeUrl, profileId, incognito, tag, webApkPackage, actionIndex);
+                    scopeUrl, profileId, incognito, webApkPackage, actionIndex);
             ActionInfo action = actions[actionIndex];
             // Don't show action button icons when there's an image, as then action buttons go on
             // the same row as the Site Settings button, so icons wouldn't leave room for text.
@@ -778,7 +770,6 @@
      *                 comes from.
      * @param profileId Id of the profile that showed the notification.
      * @param incognito if the profile session was an off the record one.
-     * @param tag The tag of the notification. May be NULL.
      * @param webApkPackage The package of the WebAPK associated with the notification.
      *                      Empty if the notification is not associated with a WebAPK.
      * @param actionIndex The index of the action button that was clicked, or -1 if not applicable.
@@ -786,11 +777,11 @@
      *              on a text action or if inline replies are not supported.
      */
     private void onNotificationClicked(String notificationId, String origin, String scopeUrl,
-            String profileId, boolean incognito, String tag, String webApkPackage, int actionIndex,
+            String profileId, boolean incognito, String webApkPackage, int actionIndex,
             @Nullable String reply) {
         mLastNotificationClickMs = System.currentTimeMillis();
         nativeOnNotificationClicked(mNativeNotificationPlatformBridge, notificationId, origin,
-                scopeUrl, profileId, incognito, tag, webApkPackage, actionIndex, reply);
+                scopeUrl, profileId, incognito, webApkPackage, actionIndex, reply);
     }
 
     /**
@@ -801,22 +792,21 @@
      * @param origin The origin of the notification.
      * @param profileId Id of the profile that showed the notification.
      * @param incognito if the profile session was an off the record one.
-     * @param tag The tag of the notification. May be NULL.
      * @param byUser Whether the notification was closed by a user gesture.
      */
     private void onNotificationClosed(String notificationId, String origin, String profileId,
-            boolean incognito, String tag, boolean byUser) {
+            boolean incognito, boolean byUser) {
         nativeOnNotificationClosed(mNativeNotificationPlatformBridge, notificationId, origin,
-                profileId, incognito, tag, byUser);
+                profileId, incognito, byUser);
     }
 
     private static native void nativeInitializeNotificationPlatformBridge();
 
     private native void nativeOnNotificationClicked(long nativeNotificationPlatformBridgeAndroid,
             String notificationId, String origin, String scopeUrl, String profileId,
-            boolean incognito, String tag, String webApkPackage, int actionIndex, String reply);
+            boolean incognito, String webApkPackage, int actionIndex, String reply);
     private native void nativeOnNotificationClosed(long nativeNotificationPlatformBridgeAndroid,
-            String notificationId, String origin, String profileId, boolean incognito, String tag,
+            String notificationId, String origin, String profileId, boolean incognito,
             boolean byUser);
     private native void nativeStoreCachedWebApkPackageForNotificationId(
             long nativeNotificationPlatformBridgeAndroid, String notificationId,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java
index 3e614aa6..61e2840 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java
@@ -86,8 +86,7 @@
     @Override
     public void onHandleIntent(final Intent intent) {
         if (!intent.hasExtra(NotificationConstants.EXTRA_NOTIFICATION_ID)
-                || !intent.hasExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN)
-                || !intent.hasExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_TAG)) {
+                || !intent.hasExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN)) {
             return;
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java
index 3699689..4c7f58c6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java
@@ -4,17 +4,21 @@
 
 package org.chromium.chrome.browser.preferences.password;
 
+import android.content.ActivityNotFoundException;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.preference.Preference;
 import android.preference.Preference.OnPreferenceChangeListener;
 import android.preference.PreferenceCategory;
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceScreen;
+import android.support.annotation.Nullable;
 import android.support.v7.app.AlertDialog;
 import android.text.SpannableString;
+import android.text.TextUtils;
 import android.text.style.ForegroundColorSpan;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -22,6 +26,8 @@
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.Callback;
+import org.chromium.base.ContentUriUtils;
+import org.chromium.base.ContextUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreference;
@@ -35,6 +41,13 @@
 import org.chromium.ui.text.SpanApplier;
 import org.chromium.ui.widget.Toast;
 
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+
 /**
  * The "Save passwords" screen in Settings, which allows the user to enable or disable password
  * saving, to view saved passwords (just the username and URL), and to delete saved passwords.
@@ -53,6 +66,9 @@
     // The key for saving |mExportRequested| to instance bundle.
     private static final String SAVED_STATE_EXPORT_REQUESTED = "saved-state-export-requested";
 
+    // The key for saving |mExportFileUri| to instance bundle.
+    private static final String SAVED_STATE_EXPORT_FILE_URI = "saved-state-export-file-uri";
+
     public static final String PREF_SAVE_PASSWORDS_SWITCH = "save_passwords_switch";
     public static final String PREF_AUTOSIGNIN_SWITCH = "autosignin_switch";
 
@@ -64,6 +80,9 @@
     // Name of the feature controlling the password export functionality.
     private static final String EXPORT_PASSWORDS = "PasswordExport";
 
+    // Name of the subdirectory in cache which stores the exported passwords file.
+    private static final String PASSWORDS_CACHE_DIR = "/passwords";
+
     private static final int ORDER_SWITCH = 0;
     private static final int ORDER_AUTO_SIGNIN_CHECKBOX = 1;
     private static final int ORDER_MANAGE_ACCOUNT_LINK = 2;
@@ -79,6 +98,16 @@
     // True if the option to export passwords in the three-dots menu should be disabled due to an
     // ongoing export.
     private boolean mExportOptionSuspended = false;
+    // True if the user just finished the UI flow for confirming a password export.
+    private boolean mExportConfirmed;
+    // When the user requests that passwords are exported and once the passwords are sent over from
+    // native code and stored in a cache file, this variable contains the content:// URI for that
+    // cache file, or an empty URI if there was a problem with storing to that file. During all
+    // other times, this variable is null. In particular, after the export is requested, the
+    // variable being null means that the passwords have not arrived from the native code yet.
+    @Nullable
+    private Uri mExportFileUri;
+
     private Preference mLinkPref;
     private ChromeSwitchPreference mSavePasswordsSwitch;
     private ChromeBaseCheckBoxPreference mAutoSignInSwitch;
@@ -94,11 +123,21 @@
                 && ReauthenticationManager.isReauthenticationApiAvailable()) {
             setHasOptionsMenu(true);
         }
-        if (savedInstanceState != null
-                && savedInstanceState.containsKey(SAVED_STATE_EXPORT_REQUESTED)) {
+
+        if (savedInstanceState == null) return;
+
+        if (savedInstanceState.containsKey(SAVED_STATE_EXPORT_REQUESTED)) {
             mExportRequested =
                     savedInstanceState.getBoolean(SAVED_STATE_EXPORT_REQUESTED, mExportRequested);
         }
+        if (savedInstanceState.containsKey(SAVED_STATE_EXPORT_FILE_URI)) {
+            String uriString = savedInstanceState.getString(SAVED_STATE_EXPORT_FILE_URI);
+            if (uriString.isEmpty()) {
+                mExportFileUri = Uri.EMPTY;
+            } else {
+                mExportFileUri = Uri.parse(uriString);
+            }
+        }
     }
 
     @Override
@@ -114,6 +153,55 @@
         super.onPrepareOptionsMenu(menu);
     }
 
+    // An encapsulation of a URI and an error string, used by the processing in
+    // exportPasswordsIntoFile.
+    private static class ExportResult {
+        public final Uri mUri;
+        @Nullable
+        public final String mError;
+
+        // Constructs the successful result: a valid URI and no error.
+        public ExportResult(Uri uri) {
+            assert uri != null && uri != Uri.EMPTY;
+            mUri = uri;
+            mError = null;
+        }
+
+        // Constructs the failed result: an empty URI and a non-empty error string.
+        public ExportResult(String error) {
+            assert !TextUtils.isEmpty(error);
+            mUri = Uri.EMPTY;
+            mError = error;
+        }
+    }
+
+    /**
+     * A helper method which first fires an AsyncTask to turn the string with serialized passwords
+     * into a cache file with a shareable URI, and then, depending on success, either calls the code
+     * for firing the share intent or displays an error.
+     * @param serializedPasswords A string with a CSV representation of the user's passwords.
+     */
+    private void shareSerializedPasswords(String serializedPasswords) {
+        AsyncTask<String, Void, ExportResult> task = new AsyncTask<String, Void, ExportResult>() {
+            @Override
+            protected ExportResult doInBackground(String... serializedPasswords) {
+                assert serializedPasswords.length == 1;
+                return exportPasswordsIntoFile(serializedPasswords[0]);
+            }
+
+            @Override
+            protected void onPostExecute(ExportResult result) {
+                if (result.mError != null) {
+                    showExportErrorAndAbort(result.mError);
+                } else {
+                    mExportFileUri = result.mUri;
+                    tryExporting();
+                }
+            }
+        };
+        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, serializedPasswords);
+    }
+
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         int id = item.getItemId();
@@ -130,13 +218,7 @@
                     .serializePasswords(new Callback<String>() {
                         @Override
                         public void onResult(String serializedPasswords) {
-                            // TODO(crbug.com/788701): Ensure that the SavePasswordsPreferences is
-                            // not dead before trying to use any of its data members.
-                            // TODO(crbug.com/788701): Ensure that the passwords are stored to a
-                            // file here and its URI in saved-state-bundle in case the reauth
-                            // dialogue causes this activity to be killed.
-                            // TODO(crbug.com/788701): Synchronise with end of the UI flow and pass
-                            // the data.
+                            shareSerializedPasswords(serializedPasswords);
                         }
                     });
             if (!ReauthenticationManager.isScreenLockSetUp(getActivity().getApplicationContext())) {
@@ -166,7 +248,8 @@
             @Override
             public void onClick(DialogInterface dialog, int which) {
                 if (which == AlertDialog.BUTTON_POSITIVE) {
-                    exportAfterWarning();
+                    mExportConfirmed = true;
+                    tryExporting();
                 }
                 // Re-enable exporting, the current one was either finished or dismissed.
                 mExportOptionSuspended = false;
@@ -175,9 +258,87 @@
         exportWarningDialogFragment.show(getFragmentManager(), null);
     }
 
-    private void exportAfterWarning() {
-        // TODO(crbug.com/788701): Synchronise with obtaining serialised passwords and pass them to
-        // the intent.
+    /**
+     * Starts the exporting intent if both blocking events are completed: serializing and the
+     * confirmation flow.
+     */
+    private void tryExporting() {
+        // TODO(crbug.com/788701): Display a progress indicator if user
+        // confirmed but serialising is not done yet and dismiss it once called
+        // again with serialising done.
+        if (mExportConfirmed && mExportFileUri != null) sendExportIntent();
+    }
+
+    /**
+     * Call this to abort the export UI flow and display an error description to the user.
+     * @param description A string with a brief explanation of the error.
+     */
+    private void showExportErrorAndAbort(String description) {
+        // TODO(crbug.com/788701): Implement.
+        // Re-enable exporting, the current one was just cancelled.
+        mExportOptionSuspended = false;
+    }
+
+    /**
+     * This method saves the contents of |serializedPasswords| into a temporary file and returns a
+     * sharing URI for it. In case of failure, returns EMPTY. It should only be run on the
+     * background thread of an AsyncTask, because it does I/O operations.
+     * @param serializedPasswords A string with serialized passwords in CSV format
+     */
+    private ExportResult exportPasswordsIntoFile(String serializedPasswords) {
+        // First ensure that the PASSWORDS_CACHE_DIR cache directory exists.
+        File passwordsDir =
+                new File(ContextUtils.getApplicationContext().getCacheDir() + PASSWORDS_CACHE_DIR);
+        passwordsDir.mkdir();
+        // Now create or overwrite the temporary file for exported passwords there and return its
+        // content:// URI.
+        File tempFile;
+        try {
+            tempFile = File.createTempFile("pwd-export", ".csv", passwordsDir);
+        } catch (IOException e) {
+            // TODO(crbug.com/788701): Change e.getMessage to an appropriate error, following the
+            // mocks.
+            return new ExportResult(e.getMessage());
+        }
+        tempFile.deleteOnExit();
+        try (BufferedWriter tempWriter = new BufferedWriter(new OutputStreamWriter(
+                     new FileOutputStream(tempFile), StandardCharsets.UTF_8))) {
+            tempWriter.write(serializedPasswords);
+        } catch (IOException e) {
+            // TODO(crbug.com/788701): Change e.getMessage to an appropriate error, following the
+            // mocks.
+            return new ExportResult(e.getMessage());
+        }
+        try {
+            return new ExportResult(ContentUriUtils.getContentUriFromFile(tempFile));
+        } catch (IllegalArgumentException e) {
+            // TODO(crbug.com/788701): Display an error, because the result of Uri.fromFile is not
+            // going to be shareable.
+            return new ExportResult(e.getMessage());
+        }
+    }
+
+    /**
+     * If the URI of the file with exported passwords is not null, passes it into an implicit
+     * intent, so that the user can use a storage app to save the exported passwords.
+     */
+    private void sendExportIntent() {
+        mExportConfirmed = false;
+        if (mExportFileUri == Uri.EMPTY) return;
+
+        Intent send = new Intent(Intent.ACTION_SEND);
+        send.setType("text/csv");
+        send.putExtra(Intent.EXTRA_STREAM, mExportFileUri);
+
+        try {
+            Intent chooser = Intent.createChooser(send, null);
+            chooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            ContextUtils.getApplicationContext().startActivity(chooser);
+        } catch (ActivityNotFoundException e) {
+            // TODO(crbug.com/788701): If no app handles it, display the appropriate error.
+            showExportErrorAndAbort(e.getMessage());
+        }
+        mExportFileUri = null;
     }
 
     /**
@@ -321,6 +482,9 @@
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
         outState.putBoolean(SAVED_STATE_EXPORT_REQUESTED, mExportRequested);
+        if (mExportFileUri != null) {
+            outState.putString(SAVED_STATE_EXPORT_FILE_URI, mExportFileUri.toString());
+        }
     }
 
     @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java
index 033798f..493ea68d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java
@@ -150,7 +150,6 @@
         intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID, "Default");
         intent.putExtra(
                 NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN, "https://example.com");
-        intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_TAG, "tag");
 
         PendingIntent pendingIntent = PendingIntent.getBroadcast(
                 context, 0 /* request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
index 10bd6a8..92e3e02 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
@@ -7,6 +7,12 @@
 import static android.support.test.espresso.action.ViewActions.click;
 import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
 import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.intent.Intents.intended;
+import static android.support.test.espresso.intent.Intents.intending;
+import static android.support.test.espresso.intent.matcher.BundleMatchers.hasEntry;
+import static android.support.test.espresso.intent.matcher.IntentMatchers.hasAction;
+import static android.support.test.espresso.intent.matcher.IntentMatchers.hasExtras;
+import static android.support.test.espresso.intent.matcher.IntentMatchers.hasType;
 import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
 import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
 import static android.support.test.espresso.matcher.ViewMatchers.isEnabled;
@@ -16,11 +22,16 @@
 
 import static org.hamcrest.Matchers.allOf;
 import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.not;
 
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Intent;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.espresso.Espresso;
+import android.support.test.espresso.intent.Intents;
 import android.support.test.filters.SmallTest;
 import android.view.View;
 
@@ -119,6 +130,7 @@
 
         @Override
         public void serializePasswords(Callback<String> callback) {
+            callback.onResult("serialized passwords");
             mSerializePasswordsCalled = true;
         }
     }
@@ -520,6 +532,51 @@
     }
 
     /**
+     * Check that the export flow ends up with sending off a share intent with the exported
+     * passwords.
+     */
+    @Test
+    @SmallTest
+    @Feature({"Preferences"})
+    @EnableFeatures("PasswordExport")
+    public void testExportIntent() throws Exception {
+        setPasswordSource(new SavedPasswordEntry("https://example.com", "test user", "password"));
+
+        ReauthenticationManager.setApiOverride(ReauthenticationManager.OverrideState.AVAILABLE);
+        ReauthenticationManager.setScreenLockSetUpOverride(
+                ReauthenticationManager.OverrideState.AVAILABLE);
+
+        final Preferences preferences =
+                PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(),
+                        SavePasswordsPreferences.class.getName());
+
+        Intents.init();
+
+        Espresso.openActionBarOverflowOrOptionsMenu(
+                InstrumentationRegistry.getInstrumentation().getTargetContext());
+        // Before exporting, pretend that the last successful reauthentication just
+        // happened. This will allow the export flow to continue.
+        ReauthenticationManager.setLastReauthTimeMillis(System.currentTimeMillis());
+        Espresso.onView(withText(R.string.save_password_preferences_export_action_title))
+                .perform(click());
+
+        // Before triggering the sharing intent chooser, stub it out to avoid leaving system UI open
+        // after the test is finished.
+        intending(hasAction(equalTo(Intent.ACTION_CHOOSER)))
+                .respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, null));
+
+        // Confirm the export warning to fire the sharing intent.
+        Espresso.onView(withText(R.string.save_password_preferences_export_action_title))
+                .perform(click());
+
+        intended(allOf(hasAction(equalTo(Intent.ACTION_CHOOSER)),
+                hasExtras(hasEntry(equalTo(Intent.EXTRA_INTENT),
+                        allOf(hasAction(equalTo(Intent.ACTION_SEND)), hasType("text/csv"))))));
+
+        Intents.release();
+    }
+
+    /**
      * Check whether the user is asked to set up a screen lock if attempting to view passwords.
      */
     @Test
@@ -566,7 +623,7 @@
         Espresso.onView(withText(containsString("test user"))).perform(click());
 
         // Before tapping the view button, pretend that the last successful reauthentication just
-        // happened. This will allow the export flow to continue.
+        // happened. This will allow showing the password.
         ReauthenticationManager.setLastReauthTimeMillis(System.currentTimeMillis());
         Espresso.onView(withContentDescription(R.string.password_entry_editor_view_stored_password))
                 .perform(click());
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h
index 19f5716..f169b87b 100644
--- a/chrome/app/chrome_command_ids.h
+++ b/chrome/app/chrome_command_ids.h
@@ -118,7 +118,7 @@
 #define IDC_FOCUS_NEXT_PANE             39004
 #define IDC_FOCUS_PREVIOUS_PANE         39005
 #define IDC_FOCUS_BOOKMARKS             39006
-#define IDC_FOCUS_INFOBARS              39007
+#define IDC_FOCUS_INACTIVE_POPUP_FOR_ACCESSIBILITY 39007
 
 // Show various bits of UI
 #define IDC_OPEN_FILE                   40000
diff --git a/chrome/app/chrome_dll.rc b/chrome/app/chrome_dll.rc
index 067e5a41..74fe0f4f 100644
--- a/chrome/app/chrome_dll.rc
+++ b/chrome/app/chrome_dll.rc
@@ -57,7 +57,7 @@
     "G",            IDC_FIND_PREVIOUS,          VIRTKEY, CONTROL, SHIFT
     VK_F3,          IDC_FIND_PREVIOUS,          VIRTKEY, SHIFT
     "B",            IDC_FOCUS_BOOKMARKS,        VIRTKEY, SHIFT, ALT
-    "A",            IDC_FOCUS_INFOBARS,         VIRTKEY, SHIFT, ALT
+    "A",            IDC_FOCUS_INACTIVE_POPUP_FOR_ACCESSIBILITY,         VIRTKEY, SHIFT, ALT
     "D",            IDC_FOCUS_LOCATION,         VIRTKEY, ALT
     "L",            IDC_FOCUS_LOCATION,         VIRTKEY, CONTROL
     VK_F10,         IDC_FOCUS_MENU_BAR,         VIRTKEY
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc
index 06c6e31..b7750340 100644
--- a/chrome/app/chrome_main_delegate.cc
+++ b/chrome/app/chrome_main_delegate.cc
@@ -149,7 +149,7 @@
 
 #if BUILDFLAG(ENABLE_PLUGINS) && (defined(CHROME_MULTIPLE_DLL_CHILD) || \
     !defined(CHROME_MULTIPLE_DLL_BROWSER))
-#include "pdf/pdf_ppapi.h"
+#include "pdf/pdf.h"
 #endif
 
 #if !defined(CHROME_MULTIPLE_DLL_CHILD)
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index f5efb6d7..3737029 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -337,6 +337,9 @@
         <message name="IDS_SEARCH_NO_RESULTS" desc="Text description of a search that has no results.">
           No search results found
         </message>
+        <message name="IDS_SHOW_BUBBLE_INACTIVE_DESCRIPTION" desc="Message announced to screen reader users when an inactive bubble gets shown.">
+          Press Alt Shift A to show
+        </message>
       </if>
 
        <!-- content area context menus. Android does not use it -->
@@ -10382,7 +10385,7 @@
         Next time, your phone will unlock your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>. Turn off Smart Lock in Settings.
       </message>
       <message name="IDS_EASY_UNLOCK_CHROMEBOOK_ADDED_NOTIFICATION_ABOUT_BUTTON" desc="Label of a button on the new chrome notification to bring user to smart lock settings.">
-         Change settings
+        Change settings
       </message>
       <!-- Strings for the phone changed (aka old Chromebook setup) notification -->
       <message name="IDS_EASY_UNLOCK_PAIRING_CHANGED_NOTIFICATION_TITLE" desc="Title for notification shown when the paired phone is changed.">
@@ -10408,10 +10411,10 @@
       <!-- Strings for the Easy Unlock setup dialog -->
       <!-- Step 1: Intro -->
       <message name="IDS_EASY_UNLOCK_SETUP_INTRO_HEADER_TITLE" desc="The text to show as the header title of the Easy Unlock dialog during the first, introductory step.">
-       Set up Smart Lock for your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
+        Set up Smart Lock for your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
       </message>
       <message name="IDS_EASY_UNLOCK_SETUP_INTRO_HEADER_TEXT" desc="The text to show as the header body text of the Easy Unlock dialog during the first, introductory step. Note that the &lt;a&gt; element surrounds a link; these HTML elements should be preserved in the translation.">
-       Make sure your phone is nearby. To find your phone, Bluetooth will be turned on for all devices that have your account. &lt;a&gt;Learn more&lt;/a&gt;
+        Make sure your phone is nearby. To find your phone, Bluetooth will be turned on for all devices that have your account. &lt;a&gt;Learn more&lt;/a&gt;
       </message>
       <message name="IDS_EASY_UNLOCK_SETUP_INTRO_FIND_PHONE_BUTTON_LABEL" desc="The text to show as the 'Find phone' button label in the Easy Unlock dialog. This button is visible during the first, introductory step.">
         Find your phone
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 39a69ca..029d661 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -4792,6 +4792,7 @@
       "//components/drive:test_support",
       "//components/storage_monitor:test_support",
       "//extensions:test_support",
+      "//services/data_decoder/public/cpp:test_support",
     ]
   }
 
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 28493e28..123f229d 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1648,6 +1648,10 @@
      flag_descriptions::kServiceWorkerScriptFullCodeCacheName,
      flag_descriptions::kServiceWorkerScriptFullCodeCacheDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kServiceWorkerScriptFullCodeCache)},
+    {"enable-service-worker-servicification",
+     flag_descriptions::kServiceWorkerServicificationName,
+     flag_descriptions::kServiceWorkerServicificationDescription, kOsAll,
+     FEATURE_VALUE_TYPE(features::kServiceWorkerServicification)},
     {"enable-pwa-full-code-cache",
      flag_descriptions::kEnablePWAFullCodeCacheName,
      flag_descriptions::kEnablePWAFullCodeCacheDescription, kOsAll,
@@ -2448,6 +2452,10 @@
     {"enable-scroll-anchoring", flag_descriptions::kEnableScrollAnchoringName,
      flag_descriptions::kEnableScrollAnchoringDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kScrollAnchoring)},
+    {"enable-scroll-anchor-serialization",
+     flag_descriptions::kEnableScrollAnchorSerializationName,
+     flag_descriptions::kEnableScrollAnchorSerializationDescription, kOsAll,
+     FEATURE_VALUE_TYPE(features::kScrollAnchorSerialization)},
     {"disable-audio-support-for-desktop-share",
      flag_descriptions::kDisableAudioForDesktopShareName,
      flag_descriptions::kDisableAudioForDesktopShareDescription, kOsAll,
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 3400d913d..179ee010 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -22,6 +22,7 @@
 #include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
@@ -40,6 +41,7 @@
 #include "base/sys_info.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/threading/platform_thread.h"
+#include "base/threading/sequence_local_storage_slot.h"
 #include "base/time/default_tick_clock.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
@@ -306,6 +308,12 @@
 
 namespace {
 
+// The profiler object is stored in a SequenceLocalStorageSlot on the IO thread
+// so that it will be destroyed when the IO thread stops.
+base::LazyInstance<base::SequenceLocalStorageSlot<
+    std::unique_ptr<base::StackSamplingProfiler>>>::Leaky
+    io_thread_sampling_profiler = LAZY_INSTANCE_INITIALIZER;
+
 // This function provides some ways to test crash and assertion handling
 // behavior of the program.
 void HandleTestParameters(const base::CommandLine& command_line) {
@@ -611,6 +619,23 @@
   }
 }
 
+// Starts to profile the IO thread.
+void StartIOThreadProfiling() {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  StackSamplingConfiguration* config = StackSamplingConfiguration::Get();
+  if (config->IsProfilerEnabledForCurrentProcess()) {
+    auto profiler = std::make_unique<base::StackSamplingProfiler>(
+        base::PlatformThread::CurrentId(),
+        config->GetSamplingParamsForCurrentProcess(),
+        metrics::CallStackProfileMetricsProvider::
+            GetProfilerCallbackForBrowserProcessIOThreadStartup());
+
+    profiler->Start();
+    io_thread_sampling_profiler.Get().Set(std::move(profiler));
+  }
+}
+
 class ScopedMainMessageLoopRunEvent {
  public:
   ScopedMainMessageLoopRunEvent() {
@@ -650,15 +675,16 @@
       result_code_(content::RESULT_CODE_NORMAL_EXIT),
       startup_watcher_(new StartupTimeBomb()),
       shutdown_watcher_(new ShutdownWatcherHelper()),
-      sampling_profiler_(base::PlatformThread::CurrentId(),
-                         StackSamplingConfiguration::Get()
-                             ->GetSamplingParamsForCurrentProcess(),
-                         metrics::CallStackProfileMetricsProvider::
-                             GetProfilerCallbackForBrowserProcessStartup()),
+      ui_thread_sampling_profiler_(
+          base::PlatformThread::CurrentId(),
+          StackSamplingConfiguration::Get()
+              ->GetSamplingParamsForCurrentProcess(),
+          metrics::CallStackProfileMetricsProvider::
+              GetProfilerCallbackForBrowserProcessUIThreadStartup()),
       profile_(NULL),
       run_message_loop_(true) {
   if (StackSamplingConfiguration::Get()->IsProfilerEnabledForCurrentProcess())
-    sampling_profiler_.Start();
+    ui_thread_sampling_profiler_.Start();
 
   // If we're running tests (ui_task is non-null).
   if (parameters.ui_task)
@@ -1196,6 +1222,18 @@
   return content::RESULT_CODE_NORMAL_EXIT;
 }
 
+void ChromeBrowserMainParts::PostCreateThreads() {
+  // This task should be posted after the IO thread starts, and prior to the
+  // base version of the function being invoked. It is functionally okay to post
+  // this task in method ChromeBrowserMainParts::BrowserThreadsStarted() which
+  // we also need to add in this class, and call this method at the very top of
+  // BrowserMainLoop::InitializeMainThread(). PostCreateThreads is preferred to
+  // BrowserThreadsStarted as it matches the PreCreateThreads and CreateThreads
+  // stages.
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                          base::BindOnce(&StartIOThreadProfiling));
+}
+
 void ChromeBrowserMainParts::ServiceManagerConnectionStarted(
     content::ServiceManagerConnection* connection) {
   // This should be called after the creation of the tracing controller. The
diff --git a/chrome/browser/chrome_browser_main.h b/chrome/browser/chrome_browser_main.h
index 7b00eeb..2ed10976 100644
--- a/chrome/browser/chrome_browser_main.h
+++ b/chrome/browser/chrome_browser_main.h
@@ -65,6 +65,7 @@
   void PreMainMessageLoopStart() override;
   void PostMainMessageLoopStart() override;
   int PreCreateThreads() override;
+  void PostCreateThreads() override;
   void ServiceManagerConnectionStarted(
       content::ServiceManagerConnection* connection) override;
   void PreMainMessageLoopRun() override;
@@ -147,9 +148,8 @@
   // Parts are deleted in the inverse order they are added.
   std::vector<ChromeBrowserMainExtraParts*> chrome_extra_parts_;
 
-  // A profiler that periodically samples stack traces. Used to sample startup
-  // behavior.
-  base::StackSamplingProfiler sampling_profiler_;
+  // A profiler that periodically samples stack traces on the UI thread.
+  base::StackSamplingProfiler ui_thread_sampling_profiler_;
 
   // Members initialized after / released before main_message_loop_ ------------
 
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
index 875188f5..65b5ee1 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
@@ -25,6 +25,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/image_loader.h"
 #include "extensions/browser/sandboxed_unpacker.h"
@@ -35,6 +36,7 @@
 #include "extensions/common/manifest_handlers/icons_handler.h"
 #include "extensions/common/manifest_handlers/kiosk_mode_info.h"
 #include "services/network/public/interfaces/url_loader_factory.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/image/image.h"
 
@@ -85,8 +87,12 @@
              base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {}
 
   void Start() {
+    auto connector = content::ServiceManagerConnection::GetForProcess()
+                         ->GetConnector()
+                         ->Clone();
     task_runner_->PostTask(FROM_HERE,
-                           base::BindOnce(&CrxLoader::StartInThreadPool, this));
+                           base::BindOnce(&CrxLoader::StartInThreadPool, this,
+                                          std::move(connector)));
   }
 
   bool success() const { return success_; }
@@ -130,7 +136,8 @@
     NotifyFinishedInThreadPool();
   }
 
-  void StartInThreadPool() {
+  void StartInThreadPool(
+      std::unique_ptr<service_manager::Connector> connector) {
     DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
     if (!temp_dir_.CreateUniqueTempDir()) {
@@ -139,10 +146,10 @@
       return;
     }
 
-    scoped_refptr<extensions::SandboxedUnpacker> unpacker(
-        new extensions::SandboxedUnpacker(
-            extensions::Manifest::INTERNAL, extensions::Extension::NO_FLAGS,
-            temp_dir_.GetPath(), task_runner_.get(), this));
+    auto unpacker = base::MakeRefCounted<extensions::SandboxedUnpacker>(
+        std::move(connector), extensions::Manifest::INTERNAL,
+        extensions::Extension::NO_FLAGS, temp_dir_.GetPath(),
+        task_runner_.get(), this);
     unpacker->StartWithCrx(extensions::CRXFileInfo(crx_file_));
   }
 
diff --git a/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.cc b/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.cc
index 6a7d64e5..bac4700 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.cc
@@ -7,8 +7,10 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/common/service_manager_connection.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/manifest_constants.h"
+#include "services/service_manager/public/cpp/connector.h"
 
 namespace chromeos {
 
@@ -27,10 +29,12 @@
 }
 
 void KioskExternalUpdateValidator::Start() {
-  scoped_refptr<extensions::SandboxedUnpacker> unpacker(
-      new extensions::SandboxedUnpacker(
-          extensions::Manifest::EXTERNAL_PREF, extensions::Extension::NO_FLAGS,
-          crx_unpack_dir_, backend_task_runner_.get(), this));
+  auto unpacker = base::MakeRefCounted<extensions::SandboxedUnpacker>(
+      content::ServiceManagerConnection::GetForProcess()
+          ->GetConnector()
+          ->Clone(),
+      extensions::Manifest::EXTERNAL_PREF, extensions::Extension::NO_FLAGS,
+      crx_unpack_dir_, backend_task_runner_.get(), this);
   if (!backend_task_runner_->PostTask(
           FROM_HERE,
           base::BindOnce(&extensions::SandboxedUnpacker::StartWithCrx,
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index ce6ebdb..7e3bce5 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -559,7 +559,8 @@
     ::testing::Values(
         TestParameter(NOT_IN_GUEST_MODE, "showHiddenFilesOnDownloads"),
         TestParameter(NOT_IN_GUEST_MODE, "showHiddenFilesOnDrive"),
-        TestParameter(NOT_IN_GUEST_MODE, "hideGoogleDocs")));
+        TestParameter(NOT_IN_GUEST_MODE, "hideGoogleDocs"),
+        TestParameter(NOT_IN_GUEST_MODE, "showPasteInGearMenu")));
 
 // Structure to describe an account info.
 struct TestAccountInfo {
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc
index 11abdd5..90efdc8 100644
--- a/chrome/browser/chromeos/login/kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -76,6 +76,8 @@
 #include "google_apis/gaia/gaia_switches.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "media/audio/mock_audio_manager.h"
+#include "media/audio/sounds/audio_stream_handler.h"
+#include "media/audio/sounds/sounds_manager.h"
 #include "media/audio/test_audio_thread.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "ui/aura/window.h"
@@ -2296,6 +2298,54 @@
   EXPECT_EQ(extensions::Manifest::EXTERNAL_POLICY, GetInstalledAppLocation());
 }
 
+// A custom SoundsManagerTestImpl implements Initialize and Play only.
+// The difference with media::SoundsManagerImpl is AudioStreamHandler is
+// only initialized upon Play is called, so the most recent AudioManager
+// instance could be used, to make sure of using MockAudioManager to play
+// bundled sounds.
+// It's not a nested class under KioskVirtualKeyboardTest because forward
+// declaration of a nested class is not possible.
+// TODO(crbug.com/805319): remove this fake impl for test.
+class KioskVirtualKeyboardTestSoundsManagerTestImpl
+    : public media::SoundsManager {
+ public:
+  KioskVirtualKeyboardTestSoundsManagerTestImpl() {}
+
+  bool Initialize(SoundKey key, const base::StringPiece& data) override {
+    sound_data_[key] = data.as_string();
+    return true;
+  }
+
+  bool Play(SoundKey key) override {
+    auto iter = sound_data_.find(key);
+    if (iter == sound_data_.end()) {
+      LOG(WARNING) << "Playing non-existent key = " << key;
+      return false;
+    }
+    auto handler = std::make_unique<media::AudioStreamHandler>(iter->second);
+    if (!handler->IsInitialized()) {
+      LOG(WARNING) << "Can't initialize AudioStreamHandler for key = " << key;
+      return false;
+    }
+    return handler->Play();
+  }
+
+  bool Stop(SoundKey key) override {
+    NOTIMPLEMENTED();
+    return false;
+  }
+
+  base::TimeDelta GetDuration(SoundKey key) override {
+    NOTIMPLEMENTED();
+    return base::TimeDelta();
+  }
+
+ private:
+  std::map<SoundKey, std::string> sound_data_;
+
+  DISALLOW_COPY_AND_ASSIGN(KioskVirtualKeyboardTestSoundsManagerTestImpl);
+};
+
 // Specialized test fixture for testing kiosk mode where virtual keyboard is
 // enabled.
 class KioskVirtualKeyboardTest : public KioskTest {
@@ -2304,7 +2354,13 @@
   ~KioskVirtualKeyboardTest() override = default;
 
  protected:
-  // KioskTest overrides:
+  // KioskVirtualKeyboardTest overrides:
+  void SetUp() override {
+    media::SoundsManager::InitializeForTesting(
+        new KioskVirtualKeyboardTestSoundsManagerTestImpl());
+    KioskTest::SetUp();
+  }
+
   void SetUpCommandLine(base::CommandLine* command_line) override {
     KioskTest::SetUpCommandLine(command_line);
     command_line->AppendSwitchASCII(
diff --git a/chrome/browser/engagement/site_engagement_observer.h b/chrome/browser/engagement/site_engagement_observer.h
index e83c969..51fcc63 100644
--- a/chrome/browser/engagement/site_engagement_observer.h
+++ b/chrome/browser/engagement/site_engagement_observer.h
@@ -44,6 +44,8 @@
 
  private:
   FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, Observers);
+  friend class SiteEngagementService;
+
   SiteEngagementService* service_;
 
   DISALLOW_COPY_AND_ASSIGN(SiteEngagementObserver);
diff --git a/chrome/browser/engagement/site_engagement_service.cc b/chrome/browser/engagement/site_engagement_service.cc
index bef7edc..db2f855 100644
--- a/chrome/browser/engagement/site_engagement_service.cc
+++ b/chrome/browser/engagement/site_engagement_service.cc
@@ -137,7 +137,11 @@
   }
 }
 
-SiteEngagementService::~SiteEngagementService() = default;
+SiteEngagementService::~SiteEngagementService() {
+  // Clear any observers to avoid dangling pointers back to this object.
+  for (auto& observer : observer_list_)
+    observer.Observe(nullptr);
+}
 
 void SiteEngagementService::Shutdown() {
   history::HistoryService* history = HistoryServiceFactory::GetForProfile(
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
index 343c71d..11ecad1 100644
--- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
+++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
@@ -44,6 +44,8 @@
   bool picker_deleted;
 };
 
+// TODO(crbug.com/805145): Uncomment this when test is re-enabled.
+#if 0
 DesktopMediaID MakeFakeWebContentsMediaId(bool audio_share) {
   DesktopMediaID media_id(DesktopMediaID::TYPE_WEB_CONTENTS,
                           DesktopMediaID::kNullId,
@@ -52,6 +54,7 @@
   media_id.audio_share = audio_share;
   return media_id;
 }
+#endif
 
 class FakeDesktopMediaPicker : public DesktopMediaPicker {
  public:
@@ -197,52 +200,55 @@
   // Each element in the following array corresponds to one test in
   // chrome/test/data/extensions/api_test/desktop_capture/test.js .
   TestFlags test_flags[] = {
-      // pickerUiCanceled()
-      {true, true, false, false, DesktopMediaID()},
-      // chooseMedia()
-      {true, true, false, false,
-       DesktopMediaID(DesktopMediaID::TYPE_SCREEN, DesktopMediaID::kNullId)},
-      // screensOnly()
-      {true, false, false, false, DesktopMediaID()},
-      // WindowsOnly()
-      {false, true, false, false, DesktopMediaID()},
-      // tabOnly()
-      {false, false, true, false, DesktopMediaID()},
-      // audioShareNoApproval()
-      {true, true, true, true,
-       DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, 123, false)},
-      // audioShareApproval()
-      {true, true, true, true,
-       DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, 123, true)},
-      // chooseMediaAndGetStream()
-      {true, true, false, false,
-       DesktopMediaID(DesktopMediaID::TYPE_SCREEN,
-                      webrtc::kFullDesktopScreenId)},
-      // chooseMediaAndTryGetStreamWithInvalidId()
-      {true, true, false, false,
-       DesktopMediaID(DesktopMediaID::TYPE_SCREEN,
-                      webrtc::kFullDesktopScreenId)},
-      // cancelDialog()
-      {true, true, false, false, DesktopMediaID(), true},
+    // pickerUiCanceled()
+    {true, true, false, false, DesktopMediaID()},
+    // chooseMedia()
+    {true, true, false, false,
+     DesktopMediaID(DesktopMediaID::TYPE_SCREEN, DesktopMediaID::kNullId)},
+    // screensOnly()
+    {true, false, false, false, DesktopMediaID()},
+    // WindowsOnly()
+    {false, true, false, false, DesktopMediaID()},
+    // tabOnly()
+    {false, false, true, false, DesktopMediaID()},
+    // audioShareNoApproval()
+    {true, true, true, true,
+     DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, 123, false)},
+    // audioShareApproval()
+    {true, true, true, true,
+     DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, 123, true)},
+    // chooseMediaAndGetStream()
+    {true, true, false, false,
+     DesktopMediaID(DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId)},
+    // chooseMediaAndTryGetStreamWithInvalidId()
+    {true, true, false, false,
+     DesktopMediaID(DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId)},
+    // cancelDialog()
+    {true, true, false, false, DesktopMediaID(), true},
+// TODO(crbug.com/805145): Test fails; invalid device IDs being generated.
+#if 0
       // tabShareWithAudioGetStream()
       {false, false, true, true, MakeFakeWebContentsMediaId(true)},
-      // windowShareWithAudioGetStream()
-      {false, true, false, true,
-       DesktopMediaID(DesktopMediaID::TYPE_WINDOW, DesktopMediaID::kFakeId,
-                      true)},
-      // screenShareWithAudioGetStream()
-      {true, false, false, true,
-       DesktopMediaID(DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId,
-                      true)},
+#endif
+    // windowShareWithAudioGetStream()
+    {false, true, false, true,
+     DesktopMediaID(DesktopMediaID::TYPE_WINDOW, DesktopMediaID::kFakeId,
+                    true)},
+    // screenShareWithAudioGetStream()
+    {true, false, false, true,
+     DesktopMediaID(DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId,
+                    true)},
+// TODO(crbug.com/805145): Test fails; invalid device IDs being generated.
+#if 0
       // tabShareWithoutAudioGetStream()
       {false, false, true, true, MakeFakeWebContentsMediaId(false)},
-      // windowShareWithoutAudioGetStream()
-      {false, true, false, true,
-       DesktopMediaID(DesktopMediaID::TYPE_WINDOW, DesktopMediaID::kFakeId)},
-      // screenShareWithoutAudioGetStream()
-      {true, false, false, true,
-       DesktopMediaID(DesktopMediaID::TYPE_SCREEN,
-                      webrtc::kFullDesktopScreenId)},
+#endif
+    // windowShareWithoutAudioGetStream()
+    {false, true, false, true,
+     DesktopMediaID(DesktopMediaID::TYPE_WINDOW, DesktopMediaID::kFakeId)},
+    // screenShareWithoutAudioGetStream()
+    {true, false, false, true,
+     DesktopMediaID(DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId)},
   };
   picker_factory_.SetTestFlags(test_flags, arraysize(test_flags));
   ASSERT_TRUE(RunExtensionTest("desktop_capture")) << message_;
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index 666b488..65713040 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -40,6 +40,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/resource_dispatcher_host.h"
+#include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/extension_file_task_runner.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
@@ -62,6 +63,7 @@
 #include "extensions/common/permissions/permissions_data.h"
 #include "extensions/common/user_script.h"
 #include "extensions/strings/grit/extensions_strings.h"
+#include "services/service_manager/public/cpp/connector.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -100,6 +102,9 @@
 }
 
 // static
+service_manager::Connector* CrxInstaller::connector_for_test_ = nullptr;
+
+// static
 scoped_refptr<CrxInstaller> CrxInstaller::Create(
     ExtensionService* service,
     std::unique_ptr<ExtensionInstallPrompt> client,
@@ -185,8 +190,8 @@
   source_file_ = source_file.path;
 
   auto unpacker = base::MakeRefCounted<SandboxedUnpacker>(
-      install_source_, creation_flags_, install_directory_,
-      installer_task_runner_.get(), this);
+      GetConnector()->Clone(), install_source_, creation_flags_,
+      install_directory_, installer_task_runner_.get(), this);
 
   if (!installer_task_runner_->PostTask(
           FROM_HERE, base::BindOnce(&SandboxedUnpacker::StartWithCrx, unpacker,
@@ -207,8 +212,8 @@
   source_file_ = unpacked_dir;
 
   auto unpacker = base::MakeRefCounted<SandboxedUnpacker>(
-      install_source_, creation_flags_, install_directory_,
-      installer_task_runner_.get(), this);
+      GetConnector()->Clone(), install_source_, creation_flags_,
+      install_directory_, installer_task_runner_.get(), this);
 
   if (!installer_task_runner_->PostTask(
           FROM_HERE,
@@ -1026,4 +1031,11 @@
   }
 }
 
+service_manager::Connector* CrxInstaller::GetConnector() const {
+  return connector_for_test_
+             ? connector_for_test_
+             : content::ServiceManagerConnection::GetForProcess()
+                   ->GetConnector();
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/crx_installer.h b/chrome/browser/extensions/crx_installer.h
index d14ea61..17205c97 100644
--- a/chrome/browser/extensions/crx_installer.h
+++ b/chrome/browser/extensions/crx_installer.h
@@ -37,6 +37,10 @@
 class SequencedTaskRunner;
 }
 
+namespace service_manager {
+class Connector;
+}
+
 namespace extensions {
 class CrxInstallError;
 class ExtensionUpdaterTest;
@@ -237,6 +241,10 @@
   // invalid if this isn't an update.
   const base::Version& current_version() const { return current_version_; }
 
+  static void set_connector_for_test(service_manager::Connector* connector) {
+    connector_for_test_ = connector;
+  }
+
  private:
   friend class ::ExtensionServiceTest;
   friend class ExtensionUpdaterTest;
@@ -307,6 +315,9 @@
   // and needs additional permissions.
   void ConfirmReEnable();
 
+  // Returns the connector to the ServiceManager.
+  service_manager::Connector* GetConnector() const;
+
   void set_install_flag(int flag, bool val) {
     if (val)
       install_flags_ |= flag;
@@ -484,6 +495,8 @@
   // Invoked when the install is completed.
   InstallerResultCallback installer_callback_;
 
+  static service_manager::Connector* connector_for_test_;
+
   DISALLOW_COPY_AND_ASSIGN(CrxInstaller);
 };
 
diff --git a/chrome/browser/extensions/extension_service_test_base.cc b/chrome/browser/extensions/extension_service_test_base.cc
index 09b97fd9..69426a8 100644
--- a/chrome/browser/extensions/extension_service_test_base.cc
+++ b/chrome/browser/extensions/extension_service_test_base.cc
@@ -15,6 +15,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "chrome/browser/extensions/component_loader.h"
+#include "chrome/browser/extensions/crx_installer.h"
 #include "chrome/browser/extensions/extension_garbage_collector_factory.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/load_error_reporter.h"
@@ -30,6 +31,7 @@
 #include "components/sync_preferences/pref_service_mock_factory.h"
 #include "components/sync_preferences/pref_service_syncable.h"
 #include "content/public/browser/browser_context.h"
+#include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/pref_names.h"
@@ -91,6 +93,7 @@
     return;
   }
   data_dir_ = test_data_dir.AppendASCII("extensions");
+  CrxInstaller::set_connector_for_test(test_data_decoder_service_.connector());
 }
 
 ExtensionServiceTestBase::~ExtensionServiceTestBase() {
diff --git a/chrome/browser/extensions/extension_service_test_base.h b/chrome/browser/extensions/extension_service_test_base.h
index e90e534..0d210e6 100644
--- a/chrome/browser/extensions/extension_service_test_base.h
+++ b/chrome/browser/extensions/extension_service_test_base.h
@@ -19,6 +19,7 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/test_utils.h"
+#include "services/data_decoder/public/cpp/test_data_decoder_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_CHROMEOS)
@@ -181,6 +182,10 @@
   chromeos::ScopedTestUserManager test_user_manager_;
 #endif
 
+  // An instance of the data decoder service that does not require the
+  // ServiceManager.
+  data_decoder::TestDataDecoderService test_data_decoder_service_;
+
   DISALLOW_COPY_AND_ASSIGN(ExtensionServiceTestBase);
 };
 
diff --git a/chrome/browser/extensions/startup_helper.cc b/chrome/browser/extensions/startup_helper.cc
index 8e7f342..bb99318 100644
--- a/chrome/browser/extensions/startup_helper.cc
+++ b/chrome/browser/extensions/startup_helper.cc
@@ -17,9 +17,11 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/chrome_extensions_client.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/extension_file_task_runner.h"
 #include "extensions/browser/sandboxed_unpacker.h"
 #include "extensions/common/extension.h"
+#include "services/service_manager/public/cpp/connector.h"
 
 using content::BrowserThread;
 
@@ -86,13 +88,17 @@
         quit_closure_(std::move(quit_closure)),
         success_(false) {}
 
-  bool success() { return success_; }
-  const base::string16& error() { return error_; }
+  bool success() const { return success_; }
+  const base::string16& error() const { return error_; }
 
   void Start() {
+    std::unique_ptr<::service_manager::Connector> connector =
+        content::ServiceManagerConnection::GetForProcess()
+            ->GetConnector()
+            ->Clone();
     GetExtensionFileTaskRunner()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&ValidateCrxHelper::StartOnBlockingThread, this));
+        FROM_HERE, base::BindOnce(&ValidateCrxHelper::StartOnBlockingThread,
+                                  this, std::move(connector)));
   }
 
  protected:
@@ -126,11 +132,13 @@
     std::move(quit_closure_).Run();
   }
 
-  void StartOnBlockingThread() {
+  void StartOnBlockingThread(
+      std::unique_ptr<service_manager::Connector> connector) {
     DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence());
-    scoped_refptr<SandboxedUnpacker> unpacker(new SandboxedUnpacker(
-        Manifest::INTERNAL, 0, /* no special creation flags */
-        temp_dir_, GetExtensionFileTaskRunner().get(), this));
+    auto unpacker = base::MakeRefCounted<SandboxedUnpacker>(
+        std::move(connector), Manifest::INTERNAL,
+        0, /* no special creation flags */
+        temp_dir_, GetExtensionFileTaskRunner().get(), this);
     unpacker->StartWithCrx(crx_file_);
   }
 
@@ -173,8 +181,8 @@
 
   base::RunLoop run_loop;
   CRXFileInfo file(path);
-  scoped_refptr<ValidateCrxHelper> helper(
-      new ValidateCrxHelper(file, temp_dir.GetPath(), run_loop.QuitClosure()));
+  auto helper = base::MakeRefCounted<ValidateCrxHelper>(
+      file, temp_dir.GetPath(), run_loop.QuitClosure());
   helper->Start();
   run_loop.Run();
 
diff --git a/chrome/browser/extensions/test_extension_system.cc b/chrome/browser/extensions/test_extension_system.cc
index beaa4f8a..dbd097f 100644
--- a/chrome/browser/extensions/test_extension_system.cc
+++ b/chrome/browser/extensions/test_extension_system.cc
@@ -10,6 +10,7 @@
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/extensions/blacklist.h"
 #include "chrome/browser/extensions/chrome_app_sorting.h"
+#include "chrome/browser/extensions/crx_installer.h"
 #include "chrome/browser/extensions/extension_management.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/shared_module_service.h"
@@ -17,6 +18,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
@@ -72,6 +74,11 @@
       profile_, command_line, install_directory, ExtensionPrefs::Get(profile_),
       Blacklist::Get(profile_), autoupdate_enabled, extensions_enabled,
       &ready_));
+  if (!test_data_decoder_service_) {
+    test_data_decoder_service_ =
+        std::make_unique<data_decoder::TestDataDecoderService>();
+  }
+  CrxInstaller::set_connector_for_test(test_data_decoder_service_->connector());
   extension_service_->ClearProvidersForTesting();
   return extension_service_.get();
 }
diff --git a/chrome/browser/extensions/test_extension_system.h b/chrome/browser/extensions/test_extension_system.h
index 73b4e6d..3a51811b 100644
--- a/chrome/browser/extensions/test_extension_system.h
+++ b/chrome/browser/extensions/test_extension_system.h
@@ -9,6 +9,7 @@
 
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/one_shot_event.h"
+#include "services/data_decoder/public/cpp/test_data_decoder_service.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
@@ -99,6 +100,8 @@
   std::unique_ptr<QuotaService> quota_service_;
   std::unique_ptr<AppSorting> app_sorting_;
   OneShotEvent ready_;
+  std::unique_ptr<data_decoder::TestDataDecoderService>
+      test_data_decoder_service_;
 
 #if defined(OS_CHROMEOS)
   std::unique_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 69869d5..c7c2056 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -572,6 +572,12 @@
     "Adjusts scroll position to prevent visible jumps when offscreen content "
     "changes.";
 
+const char kEnableScrollAnchorSerializationName[] =
+    "Scroll Anchor Serialization";
+const char kEnableScrollAnchorSerializationDescription[] =
+    "Save the scroll anchor and use it to restore the scroll position when "
+    "navigating.";
+
 const char kEnableSharedArrayBufferName[] =
     "Experimental enabled SharedArrayBuffer support in JavaScript.";
 const char kEnableSharedArrayBufferDescription[] =
@@ -1252,6 +1258,13 @@
     "message pipe and data pipes, and that is never be blocked on the main "
     "thread.";
 
+extern const char kServiceWorkerServicificationName[] =
+    "Servicified service workers";
+extern const char kServiceWorkerServicificationDescription[] =
+    "Enable the servicified service workers. A servicified service worker can "
+    "have direct connection from its clients, so that fetch events can be "
+    "dispatched through the connection without hopping to the browser process.";
+
 const char kServiceWorkerScriptFullCodeCacheName[] =
     "Service worker script full code cache.";
 const char kServiceWorkerScriptFullCodeCacheDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index b34b428..17dee8d 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -365,6 +365,9 @@
 extern const char kEnableScrollAnchoringName[];
 extern const char kEnableScrollAnchoringDescription[];
 
+extern const char kEnableScrollAnchorSerializationName[];
+extern const char kEnableScrollAnchorSerializationDescription[];
+
 extern const char kEnableSharedArrayBufferName[];
 extern const char kEnableSharedArrayBufferDescription[];
 
@@ -766,6 +769,9 @@
 extern const char kServiceWorkerPaymentAppsName[];
 extern const char kServiceWorkerPaymentAppsDescription[];
 
+extern const char kServiceWorkerServicificationName[];
+extern const char kServiceWorkerServicificationDescription[];
+
 extern const char kServiceWorkerScriptStreamingName[];
 extern const char kServiceWorkerScriptStreamingDescription[];
 
diff --git a/chrome/browser/geolocation/geolocation_browsertest.cc b/chrome/browser/geolocation/geolocation_browsertest.cc
index 75289c4..23055bf 100644
--- a/chrome/browser/geolocation/geolocation_browsertest.cc
+++ b/chrome/browser/geolocation/geolocation_browsertest.cc
@@ -36,11 +36,11 @@
 #include "content/public/test/browser_test_utils.h"
 #include "device/geolocation/network_location_request.h"
 #include "device/geolocation/public/cpp/scoped_geolocation_overrider.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "google_apis/google_api_keys.h"
 #include "net/base/escape.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/url_request/test_url_fetcher_factory.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 
 namespace {
 
diff --git a/chrome/browser/notifications/notification_platform_bridge_android.cc b/chrome/browser/notifications/notification_platform_bridge_android.cc
index a933acf3..718bcaa 100644
--- a/chrome/browser/notifications/notification_platform_bridge_android.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_android.cc
@@ -147,13 +147,11 @@
     const JavaParamRef<jstring>& java_scope_url,
     const JavaParamRef<jstring>& java_profile_id,
     jboolean incognito,
-    const JavaParamRef<jstring>& java_tag,
     const JavaParamRef<jstring>& java_webapk_package,
     jint java_action_index,
     const JavaParamRef<jstring>& java_reply) {
   std::string notification_id =
       ConvertJavaStringToUTF8(env, java_notification_id);
-  std::string tag = ConvertJavaStringToUTF8(env, java_tag);
   std::string profile_id = ConvertJavaStringToUTF8(env, java_profile_id);
   std::string webapk_package =
       ConvertJavaStringToUTF8(env, java_webapk_package);
@@ -165,7 +163,7 @@
   GURL origin(ConvertJavaStringToUTF8(env, java_origin));
   GURL scope_url(ConvertJavaStringToUTF8(env, java_scope_url));
   regenerated_notification_infos_[notification_id] =
-      RegeneratedNotificationInfo(origin, scope_url, tag, webapk_package);
+      RegeneratedNotificationInfo(scope_url, webapk_package);
 
   base::Optional<int> action_index;
   if (java_action_index != kNotificationInvalidButtonIndex)
@@ -198,7 +196,7 @@
   const RegeneratedNotificationInfo& info = iterator->second;
   regenerated_notification_infos_[notification_id] =
       RegeneratedNotificationInfo(
-          info.origin, info.service_worker_scope, info.tag,
+          info.service_worker_scope,
           ConvertJavaStringToUTF8(env, java_webapk_package));
 }
 
@@ -209,7 +207,6 @@
     const JavaParamRef<jstring>& java_origin,
     const JavaParamRef<jstring>& java_profile_id,
     jboolean incognito,
-    const JavaParamRef<jstring>& java_tag,
     jboolean by_user) {
   std::string profile_id = ConvertJavaStringToUTF8(env, java_profile_id);
   std::string notification_id =
@@ -257,10 +254,6 @@
       ConvertUTF8ToJavaString(env, notification.id());
   ScopedJavaLocalRef<jstring> j_origin =
       ConvertUTF8ToJavaString(env, origin_url.spec());
-  // TODO(https://crbug.com/801535): remove the tag field from Java and just use
-  // the notification id.
-  ScopedJavaLocalRef<jstring> tag =
-      ConvertUTF8ToJavaString(env, notification.id());
   ScopedJavaLocalRef<jstring> title =
       ConvertUTF16ToJavaString(env, notification.title());
   ScopedJavaLocalRef<jstring> body =
@@ -292,13 +285,12 @@
 
   Java_NotificationPlatformBridge_displayNotification(
       env, java_object_, j_notification_id, j_origin, j_scope_url, j_profile_id,
-      incognito, tag, title, body, image, notification_icon, badge,
+      incognito, title, body, image, notification_icon, badge,
       vibration_pattern, notification.timestamp().ToJavaTime(),
       notification.renotify(), notification.silent(), actions);
 
   regenerated_notification_infos_[notification.id()] =
-      RegeneratedNotificationInfo(origin_url, scope_url, notification.id(),
-                                  base::nullopt);
+      RegeneratedNotificationInfo(scope_url, base::nullopt);
 }
 
 void NotificationPlatformBridgeAndroid::Close(
@@ -386,13 +378,9 @@
 
 NotificationPlatformBridgeAndroid::RegeneratedNotificationInfo::
     RegeneratedNotificationInfo(
-        const GURL& origin,
         const GURL& service_worker_scope,
-        const std::string& tag,
         const base::Optional<std::string>& webapk_package)
-    : origin(origin),
-      service_worker_scope(service_worker_scope),
-      tag(tag),
+    : service_worker_scope(service_worker_scope),
       webapk_package(webapk_package) {}
 
 NotificationPlatformBridgeAndroid::RegeneratedNotificationInfo::
diff --git a/chrome/browser/notifications/notification_platform_bridge_android.h b/chrome/browser/notifications/notification_platform_bridge_android.h
index f4db644b..23c83ea 100644
--- a/chrome/browser/notifications/notification_platform_bridge_android.h
+++ b/chrome/browser/notifications/notification_platform_bridge_android.h
@@ -47,7 +47,6 @@
       const base::android::JavaParamRef<jstring>& java_scope_url,
       const base::android::JavaParamRef<jstring>& java_profile_id,
       jboolean incognito,
-      const base::android::JavaParamRef<jstring>& java_tag,
       const base::android::JavaParamRef<jstring>& java_webapk_package,
       jint action_index,
       const base::android::JavaParamRef<jstring>& java_reply);
@@ -68,7 +67,6 @@
       const base::android::JavaParamRef<jstring>& java_origin,
       const base::android::JavaParamRef<jstring>& java_profile_id,
       jboolean incognito,
-      const base::android::JavaParamRef<jstring>& java_tag,
       jboolean by_user);
 
   // NotificationPlatformBridge implementation.
@@ -104,20 +102,11 @@
   struct RegeneratedNotificationInfo {
     RegeneratedNotificationInfo();
     RegeneratedNotificationInfo(
-        // TODO(https://crbug.com/801221): origin no longer used, can be
-        // removed.
-        const GURL& origin,
         const GURL& service_worker_scope,
-        // TODO(https://crbug.com/801221): tag no longer used, can be removed
-        const std::string& tag,
         const base::Optional<std::string>& webapk_package);
     ~RegeneratedNotificationInfo();
 
-    // TODO(https://crbug.com/801221): origin no longer used, can be removed.
-    GURL origin;
     GURL service_worker_scope;
-    // TODO(https://crbug.com/801221): tag no longer used, can be removed.
-    std::string tag;
     base::Optional<std::string> webapk_package;
   };
 
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
index 5473c39..e06f7926 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
@@ -363,7 +363,7 @@
 
       if (focusIsAncestor) {
         focus = evt.target;
-        Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH);
+        Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH);
       }
 
       // Create text edit handler, if needed, now in order not to miss initial
@@ -461,7 +461,7 @@
 
       if (fromDesktop &&
           (!this.lastValueTarget_ || this.lastValueTarget_ !== t)) {
-        output.withQueueMode(cvox.QueueMode.FLUSH);
+        output.withQueueMode(cvox.QueueMode.CATEGORY_FLUSH);
         var range = cursors.Range.fromNode(t);
         output.withRichSpeechAndBraille(
             range, range, Output.EventType.NAVIGATE);
@@ -506,7 +506,7 @@
       var override = evt.target.role == RoleType.MENU_ITEM ||
           (evt.target.root == focus.root &&
            focus.root.role == RoleType.DESKTOP);
-      Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH);
+      Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH);
       if (override || AutomationUtil.isDescendantOf(evt.target, focus))
         this.onEventDefault(evt);
     }.bind(this));
@@ -623,7 +623,7 @@
 
     ChromeVoxState.instance.setCurrentRange(cursors.Range.fromNode(focus));
 
-    Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH);
+    Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH);
     o.withRichSpeechAndBraille(
          ChromeVoxState.instance.currentRange, null, evt.type)
         .go();
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
index 933322a..6f3faea 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
@@ -1216,8 +1216,9 @@
           var related = node[tree.firstChild.value];
           this.node_(related, related, Output.EventType.NAVIGATE, buff);
         } else if (token == 'nameOrTextContent') {
+          var finalOutput;
           if (node.name) {
-            this.format_(node, '$name', buff);
+            finalOutput = node.name;
           } else {
             var walker = new AutomationTreeWalker(node, Dir.FORWARD, {
               visit: AutomationPredicate.leafOrStaticText,
@@ -1229,9 +1230,9 @@
               if (walker.node.name)
                 outputStrings.push(walker.node.name);
             }
-            var joinedOutput = outputStrings.join(' ');
-            this.append_(buff, joinedOutput, options);
+            finalOutput = outputStrings.join(' ');
           }
+          this.append_(buff, finalOutput, options);
         } else if (node[token] !== undefined) {
           options.annotation.push(token);
           var value = node[token];
diff --git a/chrome/browser/resources/chromeos/zip_archiver/css/passphrase-dialog.css b/chrome/browser/resources/chromeos/zip_archiver/css/passphrase-dialog.css
index fb2bea69..dc9dc11 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/css/passphrase-dialog.css
+++ b/chrome/browser/resources/chromeos/zip_archiver/css/passphrase-dialog.css
@@ -16,13 +16,8 @@
   justify-content: space-between;
 }
 
-#bar {
-  align-items: center;
-  display: flex;
-  justify-content: space-between;
-}
-
 #buttons {
+  align-items: center;
   display: flex;
   justify-content: flex-end;
 }
diff --git a/chrome/browser/resources/chromeos/zip_archiver/html/passphrase-dialog.html b/chrome/browser/resources/chromeos/zip_archiver/html/passphrase-dialog.html
index 3efca3c..2659bb9 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/html/passphrase-dialog.html
+++ b/chrome/browser/resources/chromeos/zip_archiver/html/passphrase-dialog.html
@@ -14,22 +14,17 @@
              autofocus
              i18n-values="placeholder:ZIP_ARCHIVER_PASSPHRASE_INPUT_LABEL;aria-label:ZIP_ARCHIVER_PASSPHRASE_INPUT_LABEL">
     </paper-input-container>
-    <div id="bar">
-      <paper-checkbox id="remember"
-                      i18n-content="ZIP_ARCHIVER_PASSPHRASE_REMEMBER">
-      </paper-checkbox>
-      <div id="buttons">
-        <paper-button noink
-                      on-click="accept"
-                      id="acceptButton"
-                      i18n-content="ZIP_ARCHIVER_PASSPHRASE_ACCEPT">
-        </paper-button>
-        <paper-button noink
-                      on-click="cancel"
-                      id="cancelButton"
-                      i18n-content="ZIP_ARCHIVER_PASSPHRASE_CANCEL">
-        </paper-button>
-      </div>
+    <div id="buttons">
+      <paper-button noink
+                    on-click="accept"
+                    id="acceptButton"
+                    i18n-content="ZIP_ARCHIVER_PASSPHRASE_ACCEPT">
+      </paper-button>
+      <paper-button noink
+                    on-click="cancel"
+                    id="cancelButton"
+                    i18n-content="ZIP_ARCHIVER_PASSPHRASE_CANCEL">
+      </paper-button>
     </div>
   </template>
 </dom-module>
diff --git a/chrome/browser/resources/chromeos/zip_archiver/js/app.js b/chrome/browser/resources/chromeos/zip_archiver/js/app.js
index d7f345f..5e786bd 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/js/app.js
+++ b/chrome/browser/resources/chromeos/zip_archiver/js/app.js
@@ -10,12 +10,6 @@
  */
 unpacker.app = {
   /**
-   * The key used by chrome.storage.local to save and restore the volumes state.
-   * @const {string}
-   */
-  STORAGE_KEY: 'state',
-
-  /**
    * The default id for the NaCl module.
    * @const {string}
    */
@@ -167,98 +161,6 @@
   },
 
   /**
-   * Saves state in case of restarts, event page suspend, crashes, etc. This
-   * method does nothing when context is in incognito mode.
-   * @param {!Array<!unpacker.types.FileSystemId>} fileSystemIdsArray
-   * @private
-   */
-  saveState_: function(fileSystemIdsArray) {
-    // If current context is in incognito mode, then skip save state because
-    // retainEntry is not available in incognito mode.
-    if (chrome.extension.inIncognitoContext)
-      return;
-
-    chrome.storage.local.get([unpacker.app.STORAGE_KEY], function(result) {
-      if (!result[unpacker.app.STORAGE_KEY])  // First save state call.
-        result[unpacker.app.STORAGE_KEY] = {};
-
-      // Overwrite state only for the volumes that have their file system id
-      // present in the input array. Leave the rest of the volumes state
-      // untouched.
-      fileSystemIdsArray.forEach(function(fileSystemId) {
-        var entryId = chrome.fileSystem.retainEntry(
-            unpacker.app.volumes[fileSystemId].entry);
-        result[unpacker.app.STORAGE_KEY][fileSystemId] = {
-          entryId: entryId,
-          passphrase: unpacker.app.volumes[fileSystemId]
-                          .decompressor.passphraseManager.rememberedPassphrase
-        };
-      });
-
-      chrome.storage.local.set(result);
-    });
-  },
-
-  /**
-   * Removes state from local storage for a single volume. This method does
-   * nothing when context is in incognito mode.
-   * @param {!unpacker.types.FileSystemId} fileSystemId
-   */
-  removeState_: function(fileSystemId) {
-    if (chrome.extension.inIncognitoContext)
-      return;
-
-    chrome.storage.local.get([unpacker.app.STORAGE_KEY], function(result) {
-      console.assert(
-          result[unpacker.app.STORAGE_KEY] &&
-              result[unpacker.app.STORAGE_KEY][fileSystemId],
-          'Should call removeState_ only for file systems that ',
-          'have previously called saveState_.');
-
-      delete result[unpacker.app.STORAGE_KEY][fileSystemId];
-      chrome.storage.local.set(result);
-    });
-  },
-
-  /**
-   * Restores archive's entry and opened files for the passed file system id.
-   * @param {!unpacker.types.FileSystemId} fileSystemId
-   * @return {!Promise<!Object>} Promise fulfilled with the entry and list of
-   *     opened files.
-   * @private
-   */
-  restoreVolumeState_: function(fileSystemId) {
-    if (chrome.extension.inIncognitoContext)
-      return new Promise.reject('No state restored due to incognito context');
-    return new Promise(function(fulfill, reject) {
-      chrome.storage.local.get([unpacker.app.STORAGE_KEY], function(result) {
-        if (!result[unpacker.app.STORAGE_KEY]) {
-          reject('FAILED');
-          return;
-        }
-
-        var volumeState = result[unpacker.app.STORAGE_KEY][fileSystemId];
-        if (!volumeState) {
-          console.error('No state for: ' + fileSystemId + '.');
-          reject('FAILED');
-          return;
-        }
-
-        chrome.fileSystem.restoreEntry(volumeState.entryId, function(entry) {
-          if (chrome.runtime.lastError) {
-            console.error(
-                'Restore entry error for <', fileSystemId,
-                '>: ' + chrome.runtime.lastError.message);
-            reject('FAILED');
-            return;
-          }
-          fulfill({entry: entry, passphrase: volumeState.passphrase});
-        });
-      });
-    });
-  },
-
-  /**
    * Creates a volume and loads its metadata from NaCl.
    * @param {!unpacker.types.FileSystemId} fileSystemId
    * @param {!Entry} entry The volume's archive entry.
@@ -317,68 +219,9 @@
   },
 
   /**
-   * Restores a volume mounted previously to a suspend / restart. In case of
-   * failure of the load promise for fileSystemId, the corresponding volume is
-   * forcely unmounted.
-   * @param {!unpacker.types.FileSystemId} fileSystemId
-   * @return {!Promise} A promise that restores state and loads volume.
-   * @private
-   */
-  restoreSingleVolume_: function(fileSystemId) {
-    // Load volume after restart / suspend page event.
-    return unpacker.app.restoreVolumeState_(fileSystemId)
-        .then(function(state) {
-          return new Promise(function(fulfill, reject) {
-            // Check if the file system is compatible with this version of the
-            // ZIP unpacker.
-            // TODO(mtomasz): Implement remounting instead of unmounting.
-            chrome.fileSystemProvider.get(fileSystemId, function(fileSystem) {
-              if (chrome.runtime.lastError) {
-                console.error(chrome.runtime.lastError.name);
-                reject('FAILED');
-                return;
-              }
-              if (!fileSystem || fileSystem.openedFilesLimit != 1) {
-                console.error('No compatible mounted file system found.');
-                reject('FAILED');
-                return;
-              }
-              fulfill({state: state, fileSystem: fileSystem});
-            });
-          });
-        })
-        .then(function(stateWithFileSystem) {
-          var openedFilesOptions = {};
-          stateWithFileSystem.fileSystem.openedFiles.forEach(function(
-              openedFile) {
-            openedFilesOptions[openedFile.openRequestId] = {
-              fileSystemId: fileSystemId,
-              requestId: openedFile.openRequestId,
-              mode: openedFile.mode,
-              filePath: openedFile.filePath
-            };
-          });
-          return unpacker.app.loadVolume_(
-              fileSystemId, stateWithFileSystem.state.entry, openedFilesOptions,
-              stateWithFileSystem.state.passphrase);
-        })
-        .catch(function(error) {
-          console.error(error.stack || error);
-          // Force unmount in case restore failed. All resources related to the
-          // volume will be cleanup from both memory and local storage.
-          // TODO(523195): Show a notification that the source file is gone.
-          return unpacker.app.unmountVolume(fileSystemId, true)
-              .then(function() {
-                return Promise.reject('FAILED');
-              });
-        });
-  },
-
-  /**
    * Ensures a volume is loaded by returning its corresponding loaded promise
    * from unpacker.app.volumeLoadedPromises. In case there is no such promise,
-   * then this is a call after suspend / restart and a new volume loaded promise
-   * that restores state is returned.
+   * then this simply returns a rejected Promise.
    * @param {!unpacker.types.FileSystemId} fileSystemId
    * @return {!Promise} The loading volume promise.
    * @private
@@ -394,14 +237,8 @@
     }
 
     return unpacker.app.moduleLoadedPromise.then(function() {
-      // In case there is no volume promise for fileSystemId then we
-      // received a call after restart / suspend as load promises are
-      // created on launched. In this case we will restore volume state
-      // from local storage and create a new load promise.
-      if (!unpacker.app.volumeLoadedPromises[fileSystemId]) {
-        unpacker.app.volumeLoadedPromises[fileSystemId] =
-            unpacker.app.restoreSingleVolume_(fileSystemId);
-      }
+      if (!unpacker.app.volumeLoadedPromises[fileSystemId])
+        return Promise.reject(fileSystemId + ' requested before mounting');
 
       // Decrement the counter when the mounting process ends.
       unpacker.app.volumeLoadedPromises[fileSystemId]
@@ -495,8 +332,7 @@
   },
 
   /**
-   * Cleans up the resources for a volume, except for the local storage. If
-   * necessary that can be done using unpacker.app.removeState_.
+   * Cleans up the resources for a volume.
    * @param {!unpacker.types.FileSystemId} fileSystemId
    */
   cleanupVolume: function(fileSystemId) {
@@ -545,16 +381,6 @@
   },
 
   /**
-   * Updates the state in case of restarts, event page suspend, crashes, etc.
-   * Use this method to update or save the state out side of the object in case
-   * when password changes, etc.
-   * @param {!Array<!unpacker.types.FileSystemId>} fileSystemIdsArray
-   */
-  updateState: function(fileSystemIdsArray) {
-    unpacker.app.saveState_(fileSystemIdsArray);
-  },
-
-  /**
    * Unmounts a volume and removes any resources related to the volume from both
    * the extension and the local storage state.
    * @param {!unpacker.types.FileSystemId} fileSystemId
@@ -595,8 +421,6 @@
         else
           unpacker.app.cleanupVolume(fileSystemId);
 
-        // Remove volume from local storage.
-        unpacker.app.removeState_(fileSystemId);
         fulfill();
       });
     });
@@ -919,9 +743,6 @@
                       fileSystemId, entry, {}, null /* passphrase */);
                   loadPromise
                       .then(function() {
-                        // Mount the volume and save its information in local
-                        // storage in order to be able to recover the metadata
-                        // in case of restarts, system crashes, etc.
                         chrome.fileSystemProvider.mount(
                             {
                               fileSystemId: fileSystemId,
@@ -934,9 +755,6 @@
                                 onError(chrome.runtime.lastError, fileSystemId);
                                 return;
                               }
-                              // Save state so in case of restarts we are able
-                              // to correctly get the archive's metadata.
-                              unpacker.app.saveState_([fileSystemId]);
                               onSuccess(fileSystemId);
                             });
                       })
@@ -974,13 +792,5 @@
       unpacker.app.onLaunchedWithPack(launchData);
     else
       unpacker.app.onLaunchedWithUnpack(launchData, opt_onSuccess, opt_onError);
-  },
-
-  /**
-   * Saves the state before suspending the event page, so we can resume it
-   * once new events arrive.
-   */
-  onSuspend: function() {
-    unpacker.app.saveState_(Object.keys(unpacker.app.volumes));
   }
 };
diff --git a/chrome/browser/resources/chromeos/zip_archiver/js/background.js b/chrome/browser/resources/chromeos/zip_archiver/js/background.js
index c9fe20e..173598a 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/js/background.js
+++ b/chrome/browser/resources/chromeos/zip_archiver/js/background.js
@@ -8,10 +8,6 @@
 // declared in the manifest file.
 chrome.app.runtime.onLaunched.addListener(unpacker.app.onLaunched);
 
-// Save the state before suspending the event page, so we can resume it
-// once new events arrive.
-chrome.runtime.onSuspend.addListener(unpacker.app.onSuspend);
-
 chrome.fileSystemProvider.onUnmountRequested.addListener(
     unpacker.app.onUnmountRequested);
 chrome.fileSystemProvider.onGetMetadataRequested.addListener(
diff --git a/chrome/browser/resources/chromeos/zip_archiver/js/decompressor.js b/chrome/browser/resources/chromeos/zip_archiver/js/decompressor.js
index aa1e986..87b0453 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/js/decompressor.js
+++ b/chrome/browser/resources/chromeos/zip_archiver/js/decompressor.js
@@ -42,8 +42,7 @@
   this.passphraseManager = passphraseManager;
 
   /**
-   * Requests in progress. No need to save them onSuspend for now as metadata
-   * reads are restarted from start.
+   * Requests in progress.
    * @public {!Object<!unpacker.types.RequestId, !Object>}
    * @const
    */
@@ -296,8 +295,6 @@
 unpacker.Decompressor.prototype.readPassphrase_ = function(data, requestId) {
   this.passphraseManager.getPassphrase()
       .then(function(passphrase) {
-        // Update remembered password
-        unpacker.app.updateState([this.fileSystemId_]);
         this.naclModule_.postMessage(
             unpacker.request.createReadPassphraseDoneResponse(
                 this.fileSystemId_, requestId, passphrase));
diff --git a/chrome/browser/resources/chromeos/zip_archiver/js/passphrase-dialog.js b/chrome/browser/resources/chromeos/zip_archiver/js/passphrase-dialog.js
index 4cc7936..2df9854c 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/js/passphrase-dialog.js
+++ b/chrome/browser/resources/chromeos/zip_archiver/js/passphrase-dialog.js
@@ -19,7 +19,7 @@
   },
 
   accept: function() {
-    window.onPassphraseSuccess(this.$.input.value, this.$.remember.checked);
+    window.onPassphraseSuccess(this.$.input.value);
     window.close();
   },
 
diff --git a/chrome/browser/resources/chromeos/zip_archiver/js/passphrase-manager.js b/chrome/browser/resources/chromeos/zip_archiver/js/passphrase-manager.js
index 71755e73..9c37e57 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/js/passphrase-manager.js
+++ b/chrome/browser/resources/chromeos/zip_archiver/js/passphrase-manager.js
@@ -4,38 +4,15 @@
 
 /**
  * @constructor
- * @param {?string} initPassphrase Initial passphrase for the first passphrase
- *     request or NULL if not available. In such case, call to getPassphrase()
- *     will invoke a dialog.
  */
-unpacker.PassphraseManager = function(initPassphrase) {
-  /**
-   * @private {?string}
-   */
-  this.initPassphrase_ = initPassphrase;
-
-  /**
-   * @public {?string}
-   */
-  this.rememberedPassphrase = initPassphrase;
-};
+unpacker.PassphraseManager = function() {};
 
 /**
- * Requests a passphrase from the user. If a passphrase was previously
- * remembered, then tries it first. Otherwise shows a passphrase dialog.
+ * Requests a passphrase from the user.
  * @return {!Promise<string>}
  */
 unpacker.PassphraseManager.prototype.getPassphrase = function() {
   return new Promise(function(fulfill, reject) {
-    // For the first passphrase request try the init passphrase (which may be
-    // incorrect though, so do it only once).
-    if (this.initPassphrase_ != null) {
-      fulfill(this.initPassphrase_);
-      this.initPassphrase_ = null;
-      return;
-    }
-
-    // Ask user for a passphrase.
     chrome.app.window.create(
         '../html/passphrase.html',
         /** @type {!chrome.app.window.CreateWindowOptions} */ ({
@@ -55,10 +32,8 @@
           }.bind(this));
 
           passphraseWindow.contentWindow.onPassphraseSuccess = function(
-                                                                   passphrase,
-                                                                   remember) {
+                                                                   passphrase) {
             passphraseSucceeded = true;
-            this.rememberedPassphrase = remember ? passphrase : null;
             fulfill(passphrase);
           }.bind(this);
         }.bind(this));
diff --git a/chrome/browser/resources/chromeos/zip_archiver/manifest.json b/chrome/browser/resources/chromeos/zip_archiver/manifest.json
index 456a436..3478c1c 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/manifest.json
+++ b/chrome/browser/resources/chromeos/zip_archiver/manifest.json
@@ -22,8 +22,7 @@
         "directory"
       ]
     },
-    "notifications",
-    "storage"
+    "notifications"
   ],
   "file_system_provider_capabilities": {
     "multipleMounts": true,
diff --git a/chrome/browser/resources/md_bookmarks/item.html b/chrome/browser/resources/md_bookmarks/item.html
index d0f8fdc..0bdd113 100644
--- a/chrome/browser/resources/md_bookmarks/item.html
+++ b/chrome/browser/resources/md_bookmarks/item.html
@@ -16,7 +16,6 @@
         display: flex;
         flex-direction: row;
         height: 40px;
-        overflow: hidden;
         position: relative;
         text-decoration: none;
         user-select: none;
diff --git a/chrome/browser/resources/md_bookmarks/list.html b/chrome/browser/resources/md_bookmarks/list.html
index f602f0d..19279163 100644
--- a/chrome/browser/resources/md_bookmarks/list.html
+++ b/chrome/browser/resources/md_bookmarks/list.html
@@ -14,6 +14,7 @@
   <template>
     <style include="shared-style">
       :host {
+        min-width: 300px;
         overflow-y: auto;
         padding: 24px var(--card-padding-side) 24px
             calc(var(--card-padding-side) - var(--splitter-width));
@@ -24,7 +25,6 @@
         background-color: #fff;
         margin: 0 auto;
         max-width: var(--card-max-width);
-        min-width: 300px;
         padding: 8px 0;
       }
 
@@ -38,6 +38,7 @@
         height: 100%;
         justify-content: center;
         user-select: none;
+        white-space: nowrap;
       }
     </style>
     <iron-list id="list"
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
index bcb20f60..fb27688c 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
@@ -44,7 +44,9 @@
           <div class="separator"></div>
           <paper-toggle-button id="enableBluetooth"
               checked="{{bluetoothToggleState_}}"
-              disabled$="[[bluetoothToggleDisabled_]]" on-tap="stopTap_"
+              disabled$=
+                  "[[!isToggleEnabled_(adapterState_, stateChangeInProgress_)]]"
+              on-tap="stopTap_"
               aria-label="$i18n{bluetoothToggleA11yLabel}">
           </paper-toggle-button>
         </div>
@@ -56,7 +58,7 @@
           <settings-bluetooth-subpage
               adapter-state="[[adapterState_]]"
               bluetooth-toggle-state="{{bluetoothToggleState_}}"
-              bluetooth-toggle-disabled="[[bluetoothToggleDisabled_]]"
+              state-change-in-progress="[[stateChangeInProgress_]]"
               bluetooth="[[bluetooth]]"
               bluetooth-private="[[bluetoothPrivate]]">
           </settings-bluetooth-subpage>
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
index 674bf08..73b88de 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
@@ -46,15 +46,14 @@
     },
 
     /**
-     * Set to true before the adapter state is received, when the adapter is
-     * unavailable, and while an adapter state change is requested. This
-     * prevents user changes while a change is in progress or when the adapter
-     * is not available.
+     * Set to true while an adapter state change is requested and the callback
+     * hasn't fired yet. One of the factor that determines whether to disable
+     * the toggle button.
      * @private
      */
-    bluetoothToggleDisabled_: {
+    stateChangeInProgress_: {
       type: Boolean,
-      value: true,
+      value: false,
     },
 
     /**
@@ -160,19 +159,28 @@
   },
 
   /**
+   * @return {boolean}
+   * @private
+   */
+  isToggleEnabled_: function() {
+    return this.adapterState_ !== undefined && this.adapterState_.available &&
+        !this.stateChangeInProgress_;
+  },
+
+  /**
    * Process bluetooth.onAdapterStateChanged events.
    * @param {!chrome.bluetooth.AdapterState} state
    * @private
    */
   onBluetoothAdapterStateChanged_: function(state) {
     this.adapterState_ = state;
-    this.bluetoothToggleState_ = state.powered;
-    this.bluetoothToggleDisabled_ = !state.available;
+    if (this.isToggleEnabled_())
+      this.bluetoothToggleState_ = state.powered;
   },
 
   /** @private */
   onTap_: function() {
-    if (this.adapterState_.available === false)
+    if (!this.isToggleEnabled_())
       return;
     if (!this.bluetoothToggleState_)
       this.bluetoothToggleState_ = true;
@@ -199,13 +207,17 @@
 
   /** @private */
   bluetoothToggleStateChanged_: function() {
-    if (!this.adapterState_ || this.bluetoothToggleDisabled_ ||
+    if (!this.adapterState_ || !this.isToggleEnabled_() ||
         this.bluetoothToggleState_ == this.adapterState_.powered) {
       return;
     }
-    this.bluetoothToggleDisabled_ = true;
+    this.stateChangeInProgress_ = true;
     this.bluetoothPrivate.setAdapterState(
         {powered: this.bluetoothToggleState_}, () => {
+          // Restore the in-progress mark when the callback is called regardless
+          // of error or success.
+          this.stateChangeInProgress_ = false;
+
           const error = chrome.runtime.lastError;
           if (error && error != 'Error setting adapter properties: powered') {
             console.error('Error enabling bluetooth: ' + error.message);
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html
index 4174281c..6ca9d1b 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html
@@ -46,7 +46,7 @@
       </div>
       <paper-toggle-button id="enableBluetooth"
           checked="{{bluetoothToggleState}}"
-          disabled$="[[bluetoothToggleDisabled]]"
+          disabled$="[[!isToggleEnabled_(adapterState, stateChangeInProgress)]]"
           aria-label="$i18n{bluetoothToggleA11yLabel}"
           on-tap="stopTap_">
       </paper-toggle-button>
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
index 4837656..d8d0ef3 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
@@ -31,7 +31,7 @@
     },
 
     /** Reflects the bluetooth-page property. */
-    bluetoothToggleDisabled: Boolean,
+    stateChangeInProgress: Boolean,
 
     /**
      * The bluetooth adapter state, cached by bluetooth-page.
@@ -379,7 +379,8 @@
    * @private
    */
   onEnableTap_: function(event) {
-    this.bluetoothToggleState = !this.bluetoothToggleState;
+    if (this.isToggleEnabled_())
+      this.bluetoothToggleState = !this.bluetoothToggleState;
     event.stopPropagation();
   },
 
@@ -395,6 +396,15 @@
   },
 
   /**
+   * @return {boolean}
+   * @private
+   */
+  isToggleEnabled_: function() {
+    return this.adapterState !== undefined && this.adapterState.available &&
+        !this.stateChangeInProgress;
+  },
+
+  /**
    * @param {boolean} bluetoothToggleState
    * @param {!Array<!chrome.bluetooth.Device>} deviceList
    * @return {boolean}
diff --git a/chrome/browser/ui/app_list/app_list_model_updater.h b/chrome/browser/ui/app_list/app_list_model_updater.h
index 5fdd64a8..d4c758c 100644
--- a/chrome/browser/ui/app_list/app_list_model_updater.h
+++ b/chrome/browser/ui/app_list/app_list_model_updater.h
@@ -13,6 +13,7 @@
 #include "ash/app_list/model/app_list_folder_item.h"
 #include "ash/app_list/model/app_list_model.h"
 #include "ash/app_list/model/search/search_result.h"
+#include "ash/public/interfaces/app_list.mojom.h"
 #include "base/strings/string16.h"
 
 class ChromeAppListItem;
@@ -44,7 +45,7 @@
   virtual void MoveItemToFolder(const std::string& id,
                                 const std::string& folder_id) {}
   virtual void SetStatus(app_list::AppListModel::Status status) {}
-  virtual void SetState(app_list::AppListModel::State state) {}
+  virtual void SetState(ash::AppListState state) {}
   virtual void HighlightItemInstalledFromUI(const std::string& id) {}
   // For SearchModel:
   virtual void SetSearchEngineIsGoogle(bool is_google) {}
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
index ea2febf..79cd61e 100644
--- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
+++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
@@ -55,7 +55,7 @@
   model_->SetStatus(status);
 }
 
-void ChromeAppListModelUpdater::SetState(app_list::AppListModel::State state) {
+void ChromeAppListModelUpdater::SetState(ash::AppListState state) {
   model_->SetState(state);
 }
 
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.h b/chrome/browser/ui/app_list/chrome_app_list_model_updater.h
index e9483b09..be0a6c4 100644
--- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.h
+++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.h
@@ -37,7 +37,7 @@
   void MoveItemToFolder(const std::string& id,
                         const std::string& folder_id) override;
   void SetStatus(app_list::AppListModel::Status status) override;
-  void SetState(app_list::AppListModel::State state) override;
+  void SetState(ash::AppListState state) override;
   void HighlightItemInstalledFromUI(const std::string& id) override;
   void SetSearchEngineIsGoogle(bool is_google) override;
   void SetSearchTabletAndClamshellAccessibleName(
diff --git a/chrome/browser/ui/ash/app_list/app_list_service_ash.cc b/chrome/browser/ui/ash/app_list/app_list_service_ash.cc
index fd682962..5ef963a 100644
--- a/chrome/browser/ui/ash/app_list/app_list_service_ash.cc
+++ b/chrome/browser/ui/ash/app_list/app_list_service_ash.cc
@@ -117,8 +117,7 @@
 void AppListServiceAsh::OnProfileWillBeRemoved(
     const base::FilePath& profile_path) {}
 
-void AppListServiceAsh::ShowAndSwitchToState(
-    app_list::AppListModel::State state) {
+void AppListServiceAsh::ShowAndSwitchToState(ash::AppListState state) {
   bool app_list_was_open = true;
   app_list::AppListView* app_list_view = app_list_presenter_->GetView();
   if (!app_list_view) {
@@ -131,7 +130,7 @@
     DCHECK(app_list_view);
   }
 
-  if (state == app_list::AppListModel::INVALID_STATE)
+  if (state == ash::AppListState::kInvalidState)
     return;
 
   app_list::ContentsView* contents_view =
@@ -155,7 +154,7 @@
                                           bool start_discovery_tracking) {
   if (app_list::features::IsFullscreenAppListEnabled())
     return;
-  ShowAndSwitchToState(app_list::AppListModel::STATE_APPS);
+  ShowAndSwitchToState(ash::AppListState::kStateApps);
   AppListServiceImpl::ShowForAppInstall(profile, extension_id,
                                         start_discovery_tracking);
 }
diff --git a/chrome/browser/ui/ash/app_list/app_list_service_ash.h b/chrome/browser/ui/ash/app_list/app_list_service_ash.h
index 064e8bc4..d5b6877 100644
--- a/chrome/browser/ui/ash/app_list/app_list_service_ash.h
+++ b/chrome/browser/ui/ash/app_list/app_list_service_ash.h
@@ -8,7 +8,7 @@
 #include <memory>
 #include <string>
 
-#include "ash/app_list/model/app_list_model.h"
+#include "ash/public/interfaces/app_list.mojom.h"
 #include "base/macros.h"
 #include "chrome/browser/ui/app_list/app_list_service_impl.h"
 
@@ -55,7 +55,7 @@
 
   // Shows the app list if it isn't already showing and Switches to |state|,
   // unless it is |INVALID_STATE| (in which case, opens on the default state).
-  void ShowAndSwitchToState(app_list::AppListModel::State state);
+  void ShowAndSwitchToState(ash::AppListState state);
 
   // AppListService overrides:
   base::FilePath GetProfilePath(const base::FilePath& user_data_dir) override;
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index d9bbcbd..1562a78b 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -542,8 +542,8 @@
       base::RecordAction(base::UserMetricsAction("Accel_Focus_Bookmarks"));
       FocusBookmarksToolbar(browser_);
       break;
-    case IDC_FOCUS_INFOBARS:
-      FocusInfobars(browser_);
+    case IDC_FOCUS_INACTIVE_POPUP_FOR_ACCESSIBILITY:
+      FocusInactivePopupForAccessibility(browser_);
       break;
     case IDC_FOCUS_NEXT_PANE:
       FocusNextPane(browser_);
@@ -1144,7 +1144,7 @@
   command_updater_.UpdateCommandEnabled(
       IDC_FOCUS_BOOKMARKS, main_not_fullscreen);
   command_updater_.UpdateCommandEnabled(
-      IDC_FOCUS_INFOBARS, main_not_fullscreen);
+      IDC_FOCUS_INACTIVE_POPUP_FOR_ACCESSIBILITY, main_not_fullscreen);
 
   // Show various bits of UI
   command_updater_.UpdateCommandEnabled(IDC_DEVELOPER_MENU, show_main_ui);
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index 31f3e73..3d3a2a1 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -1045,9 +1045,9 @@
   browser->window()->FocusBookmarksToolbar();
 }
 
-void FocusInfobars(Browser* browser) {
-  base::RecordAction(UserMetricsAction("FocusInfobars"));
-  browser->window()->FocusInfobars();
+void FocusInactivePopupForAccessibility(Browser* browser) {
+  base::RecordAction(UserMetricsAction("FocusInactivePopupForAccessibility"));
+  browser->window()->FocusInactivePopupForAccessibility();
 }
 
 void FocusNextPane(Browser* browser) {
diff --git a/chrome/browser/ui/browser_commands.h b/chrome/browser/ui/browser_commands.h
index 61a4715..464bcc6 100644
--- a/chrome/browser/ui/browser_commands.h
+++ b/chrome/browser/ui/browser_commands.h
@@ -131,7 +131,7 @@
 void FocusSearch(Browser* browser);
 void FocusAppMenu(Browser* browser);
 void FocusBookmarksToolbar(Browser* browser);
-void FocusInfobars(Browser* browser);
+void FocusInactivePopupForAccessibility(Browser* browser);
 void FocusNextPane(Browser* browser);
 void FocusPreviousPane(Browser* browser);
 void ToggleDevToolsWindow(Browser* browser, DevToolsToggleAction action);
diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h
index 5bd412f..5ade181 100644
--- a/chrome/browser/ui/browser_window.h
+++ b/chrome/browser/ui/browser_window.h
@@ -198,8 +198,8 @@
   // Focuses the bookmarks toolbar (for accessibility).
   virtual void FocusBookmarksToolbar() = 0;
 
-  // Focuses an infobar, if shown (for accessibility).
-  virtual void FocusInfobars() = 0;
+  // Focuses a visible but inactive popup for accessibility.
+  virtual void FocusInactivePopupForAccessibility() = 0;
 
   // Moves keyboard focus to the next pane.
   virtual void RotatePaneFocus(bool forwards) = 0;
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h
index 02ddc77..60e2261 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa.h
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h
@@ -90,7 +90,7 @@
   void ToolbarSizeChanged(bool is_animating) override;
   void FocusAppMenu() override;
   void FocusBookmarksToolbar() override;
-  void FocusInfobars() override;
+  void FocusInactivePopupForAccessibility() override;
   void RotatePaneFocus(bool forwards) override;
   bool IsBookmarkBarVisible() const override;
   bool IsBookmarkBarAnimating() const override;
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
index ed52278..27befeb 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
@@ -446,7 +446,7 @@
   // Not needed on the Mac.
 }
 
-void BrowserWindowCocoa::FocusInfobars() {
+void BrowserWindowCocoa::FocusInactivePopupForAccessibility() {
   // Not needed on the Mac.
 }
 
diff --git a/chrome/browser/ui/views/accelerator_table.cc b/chrome/browser/ui/views/accelerator_table.cc
index 4aa6cec..a932487 100644
--- a/chrome/browser/ui/views/accelerator_table.cc
+++ b/chrome/browser/ui/views/accelerator_table.cc
@@ -148,18 +148,18 @@
   // On Chrome OS, Search + Esc is used to call out task manager.
   { ui::VKEY_ESCAPE, ui::EF_COMMAND_DOWN, IDC_TASK_MANAGER },
 #else  // !OS_CHROMEOS
-  { ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN, IDC_TASK_MANAGER },
-  { ui::VKEY_LMENU, ui::EF_NONE, IDC_FOCUS_MENU_BAR },
-  { ui::VKEY_MENU, ui::EF_NONE, IDC_FOCUS_MENU_BAR },
-  { ui::VKEY_RMENU, ui::EF_NONE, IDC_FOCUS_MENU_BAR },
-  // On Windows, all VKEY_BROWSER_* keys except VKEY_BROWSER_SEARCH are handled
-  // via WM_APPCOMMAND.
-  { ui::VKEY_BROWSER_SEARCH, ui::EF_NONE, IDC_FOCUS_SEARCH },
-  { ui::VKEY_M, ui::EF_SHIFT_DOWN | kPlatformModifier, IDC_SHOW_AVATAR_MENU },
+    {ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN, IDC_TASK_MANAGER},
+    {ui::VKEY_LMENU, ui::EF_NONE, IDC_FOCUS_MENU_BAR},
+    {ui::VKEY_MENU, ui::EF_NONE, IDC_FOCUS_MENU_BAR},
+    {ui::VKEY_RMENU, ui::EF_NONE, IDC_FOCUS_MENU_BAR},
+    // On Windows, all VKEY_BROWSER_* keys except VKEY_BROWSER_SEARCH are
+    // handled via WM_APPCOMMAND.
+    {ui::VKEY_BROWSER_SEARCH, ui::EF_NONE, IDC_FOCUS_SEARCH},
+    {ui::VKEY_M, ui::EF_SHIFT_DOWN | kPlatformModifier, IDC_SHOW_AVATAR_MENU},
   // For each entry until the end of the !OS_CHROMEOS block, and an entry into
   // kChromeCmdId2AshActionId below if Ash has a corresponding accelerator.
 #if !defined(OS_MACOSX)
-  { ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_EXIT },
+    {ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_EXIT},
 #endif  // !OS_MACOSX
 #endif  // !OS_CHROMEOS
 
@@ -216,44 +216,44 @@
   { ui::VKEY_OEM_PERIOD, ui::EF_COMMAND_DOWN, IDC_STOP },
   { ui::VKEY_U, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN, IDC_VIEW_SOURCE },
 #else  // !OS_MACOSX
-  // Alt by itself (or with just shift) is never used on Mac since it's used
-  // to generate non-ASCII characters. Such commands are given Mac-specific
-  // bindings as well. Mapping with just Alt appear here, and should have an
-  // alternative mapping in the block above.
-  { ui::VKEY_LEFT, ui::EF_ALT_DOWN, IDC_BACK },
+    // Alt by itself (or with just shift) is never used on Mac since it's used
+    // to generate non-ASCII characters. Such commands are given Mac-specific
+    // bindings as well. Mapping with just Alt appear here, and should have an
+    // alternative mapping in the block above.
+    {ui::VKEY_LEFT, ui::EF_ALT_DOWN, IDC_BACK},
 #if BUILDFLAG(ENABLE_BASIC_PRINTING)
-  { ui::VKEY_P, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_BASIC_PRINT},
+    {ui::VKEY_P, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_BASIC_PRINT},
 #endif  // ENABLE_BASIC_PRINTING
 #if !defined(OS_CHROMEOS)
-  { ui::VKEY_DELETE, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
-    IDC_CLEAR_BROWSING_DATA },
+    {ui::VKEY_DELETE, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
+     IDC_CLEAR_BROWSING_DATA},
 #endif  // !OS_CHROMEOS
-  { ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_DEV_TOOLS },
-  { ui::VKEY_J, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
-    IDC_DEV_TOOLS_CONSOLE },
-  { ui::VKEY_C, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
-    IDC_DEV_TOOLS_INSPECT },
-  { ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, IDC_FOCUS_BOOKMARKS },
-  { ui::VKEY_A, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, IDC_FOCUS_INFOBARS },
-  { ui::VKEY_D, ui::EF_ALT_DOWN, IDC_FOCUS_LOCATION },
-  { ui::VKEY_E, ui::EF_CONTROL_DOWN, IDC_FOCUS_SEARCH },
-  { ui::VKEY_K, ui::EF_CONTROL_DOWN, IDC_FOCUS_SEARCH },
-  { ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, IDC_FOCUS_TOOLBAR },
-  { ui::VKEY_RIGHT, ui::EF_ALT_DOWN, IDC_FORWARD },
-  { ui::VKEY_HOME, ui::EF_ALT_DOWN, IDC_HOME },
-  { ui::VKEY_E, ui::EF_ALT_DOWN, IDC_SHOW_APP_MENU},
-  { ui::VKEY_F, ui::EF_ALT_DOWN, IDC_SHOW_APP_MENU},
-  { ui::VKEY_O, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
-    IDC_SHOW_BOOKMARK_MANAGER },
-  { ui::VKEY_J, ui::EF_CONTROL_DOWN, IDC_SHOW_DOWNLOADS },
-  { ui::VKEY_H, ui::EF_CONTROL_DOWN, IDC_SHOW_HISTORY },
-  { ui::VKEY_U, ui::EF_CONTROL_DOWN, IDC_VIEW_SOURCE },
+    {ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_DEV_TOOLS},
+    {ui::VKEY_J, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
+     IDC_DEV_TOOLS_CONSOLE},
+    {ui::VKEY_C, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
+     IDC_DEV_TOOLS_INSPECT},
+    {ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, IDC_FOCUS_BOOKMARKS},
+    {ui::VKEY_A, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN,
+     IDC_FOCUS_INACTIVE_POPUP_FOR_ACCESSIBILITY},
+    {ui::VKEY_D, ui::EF_ALT_DOWN, IDC_FOCUS_LOCATION},
+    {ui::VKEY_E, ui::EF_CONTROL_DOWN, IDC_FOCUS_SEARCH},
+    {ui::VKEY_K, ui::EF_CONTROL_DOWN, IDC_FOCUS_SEARCH},
+    {ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, IDC_FOCUS_TOOLBAR},
+    {ui::VKEY_RIGHT, ui::EF_ALT_DOWN, IDC_FORWARD},
+    {ui::VKEY_HOME, ui::EF_ALT_DOWN, IDC_HOME},
+    {ui::VKEY_E, ui::EF_ALT_DOWN, IDC_SHOW_APP_MENU},
+    {ui::VKEY_F, ui::EF_ALT_DOWN, IDC_SHOW_APP_MENU},
+    {ui::VKEY_O, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
+     IDC_SHOW_BOOKMARK_MANAGER},
+    {ui::VKEY_J, ui::EF_CONTROL_DOWN, IDC_SHOW_DOWNLOADS},
+    {ui::VKEY_H, ui::EF_CONTROL_DOWN, IDC_SHOW_HISTORY},
+    {ui::VKEY_U, ui::EF_CONTROL_DOWN, IDC_VIEW_SOURCE},
 #if !defined(OS_CHROMEOS)
-  // On Chrome OS, these keys are assigned to change UI scale.
-  { ui::VKEY_OEM_MINUS, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
-    IDC_ZOOM_MINUS },
-  { ui::VKEY_OEM_PLUS, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
-    IDC_ZOOM_PLUS },
+    // On Chrome OS, these keys are assigned to change UI scale.
+    {ui::VKEY_OEM_MINUS, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
+     IDC_ZOOM_MINUS},
+    {ui::VKEY_OEM_PLUS, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_ZOOM_PLUS},
 #endif  // !OS_CHROMEOS
 #endif  // OS_MACOSX
 };
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 1bb3be2..e0f5351 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1051,7 +1051,10 @@
   }
 }
 
-void BrowserView::FocusInfobars() {
+void BrowserView::FocusInactivePopupForAccessibility() {
+  if (GetLocationBarView()->ActivateFirstInactiveBubbleForAccessibility())
+    return;
+
   if (infobar_container_->child_count() > 0)
     infobar_container_->SetPaneFocusAndFocusDefault();
 }
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index d50db8d..b977395 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -309,7 +309,7 @@
   void ToolbarSizeChanged(bool is_animating) override;
   void FocusAppMenu() override;
   void FocusBookmarksToolbar() override;
-  void FocusInfobars() override;
+  void FocusInactivePopupForAccessibility() override;
   void RotatePaneFocus(bool forwards) override;
   void DestroyBrowser() override;
   bool IsBookmarkBarVisible() const override;
diff --git a/chrome/browser/ui/views/location_bar/bubble_icon_view.h b/chrome/browser/ui/views/location_bar/bubble_icon_view.h
index 1cdc5c7..c0069945 100644
--- a/chrome/browser/ui/views/location_bar/bubble_icon_view.h
+++ b/chrome/browser/ui/views/location_bar/bubble_icon_view.h
@@ -34,6 +34,9 @@
   // Invoked when a bubble for this icon is created.
   void OnBubbleCreated(LocationBarBubbleDelegateView* bubble);
 
+  // Returns the bubble instance for the icon.
+  virtual views::BubbleDialogDelegateView* GetBubble() const = 0;
+
  protected:
   enum ExecuteSource {
     EXECUTE_SOURCE_MOUSE,
@@ -93,9 +96,6 @@
   // Calls OnExecuting and runs |command_id_| with a valid |command_updater_|.
   virtual void ExecuteCommand(ExecuteSource source);
 
-  // Returns the bubble instance for the icon.
-  virtual views::BubbleDialogDelegateView* GetBubble() const = 0;
-
   // Gets the given vector icon in the correct color and size based on |active|.
   virtual const gfx::VectorIcon& GetVectorIcon() const = 0;
 
diff --git a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc
index 8cb5c9f..64d838a 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc
@@ -10,10 +10,13 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
 #include "chrome/browser/ui/layout_constants.h"
+#include "chrome/grit/generated_resources.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/render_view_host.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/views/accessibility/view_accessibility.h"
 
 LocationBarBubbleDelegateView::WebContentMouseHandler::WebContentMouseHandler(
     LocationBarBubbleDelegateView* bubble,
@@ -91,7 +94,16 @@
     GetWidget()->Show();
   } else {
     GetWidget()->ShowInactive();
+
+    // Since this widget is inactive (but shown), accessibility tools won't
+    // alert the user to its presence. Accessibility tools such as screen
+    // readers work by tracking system focus. Give users of these tools a hint
+    // description and alert them to the presence of this widget.
+    GetWidget()->GetRootView()->GetViewAccessibility().OverrideDescription(
+        l10n_util::GetStringUTF8(IDS_SHOW_BUBBLE_INACTIVE_DESCRIPTION));
   }
+  GetWidget()->GetRootView()->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT,
+                                                       true);
 }
 
 void LocationBarBubbleDelegateView::Observe(
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index fbb9f35d7..055db37b 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -40,6 +40,7 @@
 #include "chrome/browser/ui/views/autofill/save_card_icon_view.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h"
+#include "chrome/browser/ui/views/location_bar/bubble_icon_view.h"
 #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
 #include "chrome/browser/ui/views/location_bar/find_bar_icon.h"
 #include "chrome/browser/ui/views/location_bar/keyword_hint_view.h"
@@ -230,26 +231,31 @@
     AddChildView(image_view);
   }
 
-  auto add_icon = [this](BubbleIconView* icon_view) -> void {
-    icon_view->Init();
-    icon_view->SetVisible(false);
-    AddChildView(icon_view);
-  };
-
-  add_icon(zoom_view_ = new ZoomView(delegate_));
-  add_icon(manage_passwords_icon_view_ =
-               new ManagePasswordsIconViews(command_updater()));
+  bubble_icons_.push_back(zoom_view_ = new ZoomView(delegate_));
+  bubble_icons_.push_back(manage_passwords_icon_view_ =
+                              new ManagePasswordsIconViews(command_updater()));
   if (browser_)
-    add_icon(save_credit_card_icon_view_ =
-                 new autofill::SaveCardIconView(command_updater(), browser_));
-  add_icon(translate_icon_view_ = new TranslateIconView(command_updater()));
+    bubble_icons_.push_back(
+        save_credit_card_icon_view_ =
+            new autofill::SaveCardIconView(command_updater(), browser_));
+  bubble_icons_.push_back(translate_icon_view_ =
+                              new TranslateIconView(command_updater()));
 #if defined(OS_CHROMEOS)
   if (browser_)
-    add_icon(intent_picker_view_ = new IntentPickerView(browser_));
+    bubble_icons_.push_back(intent_picker_view_ =
+                                new IntentPickerView(browser_));
 #endif
-  add_icon(find_bar_icon_ = new FindBarIcon());
+  bubble_icons_.push_back(find_bar_icon_ = new FindBarIcon());
   if (browser_)
-    add_icon(star_view_ = new StarView(command_updater(), browser_));
+    bubble_icons_.push_back(star_view_ =
+                                new StarView(command_updater(), browser_));
+
+  std::for_each(bubble_icons_.begin(), bubble_icons_.end(),
+                [this](BubbleIconView* icon_view) -> void {
+                  icon_view->Init();
+                  icon_view->SetVisible(false);
+                  AddChildView(icon_view);
+                });
 
   clear_all_button_ = views::CreateVectorImageButton(this);
   clear_all_button_->SetTooltipText(
@@ -650,6 +656,22 @@
   omnibox_view_->ResetTabState(contents);
 }
 
+bool LocationBarView::ActivateFirstInactiveBubbleForAccessibility() {
+  auto result = std::find_if(
+      bubble_icons_.begin(), bubble_icons_.end(), [](BubbleIconView* view) {
+        if (!view || !view->visible() || !view->GetBubble())
+          return false;
+
+        views::Widget* widget = view->GetBubble()->GetWidget();
+        return widget && widget->IsVisible() && !widget->IsActive();
+      });
+
+  if (result != bubble_icons_.end())
+    (*result)->GetBubble()->GetWidget()->Show();
+
+  return result != bubble_icons_.end();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // LocationBarView, public OmniboxEditController implementation:
 
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h
index c8c8d46..ceaa68e 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -30,6 +30,7 @@
 #include "ui/views/controls/button/button.h"
 #include "ui/views/drag_controller.h"
 
+class BubbleIconView;
 class CommandUpdater;
 class ContentSettingBubbleModelDelegate;
 class FindBarIcon;
@@ -223,6 +224,10 @@
   // Clears the location bar's state for |contents|.
   void ResetTabState(content::WebContents* contents);
 
+  // Activates the first visible but inactive LocationBarBubbleDelegateView for
+  // accessibility.
+  bool ActivateFirstInactiveBubbleForAccessibility();
+
   // LocationBar:
   void FocusLocation(bool select_all) override;
   void Revert() override;
@@ -440,6 +445,9 @@
   // Tracks this preference to determine whether bookmark editing is allowed.
   BooleanPrefMember edit_bookmarks_enabled_;
 
+  // A list of all bubble descendants ordered by focus.
+  std::vector<BubbleIconView*> bubble_icons_;
+
   DISALLOW_COPY_AND_ASSIGN(LocationBarView);
 };
 
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view_interactive_uitest.cc b/chrome/browser/ui/views/location_bar/location_icon_view_interactive_uitest.cc
index 5207f82..9d6a04d 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/location_bar/location_icon_view_interactive_uitest.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/page_info/page_info_bubble_view.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/browser/ui/views/translate/translate_icon_view.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/interactive_test_utils.h"
 
@@ -49,4 +50,37 @@
             PageInfoBubbleView::GetShownBubbleType());
 }
 
+IN_PROC_BROWSER_TEST_F(LocationIconViewTest,
+                       ActivateFirstInactiveBubbleForAccessibility) {
+  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
+  LocationBarView* location_bar_view = browser_view->GetLocationBarView();
+  EXPECT_FALSE(
+      location_bar_view->ActivateFirstInactiveBubbleForAccessibility());
+
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  browser_view->ShowTranslateBubble(web_contents,
+                                    translate::TRANSLATE_STEP_AFTER_TRANSLATE,
+                                    translate::TranslateErrors::NONE, true);
+
+  BubbleIconView* icon_view = location_bar_view->translate_icon_view();
+  ASSERT_TRUE(icon_view);
+  EXPECT_TRUE(icon_view->visible());
+
+  // Ensure the bubble's widget is visible, but inactive. Active widgets are
+  // focused by accessibility, so not of concern.
+  views::Widget* widget = icon_view->GetBubble()->GetWidget();
+  widget->Deactivate();
+  widget->ShowInactive();
+  EXPECT_TRUE(widget->IsVisible());
+  EXPECT_FALSE(widget->IsActive());
+
+  EXPECT_TRUE(location_bar_view->ActivateFirstInactiveBubbleForAccessibility());
+
+  // Ensure the bubble's widget refreshed appropriately.
+  EXPECT_TRUE(icon_view->visible());
+  EXPECT_TRUE(widget->IsVisible());
+  EXPECT_TRUE(widget->IsActive());
+}
+
 }  // namespace
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui.cc b/chrome/browser/ui/webui/media_router/media_router_ui.cc
index 63b144e..f512a21 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_ui.cc
@@ -111,7 +111,7 @@
 // used by the Media Router to find such a matching route if it exists.
 MediaSource GetSourceForRouteObserver(const std::vector<MediaSource>& sources) {
   auto source_it =
-      std::find_if(sources.begin(), sources.end(), CanConnectToMediaSource);
+      std::find_if(sources.begin(), sources.end(), IsCastPresentationUrl);
   return source_it != sources.end() ? *source_it : MediaSource("");
 }
 
diff --git a/chrome/common/media_router/BUILD.gn b/chrome/common/media_router/BUILD.gn
index 6349c12..6dae758 100644
--- a/chrome/common/media_router/BUILD.gn
+++ b/chrome/common/media_router/BUILD.gn
@@ -34,4 +34,15 @@
     "route_request_result.cc",
     "route_request_result.h",
   ]
+
+  deps = []
+
+  if (!is_android) {
+    sources += [
+      "providers/cast/cast_media_source.cc",
+      "providers/cast/cast_media_source.h",
+    ]
+
+    deps += [ "//components/cast_channel:cast_channel" ]
+  }
 }
diff --git a/chrome/common/media_router/media_source_helper.cc b/chrome/common/media_router/media_source_helper.cc
index d7d892be..426e877 100644
--- a/chrome/common/media_router/media_source_helper.cc
+++ b/chrome/common/media_router/media_source_helper.cc
@@ -80,8 +80,7 @@
          IsTabMirroringMediaSource(source);
 }
 
-bool CanConnectToMediaSource(const MediaSource& source) {
-  // Compare host, port, scheme, and path prefix for source.url().
+bool IsCastPresentationUrl(const MediaSource& source) {
   const GURL& url = source.url();
   return url.SchemeIs(kCastPresentationUrlScheme) ||
          IsLegacyCastPresentationUrl(url);
diff --git a/chrome/common/media_router/media_source_helper.h b/chrome/common/media_router/media_source_helper.h
index 9ddd967c..8c1b5d0 100644
--- a/chrome/common/media_router/media_source_helper.h
+++ b/chrome/common/media_router/media_source_helper.h
@@ -51,9 +51,8 @@
 bool IsTabMirroringMediaSource(const MediaSource& source);
 bool IsMirroringMediaSource(const MediaSource& source);
 
-// Returns true if |source| is a media source type that can be connected to the
-// Presentation API by from a request initiated by the browser.
-bool CanConnectToMediaSource(const MediaSource& source);
+// Returns true if |source| is represents a Cast Presentation URL.
+bool IsCastPresentationUrl(const MediaSource& source);
 
 // Parses the |source| and returns the SessionTabHelper tab ID referencing a
 // source tab. Returns a non-positive value on error.
diff --git a/chrome/common/media_router/media_source_helper_unittest.cc b/chrome/common/media_router/media_source_helper_unittest.cc
index 8d004e6..bdfd7241c 100644
--- a/chrome/common/media_router/media_source_helper_unittest.cc
+++ b/chrome/common/media_router/media_source_helper_unittest.cc
@@ -53,24 +53,24 @@
   EXPECT_TRUE(IsValidPresentationUrl(GURL("cast:foo")));
 }
 
-TEST(MediaSourcesTest, CanConnectToMediaSource) {
-  EXPECT_TRUE(CanConnectToMediaSource(MediaSource(GURL("cast:233637DE"))));
-  EXPECT_TRUE(CanConnectToMediaSource(
+TEST(MediaSourcesTest, IsCastPresentationUrl) {
+  EXPECT_TRUE(IsCastPresentationUrl(MediaSource(GURL("cast:233637DE"))));
+  EXPECT_TRUE(IsCastPresentationUrl(
       MediaSource(GURL("https://google.com/cast#__castAppId__=233637DE"))));
   // false scheme
-  EXPECT_FALSE(CanConnectToMediaSource(
+  EXPECT_FALSE(IsCastPresentationUrl(
       MediaSource(GURL("http://google.com/cast#__castAppId__=233637DE"))));
   // false domain
-  EXPECT_FALSE(CanConnectToMediaSource(
+  EXPECT_FALSE(IsCastPresentationUrl(
       MediaSource(GURL("https://google2.com/cast#__castAppId__=233637DE"))));
   // empty path
   EXPECT_FALSE(
-      CanConnectToMediaSource(MediaSource(GURL("https://www.google.com"))));
+      IsCastPresentationUrl(MediaSource(GURL("https://www.google.com"))));
   // false path
-  EXPECT_FALSE(CanConnectToMediaSource(
-      MediaSource(GURL("https://www.google.com/path"))));
+  EXPECT_FALSE(
+      IsCastPresentationUrl(MediaSource(GURL("https://www.google.com/path"))));
 
-  EXPECT_FALSE(CanConnectToMediaSource(MediaSource(GURL(""))));
+  EXPECT_FALSE(IsCastPresentationUrl(MediaSource(GURL(""))));
 }
 
 }  // namespace media_router
diff --git a/chrome/common/media_router/providers/cast/DEPS b/chrome/common/media_router/providers/cast/DEPS
new file mode 100644
index 0000000..b2288536
--- /dev/null
+++ b/chrome/common/media_router/providers/cast/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+components/cast_channel",
+]
diff --git a/chrome/common/media_router/providers/cast/cast_media_source.cc b/chrome/common/media_router/providers/cast/cast_media_source.cc
new file mode 100644
index 0000000..aadd779
--- /dev/null
+++ b/chrome/common/media_router/providers/cast/cast_media_source.cc
@@ -0,0 +1,237 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/media_router/providers/cast/cast_media_source.h"
+
+#include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "chrome/common/media_router/media_source_helper.h"
+#include "net/base/url_util.h"
+#include "url/gurl.h"
+#include "url/url_util.h"
+
+namespace media_router {
+
+namespace {
+
+constexpr char kMirroringAppId[] = "0F5096E8";
+constexpr char kAudioMirroringAppId[] = "85CDB22F";
+
+// Parameter keys used by new Cast URLs.
+constexpr char kCapabilitiesKey[] = "capabilities";
+constexpr char kBroadcastNamespaceKey[] = "broadcastNamespace";
+constexpr char kBroadcastMessageKey[] = "broadcastMessage";
+
+// Parameter keys used by legacy Cast URLs.
+constexpr char kLegacyAppIdKey[] = "__castAppId__";
+constexpr char kLegacyBroadcastNamespaceKey[] = "__castBroadcastNamespace__";
+constexpr char kLegacyBroadcastMessageKey[] = "__castBroadcastMessage__";
+
+// TODO(imcheng): Move to common utils?
+std::string DecodeURLComponent(const std::string& encoded) {
+  url::RawCanonOutputT<base::char16> unescaped;
+  std::string output;
+  url::DecodeURLEscapeSequences(encoded.data(), encoded.size(), &unescaped);
+  if (base::UTF16ToUTF8(unescaped.data(), unescaped.length(), &output))
+    return output;
+
+  return std::string();
+}
+
+cast_channel::CastDeviceCapability CastDeviceCapabilityFromString(
+    const base::StringPiece& s) {
+  if (s == "video_out")
+    return cast_channel::CastDeviceCapability::VIDEO_OUT;
+  if (s == "video_in")
+    return cast_channel::CastDeviceCapability::VIDEO_IN;
+  if (s == "audio_out")
+    return cast_channel::CastDeviceCapability::AUDIO_OUT;
+  if (s == "audio_in")
+    return cast_channel::CastDeviceCapability::AUDIO_IN;
+  if (s == "multizone_group")
+    return cast_channel::CastDeviceCapability::MULTIZONE_GROUP;
+
+  return cast_channel::CastDeviceCapability::NONE;
+}
+
+std::unique_ptr<CastMediaSource> CastMediaSourceForTabMirroring(
+    const MediaSource::Id& source_id) {
+  return std::make_unique<CastMediaSource>(
+      source_id, std::vector<CastAppInfo>({CastAppInfo(kMirroringAppId),
+                                           CastAppInfo(kAudioMirroringAppId)}));
+}
+
+std::unique_ptr<CastMediaSource> CastMediaSourceForDesktopMirroring(
+    const MediaSource::Id& source_id) {
+// Desktop audio mirroring is only supported on some platforms.
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
+  return std::make_unique<CastMediaSource>(
+      source_id, std::vector<CastAppInfo>({CastAppInfo(kMirroringAppId),
+                                           CastAppInfo(kAudioMirroringAppId)}));
+#else
+  return std::make_unique<CastMediaSource>(
+      source_id, std::vector<CastAppInfo>({CastAppInfo(kMirroringAppId)}));
+#endif
+}
+
+std::unique_ptr<CastMediaSource> ParseCastUrl(const MediaSource::Id& source_id,
+                                              const GURL& url) {
+  std::string app_id = url.path();
+  // App ID must be non-empty.
+  if (app_id.empty())
+    return nullptr;
+
+  std::string broadcast_namespace, broadcast_message, capabilities;
+  for (net::QueryIterator query_it(url); !query_it.IsAtEnd();
+       query_it.Advance()) {
+    std::string key = query_it.GetKey();
+    std::string value = query_it.GetValue();
+    if (key.empty() || value.empty())
+      continue;
+    if (key == kBroadcastNamespaceKey) {
+      broadcast_namespace = value;
+    } else if (key == kBroadcastMessageKey) {
+      // The broadcast message is URL-encoded.
+      broadcast_message = DecodeURLComponent(value);
+    } else if (key == kCapabilitiesKey) {
+      capabilities = value;
+    }
+  }
+
+  CastAppInfo app_info(app_id);
+  if (!capabilities.empty()) {
+    for (const auto& capability :
+         base::SplitStringPiece(capabilities, ",", base::KEEP_WHITESPACE,
+                                base::SPLIT_WANT_NONEMPTY)) {
+      app_info.required_capabilities |=
+          CastDeviceCapabilityFromString(capability);
+    }
+  }
+
+  auto parsed = std::make_unique<CastMediaSource>(source_id, app_info);
+  if (!broadcast_namespace.empty() && !broadcast_message.empty()) {
+    parsed->set_broadcast_request(
+        BroadcastRequest(broadcast_namespace, broadcast_message));
+  }
+
+  return parsed;
+}
+
+std::unique_ptr<CastMediaSource> ParseLegacyCastUrl(
+    const MediaSource::Id& source_id,
+    const GURL& url) {
+  base::StringPairs parameters;
+  base::SplitStringIntoKeyValuePairs(url.ref(), '=', '/', &parameters);
+  // Legacy URLs can specify multiple apps.
+  std::vector<std::string> app_id_params;
+  std::string broadcast_namespace, broadcast_message;
+  for (const auto& key_value : parameters) {
+    const auto& key = key_value.first;
+    const auto& value = key_value.second;
+    if (key == kLegacyAppIdKey) {
+      app_id_params.push_back(value);
+    } else if (key == kLegacyBroadcastNamespaceKey) {
+      broadcast_namespace = value;
+    } else if (key == kLegacyBroadcastMessageKey) {
+      // The broadcast message is URL-encoded.
+      broadcast_message = DecodeURLComponent(value);
+    }
+  }
+
+  std::vector<CastAppInfo> app_infos;
+  for (const auto& app_id_param : app_id_params) {
+    std::string app_id;
+    std::string capabilities;
+    auto cap_start_index = app_id_param.find('(');
+    // If |cap_start_index| is |npos|, then this will return the entire string.
+    app_id = app_id_param.substr(0, cap_start_index);
+    if (cap_start_index != std::string::npos) {
+      auto cap_end_index = app_id_param.find(')', cap_start_index);
+      if (cap_end_index != std::string::npos &&
+          cap_end_index > cap_start_index) {
+        capabilities = app_id_param.substr(cap_start_index + 1,
+                                           cap_end_index - cap_start_index - 1);
+      }
+    }
+
+    if (app_id.empty())
+      continue;
+
+    CastAppInfo app_info(app_id);
+    for (const auto& capability :
+         base::SplitStringPiece(capabilities, ",", base::KEEP_WHITESPACE,
+                                base::SPLIT_WANT_NONEMPTY)) {
+      app_info.required_capabilities |=
+          CastDeviceCapabilityFromString(capability);
+    }
+
+    app_infos.push_back(app_info);
+  }
+
+  if (app_infos.empty())
+    return nullptr;
+
+  auto parsed =
+      std::make_unique<CastMediaSource>(source_id, std::move(app_infos));
+  return parsed;
+}
+
+}  // namespace
+
+CastAppInfo::CastAppInfo(const std::string& app_id) : app_id(app_id) {}
+CastAppInfo::~CastAppInfo() = default;
+
+CastAppInfo::CastAppInfo(const CastAppInfo& other) = default;
+
+BroadcastRequest::BroadcastRequest(const std::string& broadcast_namespace,
+                                   const std::string& message)
+    : broadcast_namespace(broadcast_namespace), message(message) {}
+BroadcastRequest::~BroadcastRequest() = default;
+
+// static
+std::unique_ptr<CastMediaSource> CastMediaSource::From(
+    const MediaSource::Id& source_id) {
+  MediaSource source(source_id);
+  if (IsTabMirroringMediaSource(source))
+    return CastMediaSourceForTabMirroring(source_id);
+
+  if (IsDesktopMirroringMediaSource(source))
+    return CastMediaSourceForDesktopMirroring(source_id);
+
+  const GURL& url = source.url();
+  if (!url.is_valid())
+    return nullptr;
+
+  if (url.SchemeIs(kCastPresentationUrlScheme)) {
+    return ParseCastUrl(source_id, url);
+  } else if (IsLegacyCastPresentationUrl(url)) {
+    return ParseLegacyCastUrl(source_id, url);
+  } else if (url.SchemeIsHTTPOrHTTPS()) {
+    // Arbitrary https URLs are supported via 1-UA mode which uses tab
+    // mirroring.
+    return CastMediaSourceForTabMirroring(source_id);
+  }
+
+  return nullptr;
+}
+
+CastMediaSource::CastMediaSource(const MediaSource::Id& source_id,
+                                 const CastAppInfo& app_info)
+    : source_id_(source_id), app_infos_({app_info}) {}
+CastMediaSource::CastMediaSource(const MediaSource::Id& source_id,
+                                 const std::vector<CastAppInfo>& app_infos)
+    : source_id_(source_id), app_infos_(app_infos) {}
+CastMediaSource::CastMediaSource(const CastMediaSource& other) = default;
+CastMediaSource::~CastMediaSource() = default;
+
+bool CastMediaSource::ContainsApp(const std::string& app_id) const {
+  for (const auto& info : app_infos_) {
+    if (info.app_id == app_id)
+      return true;
+  }
+  return false;
+}
+
+}  // namespace media_router
diff --git a/chrome/common/media_router/providers/cast/cast_media_source.h b/chrome/common/media_router/providers/cast/cast_media_source.h
new file mode 100644
index 0000000..6cafad16
--- /dev/null
+++ b/chrome/common/media_router/providers/cast/cast_media_source.h
@@ -0,0 +1,81 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_MEDIA_ROUTER_PROVIDERS_CAST_CAST_MEDIA_SOURCE_H_
+#define CHROME_COMMON_MEDIA_ROUTER_PROVIDERS_CAST_CAST_MEDIA_SOURCE_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/optional.h"
+#include "chrome/common/media_router/media_source.h"
+#include "components/cast_channel/cast_socket.h"
+
+namespace media_router {
+
+// Represents a Cast app and its capabilitity requirements.
+struct CastAppInfo {
+  explicit CastAppInfo(const std::string& app_id);
+  ~CastAppInfo();
+
+  CastAppInfo(const CastAppInfo& other);
+
+  std::string app_id;
+
+  // A bitset of capabilities required by the app.
+  int required_capabilities = cast_channel::CastDeviceCapability::NONE;
+};
+
+// Represents a broadcast request. Currently it is used for precaching data
+// on a receiver.
+struct BroadcastRequest {
+  BroadcastRequest(const std::string& broadcast_namespace,
+                   const std::string& message);
+  ~BroadcastRequest();
+
+  std::string broadcast_namespace;
+  std::string message;
+};
+
+// Represents a MediaSource parsed into structured, Cast specific data. The
+// following MediaSources can be parsed into CastMediaSource:
+// - Cast Presentation URLs
+// - HTTP(S) Presentation URLs
+// - Desktop / tab mirroring URNs
+class CastMediaSource {
+ public:
+  // Returns the parsed form of |source|, or nullptr if it cannot be parsed.
+  static std::unique_ptr<CastMediaSource> From(const MediaSource::Id& source);
+
+  explicit CastMediaSource(const MediaSource::Id& source_id,
+                           const CastAppInfo& app_info);
+  explicit CastMediaSource(const MediaSource::Id& source_id,
+                           const std::vector<CastAppInfo>& app_infos);
+  CastMediaSource(const CastMediaSource& other);
+  ~CastMediaSource();
+
+  // Returns |true| if |app_infos| contain |app_id|.
+  bool ContainsApp(const std::string& app_id) const;
+
+  const MediaSource::Id& source_id() const { return source_id_; }
+  const std::vector<CastAppInfo>& app_infos() const { return app_infos_; }
+  const base::Optional<BroadcastRequest>& broadcast_request() const {
+    return broadcast_request_;
+  }
+
+  void set_broadcast_request(const BroadcastRequest& request) {
+    broadcast_request_ = request;
+  }
+
+ private:
+  // TODO(imcheng): Fill in other parameters.
+  MediaSource::Id source_id_;
+  std::vector<CastAppInfo> app_infos_;
+  base::Optional<BroadcastRequest> broadcast_request_;
+};
+
+}  // namespace media_router
+
+#endif  // CHROME_COMMON_MEDIA_ROUTER_PROVIDERS_CAST_CAST_MEDIA_SOURCE_H_
diff --git a/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc b/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc
new file mode 100644
index 0000000..df72aab
--- /dev/null
+++ b/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc
@@ -0,0 +1,71 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/media_router/providers/cast/cast_media_source.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media_router {
+
+TEST(CastMediaSourceTest, FromCastURL) {
+  MediaSource::Id source_id("cast:ABCDEFAB?capabilities=video_out,audio_out");
+  std::unique_ptr<CastMediaSource> source = CastMediaSource::From(source_id);
+  ASSERT_TRUE(source);
+  EXPECT_EQ(source_id, source->source_id());
+  ASSERT_EQ(1u, source->app_infos().size());
+  const CastAppInfo& app_info = source->app_infos()[0];
+  EXPECT_EQ("ABCDEFAB", app_info.app_id);
+  EXPECT_EQ(cast_channel::CastDeviceCapability::VIDEO_OUT |
+                cast_channel::CastDeviceCapability::AUDIO_OUT,
+            app_info.required_capabilities);
+}
+
+TEST(CastMediaSourceTest, FromLegacyCastURL) {
+  MediaSource::Id source_id(
+      "https://google.com/cast#__castAppId__=ABCDEFAB(video_out,audio_out)");
+  std::unique_ptr<CastMediaSource> source = CastMediaSource::From(source_id);
+  ASSERT_TRUE(source);
+  EXPECT_EQ(source_id, source->source_id());
+  ASSERT_EQ(1u, source->app_infos().size());
+  const CastAppInfo& app_info = source->app_infos()[0];
+  EXPECT_EQ("ABCDEFAB", app_info.app_id);
+  EXPECT_EQ(cast_channel::CastDeviceCapability::VIDEO_OUT |
+                cast_channel::CastDeviceCapability::AUDIO_OUT,
+            app_info.required_capabilities);
+}
+
+TEST(CastMediaSourceTest, FromPresentationURL) {
+  MediaSource::Id source_id("https://google.com");
+  std::unique_ptr<CastMediaSource> source = CastMediaSource::From(source_id);
+  ASSERT_TRUE(source);
+  EXPECT_EQ(source_id, source->source_id());
+  ASSERT_EQ(2u, source->app_infos().size());
+  EXPECT_EQ("0F5096E8", source->app_infos()[0].app_id);
+  EXPECT_EQ("85CDB22F", source->app_infos()[1].app_id);
+}
+
+TEST(CastMediaSourceTest, FromMirroringURN) {
+  MediaSource::Id source_id("urn:x-org.chromium.media:source:tab:5");
+  std::unique_ptr<CastMediaSource> source = CastMediaSource::From(source_id);
+  ASSERT_TRUE(source);
+  EXPECT_EQ(source_id, source->source_id());
+  ASSERT_EQ(2u, source->app_infos().size());
+  EXPECT_EQ("0F5096E8", source->app_infos()[0].app_id);
+  EXPECT_EQ("85CDB22F", source->app_infos()[1].app_id);
+}
+
+TEST(CastMediaSourceTest, FromInvalidSource) {
+  EXPECT_FALSE(CastMediaSource::From("invalid:source"));
+  EXPECT_FALSE(CastMediaSource::From("file:///foo.mp4"));
+  EXPECT_FALSE(CastMediaSource::From(""));
+  EXPECT_FALSE(CastMediaSource::From("cast:"));
+
+  // Missing app ID.
+  EXPECT_FALSE(CastMediaSource::From("cast:?param=foo"));
+  EXPECT_FALSE(CastMediaSource::From(
+      "https://google.com/cast#__castAppId__=/param=foo"));
+}
+
+}  // namespace media_router
diff --git a/chrome/common/stack_sampling_configuration.h b/chrome/common/stack_sampling_configuration.h
index 452c4ee..5463971c 100644
--- a/chrome/common/stack_sampling_configuration.h
+++ b/chrome/common/stack_sampling_configuration.h
@@ -28,6 +28,25 @@
       GetSamplingParamsForCurrentProcess() const;
 
   // Returns true if the profiler should be started for the current process.
+  //
+  // This method must first be called from the main thread while the process is
+  // single-threaded. It is thereafter safe to call it concurrently from other
+  // threads.
+  //
+  // This method can be used via the following pattern:
+  // if
+  // (StackSamplingConfiguration::Get()->IsProfilerEnabledForCurrentProcess()) {
+  //   // start the profiler.
+  // }
+  //
+  // This method is currently called unsynchronized from two different threads
+  // (UI thread and IO thread). This is okay due to the following reasons.
+  //
+  // 1) The profile configuration (which is constant) is guaranteed to have
+  // already been created when this method is called from the IO thread, because
+  // of the access for the UI thread sampling.
+  //
+  // 2) The only other data accessed in this method is the command line.
   bool IsProfilerEnabledForCurrentProcess() const;
 
   // Get the synthetic field trial configuration. Returns true if a synthetic
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 24340a3..d3bbfc6 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -933,6 +933,7 @@
       "//mojo/common:common_base",
       "//net",
       "//net:test_support",
+      "//services/device/public/interfaces",
       "//services/service_manager/public/cpp",
       "//skia",
       "//testing/gmock",
@@ -3038,6 +3039,7 @@
       "../common/media_router/discovery/media_sink_internal_unittest.cc",
       "../common/media_router/discovery/media_sink_service_base_unittest.cc",
       "../common/media_router/mojo/media_router_struct_traits_unittest.cc",
+      "../common/media_router/providers/cast/cast_media_source_unittest.cc",
     ]
     deps += [ "//components/bubble:test_support" ]
 
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h
index 7f9292dc..e446371 100644
--- a/chrome/test/base/test_browser_window.h
+++ b/chrome/test/base/test_browser_window.h
@@ -82,7 +82,7 @@
   void ToolbarSizeChanged(bool is_animating) override {}
   void FocusAppMenu() override {}
   void FocusBookmarksToolbar() override {}
-  void FocusInfobars() override {}
+  void FocusInactivePopupForAccessibility() override {}
   void RotatePaneFocus(bool forwards) override {}
   void ShowAppMenu() override {}
   content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
diff --git a/chrome/test/base/ui_test_utils.cc b/chrome/test/base/ui_test_utils.cc
index 9593718..075feb4 100644
--- a/chrome/test/base/ui_test_utils.cc
+++ b/chrome/test/base/ui_test_utils.cc
@@ -62,7 +62,6 @@
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
 #include "device/geolocation/geolocation_provider.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "net/base/filename_util.h"
 #include "net/cookies/cookie_constants.h"
 #include "net/cookies/cookie_monster.h"
@@ -70,6 +69,7 @@
 #include "net/test/python_utils.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 #include "services/network/public/cpp/resource_request_body.h"
 #include "ui/gfx/geometry/rect.h"
 
diff --git a/chrome/test/chromedriver/BUILD.gn b/chrome/test/chromedriver/BUILD.gn
index 845a1eb..a7a8ce6a 100644
--- a/chrome/test/chromedriver/BUILD.gn
+++ b/chrome/test/chromedriver/BUILD.gn
@@ -347,11 +347,6 @@
   data_deps = [
     "//chrome/test/chromedriver",
   ]
-
-  if (is_win) {
-    # On Windows, the following target produces the final chrome.exe
-    data_deps += [ "//chrome:reorder_imports" ]
-  }
 }
 
 test("chromedriver_unittests") {
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index f806f77d..c103dc03 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -2711,16 +2711,9 @@
 
   options, args = parser.parse_args()
 
-  if options.chromedriver is None:
-    parser.error('--chromedriver is required.\n' +
-                 'Please run "%s --help" for help' % __file__)
   options.chromedriver = util.GetAbsolutePathOfUserPath(options.chromedriver)
-  if (not os.path.exists(options.chromedriver) and
-      util.GetPlatformName() == 'win' and
-      not options.chromedriver.lower().endswith('.exe')):
-    options.chromedriver = options.chromedriver + '.exe'
-  if not os.path.exists(options.chromedriver):
-    parser.error('Path given by --chromedriver is invalid.\n' +
+  if not options.chromedriver or not os.path.exists(options.chromedriver):
+    parser.error('chromedriver is required or the given path is invalid.' +
                  'Please run "%s --help" for help' % __file__)
 
   global _CHROMEDRIVER_BINARY
diff --git a/chrome/test/data/extensions/api_test/desktop_capture/test.js b/chrome/test/data/extensions/api_test/desktop_capture/test.js
index e69e9fc..7b19cd7c 100644
--- a/chrome/test/data/extensions/api_test/desktop_capture/test.js
+++ b/chrome/test/data/extensions/api_test/desktop_capture/test.js
@@ -135,10 +135,11 @@
   //  6. To actually get audio track, getUserMedia() should set audio
   //     constraint.
 
-  function tabShareWithAudioPermissionGetStream() {
-    chrome.desktopCapture.chooseDesktopMedia(
-        ["tab", "audio"], onPickerResult.bind(undefined, 1));
-  },
+  // TODO(crbug.com/805145): Test fails; invalid device IDs being generated.
+  // function tabShareWithAudioPermissionGetStream() {
+  //   chrome.desktopCapture.chooseDesktopMedia(
+  //       ["tab", "audio"], onPickerResult.bind(undefined, 1));
+  // },
 
   function windowShareWithAudioPermissionGetStream() {
     chrome.desktopCapture.chooseDesktopMedia(
@@ -152,10 +153,11 @@
                             expected_audio_tracks_for_screen_share));
   },
 
-  function tabShareWithoutAudioPermissionGetStream() {
-    chrome.desktopCapture.chooseDesktopMedia(
-        ["tab", "audio"], onPickerResult.bind(undefined, 0));
-  },
+  // TODO(crbug.com/805145): Test fails; invalid device IDs being generated.
+  // function tabShareWithoutAudioPermissionGetStream() {
+  //   chrome.desktopCapture.chooseDesktopMedia(
+  //       ["tab", "audio"], onPickerResult.bind(undefined, 0));
+  // },
 
   function windowShareWithoutAudioPermissionGetStream() {
     chrome.desktopCapture.chooseDesktopMedia(
diff --git a/chrome/test/data/webui/settings/bluetooth_page_tests.js b/chrome/test/data/webui/settings/bluetooth_page_tests.js
index 5523722..53e7b803 100644
--- a/chrome/test/data/webui/settings/bluetooth_page_tests.js
+++ b/chrome/test/data/webui/settings/bluetooth_page_tests.js
@@ -119,7 +119,7 @@
         subpage.listUpdateFrequencyMs = 0;
         assertTrue(!!subpage);
         assertTrue(subpage.bluetoothToggleState);
-        assertFalse(subpage.bluetoothToggleDisabled);
+        assertFalse(subpage.stateChangeInProgress);
         assertEquals(0, subpage.listUpdateFrequencyMs);
       });
     });
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index d18977f..5f675e02 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -562,6 +562,7 @@
     "SUPPORTS_MULTIZONE=$supports_multizone",
     "ENABLE_HEADLESS_MUSIC_MODE=$enable_headless_music_mode",
     "ENABLE_CHROMECAST_EXTENSIONS=$enable_chromecast_extensions",
+    "ENABLE_CAST_FRAGMENT=$enable_cast_fragment",
   ]
 }
 
diff --git a/chromecast/base/cast_sys_info_android.cc b/chromecast/base/cast_sys_info_android.cc
index 1c078c75..021f010 100644
--- a/chromecast/base/cast_sys_info_android.cc
+++ b/chromecast/base/cast_sys_info_android.cc
@@ -5,6 +5,8 @@
 #include "chromecast/base/cast_sys_info_android.h"
 
 #include <memory>
+#include <sys/system_properties.h>
+#include <string>
 
 #include "base/android/build_info.h"
 #include "base/android/jni_android.h"
@@ -19,6 +21,18 @@
 
 namespace {
 const char kBuildTypeUser[] = "user";
+
+std::string GetAndroidProperty(const std::string& key) {
+  char value[PROP_VALUE_MAX];
+  int ret = __system_property_get(key.c_str(), value);
+  if (ret < 0) {
+    LOG(ERROR) << "Failed to get property: " << key;
+    return "";
+  }
+
+  return std::string(value);
+}
+
 }  // namespace
 
 // static
@@ -93,7 +107,7 @@
 }
 
 std::string CastSysInfoAndroid::GetFactoryCountry() {
-  return "";
+  return GetAndroidProperty("ro.boot.wificountrycode");
 }
 
 std::string CastSysInfoAndroid::GetFactoryLocale(std::string* second_locale) {
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index b5e709c..92c35875 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -134,8 +134,8 @@
       "android/cast_content_window_android.cc",
       "android/cast_content_window_android.h",
       "android/cast_metrics_helper_android.cc",
-      "android/cast_web_contents_activity.cc",
-      "android/cast_web_contents_activity.h",
+      "android/cast_web_contents_surface_helper.cc",
+      "android/cast_web_contents_surface_helper.h",
     ]
     deps += [
       ":jni_headers",
@@ -361,7 +361,7 @@
       "android/apk/src/org/chromium/chromecast/shell/CastCrashHandler.java",
       "android/apk/src/org/chromium/chromecast/shell/CastMetricsHelper.java",
       "android/apk/src/org/chromium/chromecast/shell/CastSysInfoAndroid.java",
-      "android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java",
+      "android/apk/src/org/chromium/chromecast/shell/CastWebContentsSurfaceHelper.java",
     ]
 
     jni_package = "chromecast"
diff --git a/chromecast/browser/android/BUILD.gn b/chromecast/browser/android/BUILD.gn
index a72a708..aa83e547 100644
--- a/chromecast/browser/android/BUILD.gn
+++ b/chromecast/browser/android/BUILD.gn
@@ -32,6 +32,10 @@
     defines += [ "_DISPLAY_WEB_CONTENTS_IN_SERVICE" ]
   }
 
+  if (enable_cast_fragment) {
+    defines += [ "_ENABLE_CAST_FRAGMENT" ]
+  }
+
   # Set the logcat extractor size in lines.
   defines += [ "_LOGCAT_EXTRACTOR_SIZE=${logcat_extractor_size}" ]
 }
@@ -66,7 +70,9 @@
     "$java_src_dir/org/chromium/chromecast/shell/CastMetricsHelper.java",
     "$java_src_dir/org/chromium/chromecast/shell/CastSysInfoAndroid.java",
     "$java_src_dir/org/chromium/chromecast/shell/CastWebContentsActivity.java",
+    "$java_src_dir/org/chromium/chromecast/shell/CastWebContentsFragment.java",
     "$java_src_dir/org/chromium/chromecast/shell/CastWebContentsService.java",
+    "$java_src_dir/org/chromium/chromecast/shell/CastWebContentsSurfaceHelper.java",
     "$java_src_dir/org/chromium/chromecast/shell/CastWebContentsComponent.java",
     "$java_src_dir/org/chromium/chromecast/shell/LogcatElision.java",
     "$java_src_dir/org/chromium/chromecast/shell/LogcatExtractor.java",
diff --git a/chromecast/browser/android/apk/res/layout/cast_web_contents_activity.xml b/chromecast/browser/android/apk/res/layout/cast_web_contents_activity.xml
index 8413b9a..1098baa 100644
--- a/chromecast/browser/android/apk/res/layout/cast_web_contents_activity.xml
+++ b/chromecast/browser/android/apk/res/layout/cast_web_contents_activity.xml
@@ -5,11 +5,11 @@
      found in the LICENSE file.
  -->
 
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-    <FrameLayout android:id="@+id/web_contents_container"
-        android:background="#000000"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_weight="1">
-    </FrameLayout>
-</merge>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/web_contents_container"
+    android:background="#000000"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_weight="1">
+</FrameLayout>
+
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastIntents.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastIntents.java
index 869064c..a67c7f5 100644
--- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastIntents.java
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastIntents.java
@@ -9,8 +9,31 @@
  * the life cycle of CastWebContentsActivity.
  */
 public class CastIntents {
-    public static final String ACTION_STOP_ACTIVITY =
-            "com.google.android.apps.castshell.intent.action.STOP_ACTIVITY";
     public static final String ACTION_SCREEN_OFF =
             "com.google.android.apps.castshell.intent.action.ACTION_SCREEN_OFF";
+
+    /**
+     * Action type of intent from CastWebContentsComponent to host activity of
+     * CastWebContentsFragment to show web contents. (To start CastWebContentsActivity use
+     * Context.startActivity())
+     */
+    public static final String ACTION_SHOW_WEB_CONTENT = "com.google.assistant.SHOW_WEB_CONTENT";
+
+    /**
+     * Action type of intent from CastWebContentsComponent to mInternalStopReceiver to detach
+     * WebContents and then file an intent to CastWebContentsFragment's host activity to stop
+     * fragment.
+     */
+    public static final String ACTION_STOP_WEB_CONTENT = "com.google.assistant.STOP_WEB_CONTENT";
+
+    /**
+     * Action type of intent from CastWebContentsComponent to notify host activity of WebContents,
+     * either CastWebContentsActivity or external activity, the web content has been stopped.
+     * <p>
+     * ACTION_ON_WEB_CONTENT_STOP is filed after intent ACTION_STOP_WEB_CONTENT is handled.
+     * Both CastWebContentsAcitivty and external activity should handle this intent to either stop
+     * itself or remove the fragment, or anything else base on its own logic.
+     */
+    public static final String ACTION_ON_WEB_CONTENT_STOPPED =
+            "com.google.assistant.ON_WEB_CONTENT_STOPPED";
 }
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java
index c0e1be4..234dc2a 100644
--- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java
@@ -1,4 +1,4 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// 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.
 
@@ -9,11 +9,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.graphics.Color;
-import android.media.AudioManager;
+import android.net.Uri;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.PatternMatcher;
 import android.support.v4.content.LocalBroadcastManager;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -22,44 +19,25 @@
 import android.widget.FrameLayout;
 import android.widget.Toast;
 
+import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.content.browser.ActivityContentVideoViewEmbedder;
-import org.chromium.content.browser.ContentVideoViewEmbedder;
-import org.chromium.content.browser.ContentView;
-import org.chromium.content.browser.ContentViewCore;
-import org.chromium.content.browser.ContentViewRenderView;
 import org.chromium.content_public.browser.WebContents;
-import org.chromium.ui.base.ViewAndroidDelegate;
-import org.chromium.ui.base.WindowAndroid;
 
 /**
  * Activity for displaying a WebContents in CastShell.
  * <p>
- * Typically, this class is controlled by CastContentWindowAndroid, which will
+ * Typically, this class is controlled by CastContentWindowAndroid through
+ * CastWebContentsSurfaceHelper. CastContentWindowAndroid which will
  * start a new instance of this activity. If the CastContentWindowAndroid is
  * destroyed, CastWebContentsActivity should finish(). Similarily, if this
  * activity is destroyed, CastContentWindowAndroid should be notified by intent.
  */
-@JNINamespace("chromecast::shell")
 public class CastWebContentsActivity extends Activity {
     private static final String TAG = "cr_CastWebActivity";
     private static final boolean DEBUG = true;
 
-    private Handler mHandler;
-    private String mInstanceId;
-    private BroadcastReceiver mWindowDestroyedBroadcastReceiver;
-    private BroadcastReceiver mScreenOffBroadcastReceiver;
-    private FrameLayout mCastWebContentsLayout;
-    private CastAudioManager mAudioManager;
-    private ContentViewRenderView mContentViewRenderView;
-    private WindowAndroid mWindow;
-    private ContentViewCore mContentViewCore;
-    private ContentView mContentView;
+    private CastWebContentsSurfaceHelper mSurfaceHelper;
     private boolean mReceivedUserLeave = false;
-    private boolean mIsTouchInputEnabled = false;
-
-    private static final int TEARDOWN_GRACE_PERIOD_TIMEOUT_MILLIS = 300;
 
     /*
      * Intended to be called from "onStop" to determine if this is a "legitimate" stop or not.
@@ -77,7 +55,6 @@
         if (DEBUG) Log.d(TAG, "onCreate");
         super.onCreate(savedInstanceState);
 
-        mHandler = new Handler();
 
         if (!CastBrowserHelper.initializeBrowser(getApplicationContext())) {
             Toast.makeText(this, R.string.browser_process_initialization_failed, Toast.LENGTH_SHORT)
@@ -85,87 +62,62 @@
             finish();
         }
 
-        // Whenever our app is visible, volume controls should modify the music stream.
-        // For more information read:
-        // http://developer.android.com/training/managing-audio/volume-playback.html
-        setVolumeControlStream(AudioManager.STREAM_MUSIC);
-
         // Set flags to both exit sleep mode when this activity starts and
         // avoid entering sleep mode while playing media. We cannot distinguish
         // between video and audio so this applies to both.
         getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
         getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
 
-        mAudioManager = CastAudioManager.getAudioManager(this);
-
         setContentView(R.layout.cast_web_contents_activity);
-        mCastWebContentsLayout = (FrameLayout) findViewById(R.id.web_contents_container);
 
-        Intent intent = getIntent();
-        handleIntent(intent);
+        mSurfaceHelper = new CastWebContentsSurfaceHelper(this, /* hostActivity */
+                (FrameLayout) findViewById(R.id.web_contents_container),
+                false /* showInFragment */);
+
+        // Receiver to handle on web content stopped event
+        BroadcastReceiver stopEventReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (DEBUG) Log.d(TAG, "Intent action=" + intent.getAction());
+                getLocalBroadcastManager().unregisterReceiver(this);
+                finish();
+            }
+        };
+        IntentFilter stopReceiverFilter = new IntentFilter();
+        stopReceiverFilter.addAction(CastIntents.ACTION_ON_WEB_CONTENT_STOPPED);
+        getLocalBroadcastManager().registerReceiver(stopEventReceiver, stopReceiverFilter);
+
+        handleIntent(getIntent());
+    }
+
+    private LocalBroadcastManager getLocalBroadcastManager() {
+        return LocalBroadcastManager.getInstance(ContextUtils.getApplicationContext());
     }
 
     protected void handleIntent(Intent intent) {
+        final Bundle bundle = intent.getExtras();
+        final String uriString = bundle.getString(CastWebContentsComponent.INTENT_EXTRA_URI);
+        if (uriString == null) {
+            Log.i(TAG, "Intent without uri received!");
+            return;
+        }
+        final Uri uri = Uri.parse(uriString);
+
         // Do not load the WebContents if we are simply bringing the same
         // activity to the foreground.
-        if (intent.getData() == null || intent.getData().getPath() == null
-                || (mInstanceId != null && mInstanceId.equals(intent.getData().getPath()))) {
+        if (mSurfaceHelper.getInstanceId() != null
+                && mSurfaceHelper.getInstanceId().equals(uri.getPath())) {
+            Log.i(TAG, "Duplicated intent received!");
             return;
         }
 
-        intent.setExtrasClassLoader(WebContents.class.getClassLoader());
-        mInstanceId = intent.getData().getPath();
-
-        if (mWindowDestroyedBroadcastReceiver != null) {
-            LocalBroadcastManager.getInstance(this).unregisterReceiver(
-                    mWindowDestroyedBroadcastReceiver);
-        }
-
-        mWindowDestroyedBroadcastReceiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                detachWebContentsIfAny();
-                maybeFinishLater();
-            }
-        };
-
-        IntentFilter windowDestroyedIntentFilter = new IntentFilter();
-        windowDestroyedIntentFilter.addDataScheme(intent.getData().getScheme());
-        windowDestroyedIntentFilter.addDataAuthority(intent.getData().getAuthority(), null);
-        windowDestroyedIntentFilter.addDataPath(mInstanceId, PatternMatcher.PATTERN_LITERAL);
-        windowDestroyedIntentFilter.addAction(CastIntents.ACTION_STOP_ACTIVITY);
-        LocalBroadcastManager.getInstance(this).registerReceiver(
-                mWindowDestroyedBroadcastReceiver, windowDestroyedIntentFilter);
-
-        if (mScreenOffBroadcastReceiver != null) {
-            LocalBroadcastManager.getInstance(this).unregisterReceiver(mScreenOffBroadcastReceiver);
-        }
-
-        mScreenOffBroadcastReceiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                detachWebContentsIfAny();
-                maybeFinishLater();
-            }
-        };
-
-        IntentFilter screenOffIntentFilter = new IntentFilter();
-        screenOffIntentFilter.addAction(CastIntents.ACTION_SCREEN_OFF);
-        LocalBroadcastManager.getInstance(this).registerReceiver(
-                mScreenOffBroadcastReceiver, screenOffIntentFilter);
-
-        WebContents webContents = (WebContents) intent.getParcelableExtra(
+        bundle.setClassLoader(WebContents.class.getClassLoader());
+        final WebContents webContents = (WebContents) bundle.getParcelable(
                 CastWebContentsComponent.ACTION_EXTRA_WEB_CONTENTS);
-        mIsTouchInputEnabled = intent.getBooleanExtra(
-                CastWebContentsComponent.ACTION_EXTRA_TOUCH_INPUT_ENABLED, false);
 
-        if (webContents == null) {
-            Log.e(TAG, "Received null WebContents in intent.");
-            maybeFinishLater();
-            return;
-        }
-
-        showWebContents(webContents);
+        boolean touchInputEnabled =
+                bundle.getBoolean(CastWebContentsComponent.ACTION_EXTRA_TOUCH_INPUT_ENABLED, false);
+        mSurfaceHelper.onNewWebContents(uri, webContents, touchInputEnabled);
     }
 
     @Override
@@ -186,22 +138,6 @@
         handleIntent(intent);
     }
 
-    @Override
-    protected void onDestroy() {
-        if (DEBUG) Log.d(TAG, "onDestroy");
-
-        detachWebContentsIfAny();
-
-        if (mWindowDestroyedBroadcastReceiver != null) {
-            LocalBroadcastManager.getInstance(this).unregisterReceiver(
-                    mWindowDestroyedBroadcastReceiver);
-        }
-
-        if (mScreenOffBroadcastReceiver != null) {
-            LocalBroadcastManager.getInstance(this).unregisterReceiver(mScreenOffBroadcastReceiver);
-        }
-        super.onDestroy();
-    }
 
     @Override
     protected void onStart() {
@@ -210,40 +146,37 @@
     }
 
     @Override
+    protected void onPause() {
+        if (DEBUG) Log.d(TAG, "onPause");
+        super.onPause();
+
+        if (mSurfaceHelper != null) {
+            mSurfaceHelper.onPause();
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        if (DEBUG) Log.d(TAG, "onResume");
+        super.onResume();
+        if (mSurfaceHelper != null) {
+            mSurfaceHelper.onResume();
+        }
+    }
+
+    @Override
     protected void onStop() {
         if (DEBUG) Log.d(TAG, "onStop");
         super.onStop();
     }
 
     @Override
-    protected void onResume() {
-        if (DEBUG) Log.d(TAG, "onResume");
-        super.onResume();
-
-        if (mAudioManager.requestAudioFocus(
-                    null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN)
-                != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
-            Log.e(TAG, "Failed to obtain audio focus");
+    protected void onDestroy() {
+        if (DEBUG) Log.d(TAG, "onDestroy");
+        if (mSurfaceHelper != null) {
+            mSurfaceHelper.onDestroy();
         }
-        if (mContentViewCore != null) {
-            mContentViewCore.onResume();
-        }
-    }
-
-    @Override
-    protected void onPause() {
-        if (DEBUG) Log.d(TAG, "onPause");
-        super.onPause();
-
-        // Release the audio focus. Note that releasing audio focus does not stop audio playback,
-        // it just notifies the framework that this activity has stopped playing audio.
-        if (mAudioManager.abandonAudioFocus(null) != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
-            Log.e(TAG, "Failed to abandon audio focus");
-        }
-        if (mContentViewCore != null) {
-            mContentViewCore.onPause();
-        }
-        releaseStreamMuteIfNecessary();
+        super.onDestroy();
     }
 
     @Override
@@ -280,7 +213,7 @@
                     || keyCode == KeyEvent.KEYCODE_MEDIA_STOP
                     || keyCode == KeyEvent.KEYCODE_MEDIA_NEXT
                     || keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS) {
-                CastWebContentsComponent.onKeyDown(this, mInstanceId, keyCode);
+                CastWebContentsComponent.onKeyDown(this, mSurfaceHelper.getInstanceId(), keyCode);
 
                 // Stop key should end the entire session.
                 if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP) {
@@ -311,7 +244,7 @@
 
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
-        if (mIsTouchInputEnabled) {
+        if (mSurfaceHelper.isTouchInputEnabled()) {
             return super.dispatchTouchEvent(ev);
         } else {
             return false;
@@ -322,98 +255,4 @@
     public boolean dispatchTrackballEvent(MotionEvent ev) {
         return false;
     }
-
-    @SuppressWarnings("deprecation")
-    private void releaseStreamMuteIfNecessary() {
-        AudioManager audioManager = mAudioManager.getInternal();
-        boolean isMuted = false;
-        try {
-            isMuted = (Boolean) audioManager.getClass()
-                    .getMethod("isStreamMute", int.class)
-                    .invoke(audioManager, AudioManager.STREAM_MUSIC);
-        } catch (Exception e) {
-            Log.e(TAG, "Cannot call AudioManager.isStreamMute().", e);
-        }
-
-        if (isMuted) {
-            // Note: this is a no-op on fixed-volume devices.
-            audioManager.setStreamMute(AudioManager.STREAM_MUSIC, false);
-        }
-    }
-
-    // Closes this activity if a new WebContents is not being displayed.
-    private void maybeFinishLater() {
-        Log.d(TAG, "maybeFinishLater");
-        final String currentInstanceId = mInstanceId;
-        mHandler.postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                if (currentInstanceId.equals(mInstanceId)) {
-                    Log.d(TAG, "Finishing.");
-                    finish();
-                }
-            }
-        }, TEARDOWN_GRACE_PERIOD_TIMEOUT_MILLIS);
-    }
-
-    // Sets webContents to be the currently displayed webContents.
-    private void showWebContents(WebContents webContents) {
-        if (DEBUG) Log.d(TAG, "showWebContents");
-
-        detachWebContentsIfAny();
-
-        // Set ContentVideoViewEmbedder to allow video playback.
-        nativeSetContentVideoViewEmbedder(webContents, new ActivityContentVideoViewEmbedder(this));
-
-        // TODO(thoren): Find a way to reuse some of this for efficiency.
-        mWindow = new WindowAndroid(this);
-        mContentViewRenderView = new ContentViewRenderView(this) {
-            @Override
-            protected void onReadyToRender() {
-                setOverlayVideoMode(true);
-            }
-        };
-        mContentViewRenderView.onNativeLibraryLoaded(mWindow);
-        // Setting the background color to black avoids rendering a white splash screen
-        // before the players are loaded. See crbug/307113 for details.
-        mContentViewRenderView.setSurfaceViewBackgroundColor(Color.BLACK);
-
-        mCastWebContentsLayout.addView(mContentViewRenderView,
-                new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
-                        FrameLayout.LayoutParams.MATCH_PARENT));
-
-        // TODO(derekjchow): productVersion
-        mContentViewCore = ContentViewCore.create(this, "");
-        mContentView = ContentView.createContentView(this, mContentViewCore);
-        mContentViewCore.initialize(ViewAndroidDelegate.createBasicDelegate(mContentView),
-                mContentView, webContents, mWindow);
-        // Enable display of current webContents.
-        if (getParent() != null) mContentViewCore.onShow();
-        mCastWebContentsLayout.addView(mContentView,
-                new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
-                        FrameLayout.LayoutParams.MATCH_PARENT));
-        mContentView.requestFocus();
-        mContentViewRenderView.setCurrentContentViewCore(mContentViewCore);
-    }
-
-    // Remove the currently displayed webContents. no-op if nothing is being displayed.
-    private void detachWebContentsIfAny() {
-        if (DEBUG) Log.d(TAG, "detachWebContentsIfAny");
-        if (mContentView != null) {
-            mCastWebContentsLayout.removeView(mContentView);
-            mCastWebContentsLayout.removeView(mContentViewRenderView);
-            mContentViewCore.destroy();
-            mContentViewRenderView.destroy();
-            mWindow.destroy();
-            mContentView = null;
-            mContentViewCore = null;
-            mContentViewRenderView = null;
-            mWindow = null;
-
-            CastWebContentsComponent.onComponentClosed(this, mInstanceId);
-        }
-    }
-
-    private native void nativeSetContentVideoViewEmbedder(
-            WebContents webContents, ContentVideoViewEmbedder embedder);
 }
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsComponent.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsComponent.java
index da69dd7..3b527d3 100644
--- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsComponent.java
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsComponent.java
@@ -12,9 +12,9 @@
 import android.content.ServiceConnection;
 import android.net.Uri;
 import android.os.IBinder;
-import android.os.PatternMatcher;
 import android.support.v4.content.LocalBroadcastManager;
 
+import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.content_public.browser.WebContents;
 
@@ -43,7 +43,7 @@
     }
 
     private class ActivityDelegate implements Delegate {
-        private static final String TAG = "cr_CastWebComponent_AD";
+        private static final String TAG = "cr_CastWebContent_AD";
         private boolean mEnableTouchInput;
 
         public ActivityDelegate(boolean enableTouchInput) {
@@ -52,28 +52,68 @@
 
         @Override
         public void start(Context context, WebContents webContents) {
-            if (DEBUG) Log.d(TAG, "start");
-
-            Intent intent = new Intent(Intent.ACTION_VIEW, getInstanceUri(mInstanceId), context,
-                    CastWebContentsActivity.class);
-            intent.putExtra(ACTION_EXTRA_WEB_CONTENTS, webContents);
-            intent.putExtra(ACTION_EXTRA_TOUCH_INPUT_ENABLED, mEnableTouchInput);
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
-            context.startActivity(intent);
+            if (DEBUG) Log.d(TAG, "start: SHOW_WEB_CONTENT in activity");
+            startCastActivity(context, webContents, mEnableTouchInput);
         }
 
         @Override
         public void stop(Context context) {
-            if (DEBUG) Log.d(TAG, "stop");
+            if (DEBUG) Log.d(TAG, "Stop CastWebContentsActivity");
+            Intent intent = new Intent(CastIntents.ACTION_STOP_WEB_CONTENT);
+            intent.putExtra(INTENT_EXTRA_URI, getInstanceUri(mInstanceId).toString());
+            if (DEBUG) Log.d(TAG, "stop: send STOP_WEB_CONTENT intent");
+            getLocalBroadcastManager().sendBroadcastSync(intent);
+        }
+    }
 
-            Intent intent =
-                    new Intent(CastIntents.ACTION_STOP_ACTIVITY, getInstanceUri(mInstanceId));
-            LocalBroadcastManager.getInstance(context).sendBroadcastSync(intent);
+    private void startCastActivity(Context context, WebContents webContents, boolean enableTouch) {
+        Intent intent =
+                new Intent(Intent.ACTION_VIEW, null, context, CastWebContentsActivity.class);
+        intent.putExtra(INTENT_EXTRA_URI, getInstanceUri(mInstanceId).toString());
+        intent.putExtra(ACTION_EXTRA_WEB_CONTENTS, webContents);
+        intent.putExtra(ACTION_EXTRA_TOUCH_INPUT_ENABLED, enableTouch);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
+        if (DEBUG) Log.d(TAG, "start activity by intent: " + intent);
+        context.startActivity(intent);
+    }
+
+    private void sendStopWebContentEvent() {
+        Intent intent = new Intent(CastIntents.ACTION_STOP_WEB_CONTENT);
+        intent.putExtra(INTENT_EXTRA_URI, getInstanceUri(mInstanceId).toString());
+        if (DEBUG) Log.d(TAG, "stop: send STOP_WEB_CONTENT intent: " + intent);
+        getLocalBroadcastManager().sendBroadcastSync(intent);
+    }
+
+    private class FragmentDelegate implements Delegate {
+        private static final String TAG = "cr_CastWebContent_FD";
+        private boolean mEnableTouchInput;
+
+        public FragmentDelegate(boolean enableTouchInput) {
+            mEnableTouchInput = enableTouchInput;
+        }
+
+        @Override
+        public void start(Context context, WebContents webContents) {
+            if (DEBUG) Log.d(TAG, "state: SHOW_WEB_CONTENT in fragment");
+            Intent intent = new Intent();
+            intent.setAction(CastIntents.ACTION_SHOW_WEB_CONTENT);
+            intent.putExtra(INTENT_EXTRA_URI, getInstanceUri(mInstanceId).toString());
+            intent.putExtra(ACTION_EXTRA_WEB_CONTENTS, webContents);
+            intent.putExtra(ACTION_EXTRA_TOUCH_INPUT_ENABLED, mEnableTouchInput);
+            if (!getLocalBroadcastManager().sendBroadcast(intent)) {
+                // No intent receiver to handle SHOW_WEB_CONTENT in fragment
+                startCastActivity(context, webContents, mEnableTouchInput);
+            }
+        }
+
+        @Override
+        public void stop(Context context) {
+            sendStopWebContentEvent();
         }
     }
 
     private class ServiceDelegate implements Delegate {
-        private static final String TAG = "cr_CastWebComponent_SD";
+        private static final String TAG = "cr_CastWebContent_SD";
 
         private ServiceConnection mConnection = new ServiceConnection() {
             @Override
@@ -121,6 +161,8 @@
         }
     }
 
+    static final String INTENT_EXTRA_URI = "content_uri";
+
     static final String ACTION_DATA_SCHEME = "cast";
     static final String ACTION_DATA_AUTHORITY = "webcontents";
     static final String ACTION_EXTRA_WEB_CONTENTS =
@@ -129,7 +171,7 @@
             "com.google.android.apps.castshell.intent.extra.ENABLE_TOUCH";
 
     private static final String TAG = "cr_CastWebComponent";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;
 
     private static final String ACTION_EXTRA_KEY_CODE =
             "com.google.android.apps.castshell.intent.extra.KEY_CODE";
@@ -138,9 +180,9 @@
     private static final String ACTION_ACTIVITY_STOPPED =
             "com.google.android.apps.castshell.intent.action.ACTIVITY_STOPPED";
 
-    private Delegate mDelegate;
-    private OnComponentClosedHandler mComponentClosedHandler;
-    private OnKeyDownHandler mKeyDownHandler;
+    private final Delegate mDelegate;
+    private final OnComponentClosedHandler mComponentClosedHandler;
+    private final OnKeyDownHandler mKeyDownHandler;
     private Receiver mReceiver;
     private String mInstanceId;
     private boolean mStarted = false;
@@ -152,34 +194,36 @@
         mKeyDownHandler = onKeyDownHandler;
         mInstanceId = instanceId;
         if (BuildConfig.DISPLAY_WEB_CONTENTS_IN_SERVICE || isHeadless) {
+            if (DEBUG) Log.d(TAG, "Creating service delegate...");
             mDelegate = new ServiceDelegate();
+        } else if (BuildConfig.ENABLE_CAST_FRAGMENT) {
+            if (DEBUG) Log.d(TAG, "Creating fragment delegate...");
+            mDelegate = new FragmentDelegate(enableTouchInput);
         } else {
+            if (DEBUG) Log.d(TAG, "Creating activity delegate...");
             mDelegate = new ActivityDelegate(enableTouchInput);
         }
     }
 
     public void start(Context context, WebContents webContents) {
-        if (DEBUG) Log.d(TAG, "start");
+        if (DEBUG) Log.d(TAG, "start with delegate: " + mDelegate.getClass().getSimpleName());
 
         Uri instanceUri = getInstanceUri(mInstanceId);
         mReceiver = new Receiver();
         IntentFilter filter = new IntentFilter();
-        filter.addDataScheme(instanceUri.getScheme());
-        filter.addDataAuthority(instanceUri.getAuthority(), null);
-        filter.addDataPath(instanceUri.getPath(), PatternMatcher.PATTERN_LITERAL);
         filter.addAction(ACTION_ACTIVITY_STOPPED);
         filter.addAction(ACTION_KEY_EVENT);
-        LocalBroadcastManager.getInstance(context).registerReceiver(mReceiver, filter);
+
+        getLocalBroadcastManager().registerReceiver(mReceiver, filter);
 
         mDelegate.start(context, webContents);
-
         mStarted = true;
     }
 
     public void stop(Context context) {
         if (DEBUG) Log.d(TAG, "stop");
         if (mStarted) {
-            LocalBroadcastManager.getInstance(context).unregisterReceiver(mReceiver);
+            getLocalBroadcastManager().unregisterReceiver(mReceiver);
             mDelegate.stop(context);
             mStarted = false;
         }
@@ -189,7 +233,7 @@
         if (DEBUG) Log.d(TAG, "onComponentClosed");
 
         Intent intent = new Intent(ACTION_ACTIVITY_STOPPED, getInstanceUri(instanceId));
-        LocalBroadcastManager.getInstance(context).sendBroadcastSync(intent);
+        getLocalBroadcastManager().sendBroadcastSync(intent);
     }
 
     public static void onKeyDown(Context context, String instanceId, int keyCode) {
@@ -197,10 +241,10 @@
 
         Intent intent = new Intent(ACTION_KEY_EVENT, getInstanceUri(instanceId));
         intent.putExtra(ACTION_EXTRA_KEY_CODE, keyCode);
-        LocalBroadcastManager.getInstance(context).sendBroadcastSync(intent);
+        getLocalBroadcastManager().sendBroadcastSync(intent);
     }
 
-    private static Uri getInstanceUri(String instanceId) {
+    public static Uri getInstanceUri(String instanceId) {
         Uri instanceUri = new Uri.Builder()
                                   .scheme(ACTION_DATA_SCHEME)
                                   .authority(ACTION_DATA_AUTHORITY)
@@ -208,4 +252,8 @@
                                   .build();
         return instanceUri;
     }
+
+    private static LocalBroadcastManager getLocalBroadcastManager() {
+        return LocalBroadcastManager.getInstance(ContextUtils.getApplicationContext());
+    }
 }
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsFragment.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsFragment.java
new file mode 100644
index 0000000..25420116
--- /dev/null
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsFragment.java
@@ -0,0 +1,125 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chromecast.shell;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.Toast;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.Log;
+import org.chromium.content_public.browser.WebContents;
+
+/**
+ * Fragment for displaying a WebContents in CastShell.
+ * <p>
+ * Typically, this class is controlled by CastContentWindowAndroid through
+ * CastWebContentsSurfaceHelper. If the CastContentWindowAndroid is destroyed,
+ * CastWebContentsFragment should be removed from the activity holding it.
+ * Similarily, if the fragment is removed from a activity or the activity holding
+ * it is destroyed, CastContentWindowAndroid should be notified by intent.
+ */
+public class CastWebContentsFragment extends Fragment {
+    private static final String TAG = "cr_CastWebContentFrg";
+
+    private Context mPackageContext;
+
+    private CastWebContentsSurfaceHelper mSurfaceHelper;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        Log.d(TAG, "onCreate");
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public View onCreateView(
+            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        Log.d(TAG, "onCreateView");
+        super.onCreateView(inflater, container, savedInstanceState);
+
+        if (!CastBrowserHelper.initializeBrowser(getContext())) {
+            Toast.makeText(getContext(), R.string.browser_process_initialization_failed,
+                         Toast.LENGTH_SHORT)
+                    .show();
+            return null;
+        }
+
+        return inflater.cloneInContext(getContext())
+                .inflate(R.layout.cast_web_contents_activity, null);
+    }
+
+    @Override
+    public Context getContext() {
+        if (mPackageContext == null) {
+            mPackageContext = ContextUtils.getApplicationContext();
+        }
+        return mPackageContext;
+    }
+
+    @Override
+    public void onStart() {
+        Log.d(TAG, "onStart");
+        super.onStart();
+        if (mSurfaceHelper == null) {
+            mSurfaceHelper = new CastWebContentsSurfaceHelper(getActivity(), /* hostActivity */
+                    (FrameLayout) getView().findViewById(R.id.web_contents_container),
+                    true /* showInFragment */);
+        }
+        Bundle bundle = getArguments();
+        bundle.setClassLoader(WebContents.class.getClassLoader());
+        String uriString = bundle.getString(CastWebContentsComponent.INTENT_EXTRA_URI);
+        if (uriString == null) {
+            return;
+        }
+        Uri uri = Uri.parse(uriString);
+        WebContents webContents = (WebContents) bundle.getParcelable(
+                CastWebContentsComponent.ACTION_EXTRA_WEB_CONTENTS);
+
+        boolean touchInputEnabled =
+                bundle.getBoolean(CastWebContentsComponent.ACTION_EXTRA_TOUCH_INPUT_ENABLED, false);
+        mSurfaceHelper.onNewWebContents(uri, webContents, touchInputEnabled);
+    }
+
+    @Override
+    public void onPause() {
+        Log.d(TAG, "onPause");
+        super.onPause();
+
+        if (mSurfaceHelper != null) {
+            mSurfaceHelper.onPause();
+        }
+    }
+
+    @Override
+    public void onResume() {
+        Log.d(TAG, "onResume");
+        super.onResume();
+        if (mSurfaceHelper != null) {
+            mSurfaceHelper.onResume();
+        }
+    }
+
+    @Override
+    public void onStop() {
+        Log.d(TAG, "onStop");
+        super.onStop();
+    }
+
+    @Override
+    public void onDestroy() {
+        Log.d(TAG, "onDestroy");
+        if (mSurfaceHelper != null) {
+            mSurfaceHelper.onDestroy();
+        }
+        super.onDestroy();
+    }
+}
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsSurfaceHelper.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsSurfaceHelper.java
new file mode 100644
index 0000000..e23d6f10
--- /dev/null
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsSurfaceHelper.java
@@ -0,0 +1,310 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chromecast.shell;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Color;
+import android.media.AudioManager;
+import android.net.Uri;
+import android.os.Handler;
+import android.support.v4.content.LocalBroadcastManager;
+import android.widget.FrameLayout;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.Log;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.content.browser.ActivityContentVideoViewEmbedder;
+import org.chromium.content.browser.ContentVideoViewEmbedder;
+import org.chromium.content.browser.ContentView;
+import org.chromium.content.browser.ContentViewCore;
+import org.chromium.content.browser.ContentViewRenderView;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.ui.base.ViewAndroidDelegate;
+import org.chromium.ui.base.WindowAndroid;
+
+/**
+ * A util class for CastWebContentsActivity and CastWebContentsFragment to show
+ * WebContent on its views.
+ * <p>
+ * This class is to help the activity or fragment class to work with CastContentWindowAndroid,
+ * which will start a new instance of activity or fragment. If the CastContentWindowAndroid is
+ * destroyed, CastWebContentsActivity or CastWebContentsFragment should be stopped.
+ * Similarily,  CastWebContentsActivity or CastWebContentsFragment is stopped, eg.
+ * CastWebContentsFragment is removed from a activity or the activity holding it
+ * is destroyed, or CastWebContentsActivity is closed, CastContentWindowAndroid should be
+ * notified by intent.
+ */
+@JNINamespace("chromecast::shell")
+class CastWebContentsSurfaceHelper {
+    private static final String TAG = "cr_CastWebContents";
+
+    private static final int TEARDOWN_GRACE_PERIOD_TIMEOUT_MILLIS = 300;
+
+    private final Activity mHostActivity;
+    private final boolean mShowInFragment;
+    private final Handler mHandler;
+    private final FrameLayout mCastWebContentsLayout;
+    private final CastAudioManager mAudioManager;
+
+    private Uri mUri;
+    private String mInstanceId;
+    private BroadcastReceiver mWindowDestroyedBroadcastReceiver;
+    private BroadcastReceiver mScreenOffBroadcastReceiver;
+    private BroadcastReceiver mInternalStopReceiver;
+    private ContentViewRenderView mContentViewRenderView;
+    private WindowAndroid mWindow;
+    private ContentViewCore mContentViewCore;
+    private ContentView mContentView;
+
+    // TODO(vincentli) interrupt touch event from Fragment's root view when it's false.
+    private boolean mTouchInputEnabled = false;
+
+    /**
+     * @param hostActivity Activity hosts the view showing WebContents
+     * @param castWebContentsLayout view group to add ContentViewRenderView and ContentView
+     * @param showInFragment true if the cast web view is hosted by a CastWebContentsFragment
+     */
+    CastWebContentsSurfaceHelper(
+            Activity hostActivity, FrameLayout castWebContentsLayout, boolean showInFragment) {
+        mHostActivity = hostActivity;
+        mShowInFragment = showInFragment;
+        mCastWebContentsLayout = castWebContentsLayout;
+        mHandler = new Handler();
+        mAudioManager = CastAudioManager.getAudioManager(getActivity());
+    }
+
+    void onNewWebContents(
+            final Uri uri, final WebContents webContents, final boolean touchInputEnabled) {
+        if (webContents == null) {
+            Log.e(TAG, "Received null WebContents in bundle.");
+            maybeFinishLater();
+            return;
+        }
+
+        mTouchInputEnabled = touchInputEnabled;
+
+        Log.d(TAG, "content_uri=" + uri);
+        mUri = uri;
+        mInstanceId = uri.getPath();
+
+        // Whenever our app is visible, volume controls should modify the music stream.
+        // For more information read:
+        // http://developer.android.com/training/managing-audio/volume-playback.html
+        mHostActivity.setVolumeControlStream(AudioManager.STREAM_MUSIC);
+
+        if (mWindowDestroyedBroadcastReceiver != null) {
+            getLocalBroadcastManager().unregisterReceiver(mWindowDestroyedBroadcastReceiver);
+        }
+
+        if (mScreenOffBroadcastReceiver != null) {
+            getLocalBroadcastManager().unregisterReceiver(mScreenOffBroadcastReceiver);
+        }
+
+        mScreenOffBroadcastReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                detachWebContentsIfAny();
+                maybeFinishLater();
+            }
+        };
+
+        IntentFilter screenOffIntentFilter = new IntentFilter();
+        screenOffIntentFilter.addAction(CastIntents.ACTION_SCREEN_OFF);
+        getLocalBroadcastManager().registerReceiver(
+                mScreenOffBroadcastReceiver, screenOffIntentFilter);
+
+        if (mInternalStopReceiver != null) {
+            getLocalBroadcastManager().unregisterReceiver(mWindowDestroyedBroadcastReceiver);
+        }
+        mInternalStopReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                Log.d(TAG, "Intent action=" + intent.getAction());
+                if (mUri == null
+                        || !mUri.toString().equals(intent.getStringExtra(
+                                   CastWebContentsComponent.INTENT_EXTRA_URI))) {
+                    Log.d(TAG,
+                            "Current URI=" + mUri + "; intent URI="
+                                    + intent.getStringExtra(
+                                              CastWebContentsComponent.INTENT_EXTRA_URI));
+                    return;
+                }
+                detachWebContentsIfAny();
+                maybeFinishLater();
+            }
+        };
+        IntentFilter internalStopReceiverFilter = new IntentFilter();
+        internalStopReceiverFilter.addAction(CastIntents.ACTION_STOP_WEB_CONTENT);
+        getLocalBroadcastManager().registerReceiver(
+                mInternalStopReceiver, internalStopReceiverFilter);
+
+        showWebContents(webContents);
+    }
+
+    // Closes this activity if a new WebContents is not being displayed.
+    private void maybeFinishLater() {
+        Log.d(TAG, "maybeFinishLater");
+        final String currentInstanceId = mInstanceId;
+        mHandler.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                if (currentInstanceId.equals(mInstanceId)) {
+                    Log.d(TAG, "Finishing.");
+                    if (mShowInFragment) {
+                        Intent in = new Intent();
+                        in.setAction(CastIntents.ACTION_ON_WEB_CONTENT_STOPPED);
+                        in.putExtra(CastWebContentsComponent.INTENT_EXTRA_URI, mUri.toString());
+                        getLocalBroadcastManager().sendBroadcastSync(in);
+                    } else {
+                        mHostActivity.finish();
+                    }
+                }
+            }
+        }, TEARDOWN_GRACE_PERIOD_TIMEOUT_MILLIS);
+    }
+
+    private Activity getActivity() {
+        return mHostActivity;
+    }
+
+    // Sets webContents to be the currently displayed webContents.
+    private void showWebContents(WebContents webContents) {
+        Log.d(TAG, "showWebContents");
+
+        detachWebContentsIfAny();
+
+        // Set ContentVideoViewEmbedder to allow video playback.
+        nativeSetContentVideoViewEmbedder(
+                webContents, new ActivityContentVideoViewEmbedder(getActivity()));
+
+        mWindow = new WindowAndroid(getActivity());
+        mContentViewRenderView = new ContentViewRenderView(getActivity()) {
+            @Override
+            protected void onReadyToRender() {
+                setOverlayVideoMode(true);
+            }
+        };
+        mContentViewRenderView.onNativeLibraryLoaded(mWindow);
+        // Setting the background color to black avoids rendering a white splash screen
+        // before the players are loaded. See https://crbug/307113 for details.
+        mContentViewRenderView.setSurfaceViewBackgroundColor(Color.BLACK);
+
+        mCastWebContentsLayout.addView(mContentViewRenderView,
+                new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
+                        FrameLayout.LayoutParams.MATCH_PARENT));
+
+        // TODO(derekjchow): productVersion
+        mContentViewCore = ContentViewCore.create(getActivity().getApplicationContext(), "");
+        mContentView = ContentView.createContentView(
+                getActivity().getApplicationContext(), mContentViewCore);
+        mContentViewCore.initialize(ViewAndroidDelegate.createBasicDelegate(mContentView),
+                mContentView, webContents, mWindow);
+        // Enable display of current webContents.
+        mContentViewCore.onShow();
+        mCastWebContentsLayout.addView(mContentView,
+                new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
+                        FrameLayout.LayoutParams.MATCH_PARENT));
+        mContentView.setFocusable(true);
+        mContentView.requestFocus();
+        mContentViewRenderView.setCurrentContentViewCore(mContentViewCore);
+    }
+
+    // Remove the currently displayed webContents. no-op if nothing is being displayed.
+    void detachWebContentsIfAny() {
+        Log.d(TAG, "Detach web contents if any.");
+        if (mContentView != null) {
+            mCastWebContentsLayout.removeView(mContentView);
+            mCastWebContentsLayout.removeView(mContentViewRenderView);
+            mContentViewCore.destroy();
+            mContentViewRenderView.destroy();
+            mWindow.destroy();
+            mContentView = null;
+            mContentViewCore = null;
+            mContentViewRenderView = null;
+            mWindow = null;
+            CastWebContentsComponent.onComponentClosed(getActivity(), mInstanceId);
+            Log.d(TAG, "Detach web contents done.");
+        }
+    }
+
+    void onPause() {
+        // Release the audio focus. Note that releasing audio focus does not stop audio playback,
+        // it just notifies the framework that this activity has stopped playing audio.
+        if (mAudioManager.abandonAudioFocus(null) != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
+            Log.e(TAG, "Failed to abandon audio focus");
+        }
+
+        if (mContentViewCore != null) {
+            mContentViewCore.onPause();
+        }
+
+        releaseStreamMuteIfNecessary();
+    }
+
+    @SuppressWarnings("deprecation")
+    private void releaseStreamMuteIfNecessary() {
+        AudioManager audioManager = mAudioManager.getInternal();
+        boolean isMuted = false;
+        try {
+            isMuted = (Boolean) audioManager.getClass()
+                              .getMethod("isStreamMute", int.class)
+                              .invoke(audioManager, AudioManager.STREAM_MUSIC);
+        } catch (Exception e) {
+            Log.e(TAG, "Cannot call AudioManager.isStreamMute().", e);
+        }
+
+        if (isMuted) {
+            // Note: this is a no-op on fixed-volume devices.
+            audioManager.setStreamMute(AudioManager.STREAM_MUSIC, false);
+        }
+    }
+
+    void onResume() {
+        if (mAudioManager.requestAudioFocus(
+                    null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN)
+                != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
+            Log.e(TAG, "Failed to obtain audio focus");
+        }
+        if (mContentViewCore != null) {
+            mContentViewCore.onResume();
+        }
+    }
+
+    // Destroys all resources. After calling this method, this object must be dropped.
+    void onDestroy() {
+        detachWebContentsIfAny();
+
+        if (mWindowDestroyedBroadcastReceiver != null) {
+            getLocalBroadcastManager().unregisterReceiver(mWindowDestroyedBroadcastReceiver);
+        }
+
+        if (mScreenOffBroadcastReceiver != null) {
+            getLocalBroadcastManager().unregisterReceiver(mScreenOffBroadcastReceiver);
+        }
+
+        if (mInternalStopReceiver != null) {
+            getLocalBroadcastManager().unregisterReceiver(mInternalStopReceiver);
+        }
+    }
+
+    String getInstanceId() {
+        return mInstanceId;
+    }
+
+    boolean isTouchInputEnabled() {
+        return mTouchInputEnabled;
+    }
+
+    private LocalBroadcastManager getLocalBroadcastManager() {
+        return LocalBroadcastManager.getInstance(ContextUtils.getApplicationContext());
+    }
+
+    private native void nativeSetContentVideoViewEmbedder(
+            WebContents webContents, ContentVideoViewEmbedder embedder);
+}
diff --git a/chromecast/browser/android/apk/templates/BuildConfig.template b/chromecast/browser/android/apk/templates/BuildConfig.template
index 91e5e89..1327205 100644
--- a/chromecast/browser/android/apk/templates/BuildConfig.template
+++ b/chromecast/browser/android/apk/templates/BuildConfig.template
@@ -11,6 +11,13 @@
     false;
 #endif
 
+  public static final boolean ENABLE_CAST_FRAGMENT =
+#if defined(_ENABLE_CAST_FRAGMENT)
+    true;
+#else
+    false;
+#endif
+
   // Set the number of lines for LogcatExtractor to send.
   public static final int LOGCAT_SIZE = _LOGCAT_EXTRACTOR_SIZE;
 }
diff --git a/chromecast/browser/android/cast_web_contents_activity.cc b/chromecast/browser/android/cast_web_contents_activity.cc
deleted file mode 100644
index f6593f4e..0000000
--- a/chromecast/browser/android/cast_web_contents_activity.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromecast/browser/android/cast_web_contents_activity.h"
-
-#include "base/memory/ptr_util.h"
-#include "content/public/browser/web_contents.h"
-#include "jni/CastWebContentsActivity_jni.h"
-
-using base::android::JavaParamRef;
-using base::android::ScopedJavaGlobalRef;
-using base::android::ScopedJavaLocalRef;
-
-namespace chromecast {
-namespace shell {
-
-namespace {
-const void* kCastWebContentsActivityData;
-const void* kCastWebContentsActivityKey =
-    static_cast<const void*>(&kCastWebContentsActivityData);
-}  // namespace
-
-// static
-void JNI_CastWebContentsActivity_SetContentVideoViewEmbedder(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& jcaller,
-    const JavaParamRef<jobject>& webContents,
-    const JavaParamRef<jobject>& embedder) {
-  content::WebContents* web_contents =
-      content::WebContents::FromJavaWebContents(webContents);
-  DCHECK(web_contents);
-  CastWebContentsActivity* activity =
-      CastWebContentsActivity::Get(web_contents);
-  activity->SetContentVideoViewEmbedder(embedder);
-}
-
-// static
-CastWebContentsActivity* CastWebContentsActivity::Get(
-    content::WebContents* web_contents) {
-  DCHECK(web_contents);
-  CastWebContentsActivity* instance = static_cast<CastWebContentsActivity*>(
-      web_contents->GetUserData(kCastWebContentsActivityKey));
-  if (!instance) {
-    instance = new CastWebContentsActivity(web_contents);
-    web_contents->SetUserData(kCastWebContentsActivityKey,
-                              base::WrapUnique(instance));
-  }
-  return instance;
-}
-
-CastWebContentsActivity::CastWebContentsActivity(
-    content::WebContents* web_contents)
-    : content_video_view_embedder_(ScopedJavaLocalRef<jobject>()) {}
-
-CastWebContentsActivity::~CastWebContentsActivity() {}
-
-ScopedJavaLocalRef<jobject>
-CastWebContentsActivity::GetContentVideoViewEmbedder() {
-  return ScopedJavaLocalRef<jobject>(content_video_view_embedder_);
-}
-
-void CastWebContentsActivity::SetContentVideoViewEmbedder(
-    const JavaParamRef<jobject>& content_video_view_embedder) {
-  content_video_view_embedder_ =
-      ScopedJavaGlobalRef<jobject>(content_video_view_embedder);
-}
-
-}  // namespace shell
-}  // namespace chromecast
diff --git a/chromecast/browser/android/cast_web_contents_activity.h b/chromecast/browser/android/cast_web_contents_activity.h
deleted file mode 100644
index 93270f3..0000000
--- a/chromecast/browser/android/cast_web_contents_activity.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMECAST_BROWSER_ANDROID_CAST_WEB_CONTENTS_ACTIVITY_H_
-#define CHROMECAST_BROWSER_ANDROID_CAST_WEB_CONTENTS_ACTIVITY_H_
-
-#include <jni.h>
-
-#include "base/android/scoped_java_ref.h"
-#include "base/macros.h"
-#include "base/supports_user_data.h"
-
-namespace content {
-class WebContents;
-}
-
-namespace chromecast {
-namespace shell {
-
-// Helper class to get members of the CastWebContentsActivity displaying a
-// given web_contents. This class is lazily created through the Get function and
-// will manage its own lifetime via SupportsUserData.
-class CastWebContentsActivity : public base::SupportsUserData::Data {
- public:
-  ~CastWebContentsActivity() override;
-
-  static CastWebContentsActivity* Get(content::WebContents* web_contents);
-
-  base::android::ScopedJavaLocalRef<jobject> GetContentVideoViewEmbedder();
-  void SetContentVideoViewEmbedder(
-      const base::android::JavaParamRef<jobject>& content_video_view_embedder);
-
- private:
-  explicit CastWebContentsActivity(content::WebContents* web_contents);
-
-  base::android::ScopedJavaGlobalRef<jobject> content_video_view_embedder_;
-
-  DISALLOW_COPY_AND_ASSIGN(CastWebContentsActivity);
-};
-
-}  // namespace shell
-}  // namespace chromecast
-
-#endif  // CHROMECAST_BROWSER_ANDROID_CAST_WEB_CONTENTS_ACTIVITY_H_
diff --git a/chromecast/browser/android/cast_web_contents_surface_helper.cc b/chromecast/browser/android/cast_web_contents_surface_helper.cc
new file mode 100644
index 0000000..ad9ef7a
--- /dev/null
+++ b/chromecast/browser/android/cast_web_contents_surface_helper.cc
@@ -0,0 +1,69 @@
+// Copyright 2018 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 "chromecast/browser/android/cast_web_contents_surface_helper.h"
+
+#include "base/memory/ptr_util.h"
+#include "content/public/browser/web_contents.h"
+#include "jni/CastWebContentsSurfaceHelper_jni.h"
+
+using base::android::JavaParamRef;
+using base::android::ScopedJavaGlobalRef;
+using base::android::ScopedJavaLocalRef;
+
+namespace chromecast {
+namespace shell {
+
+namespace {
+const void* kCastWebContentsSurfaceHelperData;
+const void* kCastWebContentsSurfaceHelperKey =
+    static_cast<const void*>(&kCastWebContentsSurfaceHelperData);
+}  // namespace
+
+// static
+void JNI_CastWebContentsSurfaceHelper_SetContentVideoViewEmbedder(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& j_caller,
+    const JavaParamRef<jobject>& j_web_contents,
+    const JavaParamRef<jobject>& j_embedder) {
+  content::WebContents* web_contents =
+      content::WebContents::FromJavaWebContents(j_web_contents);
+  DCHECK(web_contents);
+  CastWebContentsSurfaceHelper* fragment =
+      CastWebContentsSurfaceHelper::Get(web_contents);
+  fragment->SetContentVideoViewEmbedder(j_embedder);
+}
+
+// static
+CastWebContentsSurfaceHelper* CastWebContentsSurfaceHelper::Get(
+    content::WebContents* web_contents) {
+  DCHECK(web_contents);
+  CastWebContentsSurfaceHelper* instance =
+      static_cast<CastWebContentsSurfaceHelper*>(
+          web_contents->GetUserData(kCastWebContentsSurfaceHelperKey));
+  if (!instance) {
+    instance = new CastWebContentsSurfaceHelper();
+    web_contents->SetUserData(kCastWebContentsSurfaceHelperKey,
+                              base::WrapUnique(instance));
+  }
+  return instance;
+}
+
+CastWebContentsSurfaceHelper::CastWebContentsSurfaceHelper() {}
+
+CastWebContentsSurfaceHelper::~CastWebContentsSurfaceHelper() {}
+
+ScopedJavaLocalRef<jobject>
+CastWebContentsSurfaceHelper ::GetContentVideoViewEmbedder() {
+  return ScopedJavaLocalRef<jobject>(content_video_view_embedder_);
+}
+
+void CastWebContentsSurfaceHelper::SetContentVideoViewEmbedder(
+    const JavaParamRef<jobject>& content_video_view_embedder) {
+  content_video_view_embedder_ =
+      ScopedJavaGlobalRef<jobject>(content_video_view_embedder);
+}
+
+}  // namespace shell
+}  // namespace chromecast
diff --git a/chromecast/browser/android/cast_web_contents_surface_helper.h b/chromecast/browser/android/cast_web_contents_surface_helper.h
new file mode 100644
index 0000000..f4533552
--- /dev/null
+++ b/chromecast/browser/android/cast_web_contents_surface_helper.h
@@ -0,0 +1,46 @@
+// Copyright 2018 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 CHROMECAST_BROWSER_ANDROID_CAST_WEB_CONTENTS_SURFACE_HELPER_H_
+#define CHROMECAST_BROWSER_ANDROID_CAST_WEB_CONTENTS_SURFACE_HELPER_H_
+
+#include <jni.h>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/macros.h"
+#include "base/supports_user_data.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace chromecast {
+namespace shell {
+
+// Helper class to get android UI reference, CastWebContentsActivity or
+// CastWebContentsFragment, displaying a given web_contents.
+// This class is lazily created through the Get function and
+// will manage its own lifetime via SupportsUserData.
+class CastWebContentsSurfaceHelper : public base::SupportsUserData::Data {
+ public:
+  ~CastWebContentsSurfaceHelper() override;
+
+  static CastWebContentsSurfaceHelper* Get(content::WebContents* web_contents);
+
+  base::android::ScopedJavaLocalRef<jobject> GetContentVideoViewEmbedder();
+  void SetContentVideoViewEmbedder(
+      const base::android::JavaParamRef<jobject>& content_video_view_embedder);
+
+ private:
+  CastWebContentsSurfaceHelper();
+
+  base::android::ScopedJavaGlobalRef<jobject> content_video_view_embedder_;
+
+  DISALLOW_COPY_AND_ASSIGN(CastWebContentsSurfaceHelper);
+};
+
+}  // namespace shell
+}  // namespace chromecast
+
+#endif  // CHROMECAST_BROWSER_ANDROID_CAST_WEB_CONTENTS_SURFACE_HELPER_H_
diff --git a/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/CastWebContentsComponentTest.java b/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/CastWebContentsComponentTest.java
index 6007fd3..522980261 100644
--- a/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/CastWebContentsComponentTest.java
+++ b/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/CastWebContentsComponentTest.java
@@ -15,7 +15,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
-import android.os.PatternMatcher;
 import android.support.v4.content.LocalBroadcastManager;
 
 import org.junit.Assert;
@@ -75,10 +74,7 @@
         Assume.assumeFalse(BuildConfig.DISPLAY_WEB_CONTENTS_IN_SERVICE);
 
         BroadcastReceiver receiver = Mockito.mock(BroadcastReceiver.class);
-        IntentFilter intentFilter = new IntentFilter(CastIntents.ACTION_STOP_ACTIVITY);
-        intentFilter.addDataScheme(CastWebContentsComponent.ACTION_DATA_SCHEME);
-        intentFilter.addDataAuthority(CastWebContentsComponent.ACTION_DATA_AUTHORITY, null);
-        intentFilter.addDataPath("/" + INSTANCE_ID, PatternMatcher.PATTERN_LITERAL);
+        IntentFilter intentFilter = new IntentFilter(CastIntents.ACTION_ON_WEB_CONTENT_STOPPED);
         LocalBroadcastManager.getInstance(mActivity).registerReceiver(receiver, intentFilter);
 
         CastWebContentsComponent component =
diff --git a/chromecast/browser/cast_web_view.cc b/chromecast/browser/cast_web_view.cc
index 7bd97c2..98cf890 100644
--- a/chromecast/browser/cast_web_view.cc
+++ b/chromecast/browser/cast_web_view.cc
@@ -12,6 +12,7 @@
 #include "chromecast/base/cast_features.h"
 #include "chromecast/base/metrics/cast_metrics_helper.h"
 #include "chromecast/browser/cast_web_contents_manager.h"
+#include "chromecast/chromecast_features.h"
 #include "chromecast/public/cast_media_shlib.h"
 #include "content/public/browser/media_capture_devices.h"
 #include "content/public/browser/navigation_handle.h"
@@ -26,7 +27,7 @@
 #include "url/gurl.h"
 
 #if defined(OS_ANDROID)
-#include "chromecast/browser/android/cast_web_contents_activity.h"
+#include "chromecast/browser/android/cast_web_contents_surface_helper.h"
 #endif  // defined(OS_ANDROID)
 
 #if defined(USE_AURA)
@@ -222,8 +223,8 @@
 base::android::ScopedJavaLocalRef<jobject>
 CastWebView::GetContentVideoViewEmbedder() {
   DCHECK(web_contents_);
-  auto* activity = shell::CastWebContentsActivity::Get(web_contents_.get());
-  return activity->GetContentVideoViewEmbedder();
+  auto* helper = shell::CastWebContentsSurfaceHelper::Get(web_contents_.get());
+  return helper->GetContentVideoViewEmbedder();
 }
 #endif  // defined(OS_ANDROID)
 
diff --git a/chromecast/chromecast.gni b/chromecast/chromecast.gni
index 99759f9a..fe71006 100644
--- a/chromecast/chromecast.gni
+++ b/chromecast/chromecast.gni
@@ -56,6 +56,11 @@
   # background.
   enable_background_activities = false
 
+  # Set to true to use CastWebContentsFragment instead of CastWebContentsActivity
+  # to run cast receiver app.
+  # TODO(thoren) merge this flag with display_web_contents_in_service
+  enable_cast_fragment = false
+
   # Set the number of lines for LogcatExtractor to send.
   logcat_extractor_size = 512
 }
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index d03d64e..2a56784e 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -41,7 +41,6 @@
     "//components/signin/core/account_id",
     "//components/url_formatter",
     "//components/user_manager",
-    "//crypto",
     "//crypto:platform",
     "//google_apis",
     "//media/base:video_facing",
@@ -198,6 +197,8 @@
     "dbus/fake_permission_broker_client.h",
     "dbus/fake_power_manager_client.cc",
     "dbus/fake_power_manager_client.h",
+    "dbus/fake_session_manager_client.cc",
+    "dbus/fake_session_manager_client.h",
     "dbus/fake_shill_device_client.cc",
     "dbus/fake_shill_device_client.h",
     "dbus/fake_shill_ipconfig_client.cc",
@@ -612,6 +613,8 @@
   sources = [
     "dbus/fake_cros_disks_client.cc",
     "dbus/fake_cros_disks_client.h",
+
+    # TODO(crbug.com/799071) remove fake_session_manager_client and fix build rules.
     "dbus/fake_session_manager_client.cc",
     "dbus/fake_session_manager_client.h",
     "dbus/fake_shill_manager_client.cc",
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index eeb0dab9..80304c08 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -546,9 +546,6 @@
 // done by session manager.
 const char kSystemDevMode[] = "system-developer-mode";
 
-// Enables testing for auto update UI.
-const char kTestAutoUpdateUI[] = "test-auto-update-ui";
-
 // Enables testing for encryption migration UI.
 const char kTestEncryptionMigrationUI[] = "test-encryption-migration-ui";
 
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h
index ee7703bb5..2d62ba0 100644
--- a/chromeos/chromeos_switches.h
+++ b/chromeos/chromeos_switches.h
@@ -151,7 +151,6 @@
 CHROMEOS_EXPORT extern const char kSmsTestMessages[];
 CHROMEOS_EXPORT extern const char kStubCrosSettings[];
 CHROMEOS_EXPORT extern const char kSystemDevMode[];
-CHROMEOS_EXPORT extern const char kTestAutoUpdateUI[];
 CHROMEOS_EXPORT extern const char kTestEncryptionMigrationUI[];
 CHROMEOS_EXPORT extern const char kTetherStub[];
 CHROMEOS_EXPORT extern const char kVoiceInteractionLocales[];
diff --git a/chromeos/dbus/fake_session_manager_client.cc b/chromeos/dbus/fake_session_manager_client.cc
index c834741..f88416f0 100644
--- a/chromeos/dbus/fake_session_manager_client.cc
+++ b/chromeos/dbus/fake_session_manager_client.cc
@@ -15,11 +15,14 @@
 #include "base/numerics/safe_conversions.h"
 #include "base/path_service.h"
 #include "base/single_thread_task_runner.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/chromeos_paths.h"
 #include "chromeos/dbus/cryptohome_client.h"
 #include "components/policy/proto/device_management_backend.pb.h"
+#include "crypto/sha2.h"
 
 using RetrievePolicyResponseType =
     chromeos::FakeSessionManagerClient::RetrievePolicyResponseType;
@@ -29,6 +32,9 @@
 namespace {
 
 constexpr char kFakeContainerInstanceId[] = "0123456789ABCDEF";
+constexpr char kStubDevicePolicyFile[] = "stub_device_policy";
+constexpr char kStubPolicyFile[] = "stub_policy";
+constexpr char kStubStateKeysFile[] = "stub_state_keys";
 
 // Store the owner key in a file on the disk, so that it can be loaded by
 // DeviceSettingsService and used e.g. for validating policy signatures in the
@@ -53,22 +59,100 @@
   return true;
 }
 
+// Helper to asynchronously retrieve a file's content.
+std::string GetFileContent(const base::FilePath& path) {
+  std::string result;
+  if (!path.empty())
+    base::ReadFileToString(path, &result);
+  return result;
+}
+
+// Helper to notify the callback with SUCCESS, to be used by the stub.
+void NotifyOnRetrievePolicySuccess(
+    SessionManagerClient::RetrievePolicyCallback callback,
+    const std::string& protobuf) {
+  std::move(callback).Run(RetrievePolicyResponseType::SUCCESS, protobuf);
+}
+
+// Returns a location for |file| that is specific to the given |cryptohome_id|.
+// These paths will be relative to DIR_USER_POLICY_KEYS, and can be used only
+// to store stub files.
+base::FilePath GetUserFilePath(const cryptohome::Identification& cryptohome_id,
+                               const std::string& file) {
+  base::FilePath keys_path;
+  if (!PathService::Get(chromeos::DIR_USER_POLICY_KEYS, &keys_path))
+    return base::FilePath();
+  const std::string sanitized =
+      CryptohomeClient::GetStubSanitizedUsername(cryptohome_id);
+  return keys_path.AppendASCII(sanitized).AppendASCII(file);
+}
+
+// Helper to write a file in a background thread.
+void StoreFile(const base::FilePath& path, const std::string& data) {
+  if (path.empty() || !base::CreateDirectory(path.DirName())) {
+    LOG(WARNING) << "Failed to write to " << path.value();
+    return;
+  }
+  int result = base::WriteFile(path, data.data(), data.size());
+  if (result == -1 || static_cast<size_t>(result) != data.size())
+    LOG(WARNING) << "Failed to write to " << path.value();
+}
+
+// Helper to write policy owner key and policy blob in a background thread.
+void StorePolicyWithKey(
+    const enterprise_management::PolicyFetchResponse& policy,
+    const std::string& policy_blob,
+    const base::FilePath& owner_key_path,
+    const base::FilePath& policy_path) {
+  if (policy.has_new_public_key())
+    StoreFile(owner_key_path, policy.new_public_key());
+  StoreFile(policy_path, policy_blob);
+}
+
+// Helper to asynchronously read (or if missing create) state key stubs.
+std::vector<std::string> ReadCreateStateKeysStub(const base::FilePath& path) {
+  std::string contents;
+  if (base::PathExists(path)) {
+    contents = GetFileContent(path);
+  } else {
+    // Create stub state keys on the fly.
+    for (int i = 0; i < 5; ++i) {
+      contents += crypto::SHA256HashString(
+          base::IntToString(i) +
+          base::Int64ToString(base::Time::Now().ToJavaTime()));
+    }
+    StoreFile(path, contents);
+  }
+
+  std::vector<std::string> state_keys;
+  for (size_t i = 0; i < contents.size() / 32; ++i)
+    state_keys.push_back(contents.substr(i * 32, 32));
+  return state_keys;
+}
+
 }  // namespace
 
-FakeSessionManagerClient::FakeSessionManagerClient()
+FakeSessionManagerClient::FakeSessionManagerClient(uint32_t options)
     : start_device_wipe_call_count_(0),
       request_lock_screen_call_count_(0),
       notify_lock_screen_shown_call_count_(0),
       notify_lock_screen_dismissed_call_count_(0),
+      screen_is_locked_(false),
       arc_available_(false),
+      delegate_(nullptr),
+      options_(options),
       weak_ptr_factory_(this) {}
 
+FakeSessionManagerClient::FakeSessionManagerClient()
+    : FakeSessionManagerClient(NONE) {}
+
 FakeSessionManagerClient::~FakeSessionManagerClient() = default;
 
 void FakeSessionManagerClient::Init(dbus::Bus* bus) {
 }
 
 void FakeSessionManagerClient::SetStubDelegate(StubDelegate* delegate) {
+  delegate_ = delegate;
 }
 
 void FakeSessionManagerClient::AddObserver(Observer* observer) {
@@ -84,7 +168,7 @@
 }
 
 bool FakeSessionManagerClient::IsScreenLocked() const {
-  return false;
+  return screen_is_locked_;
 }
 
 void FakeSessionManagerClient::EmitLoginPromptVisible() {
@@ -124,14 +208,18 @@
 
 void FakeSessionManagerClient::RequestLockScreen() {
   request_lock_screen_call_count_++;
+  if (delegate_)
+    delegate_->LockScreenForStub();
 }
 
 void FakeSessionManagerClient::NotifyLockScreenShown() {
   notify_lock_screen_shown_call_count_++;
+  screen_is_locked_ = true;
 }
 
 void FakeSessionManagerClient::NotifyLockScreenDismissed() {
   notify_lock_screen_dismissed_call_count_++;
+  screen_is_locked_ = false;
 }
 
 void FakeSessionManagerClient::RetrieveActiveSessions(
@@ -142,63 +230,120 @@
 
 void FakeSessionManagerClient::RetrieveDevicePolicy(
     RetrievePolicyCallback callback) {
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::BindOnce(std::move(callback), RetrievePolicyResponseType::SUCCESS,
-                     device_policy_));
+  if (options_ & USE_HOST_POLICY) {
+    base::FilePath owner_key_path;
+    if (!PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path)) {
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE,
+          base::BindOnce(std::move(callback),
+                         RetrievePolicyResponseType::SUCCESS, std::string()));
+      return;
+    }
+    base::FilePath device_policy_path =
+        owner_key_path.DirName().AppendASCII(kStubDevicePolicyFile);
+    base::PostTaskWithTraitsAndReplyWithResult(
+        FROM_HERE,
+        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+        base::BindOnce(&GetFileContent, device_policy_path),
+        base::BindOnce(&NotifyOnRetrievePolicySuccess, std::move(callback)));
+  } else {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(std::move(callback), RetrievePolicyResponseType::SUCCESS,
+                       device_policy_));
+  }
 }
 
 RetrievePolicyResponseType
 FakeSessionManagerClient::BlockingRetrieveDevicePolicy(
     std::string* policy_out) {
-  *policy_out = device_policy_;
-  return RetrievePolicyResponseType::SUCCESS;
+  if (options_ & USE_HOST_POLICY) {
+    base::FilePath owner_key_path;
+    if (!PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path)) {
+      *policy_out = "";
+      return RetrievePolicyResponseType::SUCCESS;
+    }
+    base::FilePath device_policy_path =
+        owner_key_path.DirName().AppendASCII(kStubDevicePolicyFile);
+    *policy_out = GetFileContent(device_policy_path);
+    return RetrievePolicyResponseType::SUCCESS;
+  } else {
+    *policy_out = device_policy_;
+    return RetrievePolicyResponseType::SUCCESS;
+  }
 }
 
 void FakeSessionManagerClient::RetrievePolicyForUser(
     const cryptohome::Identification& cryptohome_id,
     RetrievePolicyCallback callback) {
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::BindOnce(std::move(callback), RetrievePolicyResponseType::SUCCESS,
-                     user_policies_[cryptohome_id]));
+  if (options_ & USE_HOST_POLICY) {
+    base::PostTaskWithTraitsAndReplyWithResult(
+        FROM_HERE,
+        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+        base::BindOnce(&GetFileContent,
+                       GetUserFilePath(cryptohome_id, kStubPolicyFile)),
+        base::BindOnce(&NotifyOnRetrievePolicySuccess, std::move(callback)));
+  } else {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(std::move(callback), RetrievePolicyResponseType::SUCCESS,
+                       user_policies_[cryptohome_id]));
+  }
 }
 
 RetrievePolicyResponseType
 FakeSessionManagerClient::BlockingRetrievePolicyForUser(
     const cryptohome::Identification& cryptohome_id,
     std::string* policy_out) {
-  *policy_out = user_policies_[cryptohome_id];
+  if (options_ & USE_HOST_POLICY) {
+    *policy_out =
+        GetFileContent(GetUserFilePath(cryptohome_id, kStubPolicyFile));
+  } else {
+    *policy_out = user_policies_[cryptohome_id];
+  }
   return RetrievePolicyResponseType::SUCCESS;
 }
 
 void FakeSessionManagerClient::RetrievePolicyForUserWithoutSession(
     const cryptohome::Identification& cryptohome_id,
     RetrievePolicyCallback callback) {
-  auto iter = user_policies_without_session_.find(cryptohome_id);
-  auto task =
-      iter == user_policies_.end()
-          ? base::BindOnce(std::move(callback),
-                           RetrievePolicyResponseType::OTHER_ERROR,
-                           std::string())
-          : base::BindOnce(std::move(callback),
-                           RetrievePolicyResponseType::SUCCESS, iter->second);
-  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(task));
+  if (options_ & USE_HOST_POLICY) {
+    RetrievePolicyForUser(cryptohome_id, std::move(callback));
+  } else {
+    auto iter = user_policies_without_session_.find(cryptohome_id);
+    auto task =
+        iter == user_policies_.end()
+            ? base::BindOnce(std::move(callback),
+                             RetrievePolicyResponseType::OTHER_ERROR,
+                             std::string())
+            : base::BindOnce(std::move(callback),
+                             RetrievePolicyResponseType::SUCCESS, iter->second);
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(task));
+  }
 }
 
 void FakeSessionManagerClient::RetrieveDeviceLocalAccountPolicy(
     const std::string& account_id,
     RetrievePolicyCallback callback) {
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::BindOnce(std::move(callback), RetrievePolicyResponseType::SUCCESS,
-                     device_local_account_policy_[account_id]));
+  if (options_ & USE_HOST_POLICY) {
+    RetrievePolicyForUser(cryptohome::Identification::FromString(account_id),
+                          std::move(callback));
+  } else {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(std::move(callback), RetrievePolicyResponseType::SUCCESS,
+                       device_local_account_policy_[account_id]));
+  }
 }
 
 RetrievePolicyResponseType
 FakeSessionManagerClient::BlockingRetrieveDeviceLocalAccountPolicy(
     const std::string& account_id,
     std::string* policy_out) {
+  if (options_ & USE_HOST_POLICY) {
+    return BlockingRetrievePolicyForUser(
+        cryptohome::Identification::FromString(account_id), policy_out);
+  }
   *policy_out = device_local_account_policy_[account_id];
   return RetrievePolicyResponseType::SUCCESS;
 }
@@ -207,54 +352,108 @@
     const std::string& policy_blob,
     VoidDBusMethodCallback callback) {
   enterprise_management::PolicyFetchResponse policy;
-  if (!policy.ParseFromString(policy_blob)) {
-    LOG(ERROR) << "Unable to parse policy protobuf";
+
+  if (options_ & USE_HOST_POLICY) {
+    base::FilePath owner_key_path;
+    if (!policy.ParseFromString(policy_blob) ||
+        !PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path)) {
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, base::BindOnce(std::move(callback), false /* success */));
+      return;
+    }
+
+    // Chrome will attempt to retrieve the device policy right after storing
+    // during enrollment, so make sure it's written before signaling
+    // completion.
+    // Note also that the owner key will be written before the device policy,
+    // if it was present in the blob.
+    base::FilePath device_policy_path =
+        owner_key_path.DirName().AppendASCII(kStubDevicePolicyFile);
+    base::PostTaskWithTraitsAndReply(
+        FROM_HERE,
+        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+        base::BindOnce(&StorePolicyWithKey, policy, policy_blob, owner_key_path,
+                       device_policy_path),
+        base::BindOnce(std::move(callback), true));
+  } else {
+    if (!policy.ParseFromString(policy_blob)) {
+      LOG(ERROR) << "Unable to parse policy protobuf";
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, base::BindOnce(std::move(callback), false /* success */));
+      return;
+    }
+
+    if (!store_device_policy_success_) {
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, base::BindOnce(std::move(callback), false /* success */));
+      return;
+    }
+
+    bool owner_key_store_success = false;
+    if (policy.has_new_public_key())
+      owner_key_store_success = StoreOwnerKey(policy.new_public_key());
+    device_policy_ = policy_blob;
+
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(std::move(callback), false /* success */));
-    return;
-  }
-
-  if (!store_device_policy_success_) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(std::move(callback), false /* success */));
-    return;
-  }
-
-  bool owner_key_store_success = false;
-  if (policy.has_new_public_key())
-    owner_key_store_success = StoreOwnerKey(policy.new_public_key());
-  device_policy_ = policy_blob;
-
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback), true /* success */));
-  if (policy.has_new_public_key()) {
+        FROM_HERE, base::BindOnce(std::move(callback), true /* success */));
+    if (policy.has_new_public_key()) {
+      for (auto& observer : observers_)
+        observer.OwnerKeySet(owner_key_store_success);
+    }
     for (auto& observer : observers_)
-      observer.OwnerKeySet(owner_key_store_success);
+      observer.PropertyChangeComplete(true /* success */);
   }
-  for (auto& observer : observers_)
-    observer.PropertyChangeComplete(true /* success */);
 }
 
 void FakeSessionManagerClient::StorePolicyForUser(
     const cryptohome::Identification& cryptohome_id,
     const std::string& policy_blob,
     VoidDBusMethodCallback callback) {
-  bool result = false;
-  if (store_user_policy_success_) {
-    user_policies_[cryptohome_id] = policy_blob;
-    result = true;
+  if (options_ & USE_HOST_POLICY) {
+    // The session manager writes the user policy key to a well-known
+    // location. Do the same with the stub impl, so that user policy works and
+    // can be tested on desktop builds.
+    enterprise_management::PolicyFetchResponse response;
+    if (!response.ParseFromString(policy_blob)) {
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, base::BindOnce(std::move(callback), false /* success */));
+      return;
+    }
+
+    // This file isn't read directly by Chrome, but is used by this class to
+    // reload the user policy across restarts.
+    base::FilePath stub_policy_path =
+        GetUserFilePath(cryptohome_id, kStubPolicyFile);
+    base::FilePath key_path = GetUserFilePath(cryptohome_id, "policy.pub");
+    base::PostTaskWithTraitsAndReply(
+        FROM_HERE,
+        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+        base::BindOnce(&StorePolicyWithKey, response, policy_blob, key_path,
+                       stub_policy_path),
+        base::BindOnce(std::move(callback), true));
+  } else {
+    bool result = false;
+    if (store_user_policy_success_) {
+      user_policies_[cryptohome_id] = policy_blob;
+      result = true;
+    }
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), result));
   }
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback), result));
 }
 
 void FakeSessionManagerClient::StoreDeviceLocalAccountPolicy(
     const std::string& account_id,
     const std::string& policy_blob,
     VoidDBusMethodCallback callback) {
-  device_local_account_policy_[account_id] = policy_blob;
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback), true));
+  if (options_ & USE_HOST_POLICY) {
+    StorePolicyForUser(cryptohome::Identification::FromString(account_id),
+                       policy_blob, std::move(callback));
+  } else {
+    device_local_account_policy_[account_id] = policy_blob;
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), true));
+  }
 }
 
 bool FakeSessionManagerClient::SupportsRestartToApplyUserFlags() const {
@@ -267,9 +466,21 @@
 
 void FakeSessionManagerClient::GetServerBackedStateKeys(
     StateKeysCallback callback) {
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::BindOnce(std::move(callback), server_backed_state_keys_));
+  if (options_ & USE_HOST_POLICY) {
+    base::FilePath owner_key_path;
+    CHECK(PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path));
+    const base::FilePath state_keys_path =
+        owner_key_path.DirName().AppendASCII(kStubStateKeysFile);
+    base::PostTaskWithTraitsAndReplyWithResult(
+        FROM_HERE,
+        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+        base::BindOnce(&ReadCreateStateKeysStub, state_keys_path),
+        std::move(callback));
+  } else {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(std::move(callback), server_backed_state_keys_));
+  }
 }
 
 void FakeSessionManagerClient::StartArcInstance(
diff --git a/chromeos/dbus/fake_session_manager_client.h b/chromeos/dbus/fake_session_manager_client.h
index 406ee96..f5ad5a6 100644
--- a/chromeos/dbus/fake_session_manager_client.h
+++ b/chromeos/dbus/fake_session_manager_client.h
@@ -23,7 +23,14 @@
 // returns them unmodified.
 class FakeSessionManagerClient : public SessionManagerClient {
  public:
+  enum FakeSessionManagerOptions : uint32_t {
+    NONE = 0,
+    USE_HOST_POLICY = 1 << 0,
+  };
+
   FakeSessionManagerClient();
+  explicit FakeSessionManagerClient(
+      uint32_t options /* bitwise or of multiple FakeSessionManagerOptions */);
   ~FakeSessionManagerClient() override;
 
   // SessionManagerClient overrides
@@ -178,6 +185,7 @@
   int request_lock_screen_call_count_;
   int notify_lock_screen_shown_call_count_;
   int notify_lock_screen_dismissed_call_count_;
+  bool screen_is_locked_;
 
   bool arc_available_;
   base::TimeTicks arc_start_time_;
@@ -189,6 +197,12 @@
   // Contains last requst passed to StartArcInstance
   login_manager::StartArcInstanceRequest last_start_arc_request_;
 
+  StubDelegate* delegate_;
+
+  // Options for FakeSessionManagerClient with value of bitwise or of
+  // multiple FakeSessionManagerOptions.
+  uint32_t options_;
+
   base::WeakPtrFactory<FakeSessionManagerClient> weak_ptr_factory_;
   DISALLOW_COPY_AND_ASSIGN(FakeSessionManagerClient);
 };
diff --git a/chromeos/dbus/session_manager_client.cc b/chromeos/dbus/session_manager_client.cc
index ae2ce82..3ce03a5 100644
--- a/chromeos/dbus/session_manager_client.cc
+++ b/chromeos/dbus/session_manager_client.cc
@@ -19,18 +19,16 @@
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/path_service.h"
-#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/chromeos_paths.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/dbus/blocking_method_caller.h"
 #include "chromeos/dbus/cryptohome_client.h"
+#include "chromeos/dbus/fake_session_manager_client.h"
 #include "chromeos/dbus/login_manager/arc.pb.h"
 #include "chromeos/dbus/login_manager/policy_descriptor.pb.h"
 #include "components/policy/proto/device_management_backend.pb.h"
-#include "crypto/sha2.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
@@ -46,72 +44,8 @@
     SessionManagerClient::RetrievePolicyResponseType;
 using login_manager::PolicyDescriptor;
 
-constexpr char kStubPolicyFile[] = "stub_policy";
-constexpr char kStubDevicePolicyFile[] = "stub_device_policy";
-constexpr char kStubStateKeysFile[] = "stub_state_keys";
-
 constexpr char kEmptyAccountId[] = "";
 
-// Returns a location for |file| that is specific to the given |cryptohome_id|.
-// These paths will be relative to DIR_USER_POLICY_KEYS, and can be used only
-// to store stub files.
-base::FilePath GetUserFilePath(const cryptohome::Identification& cryptohome_id,
-                               const char* file) {
-  base::FilePath keys_path;
-  if (!PathService::Get(chromeos::DIR_USER_POLICY_KEYS, &keys_path))
-    return base::FilePath();
-  const std::string sanitized =
-      CryptohomeClient::GetStubSanitizedUsername(cryptohome_id);
-  return keys_path.AppendASCII(sanitized).AppendASCII(file);
-}
-
-// Helper to asynchronously retrieve a file's content.
-std::string GetFileContent(const base::FilePath& path) {
-  std::string result;
-  if (!path.empty())
-    base::ReadFileToString(path, &result);
-  return result;
-}
-
-// Helper to write a file in a background thread.
-void StoreFile(const base::FilePath& path, const std::string& data) {
-  const int size = static_cast<int>(data.size());
-  if (path.empty() ||
-      !base::CreateDirectory(path.DirName()) ||
-      base::WriteFile(path, data.data(), size) != size) {
-    LOG(WARNING) << "Failed to write to " << path.value();
-  }
-}
-
-// Helper to asynchronously read (or if missing create) state key stubs.
-std::vector<std::string> ReadCreateStateKeysStub(const base::FilePath& path) {
-  std::string contents;
-  if (base::PathExists(path)) {
-    contents = GetFileContent(path);
-  } else {
-    // Create stub state keys on the fly.
-    for (int i = 0; i < 5; ++i) {
-      contents += crypto::SHA256HashString(
-          base::IntToString(i) +
-          base::Int64ToString(base::Time::Now().ToJavaTime()));
-    }
-    StoreFile(path, contents);
-  }
-
-  std::vector<std::string> state_keys;
-  for (size_t i = 0; i < contents.size() / 32; ++i) {
-    state_keys.push_back(contents.substr(i * 32, 32));
-  }
-  return state_keys;
-}
-
-// Helper to notify the callback with SUCCESS, to be used by the stub.
-void NotifyOnRetrievePolicySuccess(
-    SessionManagerClient::RetrievePolicyCallback callback,
-    const std::string& protobuf) {
-  std::move(callback).Run(RetrievePolicyResponseType::SUCCESS, protobuf);
-}
-
 // Helper to get the enum type of RetrievePolicyResponseType based on error
 // name.
 RetrievePolicyResponseType GetPolicyResponseTypeByError(
@@ -864,233 +798,6 @@
   DISALLOW_COPY_AND_ASSIGN(SessionManagerClientImpl);
 };
 
-// The SessionManagerClient implementation used on Linux desktop,
-// which does nothing.
-class SessionManagerClientStubImpl : public SessionManagerClient {
- public:
-  SessionManagerClientStubImpl() = default;
-  ~SessionManagerClientStubImpl() override = default;
-
-  // SessionManagerClient overrides:
-  void Init(dbus::Bus* bus) override {}
-  void SetStubDelegate(StubDelegate* delegate) override {
-    delegate_ = delegate;
-  }
-  void AddObserver(Observer* observer) override {
-    observers_.AddObserver(observer);
-  }
-  void RemoveObserver(Observer* observer) override {
-    observers_.RemoveObserver(observer);
-  }
-  bool HasObserver(const Observer* observer) const override {
-    return observers_.HasObserver(observer);
-  }
-  bool IsScreenLocked() const override { return screen_is_locked_; }
-  void EmitLoginPromptVisible() override {}
-  void RestartJob(int socket_fd,
-                  const std::vector<std::string>& argv,
-                  VoidDBusMethodCallback callback) override {}
-  void SaveLoginPassword(const std::string& password) override {}
-  void StartSession(const cryptohome::Identification& cryptohome_id) override {}
-  void StopSession() override {}
-  void NotifySupervisedUserCreationStarted() override {}
-  void NotifySupervisedUserCreationFinished() override {}
-  void StartDeviceWipe() override {}
-  void StartTPMFirmwareUpdate(const std::string& update_mode) override {}
-  void RequestLockScreen() override {
-    if (delegate_)
-      delegate_->LockScreenForStub();
-  }
-  void NotifyLockScreenShown() override { screen_is_locked_ = true; }
-  void NotifyLockScreenDismissed() override { screen_is_locked_ = false; }
-  void RetrieveActiveSessions(ActiveSessionsCallback callback) override {}
-  void RetrieveDevicePolicy(RetrievePolicyCallback callback) override {
-    base::FilePath owner_key_path;
-    if (!PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path)) {
-      std::move(callback).Run(RetrievePolicyResponseType::SUCCESS,
-                              std::string());
-      return;
-    }
-    base::FilePath device_policy_path =
-        owner_key_path.DirName().AppendASCII(kStubDevicePolicyFile);
-    base::PostTaskWithTraitsAndReplyWithResult(
-        FROM_HERE,
-        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-        base::BindOnce(&GetFileContent, device_policy_path),
-        base::BindOnce(&NotifyOnRetrievePolicySuccess, std::move(callback)));
-  }
-  RetrievePolicyResponseType BlockingRetrieveDevicePolicy(
-      std::string* policy_out) override {
-    base::FilePath owner_key_path;
-    if (!PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path)) {
-      *policy_out = "";
-      return RetrievePolicyResponseType::SUCCESS;
-    }
-    base::FilePath device_policy_path =
-        owner_key_path.DirName().AppendASCII(kStubDevicePolicyFile);
-    *policy_out = GetFileContent(device_policy_path);
-    return RetrievePolicyResponseType::SUCCESS;
-  }
-  void RetrievePolicyForUser(const cryptohome::Identification& cryptohome_id,
-                             RetrievePolicyCallback callback) override {
-    base::PostTaskWithTraitsAndReplyWithResult(
-        FROM_HERE,
-        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-        base::BindOnce(&GetFileContent,
-                       GetUserFilePath(cryptohome_id, kStubPolicyFile)),
-        base::BindOnce(&NotifyOnRetrievePolicySuccess, std::move(callback)));
-  }
-  RetrievePolicyResponseType BlockingRetrievePolicyForUser(
-      const cryptohome::Identification& cryptohome_id,
-      std::string* policy_out) override {
-    *policy_out =
-        GetFileContent(GetUserFilePath(cryptohome_id, kStubPolicyFile));
-    return RetrievePolicyResponseType::SUCCESS;
-  }
-  void RetrievePolicyForUserWithoutSession(
-      const cryptohome::Identification& cryptohome_id,
-      RetrievePolicyCallback callback) override {
-    RetrievePolicyForUser(cryptohome_id, std::move(callback));
-  }
-  void RetrieveDeviceLocalAccountPolicy(
-      const std::string& account_id,
-      RetrievePolicyCallback callback) override {
-    RetrievePolicyForUser(cryptohome::Identification::FromString(account_id),
-                          std::move(callback));
-  }
-  RetrievePolicyResponseType BlockingRetrieveDeviceLocalAccountPolicy(
-      const std::string& account_id,
-      std::string* policy_out) override {
-    return BlockingRetrievePolicyForUser(
-        cryptohome::Identification::FromString(account_id), policy_out);
-  }
-  void StoreDevicePolicy(const std::string& policy_blob,
-                         VoidDBusMethodCallback callback) override {
-    enterprise_management::PolicyFetchResponse response;
-    base::FilePath owner_key_path;
-    if (!response.ParseFromString(policy_blob) ||
-        !PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path)) {
-      std::move(callback).Run(false);
-      return;
-    }
-
-    if (response.has_new_public_key()) {
-      base::PostTaskWithTraits(
-          FROM_HERE,
-          {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-          base::BindOnce(&StoreFile, owner_key_path,
-                         response.new_public_key()));
-    }
-
-    // Chrome will attempt to retrieve the device policy right after storing
-    // during enrollment, so make sure it's written before signaling
-    // completion.
-    // Note also that the owner key will be written before the device policy,
-    // if it was present in the blob.
-    base::FilePath device_policy_path =
-        owner_key_path.DirName().AppendASCII(kStubDevicePolicyFile);
-    base::PostTaskWithTraitsAndReply(
-        FROM_HERE,
-        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-        base::BindOnce(&StoreFile, device_policy_path, policy_blob),
-        base::BindOnce(std::move(callback), true));
-  }
-  void StorePolicyForUser(const cryptohome::Identification& cryptohome_id,
-                          const std::string& policy_blob,
-                          VoidDBusMethodCallback callback) override {
-    // The session manager writes the user policy key to a well-known
-    // location. Do the same with the stub impl, so that user policy works and
-    // can be tested on desktop builds.
-    enterprise_management::PolicyFetchResponse response;
-    if (!response.ParseFromString(policy_blob)) {
-      std::move(callback).Run(false);
-      return;
-    }
-
-    if (response.has_new_public_key()) {
-      base::FilePath key_path = GetUserFilePath(cryptohome_id, "policy.pub");
-      base::PostTaskWithTraits(
-          FROM_HERE,
-          {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-          base::BindOnce(&StoreFile, key_path, response.new_public_key()));
-    }
-
-    // This file isn't read directly by Chrome, but is used by this class to
-    // reload the user policy across restarts.
-    base::FilePath stub_policy_path =
-        GetUserFilePath(cryptohome_id, kStubPolicyFile);
-    base::PostTaskWithTraitsAndReply(
-        FROM_HERE,
-        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-        base::BindOnce(&StoreFile, stub_policy_path, policy_blob),
-        base::BindOnce(std::move(callback), true));
-  }
-  void StoreDeviceLocalAccountPolicy(const std::string& account_id,
-                                     const std::string& policy_blob,
-                                     VoidDBusMethodCallback callback) override {
-    StorePolicyForUser(cryptohome::Identification::FromString(account_id),
-                       policy_blob, std::move(callback));
-  }
-
-  bool SupportsRestartToApplyUserFlags() const override { return false; }
-
-  void SetFlagsForUser(const cryptohome::Identification& cryptohome_id,
-                       const std::vector<std::string>& flags) override {}
-
-  void GetServerBackedStateKeys(StateKeysCallback callback) override {
-    base::FilePath owner_key_path;
-    CHECK(PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path));
-    const base::FilePath state_keys_path =
-        owner_key_path.DirName().AppendASCII(kStubStateKeysFile);
-    base::PostTaskWithTraitsAndReplyWithResult(
-        FROM_HERE,
-        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-        base::BindOnce(&ReadCreateStateKeysStub, state_keys_path),
-        std::move(callback));
-  }
-
-  void StartArcInstance(const login_manager::StartArcInstanceRequest& request,
-                        StartArcInstanceCallback callback) override {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(std::move(callback),
-                                  StartArcInstanceResult::UNKNOWN_ERROR,
-                                  std::string(), base::ScopedFD()));
-  }
-
-  void SetArcCpuRestriction(
-      login_manager::ContainerCpuRestrictionState restriction_state,
-      VoidDBusMethodCallback callback) override {
-    std::move(callback).Run(false);
-  }
-
-  void EmitArcBooted(const cryptohome::Identification& cryptohome_id,
-                     VoidDBusMethodCallback callback) override {
-    std::move(callback).Run(false);
-  }
-
-  void StopArcInstance(VoidDBusMethodCallback callback) override {
-    std::move(callback).Run(false);
-  }
-
-  void GetArcStartTime(DBusMethodCallback<base::TimeTicks> callback) override {
-    std::move(callback).Run(base::nullopt);
-  }
-
-  void RemoveArcData(const cryptohome::Identification& cryptohome_id,
-                     VoidDBusMethodCallback callback) override {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(std::move(callback), false));
-  }
-
- private:
-  StubDelegate* delegate_ = nullptr;  // Weak pointer; may be nullptr.
-  base::ObserverList<Observer> observers_;
-  std::string device_policy_;
-  bool screen_is_locked_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(SessionManagerClientStubImpl);
-};
-
 SessionManagerClient::SessionManagerClient() = default;
 
 SessionManagerClient::~SessionManagerClient() = default;
@@ -1100,7 +807,8 @@
   if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
     return new SessionManagerClientImpl();
   DCHECK_EQ(FAKE_DBUS_CLIENT_IMPLEMENTATION, type);
-  return new SessionManagerClientStubImpl();
+  return new FakeSessionManagerClient(
+      FakeSessionManagerClient::USE_HOST_POLICY);
 }
 
 }  // namespace chromeos
diff --git a/chromeos/dbus/update_engine_client.cc b/chromeos/dbus/update_engine_client.cc
index 747dc8d..0c4b526 100644
--- a/chromeos/dbus/update_engine_client.cc
+++ b/chromeos/dbus/update_engine_client.cc
@@ -542,23 +542,51 @@
  public:
   UpdateEngineClientStubImpl()
       : current_channel_(kReleaseChannelBeta),
-        target_channel_(kReleaseChannelBeta) {}
+        target_channel_(kReleaseChannelBeta),
+        weak_factory_(this) {}
 
   // UpdateEngineClient implementation:
   void Init(dbus::Bus* bus) override {}
-  void AddObserver(Observer* observer) override {}
-  void RemoveObserver(Observer* observer) override {}
-  bool HasObserver(const Observer* observer) const override { return false; }
+
+  void AddObserver(Observer* observer) override {
+    observers_.AddObserver(observer);
+  }
+
+  void RemoveObserver(Observer* observer) override {
+    observers_.RemoveObserver(observer);
+  }
+
+  bool HasObserver(const Observer* observer) const override {
+    return observers_.HasObserver(observer);
+  }
 
   void RequestUpdateCheck(const UpdateCheckCallback& callback) override {
-    callback.Run(UPDATE_RESULT_NOTIMPLEMENTED);
+    if (last_status_.status != UPDATE_STATUS_IDLE) {
+      callback.Run(UPDATE_RESULT_FAILED);
+      return;
+    }
+    callback.Run(UPDATE_RESULT_SUCCESS);
+    last_status_.status = UPDATE_STATUS_CHECKING_FOR_UPDATE;
+    last_status_.download_progress = 0.0;
+    last_status_.last_checked_time = 0;
+    last_status_.new_size = 0;
+    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE,
+        base::BindOnce(&UpdateEngineClientStubImpl::StateTransition,
+                       weak_factory_.GetWeakPtr()),
+        base::TimeDelta::FromMilliseconds(kStateTransitionDefaultDelayMs));
   }
+
   void RebootAfterUpdate() override {}
+
   void Rollback() override {}
+
   void CanRollbackCheck(const RollbackCheckCallback& callback) override {
     callback.Run(true);
   }
-  Status GetLastStatus() override { return Status(); }
+
+  Status GetLastStatus() override { return last_status_; }
+
   void SetChannel(const std::string& target_channel,
                   bool is_powerwash_allowed) override {
     VLOG(1) << "Requesting to set channel: "
@@ -590,52 +618,6 @@
       int64_t update_size,
       const UpdateOverCellularOneTimePermissionCallback& callback) override {}
 
-  std::string current_channel_;
-  std::string target_channel_;
-};
-
-// The UpdateEngineClient implementation used on Linux desktop, which
-// tries to emulate real update engine client.
-class UpdateEngineClientFakeImpl : public UpdateEngineClientStubImpl {
- public:
-  UpdateEngineClientFakeImpl() : weak_factory_(this) {
-  }
-
-  ~UpdateEngineClientFakeImpl() override = default;
-
-  // UpdateEngineClient implementation:
-  void AddObserver(Observer* observer) override {
-    if (observer)
-      observers_.AddObserver(observer);
-  }
-
-  void RemoveObserver(Observer* observer) override {
-    if (observer)
-      observers_.RemoveObserver(observer);
-  }
-
-  bool HasObserver(const Observer* observer) const override {
-    return observers_.HasObserver(observer);
-  }
-
-  void RequestUpdateCheck(const UpdateCheckCallback& callback) override {
-    if (last_status_.status != UPDATE_STATUS_IDLE) {
-      callback.Run(UPDATE_RESULT_FAILED);
-      return;
-    }
-    callback.Run(UPDATE_RESULT_SUCCESS);
-    last_status_.status = UPDATE_STATUS_CHECKING_FOR_UPDATE;
-    last_status_.download_progress = 0.0;
-    last_status_.last_checked_time = 0;
-    last_status_.new_size = 0;
-    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE, base::Bind(&UpdateEngineClientFakeImpl::StateTransition,
-                              weak_factory_.GetWeakPtr()),
-        base::TimeDelta::FromMilliseconds(kStateTransitionDefaultDelayMs));
-  }
-
-  Status GetLastStatus() override { return last_status_; }
-
  private:
   void StateTransition() {
     UpdateStatusOperation next_status = UPDATE_STATUS_ERROR;
@@ -676,18 +658,23 @@
       observer.UpdateStatusChanged(last_status_);
     if (last_status_.status != UPDATE_STATUS_IDLE) {
       base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-          FROM_HERE, base::Bind(&UpdateEngineClientFakeImpl::StateTransition,
-                                weak_factory_.GetWeakPtr()),
+          FROM_HERE,
+          base::BindOnce(&UpdateEngineClientStubImpl::StateTransition,
+                         weak_factory_.GetWeakPtr()),
           base::TimeDelta::FromMilliseconds(delay_ms));
     }
   }
 
   base::ObserverList<Observer> observers_;
+
+  std::string current_channel_;
+  std::string target_channel_;
+
   Status last_status_;
 
-  base::WeakPtrFactory<UpdateEngineClientFakeImpl> weak_factory_;
+  base::WeakPtrFactory<UpdateEngineClientStubImpl> weak_factory_;
 
-  DISALLOW_COPY_AND_ASSIGN(UpdateEngineClientFakeImpl);
+  DISALLOW_COPY_AND_ASSIGN(UpdateEngineClientStubImpl);
 };
 
 UpdateEngineClient::UpdateEngineClient() = default;
@@ -706,11 +693,7 @@
   if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
     return new UpdateEngineClientImpl();
   DCHECK_EQ(FAKE_DBUS_CLIENT_IMPLEMENTATION, type);
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kTestAutoUpdateUI))
-    return new UpdateEngineClientFakeImpl();
-  else
-    return new UpdateEngineClientStubImpl();
+  return new UpdateEngineClientStubImpl();
 }
 
 // static
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 982c25b..a3c98da 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -455,7 +455,6 @@
       "//content/test:test_support",
       "//device/bluetooth",
       "//device/geolocation/public/cpp:test_support",
-      "//device/geolocation/public/interfaces",
       "//ipc:test_support",
       "//net:test_support",
       "//printing/features",
diff --git a/components/autofill/content/browser/BUILD.gn b/components/autofill/content/browser/BUILD.gn
index 94c98d47..655903d2 100644
--- a/components/autofill/content/browser/BUILD.gn
+++ b/components/autofill/content/browser/BUILD.gn
@@ -34,7 +34,6 @@
     "//content/public/browser",
     "//content/public/common",
     "//device/geolocation/public/cpp",
-    "//device/geolocation/public/interfaces",
     "//gpu/config",
     "//mojo/common:common_base",
     "//mojo/public/cpp/bindings",
diff --git a/components/autofill/content/browser/risk/fingerprint.cc b/components/autofill/content/browser/risk/fingerprint.cc
index b194e1c9..1549701 100644
--- a/components/autofill/content/browser/risk/fingerprint.cc
+++ b/components/autofill/content/browser/risk/fingerprint.cc
@@ -39,13 +39,13 @@
 #include "content/public/common/screen_info.h"
 #include "content/public/common/webplugininfo.h"
 #include "device/geolocation/public/cpp/geoposition.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "gpu/config/gpu_info.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "ppapi/features/features.h"
 #include "services/device/public/interfaces/constants.mojom.h"
+#include "services/device/public/interfaces/geolocation.mojom.h"
 #include "services/device/public/interfaces/geolocation_context.mojom.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "third_party/WebKit/public/platform/WebRect.h"
 #include "ui/display/display.h"
diff --git a/components/autofill/content/browser/risk/fingerprint_browsertest.cc b/components/autofill/content/browser/risk/fingerprint_browsertest.cc
index 12245ec0..bcc77da 100644
--- a/components/autofill/content/browser/risk/fingerprint_browsertest.cc
+++ b/components/autofill/content/browser/risk/fingerprint_browsertest.cc
@@ -19,7 +19,7 @@
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/test_utils.h"
 #include "device/geolocation/public/cpp/scoped_geolocation_overrider.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/autofill/content/renderer/form_classifier.h b/components/autofill/content/renderer/form_classifier.h
index 2ce96c3c..9193602 100644
--- a/components/autofill/content/renderer/form_classifier.h
+++ b/components/autofill/content/renderer/form_classifier.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_AUTOFILL_CONTENT_RENDERER_FORM_CLASSIFIER_H_
+#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_FORM_CLASSIFIER_H_
+
 #include "third_party/WebKit/public/web/WebFormElement.h"
 
 namespace autofill {
@@ -12,3 +15,5 @@
 bool ClassifyFormAndFindGenerationField(const blink::WebFormElement& form,
                                         base::string16* generation_field);
 }
+
+#endif  // COMPONENTS_AUTOFILL_CONTENT_RENDERER_FORM_CLASSIFIER_H_
diff --git a/components/autofill/content/renderer/html_based_username_detector.h b/components/autofill/content/renderer/html_based_username_detector.h
index 4f589ff..cb9e4cd 100644
--- a/components/autofill/content/renderer/html_based_username_detector.h
+++ b/components/autofill/content/renderer/html_based_username_detector.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_AUTOFILL_CONTENT_RENDERER_HTML_BASED_USERNAME_DETECTOR_H_
+#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_HTML_BASED_USERNAME_DETECTOR_H_
+
 #include <map>
 
 #include "components/autofill/core/common/password_form.h"
@@ -34,3 +37,5 @@
     UsernameDetectorCache* username_detector_cache);
 
 }  // namespace autofill
+
+#endif  // COMPONENTS_AUTOFILL_CONTENT_RENDERER_HTML_BASED_USERNAME_DETECTOR_H_
diff --git a/components/autofill/content/renderer/html_based_username_detector_vocabulary.h b/components/autofill/content/renderer/html_based_username_detector_vocabulary.h
index 8164fa2..6013e3f 100644
--- a/components/autofill/content/renderer/html_based_username_detector_vocabulary.h
+++ b/components/autofill/content/renderer/html_based_username_detector_vocabulary.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_AUTOFILL_CONTENT_RENDERER_HTML_BASED_USERNAME_DETECTOR_VOCABULARY_H_
+#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_HTML_BASED_USERNAME_DETECTOR_VOCABULARY_H_
+
 namespace autofill {
 
 // Words that certainly point to a non-username field.
@@ -37,3 +40,5 @@
 extern const int kWeakWordsSize;
 
 }  // namespace autofill
+
+#endif  // COMPONENTS_AUTOFILL_CONTENT_RENDERER_HTML_BASED_USERNAME_DETECTOR_VOCABULARY_H_
diff --git a/components/autofill/core/browser/DEPS b/components/autofill/core/browser/DEPS
index ebd3a7e..40eebce 100644
--- a/components/autofill/core/browser/DEPS
+++ b/components/autofill/core/browser/DEPS
@@ -21,7 +21,6 @@
   "+third_party/fips181",
   "+third_party/libaddressinput", # For address i18n.
   "+third_party/libphonenumber",  # For phone number i18n.
-  "+third_party/libxml",
   "+third_party/re2",
   "+ui/base",
   "+ui/gfx",
diff --git a/components/autofill/core/browser/state_names.h b/components/autofill/core/browser/state_names.h
index cd71539d..ebeab8e 100644
--- a/components/autofill/core/browser/state_names.h
+++ b/components/autofill/core/browser/state_names.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/strings/string16.h"
-
 #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_STATE_NAMES_H_
 #define COMPONENTS_AUTOFILL_CORE_BROWSER_STATE_NAMES_H_
 
+#include "base/strings/string16.h"
+
 namespace autofill {
 namespace state_names {
 
diff --git a/components/bookmarks/test/mock_bookmark_model_observer.h b/components/bookmarks/test/mock_bookmark_model_observer.h
index 25d323a2..c2a70a4 100644
--- a/components/bookmarks/test/mock_bookmark_model_observer.h
+++ b/components/bookmarks/test/mock_bookmark_model_observer.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_BOOKMARKS_TEST_MOCK_BOOKMARK_MODEL_OBSERVER_H_
+#define COMPONENTS_BOOKMARKS_TEST_MOCK_BOOKMARK_MODEL_OBSERVER_H_
+
 #include "components/bookmarks/browser/bookmark_model_observer.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "url/gurl.h"
@@ -44,3 +47,5 @@
 };
 
 }  // namespace bookmarks
+
+#endif  // COMPONENTS_BOOKMARKS_TEST_MOCK_BOOKMARK_MODEL_OBSERVER_H_
diff --git a/components/cbor/cbor_binary.h b/components/cbor/cbor_binary.h
index f179065..27f675b7 100644
--- a/components/cbor/cbor_binary.h
+++ b/components/cbor/cbor_binary.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <stdint.h>
-
 #ifndef COMPONENTS_CBOR_CBOR_BINARY_H_
 #define COMPONENTS_CBOR_CBOR_BINARY_H_
 
+#include <stdint.h>
+
 namespace cbor {
 namespace constants {
 
diff --git a/components/consent_auditor/pref_names.h b/components/consent_auditor/pref_names.h
index ef0049a..978e020 100644
--- a/components/consent_auditor/pref_names.h
+++ b/components/consent_auditor/pref_names.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_CONSENT_AUDITOR_PREF_NAMES_H_
+#define COMPONENTS_CONSENT_AUDITOR_PREF_NAMES_H_
+
 namespace consent_auditor {
 namespace prefs {
 
@@ -9,3 +12,5 @@
 
 }  // namespace prefs
 }  // namespace consent_auditor
+
+#endif  // COMPONENTS_CONSENT_AUDITOR_PREF_NAMES_H_
diff --git a/components/constrained_window/native_web_contents_modal_dialog_manager_views_mac.h b/components/constrained_window/native_web_contents_modal_dialog_manager_views_mac.h
index deb28bc..cc8a37d 100644
--- a/components/constrained_window/native_web_contents_modal_dialog_manager_views_mac.h
+++ b/components/constrained_window/native_web_contents_modal_dialog_manager_views_mac.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_CONSTRAINED_WINDOW_NATIVE_WEB_CONTENTS_MODAL_DIALOG_MANAGER_VIEWS_MAC_H_
+#define COMPONENTS_CONSTRAINED_WINDOW_NATIVE_WEB_CONTENTS_MODAL_DIALOG_MANAGER_VIEWS_MAC_H_
+
 #include "components/constrained_window/native_web_contents_modal_dialog_manager_views.h"
 
 namespace web_modal {
@@ -31,3 +34,5 @@
 };
 
 }  // namespace constrained_window
+
+#endif  // COMPONENTS_CONSTRAINED_WINDOW_NATIVE_WEB_CONTENTS_MODAL_DIALOG_MANAGER_VIEWS_MAC_H_
diff --git a/components/cronet/ios/test/cronet_quic_test.mm b/components/cronet/ios/test/cronet_quic_test.mm
index b5005dbd..a29a6385 100644
--- a/components/cronet/ios/test/cronet_quic_test.mm
+++ b/components/cronet/ios/test/cronet_quic_test.mm
@@ -4,20 +4,107 @@
 
 #import <Cronet/Cronet.h>
 
+#include "base/strings/stringprintf.h"
+#include "base/strings/sys_string_conversions.h"
+#include "components/cronet/ios/test/cronet_test_base.h"
+#include "components/grpc_support/test/quic_test_server.h"
+#include "net/base/mac/url_conversions.h"
+#include "net/cert/mock_cert_verifier.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+#include "url/gurl.h"
 
 namespace cronet {
 
-TEST(QuicTest, InvalidQuicHost) {
+class QuicTest : public CronetTestBase {
+ protected:
+  QuicTest() {}
+  ~QuicTest() override {}
+
+  void SetUp() override {
+    CronetTestBase::SetUp();
+
+    // Prepare Cronet
+    [Cronet setUserAgent:@"CronetTest/1.0.0.0" partial:NO];
+    [Cronet setHttp2Enabled:false];
+    [Cronet setQuicEnabled:true];
+    [Cronet setAcceptLanguages:@"en-US,en"];
+    [Cronet addQuicHint:@"test.example.com" port:443 altPort:443];
+    [Cronet enableTestCertVerifierForTesting];
+    [Cronet setHttpCacheType:CRNHttpCacheTypeDisabled];
+    [Cronet setMetricsEnabled:YES];
+    [Cronet setRequestFilterBlock:^(NSURLRequest* request) {
+      return YES;
+    }];
+
+    // QUIC Server simple URL.
+    simple_url_ = net::NSURLWithGURL(GURL(grpc_support::kTestServerSimpleUrl));
+  }
+
+  void TearDown() override {
+    [Cronet stopNetLog];
+    [Cronet shutdownForTesting];
+    CronetTestBase::TearDown();
+  }
+
+  void StartCronet() {
+    [Cronet start];
+
+    // Add URL mapping to test server.
+    NSString* rules = base::SysUTF8ToNSString(
+        base::StringPrintf("MAP test.example.com 127.0.0.1:%d,"
+                           "MAP notfound.example.com ~NOTFOUND",
+                           grpc_support::GetQuicTestServerPort()));
+    [Cronet setHostResolverRulesForTesting:rules];
+
+    // Prepare a session.
+    NSURLSessionConfiguration* config =
+        [NSURLSessionConfiguration ephemeralSessionConfiguration];
+    config.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
+    [Cronet installIntoSessionConfiguration:config];
+    session_ = [NSURLSession sessionWithConfiguration:config
+                                             delegate:delegate_
+                                        delegateQueue:nil];
+  }
+
+  NSURLSession* session_;
+  NSURL* simple_url_;
+};
+
+TEST_F(QuicTest, InvalidQuicHost) {
   BOOL success =
       [Cronet addQuicHint:@"https://test.example.com/" port:443 altPort:443];
 
   EXPECT_FALSE(success);
 }
 
-TEST(QuicTest, ValidQuicHost) {
+TEST_F(QuicTest, ValidQuicHost) {
   BOOL success = [Cronet addQuicHint:@"test.example.com" port:443 altPort:443];
 
   EXPECT_TRUE(success);
 }
+
+// Tests a request with enabled "enable_socket_recv_optimization" QUIC
+// experimental option.
+TEST_F(QuicTest, RequestWithSocketOptimizationEnabled) {
+  // Apply test specific Cronet configuration and start it.
+  [Cronet setExperimentalOptions:
+              @"{\"QUIC\" : {\"enable_socket_recv_optimization\" : true} }"];
+  StartCronet();
+
+  // Make request and wait for the response.
+  NSURLSessionDataTask* task = [session_ dataTaskWithURL:simple_url_];
+  StartDataTaskAndWaitForCompletion(task);
+
+  // Check that a successful response was received using QUIC.
+  EXPECT_EQ(nil, [delegate_ error]);
+  EXPECT_EQ(grpc_support::kSimpleBodyValue,
+            base::SysNSStringToUTF8(delegate_.responseBody));
+  if (@available(iOS 10, *)) {
+    NSURLSessionTaskTransactionMetrics* metrics =
+        delegate_.taskMetrics.transactionMetrics[0];
+    EXPECT_TRUE([metrics.networkProtocolName containsString:@"quic"])
+        << base::SysNSStringToUTF8(metrics.networkProtocolName);
+  }
+}
 }
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc
index 0a6ebfb..b811deb 100644
--- a/components/cronet/url_request_context_config.cc
+++ b/components/cronet/url_request_context_config.cc
@@ -68,6 +68,8 @@
     "quic_disable_bidirectional_streams";
 const char kQuicRaceCertVerification[] = "race_cert_verification";
 const char kQuicHostWhitelist[] = "host_whitelist";
+const char kQuicEnableSocketRecvOptimization[] =
+    "enable_socket_recv_optimization";
 
 // AsyncDNS experiment dictionary name.
 const char kAsyncDnsFieldTrialName[] = "AsyncDNS";
@@ -304,6 +306,13 @@
         session_params->quic_user_agent_id = quic_user_agent_id;
       }
 
+      bool quic_enable_socket_recv_optimization = false;
+      if (quic_args->GetBoolean(kQuicEnableSocketRecvOptimization,
+                                &quic_enable_socket_recv_optimization)) {
+        session_params->quic_enable_socket_recv_optimization =
+            quic_enable_socket_recv_optimization;
+      }
+
       bool quic_migrate_sessions_on_network_change_v2 = false;
       int quic_max_time_on_non_default_network_seconds = 0;
       int quic_max_migrations_to_non_default_network_on_path_degrading = 0;
diff --git a/components/dom_distiller/content/browser/android/java/src/org/chromium/components/dom_distiller/content/DistillablePageUtils.java b/components/dom_distiller/content/browser/android/java/src/org/chromium/components/dom_distiller/content/DistillablePageUtils.java
index 9b7e411..97b0ce64 100644
--- a/components/dom_distiller/content/browser/android/java/src/org/chromium/components/dom_distiller/content/DistillablePageUtils.java
+++ b/components/dom_distiller/content/browser/android/java/src/org/chromium/components/dom_distiller/content/DistillablePageUtils.java
@@ -14,27 +14,6 @@
 @JNINamespace("dom_distiller::android")
 public final class DistillablePageUtils {
     /**
-     * Callback for handling the result of isPageDistillable.
-     */
-    public static interface PageDistillableCallback {
-        public void onIsPageDistillableResult(boolean isDistillable);
-    }
-
-    public static void isPageDistillable(WebContents webContents, boolean isMobileOptimized,
-            PageDistillableCallback callback) {
-        nativeIsPageDistillable(webContents, isMobileOptimized, callback);
-    }
-
-    @CalledByNative
-    private static void callOnIsPageDistillableResult(
-            PageDistillableCallback callback, boolean isDistillable) {
-        callback.onIsPageDistillableResult(isDistillable);
-    }
-
-    private static native void nativeIsPageDistillable(
-            WebContents webContents, boolean isMobileOptimized, PageDistillableCallback callback);
-
-    /**
      * Delegate to receive distillability updates.
      */
     public interface PageDistillableDelegate {
diff --git a/components/dom_distiller/content/browser/distillable_page_utils.cc b/components/dom_distiller/content/browser/distillable_page_utils.cc
index 8ef96066..80c0351 100644
--- a/components/dom_distiller/content/browser/distillable_page_utils.cc
+++ b/components/dom_distiller/content/browser/distillable_page_utils.cc
@@ -21,15 +21,6 @@
 
 namespace dom_distiller {
 namespace {
-void OnOGArticleJsResult(base::Callback<void(bool)> callback,
-                         const base::Value* result) {
-  bool success = false;
-  if (result) {
-    result->GetAsBoolean(&success);
-  }
-  callback.Run(success);
-}
-
 void OnExtractFeaturesJsResult(const DistillablePageDetector* detector,
                                base::Callback<void(bool)> callback,
                                const base::Value* result) {
@@ -37,50 +28,6 @@
 }
 }  // namespace
 
-void IsOpenGraphArticle(content::WebContents* web_contents,
-                        base::Callback<void(bool)> callback) {
-  content::RenderFrameHost* main_frame = web_contents->GetMainFrame();
-  if (!main_frame) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                  base::Bind(callback, false));
-    return;
-  }
-  std::string og_article_js = ui::ResourceBundle::GetSharedInstance()
-                                  .GetRawDataResource(IDR_IS_DISTILLABLE_JS)
-                                  .as_string();
-  RunIsolatedJavaScript(main_frame, og_article_js,
-                        base::Bind(OnOGArticleJsResult, callback));
-}
-
-void IsDistillablePage(content::WebContents* web_contents,
-                       bool is_mobile_optimized,
-                       base::Callback<void(bool)> callback) {
-  switch (GetDistillerHeuristicsType()) {
-    case DistillerHeuristicsType::ALWAYS_TRUE:
-      base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                    base::Bind(callback, true));
-      return;
-    case DistillerHeuristicsType::OG_ARTICLE:
-      IsOpenGraphArticle(web_contents, callback);
-      return;
-    case DistillerHeuristicsType::ADABOOST_MODEL:
-      // The adaboost model is only applied to non-mobile pages.
-      if (is_mobile_optimized) {
-        base::ThreadTaskRunnerHandle::Get()->PostTask(
-            FROM_HERE, base::Bind(callback, false));
-        return;
-      }
-      IsDistillablePageForDetector(
-          web_contents, DistillablePageDetector::GetDefault(), callback);
-      return;
-    case DistillerHeuristicsType::NONE:
-    default:
-      base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE, base::Bind(callback, false));
-      return;
-  }
-}
-
 void IsDistillablePageForDetector(content::WebContents* web_contents,
                                   const DistillablePageDetector* detector,
                                   base::Callback<void(bool)> callback) {
diff --git a/components/dom_distiller/content/browser/distillable_page_utils.h b/components/dom_distiller/content/browser/distillable_page_utils.h
index d2805d6..e6f31c5 100644
--- a/components/dom_distiller/content/browser/distillable_page_utils.h
+++ b/components/dom_distiller/content/browser/distillable_page_utils.h
@@ -12,16 +12,6 @@
 
 class DistillablePageDetector;
 
-// Checks if the page appears to be distillable based on whichever heuristics
-// are configured to be used (see dom_distiller::GetDistillerHeuristicsType).
-void IsDistillablePage(content::WebContents* web_contents,
-                       bool is_mobile_optimized,
-                       base::Callback<void(bool)> callback);
-
-// Checks if the web_contents is has opengraph type=article markup.
-void IsOpenGraphArticle(content::WebContents* web_contents,
-                        base::Callback<void(bool)> callback);
-
 // Uses the provided DistillablePageDetector to detect if the page is
 // distillable. The passed detector must be alive until after the callback is
 // called.
diff --git a/components/dom_distiller/content/browser/distillable_page_utils_android.cc b/components/dom_distiller/content/browser/distillable_page_utils_android.cc
index 69a880e..b998842b 100644
--- a/components/dom_distiller/content/browser/distillable_page_utils_android.cc
+++ b/components/dom_distiller/content/browser/distillable_page_utils_android.cc
@@ -19,12 +19,6 @@
 namespace dom_distiller {
 namespace android {
 namespace {
-void OnIsPageDistillableResult(const JavaRef<jobject>& callback,
-                               bool isDistillable) {
-  Java_DistillablePageUtils_callOnIsPageDistillableResult(
-      base::android::AttachCurrentThread(), callback, isDistillable);
-}
-
 void OnIsPageDistillableUpdate(const JavaRef<jobject>& callback,
                                bool isDistillable,
                                bool isLast,
@@ -35,27 +29,6 @@
 }
 }  // namespace
 
-static void JNI_DistillablePageUtils_IsPageDistillable(
-    JNIEnv* env,
-    const JavaParamRef<jclass>& jcaller,
-    const JavaParamRef<jobject>& webContents,
-    jboolean is_mobile_optimized,
-    const JavaParamRef<jobject>& callback) {
-  content::WebContents* web_contents(
-      content::WebContents::FromJavaWebContents(webContents));
-
-  if (!web_contents) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::Bind(OnIsPageDistillableResult,
-                   ScopedJavaGlobalRef<jobject>(env, callback), false));
-    return;
-  }
-  IsDistillablePage(web_contents, is_mobile_optimized,
-                    base::Bind(OnIsPageDistillableResult,
-                               ScopedJavaGlobalRef<jobject>(env, callback)));
-}
-
 static void JNI_DistillablePageUtils_SetDelegate(
     JNIEnv* env,
     const JavaParamRef<jclass>& jcaller,
diff --git a/components/dom_distiller/content/browser/distillable_page_utils_browsertest.cc b/components/dom_distiller/content/browser/distillable_page_utils_browsertest.cc
index 99cee028..43a6f040 100644
--- a/components/dom_distiller/content/browser/distillable_page_utils_browsertest.cc
+++ b/components/dom_distiller/content/browser/distillable_page_utils_browsertest.cc
@@ -26,7 +26,6 @@
 namespace {
 
 const char* kArticlePath = "/og_article.html";
-const char* kNonArticlePath = "/non_og_article.html";
 
 class DomDistillerDistillablePageUtilsTest : public content::ContentBrowserTest,
                                              content::WebContentsObserver {
@@ -112,25 +111,6 @@
 
 }  // namespace
 
-IN_PROC_BROWSER_TEST_F(DomDistillerDistillablePageUtilsTest, TestIsOGArticle) {
-  LoadURL(kArticlePath);
-  base::RunLoop run_loop_;
-  ResultHolder holder(run_loop_.QuitClosure());
-  IsOpenGraphArticle(shell()->web_contents(), holder.GetCallback());
-  run_loop_.Run();
-  ASSERT_TRUE(holder.GetResult());
-}
-
-IN_PROC_BROWSER_TEST_F(DomDistillerDistillablePageUtilsTest,
-                       TestIsNotOGArticle) {
-  LoadURL(kNonArticlePath);
-  base::RunLoop run_loop_;
-  ResultHolder holder(run_loop_.QuitClosure());
-  IsOpenGraphArticle(shell()->web_contents(), holder.GetCallback());
-  run_loop_.Run();
-  ASSERT_FALSE(holder.GetResult());
-}
-
 IN_PROC_BROWSER_TEST_F(DomDistillerDistillablePageUtilsTest,
                        TestIsDistillablePage) {
   std::unique_ptr<AdaBoostProto> proto(new AdaBoostProto);
diff --git a/components/dom_distiller/core/data/distillable_page_model.bin b/components/dom_distiller/core/data/distillable_page_model.bin
deleted file mode 100644
index 39d02eb..0000000
--- a/components/dom_distiller/core/data/distillable_page_model.bin
+++ /dev/null
Binary files differ
diff --git a/components/dom_distiller/core/distillable_page_detector.cc b/components/dom_distiller/core/distillable_page_detector.cc
index 4467a0a..1a9e5777 100644
--- a/components/dom_distiller/core/distillable_page_detector.cc
+++ b/components/dom_distiller/core/distillable_page_detector.cc
@@ -13,20 +13,6 @@
 
 namespace dom_distiller {
 
-const DistillablePageDetector* DistillablePageDetector::GetDefault() {
-  static DistillablePageDetector* detector = nullptr;
-  if (!detector) {
-    std::string serialized_proto =
-        ui::ResourceBundle::GetSharedInstance()
-            .GetRawDataResource(IDR_DISTILLABLE_PAGE_SERIALIZED_MODEL)
-            .as_string();
-    std::unique_ptr<AdaBoostProto> proto(new AdaBoostProto);
-    CHECK(proto->ParseFromString(serialized_proto));
-    detector = new DistillablePageDetector(std::move(proto));
-  }
-  return detector;
-}
-
 const DistillablePageDetector* DistillablePageDetector::GetNewModel() {
   static DistillablePageDetector* detector = nullptr;
   if (!detector) {
diff --git a/components/dom_distiller/core/distillable_page_detector.h b/components/dom_distiller/core/distillable_page_detector.h
index 78efdd56..6fe2360 100644
--- a/components/dom_distiller/core/distillable_page_detector.h
+++ b/components/dom_distiller/core/distillable_page_detector.h
@@ -19,7 +19,6 @@
 // model.
 class DistillablePageDetector {
  public:
-  static const DistillablePageDetector* GetDefault();
   static const DistillablePageDetector* GetNewModel();
   static const DistillablePageDetector* GetLongPageModel();
   explicit DistillablePageDetector(std::unique_ptr<AdaBoostProto> proto);
diff --git a/components/dom_distiller/core/javascript/is_distillable_trigger.js b/components/dom_distiller/core/javascript/is_distillable_trigger.js
deleted file mode 100644
index b09aad48..0000000
--- a/components/dom_distiller/core/javascript/is_distillable_trigger.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(function() {
-  var elems = document.querySelectorAll(
-      'meta[property="og:type"],meta[name="og:type"]');
-  for (var i in elems) {
-    if (elems[i].content && elems[i].content.toUpperCase() == 'ARTICLE') {
-      return true;
-    }
-  }
-  var elems = document.querySelectorAll(
-      '*[itemtype="http://schema.org/Article"]');
-  for (var i in elems) {
-    if (elems[i].itemscope) {
-      return true;
-    }
-  }
-  return false;
-})()
diff --git a/components/exo/test/test_client_controlled_state_delegate.h b/components/exo/test/test_client_controlled_state_delegate.h
index 25f6e2570..a39ebb7a 100644
--- a/components/exo/test/test_client_controlled_state_delegate.h
+++ b/components/exo/test/test_client_controlled_state_delegate.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_EXO_TEST_TEST_CLIENT_CONTROLLED_STATE_DELEGATE_H_
+#define COMPONENTS_EXO_TEST_TEST_CLIENT_CONTROLLED_STATE_DELEGATE_H_
+
 #include "ash/wm/client_controlled_state.h"
 
 namespace exo {
@@ -29,3 +32,5 @@
 
 }  // namespace test
 }  // namespace exo
+
+#endif  // COMPONENTS_EXO_TEST_TEST_CLIENT_CONTROLLED_STATE_DELEGATE_H_
diff --git a/components/invalidation/impl/invalidation_prefs.h b/components/invalidation/impl/invalidation_prefs.h
index cabff41..0a3c674 100644
--- a/components/invalidation/impl/invalidation_prefs.h
+++ b/components/invalidation/impl/invalidation_prefs.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_INVALIDATION_IMPL_INVALIDATION_PREFS_H_
+#define COMPONENTS_INVALIDATION_IMPL_INVALIDATION_PREFS_H_
+
 namespace invalidation {
 namespace prefs {
 
@@ -15,3 +18,5 @@
 
 }  // namespace prefs
 }  // namespace invalidation
+
+#endif  // COMPONENTS_INVALIDATION_IMPL_INVALIDATION_PREFS_H_
diff --git a/components/invalidation/impl/p2p_invalidation_service.h b/components/invalidation/impl/p2p_invalidation_service.h
index 4c4dbcc..b59fb24 100644
--- a/components/invalidation/impl/p2p_invalidation_service.h
+++ b/components/invalidation/impl/p2p_invalidation_service.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_INVALIDATION_IMPL_P2P_INVALIDATION_SERVICE_H_
+#define COMPONENTS_INVALIDATION_IMPL_P2P_INVALIDATION_SERVICE_H_
+
 #include <memory>
 
 #include "base/callback_forward.h"
@@ -12,9 +15,6 @@
 #include "components/invalidation/public/invalidation_service.h"
 #include "components/keyed_service/core/keyed_service.h"
 
-#ifndef COMPONENTS_INVALIDATION_IMPL_P2P_INVALIDATION_SERVICE_H_
-#define COMPONENTS_INVALIDATION_IMPL_P2P_INVALIDATION_SERVICE_H_
-
 namespace net {
 class URLRequestContextGetter;
 }
diff --git a/components/language/content/browser/BUILD.gn b/components/language/content/browser/BUILD.gn
index 06b29c2..d0b41993 100644
--- a/components/language/content/browser/BUILD.gn
+++ b/components/language/content/browser/BUILD.gn
@@ -45,7 +45,7 @@
     ":language_code_locator",
     "//base",
     "//net",
-    "//services/device/public/interfaces:interfaces",
+    "//services/device/public/interfaces",
     "//services/service_manager/public/cpp",
   ]
 }
@@ -61,7 +61,7 @@
     ":language_code_locator",
     "//base",
     "//base/test:test_support",
-    "//services/device/public/interfaces:interfaces",
+    "//services/device/public/interfaces",
     "//services/service_manager/public/cpp",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/components/language/content/browser/DEPS b/components/language/content/browser/DEPS
index 9d2ba3a..6f17393 100644
--- a/components/language/content/browser/DEPS
+++ b/components/language/content/browser/DEPS
@@ -1,5 +1,4 @@
 include_rules = [
-  "+device/geolocation/public/interfaces",
   "+net",
   "+services/device/public/interfaces",
   "+services/service_manager/public",
diff --git a/components/language/content/browser/geo_language_provider.h b/components/language/content/browser/geo_language_provider.h
index b361a63..baf4551 100644
--- a/components/language/content/browser/geo_language_provider.h
+++ b/components/language/content/browser/geo_language_provider.h
@@ -12,7 +12,7 @@
 #include "base/sequence_checker.h"
 #include "base/sequenced_task_runner.h"
 #include "components/language/content/browser/language_code_locator.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom.h"
+#include "services/device/public/interfaces/geolocation.mojom.h"
 
 namespace base {
 template <typename T>
diff --git a/components/language/content/browser/geo_language_provider_unittest.cc b/components/language/content/browser/geo_language_provider_unittest.cc
index 8ed519b..c1d2abef 100644
--- a/components/language/content/browser/geo_language_provider_unittest.cc
+++ b/components/language/content/browser/geo_language_provider_unittest.cc
@@ -11,9 +11,9 @@
 #include "base/macros.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/timer/timer.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/device/public/interfaces/constants.mojom.h"
+#include "services/device/public/interfaces/geolocation.mojom.h"
 #include "services/device/public/interfaces/public_ip_address_geolocation_provider.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/interfaces/connector.mojom.h"
diff --git a/components/metrics/call_stack_profile_metrics_provider.cc b/components/metrics/call_stack_profile_metrics_provider.cc
index 4a222646..2cd3a45 100644
--- a/components/metrics/call_stack_profile_metrics_provider.cc
+++ b/components/metrics/call_stack_profile_metrics_provider.cc
@@ -56,14 +56,24 @@
         ProcessPhase::SHUTDOWN_START,
 };
 
-// Parameters for browser process sampling. Not const since these may be
-// changed when transitioning from start-up profiling to periodic profiling.
-CallStackProfileParams g_browser_process_sampling_params(
+// Parameters for UI thread of browser process sampling. Not const since these
+// may be changed when transitioning from start-up profiling to periodic
+// profiling.
+CallStackProfileParams g_ui_thread_sampling_params(
     CallStackProfileParams::BROWSER_PROCESS,
     CallStackProfileParams::UI_THREAD,
     CallStackProfileParams::PROCESS_STARTUP,
     CallStackProfileParams::MAY_SHUFFLE);
 
+// Parameters for IO thread of browser process sampling. Not const since these
+// may be changed when transitioning from start-up profiling to periodic
+// profiling.
+CallStackProfileParams g_io_thread_sampling_params(
+    CallStackProfileParams::BROWSER_PROCESS,
+    CallStackProfileParams::IO_THREAD,
+    CallStackProfileParams::PROCESS_STARTUP,
+    CallStackProfileParams::MAY_SHUFFLE);
+
 // ProfilesState --------------------------------------------------------------
 
 // A set of profiles and the CallStackProfileMetricsProvider state associated
@@ -553,9 +563,14 @@
 CallStackProfileMetricsProvider::~CallStackProfileMetricsProvider() {
 }
 
-StackSamplingProfiler::CompletedCallback
-CallStackProfileMetricsProvider::GetProfilerCallbackForBrowserProcessStartup() {
-  return internal::GetProfilerCallback(&g_browser_process_sampling_params);
+StackSamplingProfiler::CompletedCallback CallStackProfileMetricsProvider::
+    GetProfilerCallbackForBrowserProcessUIThreadStartup() {
+  return internal::GetProfilerCallback(&g_ui_thread_sampling_params);
+}
+
+StackSamplingProfiler::CompletedCallback CallStackProfileMetricsProvider::
+    GetProfilerCallbackForBrowserProcessIOThreadStartup() {
+  return internal::GetProfilerCallback(&g_io_thread_sampling_params);
 }
 
 // static
@@ -608,14 +623,14 @@
 
   for (const ProfilesState& profiles_state : pending_profiles) {
     for (const StackSamplingProfiler::CallStackProfile& profile :
-             profiles_state.profiles) {
+         profiles_state.profiles) {
       SampledProfile* sampled_profile = uma_proto->add_sampled_profile();
-      sampled_profile->set_process(ToExecutionContextProcess(
-          profiles_state.params.process));
-      sampled_profile->set_thread(ToExecutionContextThread(
-          profiles_state.params.thread));
-      sampled_profile->set_trigger_event(ToSampledProfileTriggerEvent(
-          profiles_state.params.trigger));
+      sampled_profile->set_process(
+          ToExecutionContextProcess(profiles_state.params.process));
+      sampled_profile->set_thread(
+          ToExecutionContextThread(profiles_state.params.thread));
+      sampled_profile->set_trigger_event(
+          ToSampledProfileTriggerEvent(profiles_state.params.trigger));
       CopyProfileToProto(profile, profiles_state.params.ordering_spec,
                          sampled_profile->mutable_call_stack_profile());
     }
diff --git a/components/metrics/call_stack_profile_metrics_provider.h b/components/metrics/call_stack_profile_metrics_provider.h
index 0f6d2a0..0a5391d 100644
--- a/components/metrics/call_stack_profile_metrics_provider.h
+++ b/components/metrics/call_stack_profile_metrics_provider.h
@@ -54,10 +54,18 @@
   ~CallStackProfileMetricsProvider() override;
 
   // Returns a callback for use with StackSamplingProfiler that sets up
-  // parameters for browser process startup sampling. The callback should be
-  // immediately passed to the StackSamplingProfiler, and should not be reused.
+  // parameters for UI thread of browser process startup sampling. The callback
+  // should be immediately passed to the StackSamplingProfiler, and should not
+  // be reused.
   static base::StackSamplingProfiler::CompletedCallback
-  GetProfilerCallbackForBrowserProcessStartup();
+  GetProfilerCallbackForBrowserProcessUIThreadStartup();
+
+  // Returns a callback for use with StackSamplingProfiler that sets up
+  // parameters for IO thread of browser process startup sampling. The callback
+  // should be immediately passed to the StackSamplingProfiler, and should not
+  // be reused.
+  static base::StackSamplingProfiler::CompletedCallback
+  GetProfilerCallbackForBrowserProcessIOThreadStartup();
 
   // Provides completed stack profiles to the metrics provider. Intended for use
   // when receiving profiles over IPC. In-process StackSamplingProfiler users
diff --git a/components/nacl/renderer/file_downloader.h b/components/nacl/renderer/file_downloader.h
index 64a71f7..090db4ae 100644
--- a/components/nacl/renderer/file_downloader.h
+++ b/components/nacl/renderer/file_downloader.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_NACL_RENDERER_FILE_DOWNLOADER_H_
+#define COMPONENTS_NACL_RENDERER_FILE_DOWNLOADER_H_
+
 #include <stdint.h>
 
 #include <string>
@@ -64,3 +67,5 @@
 };
 
 }  // namespace nacl
+
+#endif  // COMPONENTS_NACL_RENDERER_FILE_DOWNLOADER_H_
diff --git a/components/nacl/renderer/manifest_downloader.h b/components/nacl/renderer/manifest_downloader.h
index 9c247fc..a06a347 100644
--- a/components/nacl/renderer/manifest_downloader.h
+++ b/components/nacl/renderer/manifest_downloader.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_NACL_RENDERER_MANIFEST_DOWNLOADER_H_
+#define COMPONENTS_NACL_RENDERER_MANIFEST_DOWNLOADER_H_
+
 #include <stddef.h>
 #include <stdint.h>
 
@@ -58,3 +61,5 @@
 };
 
 }  // namespace nacl
+
+#endif  // COMPONENTS_NACL_RENDERER_MANIFEST_DOWNLOADER_H_
diff --git a/components/resources/dom_distiller_resources.grdp b/components/resources/dom_distiller_resources.grdp
index d340722..3c3cc1a 100644
--- a/components/resources/dom_distiller_resources.grdp
+++ b/components/resources/dom_distiller_resources.grdp
@@ -9,9 +9,7 @@
   <include name="IDR_DISTILLER_CSS" file="../dom_distiller/core/css/distilledpage.css" type="BINDATA" />
   <include name="IDR_DISTILLER_IOS_CSS" file="../dom_distiller/core/css/distilledpage_ios.css" type="BINDATA" />
   <include name="IDR_DISTILLER_LOADING_IMAGE" file="../dom_distiller/core/images/dom_distiller_material_spinner.svg" type="BINDATA" />
-  <include name="IDR_IS_DISTILLABLE_JS" file="../dom_distiller/core/javascript/is_distillable_trigger.js" type="BINDATA" />
   <include name="IDR_EXTRACT_PAGE_FEATURES_JS" file="../dom_distiller/core/javascript/extract_features.js" type="BINDATA" />
-  <include name="IDR_DISTILLABLE_PAGE_SERIALIZED_MODEL" file="../dom_distiller/core/data/distillable_page_model.bin" type="BINDATA" />
   <include name="IDR_DISTILLABLE_PAGE_SERIALIZED_MODEL_NEW" file="../dom_distiller/core/data/distillable_page_model_new.bin" type="BINDATA" />
   <include name="IDR_LONG_PAGE_SERIALIZED_MODEL" file="../dom_distiller/core/data/long_page_model.bin" type="BINDATA" />
 </grit-part>
diff --git a/components/variations/service/safe_seed_manager.cc b/components/variations/service/safe_seed_manager.cc
index d22b813..72def41 100644
--- a/components/variations/service/safe_seed_manager.cc
+++ b/components/variations/service/safe_seed_manager.cc
@@ -61,6 +61,12 @@
   registry->RegisterIntegerPref(prefs::kVariationsFailedToFetchSeedStreak, 0);
 }
 
+bool SafeSeedManager::ShouldRunInSafeMode() const {
+  // TODO(isherman): Choose reasonable thresholds for the crash and fetch
+  // failure streaks, and return true or false based on those.
+  return false;
+}
+
 void SafeSeedManager::SetActiveSeedState(
     const std::string& seed_data,
     const std::string& base64_seed_signature,
@@ -89,8 +95,6 @@
   // even if running in safe mode, as the saved seed in that case will just be
   // the existing safe seed.
   if (active_seed_state_) {
-    // TODO(isherman): As an optimization, skip writing the seed if we're
-    // already running in safe mode.
     seed_store->StoreSafeSeed(active_seed_state_->seed_data,
                               active_seed_state_->base64_seed_signature,
                               *active_seed_state_->client_filterable_state);
diff --git a/components/variations/service/safe_seed_manager.h b/components/variations/service/safe_seed_manager.h
index e1e76da..7efd6cc6 100644
--- a/components/variations/service/safe_seed_manager.h
+++ b/components/variations/service/safe_seed_manager.h
@@ -30,8 +30,13 @@
   // Register safe mode prefs in Local State.
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
+  // Returns true iff the client should use the safe seed for variations state.
+  // Virtual for testing.
+  virtual bool ShouldRunInSafeMode() const;
+
   // Stores the combined server and client state that control the active
   // variations state. Must be called at most once per launch of the Chrome app.
+  // As an optimization, should not be called when running in safe mode.
   // Virtual for testing.
   virtual void SetActiveSeedState(
       const std::string& seed_data,
@@ -49,7 +54,7 @@
 
  private:
   // The combined server and client state needed to save an active seed as a
-  // safe seed.
+  // safe seed. Not set when running in safe mode.
   struct ActiveSeedState {
     ActiveSeedState(
         const std::string& seed_data,
diff --git a/components/variations/service/variations_field_trial_creator.cc b/components/variations/service/variations_field_trial_creator.cc
index 0962bf1..0fafb7d 100644
--- a/components/variations/service/variations_field_trial_creator.cc
+++ b/components/variations/service/variations_field_trial_creator.cc
@@ -178,10 +178,15 @@
   std::unique_ptr<ClientFilterableState> client_filterable_state =
       GetClientFilterableStateForVersion(current_version);
 
+  // TODO(isherman): Record the seed freshness when running in safe mode.
   VariationsSeed seed;
+  bool run_in_safe_mode =
+      safe_seed_manager->ShouldRunInSafeMode() &&
+      GetSeedStore()->LoadSafeSeed(&seed, client_filterable_state.get());
+
   std::string seed_data;
   std::string base64_seed_signature;
-  if (!LoadSeed(&seed, &seed_data, &base64_seed_signature))
+  if (!run_in_safe_mode && !LoadSeed(&seed, &seed_data, &base64_seed_signature))
     return false;
 
   // Note that passing |&ui_string_overrider_| via base::Unretained below is
@@ -195,9 +200,13 @@
       low_entropy_provider.get(), feature_list);
 
   // Store into the |safe_seed_manager| the combined server and client data used
-  // to create the field trials.
-  safe_seed_manager->SetActiveSeedState(seed_data, base64_seed_signature,
-                                        std::move(client_filterable_state));
+  // to create the field trials. But, as an optimization, skip this step when
+  // running in safe mode – once running in safe mode, there can never be a need
+  // to save the active state to the safe seed prefs.
+  if (!run_in_safe_mode) {
+    safe_seed_manager->SetActiveSeedState(seed_data, base64_seed_signature,
+                                          std::move(client_filterable_state));
+  }
 
   UMA_HISTOGRAM_TIMES("Variations.SeedProcessingTime",
                       base::TimeTicks::Now() - start_time);
@@ -331,7 +340,7 @@
 bool VariationsFieldTrialCreator::LoadSeed(VariationsSeed* seed,
                                            std::string* seed_data,
                                            std::string* base64_signature) {
-  if (!LoadSeedFromStore(seed, seed_data, base64_signature))
+  if (!GetSeedStore()->LoadSeed(seed, seed_data, base64_signature))
     return false;
 
   const base::Time last_fetch_time =
@@ -358,13 +367,6 @@
   return true;
 }
 
-bool VariationsFieldTrialCreator::LoadSeedFromStore(
-    VariationsSeed* seed,
-    std::string* seed_data,
-    std::string* base64_signature) {
-  return seed_store_.LoadSeed(seed, seed_data, base64_signature);
-}
-
 bool VariationsFieldTrialCreator::SetupFieldTrials(
     const char* kEnableGpuBenchmarking,
     const char* kEnableFeatures,
@@ -437,4 +439,8 @@
   return has_seed;
 }
 
+VariationsSeedStore* VariationsFieldTrialCreator::GetSeedStore() {
+  return &seed_store_;
+};
+
 }  // namespace variations
diff --git a/components/variations/service/variations_field_trial_creator.h b/components/variations/service/variations_field_trial_creator.h
index 5cf2b62..23b7c0b2 100644
--- a/components/variations/service/variations_field_trial_creator.h
+++ b/components/variations/service/variations_field_trial_creator.h
@@ -96,14 +96,6 @@
                 std::string* seed_data,
                 std::string* base64_signature);
 
-  // Loads the seed from the variations store into |seed|. Returns true on
-  // success, in which case |seed| will contain the loaded data, and |seed_data|
-  // and |base64_signature| will contain the raw pref values. Virtual for
-  // testing.
-  virtual bool LoadSeedFromStore(VariationsSeed* seed,
-                                 std::string* seed_data,
-                                 std::string* base64_signature);
-
   // Creates field trials based on the variations seed loaded from local state.
   // If there is a problem loading the seed data, all trials specified by the
   // seed may not be created. Some field trials are configured to override or
@@ -117,6 +109,9 @@
       base::FeatureList* feature_list,
       SafeSeedManager* safe_seed_manager);
 
+  // Returns the seed store. Virtual for testing.
+  virtual VariationsSeedStore* GetSeedStore();
+
   PrefService* local_state() { return seed_store_.local_state(); }
   const PrefService* local_state() const { return seed_store_.local_state(); }
 
diff --git a/components/variations/service/variations_field_trial_creator_unittest.cc b/components/variations/service/variations_field_trial_creator_unittest.cc
index 560642c..dc06a37 100644
--- a/components/variations/service/variations_field_trial_creator_unittest.cc
+++ b/components/variations/service/variations_field_trial_creator_unittest.cc
@@ -21,13 +21,15 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 using testing::_;
+using testing::Return;
 
 namespace variations {
 namespace {
 
-// Constants used to create the test seed.
+// Constants used to create the test seeds.
 const char kTestSeedStudyName[] = "test";
 const char kTestSeedExperimentName[] = "abc";
+const char kTestSafeSeedExperimentName[] = "abc.safe";
 const int kTestSeedExperimentProbability = 100;
 const char kTestSeedSerialNumber[] = "123";
 
@@ -51,6 +53,19 @@
   return seed;
 }
 
+// Returns a seed containing simple test data. The resulting seed will contain
+// one study called "test", which contains one experiment called "abc.safe" with
+// probability weight 100. This is intended to be used whenever a "safe" seed is
+// called for, so that test expectations can distinguish between a "safe" seed
+// and a "latest" seed.
+VariationsSeed CreateTestSafeSeed() {
+  VariationsSeed seed = CreateTestSeed();
+  Study* study = seed.mutable_study(0);
+  study->set_default_experiment_name(kTestSafeSeedExperimentName);
+  study->mutable_experiment(0)->set_name(kTestSafeSeedExperimentName);
+  return seed;
+}
+
 class TestPlatformFieldTrials : public PlatformFieldTrials {
  public:
   TestPlatformFieldTrials() = default;
@@ -61,6 +76,9 @@
   void SetupFeatureControllingFieldTrials(
       bool has_seed,
       base::FeatureList* feature_list) override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestPlatformFieldTrials);
 };
 
 class MockSafeSeedManager : public SafeSeedManager {
@@ -69,6 +87,7 @@
       : SafeSeedManager(true, local_state) {}
   ~MockSafeSeedManager() override = default;
 
+  MOCK_CONST_METHOD0(ShouldRunInSafeMode, bool());
   MOCK_METHOD3(DoSetActiveSeedState,
                void(const std::string& seed_data,
                     const std::string& base64_seed_signature,
@@ -123,12 +142,48 @@
   DISALLOW_COPY_AND_ASSIGN(TestVariationsServiceClient);
 };
 
+class TestVariationsSeedStore : public VariationsSeedStore {
+ public:
+  TestVariationsSeedStore(PrefService* local_state)
+      : VariationsSeedStore(local_state) {}
+  ~TestVariationsSeedStore() override = default;
+
+  bool LoadSeed(VariationsSeed* seed,
+                std::string* seed_data,
+                std::string* base64_signature) override {
+    *seed = CreateTestSeed();
+    *seed_data = kTestSeedData;
+    *base64_signature = kTestSeedSignature;
+    return true;
+  }
+
+  bool LoadSafeSeed(VariationsSeed* seed,
+                    ClientFilterableState* client_state) override {
+    if (has_corrupted_safe_seed_)
+      return false;
+
+    *seed = CreateTestSafeSeed();
+    return true;
+  }
+
+  void set_has_corrupted_safe_seed(bool is_corrupted) {
+    has_corrupted_safe_seed_ = is_corrupted;
+  }
+
+ private:
+  // Whether to simulate having a corrupted safe seed.
+  bool has_corrupted_safe_seed_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(TestVariationsSeedStore);
+};
+
 class TestVariationsFieldTrialCreator : public VariationsFieldTrialCreator {
  public:
   TestVariationsFieldTrialCreator(PrefService* local_state,
                                   TestVariationsServiceClient* client,
                                   SafeSeedManager* safe_seed_manager)
       : VariationsFieldTrialCreator(local_state, client, UIStringOverrider()),
+        seed_store_(local_state),
         safe_seed_manager_(safe_seed_manager) {}
 
   ~TestVariationsFieldTrialCreator() override = default;
@@ -144,16 +199,12 @@
         &platform_field_trials, safe_seed_manager_);
   }
 
- private:
-  bool LoadSeedFromStore(VariationsSeed* seed,
-                         std::string* seed_data,
-                         std::string* base64_signature) override {
-    *seed = CreateTestSeed();
-    *seed_data = kTestSeedData;
-    *base64_signature = kTestSeedSignature;
-    return true;
-  }
+  TestVariationsSeedStore* seed_store() { return &seed_store_; }
 
+ private:
+  VariationsSeedStore* GetSeedStore() override { return &seed_store_; }
+
+  TestVariationsSeedStore seed_store_;
   SafeSeedManager* const safe_seed_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(TestVariationsFieldTrialCreator);
@@ -193,6 +244,8 @@
   // With a valid seed, the safe seed manager should be informed of the active
   // seed state.
   testing::NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
+  ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
+      .WillByDefault(Return(false));
   EXPECT_CALL(safe_seed_manager,
               DoSetActiveSeedState(kTestSeedData, kTestSeedSignature, _))
       .Times(1);
@@ -215,6 +268,8 @@
   // With a valid seed on first run, the safe seed manager should be informed of
   // the active seed state.
   testing::NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
+  ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
+      .WillByDefault(Return(false));
   EXPECT_CALL(safe_seed_manager,
               DoSetActiveSeedState(kTestSeedData, kTestSeedSignature, _))
       .Times(1);
@@ -237,6 +292,8 @@
   // With an expired seed, there should be no field trials created, and hence no
   // active state should be passed to the safe seed manager.
   testing::NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
+  ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
+      .WillByDefault(Return(false));
   EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _)).Times(0);
 
   TestVariationsServiceClient variations_service_client;
@@ -253,4 +310,48 @@
   EXPECT_TRUE(base::FieldTrialList::FindFullName(kTestSeedStudyName).empty());
 }
 
+TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSafeSeed) {
+  // With a valid safe seed, the safe seed manager should *not* be informed of
+  // the active seed state. This is an optimization to avoid saving a safe seed
+  // when already running in safe mode.
+  testing::NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
+  ON_CALL(safe_seed_manager, ShouldRunInSafeMode()).WillByDefault(Return(true));
+  EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _)).Times(0);
+
+  TestVariationsServiceClient variations_service_client;
+  TestVariationsFieldTrialCreator field_trial_creator(
+      &prefs_, &variations_service_client, &safe_seed_manager);
+
+  // Check that field trials are created from the safe seed. Since the test
+  // study has only 1 experiment with 100% probability weight, we must be part
+  // of it.
+  EXPECT_TRUE(field_trial_creator.SetupFieldTrials());
+  EXPECT_EQ(kTestSafeSeedExperimentName,
+            base::FieldTrialList::FindFullName(kTestSeedStudyName));
+}
+
+TEST_F(FieldTrialCreatorTest,
+       SetupFieldTrials_CorruptedSafeSeed_FallsBackToLatestSeed) {
+  // With a corrupted safe seed, the field trial creator should fall back to the
+  // latest seed. Hence, the safe seed manager *should* be informed of the
+  // active seed state.
+  testing::NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
+  ON_CALL(safe_seed_manager, ShouldRunInSafeMode()).WillByDefault(Return(true));
+  EXPECT_CALL(safe_seed_manager,
+              DoSetActiveSeedState(kTestSeedData, kTestSeedSignature, _))
+      .Times(1);
+
+  TestVariationsServiceClient variations_service_client;
+  TestVariationsFieldTrialCreator field_trial_creator(
+      &prefs_, &variations_service_client, &safe_seed_manager);
+  field_trial_creator.seed_store()->set_has_corrupted_safe_seed(true);
+
+  // Check that field trials are created from the latest seed. Since the test
+  // study has only 1 experiment with 100% probability weight, we must be part
+  // of it.
+  EXPECT_TRUE(field_trial_creator.SetupFieldTrials());
+  EXPECT_EQ(kTestSeedExperimentName,
+            base::FieldTrialList::FindFullName(kTestSeedStudyName));
+}
+
 }  // namespace variations
diff --git a/components/variations/variations_seed_store.h b/components/variations/variations_seed_store.h
index fff7bcb..1e83570 100644
--- a/components/variations/variations_seed_store.h
+++ b/components/variations/variations_seed_store.h
@@ -33,9 +33,10 @@
   // raw pref values into |seed_data| and |base64_signature|. If there is a
   // problem with loading, clears the seed pref value and returns false. If
   // successful, fills the the outparams with the loaded data and returns true.
-  bool LoadSeed(VariationsSeed* seed,
-                std::string* seed_data,
-                std::string* base64_seed_signature) WARN_UNUSED_RESULT;
+  // Virtual for testing.
+  virtual bool LoadSeed(VariationsSeed* seed,
+                        std::string* seed_data,
+                        std::string* base64_seed_signature) WARN_UNUSED_RESULT;
 
   // Stores the given seed |data| (serialized protobuf) to local state, along
   // with a base64-encoded digital signature for seed and the date when it was
@@ -63,8 +64,10 @@
   // loaded, it is guaranteed that no fields in |client_state| are modified.
   // Side-effect: Upon any failure to read or validate the safe seed, clears all
   // of the safe seed pref values. This occurs iff the method returns false.
-  bool LoadSafeSeed(VariationsSeed* seed,
-                    ClientFilterableState* client_state) WARN_UNUSED_RESULT;
+  // Virtual for testing.
+  virtual bool LoadSafeSeed(VariationsSeed* seed,
+                            ClientFilterableState* client_state)
+      WARN_UNUSED_RESULT;
 
   // Stores the given |seed_data| (a serialized protobuf) to local state as a
   // safe seed, along with a base64-encoded digital signature for seed and any
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 7fc9f7f..e53c1b6b 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -84,7 +84,6 @@
     "//device/gamepad",
     "//device/geolocation",
     "//device/geolocation/public/cpp",
-    "//device/geolocation/public/interfaces",
     "//device/screen_orientation/public/interfaces",
     "//device/u2f",
     "//device/vr:mojo_bindings",
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc
index fc197cd5..55ad3678 100644
--- a/content/browser/background_sync/background_sync_manager.cc
+++ b/content/browser/background_sync/background_sync_manager.cc
@@ -792,7 +792,7 @@
       ServiceWorkerVersion::CONTINUE_ON_TIMEOUT);
 
   active_version->event_dispatcher()->DispatchSyncEvent(
-      tag, last_chance,
+      tag, last_chance, parameters_->max_sync_event_duration,
       base::BindOnce(&OnSyncEventFinished, std::move(active_version),
                      request_id, repeating_callback));
 }
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 9ff73dc..806a68c 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -992,6 +992,10 @@
       base::Bind(&BrowserMainLoop::CreateThreads, base::Unretained(this));
   startup_task_runner_->AddTask(create_threads);
 
+  StartupTask post_create_threads =
+      base::Bind(&BrowserMainLoop::PostCreateThreads, base::Unretained(this));
+  startup_task_runner_->AddTask(post_create_threads);
+
   StartupTask browser_thread_started = base::Bind(
       &BrowserMainLoop::BrowserThreadsStarted, base::Unretained(this));
   startup_task_runner_->AddTask(browser_thread_started);
@@ -1214,6 +1218,15 @@
   return result_code_;
 }
 
+int BrowserMainLoop::PostCreateThreads() {
+  if (parts_) {
+    TRACE_EVENT0("startup", "BrowserMainLoop::PostCreateThreads");
+    parts_->PostCreateThreads();
+  }
+
+  return result_code_;
+}
+
 int BrowserMainLoop::PreMainMessageLoopRun() {
 #if defined(OS_ANDROID)
   // Let screen instance be overridable by parts.
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h
index 436c293e..0bc4fc0 100644
--- a/content/browser/browser_main_loop.h
+++ b/content/browser/browser_main_loop.h
@@ -241,6 +241,9 @@
   // Create all secondary threads.
   int CreateThreads();
 
+  // Called just after creating the threads.
+  int PostCreateThreads();
+
   // Called right after the browser threads have been started.
   int BrowserThreadsStarted();
 
@@ -272,6 +275,7 @@
   // CreateStartupTasks()
   //   PreCreateThreads()
   //   CreateThreads()
+  //   PostCreateThreads()
   //   BrowserThreadsStarted()
   //     InitializeMojo()
   //     InitStartupTracingForDuration()
diff --git a/content/browser/devtools/devtools_agent_host_impl.cc b/content/browser/devtools/devtools_agent_host_impl.cc
index ffb7fb7c..b71fdd5c 100644
--- a/content/browser/devtools/devtools_agent_host_impl.cc
+++ b/content/browser/devtools/devtools_agent_host_impl.cc
@@ -311,11 +311,13 @@
   }
 }
 
-void DevToolsAgentHostImpl::ForceDetachSession(DevToolsSession* session) {
-  DevToolsAgentHostClient* client = session->client();
-  InnerDetachClient(client);
-  client->AgentHostClosed(this);
-}
+void DevToolsAgentHostImpl::AttachSession(DevToolsSession* session) {}
+
+void DevToolsAgentHostImpl::DetachSession(DevToolsSession* session) {}
+
+void DevToolsAgentHostImpl::DispatchProtocolMessage(
+    DevToolsSession* session,
+    const std::string& message) {}
 
 void DevToolsAgentHostImpl::InspectElement(
     DevToolsSession* session,
diff --git a/content/browser/devtools/devtools_agent_host_impl.h b/content/browser/devtools/devtools_agent_host_impl.h
index 17248eb..da7c5a9a 100644
--- a/content/browser/devtools/devtools_agent_host_impl.h
+++ b/content/browser/devtools/devtools_agent_host_impl.h
@@ -63,16 +63,15 @@
 
   static bool ShouldForceCreation();
 
-  virtual void AttachSession(DevToolsSession* session) = 0;
-  virtual void DetachSession(DevToolsSession* session) = 0;
+  virtual void AttachSession(DevToolsSession* session);
+  virtual void DetachSession(DevToolsSession* session);
   virtual void DispatchProtocolMessage(DevToolsSession* session,
-                                       const std::string& message) = 0;
+                                       const std::string& message);
   virtual void InspectElement(DevToolsSession* session, int x, int y);
 
   void NotifyCreated();
   void NotifyNavigated(DevToolsAgentHostImpl* host);
   void ForceDetachAllClients();
-  void ForceDetachSession(DevToolsSession* session);
   DevToolsIOContext* GetIOContext() { return &io_context_; }
 
   base::flat_set<DevToolsSession*>& sessions() { return sessions_; }
diff --git a/content/browser/devtools/devtools_session.h b/content/browser/devtools/devtools_session.h
index 72d19e4..5d4aad3f 100644
--- a/content/browser/devtools/devtools_session.h
+++ b/content/browser/devtools/devtools_session.h
@@ -28,8 +28,6 @@
                   DevToolsAgentHostClient* client);
   ~DevToolsSession() override;
 
-  DevToolsAgentHostClient* client() const { return client_; }
-
   // Browser-only sessions do not talk to mojom::DevToolsAgent, but instead
   // handle all protocol messages locally in the browser process.
   void SetBrowserOnly(bool browser_only);
diff --git a/content/browser/devtools/forwarding_agent_host.cc b/content/browser/devtools/forwarding_agent_host.cc
index 51a7dd8..2b60cf23 100644
--- a/content/browser/devtools/forwarding_agent_host.cc
+++ b/content/browser/devtools/forwarding_agent_host.cc
@@ -14,24 +14,28 @@
 
 class ForwardingAgentHost::SessionProxy : public DevToolsExternalAgentProxy {
  public:
-  SessionProxy(ForwardingAgentHost* agent_host, DevToolsSession* session)
-      : agent_host_(agent_host), session_(session) {
+  SessionProxy(ForwardingAgentHost* agent_host, DevToolsAgentHostClient* client)
+      : agent_host_(agent_host), client_(client) {
     agent_host_->delegate_->Attach(this);
   }
 
   ~SessionProxy() override { agent_host_->delegate_->Detach(this); }
 
- private:
-  void DispatchOnClientHost(const std::string& message) override {
-    session_->client()->DispatchProtocolMessage(agent_host_, message);
+  void ConnectionClosed() override {
+    DevToolsAgentHostClient* client = client_;
+    ForwardingAgentHost* agent_host = agent_host_;
+    agent_host_->session_proxies_.erase(client_);
+    // |this| is delete here, do not use any fields below.
+    client->AgentHostClosed(agent_host);
   }
 
-  void ConnectionClosed() override {
-    agent_host_->ForceDetachSession(session_);
+ private:
+  void DispatchOnClientHost(const std::string& message) override {
+    client_->DispatchProtocolMessage(agent_host_, message);
   }
 
   ForwardingAgentHost* agent_host_;
-  DevToolsSession* session_;
+  DevToolsAgentHostClient* client_;
 
   DISALLOW_COPY_AND_ASSIGN(SessionProxy);
 };
@@ -47,19 +51,36 @@
 ForwardingAgentHost::~ForwardingAgentHost() {
 }
 
-void ForwardingAgentHost::AttachSession(DevToolsSession* session) {
-  session_proxies_[session].reset(new SessionProxy(this, session));
+void ForwardingAgentHost::AttachClient(DevToolsAgentHostClient* client) {
+  session_proxies_[client].reset(new SessionProxy(this, client));
 }
 
-void ForwardingAgentHost::DetachSession(DevToolsSession* session) {
-  session_proxies_.erase(session);
+void ForwardingAgentHost::ForceAttachClient(DevToolsAgentHostClient* client) {
+  while (!session_proxies_.empty())
+    session_proxies_.begin()->second->ConnectionClosed();
+  AttachClient(client);
 }
 
-void ForwardingAgentHost::DispatchProtocolMessage(DevToolsSession* session,
-                                                  const std::string& message) {
-  auto it = session_proxies_.find(session);
-  if (it != session_proxies_.end())
-    delegate_->SendMessageToBackend(it->second.get(), message);
+bool ForwardingAgentHost::DetachClient(DevToolsAgentHostClient* client) {
+  auto it = session_proxies_.find(client);
+  if (it == session_proxies_.end())
+    return false;
+  session_proxies_.erase(it);
+  return true;
+}
+
+bool ForwardingAgentHost::DispatchProtocolMessage(
+    DevToolsAgentHostClient* client,
+    const std::string& message) {
+  auto it = session_proxies_.find(client);
+  if (it == session_proxies_.end())
+    return false;
+  delegate_->SendMessageToBackend(it->second.get(), message);
+  return true;
+}
+
+bool ForwardingAgentHost::IsAttached() {
+  return !session_proxies_.empty();
 }
 
 std::string ForwardingAgentHost::GetType() {
diff --git a/content/browser/devtools/forwarding_agent_host.h b/content/browser/devtools/forwarding_agent_host.h
index 307adc08..b09b2cf 100644
--- a/content/browser/devtools/forwarding_agent_host.h
+++ b/content/browser/devtools/forwarding_agent_host.h
@@ -26,13 +26,13 @@
 
   ~ForwardingAgentHost() override;
 
-  // DevToolsAgentHostImpl implementation.
-  void AttachSession(DevToolsSession* session) override;
-  void DetachSession(DevToolsSession* session) override;
-  void DispatchProtocolMessage(DevToolsSession* session,
-                               const std::string& message) override;
-
   // DevToolsAgentHost implementation
+  void AttachClient(DevToolsAgentHostClient* client) override;
+  void ForceAttachClient(DevToolsAgentHostClient* client) override;
+  bool DetachClient(DevToolsAgentHostClient* client) override;
+  bool DispatchProtocolMessage(DevToolsAgentHostClient* client,
+                               const std::string& message) override;
+  bool IsAttached() override;
   std::string GetType() override;
   std::string GetTitle() override;
   GURL GetURL() override;
@@ -44,7 +44,7 @@
   base::TimeTicks GetLastActivityTime() override;
 
   std::unique_ptr<DevToolsExternalAgentProxyDelegate> delegate_;
-  base::flat_map<DevToolsSession*, std::unique_ptr<SessionProxy>>
+  base::flat_map<DevToolsAgentHostClient*, std::unique_ptr<SessionProxy>>
       session_proxies_;
 
   DISALLOW_COPY_AND_ASSIGN(ForwardingAgentHost);
diff --git a/content/browser/devtools/protocol/emulation_handler.cc b/content/browser/devtools/protocol/emulation_handler.cc
index 3aa6d514..15f517f 100644
--- a/content/browser/devtools/protocol/emulation_handler.cc
+++ b/content/browser/devtools/protocol/emulation_handler.cc
@@ -15,8 +15,8 @@
 #include "content/common/view_messages.h"
 #include "content/public/common/url_constants.h"
 #include "device/geolocation/public/cpp/geoposition.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "services/device/public/interfaces/geolocation_context.mojom.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 #include "ui/events/gesture_detection/gesture_provider_config_helper.h"
 
 namespace content {
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 159ec01..0441f72 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -372,6 +372,13 @@
                  render_process_id, params.render_view_routing_id));
 }
 
+bool IsOutOfProcessNetworkService() {
+  return base::FeatureList::IsEnabled(features::kNetworkService) &&
+         !base::FeatureList::IsEnabled(features::kNetworkServiceInProcess) &&
+         !base::CommandLine::ForCurrentProcess()->HasSwitch(
+             switches::kSingleProcess);
+}
+
 }  // namespace
 
 // static
@@ -2253,6 +2260,16 @@
   delegate_->ViewSource(this);
 }
 
+void RenderFrameHostImpl::FlushNetworkAndNavigationInterfacesForTesting() {
+  DCHECK(network_service_connection_error_handler_holder_);
+  network_service_connection_error_handler_holder_.FlushForTesting();
+
+  if (!navigation_control_)
+    GetNavigationControl();
+  DCHECK(navigation_control_);
+  navigation_control_.FlushForTesting();
+}
+
 void RenderFrameHostImpl::OnDidAccessInitialDocument() {
   delegate_->DidAccessInitialDocument();
 }
@@ -3260,6 +3277,7 @@
   }
   send_before_unload_start_time_ = base::TimeTicks();
   render_view_host_->is_waiting_for_close_ack_ = false;
+  network_service_connection_error_handler_holder_.reset();
 }
 
 bool RenderFrameHostImpl::CanCommitOrigin(
@@ -3553,17 +3571,8 @@
     if (!default_factory_info) {
       // Otherwise default to a Network Service-backed loader from the
       // appropriate NetworkContext.
-      if (g_url_loader_factory_callback_for_test.Get().is_null()) {
-        storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
-            mojo::MakeRequest(&default_factory_info), GetProcess()->GetID());
-      } else {
-        network::mojom::URLLoaderFactoryPtr original_factory;
-        storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
-            mojo::MakeRequest(&original_factory), GetProcess()->GetID());
-        g_url_loader_factory_callback_for_test.Get().Run(
-            mojo::MakeRequest(&default_factory_info), GetProcess()->GetID(),
-            original_factory.PassInterface());
-      }
+      CreateNetworkServiceDefaultFactoryAndObserve(
+          mojo::MakeRequest(&default_factory_info));
     }
 
     DCHECK(default_factory_info);
@@ -3659,22 +3668,9 @@
   // completing an unload handler.
   ResetWaitingState();
 
-  StoragePartitionImpl* storage_partition =
-      static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
-          GetSiteInstance()->GetBrowserContext(), GetSiteInstance()));
-
   network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
-  if (g_url_loader_factory_callback_for_test.Get().is_null()) {
-    storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
-        mojo::MakeRequest(&default_factory_info), GetProcess()->GetID());
-  } else {
-    network::mojom::URLLoaderFactoryPtr original_factory;
-    storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
-        mojo::MakeRequest(&original_factory), GetProcess()->GetID());
-    g_url_loader_factory_callback_for_test.Get().Run(
-        mojo::MakeRequest(&default_factory_info), GetProcess()->GetID(),
-        original_factory.PassInterface());
-  }
+  CreateNetworkServiceDefaultFactoryAndObserve(
+      mojo::MakeRequest(&default_factory_info));
 
   auto subresource_loader_factories =
       std::make_unique<URLLoaderFactoryBundleInfo>(
@@ -4118,6 +4114,52 @@
     GrantFileAccessFromResourceRequestBody(*common_params.post_data);
 }
 
+void RenderFrameHostImpl::OnNetworkServiceConnectionError() {
+  DCHECK(base::FeatureList::IsEnabled(features::kNetworkService));
+  DCHECK(network_service_connection_error_handler_holder_.is_bound() &&
+         network_service_connection_error_handler_holder_.encountered_error());
+  network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
+  CreateNetworkServiceDefaultFactoryAndObserve(
+      mojo::MakeRequest(&default_factory_info));
+
+  std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories =
+      std::make_unique<URLLoaderFactoryBundleInfo>();
+  subresource_loader_factories->default_factory_info() =
+      std::move(default_factory_info);
+  GetNavigationControl()->UpdateSubresourceLoaderFactories(
+      std::move(subresource_loader_factories));
+}
+
+void RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve(
+    network::mojom::URLLoaderFactoryRequest default_factory_request) {
+  StoragePartitionImpl* storage_partition =
+      static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
+          GetSiteInstance()->GetBrowserContext(), GetSiteInstance()));
+  if (g_url_loader_factory_callback_for_test.Get().is_null()) {
+    storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
+        std::move(default_factory_request), GetProcess()->GetID());
+  } else {
+    network::mojom::URLLoaderFactoryPtr original_factory;
+    storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
+        mojo::MakeRequest(&original_factory), GetProcess()->GetID());
+    g_url_loader_factory_callback_for_test.Get().Run(
+        std::move(default_factory_request), GetProcess()->GetID(),
+        original_factory.PassInterface());
+  }
+
+  // Add connection error observer when Network Service is running
+  // out-of-process.
+  if (IsOutOfProcessNetworkService()) {
+    storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
+        mojo::MakeRequest(&network_service_connection_error_handler_holder_),
+        GetProcess()->GetID());
+    network_service_connection_error_handler_holder_
+        .set_connection_error_handler(base::BindOnce(
+            &RenderFrameHostImpl::OnNetworkServiceConnectionError,
+            weak_ptr_factory_.GetWeakPtr()));
+  }
+}
+
 bool RenderFrameHostImpl::CanExecuteJavaScript() {
 #if defined(OS_ANDROID)
   if (g_allow_injecting_javascript)
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index c994d60..8f11766 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -677,6 +677,11 @@
     return active_sandbox_flags_;
   }
 
+  // Call |FlushForTesting()| on Network Service and FrameNavigationControl
+  // related interfaces to make sure all in-flight mojo messages have been
+  // received by the other end. For test use only.
+  void FlushNetworkAndNavigationInterfacesForTesting();
+
  protected:
   friend class RenderFrameHostFactory;
 
@@ -913,6 +918,16 @@
       const CommonNavigationParams& common_params,
       const RequestNavigationParams& request_params);
 
+  // Handle Network Service connection errors. Will re-create broken Network
+  // Service-backed factories and send to |RenderFrame|.
+  void OnNetworkServiceConnectionError();
+
+  // Creates a Network Service-backed factory from appropriate |NetworkContext|
+  // and sets a connection error handler to trigger
+  // |OnNetworkServiceConnectionError()| if the factory is out-of-process.
+  void CreateNetworkServiceDefaultFactoryAndObserve(
+      network::mojom::URLLoaderFactoryRequest default_factory_request);
+
   // Returns true if the ExecuteJavaScript() API can be used on this host.
   bool CanExecuteJavaScript();
 
@@ -1387,6 +1402,12 @@
   std::unique_ptr<KeepAliveHandleFactory> keep_alive_handle_factory_;
   base::TimeDelta keep_alive_timeout_;
 
+  // For observing Network Service connection errors only. Will trigger
+  // |OnNetworkServiceConnectionError()| and push updated factories to
+  // |RenderFrame|.
+  network::mojom::URLLoaderFactoryPtr
+      network_service_connection_error_handler_holder_;
+
   // NOTE: This must be the last member.
   base::WeakPtrFactory<RenderFrameHostImpl> weak_ptr_factory_;
 
diff --git a/content/browser/geolocation/geolocation_service_impl.h b/content/browser/geolocation/geolocation_service_impl.h
index d2ce54fb..65ecc24 100644
--- a/content/browser/geolocation/geolocation_service_impl.h
+++ b/content/browser/geolocation/geolocation_service_impl.h
@@ -6,8 +6,8 @@
 #define CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_IMPL_H_
 
 #include "content/common/content_export.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/device/public/interfaces/geolocation.mojom.h"
 #include "services/device/public/interfaces/geolocation_context.mojom.h"
 #include "third_party/WebKit/public/platform/modules/geolocation/geolocation_service.mojom.h"
 
diff --git a/content/browser/geolocation/geolocation_service_impl_unittest.cc b/content/browser/geolocation/geolocation_service_impl_unittest.cc
index 23e619a..a8894cc3 100644
--- a/content/browser/geolocation/geolocation_service_impl_unittest.cc
+++ b/content/browser/geolocation/geolocation_service_impl_unittest.cc
@@ -13,8 +13,8 @@
 #include "content/test/mock_permission_manager.h"
 #include "content/test/test_render_frame_host.h"
 #include "device/geolocation/geolocation_context.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
+#include "services/device/public/interfaces/geolocation.mojom.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 #include "services/service_manager/public/cpp/bind_source_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/common/feature_policy/feature_policy_feature.h"
diff --git a/content/browser/gpu/DEPS b/content/browser/gpu/DEPS
index 24cf9495..4a508e0 100644
--- a/content/browser/gpu/DEPS
+++ b/content/browser/gpu/DEPS
@@ -7,4 +7,9 @@
   "gpu_process_host\.cc": [
     "+ui/ozone/public",
   ],
+  "in_process_gpu_thread_browsertests\.cc": [
+    # Let's move in_process_gpu_thread* to
+    # content/browser/gpu to avoid this rule.
+    "+content/gpu/in_process_gpu_thread.h"
+  ],
 }
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc
index a7b3ef7..df3efc8 100644
--- a/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -150,7 +150,11 @@
         base::BindOnce(
             &BrowserGpuChannelHostFactory::EstablishRequest::RestartTimeout,
             this));
-    EstablishOnIO();
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        base::BindOnce(
+            &BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO,
+            this));
     return;
   }
 
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index cb33385d..029fc58f0 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -481,6 +481,8 @@
 
 GpuProcessHost::~GpuProcessHost() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (in_process_gpu_thread_)
+    DCHECK(process_);
 
   SendOutstandingReplies(EstablishChannelStatus::GPU_HOST_INVALID);
 
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h
index 5efa679..3b7e23d 100644
--- a/content/browser/gpu/gpu_process_host.h
+++ b/content/browser/gpu/gpu_process_host.h
@@ -268,8 +268,6 @@
   bool swiftshader_rendering_;
   GpuProcessKind kind_;
 
-  std::unique_ptr<base::Thread> in_process_gpu_thread_;
-
   // Whether we actually launched a GPU process.
   bool process_launched_;
 
@@ -289,7 +287,12 @@
   static bool crashed_before_;
   static int swiftshader_crash_count_;
 
+  // Here the bottom-up destruction order matters:
+  // The GPU thread depends on its host so stop the host last.
+  // Otherwise, under rare timings when the thread is still in Init(),
+  // it could crash as it fails to find a message pipe to the host.
   std::unique_ptr<BrowserChildProcessHostImpl> process_;
+  std::unique_ptr<base::Thread> in_process_gpu_thread_;
 
   // Track the URLs of the pages which have live offscreen contexts,
   // assumed to be associated with untrusted content such as WebGL.
diff --git a/content/browser/gpu/in_process_gpu_thread_browsertests.cc b/content/browser/gpu/in_process_gpu_thread_browsertests.cc
new file mode 100644
index 0000000..029288b
--- /dev/null
+++ b/content/browser/gpu/in_process_gpu_thread_browsertests.cc
@@ -0,0 +1,50 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/run_loop.h"
+#include "content/browser/browser_main_loop.h"
+#include "content/browser/gpu/gpu_process_host.h"
+#include "content/gpu/in_process_gpu_thread.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/content_browser_test.h"
+
+namespace {
+
+using content::InProcessGpuThread;
+using content::GpuProcessHost;
+
+class InProcessGpuTest : public content::ContentBrowserTest {
+ public:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(switches::kInProcessGPU);
+    content::ContentBrowserTest::SetUpCommandLine(command_line);
+  }
+};
+
+void CreateGpuProcessHost() {
+  GpuProcessHost::Get();
+}
+
+void WaitUntilGpuProcessHostIsCreated() {
+  base::RunLoop run_loop;
+  content::BrowserThread::PostTaskAndReply(
+      content::BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&CreateGpuProcessHost), run_loop.QuitClosure());
+  run_loop.Run();
+}
+
+// Reproduces the race that could give crbug.com/799002's "hang until OOM" at
+// shutdown.
+IN_PROC_BROWSER_TEST_F(InProcessGpuTest, NoHangAtQuickLaunchAndShutDown) {
+  // ... then exit the browser.
+}
+
+// Tests crbug.com/799002 but with another timing.
+IN_PROC_BROWSER_TEST_F(InProcessGpuTest, NoCrashAtShutdown) {
+  WaitUntilGpuProcessHostIsCreated();
+  // ... then exit the browser.
+}
+
+}  // namespace
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index 1b6059a3..8bea287 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -588,7 +588,7 @@
 void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) {
   // Make sure we have the load state monitors running.
   if (!update_load_states_timer_->IsRunning() &&
-      scheduler_->HasLoadingClients()) {
+      scheduler_->DeprecatedHasLoadingClients()) {
     update_load_states_timer_->Start(
         FROM_HERE, TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec),
         this, &ResourceDispatcherHostImpl::UpdateLoadInfo);
@@ -1533,7 +1533,7 @@
 void ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading(int child_id,
                                                               int route_id,
                                                               bool is_loading) {
-  scheduler_->OnLoadingStateChanged(child_id, route_id, !is_loading);
+  scheduler_->DeprecatedOnLoadingStateChanged(child_id, route_id, !is_loading);
 }
 
 void ResourceDispatcherHostImpl::MarkAsTransferredNavigation(
@@ -2323,7 +2323,7 @@
   // will restart it as necessary.
   // Also stop the timer if there are no loading clients, to avoid waking up
   // unnecessarily when there is a long running (hanging get) request.
-  if (infos->empty() || !scheduler_->HasLoadingClients()) {
+  if (infos->empty() || !scheduler_->DeprecatedHasLoadingClients()) {
     update_load_states_timer_->Stop();
     return;
   }
diff --git a/content/browser/loader/resource_message_filter.cc b/content/browser/loader/resource_message_filter.cc
index db2f3ed5..606dd4d 100644
--- a/content/browser/loader/resource_message_filter.cc
+++ b/content/browser/loader/resource_message_filter.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/loader/resource_message_filter.h"
 
+#include "base/feature_list.h"
 #include "base/logging.h"
 #include "content/browser/appcache/chrome_appcache_service.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
@@ -12,8 +13,10 @@
 #include "content/browser/loader/url_loader_factory_impl.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/common/resource_messages.h"
+#include "content/network/cors/cors_url_loader_factory.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/resource_context.h"
+#include "content/public/common/content_features.h"
 #include "storage/browser/fileapi/file_system_context.h"
 
 namespace content {
@@ -142,6 +145,11 @@
   // WeakPtr of |requester_info_| now.
   requester_info_->set_filter(GetWeakPtr());
   url_loader_factory_ = std::make_unique<URLLoaderFactoryImpl>(requester_info_);
+
+  if (base::FeatureList::IsEnabled(features::kOutOfBlinkCORS)) {
+    url_loader_factory_ =
+        std::make_unique<CORSURLLoaderFactory>(std::move(url_loader_factory_));
+  }
 }
 
 }  // namespace content
diff --git a/content/browser/loader/resource_scheduler_filter.cc b/content/browser/loader/resource_scheduler_filter.cc
index 2aeea74..347fdfb 100644
--- a/content/browser/loader/resource_scheduler_filter.cc
+++ b/content/browser/loader/resource_scheduler_filter.cc
@@ -36,13 +36,13 @@
     int render_view_routing_id) {
   auto* scheduler = GetResourceSchedulerOrNullptr();
   if (scheduler)
-    scheduler->OnNavigate(render_process_id, render_view_routing_id);
+    scheduler->DeprecatedOnNavigate(render_process_id, render_view_routing_id);
 }
 
 void ResourceSchedulerFilter::OnWillInsertBody(int render_view_routing_id) {
   auto* scheduler = GetResourceSchedulerOrNullptr();
   if (scheduler)
-    scheduler->OnWillInsertBody(child_id_, render_view_routing_id);
+    scheduler->DeprecatedOnWillInsertBody(child_id_, render_view_routing_id);
 }
 
 }  // namespace content
diff --git a/content/browser/loader/url_loader_factory_impl.cc b/content/browser/loader/url_loader_factory_impl.cc
index 790b9d4..8a0aecc2 100644
--- a/content/browser/loader/url_loader_factory_impl.cc
+++ b/content/browser/loader/url_loader_factory_impl.cc
@@ -45,7 +45,7 @@
 
 void URLLoaderFactoryImpl::Clone(
     network::mojom::URLLoaderFactoryRequest request) {
-  // The cloned factories stopped working when this factory is destructed.
+  // The cloned factories stop working when this factory is destructed.
   bindings_.AddBinding(this, std::move(request));
 }
 
diff --git a/content/browser/network_service_restart_browsertest.cc b/content/browser/network_service_restart_browsertest.cc
index a3b91fb..60cd70d6 100644
--- a/content/browser/network_service_restart_browsertest.cc
+++ b/content/browser/network_service_restart_browsertest.cc
@@ -4,18 +4,22 @@
 
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/storage_partition_impl.h"
 #include "content/browser/url_loader_factory_getter.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/common/simple_url_loader.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/simple_url_loader_test_helper.h"
 #include "content/shell/browser/shell.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/http_request.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "services/network/public/interfaces/network_service.mojom.h"
 
@@ -75,7 +79,11 @@
  public:
   NetworkServiceRestartBrowserTest() {
     scoped_feature_list_.InitAndEnableFeature(features::kNetworkService);
+  }
+
+  void SetUpOnMainThread() override {
     EXPECT_TRUE(embedded_test_server()->Start());
+    ContentBrowserTest::SetUpOnMainThread();
   }
 
   GURL GetTestURL() const {
@@ -188,4 +196,91 @@
       NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html")));
 }
 
+class NetworkServiceRestartDisableWebSecurityTest
+    : public NetworkServiceRestartBrowserTest {
+ public:
+  NetworkServiceRestartDisableWebSecurityTest() {}
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    // Simulate a compromised renderer, otherwise the cross-origin request is
+    // blocked.
+    command_line->AppendSwitch(switches::kDisableWebSecurity);
+    NetworkServiceRestartBrowserTest::SetUpCommandLine(command_line);
+  }
+
+  void SetUpOnMainThread() override {
+    host_resolver()->AddRule("*", "127.0.0.1");
+    embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
+        &NetworkServiceRestartDisableWebSecurityTest::MonitorRequest,
+        base::Unretained(this)));
+    NetworkServiceRestartBrowserTest::SetUpOnMainThread();
+  }
+
+  RenderFrameHostImpl* main_frame() {
+    return static_cast<RenderFrameHostImpl*>(
+        shell()->web_contents()->GetMainFrame());
+  }
+
+  bool CheckCanLoadHttp(const std::string& relative_url) {
+    GURL test_url = embedded_test_server()->GetURL(relative_url);
+    std::string script(
+        "var xhr = new XMLHttpRequest();"
+        "xhr.open('GET', '");
+    script += test_url.spec() +
+              "', true);"
+              "xhr.onload = function (e) {"
+              "  if (xhr.readyState === 4) {"
+              "    window.domAutomationController.send(xhr.status === 200);"
+              "  }"
+              "};"
+              "xhr.onerror = function () {"
+              "  window.domAutomationController.send(false);"
+              "};"
+              "xhr.send(null)";
+    bool xhr_result = false;
+    // The JS call will fail if disallowed because the process will be killed.
+    bool execute_result =
+        ExecuteScriptAndExtractBool(shell(), script, &xhr_result);
+    return xhr_result && execute_result;
+  }
+
+  // Called by |embedded_test_server()|.
+  void MonitorRequest(const net::test_server::HttpRequest& request) {
+    last_request_relative_url_ = request.relative_url;
+  }
+
+  std::string last_request_relative_url() const {
+    return last_request_relative_url_;
+  }
+
+ private:
+  std::string last_request_relative_url_;
+
+  DISALLOW_COPY_AND_ASSIGN(NetworkServiceRestartDisableWebSecurityTest);
+};
+
+// Make sure basic XHR works after crash.
+IN_PROC_BROWSER_TEST_F(NetworkServiceRestartDisableWebSecurityTest, BasicXHR) {
+  StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+      BrowserContext::GetDefaultStoragePartition(browser_context()));
+
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("foo.com", "/echo")));
+  EXPECT_TRUE(CheckCanLoadHttp("/title1.html"));
+  EXPECT_EQ(last_request_relative_url(), "/title1.html");
+
+  // Crash the NetworkService process. Existing interfaces should receive error
+  // notifications at some point.
+  SimulateNetworkServiceCrash();
+  // Flush the interface to make sure the error notification was received.
+  partition->FlushNetworkInterfaceForTesting();
+  // Flush the interface to make sure the frame host has received error
+  // notification and the new URLLoaderFactoryBundle has been received by the
+  // frame.
+  main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
+
+  EXPECT_TRUE(CheckCanLoadHttp("/title2.html"));
+  EXPECT_EQ(last_request_relative_url(), "/title2.html");
+}
+
 }  // namespace content
diff --git a/content/browser/push_messaging/push_messaging_router.cc b/content/browser/push_messaging/push_messaging_router.cc
index 86b4529..05e3d73 100644
--- a/content/browser/push_messaging/push_messaging_router.cc
+++ b/content/browser/push_messaging/push_messaging_router.cc
@@ -23,10 +23,6 @@
 
 namespace {
 
-// The number of seconds for which the event triggered by a push message should
-// be allowed to run.
-const int kPushMessageTimeoutSeconds = 90;
-
 void RunDeliverCallback(
     const PushMessagingRouter::DeliverMessageCallback& deliver_message_callback,
     mojom::PushDeliveryStatus delivery_status) {
@@ -128,7 +124,7 @@
       ServiceWorkerMetrics::EventType::PUSH,
       base::BindOnce(&PushMessagingRouter::DeliverMessageEnd,
                      deliver_message_callback, service_worker_registration),
-      base::TimeDelta::FromSeconds(kPushMessageTimeoutSeconds),
+      base::TimeDelta::FromSeconds(mojom::kPushEventTimeoutSeconds),
       ServiceWorkerVersion::KILL_ON_TIMEOUT);
 
   service_worker->event_dispatcher()->DispatchPushEvent(
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc
index f95f8c2..01cbd7c0 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -283,6 +283,7 @@
 
   void DispatchSyncEvent(const std::string& tag,
                          bool last_chance,
+                         base::TimeDelta timeout,
                          DispatchSyncEventCallback callback) override {
     NOTIMPLEMENTED();
   }
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index 0e71cd0..383fcf8b 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -289,6 +289,10 @@
 
   // Same as StartRequest, but allows the caller to specify a custom timeout for
   // the event, as well as the behavior for when the request times out.
+  // S13nServiceWorker: |timeout| and |timeout_behavior| don't have any
+  // effect. They are just ignored. Timeouts can be added to the
+  // mojom::ServiceWorkerEventDispatcher interface instead (see
+  // DispatchSyncEvent for an example).
   int StartRequestWithCustomTimeout(ServiceWorkerMetrics::EventType event_type,
                                     StatusCallback error_callback,
                                     const base::TimeDelta& timeout,
diff --git a/content/browser/webrtc/webrtc_media_recorder_browsertest.cc b/content/browser/webrtc/webrtc_media_recorder_browsertest.cc
index 3d815a27..a92e78a 100644
--- a/content/browser/webrtc/webrtc_media_recorder_browsertest.cc
+++ b/content/browser/webrtc/webrtc_media_recorder_browsertest.cc
@@ -80,7 +80,14 @@
                   kMediaRecorderHtmlFile);
 }
 
-IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest, StartWithTimeSlice) {
+// TODO(crbug.com/805341): It seems to be flaky on Android. More details in
+// the bug.
+#if defined(OS_ANDROID)
+#define MAYBE_StartWithTimeSlice DISABLED_StartWithTimeSlice
+#else
+#define MAYBE_StartWithTimeSlice StartWithTimeSlice
+#endif
+IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest, MAYBE_StartWithTimeSlice) {
   MaybeForceDisableEncodeAccelerator(GetParam().disable_accelerator);
   MakeTypicalCall(base::StringPrintf("testStartWithTimeSlice(\"%s\");",
                                      GetParam().mime_type.c_str()),
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index b5b04254..964f02b 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -228,6 +228,9 @@
   WebRuntimeFeatures::EnableUserActivationV2(
       base::FeatureList::IsEnabled(features::kUserActivationV2));
 
+  if (base::FeatureList::IsEnabled(features::kScrollAnchorSerialization))
+    WebRuntimeFeatures::EnableScrollAnchorSerialization(true);
+
   if (command_line.HasSwitch(switches::kEnableSlimmingPaintV175))
     WebRuntimeFeatures::EnableFeatureFromString("SlimmingPaintV175", true);
   if (command_line.HasSwitch(switches::kEnableSlimmingPaintV2))
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index 539864c..dbc4f91 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -102,6 +102,16 @@
       int32 error_code,
       string? error_page_content,
       URLLoaderFactoryBundle? subresource_loader_factories);
+
+  // Provides the renderer an updated |subresource_loader_factories|.
+  //
+  // This method is intended to fix broken loaders after a Network Service
+  // crash, and is only used when Network Service is enabled.
+  //
+  // The new bundle contains replacement factories for a subset of the
+  // receiver's existing bundle.
+  UpdateSubresourceLoaderFactories(
+      URLLoaderFactoryBundle subresource_loader_factories);
 };
 
 // Implemented by the frame (e.g. renderer processes).
diff --git a/content/common/service_worker/service_worker_event_dispatcher.mojom b/content/common/service_worker/service_worker_event_dispatcher.mojom
index 15cacc59..bcc9dc7 100644
--- a/content/common/service_worker/service_worker_event_dispatcher.mojom
+++ b/content/common/service_worker/service_worker_event_dispatcher.mojom
@@ -53,6 +53,12 @@
   blink.mojom.ServiceWorkerObjectInfo? source_info_for_service_worker;
 };
 
+// The number of seconds for which a 'push' event should be allowed to run.
+// This is not in the spec but for Chromium specific internal timeouts. Each
+// event dispatched to service workers has 5 minutes timeout in the Chrome
+// implementation, but this makes the timeout for push events shorter.
+const int32 kPushEventTimeoutSeconds = 90;
+
 // An interface for dispatching events to a ServiceWorker. This interface is
 // implemented by ServiceWorkerContextClient that lives in the renderer-side
 // to dispatch events from the browser-side.
@@ -127,7 +133,12 @@
           mojo.common.mojom.Time dispatch_event_time);
   // Arguments are passed to the event handler as parameters of SyncEvent.
   // Ref: https://wicg.github.io/BackgroundSync/spec/#sync-event
-  DispatchSyncEvent(string id, bool last_chance)
+  // S13nServiceWorker: |timeout| is the amount of time to allow this event to
+  // finish.
+  // Non-S13nServiceWorker: |timeout| is just ignored.
+  DispatchSyncEvent(string id,
+                    bool last_chance,
+                    mojo.common.mojom.TimeDelta timeout)
       => (blink.mojom.ServiceWorkerEventStatus status,
           mojo.common.mojom.Time dispatch_event_time);
   DispatchAbortPaymentEvent(
diff --git a/content/common/service_worker/service_worker_loader_helpers.cc b/content/common/service_worker/service_worker_loader_helpers.cc
index b305bc73..0c89446 100644
--- a/content/common/service_worker/service_worker_loader_helpers.cc
+++ b/content/common/service_worker/service_worker_loader_helpers.cc
@@ -14,6 +14,7 @@
 #include "net/http/http_util.h"
 #include "services/network/public/cpp/loader_util.h"
 #include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/resource_request_body.h"
 #include "services/network/public/cpp/resource_response.h"
 #include "ui/base/page_transition_types.h"
 
@@ -93,6 +94,11 @@
 
   out_head->headers = new net::HttpResponseHeaders(
       net::HttpUtil::AssembleRawHeaders(buf.c_str(), buf.size()));
+
+  // Populate |out_head|'s MIME type with the value from the HTTP response
+  // headers. If there is none, set a default value.
+  // TODO(crbug.com/771118): Make the MIME sniffer work for SW controlled page
+  // loads, so we don't need to set a simple default value.
   if (out_head->mime_type.empty()) {
     std::string mime_type;
     out_head->headers->GetMimeType(&mime_type);
@@ -100,6 +106,14 @@
       mime_type = "text/plain";
     out_head->mime_type = mime_type;
   }
+
+  // Populate |out_head|'s charset with the value from the HTTP response
+  // headers.
+  if (out_head->charset.empty()) {
+    std::string charset;
+    if (out_head->headers->GetCharset(&charset))
+      out_head->charset = charset;
+  }
 }
 
 // static
@@ -174,4 +188,46 @@
   return net::OK;
 }
 
+// static
+scoped_refptr<network::ResourceRequestBody>
+ServiceWorkerLoaderHelpers::CloneResourceRequestBody(
+    const network::ResourceRequestBody* body) {
+  auto clone = base::MakeRefCounted<network::ResourceRequestBody>();
+
+  clone->set_identifier(body->identifier());
+  clone->set_contains_sensitive_info(body->contains_sensitive_info());
+  for (const network::DataElement& element : *body->elements()) {
+    switch (element.type()) {
+      case network::DataElement::TYPE_UNKNOWN:
+        NOTREACHED();
+        break;
+      case network::DataElement::TYPE_DATA_PIPE: {
+        network::mojom::DataPipeGetterPtrInfo clone_ptr_info;
+        element.data_pipe()->Clone(mojo::MakeRequest(&clone_ptr_info));
+        network::mojom::DataPipeGetterPtr clone_ptr(std::move(clone_ptr_info));
+        clone->AppendDataPipe(std::move(clone_ptr));
+        break;
+      }
+      case network::DataElement::TYPE_RAW_FILE:
+        clone->AppendRawFileRange(element.file().Duplicate(), element.path(),
+                                  element.offset(), element.length(),
+                                  element.expected_modification_time());
+        break;
+      case network::DataElement::TYPE_BLOB:
+        NOTREACHED() << "There should be no blob elements in NetworkService";
+        break;
+      case network::DataElement::TYPE_FILE:
+        clone->AppendFileRange(element.path(), element.offset(),
+                               element.length(),
+                               element.expected_modification_time());
+        break;
+      case network::DataElement::TYPE_BYTES:
+        clone->AppendBytes(element.bytes(), element.length());
+        break;
+    }
+  }
+
+  return clone;
+}
+
 }  // namespace content
diff --git a/content/common/service_worker/service_worker_loader_helpers.h b/content/common/service_worker/service_worker_loader_helpers.h
index 05c3caf..7c8ef56c 100644
--- a/content/common/service_worker/service_worker_loader_helpers.h
+++ b/content/common/service_worker/service_worker_loader_helpers.h
@@ -12,6 +12,7 @@
 #include "third_party/WebKit/common/blob/blob.mojom.h"
 
 namespace network {
+class ResourceRequestBody;
 struct ResourceRequest;
 struct ResourceResponseHead;
 }
@@ -51,6 +52,15 @@
       const net::HttpRequestHeaders& headers,
       base::OnceCallback<void(int net_error)> on_blob_read_complete,
       mojo::ScopedDataPipeConsumerHandle* handle_out);
+
+  // Returns a new copy of the given body. This is useful for service worker
+  // with NetworkService because it sends the ResourceRequestBody over Mojo IPC,
+  // which moves out the DataPipeGetter elements in the Pickle code in
+  // resources_messages.cc. We can't change the Pickle code to call
+  // DataPipeGetter's Clone method because that code can run on different thread
+  // than the DataPipeGetter.
+  static scoped_refptr<network::ResourceRequestBody> CloneResourceRequestBody(
+      const network::ResourceRequestBody* body);
 };
 
 }  // namespace content
diff --git a/content/common/service_worker/service_worker_utils.cc b/content/common/service_worker/service_worker_utils.cc
index 71165c8..8de8443 100644
--- a/content/common/service_worker/service_worker_utils.cc
+++ b/content/common/service_worker/service_worker_utils.cc
@@ -142,8 +142,8 @@
 
 // static
 bool ServiceWorkerUtils::IsServicificationEnabled() {
-  return IsBrowserSideNavigationEnabled() &&
-         base::FeatureList::IsEnabled(features::kNetworkService);
+  return base::FeatureList::IsEnabled(features::kNetworkService) ||
+         base::FeatureList::IsEnabled(features::kServiceWorkerServicification);
 }
 
 // static
diff --git a/content/common/url_loader_factory_bundle.cc b/content/common/url_loader_factory_bundle.cc
index 17dd351..22ef73e9 100644
--- a/content/common/url_loader_factory_bundle.cc
+++ b/content/common/url_loader_factory_bundle.cc
@@ -97,4 +97,12 @@
       std::move(default_factory_info), std::move(factories_info));
 }
 
+void URLLoaderFactoryBundle::Update(
+    std::unique_ptr<URLLoaderFactoryBundleInfo> info) {
+  if (info->default_factory_info())
+    default_factory_.Bind(std::move(info->default_factory_info()));
+  for (auto& factory_info : info->factories_info())
+    factories_[factory_info.first].Bind(std::move(factory_info.second));
+}
+
 }  // namespace content
diff --git a/content/common/url_loader_factory_bundle.h b/content/common/url_loader_factory_bundle.h
index 5a6c4a9..25fd23c 100644
--- a/content/common/url_loader_factory_bundle.h
+++ b/content/common/url_loader_factory_bundle.h
@@ -84,6 +84,10 @@
 
   std::unique_ptr<SharedURLLoaderFactoryInfo> Clone() override;
 
+  // The |info| contains replacement factories for a subset of the existing
+  // bundle.
+  void Update(std::unique_ptr<URLLoaderFactoryBundleInfo> info);
+
  private:
   ~URLLoaderFactoryBundle() override;
 
diff --git a/content/network/BUILD.gn b/content/network/BUILD.gn
index c1d8798..fb16240b4 100644
--- a/content/network/BUILD.gn
+++ b/content/network/BUILD.gn
@@ -36,6 +36,10 @@
   sources = [
     "cache_url_loader.cc",
     "cache_url_loader.h",
+    "cors/cors_url_loader.cc",
+    "cors/cors_url_loader.h",
+    "cors/cors_url_loader_factory.cc",
+    "cors/cors_url_loader_factory.h",
     "data_pipe_element_reader.cc",
     "data_pipe_element_reader.h",
     "http_server_properties_pref_delegate.cc",
diff --git a/content/network/DEPS b/content/network/DEPS
index fa48b11..6b87bac 100644
--- a/content/network/DEPS
+++ b/content/network/DEPS
@@ -9,9 +9,13 @@
   "-content",
   "+content/common/content_export.h",
   "+content/network",
-  "+content/public/network",
   # TODO(yhirano): Remove this dependency.
   "+content/public/common/content_features.h",
+  "+content/public/common/origin_util.h",
+  "+content/public/common/request_context_type.h",
+  "+content/public/common/resource_type.h",
+  "+content/public/common/service_worker_modes.h",
+  "+content/public/network",
   "+services/network",
   "+services/service_manager/public",
   "+services/service_manager/sandbox",
diff --git a/content/renderer/loader/cors_url_loader.cc b/content/network/cors/cors_url_loader.cc
similarity index 98%
rename from content/renderer/loader/cors_url_loader.cc
rename to content/network/cors/cors_url_loader.cc
index 10dcfed..cdb399c6 100644
--- a/content/renderer/loader/cors_url_loader.cc
+++ b/content/network/cors/cors_url_loader.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/renderer/loader/cors_url_loader.h"
+#include "content/network/cors/cors_url_loader.h"
 
 #include "content/public/common/origin_util.h"
 #include "content/public/common/resource_type.h"
diff --git a/content/renderer/loader/cors_url_loader.h b/content/network/cors/cors_url_loader.h
similarity index 95%
rename from content/renderer/loader/cors_url_loader.h
rename to content/network/cors/cors_url_loader.h
index 7eb94d4..54d7e399 100644
--- a/content/renderer/loader/cors_url_loader.h
+++ b/content/network/cors/cors_url_loader.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_RENDERER_LOADER_CORS_URL_LOADER_H_
-#define CONTENT_RENDERER_LOADER_CORS_URL_LOADER_H_
+#ifndef CONTENT_NETWORK_CORS_CORS_URL_LOADER_H_
+#define CONTENT_NETWORK_CORS_CORS_URL_LOADER_H_
 
 #include "content/common/content_export.h"
 #include "mojo/public/cpp/bindings/binding.h"
@@ -100,4 +100,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_RENDERER_LOADER_CORS_URL_LOADER_H_
+#endif  // CONTENT_NETWORK_CORS_CORS_URL_LOADER_H_
diff --git a/content/network/cors/cors_url_loader_factory.cc b/content/network/cors/cors_url_loader_factory.cc
new file mode 100644
index 0000000..37f20d8
--- /dev/null
+++ b/content/network/cors/cors_url_loader_factory.cc
@@ -0,0 +1,46 @@
+// Copyright 2018 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/network/cors/cors_url_loader_factory.h"
+
+#include "content/network/cors/cors_url_loader.h"
+#include "content/public/common/content_features.h"
+
+namespace content {
+
+CORSURLLoaderFactory::CORSURLLoaderFactory(
+    std::unique_ptr<network::mojom::URLLoaderFactory> network_loader_factory)
+    : network_loader_factory_(std::move(network_loader_factory)) {}
+
+CORSURLLoaderFactory::~CORSURLLoaderFactory() = default;
+
+void CORSURLLoaderFactory::CreateLoaderAndStart(
+    network::mojom::URLLoaderRequest request,
+    int32_t routing_id,
+    int32_t request_id,
+    uint32_t options,
+    const network::ResourceRequest& resource_request,
+    network::mojom::URLLoaderClientPtr client,
+    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
+  if (base::FeatureList::IsEnabled(features::kOutOfBlinkCORS)) {
+    loader_bindings_.AddBinding(
+        std::make_unique<CORSURLLoader>(routing_id, request_id, options,
+                                        resource_request, std::move(client),
+                                        traffic_annotation,
+                                        network_loader_factory_.get()),
+        std::move(request));
+  } else {
+    network_loader_factory_->CreateLoaderAndStart(
+        std::move(request), routing_id, request_id, options, resource_request,
+        std::move(client), traffic_annotation);
+  }
+}
+
+void CORSURLLoaderFactory::Clone(
+    network::mojom::URLLoaderFactoryRequest request) {
+  // The cloned factories stop working when this factory is destructed.
+  bindings_.AddBinding(this, std::move(request));
+}
+
+}  // namespace content
diff --git a/content/network/cors/cors_url_loader_factory.h b/content/network/cors/cors_url_loader_factory.h
new file mode 100644
index 0000000..96bae73
--- /dev/null
+++ b/content/network/cors/cors_url_loader_factory.h
@@ -0,0 +1,57 @@
+// Copyright 2018 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_NETWORK_CORS_CORS_URL_LOADER_FACTORY_H_
+#define CONTENT_NETWORK_CORS_CORS_URL_LOADER_FACTORY_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/strong_binding_set.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/interfaces/url_loader_factory.mojom.h"
+
+namespace network {
+struct ResourceRequest;
+}  // namespace network
+
+namespace content {
+
+// A factory class to create a URLLoader that supports CORS.
+// This class takes a network::mojom::URLLoaderFactory instance in the
+// constructor and owns it to make network requests for CORS preflight, and
+// actual network request.
+class CONTENT_EXPORT CORSURLLoaderFactory final
+    : public network::mojom::URLLoaderFactory {
+ public:
+  explicit CORSURLLoaderFactory(
+      std::unique_ptr<network::mojom::URLLoaderFactory> network_loader_factory);
+  ~CORSURLLoaderFactory() override;
+
+ private:
+  // Implements mojom::URLLoaderFactory.
+  void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
+                            int32_t routing_id,
+                            int32_t request_id,
+                            uint32_t options,
+                            const network::ResourceRequest& resource_request,
+                            network::mojom::URLLoaderClientPtr client,
+                            const net::MutableNetworkTrafficAnnotationTag&
+                                traffic_annotation) override;
+  void Clone(network::mojom::URLLoaderFactoryRequest request) override;
+
+  mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
+
+  std::unique_ptr<network::mojom::URLLoaderFactory> network_loader_factory_;
+
+  // The factory owns the CORSURLLoader it creates.
+  mojo::StrongBindingSet<network::mojom::URLLoader> loader_bindings_;
+
+  DISALLOW_COPY_AND_ASSIGN(CORSURLLoaderFactory);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_NETWORK_CORS_CORS_URL_LOADER_FACTORY_H_
diff --git a/content/renderer/loader/cors_url_loader_unittest.cc b/content/network/cors/cors_url_loader_unittest.cc
similarity index 82%
rename from content/renderer/loader/cors_url_loader_unittest.cc
rename to content/network/cors/cors_url_loader_unittest.cc
index 8b54ee8..f8477b5 100644
--- a/content/renderer/loader/cors_url_loader_unittest.cc
+++ b/content/network/cors/cors_url_loader_unittest.cc
@@ -2,16 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/renderer/loader/cors_url_loader.h"
+#include "content/network/cors/cors_url_loader.h"
 
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/network/cors/cors_url_loader_factory.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/request_context_type.h"
 #include "content/public/common/resource_type.h"
 #include "content/public/test/test_url_loader_client.h"
-#include "content/renderer/loader/cors_url_loader_factory.h"
 #include "net/http/http_request_headers.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "services/network/public/interfaces/url_loader.mojom.h"
@@ -25,9 +28,13 @@
 
 class TestURLLoaderFactory : public network::mojom::URLLoaderFactory {
  public:
-  TestURLLoaderFactory() = default;
+  TestURLLoaderFactory() : weak_factory_(this) {}
   ~TestURLLoaderFactory() override = default;
 
+  base::WeakPtr<TestURLLoaderFactory> GetWeakPtr() {
+    return weak_factory_.GetWeakPtr();
+  }
+
   void NotifyClientOnReceiveResponse(const std::string& extra_header) {
     DCHECK(client_ptr_);
     network::ResourceResponseHead response;
@@ -68,25 +75,30 @@
 
   network::mojom::URLLoaderClientPtr client_ptr_;
 
+  base::WeakPtrFactory<TestURLLoaderFactory> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(TestURLLoaderFactory);
 };
 
 class CORSURLLoaderTest : public testing::Test {
  public:
-  CORSURLLoaderTest()
-      : test_network_factory_binding_(&test_network_loader_factory_) {}
+  CORSURLLoaderTest() {
+    std::unique_ptr<TestURLLoaderFactory> factory =
+        std::make_unique<TestURLLoaderFactory>();
+    test_url_loader_factory_ = factory->GetWeakPtr();
+    cors_url_loader_factory_ =
+        std::make_unique<CORSURLLoaderFactory>(std::move(factory));
+  }
 
  protected:
+  // testing::Test implementation.
+  void SetUp() override {
+    feature_list_.InitAndEnableFeature(features::kOutOfBlinkCORS);
+  }
+
   void CreateLoaderAndStart(const GURL& origin,
                             const GURL& url,
                             FetchRequestMode fetch_request_mode) {
-    network::mojom::URLLoaderFactoryPtr network_factory_ptr;
-    test_network_factory_binding_.Bind(mojo::MakeRequest(&network_factory_ptr));
-
-    network::mojom::URLLoaderFactoryPtr loader_factory_ptr;
-    CORSURLLoaderFactory::CreateAndBind(network_factory_ptr.PassInterface(),
-                                        mojo::MakeRequest(&loader_factory_ptr));
-
     network::ResourceRequest request;
     request.resource_type = RESOURCE_TYPE_IMAGE;
     request.fetch_request_context_type = REQUEST_CONTEXT_TYPE_IMAGE;
@@ -95,28 +107,27 @@
     request.url = url;
     request.request_initiator = url::Origin::Create(origin);
 
-    loader_factory_ptr->CreateLoaderAndStart(
+    cors_url_loader_factory_->CreateLoaderAndStart(
         mojo::MakeRequest(&url_loader_), 0 /* routing_id */, 0 /* request_id */,
         network::mojom::kURLLoadOptionNone, request,
         test_cors_loader_client_.CreateInterfacePtr(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
-
-    // Flushes to ensure that the request is handled and
-    // TestURLLoaderFactory::CreateLoaderAndStart() runs internally.
-    loader_factory_ptr.FlushForTesting();
   }
 
   bool IsNetworkLoaderStarted() {
-    return test_network_loader_factory_.IsCreateLoaderAndStartCalled();
+    DCHECK(test_url_loader_factory_);
+    return test_url_loader_factory_->IsCreateLoaderAndStartCalled();
   }
 
   void NotifyLoaderClientOnReceiveResponse(
       const std::string& extra_header = std::string()) {
-    test_network_loader_factory_.NotifyClientOnReceiveResponse(extra_header);
+    DCHECK(test_url_loader_factory_);
+    test_url_loader_factory_->NotifyClientOnReceiveResponse(extra_header);
   }
 
   void NotifyLoaderClientOnComplete(int error_code) {
-    test_network_loader_factory_.NotifyClientOnComplete(error_code);
+    DCHECK(test_url_loader_factory_);
+    test_url_loader_factory_->NotifyClientOnComplete(error_code);
   }
 
   const TestURLLoaderClient& client() const { return test_cors_loader_client_; }
@@ -127,9 +138,14 @@
   // Be the first member so it is destroyed last.
   base::MessageLoop message_loop_;
 
-  // TestURLLoaderFactory instance and mojo binding.
-  TestURLLoaderFactory test_network_loader_factory_;
-  mojo::Binding<network::mojom::URLLoaderFactory> test_network_factory_binding_;
+  // Testing instance to enable kOutOfBlinkCORS feature.
+  base::test::ScopedFeatureList feature_list_;
+
+  // CORSURLLoaderFactory instance under tests.
+  std::unique_ptr<network::mojom::URLLoaderFactory> cors_url_loader_factory_;
+
+  // TestURLLoaderFactory instance owned by CORSURLLoaderFactory.
+  base::WeakPtr<TestURLLoaderFactory> test_url_loader_factory_;
 
   // Holds URLLoaderPtr that CreateLoaderAndStart() creates.
   network::mojom::URLLoaderPtr url_loader_;
@@ -176,8 +192,7 @@
 TEST_F(CORSURLLoaderTest, CrossOriginRequestFetchRequestModeSameOrigin) {
   const GURL origin("http://example.com");
   const GURL url("http://other.com/foo.png");
-  CreateLoaderAndStart(origin, url,
-                       network::mojom::FetchRequestMode::kSameOrigin);
+  CreateLoaderAndStart(origin, url, FetchRequestMode::kSameOrigin);
 
   RunUntilComplete();
 
diff --git a/content/network/resource_scheduler.cc b/content/network/resource_scheduler.cc
index ac5ce281..46c6aa24 100644
--- a/content/network/resource_scheduler.cc
+++ b/content/network/resource_scheduler.cc
@@ -398,8 +398,8 @@
  public:
   Client(const net::NetworkQualityEstimator* const network_quality_estimator,
          ResourceScheduler* resource_scheduler)
-      : is_loaded_(false),
-        has_html_body_(false),
+      : deprecated_is_loaded_(false),
+        deprecated_has_html_body_(false),
         using_spdy_proxy_(false),
         in_flight_delayable_count_(0),
         total_layout_blocking_count_(0),
@@ -418,7 +418,7 @@
       // When kRendererSideResourceScheduler is enabled, "layout blocking"
       // concept is moved to the renderer side, so the shceduler works always
       // with the normal mode.
-      has_html_body_ = true;
+      deprecated_has_html_body_ = true;
     }
   }
 
@@ -447,8 +447,8 @@
 
       // Removing this request may have freed up another to load.
       LoadAnyStartablePendingRequests(
-          has_html_body_ ? RequestStartTrigger::COMPLETION_POST_BODY
-                         : RequestStartTrigger::COMPLETION_PRE_BODY);
+          deprecated_has_html_body_ ? RequestStartTrigger::COMPLETION_POST_BODY
+                                    : RequestStartTrigger::COMPLETION_PRE_BODY);
     }
   }
 
@@ -477,33 +477,35 @@
     return unowned_requests;
   }
 
-  bool is_loaded() const { return is_loaded_; }
+  bool deprecated_is_loaded() const { return deprecated_is_loaded_; }
 
-  void OnLoadingStateChanged(bool is_loaded) { is_loaded_ = is_loaded; }
+  void DeprecatedOnLoadingStateChanged(bool is_loaded) {
+    deprecated_is_loaded_ = is_loaded;
+  }
 
-  void OnNavigate() {
-    has_html_body_ = false;
+  void DeprecatedOnNavigate() {
+    deprecated_has_html_body_ = false;
     if (base::FeatureList::IsEnabled(
             features::kRendererSideResourceScheduler)) {
       // When kRendererSideResourceScheduler is enabled, "layout blocking"
       // concept is moved to the renderer side, so the shceduler works always
       // with the normal mode.
-      has_html_body_ = true;
+      deprecated_has_html_body_ = true;
     }
 
-    is_loaded_ = false;
+    deprecated_is_loaded_ = false;
     max_delayable_requests_ =
         resource_scheduler_->throttle_delayable_
             .GetParamsForNetworkQuality(network_quality_estimator_)
             .max_delayable_requests;
   }
 
-  void OnWillInsertBody() {
+  void DeprecatedOnWillInsertBody() {
     // Can be called multiple times per RVH in the case of out-of-process
     // iframes.
-    if (has_html_body_)
+    if (deprecated_has_html_body_)
       return;
-    has_html_body_ = true;
+    deprecated_has_html_body_ = true;
     LoadAnyStartablePendingRequests(RequestStartTrigger::BODY_REACHED);
   }
 
@@ -668,8 +670,9 @@
       // If a request is already marked as layout-blocking make sure to keep the
       // attribute across redirects.
       attributes |= kAttributeLayoutBlocking;
-    } else if (!has_html_body_ && request->url_request()->priority() >
-                                      kLayoutBlockingPriorityThreshold) {
+    } else if (!deprecated_has_html_body_ &&
+               request->url_request()->priority() >
+                   kLayoutBlockingPriorityThreshold) {
       // Requests that are above the non_delayable threshold before the HTML
       // body has been parsed are inferred to be layout-blocking.
       attributes |= kAttributeLayoutBlocking;
@@ -677,7 +680,7 @@
                kDelayablePriorityThreshold) {
       if (resource_scheduler_->priority_requests_delayable() ||
           (resource_scheduler_->head_priority_requests_delayable() &&
-           !has_html_body_)) {
+           !deprecated_has_html_body_)) {
         // Resources below the delayable priority threshold that are considered
         // delayable.
         attributes |= kAttributeDelayable;
@@ -801,7 +804,7 @@
     bool priority_delayable =
         resource_scheduler_->priority_requests_delayable() ||
         (resource_scheduler_->head_priority_requests_delayable() &&
-         !has_html_body_);
+         !deprecated_has_html_body_);
 
     if (!priority_delayable) {
       if (using_spdy_proxy_ && url_request.url().SchemeIs(url::kHttpScheme))
@@ -845,7 +848,7 @@
     // delayable requests is handled above here so this is deciding what to
     // do with a delayable request while we are in the layout-blocking phase
     // of loading.
-    if (!has_html_body_ || total_layout_blocking_count_ != 0) {
+    if (!deprecated_has_html_body_ || total_layout_blocking_count_ != 0) {
       size_t non_delayable_requests_in_flight_count =
           in_flight_requests_.size() - in_flight_delayable_count_;
       if (non_delayable_requests_in_flight_count >
@@ -960,12 +963,12 @@
     }
   }
 
-  bool is_loaded_;
+  bool deprecated_is_loaded_;
   // Tracks if the main HTML parser has reached the body which marks the end of
   // layout-blocking resources.
   // This is disabled and the is always true when kRendererSideResourceScheduler
   // is enabled.
-  bool has_html_body_;
+  bool deprecated_has_html_body_;
   bool using_spdy_proxy_;
   RequestQueue pending_requests_;
   RequestSet in_flight_requests_;
@@ -1105,15 +1108,15 @@
   client_map_.erase(it);
 }
 
-void ResourceScheduler::OnLoadingStateChanged(int child_id,
-                                              int route_id,
-                                              bool is_loaded) {
+void ResourceScheduler::DeprecatedOnLoadingStateChanged(int child_id,
+                                                        int route_id,
+                                                        bool is_loaded) {
   Client* client = GetClient(child_id, route_id);
   DCHECK(client);
-  client->OnLoadingStateChanged(is_loaded);
+  client->DeprecatedOnLoadingStateChanged(is_loaded);
 }
 
-void ResourceScheduler::OnNavigate(int child_id, int route_id) {
+void ResourceScheduler::DeprecatedOnNavigate(int child_id, int route_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   ClientId client_id = MakeClientId(child_id, route_id);
 
@@ -1124,10 +1127,10 @@
   }
 
   Client* client = it->second;
-  client->OnNavigate();
+  client->DeprecatedOnNavigate();
 }
 
-void ResourceScheduler::OnWillInsertBody(int child_id, int route_id) {
+void ResourceScheduler::DeprecatedOnWillInsertBody(int child_id, int route_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   ClientId client_id = MakeClientId(child_id, route_id);
 
@@ -1138,7 +1141,7 @@
   }
 
   Client* client = it->second;
-  client->OnWillInsertBody();
+  client->DeprecatedOnWillInsertBody();
 }
 
 void ResourceScheduler::OnReceivedSpdyProxiedHttpResponse(int child_id,
@@ -1155,9 +1158,9 @@
   client->OnReceivedSpdyProxiedHttpResponse();
 }
 
-bool ResourceScheduler::HasLoadingClients() const {
+bool ResourceScheduler::DeprecatedHasLoadingClients() const {
   for (const auto& client : client_map_) {
-    if (!client.second->is_loaded())
+    if (!client.second->deprecated_is_loaded())
       return true;
   }
   return false;
diff --git a/content/network/resource_scheduler.h b/content/network/resource_scheduler.h
index 296e54f68..bb09c922 100644
--- a/content/network/resource_scheduler.h
+++ b/content/network/resource_scheduler.h
@@ -123,16 +123,21 @@
   void OnClientDeleted(int child_id, int route_id);
 
   // Called when a renderer stops or restarts loading.
-  void OnLoadingStateChanged(int child_id, int route_id, bool is_loaded);
+  // Do not call this function when the network service is enabled.
+  void DeprecatedOnLoadingStateChanged(int child_id,
+                                       int route_id,
+                                       bool is_loaded);
 
   // Signals from IPC messages directly from the renderers:
 
   // Called when a client navigates to a new main document.
-  void OnNavigate(int child_id, int route_id);
+  // Do not call this function when the network service is enabled.
+  void DeprecatedOnNavigate(int child_id, int route_id);
 
   // Called when the client has parsed the <body> element. This is a signal that
   // resource loads won't interfere with first paint.
-  void OnWillInsertBody(int child_id, int route_id);
+  // Do not call this function when the network service is enabled.
+  void DeprecatedOnWillInsertBody(int child_id, int route_id);
 
   // Signals from the IO thread:
 
@@ -143,7 +148,8 @@
   // Client functions:
 
   // Returns true if at least one client is currently loading.
-  bool HasLoadingClients() const;
+  // Do not call this function when the network service is enabled.
+  bool DeprecatedHasLoadingClients() const;
 
   // Updates the priority for |request|. Modifies request->priority(), and may
   // start the request loading if it wasn't already started.
diff --git a/content/network/resource_scheduler_unittest.cc b/content/network/resource_scheduler_unittest.cc
index 081d0f6..57ad782 100644
--- a/content/network/resource_scheduler_unittest.cc
+++ b/content/network/resource_scheduler_unittest.cc
@@ -295,7 +295,7 @@
     // override taking effect with the experiment enabled. For this case, the
     // new limit is 2. The limit will matter only once the page has a body,
     // since delayable requests are not loaded before that.
-    scheduler()->OnWillInsertBody(kChildId, kRouteId);
+    scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
 
     // Throw in one high priority request to ensure that it does not matter once
     // a body exists.
@@ -476,7 +476,7 @@
 
     InitializeScheduler();
     // Limit will only trigger after the page has a body.
-    scheduler()->OnWillInsertBody(kChildId, kRouteId);
+    scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
     // Start one non-delayable request.
     std::unique_ptr<TestRequest> non_delayable_request(
         NewRequest("http://host/medium", net::MEDIUM));
@@ -526,7 +526,7 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(low2->started());
 
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(low2->started());
 }
@@ -540,7 +540,7 @@
   EXPECT_TRUE(low->started());
   EXPECT_FALSE(low2->started());
 
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(low2->started());
 
@@ -563,7 +563,7 @@
   EXPECT_TRUE(lowest->started());
   EXPECT_FALSE(lowest2->started());
 
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(lowest2->started());
 }
@@ -769,7 +769,7 @@
   EXPECT_FALSE(low2->started());
   EXPECT_TRUE(low_spdy->started());
 
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   high.reset();
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(low2->started());
@@ -795,7 +795,7 @@
   EXPECT_FALSE(low2->started());
   EXPECT_FALSE(low_spdy->started());
 
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   high.reset();
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(low2->started());
@@ -832,7 +832,7 @@
       url::SchemeHostPort("https", "spdyhost", 443), true);
 
   // Body has been reached.
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
 
   // Add more than max-per-host low-priority requests.
   std::vector<std::unique_ptr<TestRequest>> requests;
@@ -859,7 +859,7 @@
       url::SchemeHostPort("https", "spdyhost", 443), true);
 
   // Body has been reached.
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
 
   // Add more than max-per-host low-priority requests.
   std::vector<std::unique_ptr<TestRequest>> requests;
@@ -895,7 +895,7 @@
   }
 
   // Body has been reached.
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   base::RunLoop().RunUntilIdle();
 
   // No throttling.
@@ -911,7 +911,7 @@
   InitializeScheduler();
 
   // Body has been reached.
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
 
   // Add more than max-per-host low-priority requests.
   std::vector<std::unique_ptr<TestRequest>> requests;
@@ -936,7 +936,7 @@
   InitializeScheduler();
 
   // Body has been reached.
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
 
   // Add more than max-per-host low-priority requests.
   std::vector<std::unique_ptr<TestRequest>> requests;
@@ -965,7 +965,7 @@
   InitializeScheduler();
 
   // Body has been reached.
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
 
   // Add more than max-per-host low-priority requests.
   std::vector<std::unique_ptr<TestRequest>> requests;
@@ -1007,7 +1007,7 @@
   }
 
   // Body has been reached.
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   base::RunLoop().RunUntilIdle();
 
   // No throttling.
@@ -1027,7 +1027,7 @@
   EXPECT_TRUE(low_spdy->started());
   EXPECT_FALSE(low->started());
 
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   high.reset();
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(low->started());
@@ -1035,8 +1035,8 @@
 
 TEST_F(ResourceSchedulerTest, NavigationResetsState) {
   base::HistogramTester histogram_tester;
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
-  scheduler()->OnNavigate(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnNavigate(kChildId, kRouteId);
 
   {
     std::unique_ptr<TestRequest> high(
@@ -1120,7 +1120,7 @@
   EXPECT_TRUE(high->started());
   EXPECT_FALSE(low2->started());
 
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   high.reset();
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(low1->started());
@@ -1135,7 +1135,7 @@
   scoped_feature_list.InitFromCommandLine("", kNetworkSchedulerYielding);
 
   // We only load low priority resources if there's a body.
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
 
   // Throw in one high priority request to make sure that's not a factor.
   std::unique_ptr<TestRequest> high(
@@ -1226,7 +1226,7 @@
     lows.push_back(NewRequest(url.c_str(), net::LOWEST));
   }
 
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   high.reset();
   base::RunLoop().RunUntilIdle();
 
@@ -1262,7 +1262,7 @@
     lows.push_back(NewRequest(url.c_str(), net::LOWEST));
   }
 
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   high.reset();
   base::RunLoop().RunUntilIdle();
 
@@ -1300,7 +1300,7 @@
   EXPECT_FALSE(request->started());
   EXPECT_FALSE(idle->started());
 
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(request->started());
   EXPECT_FALSE(idle->started());
@@ -1328,7 +1328,7 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(request->started());
 
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   high.reset();
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(request->started());
@@ -1397,7 +1397,7 @@
                                           kPrioritySupportedRequestsDelayable);
   InitializeScheduler();
 
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   const int kDefaultMaxNumDelayableRequestsPerClient =
       10;  // Should match the .cc.
 
@@ -1437,7 +1437,7 @@
                                           "");
   InitializeScheduler();
 
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   const int kDefaultMaxNumDelayableRequestsPerClient =
       10;  // Should match the .cc.
 
@@ -1546,8 +1546,8 @@
 
     // The limit will matter only once the page has a body, since delayable
     // requests are not loaded before that.
-    scheduler()->OnNavigate(kChildId, kRouteId);
-    scheduler()->OnWillInsertBody(kChildId, kRouteId);
+    scheduler()->DeprecatedOnNavigate(kChildId, kRouteId);
+    scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
 
     // Throw in one high priority request to ensure that it does not matter once
     // a body exists.
@@ -1589,8 +1589,8 @@
 
   // The limit will matter only once the page has a body, since delayable
   // requests are not loaded before that.
-  scheduler()->OnNavigate(kChildId, kRouteId);
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnNavigate(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
 
   // Throw in one high priority request to ensure that it does not matter once
   // a body exists.
@@ -1634,15 +1634,15 @@
   EXPECT_FALSE(last_singlehost->started());
 
   // The limit should change when there is a new page navigation.
-  scheduler()->OnNavigate(kChildId, kRouteId);
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnNavigate(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(last_singlehost->started());
 }
 
 // Test that when the network quality changes such that the new limit is lower,
-// and an |OnNavigate| event occurs, the new delayable requests don't start
-// until the number of requests in flight have gone below the new limit.
+// and an |DeprecatedOnNavigate| event occurs, the new delayable requests don't
+// start until the number of requests in flight have gone below the new limit.
 TEST_F(ResourceSchedulerTest, RequestLimitReducedAcrossPageLoads) {
   base::test::ScopedFeatureList scoped_feature_list;
   InitializeThrottleDelayableExperiment(&scoped_feature_list, true, 0.0);
@@ -1653,8 +1653,8 @@
 
   // The limit will matter only once the page has a body, since delayable
   // requests are not loaded before that.
-  scheduler()->OnNavigate(kChildId, kRouteId);
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnNavigate(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
 
   // Throw in one high priority request to ensure that it does not matter once
   // a body exists.
@@ -1682,8 +1682,8 @@
       net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
   // Trigger a navigation event which will recompute limits. Also insert a body,
   // because the limit matters only after the body exists.
-  scheduler()->OnNavigate(kChildId, kRouteId);
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnNavigate(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
 
   // Ensure that high priority requests still start.
   std::unique_ptr<TestRequest> high2(
@@ -1819,8 +1819,8 @@
   // Limit will only trigger after the page has a body.
 
   InitializeScheduler();
-  scheduler()->OnNavigate(kChildId, kRouteId);
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnNavigate(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   // Insert one non-delayable request. This should not affect the number of
   // delayable requests started.
   std::unique_ptr<TestRequest> medium(
@@ -1852,8 +1852,8 @@
 
   InitializeScheduler();
   // Limit will only trigger after the page has a body.
-  scheduler()->OnNavigate(kChildId, kRouteId);
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnNavigate(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   for (int num_non_delayable = 0; num_non_delayable < 10; ++num_non_delayable) {
     base::RunLoop().RunUntilIdle();
     // Start the non-delayable requests.
@@ -1905,7 +1905,7 @@
 TEST_F(ResourceSchedulerTest, NumDelayableAtStartOfNonDelayableUMA) {
   std::unique_ptr<base::HistogramTester> histogram_tester(
       new base::HistogramTester);
-  scheduler()->OnWillInsertBody(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
   // Check that 0 is recorded when a non-delayable request starts and there are
   // no delayable requests in-flight.
   std::unique_ptr<TestRequest> high(
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index a90bc89e..04b78496 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -149,7 +149,6 @@
     "java/src/org/chromium/content/browser/SyntheticGestureTarget.java",
     "java/src/org/chromium/content/browser/TracingControllerAndroid.java",
     "java/src/org/chromium/content/browser/ViewPositionObserver.java",
-    "java/src/org/chromium/content/browser/WindowAndroidProvider.java",
     "java/src/org/chromium/content/browser/WindowAndroidChangedObserver.java",
     "java/src/org/chromium/content/browser/WindowEventObserver.java",
     "java/src/org/chromium/content/browser/accessibility/KitKatWebContentsAccessibility.java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
index 5823285..0a0dfa1 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -103,18 +103,6 @@
     WindowAndroid getWindowAndroid();
 
     /**
-     * Add {@link WindowAndroidChangeObserver} object.
-     * @param observer Observer instance to add.
-     */
-    void addWindowAndroidChangedObserver(WindowAndroidChangedObserver observer);
-
-    /**
-     * Remove {@link WindowAndroidChangeObserver} object.
-     * @param observer Observer instance to remove.
-     */
-    void removeWindowAndroidChangedObserver(WindowAndroidChangedObserver observer);
-
-    /**
      * Initialize {@link ContentViewCore} object.
      * @param viewDelegate Delegate to add/remove anchor views.
      * @param internalDispatcher Handles dispatching all hidden or super methods to the
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
index 033a4ed0..6d1434c 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
@@ -64,9 +64,9 @@
  * Implementation of the interface {@ContentViewCore}.
  */
 @JNINamespace("content")
-public class ContentViewCoreImpl implements ContentViewCore, DisplayAndroidObserver,
-                                            SystemCaptioningBridge.SystemCaptioningBridgeListener,
-                                            WindowAndroidProvider, ImeEventObserver {
+public class ContentViewCoreImpl
+        implements ContentViewCore, DisplayAndroidObserver,
+                   SystemCaptioningBridge.SystemCaptioningBridgeListener, ImeEventObserver {
     private static final String TAG = "cr_ContentViewCore";
 
     /**
@@ -222,7 +222,7 @@
      * @return            A {@link ContentViewCore} that is connected to {@code webContents} or
      *                    {@code null} if none exists.
      */
-    public static ContentViewCore fromWebContents(WebContents webContents) {
+    public static ContentViewCoreImpl fromWebContents(WebContents webContents) {
         return nativeFromWebContentsAndroid(webContents);
     }
 
@@ -278,12 +278,18 @@
         mTextSuggestionHost = textSuggestionHost;
     }
 
-    @Override
+    /**
+     * Add {@link WindowAndroidChangeObserver} object.
+     * @param observer Observer instance to add.
+     */
     public void addWindowAndroidChangedObserver(WindowAndroidChangedObserver observer) {
         mWindowAndroidChangedObservers.addObserver(observer);
     }
 
-    @Override
+    /**
+     * Remove {@link WindowAndroidChangeObserver} object.
+     * @param observer Observer instance to remove.
+     */
     public void removeWindowAndroidChangedObserver(WindowAndroidChangedObserver observer) {
         mWindowAndroidChangedObservers.removeObserver(observer);
     }
@@ -323,7 +329,9 @@
         ImeAdapterImpl imeAdapter = ImeAdapterImpl.create(
                 mWebContents, mContainerView, new InputMethodManagerWrapper(mContext));
         imeAdapter.addEventObserver(this);
-        mTextSuggestionHost = new TextSuggestionHost(this);
+        mTextSuggestionHost =
+                new TextSuggestionHost(mContext, mWebContents, windowAndroid, mContainerView);
+        addWindowAndroidChangedObserver(mTextSuggestionHost);
 
         mWebContentsObserver = new ContentViewWebContentsObserver(this);
 
@@ -386,6 +394,7 @@
                 hideSelectPopupWithCancelMessage();
                 mPopupZoomer.hide(false);
                 getImeAdapter().setContainerView(containerView);
+                mTextSuggestionHost.setContainerView(containerView);
             }
 
             mContainerView = containerView;
@@ -434,6 +443,7 @@
         mWebContentsObserver.destroy();
         mWebContentsObserver = null;
         getImeAdapter().resetAndHideKeyboard();
+        removeWindowAndroidChangedObserver(mTextSuggestionHost);
         mWindowEventObservers.clear();
         hidePopupsAndPreserveSelection();
         mWebContents = null;
@@ -1246,7 +1256,7 @@
 
     private native long nativeInit(WebContents webContents, ViewAndroidDelegate viewAndroidDelegate,
             WindowAndroid window, float dipScale);
-    private static native ContentViewCore nativeFromWebContentsAndroid(WebContents webContents);
+    private static native ContentViewCoreImpl nativeFromWebContentsAndroid(WebContents webContents);
     private native void nativeUpdateWindowAndroid(long nativeContentViewCore, WindowAndroid window);
     private native WebContents nativeGetWebContentsAndroid(long nativeContentViewCore);
     private native WindowAndroid nativeGetJavaWindowAndroid(long nativeContentViewCore);
diff --git a/content/public/android/java/src/org/chromium/content/browser/NfcHost.java b/content/public/android/java/src/org/chromium/content/browser/NfcHost.java
index 32813fd..3aa492b 100644
--- a/content/public/android/java/src/org/chromium/content/browser/NfcHost.java
+++ b/content/public/android/java/src/org/chromium/content/browser/NfcHost.java
@@ -21,7 +21,7 @@
 
     // The WebContents with which this host is associated.
     private final WebContents mWebContents;
-    private final ContentViewCore mContentViewCore;
+    private final ContentViewCoreImpl mContentViewCore;
 
     // The context ID with which this host is associated.
     private final int mContextId;
@@ -46,7 +46,7 @@
         super(webContents);
 
         mWebContents = webContents;
-        mContentViewCore = ContentViewCore.fromWebContents(mWebContents);
+        mContentViewCore = ContentViewCoreImpl.fromWebContents(mWebContents);
 
         // NFC will not work if there is no CVC associated with the WebContents, and it will only
         // be requested in contexts where there is a CVC associated with the WebContents as far as
diff --git a/content/public/android/java/src/org/chromium/content/browser/WindowAndroidProvider.java b/content/public/android/java/src/org/chromium/content/browser/WindowAndroidProvider.java
deleted file mode 100644
index f0e4a6446..0000000
--- a/content/public/android/java/src/org/chromium/content/browser/WindowAndroidProvider.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.browser;
-
-import org.chromium.ui.base.WindowAndroid;
-
-/**
- * WindowAndroidProvider is an interface that provides functionality to get WindowAndroid and
- * observe changes whenver WindowAndroid is updated by the class that implements this interface.
- */
-public interface WindowAndroidProvider {
-    /**
-     * Gets WindowAndroid.
-     */
-    WindowAndroid getWindowAndroid();
-
-    /**
-     * Adds WindowAndroidChangedObserver observer.
-     */
-    void addWindowAndroidChangedObserver(WindowAndroidChangedObserver observer);
-
-    /**
-     * Removes WindowAndroidChangedObserver observer.
-     */
-    void removeWindowAndroidChangedObserver(WindowAndroidChangedObserver observer);
-}
\ No newline at end of file
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/SpellCheckPopupWindow.java b/content/public/android/java/src/org/chromium/content/browser/input/SpellCheckPopupWindow.java
index ed3ef95..936a596 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/SpellCheckPopupWindow.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/SpellCheckPopupWindow.java
@@ -8,7 +8,7 @@
 import android.text.SpannableString;
 import android.view.View;
 
-import org.chromium.content.browser.WindowAndroidProvider;
+import org.chromium.ui.base.WindowAndroid;
 
 /**
  * A subclass of SuggestionsPopupWindow to be used for showing suggestions from a spell check
@@ -20,12 +20,12 @@
     /**
      * @param context Android context to use.
      * @param textSuggestionHost TextSuggestionHost instance (used to communicate with Blink).
+     * @param windowAndroid The current WindowAndroid instance.
      * @param parentView The view used to attach the PopupWindow.
-     * @param windowAndroidProvider A WindowAndroidProvider instance used to get the window size.
      */
     public SpellCheckPopupWindow(Context context, TextSuggestionHost textSuggestionHost,
-            View parentView, WindowAndroidProvider windowAndroidProvider) {
-        super(context, textSuggestionHost, parentView, windowAndroidProvider);
+            WindowAndroid windowAndroid, View parentView) {
+        super(context, textSuggestionHost, windowAndroid, parentView);
     }
 
     /**
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/SuggestionsPopupWindow.java b/content/public/android/java/src/org/chromium/content/browser/input/SuggestionsPopupWindow.java
index c2e6876..7b1fc0c 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/SuggestionsPopupWindow.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/SuggestionsPopupWindow.java
@@ -29,8 +29,8 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.content.R;
-import org.chromium.content.browser.WindowAndroidProvider;
 import org.chromium.ui.UiUtils;
+import org.chromium.ui.base.WindowAndroid;
 
 /**
  * Popup window that displays a menu for viewing and applying text replacement suggestions.
@@ -47,7 +47,7 @@
     private final Context mContext;
     protected final TextSuggestionHost mTextSuggestionHost;
     private final View mParentView;
-    private final WindowAndroidProvider mWindowAndroidProvider;
+    private WindowAndroid mWindowAndroid;
 
     private Activity mActivity;
     private DisplayMetrics mDisplayMetrics;
@@ -67,15 +67,15 @@
     /**
      * @param context Android context to use.
      * @param textSuggestionHost TextSuggestionHost instance (used to communicate with Blink).
+     * @param windowAndroid The current WindowAndroid instance.
      * @param parentView The view used to attach the PopupWindow.
-     * @param windowAndroidProvider A WindowAndroidProvider instance used to get the window size.
      */
     public SuggestionsPopupWindow(Context context, TextSuggestionHost textSuggestionHost,
-            View parentView, WindowAndroidProvider windowAndroidProvider) {
+            WindowAndroid windowAndroid, View parentView) {
         mContext = context;
         mTextSuggestionHost = textSuggestionHost;
+        mWindowAndroid = windowAndroid;
         mParentView = parentView;
-        mWindowAndroidProvider = windowAndroidProvider;
 
         createPopupWindow();
         initContentView();
@@ -194,6 +194,13 @@
         return mPopupWindow.isShowing();
     }
 
+    /**
+     * Used by TextSuggestionHost to update {@link WindowAndroid} to the current one.
+     */
+    public void updateWindowAndroid(WindowAndroid windowAndroid) {
+        mWindowAndroid = windowAndroid;
+    }
+
     private void addToDictionary() {
         final Intent intent = new Intent(ACTION_USER_DICTIONARY_INSERT);
 
@@ -279,7 +286,7 @@
         mNumberOfSuggestionsToUse = getSuggestionsCount();
         mHighlightedText = highlightedText;
 
-        mActivity = mWindowAndroidProvider.getWindowAndroid().getActivity().get();
+        mActivity = mWindowAndroid.getActivity().get();
         // Note: the Activity can be null here if we're in a WebView that was created without
         // using an Activity. So all code in this class should handle this case.
         if (mActivity != null) {
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/TextSuggestionHost.java b/content/public/android/java/src/org/chromium/content/browser/input/TextSuggestionHost.java
index 9f37ce4..80d01ee 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/TextSuggestionHost.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/TextSuggestionHost.java
@@ -4,13 +4,17 @@
 
 package org.chromium.content.browser.input;
 
+import android.content.Context;
+import android.view.View;
+
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
-import org.chromium.content.browser.ContentViewCoreImpl;
+import org.chromium.content.browser.WindowAndroidChangedObserver;
 import org.chromium.content.browser.WindowEventObserver;
 import org.chromium.content.browser.webcontents.WebContentsImpl;
 import org.chromium.content_public.browser.WebContents;
+import org.chromium.ui.base.WindowAndroid;
 
 /**
  * Handles displaying the Android spellcheck/text suggestion menu (provided by
@@ -18,21 +22,46 @@
  * the commands in that menu (by calling back to the C++ class).
  */
 @JNINamespace("content")
-public class TextSuggestionHost implements WindowEventObserver {
+public class TextSuggestionHost implements WindowEventObserver, WindowAndroidChangedObserver {
     private long mNativeTextSuggestionHost;
-    private final ContentViewCoreImpl mContentViewCore;
+    private final Context mContext;
+    private final WebContentsImpl mWebContents;
+
+    private View mContainerView;
     private boolean mIsAttachedToWindow;
+    private WindowAndroid mWindowAndroid;
 
     private SpellCheckPopupWindow mSpellCheckPopupWindow;
     private TextSuggestionsPopupWindow mTextSuggestionsPopupWindow;
 
-    public TextSuggestionHost(ContentViewCoreImpl contentViewCore) {
-        mContentViewCore = contentViewCore;
-        mNativeTextSuggestionHost = nativeInit(contentViewCore.getWebContents());
+    public TextSuggestionHost(
+            Context context, WebContentsImpl webContents, WindowAndroid windowAndroid, View view) {
+        mContext = context;
+        mWebContents = webContents;
+        mWindowAndroid = windowAndroid;
+        mContainerView = view;
+        mNativeTextSuggestionHost = nativeInit(webContents);
     }
 
-    private static float getContentOffsetYPix(WebContents webContents) {
-        return ((WebContentsImpl) webContents).getRenderCoordinates().getContentOffsetYPix();
+    private float getContentOffsetYPix() {
+        return mWebContents.getRenderCoordinates().getContentOffsetYPix();
+    }
+
+    public void setContainerView(View containerView) {
+        mContainerView = containerView;
+    }
+
+    // WindowAndroidChangedObserver
+
+    @Override
+    public void onWindowAndroidChanged(WindowAndroid newWindowAndroid) {
+        mWindowAndroid = newWindowAndroid;
+        if (mSpellCheckPopupWindow != null) {
+            mSpellCheckPopupWindow.updateWindowAndroid(mWindowAndroid);
+        }
+        if (mTextSuggestionsPopupWindow != null) {
+            mTextSuggestionsPopupWindow.updateWindowAndroid(mWindowAndroid);
+        }
     }
 
     // WindowEventObserver
@@ -58,12 +87,11 @@
         }
 
         hidePopups();
-        mSpellCheckPopupWindow = new SpellCheckPopupWindow(mContentViewCore.getContext(), this,
-                mContentViewCore.getContainerView(), mContentViewCore);
+        mSpellCheckPopupWindow =
+                new SpellCheckPopupWindow(mContext, this, mWindowAndroid, mContainerView);
 
-        mSpellCheckPopupWindow.show(caretXPx,
-                caretYPx + getContentOffsetYPix(mContentViewCore.getWebContents()), markedText,
-                suggestions);
+        mSpellCheckPopupWindow.show(
+                caretXPx, caretYPx + getContentOffsetYPix(), markedText, suggestions);
     }
 
     @CalledByNative
@@ -77,12 +105,11 @@
         }
 
         hidePopups();
-        mTextSuggestionsPopupWindow = new TextSuggestionsPopupWindow(mContentViewCore.getContext(),
-                this, mContentViewCore.getContainerView(), mContentViewCore);
+        mTextSuggestionsPopupWindow =
+                new TextSuggestionsPopupWindow(mContext, this, mWindowAndroid, mContainerView);
 
-        mTextSuggestionsPopupWindow.show(caretXPx,
-                caretYPx + getContentOffsetYPix(mContentViewCore.getWebContents()), markedText,
-                suggestions);
+        mTextSuggestionsPopupWindow.show(
+                caretXPx, caretYPx + getContentOffsetYPix(), markedText, suggestions);
     }
 
     /**
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/TextSuggestionsPopupWindow.java b/content/public/android/java/src/org/chromium/content/browser/input/TextSuggestionsPopupWindow.java
index e463d8f..f607e6733 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/TextSuggestionsPopupWindow.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/TextSuggestionsPopupWindow.java
@@ -11,7 +11,7 @@
 import android.view.View;
 
 import org.chromium.content.R;
-import org.chromium.content.browser.WindowAndroidProvider;
+import org.chromium.ui.base.WindowAndroid;
 
 /**
  * A subclass of SuggestionsPopupWindow to be used for showing suggestions from one or more
@@ -25,12 +25,12 @@
     /**
      * @param context Android context to use.
      * @param textSuggestionHost TextSuggestionHost instance (used to communicate with Blink).
+     * @param windowAndroid The current WindowAndroid instance.
      * @param parentView The view used to attach the PopupWindow.
-     * @param windowAndroidProvider A WindowAndroidProvider instance used to get the window size.
      */
     public TextSuggestionsPopupWindow(Context context, TextSuggestionHost textSuggestionHost,
-            View parentView, WindowAndroidProvider windowAndroidProvider) {
-        super(context, textSuggestionHost, parentView, windowAndroidProvider);
+            WindowAndroid windowAndroid, View parentView) {
+        super(context, textSuggestionHost, windowAndroid, parentView);
 
         mPrefixSpan = new TextAppearanceSpan(context, R.style.SuggestionPrefixOrSuffix);
         mSuffixSpan = new TextAppearanceSpan(context, R.style.SuggestionPrefixOrSuffix);
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/PopupZoomerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/PopupZoomerTest.java
index 312a5233..17fe2c3 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/PopupZoomerTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/PopupZoomerTest.java
@@ -112,8 +112,8 @@
                 mPopupZoomer = createPopupZoomerForTest(
                         InstrumentationRegistry.getTargetContext(), webContents, containerView);
                 mContentViewCore.setPopupZoomerForTest(mPopupZoomer);
-                mContentViewCore.setTextSuggestionHostForTesting(
-                        new TextSuggestionHost(mActivityTestRule.getContentViewCore()));
+                mContentViewCore.setTextSuggestionHostForTesting(new TextSuggestionHost(
+                        context, (WebContentsImpl) webContents, null, containerView));
             }
         });
     }
diff --git a/content/public/browser/browser_main_parts.h b/content/public/browser/browser_main_parts.h
index 2c8b96aa..9739319 100644
--- a/content/public/browser/browser_main_parts.h
+++ b/content/public/browser/browser_main_parts.h
@@ -74,6 +74,10 @@
   // (or 0 if no error).
   virtual int PreCreateThreads();
 
+  // This is called right after all child threads owned by the content framework
+  // are created.
+  virtual void PostCreateThreads() {}
+
   virtual void ServiceManagerConnectionStarted(
       ServiceManagerConnection* connection) {}
 
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index b87caa7..10c06ec0 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -289,6 +289,10 @@
 const base::Feature kScrollAnchoring{"ScrollAnchoring",
                                      base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Save the scroll anchor and use it to restore scroll position.
+const base::Feature kScrollAnchorSerialization{
+    "ScrollAnchorSerialization", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Make sendBeacon throw for a Blob with a non simple type.
 const base::Feature kSendBeaconThrowForBlobWithNonSimpleType{
     "SendBeaconThrowForBlobWithNonSimpleType",
@@ -307,6 +311,10 @@
 const base::Feature kServiceWorkerScriptFullCodeCache{
     "ServiceWorkerScriptFullCodeCache", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Establish direct connection from clients to the service worker.
+const base::Feature kServiceWorkerServicification{
+    "ServiceWorkerServicification", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // http://tc39.github.io/ecmascript_sharedmem/shmem.html
 const base::Feature kSharedArrayBuffer{"SharedArrayBuffer",
                                        base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 0b0cfc3..803be63 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -76,11 +76,13 @@
 CONTENT_EXPORT extern const base::Feature kRequireCSSExtensionForFile;
 CONTENT_EXPORT extern const base::Feature kResourceLoadScheduler;
 CONTENT_EXPORT extern const base::Feature kScrollAnchoring;
+CONTENT_EXPORT extern const base::Feature kScrollAnchorSerialization;
 CONTENT_EXPORT
 extern const base::Feature kSendBeaconThrowForBlobWithNonSimpleType;
 CONTENT_EXPORT extern const base::Feature kServiceWorkerPaymentApps;
 CONTENT_EXPORT extern const base::Feature kServiceWorkerScriptStreaming;
 CONTENT_EXPORT extern const base::Feature kServiceWorkerScriptFullCodeCache;
+CONTENT_EXPORT extern const base::Feature kServiceWorkerServicification;
 CONTENT_EXPORT extern const base::Feature kSharedArrayBuffer;
 CONTENT_EXPORT extern const base::Feature kSignedHTTPExchange;
 CONTENT_EXPORT extern const base::Feature kSignInProcessIsolation;
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewCore.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewCore.java
index 5d3ac204..9e2171f 100644
--- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewCore.java
+++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewCore.java
@@ -17,7 +17,6 @@
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.ContentViewCore.InternalAccessDelegate;
 import org.chromium.content.browser.PopupZoomer;
-import org.chromium.content.browser.WindowAndroidChangedObserver;
 import org.chromium.content.browser.accessibility.WebContentsAccessibility;
 import org.chromium.content.browser.input.SelectPopup;
 import org.chromium.content.browser.input.TextSuggestionHost;
@@ -61,12 +60,6 @@
     public void setTextSuggestionHostForTesting(TextSuggestionHost textSuggestionHost) {}
 
     @Override
-    public void addWindowAndroidChangedObserver(WindowAndroidChangedObserver observer) {}
-
-    @Override
-    public void removeWindowAndroidChangedObserver(WindowAndroidChangedObserver observer) {}
-
-    @Override
     public void initialize(ViewAndroidDelegate viewDelegate,
             InternalAccessDelegate internalDispatcher, WebContents webContents,
             WindowAndroid windowAndroid) {}
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index cd18a5e..efa2ba9 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -226,10 +226,6 @@
     "layout_test_dependencies.h",
     "loader/child_url_loader_factory_getter_impl.cc",
     "loader/child_url_loader_factory_getter_impl.h",
-    "loader/cors_url_loader.cc",
-    "loader/cors_url_loader.h",
-    "loader/cors_url_loader_factory.cc",
-    "loader/cors_url_loader_factory.h",
     "loader/ftp_directory_listing_response_delegate.cc",
     "loader/ftp_directory_listing_response_delegate.h",
     "loader/request_extra_data.cc",
diff --git a/content/renderer/DEPS b/content/renderer/DEPS
index 7d55efc..95e2190d 100644
--- a/content/renderer/DEPS
+++ b/content/renderer/DEPS
@@ -47,7 +47,4 @@
   "renderer_main\.cc": [
     "+ui/ozone/public/client_native_pixmap_factory_ozone.h",
   ],
-  "service_worker_subresource_loader_unittest\.cc": [
-    "+storage/browser",
-  ]
 }
diff --git a/content/renderer/loader/cors_url_loader_factory.cc b/content/renderer/loader/cors_url_loader_factory.cc
deleted file mode 100644
index 53815d3..0000000
--- a/content/renderer/loader/cors_url_loader_factory.cc
+++ /dev/null
@@ -1,67 +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 "content/renderer/loader/cors_url_loader_factory.h"
-
-#include "content/renderer/loader/cors_url_loader.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "services/network/public/interfaces/url_loader_factory.mojom.h"
-
-namespace content {
-
-void CORSURLLoaderFactory::CreateAndBind(
-    PossiblyAssociatedInterfacePtrInfo<network::mojom::URLLoaderFactory>
-        network_loader_factory,
-    network::mojom::URLLoaderFactoryRequest request) {
-  DCHECK(network_loader_factory);
-
-  // This object will be destroyed when all pipes bound to it are closed.
-  // See OnConnectionError().
-  auto* impl = new CORSURLLoaderFactory(std::move(network_loader_factory));
-  impl->Clone(std::move(request));
-}
-
-CORSURLLoaderFactory::CORSURLLoaderFactory(
-    PossiblyAssociatedInterfacePtrInfo<network::mojom::URLLoaderFactory>
-        network_loader_factory) {
-  // Binding |this| as an unretained pointer is safe because |bindings_| shares
-  // this object's lifetime.
-  bindings_.set_connection_error_handler(base::Bind(
-      &CORSURLLoaderFactory::OnConnectionError, base::Unretained(this)));
-  loader_bindings_.set_connection_error_handler(base::Bind(
-      &CORSURLLoaderFactory::OnConnectionError, base::Unretained(this)));
-
-  network_loader_factory_.Bind(std::move(network_loader_factory));
-}
-
-CORSURLLoaderFactory::~CORSURLLoaderFactory() {}
-
-void CORSURLLoaderFactory::CreateLoaderAndStart(
-    network::mojom::URLLoaderRequest request,
-    int32_t routing_id,
-    int32_t request_id,
-    uint32_t options,
-    const network::ResourceRequest& resource_request,
-    network::mojom::URLLoaderClientPtr client,
-    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
-  // Instances of CORSURLLoader are owned by this class and their pipe so that
-  // they can share |network_loader_factory_|.
-  loader_bindings_.AddBinding(
-      std::make_unique<CORSURLLoader>(
-          routing_id, request_id, options, resource_request, std::move(client),
-          traffic_annotation, network_loader_factory_.get()),
-      std::move(request));
-}
-
-void CORSURLLoaderFactory::Clone(
-    network::mojom::URLLoaderFactoryRequest request) {
-  bindings_.AddBinding(this, std::move(request));
-}
-
-void CORSURLLoaderFactory::OnConnectionError() {
-  if (bindings_.empty() && loader_bindings_.empty())
-    delete this;
-}
-
-}  // namespace content
diff --git a/content/renderer/loader/cors_url_loader_factory.h b/content/renderer/loader/cors_url_loader_factory.h
deleted file mode 100644
index 2816a386..0000000
--- a/content/renderer/loader/cors_url_loader_factory.h
+++ /dev/null
@@ -1,61 +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 CONTENT_RENDERER_LOADER_CORS_URL_LOADER_FACTORY_H_
-#define CONTENT_RENDERER_LOADER_CORS_URL_LOADER_FACTORY_H_
-
-#include "content/common/content_export.h"
-#include "content/common/possibly_associated_interface_ptr.h"
-#include "content/common/possibly_associated_interface_ptr_info.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "mojo/public/cpp/bindings/strong_binding_set.h"
-#include "services/network/public/interfaces/url_loader_factory.mojom.h"
-
-namespace content {
-
-// URLLoaderFactory that adds cross-origin resource sharing capabilities
-// (https://www.w3.org/TR/cors/), delegating requests as well as potential
-// preflight requests to the supplied |network_loader_factory|. Its lifetime is
-// bound to that of the pipes connected to it and the CORSURLLoader instances it
-// creates.
-class CONTENT_EXPORT CORSURLLoaderFactory
-    : public network::mojom::URLLoaderFactory {
- public:
-  static void CreateAndBind(
-      PossiblyAssociatedInterfacePtrInfo<network::mojom::URLLoaderFactory>
-          network_loader_factory,
-      network::mojom::URLLoaderFactoryRequest request);
-
-  explicit CORSURLLoaderFactory(
-      PossiblyAssociatedInterfacePtrInfo<network::mojom::URLLoaderFactory>
-          network_loader_factory);
-  ~CORSURLLoaderFactory() override;
-
-  // network::mojom::URLLoaderFactory
-  void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
-                            int32_t routing_id,
-                            int32_t request_id,
-                            uint32_t options,
-                            const network::ResourceRequest& resource_request,
-                            network::mojom::URLLoaderClientPtr client,
-                            const net::MutableNetworkTrafficAnnotationTag&
-                                traffic_annotation) override;
-  void Clone(network::mojom::URLLoaderFactoryRequest request) override;
-
-  void OnConnectionError();
-
- private:
-  PossiblyAssociatedInterfacePtr<network::mojom::URLLoaderFactory>
-      network_loader_factory_;
-
-  // The factory owns the CORSURLLoaders it creates so that they can share
-  // |network_loader_factory_|.
-  mojo::StrongBindingSet<network::mojom::URLLoader> loader_bindings_;
-
-  mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_LOADER_CORS_URL_LOADER_FACTORY_H_
diff --git a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
index 8d42929..99503456 100644
--- a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
+++ b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
@@ -11,6 +11,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/unguessable_token.h"
+#include "build/build_config.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "content/child/child_thread_impl.h"
 #include "content/public/common/content_features.h"
@@ -296,14 +297,25 @@
   viz::ContextProvider::ScopedContextLock lock(context_provider_);
   auto capabilities = context_provider_->ContextCapabilities();
   if (bit_depth > 8) {
-    // If high bit depth rendering is not enabled and we support RG textures,
-    // use those, albeit at a reduced bit depth of 8 bits per component.
+    // If high bit depth rendering is enabled, bail here, otherwise try and use
+    // XR30 storage, and if not and we support RG textures, use those, albeit at
+    // a reduced bit depth of 8 bits per component.
     // TODO(mcasas): continue working on this, avoiding dropping information as
     // long as the hardware may support it https://crbug.com/798485.
-    if (!rendering_color_space_.IsHDR() && capabilities.texture_rg)
-      return media::GpuVideoAcceleratorFactories::OutputFormat::I420;
-    else
+    if (rendering_color_space_.IsHDR())
       return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
+
+#if defined(OS_MACOSX)
+    // TODO(mcasas): enable other platforms https://crbug.com/776093
+    // https://crbug.com/803451, https://crbug.com/803975.
+    // TODO(mcasas): remove the |bit_depth| check when libyuv supports more than
+    // just x010ToAR30 conversions, https://crbug.com/libyuv/751.
+    if (capabilities.image_xr30 && bit_depth == 10)
+      return media::GpuVideoAcceleratorFactories::OutputFormat::XR30;
+#endif
+    if (capabilities.texture_rg)
+      return media::GpuVideoAcceleratorFactories::OutputFormat::I420;
+    return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
   }
   if (capabilities.image_ycbcr_420v &&
       !capabilities.image_ycbcr_420v_disabled_for_video_frames) {
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 78f7d40..b6a0d92 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -3433,6 +3433,12 @@
   browser_side_navigation_pending_url_ = GURL();
 }
 
+void RenderFrameImpl::UpdateSubresourceLoaderFactories(
+    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders) {
+  DCHECK(subresource_loader_factories_);
+  subresource_loader_factories_->Update(std::move(subresource_loaders));
+}
+
 // mojom::HostZoom implementation ----------------------------------------------
 
 void RenderFrameImpl::SetHostZoomLevel(const GURL& url, double zoom_level) {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 7097b46..2f6f0713 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -537,6 +537,8 @@
       int error_code,
       const base::Optional<std::string>& error_page_content,
       std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders) override;
+  void UpdateSubresourceLoaderFactories(
+      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders) override;
 
   // mojom::FullscreenVideoElementHandler implementation:
   void RequestFullscreenVideoElement() override;
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 172f5c45..f90386a 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -55,7 +55,6 @@
 #include "content/renderer/image_capture/image_capture_frame_grabber.h"
 #include "content/renderer/indexed_db/webidbfactory_impl.h"
 #include "content/renderer/loader/child_url_loader_factory_getter_impl.h"
-#include "content/renderer/loader/cors_url_loader_factory.h"
 #include "content/renderer/loader/resource_dispatcher.h"
 #include "content/renderer/loader/web_data_consumer_handle_impl.h"
 #include "content/renderer/loader/web_url_loader_impl.h"
@@ -378,18 +377,6 @@
     render_thread->channel()->GetRemoteAssociatedInterface(&factory_ptr);
     url_loader_factory = std::move(factory_ptr);
   }
-
-  // Attach the CORS-enabled URLLoader for the network URLLoaderFactory. To
-  // avoid thread hops and prevent jank on the main thread from affecting
-  // requests from other threads this object should live on the IO thread.
-  if (base::FeatureList::IsEnabled(features::kOutOfBlinkCORS)) {
-    network::mojom::URLLoaderFactoryPtr factory_ptr;
-    RenderThreadImpl::current()->GetIOTaskRunner()->PostTask(
-        FROM_HERE, base::BindOnce(&CORSURLLoaderFactory::CreateAndBind,
-                                  url_loader_factory.PassInterface(),
-                                  mojo::MakeRequest(&factory_ptr)));
-    url_loader_factory = std::move(factory_ptr);
-  }
   return url_loader_factory;
 }
 
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index 47bcbbb..2cee8bd5 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -1353,11 +1353,12 @@
 void ServiceWorkerContextClient::DispatchSyncEvent(
     const std::string& tag,
     bool last_chance,
+    base::TimeDelta timeout,
     DispatchSyncEventCallback callback) {
   TRACE_EVENT0("ServiceWorker",
                "ServiceWorkerContextClient::DispatchSyncEvent");
-  int request_id = context_->timeout_timer->StartEvent(
-      CreateAbortCallback(&context_->sync_event_callbacks));
+  int request_id = context_->timeout_timer->StartEventWithCustomTimeout(
+      CreateAbortCallback(&context_->sync_event_callbacks), timeout);
   context_->sync_event_callbacks.emplace(request_id, std::move(callback));
 
   // TODO(jkarlin): Make this blink::WebString::FromUTF8Lenient once
@@ -1680,8 +1681,9 @@
   TRACE_EVENT0("ServiceWorker",
                "ServiceWorkerContextClient::DispatchPushEvent");
 
-  int request_id = context_->timeout_timer->StartEvent(
-      CreateAbortCallback(&context_->push_event_callbacks));
+  int request_id = context_->timeout_timer->StartEventWithCustomTimeout(
+      CreateAbortCallback(&context_->push_event_callbacks),
+      base::TimeDelta::FromSeconds(mojom::kPushEventTimeoutSeconds));
   context_->push_event_callbacks.emplace(request_id, std::move(callback));
 
   // Only set data to be a valid string if the payload had decrypted data.
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h
index 2decc63..0e57766 100644
--- a/content/renderer/service_worker/service_worker_context_client.h
+++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -329,6 +329,7 @@
                          DispatchPushEventCallback callback) override;
   void DispatchSyncEvent(const std::string& tag,
                          bool last_chance,
+                         base::TimeDelta timeout,
                          DispatchSyncEventCallback callback) override;
   void DispatchAbortPaymentEvent(
       int payment_request_id,
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.cc b/content/renderer/service_worker/service_worker_subresource_loader.cc
index 0e9556f..bbd12776 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader.cc
+++ b/content/renderer/service_worker/service_worker_subresource_loader.cc
@@ -234,17 +234,33 @@
   // (crbug.com/780405)
   // TODO(kinuko): Implement request timeout and ask the browser to kill
   // the controller if it takes too long. (crbug.com/774374)
+
+  // Passing the request body over Mojo moves it out. But the request body
+  // may be needed later, in the case where the service worker doesn't provide a
+  // response in the fetch event. So instead send a cloned body. (Note that
+  // we can't do the reverse, i.e., send the original and restore the clone
+  // later.  By always sending the clone, we ensure the original ResourceRequest
+  // passed into the constructor always points to a valid ResourceRequestBody,
+  // even if this loader gets destructed.)
+  if (resource_request_.request_body) {
+    inflight_fetch_request_->request_body =
+        ServiceWorkerLoaderHelpers::CloneResourceRequestBody(
+            resource_request_.request_body.get());
+  }
+
   controller->DispatchFetchEvent(
       *inflight_fetch_request_, std::move(response_callback_ptr),
       base::BindOnce(&ServiceWorkerSubresourceLoader::OnFetchEventFinished,
                      weak_factory_.GetWeakPtr()));
+  // |inflight_fetch_request_->request_body| should not be used after this
+  // point.
 }
 
 void ServiceWorkerSubresourceLoader::OnFetchEventFinished(
     blink::mojom::ServiceWorkerEventStatus status,
     base::Time dispatch_event_time) {
   // Stop restarting logic here since OnFetchEventFinished() indicates that the
-  // fetch event could be successfully dispatched.
+  // fetch event was successfully dispatched.
   SettleInflightFetchRequestIfNeeded();
 
   switch (status) {
@@ -350,8 +366,6 @@
   }
 
   // Hand over to the network loader.
-  // Per spec, redirects after this point are not intercepted by the service
-  // worker again. (https://crbug.com/517364)
   default_loader_factory_getter_->GetNetworkLoaderFactory()
       ->CreateLoaderAndStart(
           url_loader_binding_.Unbind(), routing_id_, request_id_, options_,
@@ -362,6 +376,8 @@
                          response_head_.service_worker_start_time,
                          response_head_.service_worker_ready_time)),
           traffic_annotation_);
+  // Per spec, redirects after this point are not intercepted by the service
+  // worker again (https://crbug.com/517364). So this loader is done.
   DeleteSoon();
 }
 
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.h b/content/renderer/service_worker/service_worker_subresource_loader.h
index 4f67ef7..1a759c0 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader.h
+++ b/content/renderer/service_worker/service_worker_subresource_loader.h
@@ -112,6 +112,9 @@
 
   scoped_refptr<ControllerServiceWorkerConnector> controller_connector_;
 
+  // The request destined for the controller service worker. This is used
+  // separately from |resource_request_| for the restarting mechanism when the
+  // first attempt to dispatch to the controller failed.
   std::unique_ptr<network::ResourceRequest> inflight_fetch_request_;
   bool fetch_request_restarted_;
 
@@ -122,7 +125,8 @@
   const uint32_t options_;
   net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
 
-  // |resource_request_| changes due to redirects.
+  // |resource_request_| is initialized in the constructor, and may change
+  // over the lifetime of this loader due to redirects.
   network::ResourceRequest resource_request_;
 
   // For network fallback.
diff --git a/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc b/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
index b6f3887..b0b8fdb8 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
+++ b/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
@@ -21,8 +21,7 @@
 #include "net/http/http_util.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request.h"
-#include "storage/browser/blob/blob_data_builder.h"
-#include "storage/browser/blob/blob_data_handle.h"
+#include "services/network/test/test_data_pipe_getter.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/origin.h"
 
@@ -30,9 +29,9 @@
 
 namespace {
 
-// This class need to set ChildURLLoaderFactoryGetter. CreateLoaderAndStart()
-// need to implement. todo(emim): Merge this and the one in
-// service_worker_url_loader_job_unittest.cc.
+// A simple URLLoaderFactory that responds with status 200 to every request.
+// This is the default network loader factory for
+// ServiceWorkerSubresourceLoaderTest.
 class FakeNetworkURLLoaderFactory final
     : public network::mojom::URLLoaderFactory {
  public:
@@ -114,13 +113,30 @@
 
   void ReadRequestBody(std::string* out_string) {
     ASSERT_TRUE(request_body_);
-    const std::vector<network::DataElement>* elements =
-        request_body_->elements();
-    // So far this test expects a single bytes element.
+    std::vector<network::DataElement>* elements =
+        request_body_->elements_mutable();
+    // So far this test expects a single element (bytes or data pipe).
     ASSERT_EQ(1u, elements->size());
-    const network::DataElement& element = elements->front();
-    ASSERT_EQ(network::DataElement::TYPE_BYTES, element.type());
-    *out_string = std::string(element.bytes(), element.length());
+    network::DataElement& element = elements->front();
+    if (element.type() == network::DataElement::TYPE_BYTES) {
+      *out_string = std::string(element.bytes(), element.length());
+    } else if (element.type() == network::DataElement::TYPE_DATA_PIPE) {
+      // Read the content into |data_pipe|.
+      mojo::DataPipe data_pipe;
+      network::mojom::DataPipeGetterPtr ptr = element.ReleaseDataPipeGetter();
+      base::RunLoop run_loop;
+      ptr->Read(
+          std::move(data_pipe.producer_handle),
+          base::BindOnce([](const base::Closure& quit_closure, int32_t status,
+                            uint64_t size) { quit_closure.Run(); },
+                         run_loop.QuitClosure()));
+      run_loop.Run();
+      // Copy the content to |out_string|.
+      mojo::common::BlockingCopyToString(std::move(data_pipe.consumer_handle),
+                                         out_string);
+    } else {
+      NOTREACHED();
+    }
   }
 
   // mojom::ControllerServiceWorker:
@@ -199,7 +215,8 @@
             base::Time::Now());
         std::move(callback).Run(
             blink::mojom::ServiceWorkerEventStatus::COMPLETED, base::Time());
-      } break;
+        break;
+      }
     }
     if (fetch_event_callback_)
       std::move(fetch_event_callback_).Run();
@@ -301,7 +318,6 @@
 
 }  // namespace
 
-
 class ServiceWorkerSubresourceLoaderTest : public ::testing::Test {
  protected:
   ServiceWorkerSubresourceLoaderTest()
@@ -353,10 +369,45 @@
     return request;
   }
 
+  // Performs a request with the given |request_body|, and checks that the body
+  // is passed to the fetch event.
+  void RunFallbackWithRequestBodyTest(
+      scoped_refptr<network::ResourceRequestBody> request_body,
+      const std::string& expected_body) {
+    std::unique_ptr<ServiceWorkerSubresourceLoaderFactory> factory =
+        CreateSubresourceLoaderFactory();
+
+    // Create a request with the body.
+    network::ResourceRequest request =
+        CreateRequest(GURL("https://www.example.com/upload"));
+    request.method = "POST";
+    request.request_body = std::move(request_body);
+
+    // Set the service worker to do network fallback as it exercises a tricky
+    // code path to ensure the body makes it to network.
+    fake_controller_.RespondWithFallback();
+
+    // Perform the request.
+    network::mojom::URLLoaderPtr loader;
+    std::unique_ptr<TestURLLoaderClient> client;
+    StartRequest(factory.get(), request, &loader, &client);
+    client->RunUntilComplete();
+
+    // Verify that the request body was passed to the fetch event.
+    std::string fetch_event_body;
+    fake_controller_.ReadRequestBody(&fetch_event_body);
+    EXPECT_EQ(expected_body, fetch_event_body);
+
+    // TODO(falken): It'd be nicer to also check the request body was sent to
+    // network but it requires more complicated network mocking and it was hard
+    // getting EmbeddedTestServer working with these tests (probably
+    // CORSFallbackResponse is too heavy). We also have Web Platform Tests that
+    // cover this case in fetch-event.https.html.
+  }
+
   TestBrowserThreadBundle thread_bundle_;
   scoped_refptr<ChildURLLoaderFactoryGetter> loader_factory_getter_;
   scoped_refptr<ControllerServiceWorkerConnector> connector_;
-
   FakeServiceWorkerContainerHost fake_container_host_;
   FakeControllerServiceWorker fake_controller_;
   base::test::ScopedFeatureList feature_list_;
@@ -365,7 +416,6 @@
 };
 
 TEST_F(ServiceWorkerSubresourceLoaderTest, Basic) {
-  const GURL kScope("https://www.example.com/");
   std::unique_ptr<ServiceWorkerSubresourceLoaderFactory> factory =
       CreateSubresourceLoaderFactory();
   network::ResourceRequest request =
@@ -384,7 +434,6 @@
 TEST_F(ServiceWorkerSubresourceLoaderTest, Abort) {
   fake_controller_.AbortEventWithNoResponse();
 
-  const GURL kScope("https://www.example.com/");
   std::unique_ptr<ServiceWorkerSubresourceLoaderFactory> factory =
       CreateSubresourceLoaderFactory();
 
@@ -400,7 +449,6 @@
 }
 
 TEST_F(ServiceWorkerSubresourceLoaderTest, DropController) {
-  const GURL kScope("https://www.example.com/");
   std::unique_ptr<ServiceWorkerSubresourceLoaderFactory> factory =
       CreateSubresourceLoaderFactory();
   {
@@ -455,7 +503,6 @@
 }
 
 TEST_F(ServiceWorkerSubresourceLoaderTest, NoController) {
-  const GURL kScope("https://www.example.com/");
   std::unique_ptr<ServiceWorkerSubresourceLoaderFactory> factory =
       CreateSubresourceLoaderFactory();
   {
@@ -494,7 +541,6 @@
 }
 
 TEST_F(ServiceWorkerSubresourceLoaderTest, DropController_RestartFetchEvent) {
-  const GURL kScope("https://www.example.com/");
   std::unique_ptr<ServiceWorkerSubresourceLoaderFactory> factory =
       CreateSubresourceLoaderFactory();
 
@@ -551,7 +597,6 @@
   // Simulate the container host fails to start a service worker.
   fake_container_host_.set_fake_controller(nullptr);
 
-  const GURL kScope("https://www.example.com/");
   std::unique_ptr<ServiceWorkerSubresourceLoaderFactory> factory =
       CreateSubresourceLoaderFactory();
   network::ResourceRequest request =
@@ -578,7 +623,6 @@
   fake_controller_.RespondWithStream(mojo::MakeRequest(&stream_callback),
                                      std::move(data_pipe.consumer_handle));
 
-  const GURL kScope("https://www.example.com/");
   std::unique_ptr<ServiceWorkerSubresourceLoaderFactory> factory =
       CreateSubresourceLoaderFactory();
 
@@ -628,7 +672,6 @@
 TEST_F(ServiceWorkerSubresourceLoaderTest, FallbackResponse) {
   fake_controller_.RespondWithFallback();
 
-  const GURL kScope("https://www.example.com/");
   std::unique_ptr<ServiceWorkerSubresourceLoaderFactory> factory =
       CreateSubresourceLoaderFactory();
 
@@ -648,7 +691,6 @@
 TEST_F(ServiceWorkerSubresourceLoaderTest, ErrorResponse) {
   fake_controller_.RespondWithError();
 
-  const GURL kScope("https://www.example.com/");
   std::unique_ptr<ServiceWorkerSubresourceLoaderFactory> factory =
       CreateSubresourceLoaderFactory();
 
@@ -666,7 +708,6 @@
 TEST_F(ServiceWorkerSubresourceLoaderTest, RedirectResponse) {
   fake_controller_.RespondWithRedirect("https://www.example.com/bar.png");
 
-  const GURL kScope("https://www.example.com/");
   std::unique_ptr<ServiceWorkerSubresourceLoaderFactory> factory =
       CreateSubresourceLoaderFactory();
 
@@ -743,7 +784,6 @@
       std::string("https://www.example.com/redirect_") +
       base::IntToString(count);
   fake_controller_.RespondWithRedirect(redirect_location);
-  const GURL kScope("https://www.example.com/");
   std::unique_ptr<ServiceWorkerSubresourceLoaderFactory> factory =
       CreateSubresourceLoaderFactory();
 
@@ -789,7 +829,6 @@
 TEST_F(ServiceWorkerSubresourceLoaderTest, CORSFallbackResponse) {
   fake_controller_.RespondWithFallback();
 
-  const GURL kScope("https://www.example.com/");
   std::unique_ptr<ServiceWorkerSubresourceLoaderFactory> factory =
       CreateSubresourceLoaderFactory();
 
@@ -855,34 +894,24 @@
   }
 }
 
-// Test that the request body is passed to the fetch event.
-TEST_F(ServiceWorkerSubresourceLoaderTest, RequestBody) {
-  const GURL kUrl("https://www.example.com");
-  std::unique_ptr<ServiceWorkerSubresourceLoaderFactory> factory =
-      CreateSubresourceLoaderFactory();
-
-  // Create a request with a body.
+TEST_F(ServiceWorkerSubresourceLoaderTest, FallbackWithRequestBody_String) {
+  const std::string kData = "Hi, this is the request body (string)";
   auto request_body = base::MakeRefCounted<network::ResourceRequestBody>();
-  const std::string kData = "hi this is the request body";
+  network::mojom::DataPipeGetterPtr data_pipe_getter_ptr;
   request_body->AppendBytes(kData.c_str(), kData.length());
-  network::ResourceRequest request = CreateRequest(kUrl);
-  request.method = "POST";
-  request.request_body = request_body;
 
-  // This test doesn't use the response to the fetch event, so just have the
-  // service worker do simple network fallback.
-  fake_controller_.RespondWithFallback();
+  RunFallbackWithRequestBodyTest(std::move(request_body), kData);
+}
 
-  // Perform the request.
-  network::mojom::URLLoaderPtr loader;
-  std::unique_ptr<TestURLLoaderClient> client;
-  StartRequest(factory.get(), request, &loader, &client);
-  fake_controller_.RunUntilFetchEvent();
+TEST_F(ServiceWorkerSubresourceLoaderTest, FallbackWithRequestBody_DataPipe) {
+  const std::string kData = "Hi, this is the request body (data pipe)";
+  auto request_body = base::MakeRefCounted<network::ResourceRequestBody>();
+  network::mojom::DataPipeGetterPtr data_pipe_getter_ptr;
+  auto data_pipe_getter = std::make_unique<network::TestDataPipeGetter>(
+      kData, mojo::MakeRequest(&data_pipe_getter_ptr));
+  request_body->AppendDataPipe(std::move(data_pipe_getter_ptr));
 
-  // Verify that the request body was passed to the fetch event.
-  std::string body;
-  fake_controller_.ReadRequestBody(&body);
-  EXPECT_EQ(kData, body);
+  RunFallbackWithRequestBodyTest(std::move(request_body), kData);
 }
 
 }  // namespace content
diff --git a/content/renderer/service_worker/service_worker_timeout_timer.cc b/content/renderer/service_worker/service_worker_timeout_timer.cc
index 669134f..2bca894 100644
--- a/content/renderer/service_worker/service_worker_timeout_timer.cc
+++ b/content/renderer/service_worker/service_worker_timeout_timer.cc
@@ -53,6 +53,12 @@
 
 int ServiceWorkerTimeoutTimer::StartEvent(
     base::OnceCallback<void(int /* event_id */)> abort_callback) {
+  return StartEventWithCustomTimeout(std::move(abort_callback), kEventTimeout);
+}
+
+int ServiceWorkerTimeoutTimer::StartEventWithCustomTimeout(
+    base::OnceCallback<void(int /* event_id */)> abort_callback,
+    base::TimeDelta timeout) {
   if (did_idle_timeout()) {
     idle_time_ = base::TimeTicks();
     did_idle_timeout_ = false;
@@ -67,7 +73,7 @@
   std::set<EventInfo>::iterator iter;
   bool is_inserted;
   std::tie(iter, is_inserted) = inflight_events_.emplace(
-      event_id, tick_clock_->NowTicks() + kEventTimeout,
+      event_id, tick_clock_->NowTicks() + timeout,
       base::BindOnce(std::move(abort_callback), event_id));
   DCHECK(is_inserted);
   id_event_map_.emplace(event_id, iter);
diff --git a/content/renderer/service_worker/service_worker_timeout_timer.h b/content/renderer/service_worker/service_worker_timeout_timer.h
index f134353..7356aac 100644
--- a/content/renderer/service_worker/service_worker_timeout_timer.h
+++ b/content/renderer/service_worker/service_worker_timeout_timer.h
@@ -56,6 +56,11 @@
   // run in order synchronouslly in StartEvent().
   // See the class comment to know when |abort_callback| runs.
   int StartEvent(base::OnceCallback<void(int /* event_id */)> abort_callback);
+  // This is basically the same as StartEvent, but you can customize the
+  // timeout time until |abort_callback| runs by |timeout|.
+  int StartEventWithCustomTimeout(
+      base::OnceCallback<void(int /* event_id */)> abort_callback,
+      base::TimeDelta timeout);
   void EndEvent(int event_id);
 
   // Pushes a task which is expected to run after any event starts again to a
diff --git a/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc b/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc
index 90997c76..f0d370b0 100644
--- a/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc
+++ b/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc
@@ -134,6 +134,33 @@
   EXPECT_TRUE(event2.has_aborted());
 }
 
+TEST_F(ServiceWorkerTimeoutTimerTest, CustomTimeouts) {
+  EnableServicification();
+
+  ServiceWorkerTimeoutTimer timer(base::BindRepeating(&base::DoNothing),
+                                  task_runner()->GetMockTickClock());
+  MockEvent event1, event2;
+  int event_id1 = timer.StartEventWithCustomTimeout(
+      event1.CreateAbortCallback(), ServiceWorkerTimeoutTimer::kUpdateInterval -
+                                        base::TimeDelta::FromSeconds(1));
+  int event_id2 = timer.StartEventWithCustomTimeout(
+      event2.CreateAbortCallback(),
+      ServiceWorkerTimeoutTimer::kUpdateInterval * 2 -
+          base::TimeDelta::FromSeconds(1));
+  event1.set_event_id(event_id1);
+  event2.set_event_id(event_id2);
+  task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kUpdateInterval +
+                               base::TimeDelta::FromSeconds(1));
+
+  EXPECT_TRUE(event1.has_aborted());
+  EXPECT_FALSE(event2.has_aborted());
+  task_runner()->FastForwardBy(ServiceWorkerTimeoutTimer::kUpdateInterval +
+                               base::TimeDelta::FromSeconds(1));
+
+  EXPECT_TRUE(event1.has_aborted());
+  EXPECT_TRUE(event2.has_aborted());
+}
+
 TEST_F(ServiceWorkerTimeoutTimerTest, BecomeIdleAfterAbort) {
   EnableServicification();
 
diff --git a/content/renderer/service_worker/thread_safe_script_container.h b/content/renderer/service_worker/thread_safe_script_container.h
index 037a072..f7e055b 100644
--- a/content/renderer/service_worker/thread_safe_script_container.h
+++ b/content/renderer/service_worker/thread_safe_script_container.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef CONTENT_RENDERER_SERVICE_WORKER_THREAD_SAFE_SCRIPT_CONTAINER_H_
+#define CONTENT_RENDERER_SERVICE_WORKER_THREAD_SAFE_SCRIPT_CONTAINER_H_
+
 #include <map>
 #include <memory>
 
@@ -11,9 +14,6 @@
 #include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h"
 
-#ifndef CONTENT_RENDERER_SERVICE_WORKER_THREAD_SAFE_SCRIPT_CONTAINER_H_
-#define CONTENT_RENDERER_SERVICE_WORKER_THREAD_SAFE_SCRIPT_CONTAINER_H_
-
 namespace content {
 
 // ThreadSafeScriptContainer stores the scripts of a service worker for
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn
index 76dd3cd..07c210e 100644
--- a/content/shell/BUILD.gn
+++ b/content/shell/BUILD.gn
@@ -253,7 +253,6 @@
     "//device/bluetooth:fake_bluetooth",
     "//device/bluetooth:mocks",
     "//device/geolocation/public/cpp:test_support",
-    "//device/geolocation/public/interfaces",
     "//device/sensors/public/cpp:full",
     "//gin",
     "//gpu",
@@ -265,6 +264,7 @@
     "//net:test_support",
     "//ppapi/features",
     "//sandbox",
+    "//services/device/public/interfaces",
     "//services/service_manager/public/cpp",
     "//services/test/echo:lib",
     "//services/test/echo/public/interfaces",
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 6a80fc2..a8c2d15 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -315,7 +315,6 @@
     "//device/base/synchronization",
     "//device/geolocation",
     "//device/geolocation/public/cpp:test_support",
-    "//device/geolocation/public/interfaces",
     "//gpu/ipc:gl_in_process_context",
     "//ipc:test_support",
     "//media",
@@ -323,6 +322,7 @@
     "//media/capture/mojo:image_capture",
     "//mojo/edk/system",
     "//net:test_support",
+    "//services/device/public/interfaces",
     "//services/network:test_support",
     "//services/network/public/interfaces:interfaces",
     "//services/proxy_resolver:lib",
@@ -731,6 +731,7 @@
     "../browser/frame_host/render_frame_message_filter_browsertest.cc",
     "../browser/generic_sensor_browsertest.cc",
     "../browser/gpu/gpu_ipc_browsertests.cc",
+    "../browser/gpu/in_process_gpu_thread_browsertests.cc",
     "../browser/indexed_db/indexed_db_browsertest.cc",
     "../browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc",
     "../browser/indexed_db/mock_browsertest_indexed_db_class_factory.h",
@@ -862,6 +863,7 @@
     "//content/public/browser",
     "//content/public/child",
     "//content/public/common",
+    "//content/public/gpu:gpu_sources",
     "//content/public/renderer",
     "//content/renderer:for_content_tests",
     "//content/shell:content_shell_lib",
@@ -960,6 +962,12 @@
     ]
   }
 
+  # FIXME: Workaround for link errors on win_chromium_compile_dbg_ng.
+  if (is_win) {
+    deps -= [ "//content/public/gpu:gpu_sources" ]
+    sources -= [ "../browser/gpu/in_process_gpu_thread_browsertests.cc" ]
+  }
+
   if (is_win) {
     sources += [ "../browser/accessibility/accessibility_win_browsertest.cc" ]
 
@@ -1514,6 +1522,7 @@
     "../common/throttling_url_loader_unittest.cc",
     "../common/unique_name_helper_unittest.cc",
     "../common/webplugininfo_unittest.cc",
+    "../network/cors/cors_url_loader_unittest.cc",
     "../network/data_pipe_element_reader_unittest.cc",
     "../network/network_change_manager_unittest.cc",
     "../network/network_context_unittest.cc",
@@ -1554,7 +1563,6 @@
     "../renderer/indexed_db/webidbdatabase_impl_unittest.cc",
     "../renderer/input/input_event_filter_unittest.cc",
     "../renderer/input/main_thread_event_queue_unittest.cc",
-    "../renderer/loader/cors_url_loader_unittest.cc",
     "../renderer/loader/resource_dispatcher_unittest.cc",
     "../renderer/loader/shared_memory_data_consumer_handle_unittest.cc",
     "../renderer/loader/site_isolation_stats_gatherer_unittest.cc",
@@ -1680,7 +1688,6 @@
     "//device/gamepad:test_helpers",
     "//device/gamepad/public/cpp:shared_with_blink",
     "//device/geolocation",
-    "//device/geolocation/public/interfaces",
     "//device/screen_orientation/public/interfaces",
     "//device/sensors/public/cpp:full",
     "//device/sensors/public/interfaces",
@@ -1705,6 +1712,7 @@
     "//printing",
     "//services/catalog:lib",
     "//services/device/public/cpp/generic_sensor",
+    "//services/device/public/interfaces",
     "//services/file:lib",
     "//services/file/public/interfaces",
     "//services/metrics/public/interfaces",
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index 52e8670..9e56471 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -84,6 +84,10 @@
       std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories)
       override {}
 
+  void UpdateSubresourceLoaderFactories(
+      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders)
+      override{};
+
  private:
   TestRenderFrameHost* const frame_host_;
 
diff --git a/device/bluetooth/bluetooth_adapter.h b/device/bluetooth/bluetooth_adapter.h
index 58db9c8..cba14a43 100644
--- a/device/bluetooth/bluetooth_adapter.h
+++ b/device/bluetooth/bluetooth_adapter.h
@@ -337,6 +337,7 @@
   // Requests a change to the adapter radio power. Setting |powered| to true
   // will turn on the radio and false will turn it off. On success, |callback|
   // will be called. On failure, |error_callback| will be called.
+  // On macOS this is only supported if low energy is available.
   virtual void SetPowered(bool powered,
                           const base::Closure& callback,
                           const ErrorCallback& error_callback) = 0;
diff --git a/device/bluetooth/bluetooth_adapter_mac.h b/device/bluetooth/bluetooth_adapter_mac.h
index fae1f018..9960bd3 100644
--- a/device/bluetooth/bluetooth_adapter_mac.h
+++ b/device/bluetooth/bluetooth_adapter_mac.h
@@ -131,6 +131,20 @@
       device::BluetoothDevice::PairingDelegate* pairing_delegate) override;
 
  private:
+  // Type of the underlying implementation of SetPowered(). It takes an int
+  // instead of a bool, since the production code calls into a C API that does
+  // not know about bool.
+  using SetControllerPowerStateFunction = base::RepeatingCallback<void(int)>;
+
+  struct SetPoweredCallbacks {
+    SetPoweredCallbacks();
+    ~SetPoweredCallbacks();
+
+    bool powered = false;
+    base::OnceClosure callback;
+    ErrorCallback error_callback;
+  };
+
   // Resets |low_energy_central_manager_| to |central_manager| and sets
   // |low_energy_central_manager_delegate_| as the manager's delegate. Should
   // be called only when |IsLowEnergyAvailable()|.
@@ -139,6 +153,10 @@
   // Returns the CBCentralManager instance.
   CBCentralManager* GetCentralManager();
 
+  // Allow the mocking out of setting the controller power state for testing.
+  void SetPowerStateFunctionForTesting(
+      SetControllerPowerStateFunction power_state_function);
+
   // The length of time that must elapse since the last Inquiry response (on
   // Classic devices) or call to BluetoothLowEnergyDevice::Update() (on Low
   // Energy) before a discovered device is considered to be no longer available.
@@ -177,6 +195,10 @@
   // connected to the local host.
   void ClassicDeviceAdded(IOBluetoothDevice* device);
 
+  // Checks if the low energy central manager is powered on. Returns false if
+  // BLE is not available.
+  bool IsLowEnergyPowered() const;
+
   // BluetoothLowEnergyDiscoveryManagerMac::Observer override:
   void LowEnergyDeviceUpdated(CBPeripheral* peripheral,
                               NSDictionary* advertisement_data,
@@ -207,6 +229,10 @@
   bool classic_powered_;
   int num_discovery_sessions_;
 
+  // SetPowered() implementation and callbacks.
+  SetControllerPowerStateFunction power_state_function_;
+  std::unique_ptr<SetPoweredCallbacks> set_powered_callbacks_;
+
   // Cached name. Updated in GetName if should_update_name_ is true.
   //
   // For performance reasons, cache the adapter's name. It's not uncommon for
diff --git a/device/bluetooth/bluetooth_adapter_mac.mm b/device/bluetooth/bluetooth_adapter_mac.mm
index 9384b8f..7c2afee 100644
--- a/device/bluetooth/bluetooth_adapter_mac.mm
+++ b/device/bluetooth/bluetooth_adapter_mac.mm
@@ -10,6 +10,7 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/compiler_specific.h"
@@ -18,6 +19,7 @@
 #include "base/mac/mac_util.h"
 #include "base/mac/sdk_forward_declarations.h"
 #include "base/memory/ptr_util.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/sys_string_conversions.h"
@@ -31,6 +33,20 @@
 #include "device/bluetooth/bluetooth_low_energy_central_manager_delegate.h"
 #include "device/bluetooth/bluetooth_socket_mac.h"
 
+extern "C" {
+// Undocumented IOBluetooth Preference API [1]. Used by `blueutil` [2] and
+// `Karabiner` [3] to programmatically control the Bluetooth state. Calling the
+// method with `1` powers the adapter on, calling it with `0` powers it off.
+// Using this API has the same effect as turning Bluetooth on or off using the
+// macOS System Preferences [4], and will effect all adapters.
+//
+// [1] https://goo.gl/Gbjm1x
+// [2] http://www.frederikseiffert.de/blueutil/
+// [3] https://pqrs.org/osx/karabiner/
+// [4] https://support.apple.com/kb/PH25091
+void IOBluetoothPreferenceSetControllerPowerState(int state);
+}
+
 namespace {
 
 // The frequency with which to poll the adapter for updates.
@@ -100,6 +116,8 @@
     : BluetoothAdapter(),
       classic_powered_(false),
       num_discovery_sessions_(0),
+      power_state_function_(
+          base::BindRepeating(IOBluetoothPreferenceSetControllerPowerState)),
       should_update_name_(true),
       classic_discovery_manager_(
           BluetoothDiscoveryManagerMac::CreateClassic(this)),
@@ -129,6 +147,11 @@
   // while being destroyed after this method. |devices_| is owned by
   // BluetoothAdapter.
   low_energy_central_manager_.reset();
+
+  // If there's a pending powered request, run its error callback.
+  if (set_powered_callbacks_) {
+    set_powered_callbacks_->error_callback.Run();
+  }
 }
 
 std::string BluetoothAdapterMac::GetAddress() const {
@@ -174,19 +197,34 @@
 }
 
 bool BluetoothAdapterMac::IsPowered() const {
-  bool is_powered = classic_powered_;
-  if (IsLowEnergyAvailable()) {
-    is_powered =
-        is_powered || (GetCBManagerState(low_energy_central_manager_) ==
-                       CBCentralManagerStatePoweredOn);
-  }
-  return is_powered;
+  return classic_powered_ || IsLowEnergyPowered();
 }
 
 void BluetoothAdapterMac::SetPowered(bool powered,
                                      const base::Closure& callback,
                                      const ErrorCallback& error_callback) {
-  NOTIMPLEMENTED();
+  if (!IsLowEnergyAvailable()) {
+    // macOS APIs for this method are only available when BLE is available.
+    ui_task_runner_->PostTask(FROM_HERE, error_callback);
+    return;
+  }
+
+  if (set_powered_callbacks_) {
+    // Only allow one pending callback at a time.
+    ui_task_runner_->PostTask(FROM_HERE, error_callback);
+    return;
+  }
+
+  if (powered == IsLowEnergyPowered()) {
+    ui_task_runner_->PostTask(FROM_HERE, callback);
+    return;
+  }
+
+  set_powered_callbacks_ = std::make_unique<SetPoweredCallbacks>();
+  set_powered_callbacks_->powered = powered;
+  set_powered_callbacks_->callback = callback;
+  set_powered_callbacks_->error_callback = error_callback;
+  power_state_function_.Run(base::strict_cast<int>(powered));
 }
 
 // TODO(krstnmnlsn): If this information is retrievable form IOBluetooth we
@@ -301,6 +339,9 @@
 void BluetoothAdapterMac::RemovePairingDelegateInternal(
     BluetoothDevice::PairingDelegate* pairing_delegate) {}
 
+BluetoothAdapterMac::SetPoweredCallbacks::SetPoweredCallbacks() = default;
+BluetoothAdapterMac::SetPoweredCallbacks::~SetPoweredCallbacks() = default;
+
 void BluetoothAdapterMac::SetCentralManagerForTesting(
     CBCentralManager* central_manager) {
   CHECK(BluetoothAdapterMac::IsLowEnergyAvailable());
@@ -314,6 +355,11 @@
   return low_energy_central_manager_;
 }
 
+void BluetoothAdapterMac::SetPowerStateFunctionForTesting(
+    SetControllerPowerStateFunction power_state_function) {
+  power_state_function_ = std::move(power_state_function);
+}
+
 void BluetoothAdapterMac::AddDiscoverySession(
     BluetoothDiscoveryFilter* discovery_filter,
     const base::Closure& callback,
@@ -501,6 +547,15 @@
     observer.DeviceAdded(this, device_classic);
 }
 
+bool BluetoothAdapterMac::IsLowEnergyPowered() const {
+  if (!IsLowEnergyAvailable()) {
+    return false;
+  }
+
+  return GetCBManagerState(low_energy_central_manager_) ==
+         CBCentralManagerStatePoweredOn;
+}
+
 void BluetoothAdapterMac::LowEnergyDeviceUpdated(
     CBPeripheral* peripheral,
     NSDictionary* advertisement_data,
@@ -601,6 +656,18 @@
 void BluetoothAdapterMac::LowEnergyCentralManagerUpdatedState() {
   VLOG(1) << "Central manager state updated: "
           << [low_energy_central_manager_ state];
+
+  if (set_powered_callbacks_) {
+    // Move into a local variable to clear out both callbacks at the end of the
+    // scope and to allow scheduling another SetPowered() call in either of the
+    // callbacks.
+    std::unique_ptr<SetPoweredCallbacks> callbacks =
+        std::move(set_powered_callbacks_);
+    callbacks->powered == IsLowEnergyPowered()
+        ? std::move(callbacks->callback).Run()
+        : callbacks->error_callback.Run();
+  }
+
   // A state with a value lower than CBCentralManagerStatePoweredOn implies that
   // scanning has stopped and that any connected peripherals have been
   // disconnected. Call DidDisconnectPeripheral manually to update the devices'
diff --git a/device/bluetooth/bluetooth_adapter_mac_unittest.mm b/device/bluetooth/bluetooth_adapter_mac_unittest.mm
index c4a2b60..efe8ab6 100644
--- a/device/bluetooth/bluetooth_adapter_mac_unittest.mm
+++ b/device/bluetooth/bluetooth_adapter_mac_unittest.mm
@@ -29,6 +29,12 @@
 #import <IOBluetooth/IOBluetooth.h>
 #endif  // defined(OS_IOS)
 
+// List of undocumented IOBluetooth APIs used for BluetoothAdapterMac.
+extern "C" {
+int IOBluetoothPreferenceGetControllerPowerState();
+void IOBluetoothPreferenceSetControllerPowerState(int state);
+}
+
 namespace {
 // |kTestHashAddress| is the hash corresponding to identifier |kTestNSUUID|.
 const char kTestNSUUID[] = "00000000-1111-2222-3333-444444444444";
@@ -142,6 +148,15 @@
   int error_callback_count_;
 };
 
+// Test if private IOBluetooth APIs are callable on all supported macOS
+// versions.
+TEST_F(BluetoothAdapterMacTest, IOBluetoothPrivateAPIs) {
+  // Obtain current power state, toggle it, and reset it to it's original value.
+  int previous_state = IOBluetoothPreferenceGetControllerPowerState();
+  IOBluetoothPreferenceSetControllerPowerState(!previous_state);
+  IOBluetoothPreferenceSetControllerPowerState(previous_state);
+}
+
 TEST_F(BluetoothAdapterMacTest, Poll) {
   PollAdapter();
   EXPECT_TRUE(ui_task_runner_->HasPendingTask());
diff --git a/device/bluetooth/bluetooth_adapter_unittest.cc b/device/bluetooth/bluetooth_adapter_unittest.cc
index 097a9ec..857972f4 100644
--- a/device/bluetooth/bluetooth_adapter_unittest.cc
+++ b/device/bluetooth/bluetooth_adapter_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
 #include "build/build_config.h"
 #include "device/bluetooth/bluetooth_common.h"
 #include "device/bluetooth/bluetooth_device.h"
@@ -685,8 +686,20 @@
 }
 #endif  // defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN)
 
-#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
-TEST_F(BluetoothTest, TogglePowerFakeAdapter) {
+// TODO(https://crbug.com/804356): Enable this test on Windows as well.
+#if defined(OS_WIN)
+#define MAYBE_TogglePowerFakeAdapter DISABLED_TogglePowerFakeAdapter
+#else
+#define MAYBE_TogglePowerFakeAdapter TogglePowerFakeAdapter
+#endif
+TEST_F(BluetoothTest, MAYBE_TogglePowerFakeAdapter) {
+#if defined(OS_MACOSX)
+  if (!PlatformSupportsLowEnergy()) {
+    LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+    return;
+  }
+#endif  // defined(OS_MACOSX)
+
   InitWithFakeAdapter();
   TestBluetoothAdapterObserver observer(adapter_);
 
@@ -697,16 +710,155 @@
   // Check if power can be turned off.
   adapter_->SetPowered(false, GetCallback(Call::EXPECTED),
                        GetErrorCallback(Call::NOT_EXPECTED));
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_FALSE(adapter_->IsPowered());
   EXPECT_EQ(1, observer.powered_changed_count());
 
   // Check if power can be turned on again.
   adapter_->SetPowered(true, GetCallback(Call::EXPECTED),
                        GetErrorCallback(Call::NOT_EXPECTED));
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(adapter_->IsPowered());
   EXPECT_EQ(2, observer.powered_changed_count());
 }
-#endif  // defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
+
+#if defined(OS_MACOSX)
+// The following tests should be implemented on Android as well once pending
+// SetPowered() callbacks are stored (https://crbug.com/803105). These tests are
+// not relevant for BlueZ and Windows. On these platforms the corresponding
+// system APIs are blocking or use callbacks, so that it is not necessary to
+// store pending callbacks and wait for the appropriate events.
+TEST_F(BluetoothTest, TogglePowerFakeAdapter_Twice) {
+  if (!PlatformSupportsLowEnergy()) {
+    LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+    return;
+  }
+
+  InitWithFakeAdapter();
+  TestBluetoothAdapterObserver observer(adapter_);
+
+  ASSERT_TRUE(adapter_->IsPresent());
+  ASSERT_TRUE(adapter_->IsPowered());
+  EXPECT_EQ(0, observer.powered_changed_count());
+
+  // Post two pending turn off requests, the second should fail due to the
+  // presence of another callback.
+  adapter_->SetPowered(false, GetCallback(Call::EXPECTED),
+                       GetErrorCallback(Call::NOT_EXPECTED));
+  adapter_->SetPowered(false, GetCallback(Call::NOT_EXPECTED),
+                       GetErrorCallback(Call::EXPECTED));
+  scoped_task_environment_.RunUntilIdle();
+  EXPECT_FALSE(adapter_->IsPowered());
+  EXPECT_EQ(1, observer.powered_changed_count());
+
+  // Post two pending turn on requests, the second should fail due to the
+  // presence of another callback.
+  adapter_->SetPowered(true, GetCallback(Call::EXPECTED),
+                       GetErrorCallback(Call::NOT_EXPECTED));
+  adapter_->SetPowered(true, GetCallback(Call::NOT_EXPECTED),
+                       GetErrorCallback(Call::EXPECTED));
+  scoped_task_environment_.RunUntilIdle();
+  EXPECT_TRUE(adapter_->IsPowered());
+  EXPECT_EQ(2, observer.powered_changed_count());
+}
+
+TEST_F(BluetoothTest, TogglePowerFakeAdapter_WithinCallback_On_Off) {
+  if (!PlatformSupportsLowEnergy()) {
+    LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+    return;
+  }
+
+  InitWithFakeAdapter();
+  TestBluetoothAdapterObserver observer(adapter_);
+
+  ASSERT_TRUE(adapter_->IsPresent());
+  ASSERT_TRUE(adapter_->IsPowered());
+  EXPECT_EQ(0, observer.powered_changed_count());
+
+  // Turn adapter off, while powering it on in the callback.
+  adapter_->SetPowered(false, base::BindLambdaForTesting([&] {
+                         adapter_->SetPowered(
+                             true, GetCallback(Call::EXPECTED),
+                             GetErrorCallback(Call::NOT_EXPECTED));
+                       }),
+                       GetErrorCallback(Call::NOT_EXPECTED));
+  scoped_task_environment_.RunUntilIdle();
+  EXPECT_TRUE(adapter_->IsPowered());
+  EXPECT_EQ(2, observer.powered_changed_count());
+}
+
+TEST_F(BluetoothTest, TogglePowerFakeAdapter_WithinCallback_Off_On) {
+  if (!PlatformSupportsLowEnergy()) {
+    LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+    return;
+  }
+
+  InitWithFakeAdapter();
+  TestBluetoothAdapterObserver observer(adapter_);
+
+  ASSERT_TRUE(adapter_->IsPresent());
+  ASSERT_TRUE(adapter_->IsPowered());
+  EXPECT_EQ(0, observer.powered_changed_count());
+
+  // Turn power off.
+  adapter_->SetPowered(false, GetCallback(Call::EXPECTED),
+                       GetErrorCallback(Call::NOT_EXPECTED));
+  scoped_task_environment_.RunUntilIdle();
+  EXPECT_FALSE(adapter_->IsPowered());
+  EXPECT_EQ(1, observer.powered_changed_count());
+
+  // Turn adapter on, while powering it off in the callback.
+  adapter_->SetPowered(true, base::BindLambdaForTesting([&] {
+                         adapter_->SetPowered(
+                             false, GetCallback(Call::EXPECTED),
+                             GetErrorCallback(Call::NOT_EXPECTED));
+                       }),
+                       GetErrorCallback(Call::NOT_EXPECTED));
+  scoped_task_environment_.RunUntilIdle();
+  EXPECT_FALSE(adapter_->IsPowered());
+  EXPECT_EQ(3, observer.powered_changed_count());
+}
+
+TEST_F(BluetoothTest, TogglePowerFakeAdapter_DestroyWithPending) {
+  if (!PlatformSupportsLowEnergy()) {
+    LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+    return;
+  }
+
+  InitWithFakeAdapter();
+  ASSERT_TRUE(adapter_->IsPresent());
+  ASSERT_TRUE(adapter_->IsPowered());
+
+  // Schedule pending power off request and cause destruction of the adapter by
+  // dropping the reference count to 0. Note that we are intentionally not using
+  // a TestBluetoothAdapterObserver, as this would hold another reference to the
+  // adapter and thus interfere with the intended destruction.
+  // We expect the error callback to be invoked, and any other subsequent calls
+  // to SetPowered() should fail as well.
+  bool error_callback_called = false;
+  BluetoothAdapter* adapter = adapter_.get();
+  adapter->SetPowered(
+      false, GetCallback(Call::NOT_EXPECTED),
+      base::BindLambdaForTesting(
+          // Note that we explicitly need to capture a pointer to the
+          // underlying adapter, even though we pass |this| implicitly. This is
+          // because by the time this callback is invoked, |adapter_| is already
+          // set to null, but the pointed to adapter instance is still alive. So
+          // using the pointer is safe, but dereferencing |adapter_| crashes.
+          [&] {
+            error_callback_called = true;
+            adapter->SetPowered(false, GetCallback(Call::NOT_EXPECTED),
+                                GetErrorCallback(Call::EXPECTED));
+            adapter->SetPowered(true, GetCallback(Call::NOT_EXPECTED),
+                                GetErrorCallback(Call::EXPECTED));
+          }));
+
+  adapter_ = nullptr;
+  // Empty the message loop to make sure posted callbacks get run.
+  scoped_task_environment_.RunUntilIdle();
+  EXPECT_TRUE(error_callback_called);
+}
+#endif  // defined(OS_MACOSX)
 
 #if defined(OS_ANDROID)
 TEST_F(BluetoothTest, TogglePowerBeforeScan) {
diff --git a/device/bluetooth/test/bluetooth_test_mac.h b/device/bluetooth/test/bluetooth_test_mac.h
index 4db9998..6ea1428 100644
--- a/device/bluetooth/test/bluetooth_test_mac.h
+++ b/device/bluetooth/test/bluetooth_test_mac.h
@@ -128,6 +128,10 @@
       BluetoothRemoteGattDescriptor* descriptor,
       short value);
 
+  // Sets the power state of the mock controller to |powered|. Used to override
+  // BluetoothAdapterMac's SetControllerPowerStateFunction.
+  void SetMockControllerPowerState(int powered);
+
   // Adds services in MockCBPeripheral.
   void AddServicesToDeviceMac(BluetoothDevice* device,
                               const std::vector<std::string>& uuids);
diff --git a/device/bluetooth/test/bluetooth_test_mac.mm b/device/bluetooth/test/bluetooth_test_mac.mm
index dd52798..3c806a6 100644
--- a/device/bluetooth/test/bluetooth_test_mac.mm
+++ b/device/bluetooth/test/bluetooth_test_mac.mm
@@ -7,6 +7,7 @@
 #import <CoreBluetooth/CoreBluetooth.h>
 #include <stdint.h>
 
+#include "base/bind.h"
 #import "base/mac/foundation_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/sys_string_conversions.h"
@@ -137,6 +138,9 @@
     mock_central_manager_->get().bluetoothTestMac = this;
     [mock_central_manager_->get() setState:CBCentralManagerStatePoweredOn];
     adapter_mac_->SetCentralManagerForTesting((id)mock_central_manager_->get());
+    adapter_mac_->SetPowerStateFunctionForTesting(
+        base::BindRepeating(&BluetoothTestMac::SetMockControllerPowerState,
+                            base::Unretained(this)));
   }
 }
 
@@ -562,6 +566,33 @@
   [GetCBMockDescriptor(descriptor) simulateReadWithValue:number error:nil];
 }
 
+void BluetoothTestMac::SetMockControllerPowerState(int powered) {
+  // We are posting a task so that the state only gets updated in the next cycle
+  // and pending callbacks are not executed immediately.
+  adapter_mac_->ui_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          [](base::WeakPtr<BluetoothAdapterMac> adapter_mac, int powered) {
+            // Guard against deletion of the adapter.
+            if (!adapter_mac)
+              return;
+
+            auto* mock_central_manager =
+                base::mac::ObjCCastStrict<MockCentralManager>(
+                    adapter_mac->GetCentralManager());
+            [mock_central_manager
+                setState:powered ? CBCentralManagerStatePoweredOn
+                                 : CBCentralManagerStatePoweredOff];
+            [mock_central_manager.delegate
+                centralManagerDidUpdateState:adapter_mac->GetCentralManager()];
+            // On real devices, the Bluetooth classic code will dispatch the
+            // AdapterPoweredChanged event. Test code does not fake Bluetooth
+            // classic behavior so we dispatch the event directly.
+            adapter_mac->NotifyAdapterPoweredChanged(powered);
+          },
+          adapter_mac_->weak_ptr_factory_.GetWeakPtr(), powered));
+}
+
 void BluetoothTest::AddServicesToDeviceMac(
     BluetoothDevice* device,
     const std::vector<std::string>& uuids) {
diff --git a/device/geolocation/BUILD.gn b/device/geolocation/BUILD.gn
index 65dfbb8..7f7e42f1 100644
--- a/device/geolocation/BUILD.gn
+++ b/device/geolocation/BUILD.gn
@@ -66,7 +66,6 @@
   ]
   public_deps = [
     "//device/geolocation/public/cpp",
-    "//device/geolocation/public/interfaces",
     "//services/device/public/interfaces",
   ]
   if (is_android) {
@@ -183,8 +182,8 @@
     "//base",
     "//base/third_party/dynamic_annotations",
     "//device/geolocation/public/cpp",
-    "//device/geolocation/public/interfaces",
     "//net:test_support",
+    "//services/device/public/interfaces",
     "//testing/gmock",
     "//testing/gtest",
   ]
diff --git a/device/geolocation/fake_location_provider.h b/device/geolocation/fake_location_provider.h
index da73590..c8fdaf2 100644
--- a/device/geolocation/fake_location_provider.h
+++ b/device/geolocation/fake_location_provider.h
@@ -11,7 +11,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
 #include "device/geolocation/public/cpp/location_provider.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 
 namespace device {
 
diff --git a/device/geolocation/geolocation_context.h b/device/geolocation/geolocation_context.h
index 1f78d6ab..d032636 100644
--- a/device/geolocation/geolocation_context.h
+++ b/device/geolocation/geolocation_context.h
@@ -10,9 +10,9 @@
 
 #include "base/macros.h"
 #include "device/geolocation/geolocation_export.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
+#include "services/device/public/interfaces/geolocation.mojom.h"
 #include "services/device/public/interfaces/geolocation_context.mojom.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 
 namespace device {
 
diff --git a/device/geolocation/geolocation_impl.h b/device/geolocation/geolocation_impl.h
index 260b409d..0036ba68 100644
--- a/device/geolocation/geolocation_impl.h
+++ b/device/geolocation/geolocation_impl.h
@@ -6,8 +6,8 @@
 
 #include "base/macros.h"
 #include "device/geolocation/geolocation_provider_impl.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "services/device/public/interfaces/geolocation.mojom.h"
 
 #ifndef DEVICE_GEOLOCATION_GEOLOCATION_IMPL_H_
 #define DEVICE_GEOLOCATION_GEOLOCATION_IMPL_H_
diff --git a/device/geolocation/geolocation_provider.h b/device/geolocation/geolocation_provider.h
index 385736d..04e4ea58 100644
--- a/device/geolocation/geolocation_provider.h
+++ b/device/geolocation/geolocation_provider.h
@@ -9,8 +9,8 @@
 
 #include "base/callback_list.h"
 #include "device/geolocation/geolocation_export.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 
 namespace device {
 
diff --git a/device/geolocation/geolocation_provider_impl.h b/device/geolocation/geolocation_provider_impl.h
index 44fcf66..8cd197ca 100644
--- a/device/geolocation/geolocation_provider_impl.h
+++ b/device/geolocation/geolocation_provider_impl.h
@@ -16,9 +16,9 @@
 #include "device/geolocation/geolocation_export.h"
 #include "device/geolocation/geolocation_provider.h"
 #include "device/geolocation/public/cpp/location_provider.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/device/public/interfaces/geolocation_control.mojom.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 
 namespace base {
 template <typename Type>
diff --git a/device/geolocation/location_api_adapter_android.h b/device/geolocation/location_api_adapter_android.h
index 39b0332..51c310d6 100644
--- a/device/geolocation/location_api_adapter_android.h
+++ b/device/geolocation/location_api_adapter_android.h
@@ -11,7 +11,7 @@
 #include "base/memory/singleton.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread_checker.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 
 namespace base {
 class SingleThreadTaskRunner;
diff --git a/device/geolocation/location_arbitrator.h b/device/geolocation/location_arbitrator.h
index ce92eb5..e2fed53 100644
--- a/device/geolocation/location_arbitrator.h
+++ b/device/geolocation/location_arbitrator.h
@@ -17,8 +17,8 @@
 #include "device/geolocation/geolocation_export.h"
 #include "device/geolocation/geolocation_provider_impl.h"
 #include "device/geolocation/public/cpp/location_provider.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 #include "url/gurl.h"
 
 namespace net {
diff --git a/device/geolocation/location_arbitrator_unittest.cc b/device/geolocation/location_arbitrator_unittest.cc
index 4a3aa61..db75d15 100644
--- a/device/geolocation/location_arbitrator_unittest.cc
+++ b/device/geolocation/location_arbitrator_unittest.cc
@@ -13,8 +13,8 @@
 #include "device/geolocation/fake_location_provider.h"
 #include "device/geolocation/public/cpp/geoposition.h"
 #include "device/geolocation/public/cpp/location_provider.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "net/url_request/url_request_test_util.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/device/geolocation/location_provider_android.h b/device/geolocation/location_provider_android.h
index 8a02230..4db253fd 100644
--- a/device/geolocation/location_provider_android.h
+++ b/device/geolocation/location_provider_android.h
@@ -9,7 +9,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "device/geolocation/public/cpp/location_provider.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 
 namespace device {
 
diff --git a/device/geolocation/network_location_provider.h b/device/geolocation/network_location_provider.h
index 2cb7464..57a4920 100644
--- a/device/geolocation/network_location_provider.h
+++ b/device/geolocation/network_location_provider.h
@@ -20,8 +20,8 @@
 #include "device/geolocation/geolocation_export.h"
 #include "device/geolocation/network_location_request.h"
 #include "device/geolocation/public/cpp/location_provider.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "device/geolocation/wifi_data_provider_manager.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 
 namespace device {
 
diff --git a/device/geolocation/network_location_request.h b/device/geolocation/network_location_request.h
index 10ae8e01..1920e243 100644
--- a/device/geolocation/network_location_request.h
+++ b/device/geolocation/network_location_request.h
@@ -12,9 +12,9 @@
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
 #include "device/geolocation/geolocation_export.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "device/geolocation/wifi_data_provider.h"
 #include "net/url_request/url_fetcher_delegate.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 #include "url/gurl.h"
 
 namespace net {
diff --git a/device/geolocation/public/cpp/BUILD.gn b/device/geolocation/public/cpp/BUILD.gn
index 99ab306..58dc2eb 100644
--- a/device/geolocation/public/cpp/BUILD.gn
+++ b/device/geolocation/public/cpp/BUILD.gn
@@ -10,7 +10,7 @@
   ]
 
   public_deps = [
-    "//device/geolocation/public/interfaces",
+    "//services/device/public/interfaces",
   ]
 }
 
@@ -24,7 +24,6 @@
 
   deps = [
     ":cpp",
-    "//services/device/public/interfaces",
     "//services/service_manager/public/cpp",
   ]
 }
diff --git a/device/geolocation/public/cpp/geoposition.h b/device/geolocation/public/cpp/geoposition.h
index e559e37a..d22f8a7 100644
--- a/device/geolocation/public/cpp/geoposition.h
+++ b/device/geolocation/public/cpp/geoposition.h
@@ -5,7 +5,7 @@
 #ifndef DEVICE_GEOLOCATION_PUBLIC_CPP_GEOPOSITION_H_
 #define DEVICE_GEOLOCATION_PUBLIC_CPP_GEOPOSITION_H_
 
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 
 namespace device {
 
diff --git a/device/geolocation/public/cpp/location_provider.h b/device/geolocation/public/cpp/location_provider.h
index 9c113e9a..7e97c9b 100644
--- a/device/geolocation/public/cpp/location_provider.h
+++ b/device/geolocation/public/cpp/location_provider.h
@@ -7,7 +7,7 @@
 
 #include "base/callback.h"
 #include "base/compiler_specific.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 
 namespace device {
 
diff --git a/device/geolocation/public/cpp/scoped_geolocation_overrider.h b/device/geolocation/public/cpp/scoped_geolocation_overrider.h
index f48327e..1dc6739d 100644
--- a/device/geolocation/public/cpp/scoped_geolocation_overrider.h
+++ b/device/geolocation/public/cpp/scoped_geolocation_overrider.h
@@ -6,11 +6,11 @@
 #define DEVICE_GEOLOCATION_PUBLIC_CPP_SCOPED_GEOLOCATION_OVERRIDER_H_
 
 #include "base/bind.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/device/public/interfaces/geolocation.mojom.h"
 #include "services/device/public/interfaces/geolocation_context.mojom.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 #include "services/service_manager/public/cpp/bind_source_info.h"
 
 namespace device {
diff --git a/device/geolocation/public/interfaces/BUILD.gn b/device/geolocation/public/interfaces/BUILD.gn
deleted file mode 100644
index b62ac9d..0000000
--- a/device/geolocation/public/interfaces/BUILD.gn
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//mojo/public/tools/bindings/mojom.gni")
-
-mojom("interfaces") {
-  sources = [
-    "geolocation.mojom",
-    "geoposition.mojom",
-  ]
-  public_deps = [
-    "//mojo/common:common_custom_types",
-  ]
-}
diff --git a/device/geolocation/public/interfaces/OWNERS b/device/geolocation/public/interfaces/OWNERS
deleted file mode 100644
index 08850f4..0000000
--- a/device/geolocation/public/interfaces/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-per-file *.mojom=set noparent
-per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index 7a106d31..24f41ae 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -254,6 +254,8 @@
     "image_loader.h",
     "image_loader_factory.cc",
     "image_loader_factory.h",
+    "image_sanitizer.cc",
+    "image_sanitizer.h",
     "info_map.cc",
     "info_map.h",
     "install_flag.h",
@@ -550,6 +552,7 @@
     "file_highlighter_unittest.cc",
     "file_reader_unittest.cc",
     "image_loader_unittest.cc",
+    "image_sanitizer_unittest.cc",
     "info_map_unittest.cc",
     "lazy_background_task_queue_unittest.cc",
     "load_monitoring_extension_host_queue_unittest.cc",
diff --git a/extensions/browser/DEPS b/extensions/browser/DEPS
index bde65cb..64eb946 100644
--- a/extensions/browser/DEPS
+++ b/extensions/browser/DEPS
@@ -23,7 +23,7 @@
   "+net",
   # This directory contains build flags and does not pull all of PPAPI in.
   "+ppapi/features",
-  "+services/data_decoder/public/cpp",
+  "+services/data_decoder/public",
   "+services/network/public/cpp",
   "+services/network/public/interfaces",
   "+services/preferences/public/cpp",
diff --git a/extensions/browser/image_sanitizer.cc b/extensions/browser/image_sanitizer.cc
new file mode 100644
index 0000000..886ad701
--- /dev/null
+++ b/extensions/browser/image_sanitizer.cc
@@ -0,0 +1,220 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/image_sanitizer.h"
+
+#include "base/files/file_util.h"
+#include "base/task_runner_util.h"
+#include "extensions/browser/extension_file_task_runner.h"
+#include "extensions/common/extension_resource_path_normalizer.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "ui/gfx/codec/png_codec.h"
+
+namespace extensions {
+
+namespace {
+
+// We don't expect icons and other extension's images to be big.
+// We use this limit to prevent from opening too large images.
+const int kMaxImageCanvas = 4096 * 4096;  // 16MB
+
+// Reads the file in |path| and then deletes it.
+// Returns a tuple containing: the file content, whether the read was
+// successful, whether the delete was successful.
+std::tuple<std::vector<uint8_t>, bool, bool> ReadAndDeleteFile(
+    const base::FilePath& path) {
+  std::vector<uint8_t> contents;
+  bool read_success = false;
+  int64_t file_size;
+  if (base::GetFileSize(path, &file_size)) {
+    contents.resize(file_size);
+    read_success = base::ReadFile(
+        path, reinterpret_cast<char*>(contents.data()), file_size);
+  }
+  bool delete_success = base::DeleteFile(path, /*recursive=*/false);
+  return std::make_tuple(std::move(contents), read_success, delete_success);
+}
+
+std::pair<bool, std::vector<unsigned char>> EncodeImage(const SkBitmap& image) {
+  std::vector<unsigned char> image_data;
+  bool success = gfx::PNGCodec::EncodeBGRASkBitmap(
+      image,
+      /*discard_transparency=*/false, &image_data);
+  return std::make_pair(success, std::move(image_data));
+}
+
+int WriteFile(const base::FilePath& path,
+              const std::vector<unsigned char>& data) {
+  return base::WriteFile(path, reinterpret_cast<const char*>(data.data()),
+                         base::checked_cast<int>(data.size()));
+}
+
+}  // namespace
+
+// static
+std::unique_ptr<ImageSanitizer> ImageSanitizer::CreateAndStart(
+    service_manager::Connector* connector,
+    const service_manager::Identity& identity,
+    const base::FilePath& image_dir,
+    const std::set<base::FilePath>& image_paths,
+    ImageDecodedCallback image_decoded_callback,
+    SanitizationDoneCallback done_callback) {
+  std::unique_ptr<ImageSanitizer> sanitizer(new ImageSanitizer(
+      image_dir, image_paths, std::move(image_decoded_callback),
+      std::move(done_callback)));
+  sanitizer->Start(connector, identity);
+  return sanitizer;
+}
+
+ImageSanitizer::ImageSanitizer(
+    const base::FilePath& image_dir,
+    const std::set<base::FilePath>& image_relative_paths,
+    ImageDecodedCallback image_decoded_callback,
+    SanitizationDoneCallback done_callback)
+    : image_dir_(image_dir),
+      image_paths_(image_relative_paths),
+      image_decoded_callback_(std::move(image_decoded_callback)),
+      done_callback_(std::move(done_callback)),
+      weak_factory_(this) {}
+
+ImageSanitizer::~ImageSanitizer() = default;
+
+void ImageSanitizer::Start(service_manager::Connector* connector,
+                           const service_manager::Identity& identity) {
+  if (image_paths_.empty()) {
+    base::SequencedTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(&ImageSanitizer::ReportSuccess,
+                                  weak_factory_.GetWeakPtr()));
+    return;
+  }
+
+  connector->BindInterface(identity, &image_decoder_ptr_);
+
+  std::set<base::FilePath> normalized_image_paths;
+  for (const base::FilePath& path : image_paths_) {
+    // Normalize paths as |image_paths_| can contain duplicates like "icon.png"
+    // and "./icon.png" to avoid unpacking the same image twice.
+    base::FilePath normalized_path;
+    if (path.IsAbsolute() || path.ReferencesParent() ||
+        !NormalizeExtensionResourcePath(path, &normalized_path)) {
+      // Report the error asynchronously so the caller stack has chance to
+      // unwind.
+      base::SequencedTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, base::BindOnce(&ImageSanitizer::ReportError,
+                                    weak_factory_.GetWeakPtr(),
+                                    Status::kImagePathError, path));
+      return;
+    }
+    normalized_image_paths.insert(normalized_path);
+  }
+  // Update |image_paths_| as some of the path might have been changed by
+  // normalization.
+  image_paths_ = std::move(normalized_image_paths);
+
+  // Note that we use 2 for loops instead of one to prevent a race and flakyness
+  // in tests: if |image_paths_| contains 2 paths, a valid one that points to a
+  // file that does not exist and an invalid one, there is a race that can cause
+  // either error to be reported (kImagePathError or kFileReadError).
+  for (const base::FilePath& path : image_paths_) {
+    base::FilePath full_image_path = image_dir_.Append(path);
+    base::PostTaskAndReplyWithResult(
+        extensions::GetExtensionFileTaskRunner().get(), FROM_HERE,
+        base::BindOnce(&ReadAndDeleteFile, full_image_path),
+        base::BindOnce(&ImageSanitizer::ImageFileRead,
+                       weak_factory_.GetWeakPtr(), path));
+  }
+}
+
+void ImageSanitizer::ImageFileRead(
+    const base::FilePath& image_path,
+    std::tuple<std::vector<uint8_t>, bool, bool> read_and_delete_result) {
+  if (!std::get<1>(read_and_delete_result)) {
+    ReportError(Status::kFileReadError, image_path);
+    return;
+  }
+  if (!std::get<2>(read_and_delete_result)) {
+    ReportError(Status::kFileDeleteError, image_path);
+    return;
+  }
+  const std::vector<uint8_t>& image_data = std::get<0>(read_and_delete_result);
+  image_decoder_ptr_->DecodeImage(
+      image_data, data_decoder::mojom::ImageCodec::DEFAULT,
+      /*shrink_to_fit=*/false, kMaxImageCanvas, gfx::Size(),
+      base::BindOnce(&ImageSanitizer::ImageDecoded, weak_factory_.GetWeakPtr(),
+                     image_path));
+}
+
+void ImageSanitizer::ImageDecoded(const base::FilePath& image_path,
+                                  const SkBitmap& decoded_image) {
+  if (decoded_image.isNull()) {
+    ReportError(Status::kDecodingError, image_path);
+    return;
+  }
+
+  if (image_decoded_callback_)
+    image_decoded_callback_.Run(image_path, decoded_image);
+
+  // TODO(mpcomplete): It's lame that we're encoding all images as PNG, even
+  // though they may originally be .jpg, etc.  Figure something out.
+  // http://code.google.com/p/chromium/issues/detail?id=12459
+  base::PostTaskAndReplyWithResult(
+      extensions::GetExtensionFileTaskRunner().get(), FROM_HERE,
+      base::BindOnce(&EncodeImage, decoded_image),
+      base::BindOnce(&ImageSanitizer::ImageReencoded,
+                     weak_factory_.GetWeakPtr(), image_path));
+}
+
+void ImageSanitizer::ImageReencoded(
+    const base::FilePath& image_path,
+    std::pair<bool, std::vector<unsigned char>> result) {
+  bool success = result.first;
+  std::vector<unsigned char> image_data = std::move(result.second);
+  if (!success) {
+    ReportError(Status::kEncodingError, image_path);
+    return;
+  }
+
+  int size = base::checked_cast<int>(image_data.size());
+  base::PostTaskAndReplyWithResult(
+      extensions::GetExtensionFileTaskRunner().get(), FROM_HERE,
+      base::BindOnce(&WriteFile, image_dir_.Append(image_path),
+                     std::move(image_data)),
+      base::BindOnce(&ImageSanitizer::ImageWritten, weak_factory_.GetWeakPtr(),
+                     image_path, size));
+}
+
+void ImageSanitizer::ImageWritten(const base::FilePath& image_path,
+                                  int expected_size,
+                                  int actual_size) {
+  if (expected_size != actual_size) {
+    ReportError(Status::kFileWriteError, image_path);
+    return;
+  }
+  // We have finished with this path.
+  size_t removed_count = image_paths_.erase(image_path);
+  DCHECK_EQ(1U, removed_count);
+
+  if (image_paths_.empty()) {
+    // This was the last path, we are done.
+    ReportSuccess();
+  }
+}
+
+void ImageSanitizer::ReportSuccess() {
+  CleanUp();
+  std::move(done_callback_).Run(Status::kSuccess, base::FilePath());
+}
+
+void ImageSanitizer::ReportError(Status status, const base::FilePath& path) {
+  CleanUp();
+  // Prevent any other task from reporting, we want to notify only once.
+  weak_factory_.InvalidateWeakPtrs();
+  std::move(done_callback_).Run(status, path);
+}
+
+void ImageSanitizer::CleanUp() {
+  image_decoder_ptr_.reset();
+}
+
+}  // namespace extensions
\ No newline at end of file
diff --git a/extensions/browser/image_sanitizer.h b/extensions/browser/image_sanitizer.h
new file mode 100644
index 0000000..ac36aa6
--- /dev/null
+++ b/extensions/browser/image_sanitizer.h
@@ -0,0 +1,116 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_BROWSER_IMAGE_SANITIZER_H_
+#define EXTENSIONS_BROWSER_IMAGE_SANITIZER_H_
+
+#include <cstdint>
+#include <memory>
+#include <set>
+#include <tuple>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/values.h"
+#include "services/data_decoder/public/interfaces/image_decoder.mojom.h"
+#include "services/service_manager/public/cpp/identity.h"
+
+class SkBitmap;
+
+namespace service_manager {
+class Connector;
+}
+
+namespace extensions {
+
+// This class takes potentially unsafe images and decodes them in a sandboxed
+// process, then reencodes them so that they can later be safely used in the
+// browser process.
+class ImageSanitizer {
+ public:
+  enum class Status {
+    kSuccess = 0,
+    kImagePathError,
+    kFileReadError,
+    kFileDeleteError,
+    kDecodingError,
+    kEncodingError,
+    kFileWriteError,
+  };
+
+  // Callback invoked when the image sanitization is is done. If status is an
+  // error, |path| points to the file that caused the error.
+  using SanitizationDoneCallback =
+      base::OnceCallback<void(Status status, const base::FilePath& path)>;
+
+  // Called on a background thread when an image has been decoded.
+  using ImageDecodedCallback =
+      base::RepeatingCallback<void(const base::FilePath& path, SkBitmap image)>;
+
+  // Creates an ImageSanitizer and starts the sanitization of the images in
+  // |image_relative_paths|. These paths should be relative and not reference
+  // their parent dir or an kImagePathError will be reported to |done_callback|.
+  // These relative paths are resolved against |image_dir|.
+  // |connector| should be a connector to the ServiceManager usable on the
+  // current thread. |identity| is used when accessing the data decoder service
+  // which is used internally to decode images. It lets callers potentially
+  // share a process when doing unrelated data decoding operations.
+  // |done_callback| is invoked asynchronously when all images have been
+  // sanitized or if an error occurred.
+  // If the returned ImageSanitizer instance is deleted, |done_callback| and
+  // |image_decoded_callback| are not called and the sanitization stops promptly
+  // (some background tasks may still run).
+  static std::unique_ptr<ImageSanitizer> CreateAndStart(
+      service_manager::Connector* connector,
+      const service_manager::Identity& identity,
+      const base::FilePath& image_dir,
+      const std::set<base::FilePath>& image_relative_paths,
+      ImageDecodedCallback image_decoded_callback,
+      SanitizationDoneCallback done_callback);
+
+  ~ImageSanitizer();
+
+ private:
+  ImageSanitizer(const base::FilePath& image_dir,
+                 const std::set<base::FilePath>& image_relative_paths,
+                 ImageDecodedCallback image_decoded_callback,
+                 SanitizationDoneCallback done_callback);
+
+  void Start(service_manager::Connector* connector,
+             const service_manager::Identity& identity);
+
+  void ImageFileRead(
+      const base::FilePath& image_path,
+      std::tuple<std::vector<uint8_t>, bool, bool> read_and_delete_result);
+
+  void ImageDecoded(const base::FilePath& image_path,
+                    const SkBitmap& decoded_image);
+
+  void ImageReencoded(const base::FilePath& image_path,
+                      std::pair<bool, std::vector<unsigned char>> result);
+
+  void ImageWritten(const base::FilePath& image_path,
+                    int expected_size,
+                    int actual_size);
+
+  void ReportSuccess();
+  void ReportError(Status status, const base::FilePath& path);
+
+  void CleanUp();
+
+  base::FilePath image_dir_;
+  std::set<base::FilePath> image_paths_;
+  ImageDecodedCallback image_decoded_callback_;
+  SanitizationDoneCallback done_callback_;
+  data_decoder::mojom::ImageDecoderPtr image_decoder_ptr_;
+  base::WeakPtrFactory<ImageSanitizer> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ImageSanitizer);
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_BROWSER_IMAGE_SANITIZER_H_
\ No newline at end of file
diff --git a/extensions/browser/image_sanitizer_unittest.cc b/extensions/browser/image_sanitizer_unittest.cc
new file mode 100644
index 0000000..27eecb3
--- /dev/null
+++ b/extensions/browser/image_sanitizer_unittest.cc
@@ -0,0 +1,211 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/image_sanitizer.h"
+
+#include <map>
+#include <memory>
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "build/build_config.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "services/data_decoder/public/cpp/test_data_decoder_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+namespace {
+
+constexpr char kBase64edValidPng[] =
+    "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd"
+    "1PeAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC";
+
+constexpr char kBase64edInvalidPng[] =
+    "Rw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd"
+    "1PeAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC";
+
+class ImageSanitizerTest : public testing::Test {
+ public:
+  ImageSanitizerTest()
+      : thread_bundle_(content::TestBrowserThreadBundle::DEFAULT) {}
+
+ protected:
+  void CreateValidImage(const base::FilePath::StringPieceType& file_name) {
+    ASSERT_TRUE(WriteBase64DataToFile(kBase64edValidPng, file_name));
+  }
+
+  void CreateInvalidImage(const base::FilePath::StringPieceType& file_name) {
+    ASSERT_TRUE(WriteBase64DataToFile(kBase64edInvalidPng, file_name));
+  }
+
+  const base::FilePath& GetImagePath() const { return temp_dir_.GetPath(); }
+
+  void WaitForSanitizationDone() {
+    ASSERT_FALSE(done_callback_);
+    base::RunLoop run_loop;
+    done_callback_ = run_loop.QuitClosure();
+    run_loop.Run();
+  }
+
+  void CreateAndStartSanitizer(
+      const std::set<base::FilePath>& image_relative_paths) {
+    sanitizer_ = ImageSanitizer::CreateAndStart(
+        test_data_decoder_service_.connector(), service_manager::Identity(),
+        temp_dir_.GetPath(), image_relative_paths,
+        base::BindRepeating(&ImageSanitizerTest::ImageSanitizerDecodedImage,
+                            base::Unretained(this)),
+        base::BindOnce(&ImageSanitizerTest::ImageSanitizationDone,
+                       base::Unretained(this)));
+  }
+
+  ImageSanitizer::Status last_reported_status() const { return last_status_; }
+
+  const base::FilePath& last_reported_path() const {
+    return last_reported_path_;
+  }
+
+  std::map<base::FilePath, SkBitmap>* decoded_images() {
+    return &decoded_images_;
+  }
+
+ private:
+  bool WriteBase64DataToFile(const std::string& base64_data,
+                             const base::FilePath::StringPieceType& file_name) {
+    std::string binary;
+    if (!base::Base64Decode(base64_data, &binary))
+      return false;
+
+    base::FilePath path = temp_dir_.GetPath().Append(file_name);
+    return base::WriteFile(path, binary.data(), binary.size());
+  }
+
+  void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
+
+  void ImageSanitizationDone(ImageSanitizer::Status status,
+                             const base::FilePath& path) {
+    last_status_ = status;
+    last_reported_path_ = path;
+    if (done_callback_)
+      std::move(done_callback_).Run();
+  }
+
+  void ImageSanitizerDecodedImage(const base::FilePath& path, SkBitmap image) {
+    EXPECT_EQ(decoded_images()->find(path), decoded_images()->end());
+    (*decoded_images())[path] = image;
+  }
+
+  content::TestBrowserThreadBundle thread_bundle_;
+  data_decoder::TestDataDecoderService test_data_decoder_service_;
+  ImageSanitizer::Status last_status_;
+  base::FilePath last_reported_path_;
+  base::OnceClosure done_callback_;
+  std::unique_ptr<ImageSanitizer> sanitizer_;
+  base::ScopedTempDir temp_dir_;
+  std::map<base::FilePath, SkBitmap> decoded_images_;
+
+  DISALLOW_COPY_AND_ASSIGN(ImageSanitizerTest);
+};
+
+}  // namespace
+
+TEST_F(ImageSanitizerTest, NoImagesProvided) {
+  CreateAndStartSanitizer(std::set<base::FilePath>());
+  WaitForSanitizationDone();
+  EXPECT_EQ(last_reported_status(), ImageSanitizer::Status::kSuccess);
+  EXPECT_TRUE(last_reported_path().empty());
+}
+
+TEST_F(ImageSanitizerTest, InvalidPathAbsolute) {
+  base::FilePath normal_path(FILE_PATH_LITERAL("hello.png"));
+#if defined(OS_WIN)
+  base::FilePath absolute_path(FILE_PATH_LITERAL("c:\\Windows\\win32"));
+#else
+  base::FilePath absolute_path(FILE_PATH_LITERAL("/usr/bin/root"));
+#endif
+  CreateAndStartSanitizer({normal_path, absolute_path});
+  WaitForSanitizationDone();
+  EXPECT_EQ(last_reported_status(), ImageSanitizer::Status::kImagePathError);
+  EXPECT_EQ(last_reported_path(), absolute_path);
+}
+
+TEST_F(ImageSanitizerTest, InvalidPathReferenceParent) {
+  base::FilePath good_path(FILE_PATH_LITERAL("hello.png"));
+  base::FilePath bad_path(FILE_PATH_LITERAL("hello"));
+  bad_path = bad_path.Append(base::FilePath::kParentDirectory)
+                 .Append(base::FilePath::kParentDirectory)
+                 .Append(base::FilePath::kParentDirectory)
+                 .Append(FILE_PATH_LITERAL("usr"))
+                 .Append(FILE_PATH_LITERAL("bin"));
+  CreateAndStartSanitizer({good_path, bad_path});
+  WaitForSanitizationDone();
+  EXPECT_EQ(last_reported_status(), ImageSanitizer::Status::kImagePathError);
+  EXPECT_EQ(last_reported_path(), bad_path);
+}
+
+TEST_F(ImageSanitizerTest, ValidCase) {
+  constexpr std::array<const base::FilePath::CharType* const, 10> kFileNames{
+      {FILE_PATH_LITERAL("image0.png"), FILE_PATH_LITERAL("image1.png"),
+       FILE_PATH_LITERAL("image2.png"), FILE_PATH_LITERAL("image3.png"),
+       FILE_PATH_LITERAL("image4.png"), FILE_PATH_LITERAL("image5.png"),
+       FILE_PATH_LITERAL("image6.png"), FILE_PATH_LITERAL("image7.png"),
+       FILE_PATH_LITERAL("image8.png"), FILE_PATH_LITERAL("image9.png")}};
+  std::set<base::FilePath> paths;
+  for (const base::FilePath::CharType* file_name : kFileNames) {
+    CreateValidImage(file_name);
+    paths.insert(base::FilePath(file_name));
+  }
+  CreateAndStartSanitizer(paths);
+  WaitForSanitizationDone();
+  EXPECT_EQ(last_reported_status(), ImageSanitizer::Status::kSuccess);
+  EXPECT_TRUE(last_reported_path().empty());
+  // Make sure the image files are there and non empty, and that the
+  // ImageSanitizerDecodedImage callback was invoked for every image.
+  for (const auto& path : paths) {
+    int64_t file_size = 0;
+    base::FilePath full_path = GetImagePath().Append(path);
+    EXPECT_TRUE(base::GetFileSize(full_path, &file_size));
+    EXPECT_GT(file_size, 0);
+
+    ASSERT_TRUE(base::ContainsKey(*decoded_images(), path));
+    EXPECT_FALSE((*decoded_images())[path].drawsNothing());
+  }
+  // No extra images should have been reported.
+  EXPECT_EQ(decoded_images()->size(), 10U);
+}
+
+TEST_F(ImageSanitizerTest, MissingImage) {
+  constexpr base::FilePath::CharType kGoodPngName[] =
+      FILE_PATH_LITERAL("image.png");
+  constexpr base::FilePath::CharType kNonExistingName[] =
+      FILE_PATH_LITERAL("i_don_t_exist.png");
+  CreateValidImage(kGoodPngName);
+  base::FilePath good_png(kGoodPngName);
+  base::FilePath bad_png(kNonExistingName);
+  CreateAndStartSanitizer({good_png, bad_png});
+  WaitForSanitizationDone();
+  EXPECT_EQ(last_reported_status(), ImageSanitizer::Status::kFileReadError);
+  EXPECT_EQ(last_reported_path(), bad_png);
+}
+
+TEST_F(ImageSanitizerTest, InvalidImage) {
+  constexpr base::FilePath::CharType kGoodPngName[] =
+      FILE_PATH_LITERAL("good.png");
+  constexpr base::FilePath::CharType kBadPngName[] =
+      FILE_PATH_LITERAL("bad.png");
+  CreateValidImage(kGoodPngName);
+  CreateInvalidImage(kBadPngName);
+  base::FilePath good_png(kGoodPngName);
+  base::FilePath bad_png(kBadPngName);
+  CreateAndStartSanitizer({good_png, bad_png});
+  WaitForSanitizationDone();
+  EXPECT_EQ(last_reported_status(), ImageSanitizer::Status::kDecodingError);
+  EXPECT_EQ(last_reported_path(), bad_png);
+}
+
+}  // namespace extensions
diff --git a/extensions/browser/sandboxed_unpacker.cc b/extensions/browser/sandboxed_unpacker.cc
index 5aa7aa9e..84cdd3d 100644
--- a/extensions/browser/sandboxed_unpacker.cc
+++ b/extensions/browser/sandboxed_unpacker.cc
@@ -15,6 +15,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/files/file_util.h"
+#include "base/i18n/rtl.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/path_service.h"
@@ -41,6 +42,8 @@
 #include "extensions/common/manifest_handlers/icons_handler.h"
 #include "extensions/common/switches.h"
 #include "extensions/strings/grit/extensions_strings.h"
+#include "services/data_decoder/public/interfaces/constants.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/codec/png_codec.h"
@@ -182,21 +185,6 @@
   return false;
 }
 
-// Read the decoded images back from the file we saved them to.
-// |extension_path| is the path to the extension we unpacked that wrote the
-// data. Returns true on success.
-bool ReadImagesFromFile(const base::FilePath& extension_path,
-                        DecodedImages* images) {
-  base::FilePath path = extension_path.AppendASCII(kDecodedImagesFilename);
-  std::string file_str;
-  if (!base::ReadFileToString(path, &file_str))
-    return false;
-
-  IPC::Message pickle(file_str.data(), file_str.size());
-  base::PickleIterator iter(pickle);
-  return IPC::ReadParam(&pickle, &iter, images);
-}
-
 // Read the decoded message catalogs back from the file we saved them to.
 // |extension_path| is the path to the extension we unpacked that wrote the
 // data. Returns true on success.
@@ -223,12 +211,14 @@
 }
 
 SandboxedUnpacker::SandboxedUnpacker(
+    std::unique_ptr<service_manager::Connector> connector,
     Manifest::Location location,
     int creation_flags,
     const base::FilePath& extensions_dir,
     const scoped_refptr<base::SequencedTaskRunner>& unpacker_io_task_runner,
     SandboxedUnpackerClient* client)
-    : client_(client),
+    : connector_(std::move(connector)),
+      client_(client),
       extensions_dir_(extensions_dir),
       location_(location),
       creation_flags_(creation_flags),
@@ -237,6 +227,12 @@
   // the utility process kills itself for a bad IPC.
   CHECK_GT(location, Manifest::INVALID_LOCATION);
   CHECK_LT(location, Manifest::NUM_LOCATIONS);
+
+  // Use a random instance ID to guarantee the connection is to a new data
+  // decoder service (running in its own process).
+  data_decoder_identity_ = service_manager::Identity(
+      data_decoder::mojom::kServiceName, service_manager::mojom::kInheritUserID,
+      base::UnguessableToken::Create().ToString());
 }
 
 bool SandboxedUnpacker::CreateTempDirectory() {
@@ -501,21 +497,105 @@
     return;
   }
 
-  SkBitmap install_icon;
-  if (!RewriteImageFiles(&install_icon))
+  // The install icon path may be empty, which is OK, but if it is not it should
+  // be normalized successfully.
+  const std::string& original_install_icon_path =
+      IconsInfo::GetIcons(extension_.get())
+          .Get(extension_misc::EXTENSION_ICON_LARGE,
+               ExtensionIconSet::MATCH_BIGGER);
+  if (!original_install_icon_path.empty() &&
+      !NormalizeExtensionResourcePath(
+          base::FilePath::FromUTF8Unsafe(original_install_icon_path),
+          &install_icon_path_)) {
+    // Invalid path for browser image.
+    ReportFailure(INVALID_PATH_FOR_BROWSER_IMAGE,
+                  l10n_util::GetStringFUTF16(
+                      IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+                      ASCIIToUTF16("INVALID_PATH_FOR_BROWSER_IMAGE")));
     return;
-
-  if (!RewriteCatalogFiles())
-    return;
-
-  // Index and persist ruleset for the Declarative Net Request API.
-  base::Optional<int> dnr_ruleset_checksum;
-  if (!IndexAndPersistRulesIfNeeded(std::move(json_ruleset),
-                                    &dnr_ruleset_checksum)) {
-    return;  // Failure was already reported.
   }
 
-  ReportSuccess(std::move(manifest), install_icon, dnr_ruleset_checksum);
+  std::set<base::FilePath> image_paths =
+      ExtensionsClient::Get()->GetBrowserImagePaths(extension_.get());
+  image_sanitizer_ = ImageSanitizer::CreateAndStart(
+      connector_.get(), data_decoder_identity_, extension_root_, image_paths,
+      base::BindRepeating(&SandboxedUnpacker::ImageSanitizerDecodedImage, this),
+      base::BindOnce(&SandboxedUnpacker::ImageSanitizationDone, this,
+                     std::move(manifest), std::move(json_ruleset)));
+}
+
+void SandboxedUnpacker::ImageSanitizationDone(
+    std::unique_ptr<base::DictionaryValue> manifest,
+    std::unique_ptr<base::ListValue> json_ruleset,
+    ImageSanitizer::Status status,
+    const base::FilePath& file_path_for_error) {
+  // Release |image_sanitizer_|, it is not useful anymore and reference |this|.
+  // (keep a local ref to this so if |image_sanitizer_| was the last ref to
+  // |this| it stays valid for the duration of the call).
+  scoped_refptr<SandboxedUnpacker> keep_this_alive = this;
+  image_sanitizer_ = nullptr;
+
+  if (status == ImageSanitizer::Status::kSuccess) {
+    if (!RewriteCatalogFiles())
+      return;
+
+    // Index and persist ruleset for the Declarative Net Request API.
+    base::Optional<int> dnr_ruleset_checksum;
+    if (!IndexAndPersistRulesIfNeeded(std::move(json_ruleset),
+                                      &dnr_ruleset_checksum)) {
+      return;  // Failure was already reported.
+    }
+
+    ReportSuccess(std::move(manifest), dnr_ruleset_checksum);
+    return;
+  }
+
+  FailureReason failure_reason = UNPACKER_CLIENT_FAILED;
+  base::string16 error;
+  switch (status) {
+    case ImageSanitizer::Status::kImagePathError:
+      failure_reason = INVALID_PATH_FOR_BROWSER_IMAGE;
+      error = l10n_util::GetStringFUTF16(
+          IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+          ASCIIToUTF16("INVALID_PATH_FOR_BROWSER_IMAGE"));
+      break;
+    case ImageSanitizer::Status::kFileReadError:
+    case ImageSanitizer::Status::kDecodingError:
+      error = l10n_util::GetStringFUTF16(
+          IDS_EXTENSION_PACKAGE_IMAGE_ERROR,
+          base::i18n::GetDisplayStringInLTRDirectionality(
+              file_path_for_error.BaseName().LossyDisplayName()));
+      break;
+    case ImageSanitizer::Status::kFileDeleteError:
+      failure_reason = ERROR_REMOVING_OLD_IMAGE_FILE;
+      error = l10n_util::GetStringFUTF16(
+          IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+          ASCIIToUTF16("ERROR_REMOVING_OLD_IMAGE_FILE"));
+      break;
+    case ImageSanitizer::Status::kEncodingError:
+      failure_reason = ERROR_RE_ENCODING_THEME_IMAGE;
+      error = l10n_util::GetStringFUTF16(
+          IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+          ASCIIToUTF16("ERROR_RE_ENCODING_THEME_IMAGE"));
+      break;
+    case ImageSanitizer::Status::kFileWriteError:
+      failure_reason = ERROR_SAVING_THEME_IMAGE;
+      error =
+          l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+                                     ASCIIToUTF16("ERROR_SAVING_THEME_IMAGE"));
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+
+  ReportFailure(failure_reason, error);
+}
+
+void SandboxedUnpacker::ImageSanitizerDecodedImage(const base::FilePath& path,
+                                                   SkBitmap image) {
+  if (path == install_icon_path_)
+    install_icon_ = image;
 }
 
 bool SandboxedUnpacker::IndexAndPersistRulesIfNeeded(
@@ -754,7 +834,6 @@
 
 void SandboxedUnpacker::ReportSuccess(
     std::unique_ptr<base::DictionaryValue> original_manifest,
-    const SkBitmap& install_icon,
     const base::Optional<int>& dnr_ruleset_checksum) {
   UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackSuccess", 1);
 
@@ -767,7 +846,7 @@
   // Client takes ownership of temporary directory, manifest, and extension.
   client_->OnUnpackSuccess(temp_dir_.Take(), extension_root_,
                            std::move(original_manifest), extension_.get(),
-                           install_icon, dnr_ruleset_checksum);
+                           install_icon_, dnr_ruleset_checksum);
   extension_ = NULL;
 }
 
@@ -806,131 +885,6 @@
   return final_manifest.release();
 }
 
-bool SandboxedUnpacker::RewriteImageFiles(SkBitmap* install_icon) {
-  DCHECK(!temp_dir_.GetPath().empty());
-
-  DecodedImages images;
-  if (!ReadImagesFromFile(temp_dir_.GetPath(), &images)) {
-    // Couldn't read image data from disk.
-    ReportFailure(COULD_NOT_READ_IMAGE_DATA_FROM_DISK,
-                  l10n_util::GetStringFUTF16(
-                      IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-                      ASCIIToUTF16("COULD_NOT_READ_IMAGE_DATA_FROM_DISK")));
-    return false;
-  }
-
-  // Delete any images that may be used by the browser.  We're going to write
-  // out our own versions of the parsed images, and we want to make sure the
-  // originals are gone for good.
-  std::set<base::FilePath> image_paths =
-      ExtensionsClient::Get()->GetBrowserImagePaths(extension_.get());
-
-  // Decoded |images| set contains normalized paths and |image_paths| contains
-  // original paths. It is required to check sizes of normalized sets.
-  std::set<base::FilePath> normalized_image_paths =
-      NormalizeExtensionResourcePaths(image_paths);
-  if (normalized_image_paths.size() != images.size()) {
-    // Decoded images don't match what's in the manifest.
-    ReportFailure(
-        DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST,
-        l10n_util::GetStringFUTF16(
-            IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-            ASCIIToUTF16("DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST")));
-    return false;
-  }
-
-  // Report if original icons paths invalid. Normalization procedure may skip
-  // invalid paths, so it is required to check exactly original paths.
-  for (const auto& path : image_paths) {
-    if (path.IsAbsolute() || path.ReferencesParent()) {
-      // Invalid path for browser image.
-      ReportFailure(INVALID_PATH_FOR_BROWSER_IMAGE,
-                    l10n_util::GetStringFUTF16(
-                        IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-                        ASCIIToUTF16("INVALID_PATH_FOR_BROWSER_IMAGE")));
-      return false;
-    }
-  }
-
-  for (const auto& path : normalized_image_paths) {
-    if (!base::DeleteFile(extension_root_.Append(path), false)) {
-      // Error removing old image file.
-      ReportFailure(ERROR_REMOVING_OLD_IMAGE_FILE,
-                    l10n_util::GetStringFUTF16(
-                        IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-                        ASCIIToUTF16("ERROR_REMOVING_OLD_IMAGE_FILE")));
-      return false;
-    }
-  }
-
-  // Get install icon normalized path. Original install icon path may be empty
-  // and it is ok. But if original install icon path is not empty, it should be
-  // normalized successfully.
-  const std::string& install_icon_path =
-      IconsInfo::GetIcons(extension_.get())
-          .Get(extension_misc::EXTENSION_ICON_LARGE,
-               ExtensionIconSet::MATCH_BIGGER);
-  base::FilePath normalized_install_icon_path;
-  if (!install_icon_path.empty() &&
-      !NormalizeExtensionResourcePath(
-          base::FilePath::FromUTF8Unsafe(install_icon_path),
-          &normalized_install_icon_path)) {
-    // Invalid path for browser image.
-    ReportFailure(INVALID_PATH_FOR_BROWSER_IMAGE,
-                  l10n_util::GetStringFUTF16(
-                      IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-                      ASCIIToUTF16("INVALID_PATH_FOR_BROWSER_IMAGE")));
-    return false;
-  }
-
-  // Write our parsed images back to disk as well.
-  for (size_t i = 0; i < images.size(); ++i) {
-    const SkBitmap& image = std::get<0>(images[i]);
-    const base::FilePath& path_suffix = std::get<1>(images[i]);
-    if (path_suffix == normalized_install_icon_path)
-      *install_icon = image;
-
-    if (path_suffix.IsAbsolute() || path_suffix.ReferencesParent()) {
-      // Invalid path for bitmap image.
-      ReportFailure(INVALID_PATH_FOR_BITMAP_IMAGE,
-                    l10n_util::GetStringFUTF16(
-                        IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-                        ASCIIToUTF16("INVALID_PATH_FOR_BITMAP_IMAGE")));
-      return false;
-    }
-
-    base::FilePath path = extension_root_.Append(path_suffix);
-
-    std::vector<unsigned char> image_data;
-    // TODO(mpcomplete): It's lame that we're encoding all images as PNG, even
-    // though they may originally be .jpg, etc.  Figure something out.
-    // http://code.google.com/p/chromium/issues/detail?id=12459
-    if (!gfx::PNGCodec::EncodeBGRASkBitmap(image, false, &image_data)) {
-      // Error re-encoding theme image.
-      ReportFailure(ERROR_RE_ENCODING_THEME_IMAGE,
-                    l10n_util::GetStringFUTF16(
-                        IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-                        ASCIIToUTF16("ERROR_RE_ENCODING_THEME_IMAGE")));
-      return false;
-    }
-
-    // Note: we're overwriting existing files that the utility process wrote,
-    // so we can be sure the directory exists.
-    const char* image_data_ptr = reinterpret_cast<const char*>(&image_data[0]);
-    int size = base::checked_cast<int>(image_data.size());
-    if (base::WriteFile(path, image_data_ptr, size) != size) {
-      // Error saving theme image.
-      ReportFailure(
-          ERROR_SAVING_THEME_IMAGE,
-          l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-                                     ASCIIToUTF16("ERROR_SAVING_THEME_IMAGE")));
-      return false;
-    }
-  }
-
-  return true;
-}
-
 bool SandboxedUnpacker::RewriteCatalogFiles() {
   base::DictionaryValue catalogs;
   if (!ReadMessageCatalogsFromFile(temp_dir_.GetPath(), &catalogs)) {
diff --git a/extensions/browser/sandboxed_unpacker.h b/extensions/browser/sandboxed_unpacker.h
index a8fe285..a9dd506 100644
--- a/extensions/browser/sandboxed_unpacker.h
+++ b/extensions/browser/sandboxed_unpacker.h
@@ -17,8 +17,10 @@
 #include "base/time/time.h"
 #include "content/public/browser/utility_process_mojo_client.h"
 #include "extensions/browser/crx_file_info.h"
+#include "extensions/browser/image_sanitizer.h"
 #include "extensions/browser/install/crx_install_error.h"
 #include "extensions/common/manifest.h"
+#include "services/service_manager/public/cpp/identity.h"
 
 class SkBitmap;
 
@@ -28,6 +30,10 @@
 class SequencedTaskRunner;
 }
 
+namespace service_manager {
+class Connector;
+}
+
 namespace extensions {
 class Extension;
 
@@ -101,6 +107,8 @@
   // passing the |location| and |creation_flags| to Extension::Create. The
   // |extensions_dir| parameter should specify the directory under which we'll
   // create a subdirectory to write the unpacked extension contents.
+  // |connector| must be a fresh connector (not yet associated to any thread) to
+  // the service manager.
   // Note: Because this requires disk I/O, the task runner passed should use
   // TaskShutdownBehavior::SKIP_ON_SHUTDOWN to ensure that either the task is
   // fully run (if initiated before shutdown) or not run at all (if shutdown is
@@ -110,6 +118,7 @@
   // TODO(devlin): SKIP_ON_SHUTDOWN is also not quite sufficient for this. We
   // should probably instead be using base::ImportantFileWriter or similar.
   SandboxedUnpacker(
+      std::unique_ptr<service_manager::Connector> connector,
       Manifest::Location location,
       int creation_flags,
       const base::FilePath& extensions_dir,
@@ -236,9 +245,14 @@
                                 std::unique_ptr<base::ListValue> json_ruleset);
   void UnpackExtensionFailed(const base::string16& error);
 
+  void ImageSanitizationDone(std::unique_ptr<base::DictionaryValue> manifest,
+                             std::unique_ptr<base::ListValue> json_ruleset,
+                             ImageSanitizer::Status status,
+                             const base::FilePath& path);
+  void ImageSanitizerDecodedImage(const base::FilePath& path, SkBitmap image);
+
   // Reports unpack success or failure, or unzip failure.
   void ReportSuccess(std::unique_ptr<base::DictionaryValue> original_manifest,
-                     const SkBitmap& install_icon,
                      const base::Optional<int>& dnr_ruleset_checksum);
   void ReportFailure(FailureReason reason, const base::string16& error);
 
@@ -249,7 +263,6 @@
 
   // Overwrites original files with safe results from utility process.
   // Reports error and returns false if it fails.
-  bool RewriteImageFiles(SkBitmap* install_icon);
   bool RewriteCatalogFiles();
 
   // Cleans up temp directory artifacts.
@@ -263,6 +276,9 @@
       std::unique_ptr<base::ListValue> json_ruleset,
       base::Optional<int>* dnr_ruleset_checksum);
 
+  // Connector to the ServiceManager required by the Unzip API.
+  std::unique_ptr<service_manager::Connector> connector_;
+
   // If we unpacked a CRX file, we hold on to the path name for use
   // in various histograms.
   base::FilePath crx_path_for_histograms_;
@@ -307,6 +323,21 @@
   std::unique_ptr<content::UtilityProcessMojoClient<mojom::ExtensionUnpacker>>
       utility_process_mojo_client_;
 
+  // The normalized path of the install icon path, retrieved from the manifest.
+  base::FilePath install_icon_path_;
+
+  // The decoded install icon.
+  SkBitmap install_icon_;
+
+  // The identity used to connect to the data decoder service. It is unique to
+  // this SandboxedUnpacker instance so that data decoder operations for
+  // unpacking this extension share the same process, and so that no unrelated
+  // data decoder operation use that process.
+  service_manager::Identity data_decoder_identity_;
+
+  // The ImageSanitizer used to clean-up images.
+  std::unique_ptr<ImageSanitizer> image_sanitizer_;
+
   DISALLOW_COPY_AND_ASSIGN(SandboxedUnpacker);
 };
 
diff --git a/extensions/browser/sandboxed_unpacker_unittest.cc b/extensions/browser/sandboxed_unpacker_unittest.cc
index 5e27fe165..40f1508 100644
--- a/extensions/browser/sandboxed_unpacker_unittest.cc
+++ b/extensions/browser/sandboxed_unpacker_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "components/crx_file/id_util.h"
@@ -23,12 +24,45 @@
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_paths.h"
 #include "extensions/common/switches.h"
+#include "extensions/test/test_extensions_client.h"
+#include "services/data_decoder/public/cpp/test_data_decoder_service.h"
+#include "services/service_manager/public/cpp/connector.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/zlib/google/zip.h"
 
 namespace extensions {
 
+namespace {
+
+// Inserts an illegal path into the browser images returned by
+// TestExtensionsClient for any extension.
+class IllegalImagePathInserter
+    : public TestExtensionsClient::BrowserImagePathsFilter {
+ public:
+  IllegalImagePathInserter(TestExtensionsClient* client) : client_(client) {
+    client_->AddBrowserImagePathsFilter(this);
+  }
+
+  virtual ~IllegalImagePathInserter() {
+    client_->RemoveBrowserImagePathsFilter(this);
+  }
+
+  void Filter(const Extension* extension,
+              std::set<base::FilePath>* paths) override {
+    base::FilePath illegal_path =
+        base::FilePath(base::FilePath::kParentDirectory)
+            .AppendASCII(kTempExtensionName)
+            .AppendASCII("product_logo_128.png");
+    paths->insert(illegal_path);
+  }
+
+ private:
+  TestExtensionsClient* client_;
+};
+
+}  // namespace
+
 class MockSandboxedUnpackerClient : public SandboxedUnpackerClient {
  public:
   void WaitForUnpack() {
@@ -83,7 +117,8 @@
     client_ = new MockSandboxedUnpackerClient;
 
     sandboxed_unpacker_ = new SandboxedUnpacker(
-        Manifest::INTERNAL, Extension::NO_FLAGS, extensions_dir_.GetPath(),
+        test_data_decoder_service_.connector()->Clone(), Manifest::INTERNAL,
+        Extension::NO_FLAGS, extensions_dir_.GetPath(),
         base::ThreadTaskRunnerHandle::Get(), client_);
   }
 
@@ -145,13 +180,16 @@
                    sandboxed_unpacker_));
   }
 
-  base::FilePath GetInstallPath() {
+  bool InstallSucceeded() const { return !client_->temp_dir().empty(); }
+
+  base::FilePath GetInstallPath() const {
     return client_->temp_dir().AppendASCII(kTempExtensionName);
   }
 
-  base::string16 GetInstallError() { return client_->unpack_err(); }
+  base::string16 GetInstallError() const { return client_->unpack_err(); }
 
  protected:
+  data_decoder::TestDataDecoderService test_data_decoder_service_;
   base::ScopedTempDir extensions_dir_;
   MockSandboxedUnpackerClient* client_;
   scoped_refptr<SandboxedUnpacker> sandboxed_unpacker_;
@@ -159,6 +197,24 @@
       in_process_utility_thread_helper_;
 };
 
+TEST_F(SandboxedUnpackerTest, ImageDecodingError) {
+  const char kExpected[] = "Could not decode image: ";
+  SetupUnpacker("bad_image.crx", "");
+  EXPECT_TRUE(base::StartsWith(GetInstallError(), base::ASCIIToUTF16(kExpected),
+                               base::CompareCase::INSENSITIVE_ASCII))
+      << "Expected prefix: \"" << kExpected << "\", actual error: \""
+      << GetInstallError() << "\"";
+}
+
+TEST_F(SandboxedUnpackerTest, BadPathError) {
+  IllegalImagePathInserter inserter(
+      static_cast<TestExtensionsClient*>(ExtensionsClient::Get()));
+  SetupUnpacker("good_package.crx", "");
+  // Install should have failed with an error.
+  EXPECT_FALSE(InstallSucceeded());
+  EXPECT_FALSE(GetInstallError().empty());
+}
+
 TEST_F(SandboxedUnpackerTest, NoCatalogsSuccess) {
   SetupUnpacker("no_l10n.crx", "");
   // Check that there is no _locales folder.
diff --git a/extensions/common/api/bluetooth_private.idl b/extensions/common/api/bluetooth_private.idl
index b2d760b9..f3ff4ba 100644
--- a/extensions/common/api/bluetooth_private.idl
+++ b/extensions/common/api/bluetooth_private.idl
@@ -123,7 +123,8 @@
   // These functions all report failures via chrome.runtime.lastError.
   interface Functions {
     // Changes the state of the Bluetooth adapter.
-    // |adapterState|:
+    // |adapterState|: The new state of the adapter.
+    // |callback|: Called when all the state changes have been completed.
     static void setAdapterState(NewAdapterState adapterState,
                                 optional VoidCallback callback);
 
diff --git a/extensions/common/constants.cc b/extensions/common/constants.cc
index ef80d21..57b6606 100644
--- a/extensions/common/constants.cc
+++ b/extensions/common/constants.cc
@@ -29,8 +29,6 @@
 
 const char kTempExtensionName[] = "CRX_INSTALL";
 
-const char kDecodedImagesFilename[] = "DECODED_IMAGES";
-
 const char kDecodedMessageCatalogsFilename[] = "DECODED_MESSAGE_CATALOGS";
 
 const char kGeneratedBackgroundPageFilename[] =
diff --git a/extensions/common/constants.h b/extensions/common/constants.h
index a55a018..f0d6c6ffb 100644
--- a/extensions/common/constants.h
+++ b/extensions/common/constants.h
@@ -46,9 +46,6 @@
 // validation before finalizing install.
 extern const char kTempExtensionName[];
 
-// The file to write our decoded images to, relative to the extension_path.
-extern const char kDecodedImagesFilename[];
-
 // The file to write our decoded message catalogs to, relative to the
 // extension_path.
 extern const char kDecodedMessageCatalogsFilename[];
diff --git a/extensions/common/extension_unpacker.mojom b/extensions/common/extension_unpacker.mojom
index 46b2a74e..2ce9482 100644
--- a/extensions/common/extension_unpacker.mojom
+++ b/extensions/common/extension_unpacker.mojom
@@ -21,8 +21,8 @@
   // the Declarative Net Request API in |json_ruleset|. The supplied |location|,
   // and the |creation_flags| defined by Extension::InitFromValueFlags are
   // passed into Extension::Create() when unpacking the extension. Decoded
-  // image and message catalog data from the extension is written to files
-  // kDecodedImagesFilename and kDecodedMessageCatalogsFilename in |path|.
+  // message catalog data from the extension is written to the
+  // kDecodedMessageCatalogsFilename file in |path|.
   // If Unpack() fails for any reason, |error| contains a user-displayable
   // explanation of what went wrong.
   // |channel| and |type| are needed to initialize the global state of the
diff --git a/extensions/utility/unpacker.cc b/extensions/utility/unpacker.cc
index c43edf7..405bf335 100644
--- a/extensions/utility/unpacker.cc
+++ b/extensions/utility/unpacker.cc
@@ -20,12 +20,10 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread.h"
 #include "base/values.h"
-#include "content/public/child/image_decoder_utils.h"
 #include "extensions/common/api/declarative_net_request/dnr_manifest_data.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_l10n_util.h"
-#include "extensions/common/extension_resource_path_normalizer.h"
 #include "extensions/common/extension_utility_types.h"
 #include "extensions/common/extensions_client.h"
 #include "extensions/common/file_util.h"
@@ -46,54 +44,12 @@
 namespace errors = manifest_errors;
 namespace keys = manifest_keys;
 
-// A limit to stop us passing dangerously large canvases to the browser.
-const int kMaxImageCanvas = 4096 * 4096;
-
 constexpr const base::FilePath::CharType* kAllowedThemeFiletypes[] = {
     FILE_PATH_LITERAL(".bmp"),  FILE_PATH_LITERAL(".gif"),
     FILE_PATH_LITERAL(".jpeg"), FILE_PATH_LITERAL(".jpg"),
     FILE_PATH_LITERAL(".json"), FILE_PATH_LITERAL(".png"),
     FILE_PATH_LITERAL(".webp")};
 
-SkBitmap DecodeImage(const base::FilePath& path) {
-  // Read the file from disk.
-  std::string file_contents;
-  if (!base::PathExists(path) ||
-      !base::ReadFileToString(path, &file_contents)) {
-    return SkBitmap();
-  }
-
-  // Decode the image using WebKit's image decoder.
-  const unsigned char* data =
-      reinterpret_cast<const unsigned char*>(file_contents.data());
-  SkBitmap bitmap =
-      content::DecodeImage(data, gfx::Size(), file_contents.length());
-  if (bitmap.computeByteSize() > kMaxImageCanvas)
-    return SkBitmap();
-  return bitmap;
-}
-
-bool PathContainsParentDirectory(const base::FilePath& path) {
-  const base::FilePath::StringType kSeparators(base::FilePath::kSeparators);
-  const base::FilePath::StringType kParentDirectory(
-      base::FilePath::kParentDirectory);
-  const size_t npos = base::FilePath::StringType::npos;
-  const base::FilePath::StringType& value = path.value();
-
-  for (size_t i = 0; i < value.length();) {
-    i = value.find(kParentDirectory, i);
-    if (i != npos) {
-      if ((i == 0 || kSeparators.find(value[i - 1]) == npos) &&
-          (i + 1 < value.length() || kSeparators.find(value[i + 1]) == npos)) {
-        return true;
-      }
-      ++i;
-    }
-  }
-
-  return false;
-}
-
 bool WritePickle(const IPC::Message& pickle, const base::FilePath& dest_path) {
   int size = base::checked_cast<int>(pickle.size());
   const char* data = static_cast<const char*>(pickle.data());
@@ -103,10 +59,6 @@
 
 }  // namespace
 
-struct Unpacker::InternalData {
-  DecodedImages decoded_images;
-};
-
 Unpacker::Unpacker(const base::FilePath& working_dir,
                    const base::FilePath& extension_dir,
                    const std::string& extension_id,
@@ -116,9 +68,7 @@
       extension_dir_(extension_dir),
       extension_id_(extension_id),
       location_(location),
-      creation_flags_(creation_flags) {
-  internal_data_.reset(new InternalData());
-}
+      creation_flags_(creation_flags) {}
 
 Unpacker::~Unpacker() {
 }
@@ -221,20 +171,6 @@
   }
   extension->AddInstallWarnings(warnings);
 
-  // Decode any images that the browser needs to display. |GetBrowserImagePaths|
-  // can contain duplicates like "icon.png" and "./icon.png". It is required to
-  // normalize paths to avoid unpacking of the same icon twice.
-  const std::set<base::FilePath> image_paths =
-      ExtensionsClient::Get()->GetBrowserImagePaths(extension.get());
-  if (!VerifyOriginalImagePaths(image_paths))
-    return false;  // Error was already reported.
-  const std::set<base::FilePath> normalized_image_paths =
-      NormalizeExtensionResourcePaths(image_paths);
-  for (const base::FilePath& path : normalized_image_paths) {
-    if (!AddDecodedImage(path))
-      return false;  // Error was already reported.
-  }
-
   // Parse all message catalogs (if any).
   parsed_catalogs_.reset(new base::DictionaryValue);
   if (!LocaleInfo::GetDefaultLocale(extension.get()).empty()) {
@@ -242,7 +178,7 @@
       return false;  // Error was already reported.
   }
 
-  return ReadJSONRulesetIfNeeded(extension.get()) && DumpImagesToFile() &&
+  return ReadJSONRulesetIfNeeded(extension.get()) &&
          DumpMessageCatalogsToFile();
 }
 
@@ -270,19 +206,6 @@
   return true;
 }
 
-bool Unpacker::DumpImagesToFile() {
-  IPC::Message pickle;  // We use a Message so we can use WriteParam.
-  IPC::WriteParam(&pickle, internal_data_->decoded_images);
-
-  base::FilePath path = working_dir_.AppendASCII(kDecodedImagesFilename);
-  if (!WritePickle(pickle, path)) {
-    SetError("Could not write image data to disk.");
-    return false;
-  }
-
-  return true;
-}
-
 bool Unpacker::DumpMessageCatalogsToFile() {
   IPC::Message pickle;
   IPC::WriteParam(&pickle, *parsed_catalogs_.get());
@@ -297,35 +220,6 @@
   return true;
 }
 
-bool Unpacker::AddDecodedImage(const base::FilePath& path) {
-  SkBitmap image_bitmap = DecodeImage(extension_dir_.Append(path));
-  if (image_bitmap.isNull()) {
-    SetUTF16Error(l10n_util::GetStringFUTF16(
-        IDS_EXTENSION_PACKAGE_IMAGE_ERROR,
-        base::i18n::GetDisplayStringInLTRDirectionality(
-            path.BaseName().LossyDisplayName())));
-    return false;
-  }
-
-  internal_data_->decoded_images.push_back(std::make_tuple(image_bitmap, path));
-  return true;
-}
-
-bool Unpacker::VerifyOriginalImagePaths(
-    const std::set<base::FilePath>& image_paths) {
-  for (const base::FilePath& path : image_paths) {
-    // Make sure it's not referencing a file outside the extension's subdir.
-    if (path.IsAbsolute() || PathContainsParentDirectory(path)) {
-      SetUTF16Error(l10n_util::GetStringFUTF16(
-          IDS_EXTENSION_PACKAGE_IMAGE_PATH_ERROR,
-          base::i18n::GetDisplayStringInLTRDirectionality(
-              path.LossyDisplayName())));
-      return false;
-    }
-  }
-  return true;
-}
-
 bool Unpacker::ReadMessageCatalog(const base::FilePath& message_path) {
   std::string error;
   JSONFileValueDeserializer deserializer(message_path);
diff --git a/extensions/utility/unpacker.h b/extensions/utility/unpacker.h
index ec9b2fa..4473110f 100644
--- a/extensions/utility/unpacker.h
+++ b/extensions/utility/unpacker.h
@@ -6,7 +6,6 @@
 #define EXTENSIONS_UTILITY_UNPACKER_H_
 
 #include <memory>
-#include <set>
 #include <string>
 #include <vector>
 
@@ -47,8 +46,7 @@
       std::string* error);
 
   // Runs the processing steps for the extension. On success, this returns true
-  // and the decoded images will be in a file at
-  // |working_dir|/kDecodedImagesFilename and the decoded messages will be in a
+  // and the decoded messages will be in a
   // file at |working_dir|/kDecodedMessageCatalogsFilename.
   bool Run();
 
@@ -70,11 +68,6 @@
   // error.
   bool ReadJSONRulesetIfNeeded(const Extension* extension);
 
-  // Write the decoded images to kDecodedImagesFilename.  We do this instead
-  // of sending them over IPC, since they are so large.  Returns true on
-  // success.
-  bool DumpImagesToFile();
-
   // Write the decoded messages to kDecodedMessageCatalogsFilename.  We do this
   // instead of sending them over IPC, since they are so large.  Returns true on
   // success.
@@ -87,10 +80,6 @@
   // images.
   bool AddDecodedImage(const base::FilePath& path);
 
-  // Verifies original image paths from extension. Returns true iff all paths
-  // are valid. Sets an error if at least one path is invalid.
-  bool VerifyOriginalImagePaths(const std::set<base::FilePath>& image_paths);
-
   // Parses the catalog at the given path and puts it in our list of parsed
   // catalogs.
   bool ReadMessageCatalog(const base::FilePath& message_path);
@@ -121,11 +110,6 @@
   // extension did not provide one.
   std::unique_ptr<base::ListValue> parsed_json_ruleset_;
 
-  // A list of decoded images and the paths where those images came from.  Paths
-  // are relative to the manifest file.
-  struct InternalData;
-  std::unique_ptr<InternalData> internal_data_;
-
   // Dictionary of relative paths and catalogs per path. Paths are in the form
   // of _locales/locale, without messages.json base part.
   std::unique_ptr<base::DictionaryValue> parsed_catalogs_;
diff --git a/extensions/utility/unpacker_unittest.cc b/extensions/utility/unpacker_unittest.cc
index 1e31a68..fdd085e 100644
--- a/extensions/utility/unpacker_unittest.cc
+++ b/extensions/utility/unpacker_unittest.cc
@@ -141,61 +141,6 @@
   EXPECT_EQ(0U, unpacker_->parsed_catalogs()->size());
 }
 
-namespace {
-
-// Inserts an illegal path into the browser images returned by
-// TestExtensionsClient for any extension.
-class IllegalImagePathInserter
-    : public TestExtensionsClient::BrowserImagePathsFilter {
- public:
-  IllegalImagePathInserter(TestExtensionsClient* client) : client_(client) {
-    client_->AddBrowserImagePathsFilter(this);
-  }
-
-  virtual ~IllegalImagePathInserter() {
-    client_->RemoveBrowserImagePathsFilter(this);
-  }
-
-  void Filter(const Extension* extension,
-              std::set<base::FilePath>* paths) override {
-    base::FilePath illegal_path =
-        base::FilePath(base::FilePath::kParentDirectory)
-            .AppendASCII(kTempExtensionName)
-            .AppendASCII("product_logo_128.png");
-    paths->insert(illegal_path);
-  }
-
- private:
-  TestExtensionsClient* client_;
-};
-
-}  // namespace
-
-TEST_F(UnpackerTest, BadPathError) {
-  const char kExpected[] = "Illegal path (absolute or relative with '..'): ";
-  SetupUnpacker("good_package.crx");
-  IllegalImagePathInserter inserter(
-      static_cast<TestExtensionsClient*>(ExtensionsClient::Get()));
-
-  EXPECT_FALSE(unpacker_->Run());
-  EXPECT_TRUE(base::StartsWith(unpacker_->error_message(),
-                               ASCIIToUTF16(kExpected),
-                               base::CompareCase::INSENSITIVE_ASCII))
-      << "Expected prefix: \"" << kExpected << "\", actual error: \""
-      << unpacker_->error_message() << "\"";
-}
-
-TEST_F(UnpackerTest, ImageDecodingError) {
-  const char kExpected[] = "Could not decode image: ";
-  SetupUnpacker("bad_image.crx");
-  EXPECT_FALSE(unpacker_->Run());
-  EXPECT_TRUE(base::StartsWith(unpacker_->error_message(),
-                               ASCIIToUTF16(kExpected),
-                               base::CompareCase::INSENSITIVE_ASCII))
-      << "Expected prefix: \"" << kExpected << "\", actual error: \""
-      << unpacker_->error_message() << "\"";
-}
-
 struct UnzipFileFilterTestCase {
   const base::FilePath::CharType* input;
   const bool should_unzip;
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 58e1c8a..b46b51f 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -147,7 +147,6 @@
       bound_copy_write_buffer_(0),
       bound_pixel_pack_buffer_(0),
       bound_pixel_unpack_buffer_(0),
-      bound_transform_feedback_buffer_(0),
       bound_uniform_buffer_(0),
       bound_pixel_pack_transfer_buffer_id_(0),
       bound_pixel_unpack_transfer_buffer_id_(0),
@@ -1117,9 +1116,6 @@
     case GL_PIXEL_UNPACK_BUFFER_BINDING:
       *params = bound_pixel_unpack_buffer_;
       return true;
-    case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
-      *params = bound_transform_feedback_buffer_;
-      return true;
     case GL_UNIFORM_BUFFER_BINDING:
       *params = bound_uniform_buffer_;
       return true;
@@ -1167,6 +1163,7 @@
     case GL_TRANSFORM_FEEDBACK_BINDING:
     case GL_TRANSFORM_FEEDBACK_ACTIVE:
     case GL_TRANSFORM_FEEDBACK_PAUSED:
+    case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
     case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
     case GL_TRANSFORM_FEEDBACK_BUFFER_START:
     case GL_UNIFORM_BUFFER_SIZE:
@@ -4330,12 +4327,6 @@
     case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM:
       bound_pixel_unpack_transfer_buffer_id_ = buffer_id;
       break;
-    case GL_TRANSFORM_FEEDBACK_BUFFER:
-      if (bound_transform_feedback_buffer_ != buffer_id) {
-        bound_transform_feedback_buffer_ = buffer_id;
-        changed = true;
-      }
-      break;
     case GL_UNIFORM_BUFFER:
       if (bound_uniform_buffer_ != buffer_id) {
         bound_uniform_buffer_ = buffer_id;
@@ -4373,9 +4364,6 @@
                    "glBindBufferBase", "index out of range");
         return;
       }
-      if (bound_transform_feedback_buffer_ != buffer_id) {
-        bound_transform_feedback_buffer_ = buffer_id;
-      }
       break;
     case GL_UNIFORM_BUFFER:
       if (index >=
@@ -4600,9 +4588,6 @@
     if (buffers[ii] == bound_pixel_unpack_buffer_) {
       bound_pixel_unpack_buffer_ = 0;
     }
-    if (buffers[ii] == bound_transform_feedback_buffer_) {
-      bound_transform_feedback_buffer_ = 0;
-    }
     if (buffers[ii] == bound_uniform_buffer_) {
       bound_uniform_buffer_ = 0;
     }
@@ -5178,8 +5163,27 @@
 GLuint GLES2Implementation::GetBoundBufferHelper(GLenum target) {
   GLenum binding = GLES2Util::MapBufferTargetToBindingEnum(target);
   GLint id = 0;
-  bool cached = GetHelper(binding, &id);
-  DCHECK(cached);
+  if (target == GL_TRANSFORM_FEEDBACK_BUFFER) {
+    // GL_TRANSFORM_FEEDBACK_BUFFER is not cached locally, so we need to call
+    // the server here. We don't cache it because it's part of the transform
+    // feedback object state, which means that it's modified by things other
+    // than glBindBuffer calls, specifically glBindTransformFeedback, the
+    // success of which depends on a bunch of other states.
+    // TODO(jdarpinian): This is slow. We should audit callers of this function
+    //     to figure out if they really need this information, and skip this if
+    //     they don't.
+    auto* result = GetResultAs<cmds::GetIntegerv::Result*>();
+    DCHECK(result);
+    result->SetNumResults(0);
+    helper_->GetIntegerv(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GetResultShmId(),
+                         GetResultShmOffset());
+    WaitForCmd();
+    DCHECK(result->GetNumResults() == 1);
+    result->CopyResult(&id);
+  } else {
+    bool cached = GetHelper(binding, &id);
+    DCHECK(cached);
+  }
   return static_cast<GLuint>(id);
 }
 
@@ -6304,6 +6308,8 @@
       return capabilities.texture_format_etc1;
     case GL_R16_EXT:
       return capabilities.texture_norm16;
+    case GL_RGB10_A2_EXT:
+      return capabilities.image_xr30;
     case GL_RED:
     case GL_RG_EXT:
     case GL_RGB:
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 7d76202..2f59edbe 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -762,8 +762,13 @@
   GLuint bound_copy_write_buffer_;
   GLuint bound_pixel_pack_buffer_;
   GLuint bound_pixel_unpack_buffer_;
-  GLuint bound_transform_feedback_buffer_;
   GLuint bound_uniform_buffer_;
+  // We don't cache the currently bound transform feedback buffer, because
+  // it is part of the current transform feedback object. Caching the transform
+  // feedback object state correctly requires predicting if a call to
+  // glBeginTransformFeedback will succeed or fail, which in turn requires
+  // caching a whole bunch of other states such as the transform feedback
+  // varyings of the current program.
 
   // The currently bound pixel transfer buffers.
   GLuint bound_pixel_pack_transfer_buffer_id_;
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index e41c7ee..ce0ba6a 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -4385,21 +4385,22 @@
   const GLuint kBufferId = 123;
   void* mem;
 
-  const int TARGET_COUNT = 8;
-  GLenum targets[TARGET_COUNT] = {
-    GL_ARRAY_BUFFER,
-    GL_ELEMENT_ARRAY_BUFFER,
-    GL_COPY_READ_BUFFER,
-    GL_COPY_WRITE_BUFFER,
-    GL_TRANSFORM_FEEDBACK_BUFFER,
-    GL_UNIFORM_BUFFER,
-    GL_PIXEL_PACK_BUFFER,
-    GL_PIXEL_UNPACK_BUFFER,
+  std::vector<GLenum> targets = {
+      GL_ARRAY_BUFFER,      GL_ELEMENT_ARRAY_BUFFER,      GL_COPY_READ_BUFFER,
+      GL_COPY_WRITE_BUFFER, GL_TRANSFORM_FEEDBACK_BUFFER, GL_UNIFORM_BUFFER,
+      GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER,
   };
 
   // Positive tests
-  for (int i = 0; i < TARGET_COUNT; i++) {
+  for (size_t i = 0; i < targets.size(); i++) {
     gl_->BindBuffer(targets[i], kBufferId);
+    if (targets[i] == GL_TRANSFORM_FEEDBACK_BUFFER) {
+      ExpectedMemoryInfo result =
+          GetExpectedResultMemory(sizeof(cmds::GetIntegerv::Result));
+      EXPECT_CALL(*command_buffer(), OnFlush())
+          .WillOnce(SetMemory(result.ptr, SizedResultHelper<GLuint>(1)))
+          .RetiresOnSaturation();
+    }
     mem = gl_->GetBufferSubDataAsyncCHROMIUM(targets[i], 10, 64);
     EXPECT_TRUE(mem != nullptr);
     EXPECT_EQ(GL_NO_ERROR, CheckError());
@@ -4409,9 +4410,16 @@
   }
 
   // Negative tests: invalid target
-  for (int i = 0; i < TARGET_COUNT; i++) {
-    GLenum wrong_target = targets[(i + 1) % TARGET_COUNT];
+  for (size_t i = 0; i < targets.size(); i++) {
+    GLenum wrong_target = targets[(i + 1) % targets.size()];
     gl_->BindBuffer(targets[i], kBufferId);
+    if (wrong_target == GL_TRANSFORM_FEEDBACK_BUFFER) {
+      ExpectedMemoryInfo result =
+          GetExpectedResultMemory(sizeof(cmds::GetIntegerv::Result));
+      EXPECT_CALL(*command_buffer(), OnFlush())
+          .WillOnce(SetMemory(result.ptr, SizedResultHelper<GLuint>(0)))
+          .RetiresOnSaturation();
+    }
     mem = gl_->GetBufferSubDataAsyncCHROMIUM(wrong_target, 10, 64);
     EXPECT_TRUE(mem == nullptr);
     EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index 6b99be35..30d3c7fe 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -2799,7 +2799,8 @@
     }
   }
 
-  if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer) {
+  if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer &&
+      args.width && args.height && args.depth) {
     uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
     if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) {
       // In ValidateTexImage(), we already made sure buffer size is no less
@@ -3028,7 +3029,8 @@
     }
   }
 
-  if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer) {
+  if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer &&
+      args.width && args.height && args.depth) {
     uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
     if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) {
       DoTexSubImageWithAlignmentWorkaround(texture_state, state, args);
diff --git a/gpu/ipc/common/gpu_memory_buffer_support.cc b/gpu/ipc/common/gpu_memory_buffer_support.cc
index 6d4a1ec..1a8313b 100644
--- a/gpu/ipc/common/gpu_memory_buffer_support.cc
+++ b/gpu/ipc/common/gpu_memory_buffer_support.cc
@@ -56,6 +56,7 @@
       return format == gfx::BufferFormat::R_8 ||
              format == gfx::BufferFormat::BGRA_8888 ||
              format == gfx::BufferFormat::RGBA_F16 ||
+             format == gfx::BufferFormat::BGRX_1010102 ||
              format == gfx::BufferFormat::UYVY_422 ||
              format == gfx::BufferFormat::YUV_420_BIPLANAR;
     case gfx::BufferUsage::SCANOUT_VDA_WRITE:
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg
index e37ecae..3b7487d 100644
--- a/infra/config/cq.cfg
+++ b/infra/config/cq.cfg
@@ -94,7 +94,7 @@
       }
       builders {
         name: "linux_chromium_ozone_compile_only_ng"
-        experiment_percentage: 10
+        experiment_percentage: 50
       }
       builders {
         name: "linux_chromium_compile_dbg_ng"
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/BUILD.gn b/ios/chrome/browser/ui/toolbar/adaptive/BUILD.gn
index b8127ec..beffede6 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/BUILD.gn
+++ b/ios/chrome/browser/ui/toolbar/adaptive/BUILD.gn
@@ -20,6 +20,7 @@
     "//components/google/core/browser",
     "//ios/chrome/browser/bookmarks",
     "//ios/chrome/browser/browser_state",
+    "//ios/chrome/browser/reading_list",
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
@@ -58,6 +59,8 @@
   deps = [
     "//base",
     "//ios/chrome/browser/ui/activity_services/requirements",
+    "//ios/chrome/browser/ui/commands",
+    "//ios/chrome/browser/ui/history_popup/requirements",
     "//ios/chrome/browser/ui/toolbar/clean:toolbar_components_ui",
     "//ios/chrome/browser/ui/toolbar/clean:toolbar_ui",
     "//ios/chrome/browser/ui/toolbar/public",
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_coordinator.mm
index 54e5dceb..c36267c7 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_coordinator.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_coordinator.mm
@@ -6,12 +6,15 @@
 
 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
 #import "ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_coordinator+subclassing.h"
 #import "ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.h"
 #import "ios/chrome/browser/ui/toolbar/clean/toolbar_button_factory.h"
 #import "ios/chrome/browser/ui/toolbar/clean/toolbar_button_visibility_configuration.h"
 #import "ios/chrome/browser/ui/toolbar/clean/toolbar_mediator.h"
+#import "ios/chrome/browser/ui/toolbar/clean/toolbar_tools_menu_button.h"
 #import "ios/chrome/browser/ui/toolbar/public/web_toolbar_controller_constants.h"
+#import "ios/chrome/browser/ui/toolbar/tools_menu_button_observer_bridge.h"
 #import "ios/chrome/browser/web_state_list/web_state_list.h"
 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
 
@@ -25,6 +28,9 @@
 @property(nonatomic, assign) BOOL started;
 // Mediator for updating the toolbar when the WebState changes.
 @property(nonatomic, strong) ToolbarMediator* mediator;
+// Button observer for the ToolsMenu button.
+@property(nonatomic, strong)
+    ToolsMenuButtonObserverBridge* toolsMenuButtonObserverBridge;
 
 @end
 
@@ -32,6 +38,7 @@
 @synthesize dispatcher = _dispatcher;
 @synthesize mediator = _mediator;
 @synthesize started = _started;
+@synthesize toolsMenuButtonObserverBridge = _toolsMenuButtonObserverBridge;
 @synthesize viewController = _viewController;
 @synthesize webStateList = _webStateList;
 
@@ -56,6 +63,12 @@
   self.mediator.webStateList = self.webStateList;
   self.mediator.bookmarkModel =
       ios::BookmarkModelFactory::GetForBrowserState(self.browserState);
+
+  DCHECK(self.viewController.toolsMenuButton);
+  self.toolsMenuButtonObserverBridge = [[ToolsMenuButtonObserverBridge alloc]
+      initWithModel:ReadingListModelFactory::GetForBrowserState(
+                        self.browserState)
+      toolbarButton:self.viewController.toolsMenuButton];
 }
 
 #pragma mark - ToolbarCoordinating
@@ -76,7 +89,7 @@
 }
 
 - (void)triggerToolsMenuButtonAnimation {
-  // TODO(crbug.com/801083): Implement that.
+  [self.viewController.toolsMenuButton triggerAnimation];
 }
 
 #pragma mark - Protected
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view.h b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view.h
index 0e92dfe..95fa692 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view.h
+++ b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view.h
@@ -9,7 +9,6 @@
 
 @class MDCProgressView;
 @class ToolbarButton;
-@class ToolbarButtonFactory;
 @class ToolbarTabGridButton;
 @class ToolbarToolsMenuButton;
 
@@ -17,9 +16,6 @@
 // toolbar.
 @protocol AdaptiveToolbarView<NSObject>
 
-// Factory used to create the buttons.
-@property(nonatomic, strong) ToolbarButtonFactory* buttonFactory;
-
 // Property to get all the buttons in this view.
 @property(nonatomic, strong, readonly) NSArray<ToolbarButton*>* allButtons;
 
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.h b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.h
index a3f9553..49354fc2 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.h
+++ b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.h
@@ -11,8 +11,9 @@
 #import "ios/chrome/browser/ui/toolbar/clean/toolbar_type.h"
 
 @protocol ApplicationCommands;
-@class ToolbarButtonFactory;
 @protocol BrowserCommands;
+@class ToolbarButtonFactory;
+@class ToolbarToolsMenuButton;
 
 // ViewController for the adaptive toolbar. This ViewController is the super
 // class of the different implementation (primary or secondary).
@@ -23,6 +24,9 @@
 // Dispatcher for the ViewController.
 @property(nonatomic, weak) id<ApplicationCommands, BrowserCommands> dispatcher;
 
+// Returns the tools menu button.
+- (ToolbarToolsMenuButton*)toolsMenuButton;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_ADAPTIVE_ADAPTIVE_TOOLBAR_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.mm b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.mm
index 2d07f1b5..26fb980 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.mm
@@ -10,6 +10,7 @@
 #import "ios/chrome/browser/ui/toolbar/clean/toolbar_button_factory.h"
 #import "ios/chrome/browser/ui/toolbar/clean/toolbar_constants.h"
 #import "ios/chrome/browser/ui/toolbar/clean/toolbar_tab_grid_button.h"
+#import "ios/chrome/browser/ui/toolbar/clean/toolbar_tools_menu_button.h"
 #import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
 #import "ios/third_party/material_components_ios/src/components/ProgressView/src/MaterialProgressView.h"
 #import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
@@ -46,6 +47,12 @@
   [self updateAllButtonsVisibility];
 }
 
+#pragma mark - Public
+
+- (ToolbarToolsMenuButton*)toolsMenuButton {
+  return self.view.toolsMenuButton;
+}
+
 #pragma mark - ToolbarConsumer
 
 - (void)setCanGoForward:(BOOL)canGoForward {
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm
index ee3fea7..c58f521 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm
@@ -74,8 +74,7 @@
 }
 
 - (id<TabHistoryUIUpdater>)tabHistoryUIUpdater {
-  // TODO(crbug.com/803373): Implement that.
-  return nil;
+  return self.viewController;
 }
 
 - (id<ActivityServicePositioner>)activityServicePositioner {
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.h b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.h
index 3244fbfd0..5337191 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.h
+++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.h
@@ -9,16 +9,32 @@
 
 #import "ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view.h"
 
+@class ToolbarButtonFactory;
+
 // View for the primary toolbar. In an adaptive toolbar paradigm, this is the
 // toolbar always displayed.
 @interface PrimaryToolbarView : UIView<AdaptiveToolbarView>
 
+// Initialize this View with the button |factory|. To finish the initialization
+// of the view, a call to |setUp| is needed.
+- (instancetype)initWithButtonFactory:(ToolbarButtonFactory*)factory
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
+- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
+- (instancetype)init NS_UNAVAILABLE;
+
 // Top anchor at the bottom of the safeAreaLayoutGuide. Used so views don't
 // overlap with the Status Bar.
 @property(nonatomic, strong) NSLayoutYAxisAnchor* topSafeAnchor;
+
 // The location bar view, containing the omnibox.
 @property(nonatomic, strong) UIView* locationBarView;
 
+// Sets all the subviews and constraints of the view. The |topSafeAnchor| needs
+// to be set before calling this.
+- (void)setUp;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_ADAPTIVE_PRIMARY_TOOLBAR_VIEW_H_
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm
index 8117eba9..b8b8007 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm
@@ -19,6 +19,9 @@
 #endif
 
 @interface PrimaryToolbarView ()
+// Factory used to create the buttons.
+@property(nonatomic, strong) ToolbarButtonFactory* buttonFactory;
+
 // Container for the location bar.
 @property(nonatomic, strong) UIView* locationBarContainer;
 
@@ -82,22 +85,23 @@
 @synthesize bookmarkButton = _bookmarkButton;
 @synthesize toolsMenuButton = _toolsMenuButton;
 
-#pragma mark - UIView
+#pragma mark - Public
 
-- (void)willMoveToSuperview:(UIView*)newSuperview {
-  [self setUp];
-  [super willMoveToSuperview:newSuperview];
+- (instancetype)initWithButtonFactory:(ToolbarButtonFactory*)factory {
+  self = [super initWithFrame:CGRectZero];
+  if (self) {
+    _buttonFactory = factory;
+  }
+  return self;
 }
 
-#pragma mark - Setup
-
-// Sets all the subviews and constraints of this view.
 - (void)setUp {
   if (self.subviews.count > 0) {
     // Setup the view only once.
     return;
   }
   DCHECK(self.buttonFactory);
+  DCHECK(self.topSafeAnchor);
 
   self.backgroundColor =
       self.buttonFactory.toolbarConfiguration.backgroundColor;
@@ -111,6 +115,8 @@
   [self setUpConstraints];
 }
 
+#pragma mark - Setup
+
 // Sets the location bar container and its view if present.
 - (void)setUpLocationBar {
   self.locationBarContainer = [[UIView alloc] init];
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.h b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.h
index 3fe1a92..0f7fe0547 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.h
+++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.h
@@ -6,12 +6,14 @@
 #define IOS_CHROME_BROWSER_UI_TOOLBAR_ADAPTIVE_PRIMARY_TOOLBAR_VIEW_CONTROLLER_H_
 
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h"
+#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_ui_updater.h"
 #import "ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.h"
 
 // ViewController for the primary toobar part of the adaptive toolbar. It is the
 // part always displayed and containing the location bar.
 @interface PrimaryToolbarViewController
-    : AdaptiveToolbarViewController<ActivityServicePositioner>
+    : AdaptiveToolbarViewController<ActivityServicePositioner,
+                                    TabHistoryUIUpdater>
 
 // Sets the location bar view, containing the omnibox.
 - (void)setLocationBarView:(UIView*)locationBarView;
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.mm b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.mm
index cc80ca2..4dcc6e1 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.mm
@@ -5,8 +5,11 @@
 #import "ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.h"
 
 #import "base/logging.h"
+#import "ios/chrome/browser/ui/commands/browser_commands.h"
+#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_constants.h"
 #import "ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller+subclassing.h"
 #import "ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.h"
+#import "ios/chrome/browser/ui/toolbar/clean/toolbar_button.h"
 #import "ios/chrome/browser/ui/toolbar/clean/toolbar_constants.h"
 #import "ios/chrome/browser/ui/toolbar/clean/toolbar_tools_menu_button.h"
 #import "ios/chrome/browser/ui/util/named_guide.h"
@@ -41,19 +44,44 @@
 
 - (void)loadView {
   DCHECK(self.buttonFactory);
-  self.view = [[PrimaryToolbarView alloc] init];
-  self.view.buttonFactory = self.buttonFactory;
+
+  self.view =
+      [[PrimaryToolbarView alloc] initWithButtonFactory:self.buttonFactory];
+
   if (@available(iOS 11, *)) {
     self.view.topSafeAnchor = self.view.safeAreaLayoutGuide.topAnchor;
   } else {
     self.view.topSafeAnchor = self.topLayoutGuide.bottomAnchor;
   }
+
+  // This method cannot be called from the init as the topSafeAnchor can only be
+  // set to topLayoutGuide after the view creation on iOS 10.
+  [self.view setUp];
 }
 
 - (void)viewDidLoad {
   [super viewDidLoad];
+
+  // Adds the layout guide to the buttons. Adds the priorities such as the
+  // layout guide constraints does not conflict with others set by other
+  // toolbar.
   self.view.toolsMenuButton.guideName = kTabSwitcherGuide;
-  self.view.toolsMenuButton.constraintPriority = kPrimaryToolbarButtonPriority;
+  self.view.toolsMenuButton.constraintPriority =
+      kPrimaryToolbarTrailingButtonPriority;
+  self.view.forwardLeadingButton.guideName = kForwardButtonGuide;
+  self.view.forwardLeadingButton.constraintPriority =
+      kPrimaryToolbarLeadingButtonPriority;
+  self.view.forwardTrailingButton.guideName = kForwardButtonGuide;
+  self.view.forwardTrailingButton.constraintPriority =
+      kPrimaryToolbarTrailingButtonPriority;
+  self.view.backButton.guideName = kBackButtonGuide;
+  self.view.backButton.constraintPriority =
+      kPrimaryToolbarLeadingButtonPriority;
+
+  // Add navigation popup menu triggers.
+  [self addLongPressGestureToView:self.view.backButton];
+  [self addLongPressGestureToView:self.view.forwardLeadingButton];
+  [self addLongPressGestureToView:self.view.forwardTrailingButton];
 }
 
 #pragma mark - Property accessors
@@ -68,4 +96,45 @@
   return self.view.shareButton;
 }
 
+#pragma mark - TabHistoryUIUpdater
+
+- (void)updateUIForTabHistoryPresentationFrom:(ToolbarButtonType)buttonType {
+  if (buttonType == ToolbarButtonTypeBack) {
+    self.view.backButton.selected = YES;
+  } else {
+    self.view.forwardLeadingButton.selected = YES;
+    self.view.forwardTrailingButton.selected = YES;
+  }
+}
+
+- (void)updateUIForTabHistoryWasDismissed {
+  self.view.backButton.selected = NO;
+  self.view.forwardLeadingButton.selected = NO;
+  self.view.forwardTrailingButton.selected = NO;
+}
+
+#pragma mark - Private
+
+// Adds a LongPressGesture to the |view|, with target on -|handleLongPress:|.
+- (void)addLongPressGestureToView:(UIView*)view {
+  UILongPressGestureRecognizer* navigationHistoryLongPress =
+      [[UILongPressGestureRecognizer alloc]
+          initWithTarget:self
+                  action:@selector(handleLongPress:)];
+  [view addGestureRecognizer:navigationHistoryLongPress];
+}
+
+// Handles the long press on the views.
+- (void)handleLongPress:(UILongPressGestureRecognizer*)gesture {
+  if (gesture.state != UIGestureRecognizerStateBegan)
+    return;
+
+  if (gesture.view == self.view.backButton) {
+    [self.dispatcher showTabHistoryPopupForBackwardHistory];
+  } else if (gesture.view == self.view.forwardLeadingButton ||
+             gesture.view == self.view.forwardTrailingButton) {
+    [self.dispatcher showTabHistoryPopupForForwardHistory];
+  }
+}
+
 @end
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.h b/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.h
index 2594c6f..d7e0d1d 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.h
+++ b/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.h
@@ -9,10 +9,20 @@
 
 #import "ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view.h"
 
+@class ToolbarButtonFactory;
+
 // View for the secondary part of the adaptive toolbar. It is the part
 // containing the controls displayed only on specific size classes.
 @interface SecondaryToolbarView : UIView<AdaptiveToolbarView>
 
+// Initialize this View with the button |factory|.
+- (instancetype)initWithButtonFactory:(ToolbarButtonFactory*)factory
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
+- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
+- (instancetype)init NS_UNAVAILABLE;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_ADAPTIVE_SECONDARY_TOOLBAR_VIEW_H_
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm b/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm
index 078972df1..b6591c98 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm
@@ -17,6 +17,8 @@
 #endif
 
 @interface SecondaryToolbarView ()
+// Factory used to create the buttons.
+@property(nonatomic, strong) ToolbarButtonFactory* buttonFactory;
 
 // Redefined as readwrite
 @property(nonatomic, strong, readwrite) NSArray<ToolbarButton*>* allButtons;
@@ -48,16 +50,20 @@
 @synthesize bookmarkButton = _bookmarkButton;
 @synthesize tabGridButton = _tabGridButton;
 
-#pragma mark - UIView
+#pragma mark - Public
 
-- (void)willMoveToSuperview:(UIView*)newSuperview {
-  [self setUp];
-  [super willMoveToSuperview:newSuperview];
+- (instancetype)initWithButtonFactory:(ToolbarButtonFactory*)factory {
+  self = [super initWithFrame:CGRectZero];
+  if (self) {
+    _buttonFactory = factory;
+    [self setUp];
+  }
+  return self;
 }
 
 #pragma mark - Setup
 
-// Sets all the subviews and constraints of this view.
+// Sets all the subviews and constraints of the view.
 - (void)setUp {
   if (self.subviews.count > 0) {
     // Make sure the view is instantiated only once.
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view_controller.mm b/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view_controller.mm
index 83b4478a..51d04e1 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view_controller.mm
@@ -24,8 +24,8 @@
 #pragma mark - UIViewController
 
 - (void)loadView {
-  self.view = [[SecondaryToolbarView alloc] init];
-  self.view.buttonFactory = self.buttonFactory;
+  self.view =
+      [[SecondaryToolbarView alloc] initWithButtonFactory:self.buttonFactory];
 }
 
 - (void)viewDidLoad {
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_button.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_button.mm
index df8bee8..cd35541 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_button.mm
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_button.mm
@@ -58,23 +58,6 @@
   _guideName = guideName;
   [NSLayoutConstraint deactivateConstraints:self.namedGuideConstraints];
   self.namedGuideConstraints = nil;
-
-  if (!_guideName)
-    return;
-
-  UILayoutGuide* guide = FindNamedGuide(_guideName, self);
-  if (!guide)
-    return;
-
-  self.namedGuideConstraints = @[
-    [guide.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
-    [guide.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
-    [guide.topAnchor constraintEqualToAnchor:self.topAnchor],
-    [guide.bottomAnchor constraintEqualToAnchor:self.bottomAnchor]
-  ];
-  for (NSLayoutConstraint* constraint in self.namedGuideConstraints) {
-    constraint.priority = self.constraintPriority;
-  }
 }
 
 #pragma mark - Public Methods
@@ -109,9 +92,8 @@
       self.visibilityMask & ToolbarComponentVisibilityIPhoneOnly) {
     newHiddenValue = NO;
   }
-  if (isCompactWidth &&
-      (self.visibilityMask &
-       ToolbarComponentVisibilityCompactWidthOnlyWhenEnabled)) {
+  if (newHiddenValue &&
+      self.visibilityMask & ToolbarComponentVisibilityOnlyWhenEnabled) {
     newHiddenValue = !self.enabled;
   }
 
@@ -132,6 +114,25 @@
 // and hiddenInCurrentState properties, then updates its visibility accordingly.
 - (void)setHiddenForCurrentStateAndSizeClass {
   self.hidden = self.hiddenInCurrentState || self.hiddenInCurrentSizeClass;
+
+  if (!self.namedGuideConstraints && self.guideName) {
+    // The guide name can be set before the button is added to the view
+    // hierarchy. Checking here if the constraints are set to prevent it.
+    UILayoutGuide* guide = FindNamedGuide(_guideName, self);
+    if (!guide)
+      return;
+
+    self.namedGuideConstraints = @[
+      [guide.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
+      [guide.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
+      [guide.topAnchor constraintEqualToAnchor:self.topAnchor],
+      [guide.bottomAnchor constraintEqualToAnchor:self.bottomAnchor]
+    ];
+    for (NSLayoutConstraint* constraint in self.namedGuideConstraints) {
+      constraint.priority = self.constraintPriority;
+    }
+  }
+
   if (self.hidden) {
     [NSLayoutConstraint deactivateConstraints:self.namedGuideConstraints];
   } else {
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_button_visibility_configuration.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_button_visibility_configuration.mm
index 3e25b8b6..d8f9cbe 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_button_visibility_configuration.mm
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_button_visibility_configuration.mm
@@ -39,8 +39,7 @@
     case SECONDARY:
       return ToolbarComponentVisibilityNone;
     case LEGACY:
-      return ToolbarComponentVisibilityCompactWidthOnlyWhenEnabled |
-             ToolbarComponentVisibilityRegularWidthCompactHeight |
+      return ToolbarComponentVisibilityOnlyWhenEnabled |
              ToolbarComponentVisibilityRegularWidthRegularHeight;
   }
 }
@@ -88,8 +87,7 @@
     case SECONDARY:
       return ToolbarComponentVisibilitySplit;
     case LEGACY:
-      return ToolbarComponentVisibilityRegularWidthCompactHeight |
-             ToolbarComponentVisibilityRegularWidthRegularHeight;
+      return ToolbarComponentVisibilityRegularWidthRegularHeight;
   }
 }
 
@@ -100,8 +98,7 @@
     case SECONDARY:
       return ToolbarComponentVisibilityNone;
     case LEGACY:
-      return ToolbarComponentVisibilityRegularWidthCompactHeight |
-             ToolbarComponentVisibilityRegularWidthRegularHeight;
+      return ToolbarComponentVisibilityRegularWidthRegularHeight;
   }
 }
 
@@ -112,8 +109,7 @@
     case SECONDARY:
       return ToolbarComponentVisibilityNone;
     case LEGACY:
-      return ToolbarComponentVisibilityRegularWidthCompactHeight |
-             ToolbarComponentVisibilityRegularWidthRegularHeight;
+      return ToolbarComponentVisibilityRegularWidthRegularHeight;
   }
 }
 
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_component_options.h b/ios/chrome/browser/ui/toolbar/clean/toolbar_component_options.h
index a0bc2a6..f7e84ff8 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_component_options.h
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_component_options.h
@@ -34,9 +34,9 @@
   ToolbarComponentVisibilitySplit =
       ToolbarComponentVisibilityCompactWidthRegularHeight,
   // TODO(crbug.com/800266): Remove this, only used for non-adaptive toolbar.
-  // Use this option when the component should be visible in CompactWidth only
-  // if it's enabled. Override other CompactWidth settings.
-  ToolbarComponentVisibilityCompactWidthOnlyWhenEnabled = 1 << 4,
+  // Use this option when the component should be visible only if it's enabled.
+  // This setting applies only if the other settings don't show the button.
+  ToolbarComponentVisibilityOnlyWhenEnabled = 1 << 4,
   // TODO(crbug.com/800266): Remove this, only used for non-adaptive toolbar.
   // Use this option when the component should be always visible on iPhone only.
   ToolbarComponentVisibilityIPhoneOnly = 1 << 5,
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_constants.h b/ios/chrome/browser/ui/toolbar/clean/toolbar_constants.h
index a72fe64be..ff445b1e 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_constants.h
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_constants.h
@@ -55,7 +55,8 @@
 // same to prevent conflicting constraints when a layout guide is changing the
 // button to which it is constrained (there might be a short time during which
 // it is constrained to both buttons).
-extern const UILayoutPriority kPrimaryToolbarButtonPriority;
+extern const UILayoutPriority kPrimaryToolbarLeadingButtonPriority;
+extern const UILayoutPriority kPrimaryToolbarTrailingButtonPriority;
 extern const UILayoutPriority kSecondaryToolbarButtonPriority;
 
 // Maximum number of tabs displayed by the button containing the tab count.
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_constants.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_constants.mm
index 25fc5f9c..686662ca 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_constants.mm
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_constants.mm
@@ -43,9 +43,12 @@
 // UILayoutPriorityRequired aside from the very small time interval during
 // which they are conflicting. Also, it allows to have potentially more
 // priorities.
-const UILayoutPriority kPrimaryToolbarButtonPriority = UILayoutPriorityRequired;
+const UILayoutPriority kPrimaryToolbarLeadingButtonPriority =
+    UILayoutPriorityRequired;
+const UILayoutPriority kPrimaryToolbarTrailingButtonPriority =
+    kPrimaryToolbarLeadingButtonPriority - 1;
 const UILayoutPriority kSecondaryToolbarButtonPriority =
-    kPrimaryToolbarButtonPriority - 1;
+    kPrimaryToolbarTrailingButtonPriority - 1;
 
 const NSInteger kShowTabStripButtonMaxTabCount = 99;
 
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc
index 2955641d..defe179ca 100644
--- a/media/video/gpu_memory_buffer_video_frame_pool.cc
+++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -208,6 +208,9 @@
     case GpuVideoAcceleratorFactories::OutputFormat::UYVY:
       DCHECK_EQ(0u, plane);
       return gfx::BufferFormat::UYVY_422;
+    case GpuVideoAcceleratorFactories::OutputFormat::XR30:
+      DCHECK_EQ(0u, plane);
+      return gfx::BufferFormat::BGRX_1010102;
     case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED:
       NOTREACHED();
       break;
@@ -230,6 +233,11 @@
     case GpuVideoAcceleratorFactories::OutputFormat::UYVY:
       DCHECK_EQ(0u, plane);
       return GL_RGB_YCBCR_422_CHROMIUM;
+    case GpuVideoAcceleratorFactories::OutputFormat::XR30:
+      DCHECK_EQ(0u, plane);
+      // Technically speaking we should say GL_RGB10_EXT, but that format is not
+      // supported in OpenGLES.
+      return GL_RGB10_A2_EXT;
     case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED:
       NOTREACHED();
       break;
@@ -246,6 +254,8 @@
     case GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB:
     case GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB:
       return 2;
+    case GpuVideoAcceleratorFactories::OutputFormat::XR30:
+      return 3;
     case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED:
       NOTREACHED();
       break;
@@ -263,6 +273,8 @@
       return PIXEL_FORMAT_NV12;
     case GpuVideoAcceleratorFactories::OutputFormat::UYVY:
       return PIXEL_FORMAT_UYVY;
+    case GpuVideoAcceleratorFactories::OutputFormat::XR30:
+      return PIXEL_FORMAT_ARGB;
     case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED:
       NOTREACHED();
       break;
@@ -281,6 +293,8 @@
       return 2;
     case GpuVideoAcceleratorFactories::OutputFormat::UYVY:
       return 1;
+    case GpuVideoAcceleratorFactories::OutputFormat::XR30:
+      return 1;
     case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED:
       NOTREACHED();
       break;
@@ -395,6 +409,66 @@
   done.Run();
 }
 
+void CopyRowsToXR30Buffer(int first_row,
+                          int rows,
+                          int width,
+                          const scoped_refptr<VideoFrame>& source_frame,
+                          uint8_t* output,
+                          int dest_stride,
+                          const base::Closure& done) {
+  TRACE_EVENT2("media", "CopyRowsToXR30Buffer", "bytes_per_row", width * 2,
+               "rows", rows);
+  if (output) {
+    DCHECK_NE(dest_stride, 0);
+    DCHECK_LE(width, std::abs(dest_stride / 2));
+    DCHECK_EQ(0, first_row % 2);
+
+    int color_space = COLOR_SPACE_UNSPECIFIED;
+    if (source_frame->metadata()->GetInteger(VideoFrameMetadata::COLOR_SPACE,
+                                             &color_space)) {
+      color_space = COLOR_SPACE_UNSPECIFIED;
+    }
+    const uint16_t* y_plane = reinterpret_cast<const uint16_t*>(
+        source_frame->visible_data(VideoFrame::kYPlane) +
+        first_row * source_frame->stride(VideoFrame::kYPlane));
+    const size_t y_plane_stride = source_frame->stride(VideoFrame::kYPlane) / 2;
+    const uint16_t* v_plane = reinterpret_cast<const uint16_t*>(
+        source_frame->visible_data(VideoFrame::kVPlane) +
+        first_row / 2 * source_frame->stride(VideoFrame::kVPlane));
+    const size_t v_plane_stride = source_frame->stride(VideoFrame::kVPlane) / 2;
+    const uint16_t* u_plane = reinterpret_cast<const uint16_t*>(
+        source_frame->visible_data(VideoFrame::kUPlane) +
+        first_row / 2 * source_frame->stride(VideoFrame::kUPlane));
+    const size_t u_plane_stride = source_frame->stride(VideoFrame::kUPlane) / 2;
+    uint8_t* dest_ar30 = output + first_row * dest_stride;
+
+    // RGB textures need RGB as MatrixID.
+    switch (color_space) {
+      case COLOR_SPACE_HD_REC709:
+        libyuv::H010ToAR30(y_plane, y_plane_stride, v_plane, v_plane_stride,
+                           u_plane, u_plane_stride, dest_ar30, dest_stride,
+                           width, rows);
+        source_frame->set_color_space(gfx::ColorSpace(
+            gfx::ColorSpace::PrimaryID::BT709,
+            gfx::ColorSpace::TransferID::BT709, gfx::ColorSpace::MatrixID::RGB,
+            gfx::ColorSpace::RangeID::LIMITED));
+        break;
+      case COLOR_SPACE_UNSPECIFIED:
+      case COLOR_SPACE_JPEG:
+      case COLOR_SPACE_SD_REC601:
+        libyuv::I010ToAR30(y_plane, y_plane_stride, v_plane, v_plane_stride,
+                           u_plane, u_plane_stride, dest_ar30, dest_stride,
+                           width, rows);
+        source_frame->set_color_space(gfx::ColorSpace(
+            gfx::ColorSpace::PrimaryID::SMPTE170M,
+            gfx::ColorSpace::TransferID::SMPTE170M,
+            gfx::ColorSpace::MatrixID::RGB, gfx::ColorSpace::RangeID::LIMITED));
+        break;
+    }
+  }
+  done.Run();
+}
+
 gfx::Size CodedSize(const scoped_refptr<VideoFrame>& video_frame,
                     GpuVideoAcceleratorFactories::OutputFormat output_format) {
   DCHECK(gfx::Rect(video_frame->coded_size())
@@ -410,6 +484,7 @@
                          (video_frame->visible_rect().height() + 1) & ~1);
       break;
     case GpuVideoAcceleratorFactories::OutputFormat::UYVY:
+    case GpuVideoAcceleratorFactories::OutputFormat::XR30:
       output = gfx::Size((video_frame->visible_rect().width() + 1) & ~1,
                          video_frame->visible_rect().height());
       break;
@@ -642,6 +717,15 @@
                                     static_cast<uint8_t*>(buffer->memory(0)),
                                     buffer->stride(0), barrier));
           break;
+
+        case GpuVideoAcceleratorFactories::OutputFormat::XR30:
+          worker_task_runner_->PostTask(
+              FROM_HERE, base::Bind(&CopyRowsToXR30Buffer, row, rows_to_copy,
+                                    coded_size.width(), video_frame,
+                                    static_cast<uint8_t*>(buffer->memory(0)),
+                                    buffer->stride(0), barrier));
+          break;
+
         case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED:
           NOTREACHED();
       }
@@ -734,6 +818,9 @@
       allow_overlay = true;
 #endif
       break;
+    case GpuVideoAcceleratorFactories::OutputFormat::XR30:
+      allow_overlay = true;
+      break;
     default:
       break;
   }
diff --git a/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc b/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc
index b62af9a..a973f823 100644
--- a/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc
+++ b/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc
@@ -289,6 +289,24 @@
       media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED));
 }
 
+TEST_F(GpuMemoryBufferVideoFramePoolTest, CreateOneHardwareXR30Frame) {
+  scoped_refptr<VideoFrame> software_frame = CreateTestYUVVideoFrame(10, 10);
+  scoped_refptr<VideoFrame> frame;
+  mock_gpu_factories_->SetVideoFrameOutputFormat(
+      media::GpuVideoAcceleratorFactories::OutputFormat::XR30);
+  gpu_memory_buffer_pool_->MaybeCreateHardwareFrame(
+      software_frame, base::Bind(MaybeCreateHardwareFrameCallback, &frame));
+
+  RunUntilIdle();
+
+  EXPECT_NE(software_frame.get(), frame.get());
+  EXPECT_EQ(PIXEL_FORMAT_ARGB, frame->format());
+  EXPECT_EQ(1u, frame->NumTextures());
+  EXPECT_EQ(1u, gles2_->gen_textures_count());
+  EXPECT_TRUE(frame->metadata()->IsTrue(
+      media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED));
+}
+
 // CreateGpuMemoryBuffer can return null (e.g: when the GPU process is down).
 // This test checks that in that case we don't crash and still create the
 // textures.
diff --git a/media/video/gpu_video_accelerator_factories.h b/media/video/gpu_video_accelerator_factories.h
index 2f1678c..e1de25b 100644
--- a/media/video/gpu_video_accelerator_factories.h
+++ b/media/video/gpu_video_accelerator_factories.h
@@ -69,6 +69,7 @@
     UYVY,             // One 422 GMB
     NV12_SINGLE_GMB,  // One NV12 GMB
     NV12_DUAL_GMB,    // One R8, one RG88 GMB
+    XR30,             // 10:10:10:2 BGRX in one GMB
   };
 
   // Return whether GPU encoding/decoding is enabled.
diff --git a/media/video/mock_gpu_video_accelerator_factories.cc b/media/video/mock_gpu_video_accelerator_factories.cc
index 65ce444..51306fd 100644
--- a/media/video/mock_gpu_video_accelerator_factories.cc
+++ b/media/video/mock_gpu_video_accelerator_factories.cc
@@ -27,7 +27,8 @@
     DCHECK(gfx::BufferFormat::R_8 == format_ ||
            gfx::BufferFormat::RG_88 == format_ ||
            gfx::BufferFormat::YUV_420_BIPLANAR == format_ ||
-           gfx::BufferFormat::UYVY_422 == format_);
+           gfx::BufferFormat::UYVY_422 == format_ ||
+           gfx::BufferFormat::BGRX_1010102 == format_);
     DCHECK(num_planes_ <= kMaxPlanes);
     for (int i = 0; i < static_cast<int>(num_planes_); ++i) {
       bytes_[i].resize(gfx::RowSizeForBufferFormat(size_.width(), format_, i) *
diff --git a/mojo/public/tools/bindings/pylib/mojom/parse/ast.py b/mojo/public/tools/bindings/pylib/mojom/parse/ast.py
index 85c7ad64..31084119 100644
--- a/mojo/public/tools/bindings/pylib/mojom/parse/ast.py
+++ b/mojo/public/tools/bindings/pylib/mojom/parse/ast.py
@@ -117,18 +117,21 @@
 class Const(Definition):
   """Represents a const definition."""
 
-  def __init__(self, mojom_name, typename, value, **kwargs):
+  def __init__(self, mojom_name, attribute_list, typename, value, **kwargs):
+    assert attribute_list is None or isinstance(attribute_list, AttributeList)
     # The typename is currently passed through as a string.
     assert isinstance(typename, str)
     # The value is either a literal (currently passed through as a string) or a
     # "wrapped identifier".
     assert isinstance(value, str) or isinstance(value, tuple)
     super(Const, self).__init__(mojom_name, **kwargs)
+    self.attribute_list = attribute_list
     self.typename = typename
     self.value = value
 
   def __eq__(self, other):
     return super(Const, self).__eq__(other) and \
+           self.attribute_list == other.attribute_list and \
            self.typename == other.typename and \
            self.value == other.value
 
diff --git a/mojo/public/tools/bindings/pylib/mojom/parse/parser.py b/mojo/public/tools/bindings/pylib/mojom/parse/parser.py
index 868fb45f..01c69f1 100644
--- a/mojo/public/tools/bindings/pylib/mojom/parse/parser.py
+++ b/mojo/public/tools/bindings/pylib/mojom/parse/parser.py
@@ -383,8 +383,8 @@
                          filename=self.filename, lineno=p.lineno(2))
 
   def p_const(self, p):
-    """const : CONST typename NAME EQUALS constant SEMI"""
-    p[0] = ast.Const(p[3], p[2], p[5])
+    """const : attribute_section CONST typename NAME EQUALS constant SEMI"""
+    p[0] = ast.Const(p[4], p[1], p[3], p[6])
 
   def p_constant(self, p):
     """constant : literal
diff --git a/mojo/public/tools/bindings/pylib/mojom_tests/parse/parser_unittest.py b/mojo/public/tools/bindings/pylib/mojom_tests/parse/parser_unittest.py
index 3f4ca87..0aadefbf 100644
--- a/mojo/public/tools/bindings/pylib/mojom_tests/parse/parser_unittest.py
+++ b/mojo/public/tools/bindings/pylib/mojom_tests/parse/parser_unittest.py
@@ -192,7 +192,7 @@
                           None,
                           ast.EnumValueList(
                               ast.EnumValue('VALUE', None, None))),
-                 ast.Const('kMyConst', 'double', '1.23'),
+                 ast.Const('kMyConst', None, 'double', '1.23'),
                  ast.StructField('a', None, None, 'int32', None),
                  ast.StructField('b', None, None, 'SomeOtherStruct', None)]))])
     self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
@@ -409,7 +409,7 @@
         [ast.Struct(
             'MyStruct', None,
             ast.StructBody(
-                [ast.Const('kNumber', 'int8', '-1'),
+                [ast.Const('kNumber', None, 'int8', '-1'),
                  ast.StructField('number', None, ast.Ordinal(0), 'int8',
                                  ('IDENTIFIER', 'kNumber'))]))])
     self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
@@ -897,7 +897,7 @@
                           None,
                           ast.EnumValueList(
                               ast.EnumValue('VALUE', None, None))),
-                 ast.Const('kMyConst', 'int32', '123'),
+                 ast.Const('kMyConst', None, 'int32', '123'),
                  ast.Method(
                     'MyMethod',
                     None,
@@ -1002,6 +1002,7 @@
         [Attr7=7] interface MyInterface {
           [Attr8=8] MyMethod([Attr9=9] int32 a) => ([Attr10=10] bool b);
         };
+        [Attr11=11] const double kMyConst = 1.23;
         """
     expected4 = ast.Mojom(
         ast.Module(('IDENTIFIER', 'my_module'),
@@ -1044,7 +1045,11 @@
                         ast.Parameter(
                             'b',
                             ast.AttributeList([ast.Attribute("Attr10", 10)]),
-                            None, 'bool')))))])
+                            None, 'bool'))))),
+         ast.Const(
+            'kMyConst',
+            ast.AttributeList(ast.Attribute("Attr11", 11)),
+            'double', '1.23')])
     self.assertEquals(parser.Parse(source4, "my_file.mojom"), expected4)
 
     # TODO(vtl): Boolean attributes don't work yet. (In fact, we just |eval()|
diff --git a/net/cert/internal/verify_name_match.cc b/net/cert/internal/verify_name_match.cc
index 598f43b..858f6fe 100644
--- a/net/cert/internal/verify_name_match.cc
+++ b/net/cert/internal/verify_name_match.cc
@@ -4,9 +4,6 @@
 
 #include "net/cert/internal/verify_name_match.h"
 
-#include <algorithm>
-#include <vector>
-
 #include "base/logging.h"
 #include "base/strings/string_util.h"
 #include "net/cert/internal/cert_error_params.h"
@@ -16,7 +13,6 @@
 #include "net/der/parser.h"
 #include "net/der/tag.h"
 #include "third_party/boringssl/src/include/openssl/bytestring.h"
-#include "third_party/boringssl/src/include/openssl/mem.h"
 
 namespace net {
 
@@ -337,31 +333,17 @@
     if (!ReadRdn(&rdn_parser, &type_and_values))
       return false;
 
-    // The AttributeTypeAndValue objects in the SET OF need to be sorted on
-    // their DER encodings. Encode each individually and save the encoded values
-    // in |encoded_attribute_type_and_values| so that it can be sorted before
-    // being added to |rdn_cbb|. |scoped_encoded_attribute_type_and_values|
-    // owns the |OPENSSL_malloc|ed memory referred to by
-    // |encoded_attribute_type_and_values|.
     CBB rdn_cbb;
     if (!CBB_add_asn1(cbb.get(), &rdn_cbb, CBS_ASN1_SET))
       return false;
-    std::vector<bssl::UniquePtr<uint8_t>>
-        scoped_encoded_attribute_type_and_values;
-    std::vector<der::Input> encoded_attribute_type_and_values;
 
     for (const auto& type_and_value : type_and_values) {
-      // A top-level CBB for encoding each individual AttributeTypeAndValue.
-      bssl::ScopedCBB type_and_value_encoder_cbb;
-      if (!CBB_init(type_and_value_encoder_cbb.get(), 0))
-        return false;
-
       // AttributeTypeAndValue ::= SEQUENCE {
       //   type     AttributeType,
       //   value    AttributeValue }
       CBB attribute_type_and_value_cbb, type_cbb, value_cbb;
-      if (!CBB_add_asn1(type_and_value_encoder_cbb.get(),
-                        &attribute_type_and_value_cbb, CBS_ASN1_SEQUENCE)) {
+      if (!CBB_add_asn1(&rdn_cbb, &attribute_type_and_value_cbb,
+                        CBS_ASN1_SEQUENCE)) {
         return false;
       }
 
@@ -392,36 +374,17 @@
           return false;
       }
 
-      uint8_t* bytes;
-      size_t len;
-      if (!CBB_finish(type_and_value_encoder_cbb.get(), &bytes, &len))
+      if (!CBB_flush(&rdn_cbb))
         return false;
-      scoped_encoded_attribute_type_and_values.push_back(
-          bssl::UniquePtr<uint8_t>(bytes));
-      encoded_attribute_type_and_values.push_back(der::Input(bytes, len));
     }
 
-    std::sort(encoded_attribute_type_and_values.begin(),
-              encoded_attribute_type_and_values.end());
-    for (const auto& encoded_attribute_type_and_value :
-         encoded_attribute_type_and_values) {
-      if (!CBB_add_bytes(&rdn_cbb,
-                         encoded_attribute_type_and_value.UnsafeData(),
-                         encoded_attribute_type_and_value.Length())) {
-        return false;
-      }
-    }
-
-    if (!CBB_flush(cbb.get()))
+    // Ensure the encoded AttributeTypeAndValue values in the SET OF are sorted.
+    if (!CBB_flush_asn1_set_of(&rdn_cbb) || !CBB_flush(cbb.get()))
       return false;
   }
 
-  uint8_t* der;
-  size_t der_len;
-  if (!CBB_finish(cbb.get(), &der, &der_len))
-    return false;
-  normalized_rdn_sequence->assign(der, der + der_len);
-  OPENSSL_free(der);
+  normalized_rdn_sequence->assign(CBB_data(cbb.get()),
+                                  CBB_data(cbb.get()) + CBB_len(cbb.get()));
   return true;
 }
 
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 5367714f..184da1a 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -110,6 +110,7 @@
       enable_quic(false),
       quic_max_packet_length(kDefaultMaxPacketSize),
       quic_max_server_configs_stored_in_properties(0u),
+      quic_enable_socket_recv_optimization(false),
       mark_quic_broken_when_network_blackholes(false),
       retry_without_alt_svc_on_quic_errors(false),
       support_ietf_format_quic_altsvc(false),
@@ -220,7 +221,8 @@
           params.quic_headers_include_h2_stream_dependency,
           params.quic_connection_options,
           params.quic_client_connection_options,
-          params.enable_token_binding),
+          params.enable_token_binding,
+          params.quic_enable_socket_recv_optimization),
       spdy_session_pool_(context.host_resolver,
                          context.ssl_config_service,
                          context.http_server_properties,
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 1bdaf82..fde705f 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -136,6 +136,8 @@
     // Set of QUIC tags to send in the handshake's connection options that only
     // affect the client.
     QuicTagVector quic_client_connection_options;
+    // Enables experimental optimization for receiving data in UDPSocket.
+    bool quic_enable_socket_recv_optimization;
 
     // Active QUIC experiments
 
diff --git a/net/http/http_proxy_client_socket_wrapper_unittest.cc b/net/http/http_proxy_client_socket_wrapper_unittest.cc
index 9d5e034b..a4790be 100644
--- a/net/http/http_proxy_client_socket_wrapper_unittest.cc
+++ b/net/http/http_proxy_client_socket_wrapper_unittest.cc
@@ -133,7 +133,8 @@
         kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
         allow_server_migration_, race_cert_verification_, estimate_initial_rtt_,
         client_headers_include_h2_stream_dependency_, connection_options_,
-        client_connection_options_, /*enable_token_binding=*/false));
+        client_connection_options_, /*enable_token_binding=*/false,
+        /*enable_socket_recv_optimization=*/false));
   }
 
   void PopulateConnectRequestIR(SpdyHeaderBlock* block) {
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc
index d5ed39e..8a96fe6 100644
--- a/net/quic/chromium/quic_stream_factory.cc
+++ b/net/quic/chromium/quic_stream_factory.cc
@@ -739,7 +739,8 @@
     bool headers_include_h2_stream_dependency,
     const QuicTagVector& connection_options,
     const QuicTagVector& client_connection_options,
-    bool enable_token_binding)
+    bool enable_token_binding,
+    bool enable_socket_recv_optimization)
     : require_confirmation_(true),
       net_log_(net_log),
       host_resolver_(host_resolver),
@@ -803,6 +804,7 @@
       num_push_streams_created_(0),
       task_runner_(nullptr),
       ssl_config_service_(ssl_config_service),
+      enable_socket_recv_optimization_(enable_socket_recv_optimization),
       weak_factory_(this) {
   if (ssl_config_service_.get())
     ssl_config_service_->AddObserver(this);
@@ -1328,8 +1330,11 @@
 std::unique_ptr<DatagramClientSocket> QuicStreamFactory::CreateSocket(
     NetLog* net_log,
     const NetLogSource& source) {
-  return client_socket_factory_->CreateDatagramClientSocket(
+  auto socket = client_socket_factory_->CreateDatagramClientSocket(
       DatagramSocket::DEFAULT_BIND, RandIntCallback(), net_log, source);
+  if (enable_socket_recv_optimization_)
+    socket->EnableRecvOptimization();
+  return socket;
 }
 
 void QuicStreamFactory::OnSSLConfigChanged() {
diff --git a/net/quic/chromium/quic_stream_factory.h b/net/quic/chromium/quic_stream_factory.h
index c658634..1fa6bec 100644
--- a/net/quic/chromium/quic_stream_factory.h
+++ b/net/quic/chromium/quic_stream_factory.h
@@ -244,7 +244,8 @@
       bool headers_include_h2_stream_dependency,
       const QuicTagVector& connection_options,
       const QuicTagVector& client_connection_options,
-      bool enable_token_binding);
+      bool enable_token_binding,
+      bool enable_socket_recv_optimization);
   ~QuicStreamFactory() override;
 
   // Returns true if there is an existing session for |server_id| or if the
@@ -578,6 +579,10 @@
 
   const scoped_refptr<SSLConfigService> ssl_config_service_;
 
+  // If set to true, the stream factory will create UDP Sockets with
+  // experimental optimization enabled for receiving data.
+  bool enable_socket_recv_optimization_;
+
   base::WeakPtrFactory<QuicStreamFactory> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(QuicStreamFactory);
diff --git a/net/quic/chromium/quic_stream_factory_fuzzer.cc b/net/quic/chromium/quic_stream_factory_fuzzer.cc
index 55ea51e2..cd5d77af 100644
--- a/net/quic/chromium/quic_stream_factory_fuzzer.cc
+++ b/net/quic/chromium/quic_stream_factory_fuzzer.cc
@@ -100,6 +100,7 @@
   bool estimate_initial_rtt = data_provider.ConsumeBool();
   bool headers_include_h2_stream_dependency = data_provider.ConsumeBool();
   bool enable_token_binding = data_provider.ConsumeBool();
+  bool enable_socket_recv_optimization = data_provider.ConsumeBool();
 
   env->crypto_client_stream_factory.AddProofVerifyDetails(&env->verify_details);
 
@@ -138,7 +139,8 @@
           kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
           allow_server_migration, race_cert_verification, estimate_initial_rtt,
           headers_include_h2_stream_dependency, env->connection_options,
-          env->client_connection_options, enable_token_binding);
+          env->client_connection_options, enable_token_binding,
+          enable_socket_recv_optimization);
 
   QuicStreamRequest request(factory.get());
   TestCompletionCallback callback;
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc
index e3ea082f..0eb7eed 100644
--- a/net/quic/chromium/quic_stream_factory_test.cc
+++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -276,7 +276,8 @@
         kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
         allow_server_migration_, race_cert_verification_, estimate_initial_rtt_,
         client_headers_include_h2_stream_dependency_, connection_options_,
-        client_connection_options_, /*enable_token_binding*/ false));
+        client_connection_options_, /*enable_token_binding*/ false,
+        /*enable_socket_recv_optimization*/ false));
   }
 
   void InitializeConnectionMigrationTest(
diff --git a/net/socket/datagram_client_socket.h b/net/socket/datagram_client_socket.h
index ca656b3..826a2e7 100644
--- a/net/socket/datagram_client_socket.h
+++ b/net/socket/datagram_client_socket.h
@@ -44,6 +44,10 @@
 
   // Apply |tag| to this socket.
   virtual void ApplySocketTag(const SocketTag& tag) = 0;
+
+  // Enables experimental optimization for receiving data from a socket.
+  // By default, this method is no-op.
+  virtual void EnableRecvOptimization() {}
 };
 
 }  // namespace net
diff --git a/net/socket/udp_client_socket.cc b/net/socket/udp_client_socket.cc
index e2eccbb..049a1fca 100644
--- a/net/socket/udp_client_socket.cc
+++ b/net/socket/udp_client_socket.cc
@@ -4,6 +4,7 @@
 
 #include "net/socket/udp_client_socket.h"
 
+#include "build/build_config.h"
 #include "net/base/net_errors.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 
@@ -128,4 +129,10 @@
 #endif
 }
 
+void UDPClientSocket::EnableRecvOptimization() {
+#if defined(OS_POSIX)
+  socket_.enable_experimental_recv_optimization();
+#endif
+}
+
 }  // namespace net
diff --git a/net/socket/udp_client_socket.h b/net/socket/udp_client_socket.h
index 986898c..4abdb27 100644
--- a/net/socket/udp_client_socket.h
+++ b/net/socket/udp_client_socket.h
@@ -50,6 +50,7 @@
   int SetSendBufferSize(int32_t size) override;
   int SetDoNotFragment() override;
   const NetLogWithSource& NetLog() const override;
+  void EnableRecvOptimization() override;
 
   // Switch to use non-blocking IO. Must be called right after construction and
   // before other calls.
diff --git a/net/socket/udp_socket_posix.cc b/net/socket/udp_socket_posix.cc
index f67eff82..6ceb75fa 100644
--- a/net/socket/udp_socket_posix.cc
+++ b/net/socket/udp_socket_posix.cc
@@ -205,7 +205,8 @@
       recv_from_address_(NULL),
       write_buf_len_(0),
       net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::UDP_SOCKET)),
-      bound_network_(NetworkChangeNotifier::kInvalidNetworkHandle) {
+      bound_network_(NetworkChangeNotifier::kInvalidNetworkHandle),
+      experimental_recv_optimization_enabled_(false) {
   net_log_.BeginEvent(NetLogEventType::SOCKET_ALIVE,
                       source.ToEventParametersCallback());
   if (bind_type == DatagramSocket::RANDOM_BIND)
@@ -772,6 +773,47 @@
 int UDPSocketPosix::InternalRecvFrom(IOBuffer* buf,
                                      int buf_len,
                                      IPEndPoint* address) {
+  // If the socket is connected and the remote address is known
+  // use the more efficient method that uses read() instead of recvmsg().
+  if (experimental_recv_optimization_enabled_ && is_connected_ &&
+      remote_address_) {
+    return InternalRecvFromConnectedSocket(buf, buf_len, address);
+  }
+  return InternalRecvFromNonConnectedSocket(buf, buf_len, address);
+}
+
+int UDPSocketPosix::InternalRecvFromConnectedSocket(IOBuffer* buf,
+                                                    int buf_len,
+                                                    IPEndPoint* address) {
+  DCHECK(is_connected_);
+  DCHECK(remote_address_);
+  int bytes_transferred;
+  bytes_transferred = HANDLE_EINTR(read(socket_, buf->data(), buf_len));
+  int result;
+
+  if (bytes_transferred < 0) {
+    result = MapSystemError(errno);
+  } else if (bytes_transferred == buf_len) {
+    result = ERR_MSG_TOO_BIG;
+  } else {
+    result = bytes_transferred;
+    if (address)
+      *address = *remote_address_.get();
+  }
+
+  if (result != ERR_IO_PENDING) {
+    SockaddrStorage sock_addr;
+    bool success =
+        remote_address_->ToSockAddr(sock_addr.addr, &sock_addr.addr_len);
+    DCHECK(success);
+    LogRead(result, buf->data(), sock_addr.addr_len, sock_addr.addr);
+  }
+  return result;
+}
+
+int UDPSocketPosix::InternalRecvFromNonConnectedSocket(IOBuffer* buf,
+                                                       int buf_len,
+                                                       IPEndPoint* address) {
   int bytes_transferred;
 
   struct iovec iov = {};
diff --git a/net/socket/udp_socket_posix.h b/net/socket/udp_socket_posix.h
index fac8d12..65958803 100644
--- a/net/socket/udp_socket_posix.h
+++ b/net/socket/udp_socket_posix.h
@@ -247,6 +247,13 @@
   // Apply |tag| to this socket.
   void ApplySocketTag(const SocketTag& tag);
 
+  // Enables experimental optimization. This method should be called
+  // before the socket is used to read data for the first time.
+  void enable_experimental_recv_optimization() {
+    DCHECK_EQ(kInvalidSocket, socket_);
+    experimental_recv_optimization_enabled_ = true;
+  };
+
  private:
   enum SocketOptions {
     SOCKET_OPTION_MULTICAST_LOOP = 1 << 0
@@ -308,7 +315,27 @@
                     const CompletionCallback& callback);
 
   int InternalConnect(const IPEndPoint& address);
+
+  // Reads data from a UDP socket. Depending whether the socket is connected or
+  // not, the method delegates the call to InternalRecvFromConnectedSocket()
+  // or InternalRecvFromNonConnectedSocket() respectively.
+  // For proper detection of truncated reads, the |buf_len| should always be
+  // one byte longer than the expected maximum packet length.
   int InternalRecvFrom(IOBuffer* buf, int buf_len, IPEndPoint* address);
+
+  // A more efficient implementation of the InternalRecvFrom() method for
+  // reading data from connected sockets. Internally the method uses the read()
+  // system call.
+  int InternalRecvFromConnectedSocket(IOBuffer* buf,
+                                      int buf_len,
+                                      IPEndPoint* address);
+
+  // An implementation of the InternalRecvFrom() method for reading data
+  // from non-connected sockets. Internally the method uses the recvmsg()
+  // system call.
+  int InternalRecvFromNonConnectedSocket(IOBuffer* buf,
+                                         int buf_len,
+                                         IPEndPoint* address);
   int InternalSendTo(IOBuffer* buf, int buf_len, const IPEndPoint* address);
 
   // Applies |socket_options_| to |socket_|. Should be called before
@@ -383,6 +410,12 @@
   // |socket_| is opened.
   SocketTag tag_;
 
+  // If set to true, the socket will use an optimized experimental code path.
+  // By default, the value is set to false. To use the optimization, the
+  // client of the socket has to opt-in by calling the
+  // enable_experimental_recv_optimization() method.
+  bool experimental_recv_optimization_enabled_;
+
   THREAD_CHECKER(thread_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(UDPSocketPosix);
diff --git a/net/socket/udp_socket_unittest.cc b/net/socket/udp_socket_unittest.cc
index 82423090..de48387 100644
--- a/net/socket/udp_socket_unittest.cc
+++ b/net/socket/udp_socket_unittest.cc
@@ -911,6 +911,121 @@
 }
 #endif
 
+TEST_F(UDPSocketTest, ReadWithSocketOptimization) {
+  const uint16_t kPort = 10000;
+  std::string simple_message("hello world!");
+
+  // Setup the server to listen.
+  IPEndPoint server_address(IPAddress::IPv4Localhost(), kPort);
+  UDPServerSocket server(NULL, NetLogSource());
+  server.AllowAddressReuse();
+  int rv = server.Listen(server_address);
+  ASSERT_THAT(rv, IsOk());
+
+  // Setup the client, enable experimental optimization and connected to the
+  // server.
+  UDPClientSocket client(DatagramSocket::DEFAULT_BIND, RandIntCallback(), NULL,
+                         NetLogSource());
+  client.EnableRecvOptimization();
+  rv = client.Connect(server_address);
+  EXPECT_THAT(rv, IsOk());
+
+  // Get the client's address.
+  IPEndPoint client_address;
+  rv = client.GetLocalAddress(&client_address);
+  EXPECT_THAT(rv, IsOk());
+
+  // Server sends the message to the client.
+  rv = SendToSocket(&server, simple_message, client_address);
+  EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv));
+
+  // Client receives the message.
+  std::string str = ReadSocket(&client);
+  EXPECT_EQ(simple_message, str);
+
+  server.Close();
+  client.Close();
+}
+
+// Tests that read from a socket correctly returns
+// |ERR_MSG_TOO_BIG| when the buffer is too small and
+// returns the actual message when it fits the buffer.
+// For the optimized path, the buffer size should be at least
+// 1 byte greater than the message.
+TEST_F(UDPSocketTest, ReadWithSocketOptimizationTruncation) {
+  const uint16_t kPort = 10000;
+  std::string too_long_message(kMaxRead + 1, 'A');
+  std::string right_length_message(kMaxRead - 1, 'B');
+  std::string exact_length_message(kMaxRead, 'C');
+
+  // Setup the server to listen.
+  IPEndPoint server_address(IPAddress::IPv4Localhost(), kPort);
+  UDPServerSocket server(NULL, NetLogSource());
+  server.AllowAddressReuse();
+  int rv = server.Listen(server_address);
+  ASSERT_THAT(rv, IsOk());
+
+  // Setup the client, enable experimental optimization and connected to the
+  // server.
+  UDPClientSocket client(DatagramSocket::DEFAULT_BIND, RandIntCallback(), NULL,
+                         NetLogSource());
+  client.EnableRecvOptimization();
+  rv = client.Connect(server_address);
+  EXPECT_THAT(rv, IsOk());
+
+  // Get the client's address.
+  IPEndPoint client_address;
+  rv = client.GetLocalAddress(&client_address);
+  EXPECT_THAT(rv, IsOk());
+
+  // Send messages to the client.
+  rv = SendToSocket(&server, too_long_message, client_address);
+  EXPECT_EQ(too_long_message.length(), static_cast<size_t>(rv));
+  rv = SendToSocket(&server, right_length_message, client_address);
+  EXPECT_EQ(right_length_message.length(), static_cast<size_t>(rv));
+  rv = SendToSocket(&server, exact_length_message, client_address);
+  EXPECT_EQ(exact_length_message.length(), static_cast<size_t>(rv));
+
+  // Client receives the messages.
+
+  // 1. The first message is |too_long_message|. Its size exceeds the buffer.
+  // In that case, the client is expected to get |ERR_MSG_TOO_BIG| when the
+  // data is read.
+  TestCompletionCallback callback;
+  rv = client.Read(buffer_.get(), kMaxRead, callback.callback());
+  rv = callback.GetResult(rv);
+  EXPECT_EQ(ERR_MSG_TOO_BIG, rv);
+
+  // 2. The second message is |right_length_message|. Its size is
+  // one byte smaller than the size of the buffer. In that case, the client
+  // is expected to read the whole message successfully.
+  rv = client.Read(buffer_.get(), kMaxRead, callback.callback());
+  rv = callback.GetResult(rv);
+  EXPECT_EQ(static_cast<int>(right_length_message.length()), rv);
+  EXPECT_EQ(right_length_message, std::string(buffer_->data(), rv));
+
+  // 3. The third message is |exact_length_message|. Its size is equal to
+  // the read buffer size. In that case, the client expects to get
+  // |ERR_MSG_TOO_BIG| when the socket is read. Internally, the optimized
+  // path uses read() system call that requires one extra byte to detect
+  // truncated messages; therefore, messages that fill the buffer exactly
+  // are considered truncated.
+  // The optimization is only enabled on POSIX platforms. On Windows,
+  // the optimization is turned off; therefore, the client
+  // should be able to read the whole message without encountering
+  // |ERR_MSG_TOO_BIG|.
+  rv = client.Read(buffer_.get(), kMaxRead, callback.callback());
+  rv = callback.GetResult(rv);
+#if defined(OS_POSIX)
+  EXPECT_EQ(ERR_MSG_TOO_BIG, rv);
+#else
+  EXPECT_EQ(static_cast<int>(exact_length_message.length()), rv);
+  EXPECT_EQ(exact_length_message, std::string(buffer_->data(), rv));
+#endif
+  server.Close();
+  client.Close();
+}
+
 // On Android, where socket tagging is supported, verify that UDPSocket::Tag
 // works as expected.
 #if defined(OS_ANDROID)
diff --git a/pdf/BUILD.gn b/pdf/BUILD.gn
index a68f013..34c33a4 100644
--- a/pdf/BUILD.gn
+++ b/pdf/BUILD.gn
@@ -4,7 +4,6 @@
 
 import("//build/buildflag_header.gni")
 import("//build/config/features.gni")
-import("//build/config/jumbo.gni")
 import("//pdf/features.gni")
 import("//testing/test.gni")
 import("//third_party/pdfium/pdfium.gni")
@@ -18,10 +17,9 @@
 if (enable_pdf) {
   pdf_engine = 0  # 0 PDFium
 
-  jumbo_component("pdf") {
+  static_library("pdf") {
     deps = [
       "//base",
-      "//base:i18n",
       "//gin",
       "//net",
       "//ppapi/cpp:objects",
@@ -30,11 +28,6 @@
       "//ui/gfx/range",
     ]
 
-    public = [
-      "pdf.h",
-      "pdf_ppapi.h",
-    ]
-
     sources = [
       "chunk_stream.h",
       "document_loader.cc",
@@ -51,9 +44,6 @@
       "pdf.h",
       "pdf_engine.cc",
       "pdf_engine.h",
-      "pdf_export.h",
-      "pdf_ppapi.cc",
-      "pdf_ppapi.h",
       "preview_mode_client.cc",
       "preview_mode_client.h",
       "range_set.cc",
@@ -89,10 +79,7 @@
       ]
     }
 
-    defines = [
-      "PDF_IMPLEMENTATION",
-      "PDFIUM_PRINT_TEXT_WITH_GDI",
-    ]
+    defines = [ "PDFIUM_PRINT_TEXT_WITH_GDI" ]
     if (pdf_enable_xfa) {
       defines += [ "PDF_ENABLE_XFA" ]
     }
diff --git a/pdf/document_loader.h b/pdf/document_loader.h
index befe488..52a5070 100644
--- a/pdf/document_loader.h
+++ b/pdf/document_loader.h
@@ -15,19 +15,18 @@
 #include <vector>
 
 #include "pdf/chunk_stream.h"
-#include "pdf/pdf_export.h"
 #include "ppapi/utility/completion_callback_factory.h"
 
 namespace chrome_pdf {
 
 class URLLoaderWrapper;
 
-class PDF_EXPORT DocumentLoader {
+class DocumentLoader {
  public:
   // Number was chosen in crbug.com/78264#c8
   static constexpr uint32_t kDefaultRequestSize = 65536;
 
-  class PDF_EXPORT Client {
+  class Client {
    public:
     virtual ~Client();
 
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc
index 1496ce3..1bb3729a9 100644
--- a/pdf/out_of_process_instance.cc
+++ b/pdf/out_of_process_instance.cc
@@ -329,12 +329,12 @@
                     const std::string& type,
                     const std::string& message,
                     const std::string& default_answer) {
-  const PPB_Instance_Private* ppb_interface =
+  const PPB_Instance_Private* interface =
       reinterpret_cast<const PPB_Instance_Private*>(
           pp::Module::Get()->GetBrowserInterface(
               PPB_INSTANCE_PRIVATE_INTERFACE));
-  pp::VarPrivate window(
-      pp::PASS_REF, ppb_interface->GetWindowObject(instance->pp_instance()));
+  pp::VarPrivate window(pp::PASS_REF,
+                        interface->GetWindowObject(instance->pp_instance()));
   if (default_answer.empty())
     return window.Call(type, message);
   return window.Call(type, message, default_answer);
diff --git a/pdf/pdf.cc b/pdf/pdf.cc
index bde70c9..b8a79d7 100644
--- a/pdf/pdf.cc
+++ b/pdf/pdf.cc
@@ -10,12 +10,75 @@
 #include <windows.h>
 #endif
 
+#include "base/command_line.h"
 #include "base/logging.h"
 #include "pdf/out_of_process_instance.h"
-#include "pdf/pdf_ppapi.h"
+#include "ppapi/c/ppp.h"
+#include "ppapi/cpp/private/internal_module.h"
+#include "ppapi/cpp/private/pdf.h"
+#include "v8/include/v8.h"
 
 namespace chrome_pdf {
 
+namespace {
+
+bool g_sdk_initialized_via_pepper = false;
+
+}  // namespace
+
+PDFModule::PDFModule() = default;
+
+PDFModule::~PDFModule() {
+  if (g_sdk_initialized_via_pepper) {
+    ShutdownSDK();
+    g_sdk_initialized_via_pepper = false;
+  }
+}
+
+bool PDFModule::Init() {
+  return true;
+}
+
+pp::Instance* PDFModule::CreateInstance(PP_Instance instance) {
+  if (!g_sdk_initialized_via_pepper) {
+    v8::StartupData natives;
+    v8::StartupData snapshot;
+    pp::PDF::GetV8ExternalSnapshotData(pp::InstanceHandle(instance),
+                                       &natives.data, &natives.raw_size,
+                                       &snapshot.data, &snapshot.raw_size);
+    if (natives.data) {
+      v8::V8::SetNativesDataBlob(&natives);
+      v8::V8::SetSnapshotDataBlob(&snapshot);
+    }
+    if (!InitializeSDK())
+      return nullptr;
+    g_sdk_initialized_via_pepper = true;
+  }
+
+  return new OutOfProcessInstance(instance);
+}
+
+// Implementation of Global PPP functions ---------------------------------
+int32_t PPP_InitializeModule(PP_Module module_id,
+                             PPB_GetInterface get_browser_interface) {
+  std::unique_ptr<PDFModule> module(new PDFModule);
+  if (!module->InternalInit(module_id, get_browser_interface))
+    return PP_ERROR_FAILED;
+
+  pp::InternalSetModuleSingleton(module.release());
+  return PP_OK;
+}
+
+void PPP_ShutdownModule() {
+  delete pp::Module::Get();
+  pp::InternalSetModuleSingleton(nullptr);
+}
+
+const void* PPP_GetInterface(const char* interface_name) {
+  auto* module = pp::Module::Get();
+  return module ? module->GetPluginInterface(interface_name) : nullptr;
+}
+
 #if defined(OS_WIN)
 bool RenderPDFPageToDC(const void* pdf_buffer,
                        int buffer_size,
@@ -31,7 +94,7 @@
                        bool keep_aspect_ratio,
                        bool center_in_bounds,
                        bool autorotate) {
-  if (!IsSDKInitializedViaPepper()) {
+  if (!g_sdk_initialized_via_pepper) {
     if (!InitializeSDK()) {
       return false;
     }
@@ -44,7 +107,7 @@
       autorotate);
   bool ret = engine_exports->RenderPDFPageToDC(pdf_buffer, buffer_size,
                                                page_number, settings, dc);
-  if (!IsSDKInitializedViaPepper())
+  if (!g_sdk_initialized_via_pepper)
     ShutdownSDK();
 
   return ret;
@@ -68,14 +131,14 @@
                    int buffer_size,
                    int* page_count,
                    double* max_page_width) {
-  if (!IsSDKInitializedViaPepper()) {
+  if (!g_sdk_initialized_via_pepper) {
     if (!InitializeSDK())
       return false;
   }
   PDFEngineExports* engine_exports = PDFEngineExports::Get();
   bool ret = engine_exports->GetPDFDocInfo(pdf_buffer, buffer_size, page_count,
                                            max_page_width);
-  if (!IsSDKInitializedViaPepper())
+  if (!g_sdk_initialized_via_pepper)
     ShutdownSDK();
 
   return ret;
@@ -86,7 +149,7 @@
                            int page_number,
                            double* width,
                            double* height) {
-  if (!IsSDKInitializedViaPepper()) {
+  if (!g_sdk_initialized_via_pepper) {
     if (!chrome_pdf::InitializeSDK())
       return false;
   }
@@ -94,7 +157,7 @@
       chrome_pdf::PDFEngineExports::Get();
   bool ret = engine_exports->GetPDFPageSizeByIndex(pdf_buffer, pdf_buffer_size,
                                                    page_number, width, height);
-  if (!IsSDKInitializedViaPepper())
+  if (!g_sdk_initialized_via_pepper)
     chrome_pdf::ShutdownSDK();
   return ret;
 }
@@ -107,7 +170,7 @@
                            int bitmap_height,
                            int dpi,
                            bool autorotate) {
-  if (!IsSDKInitializedViaPepper()) {
+  if (!g_sdk_initialized_via_pepper) {
     if (!InitializeSDK())
       return false;
   }
@@ -117,7 +180,7 @@
       autorotate);
   bool ret = engine_exports->RenderPDFPageToBitmap(
       pdf_buffer, pdf_buffer_size, page_number, settings, bitmap_buffer);
-  if (!IsSDKInitializedViaPepper())
+  if (!g_sdk_initialized_via_pepper)
     ShutdownSDK();
 
   return ret;
diff --git a/pdf/pdf.h b/pdf/pdf.h
index b4f5f3e..6f69bdb3d 100644
--- a/pdf/pdf.h
+++ b/pdf/pdf.h
@@ -5,8 +5,6 @@
 #ifndef PDF_PDF_H_
 #define PDF_PDF_H_
 
-#include "build/build_config.h"
-#include "pdf/pdf_export.h"
 #include "ppapi/c/ppb.h"
 #include "ppapi/cpp/module.h"
 
@@ -22,6 +20,21 @@
 
 namespace chrome_pdf {
 
+class PDFModule : public pp::Module {
+ public:
+  PDFModule();
+  ~PDFModule() override;
+
+  // pp::Module implementation.
+  bool Init() override;
+  pp::Instance* CreateInstance(PP_Instance instance) override;
+};
+
+int PPP_InitializeModule(PP_Module module_id,
+                         PPB_GetInterface get_browser_interface);
+void PPP_ShutdownModule();
+const void* PPP_GetInterface(const char* interface_name);
+
 #if defined(OS_WIN)
 // Printing modes - type to convert PDF to for printing
 enum PrintingMode {
@@ -58,35 +71,35 @@
 // |autorotate| specifies whether the final image should be rotated to match
 //     the output bound.
 // Returns false if the document or the page number are not valid.
-PDF_EXPORT bool RenderPDFPageToDC(const void* pdf_buffer,
-                                  int buffer_size,
-                                  int page_number,
-                                  HDC dc,
-                                  int dpi,
-                                  int bounds_origin_x,
-                                  int bounds_origin_y,
-                                  int bounds_width,
-                                  int bounds_height,
-                                  bool fit_to_bounds,
-                                  bool stretch_to_bounds,
-                                  bool keep_aspect_ratio,
-                                  bool center_in_bounds,
-                                  bool autorotate);
+bool RenderPDFPageToDC(const void* pdf_buffer,
+                       int buffer_size,
+                       int page_number,
+                       HDC dc,
+                       int dpi,
+                       int bounds_origin_x,
+                       int bounds_origin_y,
+                       int bounds_width,
+                       int bounds_height,
+                       bool fit_to_bounds,
+                       bool stretch_to_bounds,
+                       bool keep_aspect_ratio,
+                       bool center_in_bounds,
+                       bool autorotate);
 
-PDF_EXPORT void SetPDFEnsureTypefaceCharactersAccessible(
+void SetPDFEnsureTypefaceCharactersAccessible(
     PDFEnsureTypefaceCharactersAccessible func);
 
-PDF_EXPORT void SetPDFUseGDIPrinting(bool enable);
+void SetPDFUseGDIPrinting(bool enable);
 
-PDF_EXPORT void SetPDFUsePrintMode(int mode);
+void SetPDFUsePrintMode(int mode);
 #endif  // defined(OS_WIN)
 
 // |page_count| and |max_page_width| are optional and can be NULL.
 // Returns false if the document is not valid.
-PDF_EXPORT bool GetPDFDocInfo(const void* pdf_buffer,
-                              int buffer_size,
-                              int* page_count,
-                              double* max_page_width);
+bool GetPDFDocInfo(const void* pdf_buffer,
+                   int buffer_size,
+                   int* page_count,
+                   double* max_page_width);
 
 // Gets the dimensions of a specific page in a document.
 // |pdf_buffer| is the buffer that contains the entire PDF document to be
@@ -97,11 +110,11 @@
 // |width| is the output for the width of the page in points.
 // |height| is the output for the height of the page in points.
 // Returns false if the document or the page number are not valid.
-PDF_EXPORT bool GetPDFPageSizeByIndex(const void* pdf_buffer,
-                                      int pdf_buffer_size,
-                                      int page_number,
-                                      double* width,
-                                      double* height);
+bool GetPDFPageSizeByIndex(const void* pdf_buffer,
+                           int pdf_buffer_size,
+                           int page_number,
+                           double* width,
+                           double* height);
 
 // Renders PDF page into 4-byte per pixel BGRA color bitmap.
 // |pdf_buffer| is the buffer that contains the entire PDF document to be
@@ -115,14 +128,14 @@
 // |autorotate| specifies whether the final image should be rotated to match
 //     the output bound.
 // Returns false if the document or the page number are not valid.
-PDF_EXPORT bool RenderPDFPageToBitmap(const void* pdf_buffer,
-                                      int pdf_buffer_size,
-                                      int page_number,
-                                      void* bitmap_buffer,
-                                      int bitmap_width,
-                                      int bitmap_height,
-                                      int dpi,
-                                      bool autorotate);
+bool RenderPDFPageToBitmap(const void* pdf_buffer,
+                           int pdf_buffer_size,
+                           int page_number,
+                           void* bitmap_buffer,
+                           int bitmap_width,
+                           int bitmap_height,
+                           int dpi,
+                           bool autorotate);
 
 }  // namespace chrome_pdf
 
diff --git a/pdf/pdf_export.h b/pdf/pdf_export.h
deleted file mode 100644
index 8b3fc9e..0000000
--- a/pdf/pdf_export.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2018 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 PDF_PDF_EXPORT_H_
-#define PDF_PDF_EXPORT_H_
-
-#if defined(COMPONENT_BUILD)
-#if defined(WIN32)
-
-#if defined(PDF_IMPLEMENTATION)
-#define PDF_EXPORT __declspec(dllexport)
-#else
-#define PDF_EXPORT __declspec(dllimport)
-#endif  // defined(PDF_IMPLEMENTATION)
-
-#else  // defined(WIN32)
-#if defined(PDF_IMPLEMENTATION)
-#define PDF_EXPORT __attribute__((visibility("default")))
-#else
-#define PDF_EXPORT
-#endif
-#endif
-
-#else  // defined(COMPONENT_BUILD)
-#define PDF_EXPORT
-#endif
-
-#endif  // PDF_PDF_EXPORT_H_
diff --git a/pdf/pdf_ppapi.cc b/pdf/pdf_ppapi.cc
deleted file mode 100644
index 6e68d57..0000000
--- a/pdf/pdf_ppapi.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2018 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 "pdf/pdf_ppapi.h"
-
-#include <memory>
-
-#include "pdf/out_of_process_instance.h"
-#include "ppapi/c/ppp.h"
-#include "ppapi/cpp/private/internal_module.h"
-#include "ppapi/cpp/private/pdf.h"
-#include "v8/include/v8.h"
-
-namespace chrome_pdf {
-
-namespace {
-
-bool g_sdk_initialized_via_pepper = false;
-
-class PDFModule : public pp::Module {
- public:
-  PDFModule();
-  ~PDFModule() override;
-
-  // pp::Module implementation.
-  bool Init() override;
-  pp::Instance* CreateInstance(PP_Instance instance) override;
-};
-
-PDFModule::PDFModule() = default;
-
-PDFModule::~PDFModule() {
-  if (g_sdk_initialized_via_pepper) {
-    ShutdownSDK();
-    g_sdk_initialized_via_pepper = false;
-  }
-}
-
-bool PDFModule::Init() {
-  return true;
-}
-
-pp::Instance* PDFModule::CreateInstance(PP_Instance instance) {
-  if (!g_sdk_initialized_via_pepper) {
-    v8::StartupData natives;
-    v8::StartupData snapshot;
-    pp::PDF::GetV8ExternalSnapshotData(pp::InstanceHandle(instance),
-                                       &natives.data, &natives.raw_size,
-                                       &snapshot.data, &snapshot.raw_size);
-    if (natives.data) {
-      v8::V8::SetNativesDataBlob(&natives);
-      v8::V8::SetSnapshotDataBlob(&snapshot);
-    }
-    if (!InitializeSDK())
-      return nullptr;
-    g_sdk_initialized_via_pepper = true;
-  }
-
-  return new OutOfProcessInstance(instance);
-}
-
-}  // namespace
-
-int32_t PPP_InitializeModule(PP_Module module_id,
-                             PPB_GetInterface get_browser_interface) {
-  auto module = std::make_unique<PDFModule>();
-  if (!module->InternalInit(module_id, get_browser_interface))
-    return PP_ERROR_FAILED;
-
-  pp::InternalSetModuleSingleton(module.release());
-  return PP_OK;
-}
-
-void PPP_ShutdownModule() {
-  delete pp::Module::Get();
-  pp::InternalSetModuleSingleton(nullptr);
-}
-
-const void* PPP_GetInterface(const char* interface_name) {
-  auto* module = pp::Module::Get();
-  return module ? module->GetPluginInterface(interface_name) : nullptr;
-}
-
-bool IsSDKInitializedViaPepper() {
-  return g_sdk_initialized_via_pepper;
-}
-
-}  // namespace chrome_pdf
diff --git a/pdf/pdf_ppapi.h b/pdf/pdf_ppapi.h
deleted file mode 100644
index 68b7e18..0000000
--- a/pdf/pdf_ppapi.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2018 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 PDF_PDF_PPAPI_H_
-#define PDF_PDF_PPAPI_H_
-
-#include "build/build_config.h"
-#include "pdf/pdf_export.h"
-#include "ppapi/c/ppb.h"
-#include "ppapi/cpp/module.h"
-
-namespace chrome_pdf {
-
-PDF_EXPORT int PPP_InitializeModule(PP_Module module_id,
-                                    PPB_GetInterface get_browser_interface);
-PDF_EXPORT void PPP_ShutdownModule();
-PDF_EXPORT const void* PPP_GetInterface(const char* interface_name);
-
-bool IsSDKInitializedViaPepper();
-
-}  // namespace chrome_pdf
-
-#endif  // PDF_PDF_PPAPI_H_
diff --git a/pdf/range_set.h b/pdf/range_set.h
index 66252c0..b615999 100644
--- a/pdf/range_set.h
+++ b/pdf/range_set.h
@@ -11,12 +11,11 @@
 #include <set>
 #include <string>
 
-#include "pdf/pdf_export.h"
 #include "ui/gfx/range/range.h"
 
 namespace chrome_pdf {
 
-class PDF_EXPORT RangeSet {
+class RangeSet {
  public:
   RangeSet();
   explicit RangeSet(const gfx::Range& range);
@@ -72,7 +71,7 @@
 
 }  // namespace chrome_pdf
 
-PDF_EXPORT std::ostream& operator<<(std::ostream& os,
-                                    const chrome_pdf::RangeSet& range_set);
+std::ostream& operator<<(std::ostream& os,
+                         const chrome_pdf::RangeSet& range_set);
 
 #endif  // PDF_RANGE_SET_H_
diff --git a/services/device/BUILD.gn b/services/device/BUILD.gn
index c9dee83e..813b3cc 100644
--- a/services/device/BUILD.gn
+++ b/services/device/BUILD.gn
@@ -28,7 +28,6 @@
   deps = [
     "//base",
     "//device/geolocation",
-    "//device/geolocation/public/interfaces",
     "//device/sensors",
     "//device/sensors/public/interfaces",
     "//services/device/fingerprint",
@@ -96,7 +95,6 @@
     "//base/test:test_support",
     "//device/base/synchronization",
     "//device/geolocation/public/cpp",
-    "//device/geolocation/public/interfaces",
     "//mojo/edk/embedder:headers",
     "//mojo/public/cpp/bindings",
     "//net",
@@ -106,6 +104,7 @@
     "//services/device/power_monitor",
     "//services/device/public/cpp:device_features",
     "//services/device/public/cpp/power_monitor",
+    "//services/device/public/interfaces",
     "//services/device/wake_lock",
     "//testing/gmock",
     "//testing/gtest",
@@ -244,7 +243,9 @@
       "//content/public/android:*",
       "//services:*",
     ]
-    java_files = [ "android/java/src/org/chromium/services/device/InterfaceRegistrar.java" ]
+    java_files = [
+      "android/java/src/org/chromium/services/device/InterfaceRegistrar.java",
+    ]
     deps = [
       "//base:base_java",
       "//mojo/android:system_java",
diff --git a/services/device/device_service.h b/services/device/device_service.h
index 74c49be..5a953ab 100644
--- a/services/device/device_service.h
+++ b/services/device/device_service.h
@@ -9,12 +9,12 @@
 #include "build/build_config.h"
 #include "device/geolocation/geolocation_provider.h"
 #include "device/geolocation/geolocation_provider_impl.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom.h"
 #include "device/screen_orientation/public/interfaces/screen_orientation.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/device/geolocation/public_ip_address_geolocation_provider.h"
 #include "services/device/public/interfaces/battery_monitor.mojom.h"
 #include "services/device/public/interfaces/fingerprint.mojom.h"
+#include "services/device/public/interfaces/geolocation.mojom.h"
 #include "services/device/public/interfaces/geolocation_config.mojom.h"
 #include "services/device/public/interfaces/geolocation_context.mojom.h"
 #include "services/device/public/interfaces/geolocation_control.mojom.h"
diff --git a/services/device/geolocation/public_ip_address_geolocation_provider.h b/services/device/geolocation/public_ip_address_geolocation_provider.h
index a0a0e92..fc435ba 100644
--- a/services/device/geolocation/public_ip_address_geolocation_provider.h
+++ b/services/device/geolocation/public_ip_address_geolocation_provider.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include "base/macros.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/strong_binding_set.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/device/geolocation/public_ip_address_geolocator.h"
 #include "services/device/geolocation/public_ip_address_location_notifier.h"
+#include "services/device/public/interfaces/geolocation.mojom.h"
 #include "services/device/public/interfaces/public_ip_address_geolocation_provider.mojom.h"
 
 namespace device {
diff --git a/services/device/geolocation/public_ip_address_geolocator.h b/services/device/geolocation/public_ip_address_geolocator.h
index a527012..da3d1a74 100644
--- a/services/device/geolocation/public_ip_address_geolocator.h
+++ b/services/device/geolocation/public_ip_address_geolocator.h
@@ -10,10 +10,10 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/time/time.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/device/geolocation/public_ip_address_location_notifier.h"
+#include "services/device/public/interfaces/geolocation.mojom.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 
 namespace device {
 
diff --git a/services/device/geolocation/public_ip_address_location_notifier.h b/services/device/geolocation/public_ip_address_location_notifier.h
index 0f4e84b..d05581ed 100644
--- a/services/device/geolocation/public_ip_address_location_notifier.h
+++ b/services/device/geolocation/public_ip_address_location_notifier.h
@@ -15,9 +15,9 @@
 #include "base/time/time.h"
 #include "device/geolocation/geolocation_provider.h"
 #include "device/geolocation/network_location_request.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "net/base/network_change_notifier.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 
 namespace device {
 
diff --git a/services/device/geolocation/public_ip_address_location_notifier_unittest.cc b/services/device/geolocation/public_ip_address_location_notifier_unittest.cc
index 7744e0a..42b34f6e9 100644
--- a/services/device/geolocation/public_ip_address_location_notifier_unittest.cc
+++ b/services/device/geolocation/public_ip_address_location_notifier_unittest.cc
@@ -9,10 +9,10 @@
 #include "base/strings/stringprintf.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "device/geolocation/public/cpp/geoposition.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_request_test_util.h"
+#include "services/device/public/interfaces/geoposition.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/services/device/public/interfaces/BUILD.gn b/services/device/public/interfaces/BUILD.gn
index 55c288a6..b030770 100644
--- a/services/device/public/interfaces/BUILD.gn
+++ b/services/device/public/interfaces/BUILD.gn
@@ -9,9 +9,11 @@
     "battery_monitor.mojom",
     "battery_status.mojom",
     "fingerprint.mojom",
+    "geolocation.mojom",
     "geolocation_config.mojom",
     "geolocation_context.mojom",
     "geolocation_control.mojom",
+    "geoposition.mojom",
     "hid.mojom",
     "input_service.mojom",
     "nfc.mojom",
@@ -28,7 +30,6 @@
 
   public_deps = [
     ":constants",
-    "//device/geolocation/public/interfaces",
     "//services/network/public/interfaces",
   ]
 
diff --git a/device/geolocation/public/interfaces/geolocation.mojom b/services/device/public/interfaces/geolocation.mojom
similarity index 94%
rename from device/geolocation/public/interfaces/geolocation.mojom
rename to services/device/public/interfaces/geolocation.mojom
index 0dda9e3..4cab503 100644
--- a/device/geolocation/public/interfaces/geolocation.mojom
+++ b/services/device/public/interfaces/geolocation.mojom
@@ -4,7 +4,7 @@
 
 module device.mojom;
 
-import "device/geolocation/public/interfaces/geoposition.mojom";
+import "services/device/public/interfaces/geoposition.mojom";
 
 // Geolocation provides updates on the device's location. By default, it
 // provides updates with low accuracy, but |SetHighAccuracy()| may be called
diff --git a/services/device/public/interfaces/geolocation_context.mojom b/services/device/public/interfaces/geolocation_context.mojom
index e223cfe..147214d7 100644
--- a/services/device/public/interfaces/geolocation_context.mojom
+++ b/services/device/public/interfaces/geolocation_context.mojom
@@ -4,8 +4,8 @@
 
 module device.mojom;
 
-import "device/geolocation/public/interfaces/geolocation.mojom";
-import "device/geolocation/public/interfaces/geoposition.mojom";
+import "services/device/public/interfaces/geolocation.mojom";
+import "services/device/public/interfaces/geoposition.mojom";
 
 // GeolocationContext provides methods to bind Geolocation instance and to
 // set/clear overrides of geoposition that will apply to all Geolocation
diff --git a/device/geolocation/public/interfaces/geoposition.mojom b/services/device/public/interfaces/geoposition.mojom
similarity index 100%
rename from device/geolocation/public/interfaces/geoposition.mojom
rename to services/device/public/interfaces/geoposition.mojom
diff --git a/services/device/public/interfaces/public_ip_address_geolocation_provider.mojom b/services/device/public/interfaces/public_ip_address_geolocation_provider.mojom
index 214912e..8e7287b5 100644
--- a/services/device/public/interfaces/public_ip_address_geolocation_provider.mojom
+++ b/services/device/public/interfaces/public_ip_address_geolocation_provider.mojom
@@ -4,7 +4,7 @@
 
 module device.mojom;
 
-import "device/geolocation/public/interfaces/geolocation.mojom";
+import "services/device/public/interfaces/geolocation.mojom";
 import "services/network/public/interfaces/mutable_partial_network_traffic_annotation_tag.mojom";
 
 // Provides a coarse-grained device.mojom.Geolocation which, subject to
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index e15a13d..569b996 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -970,7 +970,8 @@
       },
       {
         "args": [
-          "--mus"
+          "--mus",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/mus.content_browsertests.filter"
         ],
         "name": "mus_content_browsertests",
         "swarming": {
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 34dfb00c..1d23334 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -7553,16 +7553,6 @@
     ],
     "isolated_scripts": [
       {
-        "args": [
-          "--filter=__main__.ChromeDriverTest.testLoadUrl"
-        ],
-        "isolate_name": "chromedriver_py_tests",
-        "name": "chromedriver_py_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index fc8f1b3..b9ff652f 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -1695,16 +1695,6 @@
     ],
     "isolated_scripts": [
       {
-        "args": [
-          "--filter=__main__.ChromeDriverTest.testLoadUrl"
-        ],
-        "isolate_name": "chromedriver_py_tests",
-        "name": "chromedriver_py_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        }
-      },
-      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
@@ -2330,16 +2320,6 @@
     ],
     "isolated_scripts": [
       {
-        "args": [
-          "--filter=__main__.ChromeDriverTest.testLoadUrl"
-        ],
-        "isolate_name": "chromedriver_py_tests",
-        "name": "chromedriver_py_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
@@ -4569,7 +4549,8 @@
       },
       {
         "args": [
-          "--mus"
+          "--mus",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/mus.content_browsertests.filter"
         ],
         "name": "mus_content_browsertests",
         "swarming": {
@@ -6018,16 +5999,6 @@
     ],
     "isolated_scripts": [
       {
-        "args": [
-          "--filter=__main__.ChromeDriverTest.testLoadUrl"
-        ],
-        "isolate_name": "chromedriver_py_tests",
-        "name": "chromedriver_py_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 137171f1..1e7afe8 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -396,16 +396,6 @@
     ],
     "isolated_scripts": [
       {
-        "args": [
-          "--filter=__main__.ChromeDriverTest.testLoadUrl"
-        ],
-        "isolate_name": "chromedriver_py_tests",
-        "name": "chromedriver_py_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
@@ -843,16 +833,6 @@
     ],
     "isolated_scripts": [
       {
-        "args": [
-          "--filter=__main__.ChromeDriverTest.testLoadUrl"
-        ],
-        "isolate_name": "chromedriver_py_tests",
-        "name": "chromedriver_py_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
@@ -1290,16 +1270,6 @@
     ],
     "isolated_scripts": [
       {
-        "args": [
-          "--filter=__main__.ChromeDriverTest.testLoadUrl"
-        ],
-        "isolate_name": "chromedriver_py_tests",
-        "name": "chromedriver_py_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
@@ -1751,16 +1721,6 @@
     ],
     "isolated_scripts": [
       {
-        "args": [
-          "--filter=__main__.ChromeDriverTest.testLoadUrl"
-        ],
-        "isolate_name": "chromedriver_py_tests",
-        "name": "chromedriver_py_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
         "isolate_name": "content_shell_crash_test",
         "name": "content_shell_crash_test",
         "swarming": {
@@ -2198,16 +2158,6 @@
     ],
     "isolated_scripts": [
       {
-        "args": [
-          "--filter=__main__.ChromeDriverTest.testLoadUrl"
-        ],
-        "isolate_name": "chromedriver_py_tests",
-        "name": "chromedriver_py_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index d299362..6846ac3c 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -996,7 +996,8 @@
       },
       {
         "args": [
-          "--mus"
+          "--mus",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/mus.content_browsertests.filter"
         ],
         "name": "mus_content_browsertests",
         "swarming": {
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index f29c301..640efbf 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -538,16 +538,6 @@
     ],
     "isolated_scripts": [
       {
-        "args": [
-          "--filter=__main__.ChromeDriverTest.testLoadUrl"
-        ],
-        "isolate_name": "chromedriver_py_tests",
-        "name": "chromedriver_py_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
         "isolate_name": "metrics_python_tests",
         "name": "metrics_python_tests",
         "swarming": {
@@ -1717,16 +1707,6 @@
     ],
     "isolated_scripts": [
       {
-        "args": [
-          "--filter=__main__.ChromeDriverTest.testLoadUrl"
-        ],
-        "isolate_name": "chromedriver_py_tests",
-        "name": "chromedriver_py_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
         "isolate_name": "content_shell_crash_test",
         "name": "content_shell_crash_test",
         "swarming": {
@@ -2279,16 +2259,6 @@
     ],
     "isolated_scripts": [
       {
-        "args": [
-          "--filter=__main__.ChromeDriverTest.testLoadUrl"
-        ],
-        "isolate_name": "chromedriver_py_tests",
-        "name": "chromedriver_py_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index 7dc3897..12f156f 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -45,6 +45,7 @@
     "//testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter",
     "//testing/buildbot/filters/site-per-process.content_browsertests.filter",
     "//testing/buildbot/filters/mojo.fyi.viz.content_browsertests.filter",
+    "//testing/buildbot/filters/mus.content_browsertests.filter",
     "//testing/buildbot/filters/viz.content_browsertests.filter",
   ]
 }
diff --git a/testing/buildbot/filters/mojo.fyi.viz.content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.viz.content_browsertests.filter
index 6b57151..4018cd9 100644
--- a/testing/buildbot/filters/mojo.fyi.viz.content_browsertests.filter
+++ b/testing/buildbot/filters/mojo.fyi.viz.content_browsertests.filter
@@ -16,6 +16,7 @@
 -ContentBrowserTestSanityTest.SingleProcess
 -DomSerializerTests.*
 -IndexedDBBrowserTestSingleProcess.RenderThreadShutdownTest
+-InProcessGpuTest.*
 -RenderThreadImplDiscardableMemoryBrowserTest.*
 -RenderViewBrowserTest.ConfirmCacheInformationPlumbed
 -ResourceFetcherTests.*
diff --git a/testing/buildbot/filters/mus.content_browsertests.filter b/testing/buildbot/filters/mus.content_browsertests.filter
new file mode 100644
index 0000000..26f456d
--- /dev/null
+++ b/testing/buildbot/filters/mus.content_browsertests.filter
@@ -0,0 +1,2 @@
+# Crash during shutdown on wrong thread http://crbug.com/785023
+-InProcessGpuTest.*
diff --git a/testing/buildbot/filters/viz.content_browsertests.filter b/testing/buildbot/filters/viz.content_browsertests.filter
index 6b57151..4018cd9 100644
--- a/testing/buildbot/filters/viz.content_browsertests.filter
+++ b/testing/buildbot/filters/viz.content_browsertests.filter
@@ -16,6 +16,7 @@
 -ContentBrowserTestSanityTest.SingleProcess
 -DomSerializerTests.*
 -IndexedDBBrowserTestSingleProcess.RenderThreadShutdownTest
+-InProcessGpuTest.*
 -RenderThreadImplDiscardableMemoryBrowserTest.*
 -RenderViewBrowserTest.ConfirmCacheInformationPlumbed
 -ResourceFetcherTests.*
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 9658a91..34a9258 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -327,6 +327,18 @@
     },
   },
 
+  'chromedriver_py_tests_isolated_scripts': {
+    'chromedriver_py_tests': {
+      "args": [
+        # TODO(johnchen@chromium.org): As the initial step of adding
+        # ChromeDriver tests to commit queue, the following filter is used to
+        # enable a single test case as a smoke test. Many more test cases will
+        # be enabled in the future.
+        "--filter=__main__.ChromeDriverTest.testLoadUrl",
+      ],
+    },
+  },
+
   'chromium_android_asan_gtests': {
     # TODO(kbr): reduce duplication among these tests, and with other
     # test suites.
@@ -745,15 +757,6 @@
   },
 
   'desktop_chromium_isolated_scripts': {
-    'chromedriver_py_tests': {
-      "args": [
-        # TODO(johnchen@chromium.org): As the initial step of adding
-        # ChromeDriver tests to commit queue, the following filter is used to
-        # enable a single test case as a smoke test. Many more test cases will
-        # be enabled in the future.
-        "--filter=__main__.ChromeDriverTest.testLoadUrl",
-      ],
-    },
     'content_shell_crash_test': {},
     'metrics_python_tests': {},
     'telemetry_gpu_unittests': {},
@@ -1084,6 +1087,7 @@
     'mus_content_browsertests': {
       'args': [
         '--mus',
+        '--test-launcher-filter-file=../../testing/buildbot/filters/mus.content_browsertests.filter',
       ],
       'swarming': {
         'shards': 2,
@@ -1949,6 +1953,7 @@
   ],
 
   'chromium_linux_isolated_scripts': [
+    'chromedriver_py_tests_isolated_scripts',
     'desktop_chromium_isolated_scripts',
     'linux_specific_chromium_isolated_scripts',
     'telemetry_perf_unittests_isolated_scripts',
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn
index ed5bc63..9722ed2 100644
--- a/testing/libfuzzer/fuzzers/BUILD.gn
+++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -220,6 +220,13 @@
   libfuzzer_options = [ "max_len=64" ]
 }
 
+fuzzer_test("v8_regexp_builtins_fuzzer") {
+  sources = []
+  deps = [
+    "//v8:regexp_builtins_fuzzer",
+  ]
+}
+
 fuzzer_test("v8_wasm_code_fuzzer") {
   sources = []
   deps = [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 52251d9..cda20cb 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -57,7 +57,6 @@
 
 # New failures are appended below by the script.
 crbug.com/714962 accessibility/adjacent-continuations-cause-assertion-failure.html [ Failure ]
-crbug.com/591099 accessibility/anchor-linked-anonymous-block-crash.html [ Crash ]
 crbug.com/591099 accessibility/aom-decrement-action.html [ Crash Pass ]
 crbug.com/591099 accessibility/aom-increment-action.html [ Crash Pass ]
 crbug.com/591099 accessibility/aom-relation-list-properties.html [ Failure ]
@@ -79,20 +78,18 @@
 crbug.com/591099 accessibility/canvas-fallback-content-2.html [ Crash Timeout ]
 crbug.com/591099 accessibility/canvas-fallback-content-labels.html [ Crash Pass ]
 crbug.com/591099 accessibility/canvas-fallback-content.html [ Failure ]
-crbug.com/591099 accessibility/clickable.html [ Crash ]
 crbug.com/591099 accessibility/color-well.html [ Failure ]
-crbug.com/591099 accessibility/computed-name.html [ Crash ]
-crbug.com/591099 accessibility/computed-role.html [ Crash ]
+crbug.com/591099 accessibility/computed-name.html [ Crash Timeout ]
+crbug.com/591099 accessibility/computed-role.html [ Crash Timeout ]
 crbug.com/591099 accessibility/corresponding-control-deleted-crash.html [ Crash Pass ]
 crbug.com/714962 accessibility/css-first-letter-children.html [ Failure ]
 crbug.com/591099 accessibility/css-generated-content.html [ Failure ]
 crbug.com/591099 accessibility/css-styles.html [ Failure ]
-crbug.com/591099 accessibility/description-calc-summary.html [ Crash ]
 crbug.com/591099 accessibility/disabled-controls-not-focusable.html [ Crash Pass ]
 crbug.com/591099 accessibility/disabled-controls.html [ Crash Failure ]
 crbug.com/714962 accessibility/div-within-anchors-causes-crash.html [ Failure ]
 crbug.com/714962 accessibility/dl-role.html [ Failure ]
-crbug.com/591099 accessibility/element-role-mapping-focusable.html [ Crash ]
+crbug.com/591099 accessibility/element-role-mapping-focusable.html [ Crash Failure ]
 crbug.com/591099 accessibility/element-role-mapping-normal.html [ Crash ]
 crbug.com/714962 accessibility/first-letter-text-transform-causes-crash.html [ Failure ]
 crbug.com/591099 accessibility/focusable-div.html [ Failure ]
@@ -117,7 +114,6 @@
 crbug.com/591099 accessibility/name-calc-aria-owns.html [ Failure ]
 crbug.com/591099 accessibility/name-calc-img.html [ Failure ]
 crbug.com/714962 accessibility/name-calc-inputs.html [ Failure ]
-crbug.com/591099 accessibility/name-calc-summary.html [ Crash ]
 crbug.com/591099 accessibility/presentation-owned-elements.html [ Failure ]
 crbug.com/591099 accessibility/radio-button-title-label.html [ Failure ]
 crbug.com/591099 accessibility/readonly.html [ Crash Failure ]
@@ -1095,7 +1091,6 @@
 crbug.com/714962 editing/pasteboard/copy-paste-pre-line-content.html [ Failure ]
 crbug.com/591099 editing/pasteboard/copy-paste-white-space.html [ Failure ]
 crbug.com/591099 editing/pasteboard/copy-standalone-image.html [ Failure ]
-crbug.com/591099 editing/pasteboard/copy-summary-crash.html [ Crash ]
 crbug.com/714962 editing/pasteboard/drag-drop-copy-text.html [ Failure ]
 crbug.com/714962 editing/pasteboard/drag-drop-input-textarea.html [ Failure ]
 crbug.com/591099 editing/pasteboard/drag-drop-url-text.html [ Failure ]
@@ -1363,6 +1358,7 @@
 crbug.com/714962 external/wpt/css/css-backgrounds/background-image-004.html [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-backgrounds/background-image-005.html [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-backgrounds/background-image-006.html [ Failure Pass ]
+crbug.com/591099 external/wpt/css/css-display/display-contents-details.html [ Crash ]
 crbug.com/714962 external/wpt/css/css-display/display-contents-dynamic-before-after-001.html [ Failure ]
 crbug.com/714962 external/wpt/css/css-display/display-contents-dynamic-before-after-first-letter-001.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-display/display-contents-dynamic-table-001-inline.html [ Failure ]
@@ -1785,7 +1781,7 @@
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-135.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-137.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-139.xht [ Failure Pass ]
-crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-141.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-141.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-143.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-145.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-147.xht [ Failure ]
@@ -2069,23 +2065,23 @@
 crbug.com/591099 external/wpt/css/css-writing-modes/text-indent-vrl-014.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/text-indent-vrl-016.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-016.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001a.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001b.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001c.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001d.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001e.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001f.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001g.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001h.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001i.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001j.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001k.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001l.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001m.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001n.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001o.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001p.html [ Crash ]
-crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001q.html [ Crash ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001a.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001b.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001c.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001d.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001e.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001f.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001g.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001h.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001i.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001j.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001k.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001l.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001m.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001n.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001o.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001p.html [ Crash Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001q.html [ Crash Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/vertical-alignment-005.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/vertical-alignment-007.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/vertical-alignment-vlr-023.xht [ Failure ]
@@ -2269,11 +2265,8 @@
 crbug.com/591099 external/wpt/html-media-capture/capture_video_cancel-manual.html [ Failure ]
 crbug.com/591099 external/wpt/html/browsers/windows/noreferrer-window-name.html [ Timeout ]
 crbug.com/591099 external/wpt/html/dom/documents/dom-tree-accessors/Document.currentScript.html [ Pass ]
-crbug.com/591099 external/wpt/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-newelements-xhtml.xhtml [ Crash ]
-crbug.com/591099 external/wpt/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-newelements.html [ Crash ]
 crbug.com/591099 external/wpt/html/dom/documents/resource-metadata-management/document-lastModified-01.html [ Pass ]
 crbug.com/591099 external/wpt/html/dom/interfaces.html [ Timeout ]
-crbug.com/591099 external/wpt/html/editing/focus/tabindex-focus-flag.html [ Crash ]
 crbug.com/591099 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-16be.html [ Timeout ]
 crbug.com/591099 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-16le.html [ Timeout ]
 crbug.com/591099 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-8.html [ Timeout ]
@@ -2299,9 +2292,6 @@
 crbug.com/591099 external/wpt/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-001.html [ Failure ]
 crbug.com/591099 external/wpt/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-002.html [ Failure ]
 crbug.com/591099 external/wpt/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-003.html [ Failure ]
-crbug.com/591099 external/wpt/html/semantics/grouping-content/the-ol-element/grouping-ol.html [ Crash ]
-crbug.com/591099 external/wpt/html/semantics/interactive-elements/the-details-element/details.html [ Crash ]
-crbug.com/591099 external/wpt/html/semantics/interactive-elements/the-details-element/toggleEvent.html [ Crash ]
 crbug.com/591099 external/wpt/html/semantics/interactive-elements/the-dialog-element/abspos-dialog-layout.html [ Failure ]
 crbug.com/591099 external/wpt/html/semantics/interactive-elements/the-dialog-element/centering.html [ Failure ]
 crbug.com/591099 external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-autofocus-multiple-times.html [ Crash ]
@@ -2310,7 +2300,6 @@
 crbug.com/591099 external/wpt/html/semantics/interactive-elements/the-dialog-element/inert-does-not-match-disabled-selector.html [ Crash ]
 crbug.com/591099 external/wpt/html/semantics/interactive-elements/the-dialog-element/inert-node-is-unfocusable.html [ Crash ]
 crbug.com/591099 external/wpt/html/semantics/interactive-elements/the-dialog-element/show-modal-focusing-steps.html [ Crash ]
-crbug.com/591099 external/wpt/html/semantics/interactive-elements/the-summary-element/activation-behavior.html [ Crash ]
 crbug.com/591099 external/wpt/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html [ Pass ]
 crbug.com/591099 external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports.html [ Pass ]
 crbug.com/591099 external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-classic.html [ Pass ]
@@ -2536,9 +2525,7 @@
 crbug.com/591099 fast/block/basic/quirk-percent-height-grandchild.html [ Failure ]
 crbug.com/591099 fast/block/basic/quirk-percent-height-table-cell.html [ Failure ]
 crbug.com/591099 fast/block/block-add-child-crash.html [ Crash ]
-crbug.com/591099 fast/block/block-remove-child-delete-line-box-crash.html [ Crash ]
 crbug.com/591099 fast/block/block-width-recalc-with-relative-height.html [ Failure ]
-crbug.com/591099 fast/block/child-not-removed-from-parent-lineboxes-crash.html [ Crash ]
 crbug.com/591099 fast/block/containing-block-negative-margins.html [ Failure ]
 crbug.com/591099 fast/block/float-avoids-padding-inline-ancestors.html [ Crash ]
 crbug.com/591099 fast/block/float/003.html [ Failure ]
@@ -2717,7 +2704,6 @@
 crbug.com/591099 fast/css-generated-content/before-with-first-letter.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/beforeAfter-interdocument.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/crash-selection-editing-removes-pseudo.html [ Failure ]
-crbug.com/591099 fast/css-generated-content/details-before-after-content.html [ Crash ]
 crbug.com/591099 fast/css-generated-content/empty-first-letter-with-columns-crash.html [ Crash ]
 crbug.com/591099 fast/css-generated-content/first-letter-in-nested-before-table.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/first-letter-in-nested-before.html [ Failure ]
@@ -2728,7 +2714,6 @@
 crbug.com/591099 fast/css-generated-content/inline-display-types.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/nested-tables-with-before-after-content-crash.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/no-openclose-quote.html [ Failure ]
-crbug.com/591099 fast/css-generated-content/summary-before-after-content.html [ Crash ]
 crbug.com/591099 fast/css-generated-content/table-before-after-child-add.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/table-cell-before-after-child-add.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/table-cell-before-content.html [ Failure ]
@@ -3128,7 +3113,6 @@
 crbug.com/591099 fast/css/transition-color-unspecified.html [ Failure ]
 crbug.com/591099 fast/css/universal-hover-quirk.html [ Failure ]
 crbug.com/591099 fast/css/unknown-pseudo-element-matching.html [ Crash Failure ]
-crbug.com/591099 fast/css/usecounter-summary-display-block.html [ Crash ]
 crbug.com/714962 fast/css/user-drag-none.html [ Crash ]
 crbug.com/591099 fast/css/vertical-align-lengths.html [ Failure ]
 crbug.com/591099 fast/css/vertical-lr-bfc-auto-margins-beside-float.html [ Failure ]
@@ -3289,24 +3273,17 @@
 crbug.com/591099 fast/dom/rtl-scroll-to-leftmost-and-resize.html [ Failure ]
 crbug.com/714962 fast/dom/search-shadow-host-crash.html [ Failure ]
 crbug.com/591099 fast/dom/set-outer-html.html [ Failure ]
-crbug.com/591099 fast/dom/shadow/content-child-whitespace-between-span.html [ Crash ]
 crbug.com/714962 fast/dom/shadow/content-pseudo-element-dynamic-attribute-change.html [ Failure ]
 crbug.com/714962 fast/dom/shadow/cppevent-input-in-shadow.html [ Failure ]
 crbug.com/714962 fast/dom/shadow/drop-event-for-input-in-shadow.html [ Failure ]
-crbug.com/591099 fast/dom/shadow/event-path-for-user-agent-shadow-tree.html [ Crash ]
-crbug.com/591099 fast/dom/shadow/focus-navigation-with-distributed-nodes.html [ Crash ]
 crbug.com/591099 fast/dom/shadow/form-in-shadow.html [ Crash Pass ]
 crbug.com/714962 fast/dom/shadow/import-rule-in-shadow-tree-needs-document-style-recalc.html [ Failure ]
 crbug.com/714962 fast/dom/shadow/input-color-in-content.html [ Timeout ]
-crbug.com/591099 fast/dom/shadow/normalize-progress-element-crash.html [ Crash ]
-crbug.com/591099 fast/dom/shadow/querySelector-for-useragent-shadowroot.html [ Crash ]
+crbug.com/591099 fast/dom/shadow/querySelector-for-useragent-shadowroot.html [ Crash Failure ]
 crbug.com/714962 fast/dom/shadow/scrollbar.html [ Crash ]
 crbug.com/714962 fast/dom/shadow/select-in-shadowdom.html [ Failure Pass ]
 crbug.com/591099 fast/dom/shadow/selections-in-shadow.html [ Timeout ]
 crbug.com/714962 fast/dom/shadow/shadow-boundary-crossing.html [ Failure ]
-crbug.com/591099 fast/dom/shadow/shadow-contents-event.html [ Crash ]
-crbug.com/591099 fast/dom/shadow/shadow-contents-select.html [ Crash ]
-crbug.com/591099 fast/dom/shadow/shadow-dom-event-dispatching-details-summary.html [ Crash ]
 crbug.com/591099 fast/dom/shadow/shadow-dom-event-dispatching-svg-in-shadow-subtree.html [ Failure ]
 crbug.com/714962 fast/dom/shadow/touch-event.html [ Failure ]
 crbug.com/714962 fast/dom/shadow/wheel-event-on-input-in-shadow-dom.html [ Failure ]
@@ -3393,7 +3370,7 @@
 crbug.com/714962 fast/events/contextmenu-follows-focus.html [ Failure ]
 crbug.com/714962 fast/events/contextmenu-scrolled-page-with-frame.html [ Failure ]
 crbug.com/714962 fast/events/document-elementFromPoint.html [ Failure ]
-crbug.com/591099 fast/events/domactivate-sets-underlying-click-event-as-handled.html [ Crash ]
+crbug.com/591099 fast/events/domactivate-sets-underlying-click-event-as-handled.html [ Crash Failure ]
 crbug.com/714962 fast/events/drag-and-drop-subframe-dataTransfer.html [ Timeout ]
 crbug.com/714962 fast/events/drag-dataTransferItemList-file-handling.html [ Failure ]
 crbug.com/714962 fast/events/drag-in-frames.html [ Failure ]
@@ -3506,7 +3483,6 @@
 crbug.com/591099 fast/forms/007.html [ Failure ]
 crbug.com/714962 fast/forms/25153.html [ Failure ]
 crbug.com/591099 fast/forms/ValidityState-customError.html [ Failure ]
-crbug.com/591099 fast/forms/access-key-for-all-elements.html [ Crash ]
 crbug.com/591099 fast/forms/access-key.html [ Failure ]
 crbug.com/591099 fast/forms/activate-and-disabled-elements.html [ Failure ]
 crbug.com/591099 fast/forms/autofilled.html [ Failure ]
@@ -3618,7 +3594,6 @@
 crbug.com/714962 fast/forms/label/continous-click-on-label.html [ Failure ]
 crbug.com/714962 fast/forms/label/hover-on-moving-mouse-checkbox-to-parent-label.html [ Failure ]
 crbug.com/591099 fast/forms/label/label-click.html [ Pass ]
-crbug.com/591099 fast/forms/label/label-contains-other-interactive-content.html [ Crash ]
 crbug.com/591099 fast/forms/label/label-selection-by-textSelection-and-click.html [ Failure ]
 crbug.com/591099 fast/forms/label/selection-disabled-label.html [ Failure Crash ]
 crbug.com/591099 fast/forms/long-text-in-input.html [ Crash Failure ]
@@ -4120,7 +4095,6 @@
 crbug.com/591099 fast/loader/document-with-fragment-url-3.html [ Timeout ]
 crbug.com/591099 fast/loader/document-with-fragment-url-4.html [ Timeout ]
 crbug.com/591099 fast/loader/frame-creation-removal.html [ Failure ]
-crbug.com/591099 fast/loader/javascript-url-iframe-crash.html [ Crash ]
 crbug.com/591099 fast/loader/local-CSS-from-local.html [ Failure ]
 crbug.com/591099 fast/loader/local-JavaScript-from-local.html [ Failure ]
 crbug.com/591099 fast/loader/local-iFrame-source-from-local.html [ Failure ]
@@ -4466,7 +4440,7 @@
 crbug.com/591099 fast/multicol/span/spanner-with-margin.html [ Crash ]
 crbug.com/591099 fast/multicol/span/spanner-with-margins-between-margins.html [ Crash ]
 crbug.com/591099 fast/multicol/span/spanner-with-relpos-child.html [ Failure ]
-crbug.com/591099 fast/multicol/span/summary-split.html [ Crash ]
+crbug.com/591099 fast/multicol/span/summary-split.html [ Crash Failure ]
 crbug.com/591099 fast/multicol/span/trailing-margin-around-spanner.html [ Crash ]
 crbug.com/591099 fast/multicol/span/trailing-margin-before-spanner.html [ Failure ]
 crbug.com/591099 fast/multicol/span/two-rows-then-spanner-then-two-rows.html [ Crash ]
@@ -4655,7 +4629,6 @@
 crbug.com/591099 fast/replaced/width100percent-image.html [ Failure ]
 crbug.com/591099 fast/ruby/add-text-to-block-ruby-with-after-pseudo-crash.html [ Crash ]
 crbug.com/591099 fast/ruby/base-shorter-than-text.html [ Failure ]
-crbug.com/591099 fast/ruby/float-object-doesnt-crash.html [ Crash ]
 crbug.com/591099 fast/ruby/float-overhang-from-ruby-text.html [ Failure ]
 crbug.com/591099 fast/ruby/floating-ruby-text.html [ Failure ]
 crbug.com/591099 fast/ruby/list-item-marker-in-block-ruby.html [ Crash ]
@@ -4932,7 +4905,6 @@
 crbug.com/591099 fast/table/inline-table-margin-baseline.html [ Failure ]
 crbug.com/591099 fast/table/large-shrink-wrapped-width.html [ Failure ]
 crbug.com/591099 fast/table/min-max-width-preferred-size.html [ Failure ]
-crbug.com/591099 fast/table/multiple-captions-crash4.html [ Crash ]
 crbug.com/591099 fast/table/padding-height-and-override-height.html [ Failure ]
 crbug.com/591099 fast/table/percent-height-content-in-fixed-height-border-box-sized-cell-with-collapsed-border-on-table.html [ Failure ]
 crbug.com/591099 fast/table/percent-height-content-in-fixed-height-border-box-sized-cell-with-collapsed-border.html [ Failure ]
@@ -5320,6 +5292,7 @@
 crbug.com/591099 fullscreen/full-screen-css.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-element-stack.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-iframe-not-allowed.html [ Failure ]
+crbug.com/591099 fullscreen/full-screen-remove-ancestor-after.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-ruleset-crash.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-twice-newapi.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-with-css-reference-filter.html [ Crash ]
@@ -5336,79 +5309,68 @@
 crbug.com/714962 hittesting/image-with-clip-path.html [ Failure ]
 crbug.com/591099 hittesting/inline-with-clip-path.html [ Failure ]
 crbug.com/591099 hittesting/inner-border-radius-hittest.html [ Failure ]
-crbug.com/591099 html/details_summary/details-add-child-1.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-child-2.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-details-child-1.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-details-child-2.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-1-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-1.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-10-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-10.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-2-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-2.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-3-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-3.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-4-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-4.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-5-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-5.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-6-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-6.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-7-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-7.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-8-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-8.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-9-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-9.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-child-1.html [ Crash ]
-crbug.com/591099 html/details_summary/details-add-summary-child-2.html [ Crash ]
-crbug.com/591099 html/details_summary/details-children-merge-crash.html [ Crash ]
-crbug.com/591099 html/details_summary/details-click-controls.html [ Crash ]
-crbug.com/591099 html/details_summary/details-clone.html [ Crash ]
-crbug.com/591099 html/details_summary/details-inline.html [ Crash ]
-crbug.com/591099 html/details_summary/details-keyboard-show-hide.html [ Crash ]
-crbug.com/591099 html/details_summary/details-marker-style.html [ Crash ]
-crbug.com/591099 html/details_summary/details-mouse-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-nested-1.html [ Crash ]
-crbug.com/591099 html/details_summary/details-nested-2.html [ Crash ]
-crbug.com/591099 html/details_summary/details-no-summary1.html [ Crash ]
-crbug.com/591099 html/details_summary/details-no-summary2.html [ Crash ]
-crbug.com/591099 html/details_summary/details-no-summary3.html [ Crash ]
-crbug.com/591099 html/details_summary/details-no-summary4.html [ Crash ]
-crbug.com/591099 html/details_summary/details-open-javascript.html [ Crash ]
-crbug.com/591099 html/details_summary/details-open-toggle-event.html [ Crash ]
-crbug.com/591099 html/details_summary/details-open1.html [ Crash ]
-crbug.com/591099 html/details_summary/details-open2.html [ Crash ]
-crbug.com/591099 html/details_summary/details-open3.html [ Crash ]
-crbug.com/591099 html/details_summary/details-open4.html [ Crash ]
-crbug.com/591099 html/details_summary/details-open5.html [ Crash ]
-crbug.com/591099 html/details_summary/details-open6.html [ Crash ]
-crbug.com/591099 html/details_summary/details-position.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-child-1.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-child-2.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-summary-1-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-summary-1.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-summary-2-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-summary-2.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-summary-3-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-summary-3.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-summary-4-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-summary-4.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-summary-5-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-summary-5.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-summary-6-and-click.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-summary-6.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-summary-child-1.html [ Crash ]
-crbug.com/591099 html/details_summary/details-remove-summary-child-2.html [ Crash ]
-crbug.com/591099 html/details_summary/details-replace-summary-child.html [ Crash ]
-crbug.com/591099 html/details_summary/details-replace-text.html [ Crash ]
-crbug.com/591099 html/details_summary/details-writing-mode-align-center.html [ Crash ]
-crbug.com/591099 html/details_summary/details-writing-mode-align-left.html [ Crash ]
-crbug.com/591099 html/details_summary/details-writing-mode-align-right.html [ Crash ]
-crbug.com/591099 html/details_summary/details-writing-mode.html [ Crash ]
-crbug.com/591099 html/details_summary/mutation-details-focus.html [ Crash ]
-crbug.com/591099 html/details_summary/summary-display-flex.html [ Crash ]
-crbug.com/591099 html/details_summary/summary-display-inline-flex.html [ Crash ]
+crbug.com/591099 html/details_summary/details-add-child-1.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-child-2.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-details-child-1.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-details-child-2.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-1-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-1.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-10-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-10.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-2-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-2.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-3-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-3.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-4-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-4.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-5-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-5.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-6-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-6.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-7-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-7.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-8-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-8.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-9-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-9.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-child-1.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-add-summary-child-2.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-nested-1.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-nested-2.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-no-summary1.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-no-summary2.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-no-summary3.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-no-summary4.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-open-javascript.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-open1.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-open2.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-open3.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-open4.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-open5.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-open6.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-position.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-child-1.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-child-2.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-summary-1-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-summary-1.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-summary-2-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-summary-2.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-summary-3-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-summary-3.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-summary-4-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-summary-4.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-summary-5-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-summary-5.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-summary-6-and-click.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-summary-6.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-summary-child-1.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-remove-summary-child-2.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-replace-summary-child.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-replace-text.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-writing-mode-align-center.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-writing-mode-align-left.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-writing-mode-align-right.html [ Crash Failure ]
+crbug.com/591099 html/details_summary/details-writing-mode.html [ Crash Failure ]
 crbug.com/591099 html/dialog/backdrop-descendant-selector.html [ Crash ]
 crbug.com/591099 html/dialog/backdrop-does-not-inherit.html [ Crash ]
 crbug.com/591099 html/dialog/backdrop-dynamic-style-change.html [ Crash ]
@@ -5471,8 +5433,6 @@
 crbug.com/591099 http/tests/devtools/animation/animation-timeline.js [ Crash Pass ]
 crbug.com/591099 http/tests/devtools/animation/animation-transition-setTiming-crash.js [ Crash Pass ]
 crbug.com/591099 http/tests/devtools/animation/animation-web-anim-negative-start-time.js [ Crash Pass ]
-crbug.com/591099 http/tests/devtools/audits2/audits2-limited-run.js [ Crash ]
-crbug.com/591099 http/tests/devtools/audits2/audits2-successful-run.js [ Crash ]
 crbug.com/591099 http/tests/devtools/console/console-functions.js [ Failure ]
 crbug.com/591099 http/tests/devtools/console/console-search.js [ Timeout ]
 crbug.com/591099 http/tests/devtools/console/console-uncaught-promise.js [ Failure ]
@@ -5902,7 +5862,6 @@
 crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-input-buttons.js [ Timeout ]
 crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-input.js [ Timeout ]
 crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-labelledby.js [ Timeout ]
-crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-summary.js [ Crash ]
 crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-visiblity.js [ Timeout ]
 crbug.com/591099 inspector-protocol/css/css-add-rule.js [ Pass Timeout ]
 crbug.com/714962 inspector-protocol/css/css-get-platform-fonts.js [ Failure ]
@@ -6082,7 +6041,7 @@
 crbug.com/591099 paint/invalidation/css-grid-layout/grid-item-change-row-repaint.html [ Failure ]
 crbug.com/591099 paint/invalidation/css-grid-layout/grid-item-z-index-change-repaint.html [ Failure ]
 crbug.com/591099 paint/invalidation/delete-into-nested-block.html [ Failure ]
-crbug.com/591099 paint/invalidation/details-open-repaint.html [ Crash ]
+crbug.com/591099 paint/invalidation/details-open-repaint.html [ Crash Failure ]
 crbug.com/714962 paint/invalidation/empty-object-move-and-resize.html [ Failure ]
 crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-composite-3.html [ Failure ]
 crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-gaussianblur-xonly.html [ Failure ]
@@ -6734,10 +6693,7 @@
 crbug.com/591099 security/autocomplete-cleared-on-back.html [ Failure ]
 crbug.com/591099 shadow-dom/event-composed-ua.html [ Timeout ]
 crbug.com/591099 shadow-dom/focus-navigation-with-delegatesFocus.html [ Timeout ]
-crbug.com/591099 shadow-dom/range-caret-range-from-point-left-of-shadow.html [ Crash ]
 crbug.com/714962 shadow-dom/slotted-pseudo-element-dynamic-attribute-change.html [ Failure ]
-crbug.com/591099 shadow-dom/ua/summary-details-and-ua-shadow.html [ Crash ]
-crbug.com/591099 shadow-dom/ua/summary-details-distribution.html [ Crash ]
 crbug.com/591099 shapedetection/detection-HTMLVideoElement.html [ Pass ]
 crbug.com/714962 storage/indexeddb/blob-basics-metadata.html [ Failure ]
 crbug.com/591099 storage/indexeddb/cursor-advance.html [ Pass Timeout ]
@@ -7448,25 +7404,19 @@
 crbug.com/591099 virtual/incremental-shadow-dom/external/wpt/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-001.html [ Pass ]
 crbug.com/591099 virtual/incremental-shadow-dom/external/wpt/shadow-dom/untriaged/shadow-trees/shadow-root-002.html [ Pass ]
 crbug.com/591099 virtual/incremental-shadow-dom/external/wpt/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-002.html [ Pass ]
-crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/content-child-whitespace-between-span.html [ Crash ]
 crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/content-pseudo-element-dynamic-attribute-change.html [ Failure ]
 crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/cppevent-input-in-shadow.html [ Failure ]
 crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/drop-event-for-input-in-shadow.html [ Failure ]
-crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/event-path-for-user-agent-shadow-tree.html [ Crash ]
-crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/focus-navigation-with-distributed-nodes.html [ Crash ]
 crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/form-in-shadow.html [ Crash Pass ]
 crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/import-rule-in-shadow-tree-needs-document-style-recalc.html [ Failure ]
 crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/input-color-in-content.html [ Timeout ]
 crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/make-marquee-bold-by-exec-command-crash.html [ Pass ]
 crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/no-renderers-for-light-children.html [ Pass ]
-crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/normalize-progress-element-crash.html [ Crash ]
-crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/querySelector-for-useragent-shadowroot.html [ Crash ]
+crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/querySelector-for-useragent-shadowroot.html [ Crash Failure ]
 crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/scrollbar.html [ Crash ]
 crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/select-in-shadowdom.html [ Failure Pass ]
 crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/selections-in-shadow.html [ Timeout ]
 crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/shadow-boundary-crossing.html [ Failure ]
-crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/shadow-contents-event.html [ Crash ]
-crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/shadow-contents-select.html [ Crash ]
 crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/shadow-dom-event-dispatching-details-summary.html [ Crash ]
 crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/shadow-dom-event-dispatching-svg-in-shadow-subtree.html [ Failure ]
 crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/touch-event.html [ Failure ]
@@ -7482,15 +7432,12 @@
 crbug.com/714962 virtual/incremental-shadow-dom/shadow-dom/focus-navigation-with-delegatesFocus.html [ Timeout ]
 crbug.com/591099 virtual/incremental-shadow-dom/shadow-dom/focus-navigation.html [ Pass ]
 crbug.com/591099 virtual/incremental-shadow-dom/shadow-dom/layout.html [ Pass ]
-crbug.com/591099 virtual/incremental-shadow-dom/shadow-dom/range-caret-range-from-point-left-of-shadow.html [ Crash ]
 crbug.com/591099 virtual/incremental-shadow-dom/shadow-dom/slots-1.html [ Pass ]
 crbug.com/591099 virtual/incremental-shadow-dom/shadow-dom/slots-2.html [ Pass ]
 crbug.com/591099 virtual/incremental-shadow-dom/shadow-dom/slots-dynamic.html [ Pass ]
 crbug.com/591099 virtual/incremental-shadow-dom/shadow-dom/slotted-pseudo-element-dynamic-attribute-change.html [ Failure ]
 crbug.com/591099 virtual/incremental-shadow-dom/shadow-dom/slotted-pseudo-element-shared-style.html [ Pass ]
 crbug.com/591099 virtual/incremental-shadow-dom/shadow-dom/slotted-pseudo-element.html [ Pass ]
-crbug.com/591099 virtual/incremental-shadow-dom/shadow-dom/ua/summary-details-and-ua-shadow.html [ Crash ]
-crbug.com/591099 virtual/incremental-shadow-dom/shadow-dom/ua/summary-details-distribution.html [ Crash ]
 crbug.com/591099 virtual/layout_ng/ [ Skip ]
 crbug.com/591099 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/float-replaced-width-002.xht [ Pass ]
 crbug.com/591099 virtual/layout_ng/external/wpt/css/CSS2/positioning/position-static-001.xht [ Pass ]
@@ -7537,7 +7484,7 @@
 crbug.com/714962 virtual/mouseevent_fractional/fast/events/contextmenu-follows-focus.html [ Failure ]
 crbug.com/714962 virtual/mouseevent_fractional/fast/events/contextmenu-scrolled-page-with-frame.html [ Failure ]
 crbug.com/714962 virtual/mouseevent_fractional/fast/events/document-elementFromPoint.html [ Failure ]
-crbug.com/591099 virtual/mouseevent_fractional/fast/events/domactivate-sets-underlying-click-event-as-handled.html [ Crash ]
+crbug.com/591099 virtual/mouseevent_fractional/fast/events/domactivate-sets-underlying-click-event-as-handled.html [ Crash Failure ]
 crbug.com/714962 virtual/mouseevent_fractional/fast/events/drag-and-drop-subframe-dataTransfer.html [ Timeout ]
 crbug.com/714962 virtual/mouseevent_fractional/fast/events/drag-dataTransferItemList-file-handling.html [ Failure ]
 crbug.com/714962 virtual/mouseevent_fractional/fast/events/drag-in-frames.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
index ff6d600..f9929e5c 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -26,7 +26,6 @@
 Bug(none) external/wpt/service-workers/service-worker/clients-get-client-types.https.html [ Failure ]
 Bug(none) external/wpt/service-workers/service-worker/clients-get.https.html [ Failure ]
 Bug(none) external/wpt/service-workers/service-worker/fetch-event-respond-with-response-body-with-invalid-chunk.https.html [ Failure ]
-Bug(none) external/wpt/service-workers/service-worker/fetch-event.https.html [ Pass Failure Crash ]
 Bug(none) external/wpt/service-workers/service-worker/fetch-frame-resource.https.html [ Pass Failure ]
 Bug(none) external/wpt/service-workers/service-worker/fetch-header-visibility.https.html [ Pass Failure Crash ]
 Bug(none) external/wpt/service-workers/service-worker/fetch-request-resources.https.html [ Pass Failure Crash ]
@@ -122,6 +121,7 @@
 crbug.com/721408 http/tests/inspector-protocol/network/response-interception-with-data-url.js [ Failure Timeout ]
 crbug.com/721408 http/tests/inspector-protocol/network/xhr-interception-auth-fail.js [ Failure ]
 crbug.com/721408 http/tests/inspector-protocol/network/xhr-interception.js [ Timeout ]
+crbug.com/721408 http/tests/inspector-protocol/network/request-interception-referer.js [ Timeout ]
 crbug.com/721408 http/tests/devtools/console/console-uncaught-promise.js [ Failure ]
 crbug.com/721408 http/tests/devtools/sdk/network-interception-wildcard-pattern-matching.js [ Failure ]
 crbug.com/721408 http/tests/devtools/sources/debugger-async/async-callstack-xhrs.js [ Failure Timeout ]
@@ -167,6 +167,9 @@
 Bug(none) plugins/iframe-plugin-bgcolor.html [ Timeout ]
 Bug(none) virtual/mouseevent_fractional/fast/events/attribute-listener-cloned-from-frameless-doc.xhtml [ Timeout ]
 
+# The parent or opener frame might be out-of-process:
+crbug.com/805310 http/tests/devtools/network/oopif-content.js [ Crash Failure ]
+
 # Plugin throttle is not implemented.
 crbug.com/764474 http/tests/security/contentSecurityPolicy/object-src-url-allowed.html [ Failure ]
 crbug.com/764474 http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-cross-site-child-disallowed.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v175 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v175
index caff519..ba18a1b 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v175
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v175
@@ -100,3 +100,6 @@
 crbug.com/771643 tables/table-transform-absolute-position-child.html [ Failure ]
 # Others.
 crbug.com/771643 virtual/threaded/printing/fixed-positioned-scrolled.html [ Failure ]
+
+crbug.com/805134 http/tests/devtools/tracing/scroll-invalidations.js [ Failure ]
+crbug.com/805134 virtual/threaded/http/tests/devtools/tracing/scroll-invalidations.js [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 5148b0c..348fcdaa 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -34,6 +34,8 @@
 #  transforms
 # Some additional bugs that are caused by painting problems are also within this section.
 
+crbug.com/805292 hittesting/image-with-clip-path.html [ Skip ]
+
 # Failures due to SPV2, that don't also fail without SPV2. DO NOT REBASELINE.
 # SPv2 paint properties are still being implemented.
 #
@@ -79,14 +81,18 @@
 crbug.com/769942 virtual/spv175/paint/invalidation/svg/resource-invalidate-on-target-update.svg [ Failure ]
 
 crbug.com/771643 virtual/spv175/compositing/overflow/nested-border-radius-clipping.html [ Failure ]
-crbug.com/771643 virtual/spv175/fast/borders/inline-mask-overlay-image-outset-vertical-rl.html [ Failure ]
-crbug.com/771643 virtual/spv175/fast/borders/inline-mask-overlay-image-outset.html [ Failure ]
-crbug.com/771643 virtual/spv175/fast/borders/inline-mask-overlay-image.html [ Failure ]
+crbug.com/768691 virtual/spv175/fast/borders/inline-mask-overlay-image-outset-vertical-rl.html [ Failure ]
 crbug.com/771643 virtual/spv175/fast/multicol/border-radius-clipped-layer.html [ Failure ]
 crbug.com/771643 virtual/spv175/fast/multicol/mixed-opacity-test.html [ Failure ]
 crbug.com/771643 virtual/spv175/fast/multicol/multicol-svg.html [ Failure ]
 crbug.com/771643 virtual/spv175/paint/invalidation/svg/absolute-sized-content-with-resources.xhtml [ Failure ]
 
+crbug.com/805049 virtual/spv175/compositing/iframes/fixed-position-iframe.html [ Failure ]
+crbug.com/805049 virtual/spv175/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer.html [ Failure ]
+crbug.com/805049 virtual/spv175/paint/invalidation/compositing/fixed-scroll-in-empty-root-layer.html [ Failure ]
+crbug.com/805049 virtual/spv175/paint/invalidation/scroll/fixed-scroll-simple.html [ Failure ]
+crbug.com/805049 virtual/spv175/paint/overflow/fixed-background-scroll-in-frame.html [ Failure ]
+
 # spv175+root-layer-scrolls failures. They also fail with root-layer-scrolls without enable-slimming-paint-v175.
 crbug.com/417782 virtual/spv175/compositing/overflow/border-radius-composited-subframe.html [ Failure ]
 crbug.com/417782 virtual/spv175/paint/invalidation/window-resize/window-resize-vertical-writing-mode.html [ Crash ]
@@ -638,6 +644,7 @@
 
 # Crashing tests in dictionary order.
 crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-cors-xhr.https.html [ Failure Crash ]
+crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-event.https.html [ Crash ]
 crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-event-network-error.https.html [ Crash ]
 crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-request-fallback.https.html [ Crash Failure ]
 crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-request-redirect.https.html [ Crash ]
diff --git a/third_party/WebKit/LayoutTests/crypto/subtle/resources/common.js b/third_party/WebKit/LayoutTests/crypto/subtle/resources/common.js
index 39640d7..afdfa9b 100644
--- a/third_party/WebKit/LayoutTests/crypto/subtle/resources/common.js
+++ b/third_party/WebKit/LayoutTests/crypto/subtle/resources/common.js
@@ -25,6 +25,10 @@
 {
     if (!bytes)
         return null;
+    // "bytes" could be a typed array with a detached buffer, in which case the
+    // constructor below would throw.
+    if (bytes.length === 0)
+        return "";
 
     bytes = new Uint8Array(bytes);
     var hexBytes = [];
diff --git a/third_party/WebKit/LayoutTests/editing/selection/stay-in-textarea.html b/third_party/WebKit/LayoutTests/editing/selection/stay-in-textarea.html
index 1c89fb0..359e6fa 100644
--- a/third_party/WebKit/LayoutTests/editing/selection/stay-in-textarea.html
+++ b/third_party/WebKit/LayoutTests/editing/selection/stay-in-textarea.html
@@ -17,7 +17,7 @@
 
 textarea.focus();
 textarea.setSelectionRange(0, 2);
-var textareaSelection = internals.youngestShadowRoot(textarea).getSelection();
+var textareaSelection = internals.shadowRoot(textarea).getSelection();
 var initialTextareaFocusNode = textareaSelection.focusNode;
 
 var initialFocusNode = window.getSelection().focusNode;
diff --git a/third_party/WebKit/LayoutTests/editing/text-iterator/basic-iteration-shadowdom-expected.txt b/third_party/WebKit/LayoutTests/editing/text-iterator/basic-iteration-shadowdom-expected.txt
index 9364a536..8f47bce 100644
--- a/third_party/WebKit/LayoutTests/editing/text-iterator/basic-iteration-shadowdom-expected.txt
+++ b/third_party/WebKit/LayoutTests/editing/text-iterator/basic-iteration-shadowdom-expected.txt
@@ -3,8 +3,8 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS addShadowTreeWithDivElement(div); range.selectNodeContents(internals.oldestShadowRoot(div)); internals.rangeAsText(range) is "b"
-PASS appendBrElement(internals.oldestShadowRoot(div).childNodes[0]); range.selectNodeContents(internals.oldestShadowRoot(div)); internals.rangeAsText(range) is "b\n"
+PASS addShadowTreeWithDivElement(div); range.selectNodeContents(div.shadowRoot); internals.rangeAsText(range) is "b"
+PASS appendBrElement(div.shadowRoot.childNodes[0]); range.selectNodeContents(div.shadowRoot); internals.rangeAsText(range) is "b\n"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/editing/text-iterator/basic-iteration-shadowdom.html b/third_party/WebKit/LayoutTests/editing/text-iterator/basic-iteration-shadowdom.html
index 17e871553..36dc5d6f 100644
--- a/third_party/WebKit/LayoutTests/editing/text-iterator/basic-iteration-shadowdom.html
+++ b/third_party/WebKit/LayoutTests/editing/text-iterator/basic-iteration-shadowdom.html
@@ -20,7 +20,7 @@
 function addShadowTreeWithDivElement(node)
 {
     node.createShadowRoot();
-    internals.oldestShadowRoot(node).innerHTML = '<div>b</div>';
+    node.shadowRoot.innerHTML = '<div>b</div>';
 }
 
 var testDocument = subframe.contentDocument;
@@ -31,9 +31,9 @@
 
 testDocument.body.innerHTML = '<div>a</div>';
 var div = testDocument.body.childNodes[0];
-shouldBe('addShadowTreeWithDivElement(div); range.selectNodeContents(internals.oldestShadowRoot(div)); internals.rangeAsText(range)', '"b"');
+shouldBe('addShadowTreeWithDivElement(div); range.selectNodeContents(div.shadowRoot); internals.rangeAsText(range)', '"b"');
 
-shouldBe('appendBrElement(internals.oldestShadowRoot(div).childNodes[0]); range.selectNodeContents(internals.oldestShadowRoot(div)); internals.rangeAsText(range)', '"b\\n"');
+shouldBe('appendBrElement(div.shadowRoot.childNodes[0]); range.selectNodeContents(div.shadowRoot); internals.rangeAsText(range)', '"b\\n"');
 
 document.body.removeChild(subframe);
 
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 606a9275..5c4bb1df 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -170238,6 +170238,12 @@
      {}
     ]
    ],
+   "css/css-multicol/multicol-gap-percentage-001.html": [
+    [
+     "/css/css-multicol/multicol-gap-percentage-001.html",
+     {}
+    ]
+   ],
    "css/css-position/position-sticky-bottom.html": [
     [
      "/css/css-position/position-sticky-bottom.html",
@@ -230304,7 +230310,7 @@
    "support"
   ],
   "./lint.whitelist": [
-   "c55f23203c2e4b158dc13d25617031fcbb791744",
+   "fc1e09fcc92c3f54ed75fe93681c5ff0a53d25a4",
    "support"
   ],
   "./update-built-tests.sh": [
@@ -241960,11 +241966,11 @@
    "reftest"
   ],
   "css/CSS2/floats-clear/clear-applies-to-008-ref.xht": [
-   "db9d3c111a4f01fd54c04de57aa592ee0a2babb1",
+   "6c2e5e15021e893db1a60ab205feaf08200d5295",
    "support"
   ],
   "css/CSS2/floats-clear/clear-applies-to-008.xht": [
-   "4dea511a4f95e4b3084a224e992ffc87957a0d28",
+   "7c0e621739b7b88792efacf92e49b98061155c3e",
    "reftest"
   ],
   "css/CSS2/floats-clear/clear-applies-to-009-ref.xht": [
@@ -241980,7 +241986,7 @@
    "visual"
   ],
   "css/CSS2/floats-clear/clear-applies-to-012.xht": [
-   "1e8e5c96d43520b6cdbf20232009a706648414e8",
+   "d6fb4efccca1214e61d3145483b093f2b8c8c7ab",
    "reftest"
   ],
   "css/CSS2/floats-clear/clear-applies-to-013.xht": [
@@ -242196,11 +242202,11 @@
    "reftest"
   ],
   "css/CSS2/floats-clear/float-applies-to-008-ref.xht": [
-   "659238329fb18ea5614ed6334f37f30f1fed9d2f",
+   "a77222162ef2cc0a3065fca9918ce6bff8cd70c8",
    "support"
   ],
   "css/CSS2/floats-clear/float-applies-to-008.xht": [
-   "7324b707a78a81f274a9c8f3cacc33f5126918ee",
+   "ea0589a743f79dae9b5f33df683c126bbfc4c5a5",
    "reftest"
   ],
   "css/CSS2/floats-clear/float-applies-to-008a.xht": [
@@ -242216,7 +242222,7 @@
    "visual"
   ],
   "css/CSS2/floats-clear/float-applies-to-012.xht": [
-   "fb1f1ca067f5c5d97c0ce468c66083fc086a7104",
+   "3703899da92098c3e2d36284e5789bf7467a794a",
    "reftest"
   ],
   "css/CSS2/floats-clear/float-applies-to-013.xht": [
@@ -242564,11 +242570,11 @@
    "reftest"
   ],
   "css/CSS2/floats-clear/floats-028-ref.xht": [
-   "48c364f5ffbd8426889479a03e530d602cd41b49",
+   "50b611939fb7cffa6fa5b4469056589a03e27012",
    "support"
   ],
   "css/CSS2/floats-clear/floats-028.xht": [
-   "1f83cd725b3fdb0aca8d5fa4f660ceae14e48ef6",
+   "229392ae1aa78dd1ffebdaf72faf47bc1a1a0fd5",
    "reftest"
   ],
   "css/CSS2/floats-clear/floats-029-ref.xht": [
@@ -242596,11 +242602,11 @@
    "reftest"
   ],
   "css/CSS2/floats-clear/floats-036-ref.xht": [
-   "5c69b8814fd1285e78e18916f717f41dd19fcfd6",
+   "001a8147de3e6d6290b4581f6c5c4a01461e2324",
    "support"
   ],
   "css/CSS2/floats-clear/floats-036.xht": [
-   "8cfcf886e5410936904b8494db5f7358b3322cab",
+   "cb85400e14a9c7908952cbee62b322d1c7a7b125",
    "reftest"
   ],
   "css/CSS2/floats-clear/floats-037.xht": [
@@ -246544,7 +246550,7 @@
    "reftest"
   ],
   "css/CSS2/normal-flow/inline-table-002-ref.xht": [
-   "f2d793d01506513aa4eb77060654848b08ba81ce",
+   "a72122a5cf0b18fb5ca1ed5bc21d4ffb5adbe9ff",
    "support"
   ],
   "css/CSS2/normal-flow/inline-table-002a.xht": [
@@ -246580,7 +246586,7 @@
    "reftest"
   ],
   "css/CSS2/normal-flow/inline-table-valign-001-ref.xht": [
-   "2dd458188be1b03d22ffd5ff5b50251f68236b88",
+   "e0dda44b942f3ab082d495d9c3ea7cdfb06f5672",
    "support"
   ],
   "css/CSS2/normal-flow/inline-table-valign-001.xht": [
@@ -248876,7 +248882,7 @@
    "reftest"
   ],
   "css/CSS2/normal-flow/width-inherit-001.xht": [
-   "e12ea1ffae7291ba97850bd8c9d26a363e8a3e8d",
+   "b44bc8b00c6a11155958abe91b5b1e77a137d74d",
    "reftest"
   ],
   "css/CSS2/normal-flow/width-non-replaced-inline-001-ref.xht": [
@@ -249696,15 +249702,15 @@
    "visual"
   ],
   "css/CSS2/positioning/abspos-011-ref.xht": [
-   "c235af55f1a48bf1537880675cc07fb540672238",
+   "e2759da948136a4af51259eff808b067e877b4da",
    "support"
   ],
   "css/CSS2/positioning/abspos-011.xht": [
-   "7deaa3e6c992cbc2cdcc8aba918d3896bc21c396",
+   "3b5e6cb42b5b130e6dc63912a34f29a631578004",
    "reftest"
   ],
   "css/CSS2/positioning/abspos-012.xht": [
-   "888c0e9b10f97a37f320f9d947650bd10d0f3126",
+   "e11cb76a18a4eb52554cddf5ea79c2085741f7c5",
    "reftest"
   ],
   "css/CSS2/positioning/abspos-013-ref.xht": [
@@ -249772,7 +249778,7 @@
    "reftest"
   ],
   "css/CSS2/positioning/abspos-027.xht": [
-   "4206e6ba1f6839097eeeedf836b959883bfb0f4b",
+   "92f26a5069fa65e26c24b5ff548757174b491b1b",
    "reftest"
   ],
   "css/CSS2/positioning/abspos-028-ref.xht": [
@@ -250920,11 +250926,11 @@
    "reftest"
   ],
   "css/CSS2/positioning/position-relative-031-ref.xht": [
-   "d8ab20871c04f15927a2421400fc0bd94751d801",
+   "713239d97e9516c8a650c35062a8ac381a977a87",
    "support"
   ],
   "css/CSS2/positioning/position-relative-031.xht": [
-   "3e7ea161ba0c2ca703de599084a12f67841ce8cc",
+   "9ef83749003fb8881335bddbe8a1d4978709fc94",
    "reftest"
   ],
   "css/CSS2/positioning/position-relative-032-ref.xht": [
@@ -250992,11 +250998,11 @@
    "reftest"
   ],
   "css/CSS2/positioning/positioning-float-001-ref.xht": [
-   "6c2415a373b5eda24ddb8718d4d2483a2a2902a3",
+   "fe017fcbf93173ebaa9f320c735c15fa366c04b6",
    "support"
   ],
   "css/CSS2/positioning/positioning-float-001.xht": [
-   "f09c12ed86ca1c628f5cd14af54e5815eef5b3b0",
+   "26a3c992262056846e4ae74695c0cadb4a4993f6",
    "reftest"
   ],
   "css/CSS2/positioning/positioning-float-002-ref.xht": [
@@ -262404,7 +262410,7 @@
    "support"
   ],
   "css/css-flexbox/support/100x100-green.png": [
-   "e5142090341e9557fa0fa8bb44ba2f5114796484",
+   "237282657ba1c809361506de0f7a7185cc7457c4",
    "support"
   ],
   "css/css-flexbox/support/1x1-green.png": [
@@ -271168,7 +271174,7 @@
    "reftest"
   ],
   "css/css-grid/alignment/support/100x100-green.png": [
-   "ff6fda3a436fa54df17a321e2458204fd963dfb2",
+   "237282657ba1c809361506de0f7a7185cc7457c4",
    "support"
   ],
   "css/css-grid/alignment/support/style-change.js": [
@@ -271608,7 +271614,7 @@
    "support"
   ],
   "css/css-grid/grid-items/support/100x100-green.png": [
-   "ff6fda3a436fa54df17a321e2458204fd963dfb2",
+   "237282657ba1c809361506de0f7a7185cc7457c4",
    "support"
   ],
   "css/css-grid/grid-items/support/200x200-green.png": [
@@ -272283,6 +272289,10 @@
    "9294744a72ec5b0fe7622c4a68284daefa9372d9",
    "reftest"
   ],
+  "css/css-multicol/multicol-gap-percentage-001.html": [
+   "e13f8ae08605871e1ae175eed0a83dafae77de31",
+   "testharness"
+  ],
   "css/css-multicol/multicol-height-001-ref.xht": [
    "028a0a0f0137840368c556b59f58deacccd5a063",
    "support"
@@ -273284,11 +273294,11 @@
    "reftest"
   ],
   "css/css-paint-api/invalid-image-constructor-error-ref.html": [
-   "b0c34ee1480fe1108fe8dc53f2bbb2f3ffa1c408",
+   "9ae74dc1b6bc4a2f346d072eca0020e7fd1b39ec",
    "support"
   ],
   "css/css-paint-api/invalid-image-constructor-error.https.html": [
-   "6e73e10076d29e69dad68deca551ad9cb84f82f9",
+   "3fb935202b776ac0669804e7484a6a56667db64a",
    "reftest"
   ],
   "css/css-paint-api/invalid-image-paint-error-ref.html": [
@@ -273296,7 +273306,7 @@
    "support"
   ],
   "css/css-paint-api/invalid-image-paint-error.https.html": [
-   "53ea8b4f95f9afafd145c04c5f5961af19a9eae4",
+   "14d684741bcea0c95b1f50881f489e29abff080c",
    "reftest"
   ],
   "css/css-paint-api/invalid-image-pending-script-ref.html": [
@@ -273304,7 +273314,7 @@
    "support"
   ],
   "css/css-paint-api/invalid-image-pending-script.https.html": [
-   "40cd95de01fb371990dac73777e75bd306d28be9",
+   "780d368f790ae61cd3d9a575213dd8c9cce9a3a6",
    "reftest"
   ],
   "css/css-paint-api/overdraw-ref.html": [
@@ -318916,11 +318926,11 @@
    "testharness"
   ],
   "html/semantics/embedded-content/media-elements/mime-types/canPlayType-expected.txt": [
-   "23df7a0d3de893f1d096fa92de73285f9d9e1966",
+   "9d4548106160dc2fa7c8ebe38f56785d86312799",
    "support"
   ],
   "html/semantics/embedded-content/media-elements/mime-types/canPlayType.html": [
-   "960d7daccac83f48f553edb4d32f1b5919f67dcc",
+   "06c4d54aa102c108a7e51e425933eb2cfb97b920",
    "testharness"
   ],
   "html/semantics/embedded-content/media-elements/networkState_during_loadstart.html": [
@@ -354476,7 +354486,7 @@
    "testharness"
   ],
   "webrtc/RTCPeerConnection-getStats.https-expected.txt": [
-   "3244f1a2c62b5441a4d55dc029a23c133742b108",
+   "faa3a059aafc9d74daf8d0888663788e873eaa68",
    "support"
   ],
   "webrtc/RTCPeerConnection-getStats.https.html": [
@@ -354832,7 +354842,7 @@
    "testharness"
   ],
   "webrtc/RTCStats-helper.js": [
-   "1c18bc44f5694a5a273807c06b7ab8f025dd1530",
+   "f640565a3a6fd6e7f80e8891638b88a1b9fec949",
    "support"
   ],
   "webrtc/RTCTrackEvent-constructor-expected.txt": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/reporting/report-uri-from-child-frame.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/reporting/report-uri-from-child-frame.html
index 3bfde9e..92b1e1be 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/reporting/report-uri-from-child-frame.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/reporting/report-uri-from-child-frame.html
@@ -4,10 +4,24 @@
     <script src="/resources/testharness.js"></script>
     <script src="/resources/testharnessreport.js"></script>
     <title>Reporting works in child iframes.</title>
-    <meta http-equiv="Content-Security-Policy" content="script-src 'self'">
+    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'nonce-abc'">
 </head>
 <body>
-    <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=script-src%20%27self%27&reportCookieName=generate-csp-report'></script>
+    <script nonce="abc">
+      var t1 = async_test("Check that we received a message from the child frame");
+
+      window.onmessage = function(e) {
+        if (e.data == 'cookie set') {
+          var s = document.createElement('script');
+          s.async = true;
+          s.defer = true;
+          s.src = '../support/checkReport.sub.js?reportField=violated-directive&reportValue=script-src%20%27self%27%20%27nonce-abc%27&reportCookieName=generate-csp-report';
+          document.body.appendChild(s);
+
+          t1.done();
+        }
+      }
+    </script>
     <iframe src="support/generate-csp-report.html"/>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/reporting/support/generate-csp-report.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/reporting/support/generate-csp-report.html
index ca4c5d7..c2024c0 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/reporting/support/generate-csp-report.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/reporting/support/generate-csp-report.html
@@ -1,6 +1,9 @@
 <!DOCTYPE html>
 <html>
 <body>
+    <script nonce='abc'>
+      top.postMessage('cookie set', '*');
+    </script>
     <script>
         // This script block will trigger a violation report.
         alert('FAIL');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/reporting/support/generate-csp-report.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/reporting/support/generate-csp-report.html.sub.headers
index 0fd45bf..6d1eedb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/reporting/support/generate-csp-report.html.sub.headers
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/reporting/support/generate-csp-report.html.sub.headers
@@ -3,4 +3,4 @@
 Cache-Control: post-check=0, pre-check=0, false
 Pragma: no-cache
 Set-Cookie: generate-csp-report={{$id:uuid()}}; Path=/content-security-policy/reporting/
-Content-Security-Policy: script-src 'self'; report-uri ../../support/report.py?op=put&reportID={{$id}}
+Content-Security-Policy: script-src 'self' 'nonce-abc'; report-uri ../../support/report.py?op=put&reportID={{$id}}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/support/100x100-green.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/support/100x100-green.png
index 3f07c9e..25b76c3c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/support/100x100-green.png
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/support/100x100-green.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/alignment/support/100x100-green.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/alignment/support/100x100-green.png
index 0dcda08..25b76c3c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/alignment/support/100x100-green.png
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/alignment/support/100x100-green.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/support/100x100-green.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/support/100x100-green.png
index 0dcda08..25b76c3c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/support/100x100-green.png
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/support/100x100-green.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/read-media/pageload-image-in-popup.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/read-media/pageload-image-in-popup.html
new file mode 100644
index 0000000..4d81119
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/read-media/pageload-image-in-popup.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media documents: image</title>
+  <link rel="author" title="Takayoshi Kochi" href="mailto:kochi@chromium.org">
+  <link rel="author" title="Michael Ventnor" href="mailto:mventnor@mozilla.com">
+  <link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+  <link rel="help" href="https://html.spec.whatwg.org/multipage/#read-media">
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+
+<script>
+  var t = async_test("The document for a standalone media file should have one child in the body.");
+
+  var imgwin = window.open('/images/blue.png');
+  // imgwin.onload doesn't work, check popup's URL to see if the loading of
+  // the image and creation of image document is finished.
+  function checkURL() {
+    if (imgwin.location.href.indexOf('blue.png') == -1) {
+      step_timeout(checkURL, 100);
+      return;
+    }
+    t.step(frameLoaded);
+  }
+  checkURL();
+
+  function frameLoaded() {
+    assert_equals(imgwin.opener, window);
+    assert_equals(imgwin.document.contentType, "image/png");
+    var imgwinChildren = imgwin.document.body.childNodes;
+    assert_equals(imgwinChildren.length, 1, "Body of image document has 1 child");
+    assert_equals(imgwinChildren[0].nodeName, "IMG", "Only child of body must be an <img> element");
+    assert_equals(imgwinChildren[0].namespaceURI, "http://www.w3.org/1999/xhtml",
+                  "Only child of body must be an HTML element");
+    imgwin.close();
+    t.done();
+  }
+</script>
+</head>
+<body>
+  <div id="log"></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-forms-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-forms-expected.txt
index 0f9591e..3ec7618 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-forms-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-forms-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 6725 tests; 6675 PASS, 50 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 6725 tests; 6709 PASS, 16 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS form.title: 32 tests
 PASS form.lang: 32 tests
 PASS form.dir: 62 tests
@@ -105,23 +105,7 @@
 PASS select.hidden: 33 tests
 PASS select.accessKey: 32 tests
 PASS select.tabIndex: 24 tests
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
+PASS select.autocomplete: 17 tests
 PASS select.autofocus: 33 tests
 PASS select.disabled: 33 tests
 PASS select.multiple: 33 tests
@@ -162,23 +146,7 @@
 PASS textarea.hidden: 33 tests
 PASS textarea.accessKey: 32 tests
 PASS textarea.tabIndex: 24 tests
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
+PASS textarea.autocomplete: 17 tests
 PASS textarea.autofocus: 33 tests
 PASS textarea.cols: 59 tests
 PASS textarea.dirName: 32 tests
diff --git a/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist b/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist
index b8728fe..2f9b44d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist
+++ b/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist
@@ -585,8 +585,6 @@
 CSS-COLLIDING-SUPPORT-NAME: css/*/LOCK
 
 # These are all the current "merge mismatch" errors the build system produces
-CSS-COLLIDING-SUPPORT-NAME: css/css-flexbox/support/100x100-green.png
-CSS-COLLIDING-SUPPORT-NAME: css/css-grid/grid-items/support/100x100-green.png
 CSS-COLLIDING-SUPPORT-NAME: css/css-flexbox/support/200x200-green.png
 CSS-COLLIDING-SUPPORT-NAME: css/css-grid/grid-items/support/200x200-green.png
 CSS-COLLIDING-SUPPORT-NAME: css/css-regions/contentEditable/support/common.css
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https-expected.txt
index 75de0081..69634f4 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https-expected.txt
@@ -15,7 +15,9 @@
 PASS Service Worker should intercept EventSource
 FAIL Service Worker responds to fetch event with the correct integrity_metadata assert_unreached: unexpected rejection: assert_equals: integrity expected "gs0nqru8KbsrIt5YToQqS9fYao4GQJXtcId610g7cCU=" but got "" Reached unreachable code
 PASS FetchEvent#body is a string
+PASS FetchEvent#body is a string and is passed to network fallback
 PASS FetchEvent#body is a blob
+PASS FetchEvent#body is a blob and is passed to network fallback
 PASS Service Worker responds to fetch event with the correct keepalive value
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https.html
index 240219b0..a960a801 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https.html
@@ -456,6 +456,43 @@
         });
   }, 'FetchEvent#body is a string');
 
+// Test that the request body is sent to network upon network fallback,
+// for a string body.
+promise_test(t => {
+    // Set scope to "?ignore" so the service worker falls back to network
+    // for the main resource request, and add a suffix to avoid colliding
+    // with other tests.
+    const scope = 'resources/?ignore-for-request-body-fallback-string';
+    let frame;
+
+    return service_worker_unregister_and_register(t, worker, scope)
+      .then(reg => {
+          add_completion_callback(() => { reg.unregister(); });
+          return wait_for_state(t, reg.installing, 'activated');
+        })
+      .then(() => {
+          return with_iframe(scope); })
+      .then(f => {
+          frame = f;
+          // Add "?ignore" so the service worker falls back to echo-content.py.
+          const echo_url = '/fetch/api/resources/echo-content.py?ignore';
+          return frame.contentWindow.fetch(echo_url, {
+              method: 'POST',
+              body: 'i am the request body'
+            });
+        })
+      .then(response => {
+          return response.text();
+        })
+      .then(response_text => {
+          frame.remove();
+          assert_equals(
+              response_text,
+              'i am the request body',
+              'the network fallback request should include the request body');
+        });
+  }, 'FetchEvent#body is a string and is passed to network fallback');
+
 // Test that the service worker can read FetchEvent#body when it is a blob.
 // It responds with request body it read.
 promise_test(t => {
@@ -489,6 +526,44 @@
         });
   }, 'FetchEvent#body is a blob');
 
+// Test that the request body is sent to network upon network fallback,
+// for a blob body.
+promise_test(t => {
+    // Set scope to "?ignore" so the service worker falls back to network
+    // for the main resource request, and add a suffix to avoid colliding
+    // with other tests.
+    const scope = 'resources/simple.html?ignore-for-request-body-fallback-blob';
+    let frame;
+
+    return service_worker_unregister_and_register(t, worker, scope)
+      .then(reg => {
+          add_completion_callback(() => { reg.unregister(); });
+          return wait_for_state(t, reg.installing, 'activated');
+        })
+      .then(() => {
+          return with_iframe(scope); })
+      .then(f => {
+          frame = f;
+          const blob = new Blob(['it\'s me the blob', ' ', 'and more blob!']);
+          // Add "?ignore" so the service worker falls back to echo-content.py.
+          const echo_url = '/fetch/api/resources/echo-content.py?ignore';
+          return frame.contentWindow.fetch(echo_url, {
+              method: 'POST',
+              body: blob
+            });
+        })
+      .then(response => {
+          return response.text();
+        })
+      .then(response_text => {
+          frame.remove();
+          assert_equals(
+              response_text,
+              'it\'s me the blob and more blob!',
+              'the network fallback request should include the request body');
+        });
+  }, 'FetchEvent#body is a blob and is passed to network fallback');
+
 promise_test(async (t) => {
     const scope = 'resources/simple.html?keepalive';
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/shadow/drag-and-drop-in-user-agent-shadow.html b/third_party/WebKit/LayoutTests/fast/dom/shadow/drag-and-drop-in-user-agent-shadow.html
index ef1233f..8fd215c 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/shadow/drag-and-drop-in-user-agent-shadow.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/shadow/drag-and-drop-in-user-agent-shadow.html
@@ -12,7 +12,7 @@
                                                document.createTextNode('Shadow Root Child')),
                                      createDOM('slot', {'name': 'user-agent-default-slot'}))));
 
-var shadowRootChild = window.internals.youngestShadowRoot(host).getElementById('shadow-root-child');
+var shadowRootChild = window.internals.shadowRoot(host).getElementById('shadow-root-child');
 var dragstartCount = 0;
 
 host.addEventListener('dragstart', function(e) {
diff --git a/third_party/WebKit/LayoutTests/fast/dom/shadow/offset-parent-does-not-leak-ua-shadow.html b/third_party/WebKit/LayoutTests/fast/dom/shadow/offset-parent-does-not-leak-ua-shadow.html
index 6599e50..77c5a35 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/shadow/offset-parent-does-not-leak-ua-shadow.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/shadow/offset-parent-does-not-leak-ua-shadow.html
@@ -46,7 +46,7 @@
 container.appendChild(host);
 host.setAttribute('open', 'open');
 host.appendChild(child);
-var shadow = window.internals.youngestShadowRoot(host);  // this is a UA shadow root
+var shadow = window.internals.shadowRoot(host);  // this is a UA shadow root
 configureUAShadowRoot(shadow);
 shouldBe('child.offsetParent', 'container');
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/shadow/resources/shadow-dom.js b/third_party/WebKit/LayoutTests/fast/dom/shadow/resources/shadow-dom.js
index c734253e..1ba6705 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/shadow/resources/shadow-dom.js
+++ b/third_party/WebKit/LayoutTests/fast/dom/shadow/resources/shadow-dom.js
@@ -102,7 +102,7 @@
 
 function isShadowHost(node)
 {
-    return window.internals.oldestShadowRoot(node);
+    return window.internals.shadowRoot(node);
 }
 
 function isShadowRoot(node)
@@ -115,8 +115,6 @@
     return element && element.nodeName == 'IFRAME';
 }
 
-// You can specify youngerShadowRoot by consecutive slashes.
-// See LayoutTests/fast/dom/shadow/get-element-by-id-in-shadow-root.html for actual usages.
 function getNodeInComposedTree(path)
 {
     var ids = path.split('/');
@@ -126,10 +124,8 @@
             node = node.contentDocument.getElementById(ids[i]);
             continue;
         }
-        if (isShadowRoot(node))
-            node = internals.youngerShadowRoot(node);
-        else if (internals.oldestShadowRoot(node))
-            node = internals.oldestShadowRoot(node);
+        if (internals.shadowRoot(node))
+          node = internals.shadowRoot(node);
         else
             return null;
         if (ids[i] != '')
@@ -176,11 +172,10 @@
         return element;
     }
     if (isShadowHost(element)) {
-        var shadowRoot = window.internals.oldestShadowRoot(element);
-        while (shadowRoot) {
+        var shadowRoot = window.internals.shadowRoot(element);
+        if (shadowRoot) {
             if (shadowRoot.activeElement)
                 return innermostActiveElement(shadowRoot.activeElement);
-            shadowRoot = window.internals.youngerShadowRoot(shadowRoot);
         }
     }
     return element;
@@ -342,7 +337,8 @@
         if (root.nodeType != 1)
             return null;
 
-        for (var shadowRoot = internals.youngestShadowRoot(root); shadowRoot; shadowRoot = shadowRoot.olderShadowRoot) {
+        var shadowRoot = internals.shadowRoot(root);
+        if (shadowRoot) {
             var node = iter(shadowRoot, id);
             if (node != null)
                 return node;
diff --git a/third_party/WebKit/LayoutTests/fast/forms/calendar-picker/calendar-picker-should-not-change-datetimelocal-time.html b/third_party/WebKit/LayoutTests/fast/forms/calendar-picker/calendar-picker-should-not-change-datetimelocal-time.html
index 03ff0ef9..b6368f4 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/calendar-picker/calendar-picker-should-not-change-datetimelocal-time.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/calendar-picker/calendar-picker-should-not-change-datetimelocal-time.html
@@ -12,7 +12,7 @@
 
 var input = document.createElement('input');
 input.type = 'datetime-local';
-getElementByPseudoId(internals.youngestShadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', 'yyyy-MM-dd HH:mm');
+getElementByPseudoId(internals.shadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', 'yyyy-MM-dd HH:mm');
 document.body.appendChild(input);
 
 input.value = '1999-07-31T12:59';
diff --git a/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-clearbutton-preventdefault-mousecapture-status.html b/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-clearbutton-preventdefault-mousecapture-status.html
index 5c6b07b3..ceecd7e4 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-clearbutton-preventdefault-mousecapture-status.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-clearbutton-preventdefault-mousecapture-status.html
@@ -28,7 +28,7 @@
     evt.preventDefault();
 });
 
-var clearButton = getElementByPseudoId(internals.oldestShadowRoot(input),'-webkit-clear-button');
+var clearButton = getElementByPseudoId(internals.shadowRoot(input),'-webkit-clear-button');
 clickElement(clearButton);
 shouldBeEqualToString('input.value', '');
 
diff --git a/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-fallback-format.html b/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-fallback-format.html
index 7f0dbbf..0bc22d65 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-fallback-format.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-fallback-format.html
@@ -14,7 +14,7 @@
 
 function setDateTimeFormat(pattern) {
     var value = input.value;
-    getElementByPseudoId(internals.youngestShadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern);
+    getElementByPseudoId(internals.shadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern);
     input.value = ''; // Updates the element for new format
     input.value = value;
 }
diff --git a/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-focus-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-focus-expected.txt
index 8e58ad0..9d468bf4 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-focus-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-focus-expected.txt
@@ -3,8 +3,8 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS internals.shadowPseudoId(internals.youngestShadowRoot(dateInput).activeElement) is "-webkit-datetime-edit-month-field"
-PASS internals.shadowPseudoId(internals.youngestShadowRoot(dateInput).activeElement) is "-webkit-datetime-edit-month-field"
+PASS internals.shadowPseudoId(internals.shadowRoot(dateInput).activeElement) is "-webkit-datetime-edit-month-field"
+PASS internals.shadowPseudoId(internals.shadowRoot(dateInput).activeElement) is "-webkit-datetime-edit-month-field"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-focus.html b/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-focus.html
index aa1cfa3..34e9f61f 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-focus.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-focus.html
@@ -19,10 +19,10 @@
 dateInput.focus();
 // Because the year field is fixed, the first focusable element is the
 // month field.
-shouldBeEqualToString('internals.shadowPseudoId(internals.youngestShadowRoot(dateInput).activeElement)', '-webkit-datetime-edit-month-field');
+shouldBeEqualToString('internals.shadowPseudoId(internals.shadowRoot(dateInput).activeElement)', '-webkit-datetime-edit-month-field');
 dateInput.blur();
 dateInput.focus();
-shouldBeEqualToString('internals.shadowPseudoId(internals.youngestShadowRoot(dateInput).activeElement)', '-webkit-datetime-edit-month-field');
+shouldBeEqualToString('internals.shadowPseudoId(internals.shadowRoot(dateInput).activeElement)', '-webkit-datetime-edit-month-field');
 
 dateInput.remove();
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-readonly-subfield.html b/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-readonly-subfield.html
index be4118a6..8bef81600 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-readonly-subfield.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-readonly-subfield.html
@@ -16,7 +16,7 @@
 
 // FIXME: Rename this function and the test file.
 function isReadOnlyField(input, pseudo) {
-    var node = internals.youngestShadowRoot(input).querySelector('*[pseudo="' + pseudo + '"]');
+    var node = internals.shadowRoot(input).querySelector('*[pseudo="' + pseudo + '"]');
     if (!node)
         testFailed('Requested node is missing.');
     return node && node.hasAttribute('disabled');
diff --git a/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/resources/preserve-value-after-history-back-frame.html b/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/resources/preserve-value-after-history-back-frame.html
index 4c8199c..67e8cf42 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/resources/preserve-value-after-history-back-frame.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/date-multiple-fields/resources/preserve-value-after-history-back-frame.html
@@ -4,7 +4,7 @@
 <input type="date" id="test2" min="1999-01-01" max="2000-12-31">
 <script>
 function fieldsText(input) {
-    return window.internals.oldestShadowRoot(input).textContent;
+    return window.internals.shadowRoot(input).textContent;
 }
 
 function back(newState) {
diff --git a/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-fallback-format.html b/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-fallback-format.html
index 383434d..c4f7f19 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-fallback-format.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-fallback-format.html
@@ -14,7 +14,7 @@
 
 function setDateTimeFormat(pattern) {
     var value = input.value;
-    getElementByPseudoId(internals.youngestShadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern);
+    getElementByPseudoId(internals.shadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern);
     input.value = ''; // Updates the element for new format
     input.value = value;
 }
diff --git a/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-mouse-events.html b/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-mouse-events.html
index e647d0a..21a820c 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-mouse-events.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-mouse-events.html
@@ -76,7 +76,7 @@
 
     // With ICU 52 on Linux/Android, a comma is used to delimete date and time and
     // the hour and time field positions are shifted.
-    var commaOffset = window.internals.oldestShadowRoot(input).textContent.indexOf(', ') == -1 ? 0 : 16;
+    var commaOffset = window.internals.shadowRoot(input).textContent.indexOf(', ') == -1 ? 0 : 16;
 
     debug('');
     debug('==> Focus on the hour field.');
diff --git a/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-readonly-subfield.html b/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-readonly-subfield.html
index ca86145..ac732a6 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-readonly-subfield.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-readonly-subfield.html
@@ -18,7 +18,7 @@
 
 // FIXME: Rename this function and the test file.
 function isReadOnlyField(input, pseudo) {
-    var node = internals.youngestShadowRoot(input).querySelector('*[pseudo="' + pseudo + '"]');
+    var node = internals.shadowRoot(input).querySelector('*[pseudo="' + pseudo + '"]');
     if (!node)
         testFailed('Requested node is missing.');
     return node && node.hasAttribute('disabled');
diff --git a/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/resources/preserve-value-after-history-back-frame.html b/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/resources/preserve-value-after-history-back-frame.html
index 2770cff..96a48378 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/resources/preserve-value-after-history-back-frame.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/datetimelocal-multiple-fields/resources/preserve-value-after-history-back-frame.html
@@ -4,7 +4,7 @@
 <input type="datetime-local" id="test2" min="1999-01-01T00:00" max="2000-12-31T23:59">
 <script>
 function fieldsText(input) {
-    return window.internals.oldestShadowRoot(input).textContent;
+    return window.internals.shadowRoot(input).textContent;
 }
 
 // On Linux/Android with a newer ICU, date and time are separated by ','.
diff --git a/third_party/WebKit/LayoutTests/fast/forms/month-multiple-fields/month-multiple-fields-fallback-format.html b/third_party/WebKit/LayoutTests/fast/forms/month-multiple-fields/month-multiple-fields-fallback-format.html
index 6ad72ac..e5c0003 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/month-multiple-fields/month-multiple-fields-fallback-format.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/month-multiple-fields/month-multiple-fields-fallback-format.html
@@ -14,7 +14,7 @@
 
 function setDateTimeFormat(pattern) {
     var value = input.value;
-    getElementByPseudoId(internals.youngestShadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern);
+    getElementByPseudoId(internals.shadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern);
     input.value = ''; // Updates the element for new format
     input.value = value;
 }
diff --git a/third_party/WebKit/LayoutTests/fast/forms/month-multiple-fields/month-multiple-fields-readonly-subfield.html b/third_party/WebKit/LayoutTests/fast/forms/month-multiple-fields/month-multiple-fields-readonly-subfield.html
index b0bf28b..ab87c72 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/month-multiple-fields/month-multiple-fields-readonly-subfield.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/month-multiple-fields/month-multiple-fields-readonly-subfield.html
@@ -16,7 +16,7 @@
 
 // FIXME: Rename this function and the test file.
 function isReadOnlyField(input, pseudo) {
-    var node = internals.youngestShadowRoot(input).querySelector('*[pseudo="' + pseudo + '"]');
+    var node = internals.shadowRoot(input).querySelector('*[pseudo="' + pseudo + '"]');
     if (!node)
         testFailed('Requested node is missing.');
     return node && node.hasAttribute('disabled');
diff --git a/third_party/WebKit/LayoutTests/fast/forms/month-multiple-fields/resources/preserve-value-after-history-back-frame.html b/third_party/WebKit/LayoutTests/fast/forms/month-multiple-fields/resources/preserve-value-after-history-back-frame.html
index 4540ab1..177be07b 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/month-multiple-fields/resources/preserve-value-after-history-back-frame.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/month-multiple-fields/resources/preserve-value-after-history-back-frame.html
@@ -4,7 +4,7 @@
 <input type="month" id="test2" min="1998-01" max="1999-12">
 <script>
 function fieldsText(input) {
-    return window.internals.oldestShadowRoot(input).textContent;
+    return window.internals.shadowRoot(input).textContent;
 }
 
 function back(newState) {
diff --git a/third_party/WebKit/LayoutTests/fast/forms/resources/common-clearbutton-change-and-input-events.js b/third_party/WebKit/LayoutTests/fast/forms/resources/common-clearbutton-change-and-input-events.js
index 54723483..c3793e27 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/resources/common-clearbutton-change-and-input-events.js
+++ b/third_party/WebKit/LayoutTests/fast/forms/resources/common-clearbutton-change-and-input-events.js
@@ -26,7 +26,7 @@
 
     debug('Click the clear button');
     // Move the cursor on to the clear button.
-    var clearButton = getElementByPseudoId(internals.oldestShadowRoot(testInput), "-webkit-clear-button");
+    var clearButton = getElementByPseudoId(internals.shadowRoot(testInput), "-webkit-clear-button");
     eventSender.mouseMoveTo(clearButton.offsetLeft + clearButton.offsetWidth / 2, clearButton.offsetTop + clearButton.offsetHeight / 2);
     eventSender.mouseDown();
     eventSender.mouseUp();
diff --git a/third_party/WebKit/LayoutTests/fast/forms/resources/common-spinbutton-change-and-input-events.js b/third_party/WebKit/LayoutTests/fast/forms/resources/common-spinbutton-change-and-input-events.js
index 404031a6..116d140 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/resources/common-spinbutton-change-and-input-events.js
+++ b/third_party/WebKit/LayoutTests/fast/forms/resources/common-spinbutton-change-and-input-events.js
@@ -31,7 +31,7 @@
 
     debug('Click the upper button');
     // Move the cursor on the upper button.
-    var spinButton = getElementByPseudoId(internals.oldestShadowRoot(testInput), "-webkit-inner-spin-button");
+    var spinButton = getElementByPseudoId(internals.shadowRoot(testInput), "-webkit-inner-spin-button");
     var rect = spinButton.getBoundingClientRect();
     eventSender.mouseMoveTo(rect.left, rect.top + rect.height / 4);
     eventSender.mouseDown();
diff --git a/third_party/WebKit/LayoutTests/fast/forms/resources/common-spinbutton-click-in-iframe.js b/third_party/WebKit/LayoutTests/fast/forms/resources/common-spinbutton-click-in-iframe.js
index 03e8be11..bb0b5778 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/resources/common-spinbutton-click-in-iframe.js
+++ b/third_party/WebKit/LayoutTests/fast/forms/resources/common-spinbutton-click-in-iframe.js
@@ -7,7 +7,7 @@
 {
     if (!window.internals)
         return null;
-    return getElementByPseudoId(internals.oldestShadowRoot(input), "-webkit-inner-spin-button");
+    return getElementByPseudoId(internals.shadowRoot(input), "-webkit-inner-spin-button");
 }
 
 function mouseClick()
diff --git a/third_party/WebKit/LayoutTests/fast/forms/resources/common.js b/third_party/WebKit/LayoutTests/fast/forms/resources/common.js
index 848bbb1..03286df 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/resources/common.js
+++ b/third_party/WebKit/LayoutTests/fast/forms/resources/common.js
@@ -120,7 +120,7 @@
 }
 
 function getUserAgentShadowTextContent(element) {
-    return internals.youngestShadowRoot(element).textContent;
+    return internals.shadowRoot(element).textContent;
 };
 
 function cumulativeOffset(element) {
diff --git a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/resources/preserve-value-after-history-back-frame.html b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/resources/preserve-value-after-history-back-frame.html
index e21a86fa..ba1a3d7 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/resources/preserve-value-after-history-back-frame.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/resources/preserve-value-after-history-back-frame.html
@@ -4,7 +4,7 @@
 <input type=time id=test2 step=1>
 <script>
 function fieldsText(input) {
-    return window.internals.oldestShadowRoot(input).textContent;
+    return window.internals.shadowRoot(input).textContent;
 }
 
 function back(newState) {
diff --git a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-fallback-format.html b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-fallback-format.html
index a834c00..2b90ac0e6 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-fallback-format.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-fallback-format.html
@@ -14,7 +14,7 @@
 
 function setDateTimeFormat(pattern) {
     var value = input.value;
-    getElementByPseudoId(internals.youngestShadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern);
+    getElementByPseudoId(internals.shadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern);
     input.value = ''; // Updates the element for new format
     input.value = value;
 }
diff --git a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-focus-style.html b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-focus-style.html
index 0df2fab..d4cbc6bc 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-focus-style.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-focus-style.html
@@ -28,7 +28,7 @@
 var highlight = sampleStyle.backgroundColor;
 
 testInput.focus();
-var shadowRoot = internals.oldestShadowRoot(testInput);
+var shadowRoot = internals.shadowRoot(testInput);
 var fields = getElementByPseudoId(shadowRoot, "-webkit-datetime-edit-fields-wrapper").childNodes;
 for (var index = 0; index < fields.length; ++index) {
     var field = fields[index];
diff --git a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-focus.html b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-focus.html
index b6c13407..b8240f7 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-focus.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-focus.html
@@ -4,7 +4,7 @@
 <input id="timeInput" type="time" value="01:01" style="font-size:20px">
 <script>
 function shadowPseudoIdOfFocused() {
-    return internals.shadowPseudoId(internals.youngestShadowRoot(timeInput).activeElement);
+    return internals.shadowPseudoId(internals.shadowRoot(timeInput).activeElement);
 }
 
 description('Check if focus() for focused input does not change focused sub-field.');
@@ -18,7 +18,7 @@
 shouldBeEqualToString('timeInput.focus(); shadowPseudoIdOfFocused(timeInput)', '-webkit-datetime-edit-minute-field');
 
 debug('Click on a delimiter between sub-fields, then check if focused element is not changed:');
-var focusedField = internals.youngestShadowRoot(timeInput).activeElement;
+var focusedField = internals.shadowRoot(timeInput).activeElement;
 eventSender.mouseMoveTo(focusedField.offsetLeft + focusedField.offsetWidth + 10, focusedField.offsetTop + 10);
 eventSender.mouseDown();
 eventSender.mouseUp();
diff --git a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-keyboard-events.html b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-keyboard-events.html
index 23f1a17..cddfac1 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-keyboard-events.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-keyboard-events.html
@@ -28,7 +28,7 @@
 
 function shadowPseudoIdOfFocusedSubField(host)
 {
-    return internals.shadowPseudoId(internals.youngestShadowRoot(host).activeElement);
+    return internals.shadowPseudoId(internals.shadowRoot(host).activeElement);
 }
 
 function keyDown(key, modifiers)
diff --git a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-narrow-width-scroll.html b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-narrow-width-scroll.html
index 1e13ad24..3a697ed 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-narrow-width-scroll.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-narrow-width-scroll.html
@@ -11,7 +11,7 @@
     debug('This test rquires DRT/WRT.');
 var time1 = $('time1');
 time1.focus();
-var container = getElementByPseudoId(internals.oldestShadowRoot(time1), '-webkit-datetime-edit');
+var container = getElementByPseudoId(internals.shadowRoot(time1), '-webkit-datetime-edit');
 var initialScrollLeft = container.scrollLeft;
 eventSender.keyDown('\t');
 shouldBeTrue('initialScrollLeft < container.scrollLeft');
diff --git a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-readonly-subfield.html b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-readonly-subfield.html
index b0674a0..a1a62dad 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-readonly-subfield.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-readonly-subfield.html
@@ -15,7 +15,7 @@
 
 // FIXME: Rename this function and the test file.
 function isReadOnlyField(input, pseudo) {
-    var node = internals.youngestShadowRoot(input).querySelector('*[pseudo="' + pseudo + '"]');
+    var node = internals.shadowRoot(input).querySelector('*[pseudo="' + pseudo + '"]');
     if (!node)
         testFailed('Requested node is missing.');
     return node && node.hasAttribute('disabled');
diff --git a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-hour.html b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-hour.html
index e37bae8..58778d2 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-hour.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-hour.html
@@ -14,7 +14,7 @@
 input.focus();
 
 function setDateTimeFormat(pattern) {
-  getElementByPseudoId(internals.youngestShadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern);
+  getElementByPseudoId(internals.shadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern);
   input.value = '';  // Updates the element for new format
 }
 
diff --git a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-tabindex.html b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-tabindex.html
index 6cc8a87..e4bbec31 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-tabindex.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-tabindex.html
@@ -20,7 +20,7 @@
 var shift = ['shiftKey'];
 
 $('tabindex10').focus();
-var shadowRoot = internals.youngestShadowRoot($('time-with-tabindex20'));
+var shadowRoot = internals.shadowRoot($('time-with-tabindex20'));
 
 debug('Forword:');
 shouldBeEqualToString('eventSender.keyDown(tab); document.activeElement.id', 'tabindex20-1');
diff --git a/third_party/WebKit/LayoutTests/fast/forms/week-multiple-fields/resources/preserve-value-after-history-back-frame.html b/third_party/WebKit/LayoutTests/fast/forms/week-multiple-fields/resources/preserve-value-after-history-back-frame.html
index 92bc53e..45b9c62 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/week-multiple-fields/resources/preserve-value-after-history-back-frame.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/week-multiple-fields/resources/preserve-value-after-history-back-frame.html
@@ -4,7 +4,7 @@
 <input type="week" id="test2" min="1998-W01" max="1999-W12">
 <script>
 function fieldsText(input) {
-    return window.internals.oldestShadowRoot(input).textContent;
+    return window.internals.shadowRoot(input).textContent;
 }
 
 function back(newState) {
diff --git a/third_party/WebKit/LayoutTests/fast/forms/week-multiple-fields/week-multiple-fields-fallback-format.html b/third_party/WebKit/LayoutTests/fast/forms/week-multiple-fields/week-multiple-fields-fallback-format.html
index 87495d3..f3b6865 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/week-multiple-fields/week-multiple-fields-fallback-format.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/week-multiple-fields/week-multiple-fields-fallback-format.html
@@ -14,7 +14,7 @@
 
 function setDateTimeFormat(pattern) {
     var value = input.value;
-    getElementByPseudoId(internals.youngestShadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern);
+    getElementByPseudoId(internals.shadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern);
     input.value = ''; // Updates the element for new format
     input.value = value;
 }
diff --git a/third_party/WebKit/LayoutTests/fast/forms/week-multiple-fields/week-multiple-fields-readonly-subfield.html b/third_party/WebKit/LayoutTests/fast/forms/week-multiple-fields/week-multiple-fields-readonly-subfield.html
index 5d8c09d2d..9549e7f 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/week-multiple-fields/week-multiple-fields-readonly-subfield.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/week-multiple-fields/week-multiple-fields-readonly-subfield.html
@@ -16,7 +16,7 @@
 
 // FIXME: Rename this function and the test file.
 function isReadOnlyField(input, pseudo) {
-    var node = internals.youngestShadowRoot(input).querySelector('*[pseudo="' + pseudo + '"]');
+    var node = internals.shadowRoot(input).querySelector('*[pseudo="' + pseudo + '"]');
     if (!node)
         testFailed('Requested node is missing.');
     return node && node.hasAttribute('disabled');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/nodejs-set-breakpoint.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/nodejs-set-breakpoint.js
index c9dbf99..7e407cb 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/nodejs-set-breakpoint.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/nodejs-set-breakpoint.js
@@ -5,16 +5,29 @@
 (async function() {
   TestRunner.addResult(`Verify that front-end is able to set breakpoint for node.js scripts.\n`);
   await TestRunner.loadModule('sources_test_runner');
+  await TestRunner.loadModule('sdk_test_runner');
   await TestRunner.showPanel('sources');
 
   SDK.targetManager.mainTarget().setIsNodeJSForTest();
   SourcesTestRunner.startDebuggerTest();
 
+  var debuggerModel = SDK.targetManager.mainTarget().model(SDK.DebuggerModel);
+  var originalParsedScriptSource = TestRunner.override(debuggerModel, '_parsedScriptSource', overrideSourceURL, true);
+
+  function overrideSourceURL(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
+               executionContextAuxData, isLiveEdit, sourceMapURL, hasSourceURL, hasSyntaxError, length) {
+    // Overwrite hasSourceURL to pretend we're Node.js
+    hasSourceURL = false;
+    originalParsedScriptSource.call(this, scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
+               executionContextAuxData, isLiveEdit, sourceMapURL, hasSourceURL, hasSyntaxError, length);
+  }
+
   var functionText = 'function foobar() { \nconsole.log(\'foobar execute!\');\n}';
   var sourceURL = '\n//# sourceURL=/usr/local/home/prog/foobar.js';
   await TestRunner.evaluateInPageAnonymously(functionText + sourceURL);
   SourcesTestRunner.showScriptSource('foobar.js', didShowScriptSource);
 
+
   function didShowScriptSource(sourceFrame) {
     TestRunner.addResult('Setting breakpoint:');
     TestRunner.addSniffer(
diff --git a/third_party/WebKit/LayoutTests/media/media-controls.js b/third_party/WebKit/LayoutTests/media/media-controls.js
index 380f8283..e65cf81 100644
--- a/third_party/WebKit/LayoutTests/media/media-controls.js
+++ b/third_party/WebKit/LayoutTests/media/media-controls.js
@@ -342,7 +342,7 @@
 function checkPictureInPictureInterstitialDoesNotExist(videoElement) {
   var controlID = '-internal-picture-in-picture-interstitial';
 
-  var interstitial = getElementByPseudoId(internals.oldestShadowRoot(videoElement), controlID);
+  var interstitial = getElementByPseudoId(internals.shadowRoot(videoElement), controlID);
   if (interstitial)
       throw 'Should not have a picture in picture interstitial';
 }
@@ -430,4 +430,4 @@
         node = traverseNextNode(node, root);
     }
     return null;
-}
\ No newline at end of file
+}
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt
index c1127fa..de16df96 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt
@@ -27,12 +27,12 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
           "rect": [25, 125, 50, 50],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
           "rect": [25, 25, 50, 50],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ],
       "transform": 1
@@ -63,7 +63,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/compositing/fixed-scroll-in-empty-root-layer-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/fixed-scroll-in-empty-root-layer-expected.txt
index cf3826f..8b7af015 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/compositing/fixed-scroll-in-empty-root-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/fixed-scroll-in-empty-root-layer-expected.txt
@@ -15,12 +15,12 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV",
           "rect": [0, 250, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV",
           "rect": [0, 50, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ],
       "transform": 1
@@ -41,12 +41,12 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV",
           "rect": [0, 250, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV",
           "rect": [0, 50, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ],
       "transform": 1
@@ -66,7 +66,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/filters/filter-on-html-element-with-fixed-position-child-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/filters/filter-on-html-element-with-fixed-position-child-expected.txt
index 7432a6d..9455232 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/filters/filter-on-html-element-with-fixed-position-child-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/filters/filter-on-html-element-with-fixed-position-child-expected.txt
@@ -19,22 +19,22 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV",
           "rect": [100, 110, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV",
           "rect": [100, 100, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV",
           "rect": [8, 18, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV",
           "rect": [8, 8, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ],
       "transform": 1
@@ -58,11 +58,11 @@
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-absolute-layer-with-reflection-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-absolute-layer-with-reflection-expected.txt
index 274fd6819..54f8bc3 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-absolute-layer-with-reflection-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-absolute-layer-with-reflection-expected.txt
@@ -9,22 +9,22 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
           "rect": [250, 230, 100, 100],
-          "reason": "subtree"
+          "reason": "disappeared"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'",
           "rect": [250, 230, 100, 100],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow (relative positioned) DIV class='relative reflected'",
           "rect": [250, 230, 100, 100],
-          "reason": "subtree"
+          "reason": "appeared"
         },
         {
           "object": "LayoutBlockFlow DIV class='green'",
           "rect": [250, 230, 100, 100],
-          "reason": "subtree"
+          "reason": "appeared"
         }
       ],
       "transform": 1
@@ -44,19 +44,19 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow (relative positioned) DIV class='relative reflected'",
-      "reason": "subtree"
+      "reason": "appeared"
     },
     {
       "object": "LayoutBlockFlow DIV class='green'",
-      "reason": "subtree"
+      "reason": "appeared"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "disappeared"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
index 5951c3c..480ef17 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
@@ -9,17 +9,17 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute green reflected'",
           "rect": [250, 280, 100, 100],
-          "reason": "subtree"
+          "reason": "appeared"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
           "rect": [250, 280, 100, 100],
-          "reason": "subtree"
+          "reason": "disappeared"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
           "rect": [250, 280, 100, 100],
-          "reason": "subtree"
+          "reason": "full"
         }
       ],
       "transform": 1
@@ -39,15 +39,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute green reflected'",
-      "reason": "subtree"
+      "reason": "appeared"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "disappeared"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/fixed-img-src-change-after-scroll-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/fixed-img-src-change-after-scroll-expected.txt
index b3d94e0e..37216e2 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/fixed-img-src-change-after-scroll-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/fixed-img-src-change-after-scroll-expected.txt
@@ -9,12 +9,12 @@
         {
           "object": "LayoutImage (positioned) IMG id='img'",
           "rect": [0, 1050, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutImage (positioned) IMG id='img'",
           "rect": [0, 50, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ],
       "transform": 1
@@ -34,7 +34,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutImage (positioned) IMG id='img'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/fixed-scroll-simple-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/fixed-scroll-simple-expected.txt
index 2a3281d..9f4596ab 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/fixed-scroll-simple-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/fixed-scroll-simple-expected.txt
@@ -9,12 +9,12 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV class='green'",
           "rect": [8, 200, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV class='green'",
           "rect": [8, 100, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ],
       "transform": 1
@@ -34,7 +34,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV class='green'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt
index 4cdd7f2..4a5593b 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt
@@ -9,17 +9,17 @@
         {
           "object": "LayoutBlockFlow DIV id='innerDiv'",
           "rect": [8, 8, 769, 300],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow DIV",
           "rect": [8, 8, 300, 300],
-          "reason": "subtree"
+          "reason": "appeared"
         },
         {
           "object": "LayoutBlockFlow DIV",
           "rect": [8, 8, 300, 300],
-          "reason": "subtree"
+          "reason": "disappeared"
         },
         {
           "object": "LayoutBlockFlow DIV id='innerDiv'",
@@ -32,7 +32,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV id='innerDiv'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "VerticalScrollbar",
@@ -40,11 +40,11 @@
     },
     {
       "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
+      "reason": "disappeared"
     },
     {
       "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
+      "reason": "appeared"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled-expected.txt
index b5d95840..e92407e 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled-expected.txt
@@ -9,17 +9,17 @@
         {
           "object": "LayoutBlockFlow DIV class='innerWrapper'",
           "rect": [8, 18, 100, 190],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow DIV class='red'",
           "rect": [8, 18, 100, 190],
-          "reason": "subtree"
+          "reason": "disappeared"
         },
         {
           "object": "LayoutBlockFlow DIV id='ucp' class='green'",
           "rect": [8, 18, 100, 190],
-          "reason": "subtree"
+          "reason": "appeared"
         }
       ]
     }
@@ -27,15 +27,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV class='innerWrapper'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow DIV class='red'",
-      "reason": "subtree"
+      "reason": "disappeared"
     },
     {
       "object": "LayoutBlockFlow DIV id='ucp' class='green'",
-      "reason": "subtree"
+      "reason": "appeared"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-expected.txt
index 0362d98..eac29247 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-expected.txt
@@ -15,27 +15,17 @@
         {
           "object": "LayoutBlockFlow DIV id='scroller'",
           "rect": [0, 0, 302, 302],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutBlockFlow DIV",
-          "rect": [1, 1, 300, 600],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutBlockFlow DIV",
-          "rect": [1, -399, 300, 600],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow DIV",
           "rect": [1, 601, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow DIV",
           "rect": [1, 201, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ]
     }
@@ -43,15 +33,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV id='scroller'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar-expected.txt
index 58521f8..324e2f7 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar-expected.txt
@@ -15,27 +15,17 @@
         {
           "object": "LayoutBlockFlow DIV id='scroller'",
           "rect": [0, 0, 302, 302],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutBlockFlow DIV",
-          "rect": [1, 1, 300, 600],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutBlockFlow DIV",
-          "rect": [1, -399, 300, 600],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow DIV id='target'",
           "rect": [1, 601, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow DIV id='target'",
           "rect": [1, 201, 100, 100],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow DIV id='target'",
@@ -73,15 +63,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV id='scroller'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow DIV id='target'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "HorizontalScrollbar",
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt
index 42cbfbf..5a81e12 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt
@@ -9,17 +9,7 @@
         {
           "object": "LayoutBlockFlow DIV class='scroller'",
           "rect": [18, 60, 310, 200],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutBlockFlow (positioned) DIV class='back'",
-          "rect": [93, 125, 180, 100],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutBlockFlow (positioned) DIV class='back'",
-          "rect": [93, 75, 180, 100],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow DIV class='scroller'",
@@ -67,15 +57,11 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV class='scroller'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "VerticalScrollbar",
       "reason": "scroll control"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV class='back'",
-      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt
index 4cdd7f2..4a5593b 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt
@@ -9,17 +9,17 @@
         {
           "object": "LayoutBlockFlow DIV id='innerDiv'",
           "rect": [8, 8, 769, 300],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow DIV",
           "rect": [8, 8, 300, 300],
-          "reason": "subtree"
+          "reason": "appeared"
         },
         {
           "object": "LayoutBlockFlow DIV",
           "rect": [8, 8, 300, 300],
-          "reason": "subtree"
+          "reason": "disappeared"
         },
         {
           "object": "LayoutBlockFlow DIV id='innerDiv'",
@@ -32,7 +32,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV id='innerDiv'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "VerticalScrollbar",
@@ -40,11 +40,11 @@
     },
     {
       "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
+      "reason": "disappeared"
     },
     {
       "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
+      "reason": "appeared"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt
index 102720d..63ffec5c 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt
@@ -9,12 +9,12 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
           "rect": [100, 1150, 100, 100],
-          "reason": "subtree"
+          "reason": "style change"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
           "rect": [100, 1150, 100, 100],
-          "reason": "subtree"
+          "reason": "style change"
         }
       ],
       "transform": 1
@@ -34,11 +34,11 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
-      "reason": "subtree"
+      "reason": "style change"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
+      "reason": "style change"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-fixed-layer-with-transformed-parent-layer-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-fixed-layer-with-transformed-parent-layer-expected.txt
index 18c48585..f4c6575 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-fixed-layer-with-transformed-parent-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-fixed-layer-with-transformed-parent-layer-expected.txt
@@ -9,17 +9,17 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
           "rect": [93, 234, 142, 143],
-          "reason": "subtree"
+          "reason": "appeared"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
           "rect": [93, 234, 142, 143],
-          "reason": "subtree"
+          "reason": "disappeared"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
           "rect": [93, 234, 142, 143],
-          "reason": "subtree"
+          "reason": "full"
         }
       ],
       "transform": 1
@@ -39,15 +39,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
+      "reason": "appeared"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "disappeared"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-clipped-layer-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-clipped-layer-expected.txt
index dab1f43..e9ee73c 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-clipped-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-clipped-layer-expected.txt
@@ -9,17 +9,17 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
           "rect": [100, 150, 100, 100],
-          "reason": "subtree"
+          "reason": "disappeared"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'",
           "rect": [100, 150, 100, 100],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow (relative positioned) DIV class='relative green'",
           "rect": [100, 150, 100, 100],
-          "reason": "subtree"
+          "reason": "appeared"
         }
       ]
     }
@@ -27,15 +27,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow (relative positioned) DIV class='relative green'",
-      "reason": "subtree"
+      "reason": "appeared"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "disappeared"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
index 65379f13..681e37d 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
@@ -9,17 +9,17 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
           "rect": [100, 1150, 100, 100],
-          "reason": "subtree"
+          "reason": "appeared"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
           "rect": [100, 1150, 100, 100],
-          "reason": "subtree"
+          "reason": "disappeared"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
           "rect": [100, 1150, 100, 100],
-          "reason": "subtree"
+          "reason": "full"
         }
       ],
       "transform": 1
@@ -39,15 +39,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
+      "reason": "appeared"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "disappeared"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
similarity index 64%
rename from third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
rename to third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
index 696f3de..8f0f027 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
@@ -14,24 +14,14 @@
       "backfaceVisibility": "hidden",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow (positioned) DIV id='searchbar'",
-          "rect": [10, 1822, 150, 150],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutBlockFlow DIV id='recentlink'",
           "rect": [10, 1822, 150, 150],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutBlockFlow (positioned) DIV id='searchbar'",
-          "rect": [10, 1422, 150, 150],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow DIV id='recentlink'",
           "rect": [10, 1422, 150, 150],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ],
       "transform": 1
@@ -50,12 +40,8 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow (positioned) DIV id='searchbar'",
-      "reason": "subtree"
-    },
-    {
       "object": "LayoutBlockFlow DIV id='recentlink'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-with-transformed-parent-layer-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-with-transformed-parent-layer-expected.txt
index b4910e2c..7498165 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-with-transformed-parent-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-with-transformed-parent-layer-expected.txt
@@ -9,22 +9,22 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
           "rect": [79, 129, 142, 142],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
           "rect": [79, 129, 142, 142],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'",
           "rect": [79, 129, 142, 142],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
           "rect": [114, 129, 107, 36],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ]
     }
@@ -32,15 +32,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-inside-table-cell-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-inside-table-cell-expected.txt
index 7023638..ddc8b57d 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-inside-table-cell-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-inside-table-cell-expected.txt
@@ -9,17 +9,17 @@
         {
           "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'",
           "rect": [312, 112, 454, 469],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
           "rect": [314, 114, 435, 450],
-          "reason": "subtree"
+          "reason": "appeared"
         },
         {
           "object": "LayoutBlockFlow (relative positioned) DIV class='relative red'",
           "rect": [314, 114, 435, 450],
-          "reason": "subtree"
+          "reason": "disappeared"
         },
         {
           "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'",
@@ -32,7 +32,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "HorizontalScrollbar",
@@ -40,11 +40,11 @@
     },
     {
       "object": "LayoutBlockFlow (relative positioned) DIV class='relative red'",
-      "reason": "subtree"
+      "reason": "disappeared"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
+      "reason": "appeared"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt
index 15930d1..5e4eca9 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt
@@ -9,17 +9,17 @@
         {
           "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'",
           "rect": [1112, 1312, 454, 469],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
           "rect": [1114, 1314, 435, 450],
-          "reason": "subtree"
+          "reason": "appeared"
         },
         {
           "object": "LayoutBlockFlow (relative positioned) DIV class='relative red'",
           "rect": [1114, 1314, 435, 450],
-          "reason": "subtree"
+          "reason": "disappeared"
         },
         {
           "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'",
@@ -44,7 +44,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "HorizontalScrollbar",
@@ -52,11 +52,11 @@
     },
     {
       "object": "LayoutBlockFlow (relative positioned) DIV class='relative red'",
-      "reason": "subtree"
+      "reason": "disappeared"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
+      "reason": "appeared"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt
index ae6dae2a..a85f449 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt
@@ -9,37 +9,17 @@
         {
           "object": "LayoutBlockFlow DIV id='innerDiv'",
           "rect": [8, 8, 769, 300],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutTable TABLE",
-          "rect": [8, 8, 306, 300],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutTableRow TR",
-          "rect": [8, 8, 306, 300],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutTableRow TR",
-          "rect": [8, 8, 306, 300],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutTableSection TBODY",
-          "rect": [8, 8, 306, 300],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutTableCell TD",
           "rect": [10, 8, 302, 300],
-          "reason": "subtree"
+          "reason": "appeared"
         },
         {
           "object": "LayoutTableCell TD",
           "rect": [10, 8, 302, 300],
-          "reason": "subtree"
+          "reason": "disappeared"
         },
         {
           "object": "LayoutBlockFlow DIV id='innerDiv'",
@@ -52,7 +32,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV id='innerDiv'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "VerticalScrollbar",
@@ -60,27 +40,27 @@
     },
     {
       "object": "LayoutTable TABLE",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutTableSection TBODY",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutTableRow TR",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutTableCell TD",
-      "reason": "subtree"
+      "reason": "disappeared"
     },
     {
       "object": "LayoutTableRow TR",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutTableCell TD",
-      "reason": "subtree"
+      "reason": "appeared"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt
index ae6dae2a..a85f449 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt
@@ -9,37 +9,17 @@
         {
           "object": "LayoutBlockFlow DIV id='innerDiv'",
           "rect": [8, 8, 769, 300],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutTable TABLE",
-          "rect": [8, 8, 306, 300],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutTableRow TR",
-          "rect": [8, 8, 306, 300],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutTableRow TR",
-          "rect": [8, 8, 306, 300],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutTableSection TBODY",
-          "rect": [8, 8, 306, 300],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutTableCell TD",
           "rect": [10, 8, 302, 300],
-          "reason": "subtree"
+          "reason": "appeared"
         },
         {
           "object": "LayoutTableCell TD",
           "rect": [10, 8, 302, 300],
-          "reason": "subtree"
+          "reason": "disappeared"
         },
         {
           "object": "LayoutBlockFlow DIV id='innerDiv'",
@@ -52,7 +32,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV id='innerDiv'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "VerticalScrollbar",
@@ -60,27 +40,27 @@
     },
     {
       "object": "LayoutTable TABLE",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutTableSection TBODY",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutTableRow TR",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutTableCell TD",
-      "reason": "subtree"
+      "reason": "disappeared"
     },
     {
       "object": "LayoutTableRow TR",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutTableCell TD",
-      "reason": "subtree"
+      "reason": "appeared"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
index 94cfb14c..757e456 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
@@ -10,86 +10,78 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV id='abs'",
           "rect": [425, 980, 360, 90],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='abs'",
           "rect": [425, 980, 360, 90],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='abs'",
           "rect": [425, 480, 360, 90],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='abs'",
           "rect": [425, 480, 360, 90],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [425, 980, 21, 19],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [425, 980, 21, 19],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [425, 480, 21, 19],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [425, 480, 21, 19],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ]
     }
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow (positioned) DIV id='fixed'",
-      "reason": "subtree"
-    },
-    {
       "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'Hi!'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV id='fixed'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'Hi!'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt
index 07beef0..6bbabdff 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt
@@ -7,29 +7,24 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [0, 0, 939, 235],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutView #document",
           "rect": [0, 0, 939, 235],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow BODY",
           "rect": [8, 8, 923, 219],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [10, 7, 920, 213],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
           "rect": [339, 0, 600, 500],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
@@ -42,19 +37,14 @@
           "reason": "scroll control"
         },
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [497, 0, 442, 500],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutBlockFlow BODY",
           "rect": [505, 8, 426, 484],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [507, 8, 423, 482],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ],
       "transform": 1
@@ -78,75 +68,75 @@
     },
     {
       "object": "LayoutView #document",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow HTML",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow BODY",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'AAAA'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'BBBB'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'CCCC'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'DDDD'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'EEEE'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'FFFF'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'GGGG'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'HHHH'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'IIII JJJJ'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'KKKK'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'LLLL'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'MMMM'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'NNNN'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
@@ -159,19 +149,9 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [200, 0, 939, 235],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutView #document",
           "rect": [200, 0, 939, 235],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [0, 0, 939, 235],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
@@ -181,27 +161,27 @@
         {
           "object": "LayoutView #document",
           "rect": [0, 0, 939, 235],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow BODY",
           "rect": [208, 8, 923, 219],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow BODY",
           "rect": [8, 8, 923, 219],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [210, 7, 920, 213],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [10, 7, 920, 213],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
@@ -235,75 +215,75 @@
     },
     {
       "object": "LayoutView #document",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow HTML",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow BODY",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'AAAA'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'BBBB'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'CCCC'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'DDDD'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'EEEE'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'FFFF'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'GGGG'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'HHHH'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'IIII JJJJ'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'KKKK'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'LLLL'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'MMMM'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'NNNN'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
@@ -321,29 +301,24 @@
           "reason": "full"
         },
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [-539, 0, 939, 235],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutView #document",
           "rect": [-539, 0, 939, 235],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow BODY",
           "rect": [-531, 8, 923, 219],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [-529, 7, 920, 213],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
           "rect": [0, 0, 400, 600],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
@@ -351,19 +326,14 @@
           "reason": "scroll control"
         },
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [29, 0, 371, 600],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutBlockFlow BODY",
           "rect": [37, 8, 355, 584],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [39, 7, 352, 563],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ]
     }
@@ -375,43 +345,43 @@
     },
     {
       "object": "LayoutView #document",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow HTML",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow BODY",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'AAAA BBBB CCCC'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'DDDD EEEE FFFF'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'GGGG HHHH IIII JJJJ'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'KKKK LLLL MMMM'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'NNNN'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
index 197796f..e2c34ec 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
@@ -10,86 +10,78 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV id='abs'",
           "rect": [425, 980, 360, 90],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='abs'",
           "rect": [425, 980, 360, 90],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='abs'",
           "rect": [425, 480, 360, 90],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='abs'",
           "rect": [425, 480, 360, 90],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [425, 980, 22, 18],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [425, 980, 22, 18],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [425, 480, 22, 18],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [425, 480, 22, 18],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ]
     }
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow (positioned) DIV id='fixed'",
-      "reason": "subtree"
-    },
-    {
       "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'Hi!'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV id='fixed'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'Hi!'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
index f9f7c22a..4f806c3 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
@@ -14,24 +14,14 @@
       "backfaceVisibility": "hidden",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow (positioned) DIV id='searchbar'",
-          "rect": [10, 1824, 150, 150],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutBlockFlow DIV id='recentlink'",
           "rect": [10, 1824, 150, 150],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutBlockFlow (positioned) DIV id='searchbar'",
-          "rect": [10, 1424, 150, 150],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow DIV id='recentlink'",
           "rect": [10, 1424, 150, 150],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ],
       "transform": 1
@@ -50,12 +40,8 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow (positioned) DIV id='searchbar'",
-      "reason": "subtree"
-    },
-    {
       "object": "LayoutBlockFlow DIV id='recentlink'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt
index 01b2f7b..9291f55 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt
@@ -7,29 +7,24 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [0, 0, 913, 235],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutView #document",
           "rect": [0, 0, 913, 235],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow BODY",
           "rect": [8, 8, 897, 219],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [8, 8, 897, 214],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
           "rect": [313, 0, 600, 500],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
@@ -42,19 +37,14 @@
           "reason": "scroll control"
         },
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [483, 0, 430, 500],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutBlockFlow BODY",
           "rect": [491, 8, 414, 484],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [491, 8, 414, 484],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ],
       "transform": 1
@@ -78,75 +68,75 @@
     },
     {
       "object": "LayoutView #document",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow HTML",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow BODY",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'AAAA'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'BBBB'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'CCCC'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'DDDD'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'EEEE'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'FFFF'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'GGGG'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'HHHH'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'IIII JJJJ'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'KKKK'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'LLLL'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'MMMM'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'NNNN'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
@@ -159,19 +149,9 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [200, 0, 913, 235],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutView #document",
           "rect": [200, 0, 913, 235],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [0, 0, 913, 235],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
@@ -181,27 +161,27 @@
         {
           "object": "LayoutView #document",
           "rect": [0, 0, 913, 235],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow BODY",
           "rect": [208, 8, 897, 219],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow BODY",
           "rect": [8, 8, 897, 219],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [208, 8, 897, 214],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [8, 8, 897, 214],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
@@ -235,75 +215,75 @@
     },
     {
       "object": "LayoutView #document",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow HTML",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow BODY",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'AAAA'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'BBBB'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'CCCC'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'DDDD'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'EEEE'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'FFFF'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'GGGG'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'HHHH'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'IIII JJJJ'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'KKKK'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'LLLL'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'MMMM'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'NNNN'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
@@ -321,29 +301,24 @@
           "reason": "full"
         },
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [-513, 0, 913, 235],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutView #document",
           "rect": [-513, 0, 913, 235],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow BODY",
           "rect": [-505, 8, 897, 219],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [-505, 8, 897, 214],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
           "rect": [0, 0, 400, 600],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
@@ -351,19 +326,14 @@
           "reason": "scroll control"
         },
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [39, 0, 361, 600],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutBlockFlow BODY",
           "rect": [47, 8, 345, 584],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [47, 8, 345, 565],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ]
     }
@@ -375,43 +345,43 @@
     },
     {
       "object": "LayoutView #document",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow HTML",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow BODY",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'AAAA BBBB CCCC'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'DDDD EEEE FFFF'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'GGGG HHHH IIII JJJJ'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'KKKK LLLL MMMM'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'NNNN'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
index 36c7a2c..3e357b4 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
@@ -10,86 +10,78 @@
         {
           "object": "LayoutBlockFlow (positioned) DIV id='abs'",
           "rect": [425, 980, 360, 90],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='abs'",
           "rect": [425, 980, 360, 90],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='abs'",
           "rect": [425, 480, 360, 90],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV id='abs'",
           "rect": [425, 480, 360, 90],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [425, 980, 19, 19],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [425, 980, 19, 19],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [425, 480, 19, 19],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [425, 480, 19, 19],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ]
     }
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow (positioned) DIV id='fixed'",
-      "reason": "subtree"
-    },
-    {
       "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'Hi!'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV id='fixed'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'Hi!'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt
similarity index 76%
rename from third_party/WebKit/LayoutTests/platform/win/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt
rename to third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt
index 889e064d..b3befedb 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/window-resize/window-resize-vertical-writing-mode-expected.txt
@@ -7,29 +7,24 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [0, 0, 939, 235],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutView #document",
           "rect": [0, 0, 939, 235],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow BODY",
           "rect": [8, 8, 923, 219],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [9, 7, 921, 213],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
           "rect": [339, 0, 600, 500],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
@@ -42,19 +37,14 @@
           "reason": "scroll control"
         },
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [497, 0, 442, 500],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutBlockFlow BODY",
           "rect": [505, 8, 426, 484],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [506, 8, 424, 470],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ],
       "transform": 1
@@ -78,75 +68,75 @@
     },
     {
       "object": "LayoutView #document",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow HTML",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow BODY",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'AAAA'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'BBBB'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'CCCC'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'DDDD'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'EEEE'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'FFFF'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'GGGG'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'HHHH'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'IIII JJJJ'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'KKKK'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'LLLL'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'MMMM'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'NNNN'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
@@ -159,19 +149,9 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [200, 0, 939, 235],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutView #document",
           "rect": [200, 0, 939, 235],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [0, 0, 939, 235],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
@@ -181,27 +161,27 @@
         {
           "object": "LayoutView #document",
           "rect": [0, 0, 939, 235],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow BODY",
           "rect": [208, 8, 923, 219],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow BODY",
           "rect": [8, 8, 923, 219],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [209, 7, 921, 213],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [9, 7, 921, 213],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
@@ -235,75 +215,75 @@
     },
     {
       "object": "LayoutView #document",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow HTML",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow BODY",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'AAAA'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'BBBB'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'CCCC'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'DDDD'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'EEEE'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'FFFF'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'GGGG'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'HHHH'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'IIII JJJJ'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'KKKK'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'LLLL'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'MMMM'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'NNNN'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
@@ -321,29 +301,24 @@
           "reason": "full"
         },
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [-539, 0, 939, 235],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutView #document",
           "rect": [-539, 0, 939, 235],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutBlockFlow BODY",
           "rect": [-531, 8, 923, 219],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [-530, 7, 921, 213],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
           "rect": [0, 0, 400, 600],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutView #document",
@@ -351,19 +326,14 @@
           "reason": "scroll control"
         },
         {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [29, 0, 371, 600],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutBlockFlow BODY",
           "rect": [37, 8, 355, 584],
-          "reason": "subtree"
+          "reason": "geometry"
         },
         {
           "object": "LayoutText #text",
           "rect": [38, 7, 353, 554],
-          "reason": "subtree"
+          "reason": "geometry"
         }
       ]
     }
@@ -375,43 +345,43 @@
     },
     {
       "object": "LayoutView #document",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow HTML",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow BODY",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "RootInlineBox",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutText #text",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'AAAA BBBB CCCC'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'DDDD EEEE FFFF'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'GGGG HHHH IIII JJJJ'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'KKKK LLLL MMMM'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "InlineTextBox 'NNNN'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/resources/focus-utils.js b/third_party/WebKit/LayoutTests/shadow-dom/resources/focus-utils.js
index 5f2c5e63..5c3f471 100644
--- a/third_party/WebKit/LayoutTests/shadow-dom/resources/focus-utils.js
+++ b/third_party/WebKit/LayoutTests/shadow-dom/resources/focus-utils.js
@@ -8,11 +8,10 @@
     return element;
   }
   if (isShadowHost(element)) {
-    let shadowRoot = window.internals.oldestShadowRoot(element);
-    while (shadowRoot) {
+    let shadowRoot = window.internals.shadowRoot(element);
+    if (shadowRoot) {
       if (shadowRoot.activeElement)
         return innermostActiveElement(shadowRoot.activeElement);
-      shadowRoot = window.internals.youngerShadowRoot(shadowRoot);
     }
   }
   return element;
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/v0/closed-mode-deep-combinator-and-shadow-pseudo-expected.txt b/third_party/WebKit/LayoutTests/shadow-dom/v0/closed-mode-deep-combinator-and-shadow-pseudo-expected.txt
index 1186371..95117d9f 100644
--- a/third_party/WebKit/LayoutTests/shadow-dom/v0/closed-mode-deep-combinator-and-shadow-pseudo-expected.txt
+++ b/third_party/WebKit/LayoutTests/shadow-dom/v0/closed-mode-deep-combinator-and-shadow-pseudo-expected.txt
@@ -1,4 +1,4 @@
-CONSOLE WARNING: line 311: /deep/ combinator is no longer supported in CSS dynamic profile.It is now effectively no-op, acting as if it were a descendant combinator. /deep/ combinator will be removed, and will be invalid at M65. You should remove it. See https://www.chromestatus.com/features/4964279606312960 for more details.
+CONSOLE WARNING: line 306: /deep/ combinator is no longer supported in CSS dynamic profile.It is now effectively no-op, acting as if it were a descendant combinator. /deep/ combinator will be removed, and will be invalid at M65. You should remove it. See https://www.chromestatus.com/features/4964279606312960 for more details.
 (1/6) /deep/ style rule on top-level document.
 PASS backgroundColorOf('host_open_open') is "rgba(0, 0, 0, 0)"
 PASS backgroundColorOf('host_open_open/div1') is "rgba(0, 0, 0, 0)"
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/fast/borders/inline-mask-overlay-image-outset-expected.png b/third_party/WebKit/LayoutTests/virtual/spv175/fast/borders/inline-mask-overlay-image-outset-expected.png
new file mode 100644
index 0000000..b0c4012
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/fast/borders/inline-mask-overlay-image-outset-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt
index 92437853..32975ca 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt
@@ -33,18 +33,6 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='containerOverlapsComposited')",
       "position": [20, 20],
       "bounds": [100, 30000],
-      "paintInvalidations": [
-        {
-          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
-          "rect": [25, 125, 50, 50],
-          "reason": "paint property change"
-        },
-        {
-          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
-          "rect": [25, 25, 50, 50],
-          "reason": "paint property change"
-        }
-      ],
       "transform": 1
     }
   ],
@@ -70,12 +58,6 @@
       ],
       "flattenInheritedTransform": false
     }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
-      "reason": "subtree"
-    }
   ]
 }
 
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
index 899b4f0..ebc9af32 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
@@ -15,91 +15,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [785, 4021],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
-      "paintInvalidations": [
-        {
-          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-          "rect": [425, 980, 360, 90],
-          "reason": "paint property change"
-        },
-        {
-          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-          "rect": [425, 980, 360, 90],
-          "reason": "paint property change"
-        },
-        {
-          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-          "rect": [425, 480, 360, 90],
-          "reason": "paint property change"
-        },
-        {
-          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-          "rect": [425, 480, 360, 90],
-          "reason": "paint property change"
-        },
-        {
-          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-          "rect": [425, 980, 21, 19],
-          "reason": "paint property change"
-        },
-        {
-          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-          "rect": [425, 980, 21, 19],
-          "reason": "paint property change"
-        },
-        {
-          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-          "rect": [425, 480, 21, 19],
-          "reason": "paint property change"
-        },
-        {
-          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-          "rect": [425, 480, 21, 19],
-          "reason": "paint property change"
-        }
-      ]
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow (positioned) DIV id='fixed'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-      "reason": "subtree"
-    },
-    {
-      "object": "RootInlineBox",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutText #text",
-      "reason": "subtree"
-    },
-    {
-      "object": "InlineTextBox 'Hi!'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV id='fixed'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV id='abs'",
-      "reason": "subtree"
-    },
-    {
-      "object": "RootInlineBox",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutText #text",
-      "reason": "subtree"
-    },
-    {
-      "object": "InlineTextBox 'Hi!'",
-      "reason": "subtree"
+      "backgroundColor": "#FFFFFF"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/fixed-scroll-in-empty-root-layer-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/fixed-scroll-in-empty-root-layer-expected.txt
index 4e83207..aef65ce6 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/fixed-scroll-in-empty-root-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/compositing/fixed-scroll-in-empty-root-layer-expected.txt
@@ -35,18 +35,6 @@
     {
       "name": "LayoutBlockFlow HTML (foreground) Layer",
       "bounds": [785, 2016],
-      "paintInvalidations": [
-        {
-          "object": "LayoutBlockFlow (positioned) DIV",
-          "rect": [0, 250, 100, 100],
-          "reason": "paint property change"
-        },
-        {
-          "object": "LayoutBlockFlow (positioned) DIV",
-          "rect": [0, 50, 100, 100],
-          "reason": "paint property change"
-        }
-      ],
       "transform": 1
     }
   ],
@@ -61,12 +49,6 @@
       ],
       "flattenInheritedTransform": false
     }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow (positioned) DIV",
-      "reason": "subtree"
-    }
   ]
 }
 
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/filters/filter-on-html-element-with-fixed-position-child-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/filters/filter-on-html-element-with-fixed-position-child-expected.txt
index 73be97a1..0356ccfc 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/filters/filter-on-html-element-with-fixed-position-child-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/filters/filter-on-html-element-with-fixed-position-child-expected.txt
@@ -17,11 +17,6 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow DIV",
-          "rect": [8, 8, 200, 10000],
-          "reason": "subtree"
-        },
-        {
           "object": "LayoutBlockFlow (positioned) DIV",
           "rect": [100, 110, 100, 100],
           "reason": "paint property change"
@@ -60,27 +55,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutView #document",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
+      "reason": "full"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/reflection/scroll-absolute-layer-with-reflection-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/reflection/scroll-absolute-layer-with-reflection-expected.txt
index 3fbf563..4c5418d 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/reflection/scroll-absolute-layer-with-reflection-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/reflection/scroll-absolute-layer-with-reflection-expected.txt
@@ -45,19 +45,19 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow (relative positioned) DIV class='relative reflected'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow DIV class='green'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
index 681a28562..fb7f373f8 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
@@ -45,15 +45,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute green reflected'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/fixed-img-src-change-after-scroll-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/fixed-img-src-change-after-scroll-expected.txt
index 27cb3c8..1476636 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/fixed-img-src-change-after-scroll-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/fixed-img-src-change-after-scroll-expected.txt
@@ -15,18 +15,6 @@
       "bounds": [785, 2016],
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
-      "paintInvalidations": [
-        {
-          "object": "LayoutImage (positioned) IMG id='img'",
-          "rect": [0, 1050, 100, 100],
-          "reason": "paint property change"
-        },
-        {
-          "object": "LayoutImage (positioned) IMG id='img'",
-          "rect": [0, 50, 100, 100],
-          "reason": "paint property change"
-        }
-      ],
       "transform": 1
     }
   ],
@@ -41,12 +29,6 @@
       ],
       "flattenInheritedTransform": false
     }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutImage (positioned) IMG id='img'",
-      "reason": "subtree"
-    }
   ]
 }
 
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/fixed-scroll-simple-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/fixed-scroll-simple-expected.txt
index fa05654..2fc218f 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/fixed-scroll-simple-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/fixed-scroll-simple-expected.txt
@@ -15,18 +15,6 @@
       "bounds": [800, 2016],
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
-      "paintInvalidations": [
-        {
-          "object": "LayoutBlockFlow (positioned) DIV class='green'",
-          "rect": [8, 200, 100, 100],
-          "reason": "paint property change"
-        },
-        {
-          "object": "LayoutBlockFlow (positioned) DIV class='green'",
-          "rect": [8, 100, 100, 100],
-          "reason": "paint property change"
-        }
-      ],
       "transform": 1
     }
   ],
@@ -41,12 +29,6 @@
       ],
       "flattenInheritedTransform": false
     }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow (positioned) DIV class='green'",
-      "reason": "subtree"
-    }
   ]
 }
 
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/iframe-scroll-repaint-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/iframe-scroll-repaint-expected.txt
new file mode 100644
index 0000000..85d9057
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/iframe-scroll-repaint-expected.txt
@@ -0,0 +1,9 @@
+{
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutView #document",
+      "reason": "full"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt
index d0c7ed2..d39ba713 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt
@@ -32,19 +32,11 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV id='innerDiv'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "VerticalScrollbar",
       "reason": "scroll control"
-    },
-    {
-      "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled-expected.txt
index 26bb718d..39ddb3b 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled-expected.txt
@@ -32,15 +32,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV class='innerWrapper'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow DIV class='red'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow DIV id='ucp' class='green'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-hidden-yet-scrolled-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-hidden-yet-scrolled-expected.txt
index 9bf82dc..f154fe8 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-hidden-yet-scrolled-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-hidden-yet-scrolled-expected.txt
@@ -25,7 +25,7 @@
         {
           "object": "LayoutBlockFlow DIV id='scroller'",
           "rect": [0, 0, 302, 302],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow DIV id='scroller'",
@@ -38,15 +38,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV id='scroller'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
+      "reason": "full"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar-expected.txt
index 89c0c179..75508387 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar-expected.txt
@@ -25,7 +25,7 @@
         {
           "object": "LayoutBlockFlow DIV id='scroller'",
           "rect": [0, 0, 302, 302],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow DIV id='target'",
@@ -38,15 +38,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV id='scroller'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='target'",
-      "reason": "subtree"
+      "reason": "full"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt
index 21247d4..0e0a867 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt
@@ -19,7 +19,7 @@
         {
           "object": "LayoutBlockFlow DIV class='scroller'",
           "rect": [18, 60, 310, 200],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV class='back'",
@@ -77,15 +77,11 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV class='scroller'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "VerticalScrollbar",
       "reason": "scroll control"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV class='back'",
-      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt
index d0c7ed2..d39ba713 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt
@@ -32,19 +32,11 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV id='innerDiv'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "VerticalScrollbar",
       "reason": "scroll control"
-    },
-    {
-      "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow DIV",
-      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/repaint-during-scroll-with-zoom-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/repaint-during-scroll-with-zoom-expected.txt
index 2cbfcc9..7aaf8d0 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/repaint-during-scroll-with-zoom-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/repaint-during-scroll-with-zoom-expected.txt
@@ -19,7 +19,7 @@
         {
           "object": "LayoutView #document",
           "rect": [3, 65, 250, 250],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow HTML",
@@ -47,7 +47,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutView #document",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "HorizontalScrollbar",
@@ -56,26 +56,6 @@
     {
       "object": "VerticalScrollbar",
       "reason": "scroll control"
-    },
-    {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "subtree"
-    },
-    {
-      "object": "RootInlineBox",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutText #text",
-      "reason": "subtree"
-    },
-    {
-      "object": "InlineTextBox 'scroll me'",
-      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt
index 99bf3f5..35c5a77 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt
@@ -40,11 +40,11 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
-      "reason": "subtree"
+      "reason": "style change"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
+      "reason": "style change"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-fixed-layer-with-transformed-parent-layer-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-fixed-layer-with-transformed-parent-layer-expected.txt
index 1f4893e5..f6fe248 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-fixed-layer-with-transformed-parent-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-fixed-layer-with-transformed-parent-layer-expected.txt
@@ -45,15 +45,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-in-clipped-layer-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-in-clipped-layer-expected.txt
index 916240d..c7edc039 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-in-clipped-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-in-clipped-layer-expected.txt
@@ -32,15 +32,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow (relative positioned) DIV class='relative green'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
index 049fb97..02558861 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
@@ -45,15 +45,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
+      "reason": "geometry"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "geometry"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-in-transformed-layer-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-in-transformed-layer-expected.txt
index 4e6b61e..8bc0ba81 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-in-transformed-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-in-transformed-layer-expected.txt
@@ -37,15 +37,15 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped rotated'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
+      "reason": "style change"
     },
     {
       "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "style change"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
index 450b02e..484d3f1 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
@@ -48,16 +48,6 @@
       ],
       "flattenInheritedTransform": false
     }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow (positioned) DIV id='searchbar'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='recentlink'",
-      "reason": "subtree"
-    }
   ]
 }
 
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-with-transformed-parent-layer-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-with-transformed-parent-layer-expected.txt
index 78623ca..8821614 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-with-transformed-parent-layer-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/scroll/scroll-with-transformed-parent-layer-expected.txt
@@ -37,15 +37,7 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
-      "reason": "subtree"
+      "reason": "full"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/scroll-inside-table-cell-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/scroll-inside-table-cell-expected.txt
index dbdb415..7d103df 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/scroll-inside-table-cell-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/scroll-inside-table-cell-expected.txt
@@ -19,7 +19,7 @@
         {
           "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'",
           "rect": [312, 112, 454, 469],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
@@ -42,19 +42,11 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "HorizontalScrollbar",
       "reason": "scroll control"
-    },
-    {
-      "object": "LayoutBlockFlow (relative positioned) DIV class='relative red'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt
index 1a92c44..3050b71 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt
@@ -19,7 +19,7 @@
         {
           "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'",
           "rect": [1112, 1312, 454, 469],
-          "reason": "subtree"
+          "reason": "full"
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
@@ -55,19 +55,11 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "HorizontalScrollbar",
       "reason": "scroll control"
-    },
-    {
-      "object": "LayoutBlockFlow (relative positioned) DIV class='relative red'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
-      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt
index e2013a37..32059997 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt
@@ -32,35 +32,11 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV id='innerDiv'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "VerticalScrollbar",
       "reason": "scroll control"
-    },
-    {
-      "object": "LayoutTable TABLE",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutTableSection TBODY",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutTableRow TR",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutTableCell TD",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutTableRow TR",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutTableCell TD",
-      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt
index e2013a37..32059997 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt
@@ -32,35 +32,11 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow DIV id='innerDiv'",
-      "reason": "subtree"
+      "reason": "full"
     },
     {
       "object": "VerticalScrollbar",
       "reason": "scroll control"
-    },
-    {
-      "object": "LayoutTable TABLE",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutTableSection TBODY",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutTableRow TR",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutTableCell TD",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutTableRow TR",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutTableCell TD",
-      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
index 5867bc5..894c788 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
@@ -835,6 +835,7 @@
 html element section
 html element select
     property add
+    property autocomplete
     property autofocus
     property checkValidity
     property disabled
@@ -932,6 +933,7 @@
 html element template
     property content
 html element textarea
+    property autocomplete
     property autofocus
     property checkValidity
     property cols
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
index b33b951..5b53a38 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -2724,6 +2724,7 @@
     setter type
 interface HTMLSelectElement : HTMLElement
     attribute @@toStringTag
+    getter autocomplete
     getter autofocus
     getter disabled
     getter form
@@ -2750,6 +2751,7 @@
     method remove
     method reportValidity
     method setCustomValidity
+    setter autocomplete
     setter autofocus
     setter disabled
     setter length
@@ -2924,6 +2926,7 @@
     method constructor
 interface HTMLTextAreaElement : HTMLElement
     attribute @@toStringTag
+    getter autocomplete
     getter autofocus
     getter cols
     getter defaultValue
@@ -2955,6 +2958,7 @@
     method setCustomValidity
     method setRangeText
     method setSelectionRange
+    setter autocomplete
     setter autofocus
     setter cols
     setter defaultValue
diff --git a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
index b5f5ae3..b28df1b 100644
--- a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
@@ -854,6 +854,7 @@
 html element section
 html element select
     property add
+    property autocomplete
     property autofocus
     property checkValidity
     property disabled
@@ -951,6 +952,7 @@
 html element template
     property content
 html element textarea
+    property autocomplete
     property autofocus
     property checkValidity
     property cols
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index c27f0165..22c5ce8 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -3336,6 +3336,7 @@
     setter type
 interface HTMLSelectElement : HTMLElement
     attribute @@toStringTag
+    getter autocomplete
     getter autofocus
     getter disabled
     getter form
@@ -3362,6 +3363,7 @@
     method remove
     method reportValidity
     method setCustomValidity
+    setter autocomplete
     setter autofocus
     setter disabled
     setter length
@@ -3536,6 +3538,7 @@
     method constructor
 interface HTMLTextAreaElement : HTMLElement
     attribute @@toStringTag
+    getter autocomplete
     getter autofocus
     getter cols
     getter defaultValue
@@ -3567,6 +3570,7 @@
     method setCustomValidity
     method setRangeText
     method setSelectionRange
+    setter autocomplete
     setter autofocus
     setter cols
     setter defaultValue
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
index 61c684f..5298acc 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
@@ -237,7 +237,7 @@
     current_parent_ = PersistentForWrappable(traceable);
 
     TracePrologue();
-    traceable->GetWrapperTypeInfo()->TraceWrappers(this, traceable);
+    traceable->TraceWrappers(this);
     AdvanceTracing(
         0,
         v8::EmbedderHeapTracer::AdvanceTracingActions(
@@ -494,8 +494,8 @@
     const v8::Persistent<v8::Object>& wrapper =
         v8::Persistent<v8::Object>::Cast(*value);
 
-    if (ScriptWrappable* script_wrappable = ToScriptWrappable(wrapper))
-      ToWrapperTypeInfo(wrapper)->Trace(visitor_, script_wrappable);
+    ScriptWrappable* script_wrappable = ToScriptWrappable(wrapper);
+    visitor_->Trace(script_wrappable);
   }
 
  private:
diff --git a/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl
index 4d82d7c..eb10c188 100644
--- a/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl
@@ -726,8 +726,6 @@
 const WrapperTypeInfo {{v8_class}}Constructor::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     {{v8_class}}Constructor::domTemplate,
-    {{v8_class}}::Trace,
-    {{v8_class}}::TraceWrappers,
     {{install_conditional_features_func or 'nullptr'}},
     "{{interface_name}}",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/templates/interface.h.tmpl b/third_party/WebKit/Source/bindings/templates/interface.h.tmpl
index 1523bfc2..ef197340 100644
--- a/third_party/WebKit/Source/bindings/templates/interface.h.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/interface.h.tmpl
@@ -45,12 +45,6 @@
   {% else %}
   {{exported}}static const WrapperTypeInfo wrapperTypeInfo;
   {% endif %}
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<{{cpp_class}}>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<{{cpp_class}}>());
-  }
   {% for method in methods %}
   {% if method.is_custom %}
   static void {{method.name}}MethodCustom(const v8::FunctionCallbackInfo<v8::Value>&);
diff --git a/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl
index 0d0f53a..f8717ce 100644
--- a/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl
@@ -27,8 +27,6 @@
 {{wrapper_type_info_const}}WrapperTypeInfo {{v8_class}}::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     {{dom_template}},
-    {{v8_class}}::Trace,
-    {{v8_class}}::TraceWrappers,
     {{install_conditional_features_func or 'nullptr'}},
     "{{interface_name}}",
     {{parent_wrapper_type_info}},
diff --git a/third_party/WebKit/Source/bindings/templates/legacy_callback_interface.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/legacy_callback_interface.cpp.tmpl
index db4b2eb..0f67d02 100644
--- a/third_party/WebKit/Source/bindings/templates/legacy_callback_interface.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/legacy_callback_interface.cpp.tmpl
@@ -19,8 +19,6 @@
     gin::kEmbedderBlink,
     {{v8_class}}::DomTemplate,
     nullptr,
-    nullptr,
-    nullptr,
     "{{interface_name}}",
     nullptr,
     WrapperTypeInfo::kWrapperTypeNoPrototype,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.cpp
index 6df7ae78..d51b690 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.cpp
@@ -33,8 +33,6 @@
 const WrapperTypeInfo V8ArrayBuffer::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     nullptr,
-    V8ArrayBuffer::Trace,
-    V8ArrayBuffer::TraceWrappers,
     nullptr,
     "ArrayBuffer",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.h b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.h
index 61e9057..280de60 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.h
@@ -30,12 +30,6 @@
   CORE_EXPORT static TestArrayBuffer* ToImpl(v8::Local<v8::Object> object);
   CORE_EXPORT static TestArrayBuffer* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestArrayBuffer>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestArrayBuffer>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.cpp
index 6dcd98c5..774d821 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.cpp
@@ -44,8 +44,6 @@
 const WrapperTypeInfo V8ArrayBufferView::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     nullptr,
-    V8ArrayBufferView::Trace,
-    V8ArrayBufferView::TraceWrappers,
     nullptr,
     "ArrayBufferView",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.h b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.h
index 158d5fb0..c6cdff9c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.h
@@ -30,12 +30,6 @@
   CORE_EXPORT static TestArrayBufferView* ToImpl(v8::Local<v8::Object> object);
   CORE_EXPORT static TestArrayBufferView* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestArrayBufferView>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestArrayBufferView>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.cpp
index 27504e1..4203820c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.cpp
@@ -33,8 +33,6 @@
 const WrapperTypeInfo V8DataView::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     nullptr,
-    V8DataView::Trace,
-    V8DataView::TraceWrappers,
     nullptr,
     "DataView",
     &V8ArrayBufferView::wrapperTypeInfo,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.h b/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.h
index 458760cd0..7ea9aa400 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.h
@@ -33,12 +33,6 @@
   CORE_EXPORT static TestDataView* ToImpl(v8::Local<v8::Object> object);
   CORE_EXPORT static TestDataView* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestDataView>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestDataView>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp
index ff59738..1ce03800 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp
@@ -33,8 +33,6 @@
 const WrapperTypeInfo V8SVGTestInterface::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8SVGTestInterface::domTemplate,
-    V8SVGTestInterface::Trace,
-    V8SVGTestInterface::TraceWrappers,
     nullptr,
     "SVGTestInterface",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.h b/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.h
index 737bf6c..097e48be 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static SVGTestInterface* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<SVGTestInterface>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<SVGTestInterface>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestAttributeGetters.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestAttributeGetters.cpp
index 2556be0..2fa9cd6 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestAttributeGetters.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestAttributeGetters.cpp
@@ -32,8 +32,6 @@
 const WrapperTypeInfo V8TestAttributeGetters::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestAttributeGetters::domTemplate,
-    V8TestAttributeGetters::Trace,
-    V8TestAttributeGetters::TraceWrappers,
     nullptr,
     "TestAttributeGetters",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestAttributeGetters.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestAttributeGetters.h
index 0d0b299..5660986 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestAttributeGetters.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestAttributeGetters.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestAttributeGetters* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestAttributeGetters>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestAttributeGetters>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.cpp
index 8a39d15..5c16470 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.cpp
@@ -35,8 +35,6 @@
 const WrapperTypeInfo V8TestCallbackFunctions::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestCallbackFunctions::domTemplate,
-    V8TestCallbackFunctions::Trace,
-    V8TestCallbackFunctions::TraceWrappers,
     nullptr,
     "TestCallbackFunctions",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.h
index 53b785a..f7fd401 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestCallbackFunctions* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestCallbackFunctions>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestCallbackFunctions>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp
index e22b252..e78c019 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp
@@ -33,8 +33,6 @@
 const WrapperTypeInfo V8TestConstants::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestConstants::domTemplate,
-    V8TestConstants::Trace,
-    V8TestConstants::TraceWrappers,
     nullptr,
     "TestConstants",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.h
index 83a7742..f0d663b8 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.h
@@ -36,12 +36,6 @@
   }
   CORE_EXPORT static TestConstants* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestConstants>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestConstants>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   static void installFeatureName1(v8::Isolate*, const DOMWrapperWorld&, v8::Local<v8::Object> instance, v8::Local<v8::Object> prototype, v8::Local<v8::Function> interface);
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp
index e6359b99..c6a4d9f 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp
@@ -36,8 +36,6 @@
 const WrapperTypeInfo V8TestIntegerIndexed::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestIntegerIndexed::domTemplate,
-    V8TestIntegerIndexed::Trace,
-    V8TestIntegerIndexed::TraceWrappers,
     nullptr,
     "TestIntegerIndexed",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.h
index 63ed663..1a30c81 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestIntegerIndexed* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestIntegerIndexed>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestIntegerIndexed>());
-  }
   static void indexedPropertyGetterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Value>&);
   static void indexedPropertySetterCustom(uint32_t, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);
   static void indexedPropertyDeleterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Boolean>&);
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp
index c1f41ed4..ea0a1165 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp
@@ -33,8 +33,6 @@
 const WrapperTypeInfo V8TestIntegerIndexedGlobal::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestIntegerIndexedGlobal::domTemplate,
-    V8TestIntegerIndexedGlobal::Trace,
-    V8TestIntegerIndexedGlobal::TraceWrappers,
     nullptr,
     "TestIntegerIndexedGlobal",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.h
index a0a1a10..4652667 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.h
@@ -36,12 +36,6 @@
   }
   CORE_EXPORT static TestIntegerIndexedGlobal* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestIntegerIndexedGlobal>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestIntegerIndexedGlobal>());
-  }
   static void indexedPropertyGetterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Value>&);
   static void indexedPropertySetterCustom(uint32_t, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);
   static void indexedPropertyDeleterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Boolean>&);
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp
index 5984ea3..2879ebaa 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp
@@ -33,8 +33,6 @@
 const WrapperTypeInfo V8TestIntegerIndexedPrimaryGlobal::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestIntegerIndexedPrimaryGlobal::domTemplate,
-    V8TestIntegerIndexedPrimaryGlobal::Trace,
-    V8TestIntegerIndexedPrimaryGlobal::TraceWrappers,
     nullptr,
     "TestIntegerIndexedPrimaryGlobal",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.h
index 179ddcac..40e6f5c1b 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.h
@@ -36,12 +36,6 @@
   }
   CORE_EXPORT static TestIntegerIndexedPrimaryGlobal* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestIntegerIndexedPrimaryGlobal>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestIntegerIndexedPrimaryGlobal>());
-  }
   static void indexedPropertyGetterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Value>&);
   static void indexedPropertySetterCustom(uint32_t, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);
   static void indexedPropertyDeleterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Boolean>&);
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
index 0612696..5e2e9ea 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
@@ -51,8 +51,6 @@
 WrapperTypeInfo V8TestInterface::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterface::domTemplate,
-    V8TestInterface::Trace,
-    V8TestInterface::TraceWrappers,
     V8TestInterface::InstallConditionalFeatures,
     "TestInterface",
     &V8TestInterfaceEmpty::wrapperTypeInfo,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.h
index 3417d3f..622b9252 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.h
@@ -38,12 +38,6 @@
   }
   CORE_EXPORT static TestInterfaceImplementation* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceImplementation>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceImplementation>());
-  }
   static void implementsCustomVoidMethodMethodCustom(const v8::FunctionCallbackInfo<v8::Value>&);
   static void legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>&);
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
index a23d8cfb..d9ff12c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
@@ -37,8 +37,6 @@
 WrapperTypeInfo V8TestInterface2::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterface2::domTemplate,
-    V8TestInterface2::Trace,
-    V8TestInterface2::TraceWrappers,
     nullptr,
     "TestInterface2",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h
index ba7473b..e472e3e 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestInterface2* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterface2>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterface2>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   CORE_EXPORT static void InstallConditionalFeatures(
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
index aa170ba1..5c0d166fb 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
@@ -33,8 +33,6 @@
 const WrapperTypeInfo V8TestInterface3::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterface3::domTemplate,
-    V8TestInterface3::Trace,
-    V8TestInterface3::TraceWrappers,
     nullptr,
     "TestInterface3",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.h
index cd17b5a6..d514c99 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestInterface3* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterface3>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterface3>());
-  }
   static void indexedPropertyGetterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Value>&);
   static void indexedPropertySetterCustom(uint32_t, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);
   static void indexedPropertyDeleterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Boolean>&);
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp
index dfc4e721..cd678007 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp
@@ -34,8 +34,6 @@
 const WrapperTypeInfo V8TestInterfaceCheckSecurity::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceCheckSecurity::domTemplate,
-    V8TestInterfaceCheckSecurity::Trace,
-    V8TestInterfaceCheckSecurity::TraceWrappers,
     nullptr,
     "TestInterfaceCheckSecurity",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.h
index 8ce505b1..87e2557 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestInterfaceCheckSecurity* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceCheckSecurity>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceCheckSecurity>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
index 39601b67..f3a60ec9 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
@@ -37,8 +37,6 @@
 const WrapperTypeInfo V8TestInterfaceConstructor::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceConstructor::domTemplate,
-    V8TestInterfaceConstructor::Trace,
-    V8TestInterfaceConstructor::TraceWrappers,
     nullptr,
     "TestInterfaceConstructor",
     nullptr,
@@ -319,8 +317,6 @@
 const WrapperTypeInfo V8TestInterfaceConstructorConstructor::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceConstructorConstructor::domTemplate,
-    V8TestInterfaceConstructor::Trace,
-    V8TestInterfaceConstructor::TraceWrappers,
     nullptr,
     "TestInterfaceConstructor",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.h
index f9a35c04..1572fe6 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.h
@@ -44,12 +44,6 @@
   }
   CORE_EXPORT static TestInterfaceConstructor* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceConstructor>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceConstructor>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp
index 2ca0d7f1..f5d6f76 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp
@@ -33,8 +33,6 @@
 const WrapperTypeInfo V8TestInterfaceConstructor2::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceConstructor2::domTemplate,
-    V8TestInterfaceConstructor2::Trace,
-    V8TestInterfaceConstructor2::TraceWrappers,
     nullptr,
     "TestInterfaceConstructor2",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.h
index 061363f..b22011b0 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestInterfaceConstructor2* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceConstructor2>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceConstructor2>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp
index af61fc8..1a8bc40 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp
@@ -31,8 +31,6 @@
 const WrapperTypeInfo V8TestInterfaceConstructor3::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceConstructor3::domTemplate,
-    V8TestInterfaceConstructor3::Trace,
-    V8TestInterfaceConstructor3::TraceWrappers,
     nullptr,
     "TestInterfaceConstructor3",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.h
index 4b83941..c0e6f87 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestInterfaceConstructor3* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceConstructor3>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceConstructor3>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp
index bf03c93..721172d0 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp
@@ -32,8 +32,6 @@
 const WrapperTypeInfo V8TestInterfaceConstructor4::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceConstructor4::domTemplate,
-    V8TestInterfaceConstructor4::Trace,
-    V8TestInterfaceConstructor4::TraceWrappers,
     nullptr,
     "TestInterfaceConstructor4",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.h
index 1093026..e06aec8 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestInterfaceConstructor4* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceConstructor4>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceConstructor4>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp
index defb69c..57a75e8 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp
@@ -29,8 +29,6 @@
 const WrapperTypeInfo V8TestInterfaceCustomConstructor::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceCustomConstructor::domTemplate,
-    V8TestInterfaceCustomConstructor::Trace,
-    V8TestInterfaceCustomConstructor::TraceWrappers,
     nullptr,
     "TestInterfaceCustomConstructor",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.h
index 773e5cd..58619a9d 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestInterfaceCustomConstructor* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceCustomConstructor>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceCustomConstructor>());
-  }
   static void constructorCustom(const v8::FunctionCallbackInfo<v8::Value>&);
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp
index fa9cfd9..739a9355 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp
@@ -34,8 +34,6 @@
 const WrapperTypeInfo V8TestInterfaceDocument::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceDocument::domTemplate,
-    V8TestInterfaceDocument::Trace,
-    V8TestInterfaceDocument::TraceWrappers,
     nullptr,
     "TestInterfaceDocument",
     &V8Document::wrapperTypeInfo,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.h
index cb46d94..9c454ff1 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.h
@@ -37,12 +37,6 @@
   }
   CORE_EXPORT static TestInterfaceDocument* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceDocument>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceDocument>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp
index 50979651..0fed3a9 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp
@@ -28,8 +28,6 @@
 const WrapperTypeInfo V8TestInterfaceEmpty::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceEmpty::domTemplate,
-    V8TestInterfaceEmpty::Trace,
-    V8TestInterfaceEmpty::TraceWrappers,
     nullptr,
     "TestInterfaceEmpty",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.h
index d992f48f..37912e1 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestInterfaceEmpty* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceEmpty>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceEmpty>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp
index 0ea7d3a..58a8dbd 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp
@@ -33,8 +33,6 @@
 const WrapperTypeInfo V8TestInterfaceEventInitConstructor::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceEventInitConstructor::domTemplate,
-    V8TestInterfaceEventInitConstructor::Trace,
-    V8TestInterfaceEventInitConstructor::TraceWrappers,
     nullptr,
     "TestInterfaceEventInitConstructor",
     &V8Event::wrapperTypeInfo,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.h
index 4388933..a1a0eb62 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.h
@@ -36,12 +36,6 @@
   }
   CORE_EXPORT static TestInterfaceEventInitConstructor* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceEventInitConstructor>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceEventInitConstructor>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp
index dbcd66b0..0735657f 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp
@@ -31,8 +31,6 @@
 const WrapperTypeInfo V8TestInterfaceEventTarget::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceEventTarget::domTemplate,
-    V8TestInterfaceEventTarget::Trace,
-    V8TestInterfaceEventTarget::TraceWrappers,
     nullptr,
     "TestInterfaceEventTarget",
     &V8EventTarget::wrapperTypeInfo,
@@ -75,8 +73,6 @@
 const WrapperTypeInfo V8TestInterfaceEventTargetConstructor::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceEventTargetConstructor::domTemplate,
-    V8TestInterfaceEventTarget::Trace,
-    V8TestInterfaceEventTarget::TraceWrappers,
     nullptr,
     "TestInterfaceEventTarget",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.h
index 05a421c..a3ab1d18 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.h
@@ -44,12 +44,6 @@
   }
   CORE_EXPORT static TestInterfaceEventTarget* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceEventTarget>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceEventTarget>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp
index 0817948..582baea 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp
@@ -36,8 +36,6 @@
 const WrapperTypeInfo V8TestInterfaceGarbageCollected::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceGarbageCollected::domTemplate,
-    V8TestInterfaceGarbageCollected::Trace,
-    V8TestInterfaceGarbageCollected::TraceWrappers,
     nullptr,
     "TestInterfaceGarbageCollected",
     &V8EventTarget::wrapperTypeInfo,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.h
index c9e72eb..06c4464 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.h
@@ -36,12 +36,6 @@
   }
   CORE_EXPORT static TestInterfaceGarbageCollected* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceGarbageCollected>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceGarbageCollected>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp
index 0f139c3..aabd35a 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp
@@ -34,8 +34,6 @@
 const WrapperTypeInfo V8TestInterfaceNamedConstructor::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceNamedConstructor::domTemplate,
-    V8TestInterfaceNamedConstructor::Trace,
-    V8TestInterfaceNamedConstructor::TraceWrappers,
     nullptr,
     "TestInterfaceNamedConstructor",
     nullptr,
@@ -97,8 +95,6 @@
 const WrapperTypeInfo V8TestInterfaceNamedConstructorConstructor::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceNamedConstructorConstructor::domTemplate,
-    V8TestInterfaceNamedConstructor::Trace,
-    V8TestInterfaceNamedConstructor::TraceWrappers,
     nullptr,
     "TestInterfaceNamedConstructor",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.h
index c851f89..90756e5 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.h
@@ -43,12 +43,6 @@
   }
   CORE_EXPORT static TestInterfaceNamedConstructor* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceNamedConstructor>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceNamedConstructor>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp
index 23b71b56..9796d98a 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp
@@ -32,8 +32,6 @@
 const WrapperTypeInfo V8TestInterfaceNamedConstructor2::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceNamedConstructor2::domTemplate,
-    V8TestInterfaceNamedConstructor2::Trace,
-    V8TestInterfaceNamedConstructor2::TraceWrappers,
     nullptr,
     "TestInterfaceNamedConstructor2",
     nullptr,
@@ -76,8 +74,6 @@
 const WrapperTypeInfo V8TestInterfaceNamedConstructor2Constructor::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceNamedConstructor2Constructor::domTemplate,
-    V8TestInterfaceNamedConstructor2::Trace,
-    V8TestInterfaceNamedConstructor2::TraceWrappers,
     nullptr,
     "TestInterfaceNamedConstructor2",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.h
index 42e9111d..a53ae36 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.h
@@ -43,12 +43,6 @@
   }
   CORE_EXPORT static TestInterfaceNamedConstructor2* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceNamedConstructor2>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceNamedConstructor2>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp
index f7114d16..1b928371 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp
@@ -36,8 +36,6 @@
 const WrapperTypeInfo V8TestInterfaceNode::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceNode::domTemplate,
-    V8TestInterfaceNode::Trace,
-    V8TestInterfaceNode::TraceWrappers,
     nullptr,
     "TestInterfaceNode",
     &V8Node::wrapperTypeInfo,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.h
index 266b627..f2c98a7 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.h
@@ -36,12 +36,6 @@
   }
   CORE_EXPORT static TestInterfaceNode* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceNode>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceNode>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.cpp
index 10f133a7..6ee0983 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.cpp
@@ -32,8 +32,6 @@
 const WrapperTypeInfo V8TestInterfaceOriginTrialEnabled::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceOriginTrialEnabled::domTemplate,
-    V8TestInterfaceOriginTrialEnabled::Trace,
-    V8TestInterfaceOriginTrialEnabled::TraceWrappers,
     nullptr,
     "TestInterfaceOriginTrialEnabled",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.h
index daf7f96..2c0007b4 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestInterfaceOriginTrialEnabled* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceOriginTrialEnabled>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceOriginTrialEnabled>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.cpp
index c22b5067..813a779 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.cpp
@@ -32,8 +32,6 @@
 const WrapperTypeInfo V8TestInterfaceSecureContext::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterfaceSecureContext::domTemplate,
-    V8TestInterfaceSecureContext::Trace,
-    V8TestInterfaceSecureContext::TraceWrappers,
     V8TestInterfaceSecureContext::InstallConditionalFeatures,
     "TestInterfaceSecureContext",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.h
index 4d294a6c..ebc4917 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestInterfaceSecureContext* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceSecureContext>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterfaceSecureContext>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   CORE_EXPORT static void InstallConditionalFeatures(
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestLegacyCallbackInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestLegacyCallbackInterface.cpp
index 941269c..7088cc0 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestLegacyCallbackInterface.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestLegacyCallbackInterface.cpp
@@ -25,8 +25,6 @@
     gin::kEmbedderBlink,
     V8TestLegacyCallbackInterface::DomTemplate,
     nullptr,
-    nullptr,
-    nullptr,
     "TestLegacyCallbackInterface",
     nullptr,
     WrapperTypeInfo::kWrapperTypeNoPrototype,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp
index 1480f29..48386980 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp
@@ -32,8 +32,6 @@
 const WrapperTypeInfo V8TestNode::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestNode::domTemplate,
-    V8TestNode::Trace,
-    V8TestNode::TraceWrappers,
     nullptr,
     "TestNode",
     &V8Node::wrapperTypeInfo,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.h
index 6eea858..afa0eab 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.h
@@ -36,12 +36,6 @@
   }
   CORE_EXPORT static TestNode* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestNode>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestNode>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
index 187ce31..7ceb58ad 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
@@ -89,8 +89,6 @@
 const WrapperTypeInfo V8TestObject::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestObject::domTemplate,
-    V8TestObject::Trace,
-    V8TestObject::TraceWrappers,
     V8TestObject::InstallConditionalFeatures,
     "TestObject",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.h
index a304f7fa..335690a4 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.h
@@ -50,12 +50,6 @@
   }
   CORE_EXPORT static TestObject* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestObject>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestObject>());
-  }
   static void customVoidMethodMethodCustom(const v8::FunctionCallbackInfo<v8::Value>&);
   static void customCallPrologueVoidMethodMethodPrologueCustom(const v8::FunctionCallbackInfo<v8::Value>&, TestObject*);
   static void customCallEpilogueVoidMethodMethodEpilogueCustom(const v8::FunctionCallbackInfo<v8::Value>&, TestObject*);
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp
index ed46c2f2..0625641 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp
@@ -37,8 +37,6 @@
 const WrapperTypeInfo V8TestSpecialOperations::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestSpecialOperations::domTemplate,
-    V8TestSpecialOperations::Trace,
-    V8TestSpecialOperations::TraceWrappers,
     nullptr,
     "TestSpecialOperations",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.h
index 92ede5b6..b62f073 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.h
@@ -36,12 +36,6 @@
   }
   CORE_EXPORT static TestSpecialOperations* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestSpecialOperations>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestSpecialOperations>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp
index b05d5d58..221f7e1 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp
@@ -30,8 +30,6 @@
 const WrapperTypeInfo V8TestSpecialOperationsNotEnumerable::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestSpecialOperationsNotEnumerable::domTemplate,
-    V8TestSpecialOperationsNotEnumerable::Trace,
-    V8TestSpecialOperationsNotEnumerable::TraceWrappers,
     nullptr,
     "TestSpecialOperationsNotEnumerable",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.h
index c14f348..bd00b8ab 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestSpecialOperationsNotEnumerable* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestSpecialOperationsNotEnumerable>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestSpecialOperationsNotEnumerable>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp
index ab9fe2b..efa2bc0 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp
@@ -44,8 +44,6 @@
 const WrapperTypeInfo V8TestTypedefs::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestTypedefs::domTemplate,
-    V8TestTypedefs::Trace,
-    V8TestTypedefs::TraceWrappers,
     nullptr,
     "TestTypedefs",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.h
index d2cb72e6..7b07b84 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.h
@@ -40,12 +40,6 @@
   }
   CORE_EXPORT static TestTypedefs* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestTypedefs>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestTypedefs>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestVariadicConstructorArguments.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestVariadicConstructorArguments.cpp
index 58900704..17d693ed 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestVariadicConstructorArguments.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestVariadicConstructorArguments.cpp
@@ -31,8 +31,6 @@
 const WrapperTypeInfo V8TestVariadicConstructorArguments::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestVariadicConstructorArguments::domTemplate,
-    V8TestVariadicConstructorArguments::Trace,
-    V8TestVariadicConstructorArguments::TraceWrappers,
     nullptr,
     "TestVariadicConstructorArguments",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestVariadicConstructorArguments.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestVariadicConstructorArguments.h
index feeb6ac..93ba40d 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestVariadicConstructorArguments.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestVariadicConstructorArguments.h
@@ -35,12 +35,6 @@
   }
   CORE_EXPORT static TestVariadicConstructorArguments* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestVariadicConstructorArguments>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestVariadicConstructorArguments>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.cpp
index 6edaeb06..c2502cc 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.cpp
@@ -30,8 +30,6 @@
 const WrapperTypeInfo V8Uint8ClampedArray::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     nullptr,
-    V8Uint8ClampedArray::Trace,
-    V8Uint8ClampedArray::TraceWrappers,
     nullptr,
     "Uint8ClampedArray",
     &V8ArrayBufferView::wrapperTypeInfo,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.h b/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.h
index fe6c3edc..8d5c6cf 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.h
@@ -33,12 +33,6 @@
   CORE_EXPORT static TestUint8ClampedArray* ToImpl(v8::Local<v8::Object> object);
   CORE_EXPORT static TestUint8ClampedArray* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   CORE_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestUint8ClampedArray>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestUint8ClampedArray>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInheritedLegacyUnenumerableNamedProperties.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInheritedLegacyUnenumerableNamedProperties.cpp
index ca560df..1243e3c2 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInheritedLegacyUnenumerableNamedProperties.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInheritedLegacyUnenumerableNamedProperties.cpp
@@ -31,8 +31,6 @@
 const WrapperTypeInfo V8TestInheritedLegacyUnenumerableNamedProperties::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInheritedLegacyUnenumerableNamedProperties::domTemplate,
-    V8TestInheritedLegacyUnenumerableNamedProperties::Trace,
-    V8TestInheritedLegacyUnenumerableNamedProperties::TraceWrappers,
     nullptr,
     "TestInheritedLegacyUnenumerableNamedProperties",
     &V8TestSpecialOperationsNotEnumerable::wrapperTypeInfo,
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInheritedLegacyUnenumerableNamedProperties.h b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInheritedLegacyUnenumerableNamedProperties.h
index 9c6c2ac..909cb8f 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInheritedLegacyUnenumerableNamedProperties.h
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInheritedLegacyUnenumerableNamedProperties.h
@@ -36,12 +36,6 @@
   }
   MODULES_EXPORT static TestInheritedLegacyUnenumerableNamedProperties* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   MODULES_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInheritedLegacyUnenumerableNamedProperties>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInheritedLegacyUnenumerableNamedProperties>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp
index e820eeb..8a98d19 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp
@@ -35,8 +35,6 @@
 const WrapperTypeInfo V8TestInterface5::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestInterface5::domTemplate,
-    V8TestInterface5::Trace,
-    V8TestInterface5::TraceWrappers,
     V8TestInterface5::InstallConditionalFeatures,
     "TestInterface5",
     &V8TestInterfaceEmpty::wrapperTypeInfo,
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.h b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.h
index a068ce7..f084ce7 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.h
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.h
@@ -38,12 +38,6 @@
   }
   MODULES_EXPORT static TestInterface5Implementation* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   MODULES_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestInterface5Implementation>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestInterface5Implementation>());
-  }
   static void legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>&);
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestNotEnumerableNamedGetter.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestNotEnumerableNamedGetter.cpp
index f1d865b..d1c639f 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestNotEnumerableNamedGetter.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestNotEnumerableNamedGetter.cpp
@@ -30,8 +30,6 @@
 const WrapperTypeInfo V8TestNotEnumerableNamedGetter::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestNotEnumerableNamedGetter::domTemplate,
-    V8TestNotEnumerableNamedGetter::Trace,
-    V8TestNotEnumerableNamedGetter::TraceWrappers,
     nullptr,
     "TestNotEnumerableNamedGetter",
     nullptr,
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestNotEnumerableNamedGetter.h b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestNotEnumerableNamedGetter.h
index 18c2123a..781e304 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestNotEnumerableNamedGetter.h
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestNotEnumerableNamedGetter.h
@@ -35,12 +35,6 @@
   }
   MODULES_EXPORT static TestNotEnumerableNamedGetter* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   MODULES_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestNotEnumerableNamedGetter>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestNotEnumerableNamedGetter>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestSubObject.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestSubObject.cpp
index 0be722a..198d5d4 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestSubObject.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestSubObject.cpp
@@ -31,8 +31,6 @@
 const WrapperTypeInfo V8TestSubObject::wrapperTypeInfo = {
     gin::kEmbedderBlink,
     V8TestSubObject::domTemplate,
-    V8TestSubObject::Trace,
-    V8TestSubObject::TraceWrappers,
     nullptr,
     "TestSubObject",
     &V8TestObject::wrapperTypeInfo,
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestSubObject.h b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestSubObject.h
index 9352331..921b954c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestSubObject.h
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestSubObject.h
@@ -36,12 +36,6 @@
   }
   MODULES_EXPORT static TestSubObject* ToImplWithTypeCheck(v8::Isolate*, v8::Local<v8::Value>);
   MODULES_EXPORT static const WrapperTypeInfo wrapperTypeInfo;
-  static void Trace(Visitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceFromGeneratedCode(scriptWrappable->ToImpl<TestSubObject>());
-  }
-  static void TraceWrappers(ScriptWrappableVisitor* visitor, ScriptWrappable* scriptWrappable) {
-    visitor->TraceWrappersFromGeneratedCode(scriptWrappable->ToImpl<TestSubObject>());
-  }
   static const int internalFieldCount = kV8DefaultWrapperInternalFieldCount;
 
   // Callback functions
diff --git a/third_party/WebKit/Source/core/animation/OWNERS b/third_party/WebKit/Source/core/animation/OWNERS
index 4364bfb73..223157a5 100644
--- a/third_party/WebKit/Source/core/animation/OWNERS
+++ b/third_party/WebKit/Source/core/animation/OWNERS
@@ -1,4 +1,5 @@
 flackr@chromium.org
+smcgruer@chromium.org
 
 # Legacy owners:
 alancutter@chromium.org
diff --git a/third_party/WebKit/Source/core/css/SelectorQuery.cpp b/third_party/WebKit/Source/core/css/SelectorQuery.cpp
index 62cee6e..67cd6bf 100644
--- a/third_party/WebKit/Source/core/css/SelectorQuery.cpp
+++ b/third_party/WebKit/Source/core/css/SelectorQuery.cpp
@@ -305,9 +305,8 @@
   }
 }
 
-// FIXME: Move the following helper functions, authorShadowRootOf,
-// firstWithinTraversingShadowTree, nextTraversingShadowTree to the best place,
-// e.g. NodeTraversal.
+// FIXME: Move the following helper functions, AuthorShadowRootOf,
+// NextTraversingShadowTree to the best place, e.g. NodeTraversal.
 static ShadowRoot* AuthorShadowRootOf(const ContainerNode& node) {
   if (!node.IsElementNode())
     return nullptr;
@@ -315,11 +314,9 @@
   if (!shadow)
     return nullptr;
 
-  for (ShadowRoot* shadow_root = &shadow->OldestShadowRoot(); shadow_root;
-       shadow_root = shadow_root->YoungerShadowRoot()) {
-    if (shadow_root->IsOpenOrV0())
-      return shadow_root;
-  }
+  ShadowRoot& shadow_root = shadow->GetShadowRoot();
+  if (shadow_root.IsOpenOrV0())
+    return &shadow_root;
   return nullptr;
 }
 
@@ -339,10 +336,6 @@
     ShadowRoot* shadow_root = current->ContainingShadowRoot();
     if (shadow_root == root_node)
       return nullptr;
-    if (ShadowRoot* younger_shadow_root = shadow_root->YoungerShadowRoot()) {
-      DCHECK(younger_shadow_root->IsOpenOrV0());
-      return younger_shadow_root;
-    }
 
     current = &shadow_root->host();
   }
diff --git a/third_party/WebKit/Source/core/css/StyleEngine.cpp b/third_party/WebKit/Source/core/css/StyleEngine.cpp
index 67141f87..2419882 100644
--- a/third_party/WebKit/Source/core/css/StyleEngine.cpp
+++ b/third_party/WebKit/Source/core/css/StyleEngine.cpp
@@ -1032,12 +1032,10 @@
       InvalidateSlottedElements(ToHTMLSlotElement(*element));
 
     if (invalidation_scope == kInvalidateAllScopes) {
-      ElementShadow* shadow = element->Shadow();
-      ShadowRoot* shadow_root = shadow ? &shadow->OldestShadowRoot() : nullptr;
-      while (shadow_root) {
-        ScheduleInvalidationsForRuleSets(*shadow_root, rule_sets,
+      if (ElementShadow* shadow = element->Shadow()) {
+        ShadowRoot& shadow_root = shadow->GetShadowRoot();
+        ScheduleInvalidationsForRuleSets(shadow_root, rule_sets,
                                          kInvalidateAllScopes);
-        shadow_root = shadow_root->YoungerShadowRoot();
       }
     }
 
diff --git a/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp b/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp
index 6165d79..af99cc9 100644
--- a/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp
+++ b/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp
@@ -342,11 +342,10 @@
     Element& element,
     RecursionData& recursion_data) {
   bool some_children_need_style_recalc = false;
-  for (ShadowRoot* root = element.YoungestShadowRoot(); root;
-       root = root->OlderShadowRoot()) {
+  if (ShadowRoot* root = element.GetShadowRoot()) {
     if (!recursion_data.TreeBoundaryCrossing() &&
         !root->ChildNeedsStyleInvalidation() && !root->NeedsStyleInvalidation())
-      continue;
+      return false;
     RecursionCheckpoint checkpoint(&recursion_data);
     SiblingData sibling_data;
     if (UNLIKELY(root->NeedsStyleInvalidation()))
@@ -367,7 +366,7 @@
                                           RecursionData& recursion_data) {
   SiblingData sibling_data;
   bool some_children_need_style_recalc = false;
-  if (UNLIKELY(!!element.YoungestShadowRoot())) {
+  if (UNLIKELY(!!element.GetShadowRoot())) {
     some_children_need_style_recalc =
         InvalidateShadowRootChildren(element, recursion_data);
   }
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
index c3d3f308..a31e3b8 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -137,11 +137,9 @@
     return;
 
   // Adding scoped resolver for active shadow roots for shadow host styling.
-  for (ShadowRoot* shadow_root = &shadow->YoungestShadowRoot(); shadow_root;
-       shadow_root = shadow_root->OlderShadowRoot()) {
-    if (ScopedStyleResolver* resolver = shadow_root->GetScopedStyleResolver())
-      resolvers.push_back(resolver);
-  }
+  ShadowRoot& shadow_root = shadow->GetShadowRoot();
+  if (ScopedStyleResolver* resolver = shadow_root.GetScopedStyleResolver())
+    resolvers.push_back(resolver);
 }
 
 StyleResolver::StyleResolver(Document& document) : document_(document) {
@@ -196,14 +194,12 @@
   if (!shadow)
     return;
 
-  for (ShadowRoot* shadow_root = &shadow->OldestShadowRoot(); shadow_root;
-       shadow_root = shadow_root->YoungerShadowRoot()) {
-    if (ScopedStyleResolver* resolver = shadow_root->GetScopedStyleResolver()) {
-      collector.ClearMatchedRules();
-      resolver->CollectMatchingShadowHostRules(collector);
-      collector.SortAndTransferMatchedRules();
-      collector.FinishAddingAuthorRulesForTreeScope();
-    }
+  ShadowRoot& shadow_root = shadow->GetShadowRoot();
+  if (ScopedStyleResolver* resolver = shadow_root.GetScopedStyleResolver()) {
+    collector.ClearMatchedRules();
+    resolver->CollectMatchingShadowHostRules(collector);
+    collector.SortAndTransferMatchedRules();
+    collector.FinishAddingAuthorRulesForTreeScope();
   }
 }
 
diff --git a/third_party/WebKit/Source/core/dom/ChildFrameDisconnector.cpp b/third_party/WebKit/Source/core/dom/ChildFrameDisconnector.cpp
index c5c0973b..937298ec 100644
--- a/third_party/WebKit/Source/core/dom/ChildFrameDisconnector.cpp
+++ b/third_party/WebKit/Source/core/dom/ChildFrameDisconnector.cpp
@@ -46,7 +46,7 @@
   ElementShadow* shadow =
       root.IsElementNode() ? ToElement(root).Shadow() : nullptr;
   if (shadow)
-    CollectFrameOwners(*shadow);
+    CollectFrameOwners(shadow->GetShadowRoot());
 }
 
 void ChildFrameDisconnector::DisconnectCollectedFrameOwners() {
@@ -63,12 +63,6 @@
   }
 }
 
-void ChildFrameDisconnector::CollectFrameOwners(ElementShadow& shadow) {
-  for (ShadowRoot* root = &shadow.YoungestShadowRoot(); root;
-       root = root->OlderShadowRoot())
-    CollectFrameOwners(*root);
-}
-
 #if DCHECK_IS_ON()
 static unsigned CheckConnectedSubframeCountIsConsistent(Node& node) {
   unsigned count = 0;
@@ -79,9 +73,8 @@
       count++;
 
     if (ElementShadow* shadow = ToElement(node).Shadow()) {
-      for (ShadowRoot* root = &shadow->YoungestShadowRoot(); root;
-           root = root->OlderShadowRoot())
-        count += CheckConnectedSubframeCountIsConsistent(*root);
+      ShadowRoot& root = shadow->GetShadowRoot();
+      count += CheckConnectedSubframeCountIsConsistent(root);
     }
   }
 
diff --git a/third_party/WebKit/Source/core/dom/ChildFrameDisconnector.h b/third_party/WebKit/Source/core/dom/ChildFrameDisconnector.h
index f3b650b4..ea35f421 100644
--- a/third_party/WebKit/Source/core/dom/ChildFrameDisconnector.h
+++ b/third_party/WebKit/Source/core/dom/ChildFrameDisconnector.h
@@ -9,7 +9,6 @@
 
 namespace blink {
 
-class ElementShadow;
 class HTMLFrameOwnerElement;
 class Node;
 
@@ -25,7 +24,6 @@
 
  private:
   void CollectFrameOwners(Node&);
-  void CollectFrameOwners(ElementShadow&);
   void DisconnectCollectedFrameOwners();
   Node& Root() const { return *root_; }
 
diff --git a/third_party/WebKit/Source/core/dom/ContainerNode.cpp b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
index 2a21883f..3f2da247 100644
--- a/third_party/WebKit/Source/core/dom/ContainerNode.cpp
+++ b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
@@ -912,8 +912,7 @@
     if (Node::kInsertionShouldCallDidNotifySubtreeInsertions ==
         node.InsertedInto(this))
       post_insertion_notification_targets.push_back(&node);
-    for (ShadowRoot* shadow_root = node.YoungestShadowRoot(); shadow_root;
-         shadow_root = shadow_root->OlderShadowRoot())
+    if (ShadowRoot* shadow_root = node.GetShadowRoot())
       NotifyNodeInsertedInternal(*shadow_root,
                                  post_insertion_notification_targets);
   }
@@ -930,8 +929,7 @@
     if (!node.IsContainerNode() && !node.IsInTreeScope())
       continue;
     node.RemovedFrom(this);
-    for (ShadowRoot* shadow_root = node.YoungestShadowRoot(); shadow_root;
-         shadow_root = shadow_root->OlderShadowRoot())
+    if (ShadowRoot* shadow_root = node.GetShadowRoot())
       NotifyNodeRemoved(*shadow_root);
   }
 }
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index 9a7a4993..c9a921b 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -2110,8 +2110,7 @@
     DCHECK(!node.ChildNeedsDistributionRecalc());
     DCHECK(!node.NeedsStyleInvalidation());
     DCHECK(!node.ChildNeedsStyleInvalidation());
-    for (ShadowRoot* shadow_root = node.YoungestShadowRoot(); shadow_root;
-         shadow_root = shadow_root->OlderShadowRoot())
+    if (ShadowRoot* shadow_root = node.GetShadowRoot())
       AssertLayoutTreeUpdated(*shadow_root);
   }
 }
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index aec9faf..cf6ea960 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -240,7 +240,7 @@
              : 0;
 }
 
-bool Element::LayoutObjectIsFocusable() const {
+bool Element::IsFocusableStyle() const {
   // Elements in canvas fallback content are not rendered, but they are allowed
   // to be focusable as long as their canvas is displayed and visible.
   if (IsInCanvasSubtree()) {
@@ -2065,8 +2065,7 @@
     UpdatePseudoElement(kPseudoIdBefore, change);
 
     if (change > kUpdatePseudoElements || ChildNeedsStyleRecalc()) {
-      for (ShadowRoot* root = YoungestShadowRoot(); root;
-           root = root->OlderShadowRoot()) {
+      if (ShadowRoot* root = GetShadowRoot()) {
         if (root->ShouldCallRecalcStyle(change))
           root->RecalcStyle(change);
       }
@@ -2223,10 +2222,8 @@
 }
 
 void Element::RecalcShadowRootStylesForReattach() {
-  for (ShadowRoot* root = YoungestShadowRoot(); root;
-       root = root->OlderShadowRoot()) {
+  if (ShadowRoot* root = GetShadowRoot())
     root->RecalcStylesForReattach();
-  }
 }
 
 void Element::RebuildLayoutTree(WhitespaceAttacher& whitespace_attacher) {
@@ -2277,10 +2274,8 @@
 void Element::RebuildShadowRootLayoutTree(
     WhitespaceAttacher& whitespace_attacher) {
   DCHECK(Shadow());
-  for (ShadowRoot* root = YoungestShadowRoot(); root;
-       root = root->OlderShadowRoot()) {
+  if (ShadowRoot* root = GetShadowRoot())
     root->RebuildLayoutTree(whitespace_attacher);
-  }
   RebuildNonDistributedChildren();
 }
 
@@ -2526,13 +2521,6 @@
   return shadow_root;
 }
 
-ShadowRoot* Element::GetShadowRoot() const {
-  ElementShadow* element_shadow = Shadow();
-  if (!element_shadow)
-    return nullptr;
-  return &element_shadow->YoungestShadowRoot();
-}
-
 ShadowRoot* Element::OpenShadowRoot() const {
   ShadowRoot* root = GetShadowRoot();
   if (!root)
@@ -2559,11 +2547,10 @@
 
 ShadowRoot* Element::UserAgentShadowRoot() const {
   if (ElementShadow* element_shadow = Shadow()) {
-    ShadowRoot& root = element_shadow->OldestShadowRoot();
+    ShadowRoot& root = element_shadow->GetShadowRoot();
     DCHECK(root.IsUserAgent());
     return &root;
   }
-
   return nullptr;
 }
 
@@ -3035,8 +3022,7 @@
   // needsLayoutTreeUpdateForNode check is invalid.
   DCHECK(!GetDocument().IsActive() ||
          !GetDocument().NeedsLayoutTreeUpdateForNode(*this));
-  return isConnected() && SupportsFocus() && !IsInert() &&
-         LayoutObjectIsFocusable();
+  return isConnected() && SupportsFocus() && !IsInert() && IsFocusableStyle();
 }
 
 bool Element::IsKeyboardFocusable() const {
diff --git a/third_party/WebKit/Source/core/dom/Element.h b/third_party/WebKit/Source/core/dom/Element.h
index 650dab5..2c52e015 100644
--- a/third_party/WebKit/Source/core/dom/Element.h
+++ b/third_party/WebKit/Source/core/dom/Element.h
@@ -502,13 +502,12 @@
   ShadowRoot& AttachShadowRootInternal(ShadowRootType,
                                        bool delegates_focus = false);
 
+  ShadowRoot* GetShadowRoot() const;
   ShadowRoot* OpenShadowRoot() const;
   ShadowRoot* ClosedShadowRoot() const;
   ShadowRoot* AuthorShadowRoot() const;
   ShadowRoot* UserAgentShadowRoot() const;
 
-  ShadowRoot* YoungestShadowRoot() const;
-
   ShadowRoot* ShadowRootIfV1() const;
 
   ShadowRoot& EnsureUserAgentShadowRoot();
@@ -887,8 +886,7 @@
   // However, it must not retrieve layout information like position and size.
   // This method cannot be moved to LayoutObject because some focusable nodes
   // don't have layoutObjects. e.g., HTMLOptionElement.
-  // TODO(tkent): Rename this to isFocusableStyle.
-  virtual bool LayoutObjectIsFocusable() const;
+  virtual bool IsFocusableStyle() const;
 
   virtual bool ChildrenCanHaveStyle() const { return true; }
 
@@ -956,8 +954,6 @@
   inline PseudoElement* CreatePseudoElementIfNeeded(PseudoId);
   void CreateAndAttachPseudoElementIfNeeded(PseudoId, AttachContext&);
 
-  ShadowRoot* GetShadowRoot() const;
-
   // FIXME: Everyone should allow author shadows.
   virtual bool AreAuthorShadowsAllowed() const { return true; }
   virtual void DidAddUserAgentShadowRoot(ShadowRoot&) {}
diff --git a/third_party/WebKit/Source/core/dom/ElementShadow.cpp b/third_party/WebKit/Source/core/dom/ElementShadow.cpp
index b293c64..518ceb2e 100644
--- a/third_party/WebKit/Source/core/dom/ElementShadow.cpp
+++ b/third_party/WebKit/Source/core/dom/ElementShadow.cpp
@@ -44,37 +44,20 @@
 
 ElementShadow::ElementShadow() : needs_distribution_recalc_(false) {}
 
-ShadowRoot& ElementShadow::YoungestShadowRoot() const {
-  ShadowRoot* current = shadow_root_;
-  DCHECK(current);
-  while (current->YoungerShadowRoot())
-    current = current->YoungerShadowRoot();
-  return *current;
-}
-
 ShadowRoot& ElementShadow::AddShadowRoot(Element& shadow_host,
                                          ShadowRootType type) {
   EventDispatchForbiddenScope assert_no_event_dispatch;
   ScriptForbiddenScope forbid_script;
 
-  // Multiple ShadowRoots are removed.
-  // TODO(kochi): Further cleanup of unnecessary code for multiple shadow.
   DCHECK(!shadow_root_);
-
-  if (shadow_root_) {
-    // TODO(hayato): Is the order, from the youngest to the oldest, important?
-    for (ShadowRoot* root = &YoungestShadowRoot(); root;
-         root = root->OlderShadowRoot())
-      root->LazyReattachIfAttached();
-  } else if (type == ShadowRootType::V0) {
+  if (type == ShadowRootType::V0) {
     DCHECK(!element_shadow_v0_);
     element_shadow_v0_ = ElementShadowV0::Create(*this);
   }
 
-  ShadowRoot* shadow_root = ShadowRoot::Create(shadow_host.GetDocument(), type);
-  shadow_root->SetParentOrShadowHostNode(&shadow_host);
-  shadow_root->SetParentTreeScope(shadow_host.GetTreeScope());
-  AppendShadowRoot(*shadow_root);
+  shadow_root_ = ShadowRoot::Create(shadow_host.GetDocument(), type);
+  shadow_root_->SetParentOrShadowHostNode(&shadow_host);
+  shadow_root_->SetParentTreeScope(shadow_host.GetTreeScope());
   if (type == ShadowRootType::V0) {
     SetNeedsDistributionRecalc();
   } else {
@@ -82,51 +65,33 @@
       child.LazyReattachIfAttached();
   }
 
-  shadow_root->InsertedInto(&shadow_host);
+  shadow_root_->InsertedInto(&shadow_host);
   shadow_host.SetChildNeedsStyleRecalc();
   shadow_host.SetNeedsStyleRecalc(
       kSubtreeStyleChange,
       StyleChangeReasonForTracing::Create(StyleChangeReason::kShadow));
 
-  probe::didPushShadowRoot(&shadow_host, shadow_root);
+  probe::didPushShadowRoot(&shadow_host, shadow_root_);
 
-  return *shadow_root;
-}
-
-void ElementShadow::AppendShadowRoot(ShadowRoot& shadow_root) {
-  if (!shadow_root_) {
-    shadow_root_ = &shadow_root;
-    return;
-  }
-  ShadowRoot& youngest = YoungestShadowRoot();
-  DCHECK(shadow_root.GetType() == ShadowRootType::V0);
-  DCHECK(youngest.GetType() == ShadowRootType::V0);
-  youngest.SetYoungerShadowRoot(shadow_root);
-  shadow_root.SetOlderShadowRoot(youngest);
+  return *shadow_root_;
 }
 
 void ElementShadow::Attach(const Node::AttachContext& context) {
   Node::AttachContext children_context(context);
-
-  for (ShadowRoot* root = &YoungestShadowRoot(); root;
-       root = root->OlderShadowRoot()) {
-    if (root->NeedsAttach())
-      root->AttachLayoutTree(children_context);
-  }
+  ShadowRoot& root = GetShadowRoot();
+  if (root.NeedsAttach())
+    root.AttachLayoutTree(children_context);
 }
 
 void ElementShadow::Detach(const Node::AttachContext& context) {
   Node::AttachContext children_context(context);
   children_context.clear_invalidation = true;
-
-  for (ShadowRoot* root = &YoungestShadowRoot(); root;
-       root = root->OlderShadowRoot())
-    root->DetachLayoutTree(children_context);
+  GetShadowRoot().DetachLayoutTree(children_context);
 }
 
 void ElementShadow::SetNeedsDistributionRecalcWillBeSetNeedsAssignmentRecalc() {
   if (RuntimeEnabledFeatures::IncrementalShadowDOMEnabled() && IsV1())
-    YoungestShadowRoot().SetNeedsAssignmentRecalc();
+    GetShadowRoot().SetNeedsAssignmentRecalc();
   else
     SetNeedsDistributionRecalc();
 }
@@ -141,29 +106,9 @@
     V0().ClearDistribution();
 }
 
-bool ElementShadow::HasSameStyles(const ElementShadow& other) const {
-  ShadowRoot* root = &YoungestShadowRoot();
-  ShadowRoot* other_root = &other.YoungestShadowRoot();
-  while (root || other_root) {
-    if (!root || !other_root)
-      return false;
-
-    if (!ScopedStyleResolver::HaveSameStyles(
-            root->GetScopedStyleResolver(),
-            other_root->GetScopedStyleResolver())) {
-      return false;
-    }
-
-    root = root->OlderShadowRoot();
-    other_root = other_root->OlderShadowRoot();
-  }
-
-  return true;
-}
-
 void ElementShadow::Distribute() {
   if (IsV1())
-    YoungestShadowRoot().DistributeV1();
+    GetShadowRoot().DistributeV1();
   else
     V0().Distribute();
 }
diff --git a/third_party/WebKit/Source/core/dom/ElementShadow.h b/third_party/WebKit/Source/core/dom/ElementShadow.h
index fee3237..c13a5b0 100644
--- a/third_party/WebKit/Source/core/dom/ElementShadow.h
+++ b/third_party/WebKit/Source/core/dom/ElementShadow.h
@@ -48,20 +48,14 @@
     return shadow_root_->host();
   }
 
-  // TODO(hayato): Remove youngestShadowRoot() and oldestShadowRoot() from
-  // ElementShadow
-  ShadowRoot& YoungestShadowRoot() const;
-  ShadowRoot& OldestShadowRoot() const {
+  ShadowRoot& GetShadowRoot() const {
     DCHECK(shadow_root_);
     return *shadow_root_;
   }
-
   ElementShadow* ContainingShadow() const;
 
   ShadowRoot& AddShadowRoot(Element& shadow_host, ShadowRootType);
 
-  bool HasSameStyles(const ElementShadow&) const;
-
   void Attach(const Node::AttachContext&);
   void Detach(const Node::AttachContext&);
 
@@ -71,8 +65,8 @@
   void SetNeedsDistributionRecalc();
   bool NeedsDistributionRecalc() const { return needs_distribution_recalc_; }
 
-  bool IsV1() const { return YoungestShadowRoot().IsV1(); }
-  bool IsOpenOrV0() const { return YoungestShadowRoot().IsOpenOrV0(); }
+  bool IsV1() const { return GetShadowRoot().IsV1(); }
+  bool IsOpenOrV0() const { return GetShadowRoot().IsOpenOrV0(); }
 
   ElementShadowV0& V0() const {
     DCHECK(element_shadow_v0_);
@@ -85,7 +79,6 @@
  private:
   ElementShadow();
 
-  void AppendShadowRoot(ShadowRoot&);
   void Distribute();
 
   TraceWrapperMember<ElementShadowV0> element_shadow_v0_;
@@ -94,15 +87,22 @@
   DISALLOW_COPY_AND_ASSIGN(ElementShadow);
 };
 
-inline ShadowRoot* Node::YoungestShadowRoot() const {
+inline ShadowRoot* Node::GetShadowRoot() const {
   if (!IsElementNode())
     return nullptr;
-  return ToElement(this)->YoungestShadowRoot();
+  return ToElement(this)->GetShadowRoot();
 }
 
-inline ShadowRoot* Element::YoungestShadowRoot() const {
+inline ShadowRoot* Element::GetShadowRoot() const {
   if (ElementShadow* shadow = Shadow())
-    return &shadow->YoungestShadowRoot();
+    return &shadow->GetShadowRoot();
+  return nullptr;
+}
+
+inline ShadowRoot* Element::ShadowRootIfV1() const {
+  ShadowRoot* root = GetShadowRoot();
+  if (root && root->IsV1())
+    return root;
   return nullptr;
 }
 
diff --git a/third_party/WebKit/Source/core/dom/ElementShadowV0.cpp b/third_party/WebKit/Source/core/dom/ElementShadowV0.cpp
index 256c3f8..b499c28 100644
--- a/third_party/WebKit/Source/core/dom/ElementShadowV0.cpp
+++ b/third_party/WebKit/Source/core/dom/ElementShadowV0.cpp
@@ -132,12 +132,8 @@
 
 ElementShadowV0::~ElementShadowV0() = default;
 
-ShadowRoot& ElementShadowV0::YoungestShadowRoot() const {
-  return element_shadow_->YoungestShadowRoot();
-}
-
-ShadowRoot& ElementShadowV0::OldestShadowRoot() const {
-  return element_shadow_->OldestShadowRoot();
+inline ShadowRoot& ElementShadowV0::GetShadowRoot() const {
+  return element_shadow_->GetShadowRoot();
 }
 
 const V0InsertionPoint* ElementShadowV0::FinalDestinationInsertionPointFor(
@@ -162,24 +158,22 @@
   HeapVector<Member<HTMLShadowElement>, 32> shadow_insertion_points;
   DistributionPool pool(element_shadow_->Host());
 
-  for (ShadowRoot* root = &YoungestShadowRoot(); root;
-       root = root->OlderShadowRoot()) {
-    HTMLShadowElement* shadow_insertion_point = nullptr;
-    for (const auto& point : root->DescendantInsertionPoints()) {
-      if (!point->IsActive())
-        continue;
-      if (auto* shadow = ToHTMLShadowElementOrNull(*point)) {
-        DCHECK(!shadow_insertion_point);
-        shadow_insertion_point = shadow;
-        shadow_insertion_points.push_back(shadow_insertion_point);
-      } else {
-        pool.DistributeTo(point, this);
-        if (ElementShadow* shadow =
-                ShadowWhereNodeCanBeDistributedForV0(*point)) {
-          if (!(RuntimeEnabledFeatures::IncrementalShadowDOMEnabled() &&
-                shadow->IsV1()))
-            shadow->SetNeedsDistributionRecalc();
-        }
+  ShadowRoot& root = GetShadowRoot();
+  HTMLShadowElement* shadow_insertion_point = nullptr;
+  for (const auto& point : root.DescendantInsertionPoints()) {
+    if (!point->IsActive())
+      continue;
+    if (auto* shadow = ToHTMLShadowElementOrNull(*point)) {
+      DCHECK(!shadow_insertion_point);
+      shadow_insertion_point = shadow;
+      shadow_insertion_points.push_back(shadow_insertion_point);
+    } else {
+      pool.DistributeTo(point, this);
+      if (ElementShadow* shadow =
+              ShadowWhereNodeCanBeDistributedForV0(*point)) {
+        if (!(RuntimeEnabledFeatures::IncrementalShadowDOMEnabled() &&
+              shadow->IsV1()))
+          shadow->SetNeedsDistributionRecalc();
       }
     }
   }
@@ -188,16 +182,7 @@
     HTMLShadowElement* shadow_insertion_point = shadow_insertion_points[i - 1];
     ShadowRoot* root = shadow_insertion_point->ContainingShadowRoot();
     DCHECK(root);
-    if (root->IsOldest()) {
-      pool.DistributeTo(shadow_insertion_point, this);
-    } else if (root->OlderShadowRoot()->GetType() == root->GetType()) {
-      // Only allow reprojecting older shadow roots between the same type to
-      // disallow reprojecting UA elements into author shadows.
-      DistributionPool older_shadow_root_pool(*root->OlderShadowRoot());
-      older_shadow_root_pool.DistributeTo(shadow_insertion_point, this);
-      root->OlderShadowRoot()->SetShadowInsertionPointOfYoungerShadowRoot(
-          shadow_insertion_point);
-    }
+    pool.DistributeTo(shadow_insertion_point, this);
     if (ElementShadow* shadow =
             ShadowWhereNodeCanBeDistributedForV0(*shadow_insertion_point))
       shadow->SetNeedsDistributionRecalc();
@@ -219,9 +204,7 @@
     return select_features_;
 
   select_features_.Clear();
-  for (const ShadowRoot* root = &OldestShadowRoot(); root;
-       root = root->YoungerShadowRoot())
-    CollectSelectFeatureSetFrom(*root);
+  CollectSelectFeatureSetFrom(GetShadowRoot());
   needs_select_feature_set_ = false;
   return select_features_;
 }
@@ -252,10 +235,6 @@
 
 void ElementShadowV0::ClearDistribution() {
   node_to_insertion_points_.clear();
-
-  for (ShadowRoot* root = &element_shadow_->YoungestShadowRoot(); root;
-       root = root->OlderShadowRoot())
-    root->SetShadowInsertionPointOfYoungerShadowRoot(nullptr);
 }
 
 void ElementShadowV0::Trace(blink::Visitor* visitor) {
diff --git a/third_party/WebKit/Source/core/dom/ElementShadowV0.h b/third_party/WebKit/Source/core/dom/ElementShadowV0.h
index 886c93b..daf1db5 100644
--- a/third_party/WebKit/Source/core/dom/ElementShadowV0.h
+++ b/third_party/WebKit/Source/core/dom/ElementShadowV0.h
@@ -60,8 +60,7 @@
  private:
   explicit ElementShadowV0(ElementShadow&);
 
-  ShadowRoot& YoungestShadowRoot() const;
-  ShadowRoot& OldestShadowRoot() const;
+  ShadowRoot& GetShadowRoot() const;
 
   void DistributeNodeChildrenTo(V0InsertionPoint*, ContainerNode*);
 
diff --git a/third_party/WebKit/Source/core/dom/FlatTreeTraversal.cpp b/third_party/WebKit/Source/core/dom/FlatTreeTraversal.cpp
index 48810bf..73ee7ee0 100644
--- a/third_party/WebKit/Source/core/dom/FlatTreeTraversal.cpp
+++ b/third_party/WebKit/Source/core/dom/FlatTreeTraversal.cpp
@@ -38,7 +38,7 @@
                                        TraversalDirection direction) {
   ElementShadow* shadow = ShadowFor(node);
   if (shadow) {
-    ShadowRoot& shadow_root = shadow->YoungestShadowRoot();
+    ShadowRoot& shadow_root = shadow->GetShadowRoot();
     return ResolveDistributionStartingAt(direction == kTraversalDirectionForward
                                              ? shadow_root.firstChild()
                                              : shadow_root.lastChild(),
@@ -122,19 +122,6 @@
       return TraverseSiblings(*slot, direction);
   }
 
-  if (!node.IsInV0ShadowTree())
-    return nullptr;
-
-  // For v0 older shadow tree
-  if (node.parentNode() && node.parentNode()->IsShadowRoot()) {
-    ShadowRoot* parent_shadow_root = ToShadowRoot(node.parentNode());
-    if (!parent_shadow_root->IsYoungest()) {
-      HTMLShadowElement* assigned_insertion_point =
-          parent_shadow_root->ShadowInsertionPointOfYoungerShadowRoot();
-      DCHECK(assigned_insertion_point);
-      return TraverseSiblings(*assigned_insertion_point, direction);
-    }
-  }
   return nullptr;
 }
 
@@ -223,9 +210,6 @@
   if (!parent->IsShadowRoot())
     return parent;
   ShadowRoot* shadow_root = ToShadowRoot(parent);
-  DCHECK(!shadow_root->ShadowInsertionPointOfYoungerShadowRoot());
-  if (!shadow_root->IsYoungest())
-    return nullptr;
   return &shadow_root->host();
 }
 
diff --git a/third_party/WebKit/Source/core/dom/LiveNodeListBase.h b/third_party/WebKit/Source/core/dom/LiveNodeListBase.h
index ffcd400..0531165 100644
--- a/third_party/WebKit/Source/core/dom/LiveNodeListBase.h
+++ b/third_party/WebKit/Source/core/dom/LiveNodeListBase.h
@@ -76,6 +76,8 @@
   static bool ShouldInvalidateTypeOnAttributeChange(NodeListInvalidationType,
                                                     const QualifiedName&);
 
+  virtual void Trace(blink::Visitor* visitor) { visitor->Trace(owner_node_); }
+
  protected:
   Document& GetDocument() const { return owner_node_->GetDocument(); }
 
@@ -98,8 +100,6 @@
       unsigned& current_offset,
       MatchFunc);
 
-  virtual void Trace(blink::Visitor* visitor) { visitor->Trace(owner_node_); }
-
  private:
   Member<ContainerNode> owner_node_;  // Cannot be null.
   const unsigned root_type_ : 1;
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp
index 295b3e3..05c0cb3b 100644
--- a/third_party/WebKit/Source/core/dom/Node.cpp
+++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -701,11 +701,11 @@
 }
 
 #ifndef NDEBUG
-inline static ShadowRoot* OldestShadowRootFor(const Node* node) {
+inline static ShadowRoot* GetShadowRootFor(const Node* node) {
   if (!node->IsElementNode())
     return nullptr;
   if (ElementShadow* shadow = ToElement(node)->Shadow())
-    return &shadow->OldestShadowRoot();
+    return &shadow->GetShadowRoot();
   return nullptr;
 }
 #endif
@@ -785,8 +785,7 @@
       child->RecalcDistribution();
   }
 
-  for (ShadowRoot* root = YoungestShadowRoot(); root;
-       root = root->OlderShadowRoot()) {
+  if (ShadowRoot* root = GetShadowRoot()) {
     if (root->ChildNeedsDistributionRecalc())
       root->RecalcDistribution();
   }
@@ -1620,13 +1619,6 @@
         if (!child1->IsShadowRoot())
           return Node::kDocumentPositionPreceding | connection;
 
-        for (const ShadowRoot* child = ToShadowRoot(child2)->OlderShadowRoot();
-             child; child = child->OlderShadowRoot()) {
-          if (child == child1) {
-            return Node::kDocumentPositionFollowing | connection;
-          }
-        }
-
         return Node::kDocumentPositionPreceding | connection;
       }
 
@@ -1752,12 +1744,7 @@
   for (unsigned index = chain.size(); index > 0; --index) {
     const Node* node = chain[index - 1];
     if (node->IsShadowRoot()) {
-      int count = 0;
-      for (const ShadowRoot* shadow_root =
-               ToShadowRoot(node)->OlderShadowRoot();
-           shadow_root; shadow_root = shadow_root->OlderShadowRoot())
-        ++count;
-      stream << "/#shadow-root[" << count << "]";
+      stream << "/#shadow-root";
       continue;
     }
 
@@ -1836,13 +1823,8 @@
                          marked_node2, marked_label2, builder);
     }
 
-    if (node.IsShadowRoot()) {
-      if (ShadowRoot* younger_shadow_root =
-              ToShadowRoot(node).YoungerShadowRoot())
-        AppendMarkedTree(indent.ToString(), younger_shadow_root, marked_node1,
-                         marked_label1, marked_node2, marked_label2, builder);
-    } else if (ShadowRoot* oldest_shadow_root = OldestShadowRootFor(&node)) {
-      AppendMarkedTree(indent.ToString(), oldest_shadow_root, marked_node1,
+    if (ShadowRoot* shadow_root = GetShadowRootFor(&node)) {
+      AppendMarkedTree(indent.ToString(), shadow_root, marked_node1,
                        marked_label1, marked_node2, marked_label2, builder);
     }
   }
@@ -1922,19 +1904,12 @@
   if (node == marked_node)
     stream << "*";
   stream << indent.Utf8().data() << *node << "\n";
-  if (node->IsShadowRoot()) {
-    if (ShadowRoot* younger_shadow_root =
-            ToShadowRoot(node)->YoungerShadowRoot())
-      PrintSubTreeAcrossFrame(younger_shadow_root, marked_node, indent + "\t",
-                              stream);
-  } else {
-    if (node->IsFrameOwnerElement())
-      PrintSubTreeAcrossFrame(ToHTMLFrameOwnerElement(node)->contentDocument(),
-                              marked_node, indent + "\t", stream);
-    if (ShadowRoot* oldest_shadow_root = OldestShadowRootFor(node))
-      PrintSubTreeAcrossFrame(oldest_shadow_root, marked_node, indent + "\t",
-                              stream);
+  if (node->IsFrameOwnerElement()) {
+    PrintSubTreeAcrossFrame(ToHTMLFrameOwnerElement(node)->contentDocument(),
+                            marked_node, indent + "\t", stream);
   }
+  if (ShadowRoot* shadow_root = GetShadowRootFor(node))
+    PrintSubTreeAcrossFrame(shadow_root, marked_node, indent + "\t", stream);
   for (const Node* child = node->firstChild(); child;
        child = child->nextSibling())
     PrintSubTreeAcrossFrame(child, marked_node, indent + "\t", stream);
@@ -2053,8 +2028,7 @@
   ScriptForbiddenScope forbid_script_during_raw_iteration;
   for (Node& node : NodeTraversal::StartsAt(*this)) {
     node.RemoveAllEventListeners();
-    for (ShadowRoot* root = node.YoungestShadowRoot(); root;
-         root = root->OlderShadowRoot())
+    if (ShadowRoot* root = node.GetShadowRoot())
       root->RemoveAllEventListenersRecursively();
   }
 }
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h
index 78d7d23..53602dd 100644
--- a/third_party/WebKit/Source/core/dom/Node.h
+++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -364,7 +364,7 @@
   // isInShadowTree() returns true.
   // This can happen when handling queued events (e.g. during execCommand())
   ShadowRoot* ContainingShadowRoot() const;
-  ShadowRoot* YoungestShadowRoot() const;
+  ShadowRoot* GetShadowRoot() const;
   bool IsInUserAgentShadowRoot() const;
 
   // Returns nullptr, a child of ShadowRoot, or a legacy shadow root.
diff --git a/third_party/WebKit/Source/core/dom/ShadowRoot.cpp b/third_party/WebKit/Source/core/dom/ShadowRoot.cpp
index ff4c56d..e824df1 100644
--- a/third_party/WebKit/Source/core/dom/ShadowRoot.cpp
+++ b/third_party/WebKit/Source/core/dom/ShadowRoot.cpp
@@ -69,28 +69,6 @@
 
 ShadowRoot::~ShadowRoot() = default;
 
-ShadowRoot* ShadowRoot::YoungerShadowRoot() const {
-  if (GetType() == ShadowRootType::V0 && shadow_root_rare_data_v0_)
-    return shadow_root_rare_data_v0_->YoungerShadowRoot();
-  return nullptr;
-}
-
-ShadowRoot* ShadowRoot::OlderShadowRoot() const {
-  if (GetType() == ShadowRootType::V0 && shadow_root_rare_data_v0_)
-    return shadow_root_rare_data_v0_->OlderShadowRoot();
-  return nullptr;
-}
-
-void ShadowRoot::SetYoungerShadowRoot(ShadowRoot& root) {
-  DCHECK_EQ(GetType(), ShadowRootType::V0);
-  EnsureShadowRootRareDataV0().SetYoungerShadowRoot(root);
-}
-
-void ShadowRoot::SetOlderShadowRoot(ShadowRoot& root) {
-  DCHECK_EQ(GetType(), ShadowRootType::V0);
-  EnsureShadowRootRareDataV0().SetOlderShadowRoot(root);
-}
-
 SlotAssignment& ShadowRoot::EnsureSlotAssignment() {
   if (!slot_assignment_)
     slot_assignment_ = SlotAssignment::Create(*this);
@@ -201,7 +179,7 @@
     ContainerNode* insertion_point) {
   DocumentFragment::InsertedInto(insertion_point);
 
-  if (!insertion_point->isConnected() || !IsOldest())
+  if (!insertion_point->isConnected())
     return kInsertionDone;
 
   // FIXME: When parsing <video controls>, insertedInto() is called many times
@@ -258,11 +236,6 @@
         ToElement(change.sibling_changed), change.sibling_before_change,
         change.sibling_after_change);
   }
-
-  if (V0InsertionPoint* point = ShadowInsertionPointOfYoungerShadowRoot()) {
-    if (ShadowRoot* root = point->ContainingShadowRoot())
-      root->Owner()->SetNeedsDistributionRecalc();
-  }
 }
 
 ShadowRootRareDataV0& ShadowRoot::EnsureShadowRootRareDataV0() {
@@ -291,21 +264,6 @@
              : 0;
 }
 
-HTMLShadowElement* ShadowRoot::ShadowInsertionPointOfYoungerShadowRoot() const {
-  return shadow_root_rare_data_v0_
-             ? shadow_root_rare_data_v0_
-                   ->ShadowInsertionPointOfYoungerShadowRoot()
-             : nullptr;
-}
-
-void ShadowRoot::SetShadowInsertionPointOfYoungerShadowRoot(
-    HTMLShadowElement* shadow_insertion_point) {
-  if (!shadow_root_rare_data_v0_ && !shadow_insertion_point)
-    return;
-  EnsureShadowRootRareDataV0().SetShadowInsertionPointOfYoungerShadowRoot(
-      shadow_insertion_point);
-}
-
 void ShadowRoot::DidAddInsertionPoint(V0InsertionPoint* insertion_point) {
   EnsureShadowRootRareDataV0().DidAddInsertionPoint(insertion_point);
   InvalidateDescendantInsertionPoints();
diff --git a/third_party/WebKit/Source/core/dom/ShadowRoot.h b/third_party/WebKit/Source/core/dom/ShadowRoot.h
index 69d0f29..ec376ab3 100644
--- a/third_party/WebKit/Source/core/dom/ShadowRoot.h
+++ b/third_party/WebKit/Source/core/dom/ShadowRoot.h
@@ -42,7 +42,6 @@
 class Document;
 class ElementShadow;
 class ExceptionState;
-class HTMLShadowElement;
 class ShadowRootRareDataV0;
 class SlotAssignment;
 class StringOrTrustedHTML;
@@ -107,20 +106,12 @@
   void SetNeedsAssignmentRecalc();
 
   // For V0
-  ShadowRoot* YoungerShadowRoot() const;
-  ShadowRoot* OlderShadowRoot() const;
-  void SetYoungerShadowRoot(ShadowRoot&);
-  void SetOlderShadowRoot(ShadowRoot&);
-  bool IsYoungest() const { return !YoungerShadowRoot(); }
-  bool IsOldest() const { return !OlderShadowRoot(); }
   bool ContainsShadowElements() const;
   bool ContainsContentElements() const;
   bool ContainsInsertionPoints() const {
     return ContainsShadowElements() || ContainsContentElements();
   }
   unsigned DescendantShadowElementCount() const;
-  HTMLShadowElement* ShadowInsertionPointOfYoungerShadowRoot() const;
-  void SetShadowInsertionPointOfYoungerShadowRoot(HTMLShadowElement*);
   void DidAddInsertionPoint(V0InsertionPoint*);
   void DidRemoveInsertionPoint(V0InsertionPoint*);
   const HeapVector<Member<V0InsertionPoint>>& DescendantInsertionPoints();
@@ -205,13 +196,6 @@
   return AdjustedFocusedElement();
 }
 
-inline ShadowRoot* Element::ShadowRootIfV1() const {
-  ShadowRoot* root = GetShadowRoot();
-  if (root && root->IsV1())
-    return root;
-  return nullptr;
-}
-
 inline bool Node::IsInUserAgentShadowRoot() const {
   return ContainingShadowRoot() && ContainingShadowRoot()->IsUserAgent();
 }
diff --git a/third_party/WebKit/Source/core/dom/ShadowRootRareDataV0.h b/third_party/WebKit/Source/core/dom/ShadowRootRareDataV0.h
index f4851c42..efe5be4 100644
--- a/third_party/WebKit/Source/core/dom/ShadowRootRareDataV0.h
+++ b/third_party/WebKit/Source/core/dom/ShadowRootRareDataV0.h
@@ -42,14 +42,6 @@
       : descendant_shadow_element_count_(0),
         descendant_content_element_count_(0) {}
 
-  HTMLShadowElement* ShadowInsertionPointOfYoungerShadowRoot() const {
-    return shadow_insertion_point_of_younger_shadow_root_.Get();
-  }
-  void SetShadowInsertionPointOfYoungerShadowRoot(
-      HTMLShadowElement* shadow_insertion_point) {
-    shadow_insertion_point_of_younger_shadow_root_ = shadow_insertion_point;
-  }
-
   void DidAddInsertionPoint(V0InsertionPoint*);
   void DidRemoveInsertionPoint(V0InsertionPoint*);
 
@@ -75,27 +67,11 @@
     descendant_insertion_points_.clear();
   }
 
-  void SetYoungerShadowRoot(ShadowRoot& younger_shadow_root) {
-    younger_shadow_root_ = &younger_shadow_root;
-  }
-  void SetOlderShadowRoot(ShadowRoot& older_shadow_root) {
-    older_shadow_root_ = &older_shadow_root;
-  }
-
-  ShadowRoot* YoungerShadowRoot() const { return younger_shadow_root_; }
-  ShadowRoot* OlderShadowRoot() const { return older_shadow_root_; }
-
   void Trace(blink::Visitor* visitor) {
-    visitor->Trace(younger_shadow_root_);
-    visitor->Trace(older_shadow_root_);
-    visitor->Trace(shadow_insertion_point_of_younger_shadow_root_);
     visitor->Trace(descendant_insertion_points_);
   }
 
  private:
-  Member<ShadowRoot> younger_shadow_root_;
-  Member<ShadowRoot> older_shadow_root_;
-  Member<HTMLShadowElement> shadow_insertion_point_of_younger_shadow_root_;
   unsigned descendant_shadow_element_count_;
   unsigned descendant_content_element_count_;
   HeapVector<Member<V0InsertionPoint>> descendant_insertion_points_;
diff --git a/third_party/WebKit/Source/core/dom/TreeScope.cpp b/third_party/WebKit/Source/core/dom/TreeScope.cpp
index 6ad6b022..ca4e33fd 100644
--- a/third_party/WebKit/Source/core/dom/TreeScope.cpp
+++ b/third_party/WebKit/Source/core/dom/TreeScope.cpp
@@ -80,19 +80,10 @@
   selection_ = nullptr;
 }
 
-TreeScope* TreeScope::OlderShadowRootOrParentTreeScope() const {
-  if (RootNode().IsShadowRoot()) {
-    if (ShadowRoot* older_shadow_root =
-            ToShadowRoot(RootNode()).OlderShadowRoot())
-      return older_shadow_root;
-  }
-  return ParentTreeScope();
-}
-
 bool TreeScope::IsInclusiveOlderSiblingShadowRootOrAncestorTreeScopeOf(
     const TreeScope& scope) const {
   for (const TreeScope* current = &scope; current;
-       current = current->OlderShadowRootOrParentTreeScope()) {
+       current = current->ParentTreeScope()) {
     if (current == this)
       return true;
   }
@@ -449,14 +440,6 @@
       if (shadow_host1 != shadow_host2)
         return shadow_host1->compareDocumentPosition(
             shadow_host2, Node::kTreatShadowTreesAsDisconnected);
-
-      for (const ShadowRoot* child =
-               ToShadowRoot(child2->RootNode()).OlderShadowRoot();
-           child; child = child->OlderShadowRoot()) {
-        if (child == child1)
-          return Node::kDocumentPositionFollowing;
-      }
-
       return Node::kDocumentPositionPreceding;
     }
   }
@@ -515,8 +498,7 @@
     if (DeprecatedEqualIgnoringCase(element.FastGetAttribute(accesskeyAttr),
                                     key))
       result = &element;
-    for (ShadowRoot* shadow_root = element.YoungestShadowRoot(); shadow_root;
-         shadow_root = shadow_root->OlderShadowRoot()) {
+    if (ShadowRoot* shadow_root = element.GetShadowRoot()) {
       if (Element* shadow_result = shadow_root->GetElementByAccessKey(key))
         result = shadow_result;
     }
@@ -527,8 +509,7 @@
 void TreeScope::SetNeedsStyleRecalcForViewportUnits() {
   for (Element* element = ElementTraversal::FirstWithin(RootNode()); element;
        element = ElementTraversal::NextIncludingPseudo(*element)) {
-    for (ShadowRoot* root = element->YoungestShadowRoot(); root;
-         root = root->OlderShadowRoot())
+    if (ShadowRoot* root = element->GetShadowRoot())
       root->SetNeedsStyleRecalcForViewportUnits();
     const ComputedStyle* style = element->GetComputedStyle();
     if (style && style->HasViewportUnits())
diff --git a/third_party/WebKit/Source/core/dom/TreeScope.h b/third_party/WebKit/Source/core/dom/TreeScope.h
index 56ff525..d3b1687c 100644
--- a/third_party/WebKit/Source/core/dom/TreeScope.h
+++ b/third_party/WebKit/Source/core/dom/TreeScope.h
@@ -54,7 +54,6 @@
  public:
   TreeScope* ParentTreeScope() const { return parent_tree_scope_; }
 
-  TreeScope* OlderShadowRootOrParentTreeScope() const;
   bool IsInclusiveOlderSiblingShadowRootOrAncestorTreeScopeOf(
       const TreeScope&) const;
 
diff --git a/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp b/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp
index 1365eda..8363437a 100644
--- a/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp
+++ b/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp
@@ -79,8 +79,7 @@
         MoveTreeToNewScope(*attr);
     }
 
-    for (ShadowRoot* shadow = element.YoungestShadowRoot(); shadow;
-         shadow = shadow->OlderShadowRoot()) {
+    if (ShadowRoot* shadow = element.GetShadowRoot()) {
       shadow->SetParentTreeScope(NewScope());
       if (will_move_to_new_document) {
         if (shadow->GetType() == ShadowRootType::V0) {
@@ -113,8 +112,7 @@
         MoveTreeToNewDocument(*attr, old_document, new_document);
     }
 
-    for (ShadowRoot* shadow = element.YoungestShadowRoot(); shadow;
-         shadow = shadow->OlderShadowRoot())
+    if (ShadowRoot* shadow = element.GetShadowRoot())
       MoveTreeToNewDocument(*shadow, old_document, new_document);
   }
 }
diff --git a/third_party/WebKit/Source/core/dom/V0InsertionPoint.cpp b/third_party/WebKit/Source/core/dom/V0InsertionPoint.cpp
index 0bd59d28..8bd06fe 100644
--- a/third_party/WebKit/Source/core/dom/V0InsertionPoint.cpp
+++ b/third_party/WebKit/Source/core/dom/V0InsertionPoint.cpp
@@ -183,10 +183,6 @@
   return true;
 }
 
-bool V0InsertionPoint::IsShadowInsertionPoint() const {
-  return IsHTMLShadowElement(*this) && IsActive();
-}
-
 bool V0InsertionPoint::IsContentInsertionPoint() const {
   return IsHTMLContentElement(*this) && IsActive();
 }
diff --git a/third_party/WebKit/Source/core/dom/V0InsertionPoint.h b/third_party/WebKit/Source/core/dom/V0InsertionPoint.h
index 6390dea5..ac2468d 100644
--- a/third_party/WebKit/Source/core/dom/V0InsertionPoint.h
+++ b/third_party/WebKit/Source/core/dom/V0InsertionPoint.h
@@ -49,7 +49,6 @@
   bool IsActive() const;
   bool CanBeActive() const;
 
-  bool IsShadowInsertionPoint() const;
   bool IsContentInsertionPoint() const;
 
   StaticNodeList* getDistributedNodes();
@@ -103,17 +102,10 @@
   return node.IsV0InsertionPoint() && ToV0InsertionPoint(node).IsActive();
 }
 
-inline bool IsActiveShadowInsertionPoint(const Node& node) {
-  return node.IsV0InsertionPoint() &&
-         ToV0InsertionPoint(node).IsShadowInsertionPoint();
-}
-
 inline ElementShadow* ShadowWhereNodeCanBeDistributedForV0(const Node& node) {
   Node* parent = node.parentNode();
   if (!parent)
     return nullptr;
-  if (parent->IsShadowRoot() && !ToShadowRoot(parent)->IsYoungest())
-    return node.OwnerShadowHost()->Shadow();
   if (IsActiveV0InsertionPoint(*parent))
     return node.OwnerShadowHost()->Shadow();
   if (parent->IsElementNode())
diff --git a/third_party/WebKit/Source/core/dom/VisitedLinkState.cpp b/third_party/WebKit/Source/core/dom/VisitedLinkState.cpp
index 5cff2b8e..a9e0425 100644
--- a/third_party/WebKit/Source/core/dom/VisitedLinkState.cpp
+++ b/third_party/WebKit/Source/core/dom/VisitedLinkState.cpp
@@ -75,8 +75,7 @@
       ToElement(node).PseudoStateChanged(CSSSelector::kPseudoAnyLink);
     }
     if (IsShadowHost(&node)) {
-      for (ShadowRoot* root = node.YoungestShadowRoot(); root;
-           root = root->OlderShadowRoot())
+      if (ShadowRoot* root = node.GetShadowRoot())
         InvalidateStyleForAllLinksRecursively(*root,
                                               invalidate_visited_link_hashes);
     }
@@ -100,8 +99,7 @@
       ToElement(node).PseudoStateChanged(CSSSelector::kPseudoAnyLink);
     }
     if (IsShadowHost(&node))
-      for (ShadowRoot* root = node.YoungestShadowRoot(); root;
-           root = root->OlderShadowRoot())
+      if (ShadowRoot* root = node.GetShadowRoot())
         InvalidateStyleForLinkRecursively(*root, link_hash);
   }
 }
diff --git a/third_party/WebKit/Source/core/dom/events/EventPath.cpp b/third_party/WebKit/Source/core/dom/events/EventPath.cpp
index 6d416f7..5bf64294 100644
--- a/third_party/WebKit/Source/core/dom/events/EventPath.cpp
+++ b/third_party/WebKit/Source/core/dom/events/EventPath.cpp
@@ -106,16 +106,8 @@
     HeapVector<Member<V0InsertionPoint>, 8> insertion_points;
     CollectDestinationInsertionPoints(*current, insertion_points);
     if (!insertion_points.IsEmpty()) {
-      for (const auto& insertion_point : insertion_points) {
-        if (insertion_point->IsShadowInsertionPoint()) {
-          ShadowRoot* containing_shadow_root =
-              insertion_point->ContainingShadowRoot();
-          DCHECK(containing_shadow_root);
-          if (!containing_shadow_root->IsOldest())
-            nodes_in_path.push_back(containing_shadow_root->OlderShadowRoot());
-        }
+      for (const auto& insertion_point : insertion_points)
         nodes_in_path.push_back(insertion_point);
-      }
       current = insertion_points.back();
       continue;
     }
@@ -153,12 +145,8 @@
   //   - The root tree must be included.
   TreeScopeEventContext* root_tree = nullptr;
   for (const auto& tree_scope_event_context : tree_scope_event_contexts_) {
-    // Use olderShadowRootOrParentTreeScope here for parent-child relationships.
-    // See the definition of trees of trees in the Shadow DOM spec:
-    // http://w3c.github.io/webcomponents/spec/shadow/
-    TreeScope* parent = tree_scope_event_context.Get()
-                            ->GetTreeScope()
-                            .OlderShadowRootOrParentTreeScope();
+    TreeScope* parent =
+        tree_scope_event_context.Get()->GetTreeScope().ParentTreeScope();
     if (!parent) {
       DCHECK(!root_tree);
       root_tree = tree_scope_event_context.Get();
@@ -197,8 +185,7 @@
     tree_scope_event_contexts_.push_back(tree_scope_event_context);
 
     TreeScopeEventContext* parent_tree_scope_event_context =
-        EnsureTreeScopeEventContext(
-            nullptr, tree_scope->OlderShadowRootOrParentTreeScope());
+        EnsureTreeScopeEventContext(nullptr, tree_scope->ParentTreeScope());
     if (parent_tree_scope_event_context &&
         parent_tree_scope_event_context->Target()) {
       tree_scope_event_context->SetTarget(
@@ -250,7 +237,7 @@
   HeapVector<Member<TreeScope>, 32> parent_tree_scopes;
   EventTarget* related_node = nullptr;
   for (TreeScope* current = &scope; current;
-       current = current->OlderShadowRootOrParentTreeScope()) {
+       current = current->ParentTreeScope()) {
     parent_tree_scopes.push_back(current);
     RelatedTargetMap::const_iterator iter = related_target_map.find(current);
     if (iter != related_target_map.end() && iter->value) {
diff --git a/third_party/WebKit/Source/core/dom/ng/flat_tree_traversal_ng.cc b/third_party/WebKit/Source/core/dom/ng/flat_tree_traversal_ng.cc
index c9397c6..f95868b 100644
--- a/third_party/WebKit/Source/core/dom/ng/flat_tree_traversal_ng.cc
+++ b/third_party/WebKit/Source/core/dom/ng/flat_tree_traversal_ng.cc
@@ -57,7 +57,7 @@
   Node* child;
   ElementShadow* shadow = ShadowFor(node);
   if (shadow) {
-    ShadowRoot& shadow_root = shadow->YoungestShadowRoot();
+    ShadowRoot& shadow_root = shadow->GetShadowRoot();
     child = direction == kTraversalDirectionForward ? shadow_root.firstChild()
                                                     : shadow_root.lastChild();
   } else {
@@ -143,17 +143,6 @@
   //   if (slot->SupportsAssignment() && slot->AssignedNodes().IsEmpty())
   //     return TraverseSiblings(*slot, direction);
   // }
-
-  // For v0 older shadow tree
-  if (node.parentNode() && node.parentNode()->IsShadowRoot()) {
-    ShadowRoot* parent_shadow_root = ToShadowRoot(node.parentNode());
-    if (!parent_shadow_root->IsYoungest()) {
-      HTMLShadowElement* assigned_insertion_point =
-          parent_shadow_root->ShadowInsertionPointOfYoungerShadowRoot();
-      DCHECK(assigned_insertion_point);
-      return TraverseSiblings(*assigned_insertion_point, direction);
-    }
-  }
   return nullptr;
 }
 
@@ -233,9 +222,6 @@
   if (!parent->IsShadowRoot())
     return parent;
   ShadowRoot* shadow_root = ToShadowRoot(parent);
-  DCHECK(!shadow_root->ShadowInsertionPointOfYoungerShadowRoot());
-  if (!shadow_root->IsYoungest())
-    return nullptr;
   return &shadow_root->host();
 }
 
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
index edb5c59..26a15b1e 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
@@ -1329,7 +1329,8 @@
   // TODO(editing-dev): Hoist the call of UpdateStyleAndLayoutTree to callers.
   // See crbug.com/590369 for details.
   node->GetDocument().UpdateStyleAndLayoutTree();
-  return node->GetComputedStyle()->WhiteSpace() == EWhiteSpace::kPre;
+  const ComputedStyle* style = node->GetComputedStyle();
+  return style && style->WhiteSpace() == EWhiteSpace::kPre;
 }
 
 bool IsTabHTMLSpanElementTextNode(const Node* node) {
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.h b/third_party/WebKit/Source/core/editing/EditingUtilities.h
index 4ddf35b..fd33926 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.h
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.h
@@ -157,7 +157,7 @@
 
 bool IsAtomicNode(const Node*);
 CORE_EXPORT bool IsEnclosingBlock(const Node*);
-bool IsTabHTMLSpanElement(const Node*);
+CORE_EXPORT bool IsTabHTMLSpanElement(const Node*);
 bool IsTabHTMLSpanElementTextNode(const Node*);
 bool IsMailHTMLBlockquoteElement(const Node*);
 // Returns true if the specified node is visible <table>. We don't want to add
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp b/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp
index 1513de4..0b0e855 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp
@@ -771,6 +771,12 @@
                                PositionMoveType::kBackwardDeletion));
 }
 
+TEST_F(EditingUtilitiesTest, IsTabHTMLSpanElementOnDisplayNone) {
+  SetBodyContent("<span style=\"display:none\">\t</span>");
+  const Node* const node = GetDocument().QuerySelector("span");
+  EXPECT_EQ(false, IsTabHTMLSpanElement(node));
+}
+
 TEST_F(EditingUtilitiesTest, previousPositionOf_Backspace_SurrogatePairs) {
   // Supplementary plane characters. Only one code point should be deleted.
   // &#x1F441; is EYE.
diff --git a/third_party/WebKit/Source/core/editing/LocalCaretRectTest.cpp b/third_party/WebKit/Source/core/editing/LocalCaretRectTest.cpp
index 9fc9960..54e590a 100644
--- a/third_party/WebKit/Source/core/editing/LocalCaretRectTest.cpp
+++ b/third_party/WebKit/Source/core/editing/LocalCaretRectTest.cpp
@@ -200,7 +200,6 @@
 TEST_F(LocalCaretRectTest, Images) {
   // This test only records the current behavior. Future changes are allowed.
 
-  GetDocument().SetCompatibilityMode(Document::kQuirksMode);
   LoadAhem();
   SetBodyContent(
       "<div id=div style='font: 10px/10px Ahem; width: 30px'>"
@@ -210,10 +209,10 @@
 
   const Element& img1 = *GetElementById("img1");
 
-  EXPECT_EQ(LocalCaretRect(img1.GetLayoutObject(), LayoutRect(0, 0, 1, 10)),
+  EXPECT_EQ(LocalCaretRect(img1.GetLayoutObject(), LayoutRect(0, 0, 1, 12)),
             LocalCaretRectOfPosition(
                 {Position::BeforeNode(img1), TextAffinity::kDownstream}));
-  EXPECT_EQ(LocalCaretRect(img1.GetLayoutObject(), LayoutRect(9, 0, 1, 10)),
+  EXPECT_EQ(LocalCaretRect(img1.GetLayoutObject(), LayoutRect(9, 0, 1, 12)),
             LocalCaretRectOfPosition(
                 {Position::AfterNode(img1), TextAffinity::kDownstream}));
 
@@ -221,10 +220,10 @@
 
   // Box-anchored LocalCaretRect is local to the box itself, instead of its
   // containing block.
-  EXPECT_EQ(LocalCaretRect(img2.GetLayoutObject(), LayoutRect(0, 0, 1, 10)),
+  EXPECT_EQ(LocalCaretRect(img2.GetLayoutObject(), LayoutRect(0, 0, 1, 12)),
             LocalCaretRectOfPosition(
                 {Position::BeforeNode(img2), TextAffinity::kDownstream}));
-  EXPECT_EQ(LocalCaretRect(img2.GetLayoutObject(), LayoutRect(9, 0, 1, 10)),
+  EXPECT_EQ(LocalCaretRect(img2.GetLayoutObject(), LayoutRect(9, 0, 1, 12)),
             LocalCaretRectOfPosition(
                 {Position::AfterNode(img2), TextAffinity::kDownstream}));
 }
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp
index ac2233b..a2faa67 100644
--- a/third_party/WebKit/Source/core/editing/SelectionController.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp
@@ -528,10 +528,13 @@
                                          Selection().Granularity())
           : SelectionInFlatTree::Builder().Collapse(adjusted_position).Build();
 
+  const bool selection_is_directional =
+      should_extend_selection ? Selection().IsDirectional() : false;
   SetNonDirectionalSelectionIfNeeded(
       adjusted_selection,
       SetSelectionOptions::Builder()
           .SetGranularity(Selection().Granularity())
+          .SetIsDirectional(selection_is_directional)
           .Build(),
       kAdjustEndpointsAtBidiBoundary);
 }
@@ -836,6 +839,8 @@
 
 // TODO(yosin): We should take |granularity| and |handleVisibility| from
 // |newSelection|.
+// We should rename this function to appropriate name because
+// set_selection_options has selection directional value in few cases.
 void SelectionController::SetNonDirectionalSelectionIfNeeded(
     const SelectionInFlatTree& passed_selection,
     const SetSelectionOptions& set_selection_options,
@@ -884,19 +889,28 @@
     original_base_in_flat_tree_ = PositionInFlatTreeWithAffinity();
   }
 
-  builder.SetIsDirectional(
+  const bool selection_is_directional =
       frame_->GetEditor().Behavior().ShouldConsiderSelectionAsDirectional() ||
-      new_selection.IsDirectional());
+      set_selection_options.IsDirectional();
+  builder.SetIsDirectional(selection_is_directional);
   const SelectionInFlatTree& selection_in_flat_tree = builder.Build();
-  if (Selection().ComputeVisibleSelectionInFlatTree() ==
+
+  const bool selection_remains_the_same =
+      Selection().ComputeVisibleSelectionInFlatTree() ==
           CreateVisibleSelection(selection_in_flat_tree) &&
-      Selection().IsHandleVisible() == set_selection_options.ShouldShowHandle())
+      Selection().IsHandleVisible() ==
+          set_selection_options.ShouldShowHandle() &&
+      selection_is_directional == Selection().IsDirectional();
+
+  // If selection has not changed we do not clear editing style.
+  if (selection_remains_the_same)
     return;
   Selection().SetSelection(
       ConvertToSelectionInDOMTree(selection_in_flat_tree),
       SetSelectionOptions::Builder(set_selection_options)
           .SetShouldCloseTyping(true)
           .SetShouldClearTypingStyle(true)
+          .SetIsDirectional(selection_is_directional)
           .SetCursorAlignOnScroll(CursorAlignOnScroll::kIfNeeded)
           .Build());
 }
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
index e82446cd..5232bad9 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
@@ -414,23 +414,12 @@
           const ShadowRoot* shadow_root = ToShadowRoot(node_);
           if (shadow_root->GetType() == ShadowRootType::V0 ||
               shadow_root->GetType() == ShadowRootType::kOpen) {
-            ShadowRoot* next_shadow_root = shadow_root->OlderShadowRoot();
-            if (next_shadow_root &&
-                next_shadow_root->GetType() == ShadowRootType::V0) {
-              fully_clipped_stack_.Pop();
-              node_ = next_shadow_root;
-              iteration_progress_ = kHandledNone;
-              // m_shadowDepth is unchanged since we exit from a shadow root and
-              // enter another.
-              fully_clipped_stack_.PushFullyClippedState(node_);
-            } else {
-              // We are the last shadow root; exit from here and go back to
-              // where we were.
-              node_ = &shadow_root->host();
-              iteration_progress_ = kHandledOpenShadowRoots;
-              --shadow_depth_;
-              fully_clipped_stack_.Pop();
-            }
+            // We are the shadow root; exit from here and go back to
+            // where we were.
+            node_ = &shadow_root->host();
+            iteration_progress_ = kHandledOpenShadowRoots;
+            --shadow_depth_;
+            fully_clipped_stack_.Pop();
           } else {
             // If we are in a closed or user-agent shadow root, then go back to
             // the host.
diff --git a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp
index 128ab2b..48b0aaf2 100644
--- a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp
+++ b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp
@@ -79,7 +79,7 @@
   ElementShadow* shadow = ToElement(node).Shadow();
   if (!shadow)
     return false;
-  return shadow->YoungestShadowRoot().IsUserAgent();
+  return shadow->GetShadowRoot().IsUserAgent();
 }
 
 }  // namespace
diff --git a/third_party/WebKit/Source/core/editing/testing/SelectionSample.cpp b/third_party/WebKit/Source/core/editing/testing/SelectionSample.cpp
index c25f42c..a12389a 100644
--- a/third_party/WebKit/Source/core/editing/testing/SelectionSample.cpp
+++ b/third_party/WebKit/Source/core/editing/testing/SelectionSample.cpp
@@ -11,6 +11,7 @@
 #include "core/dom/CharacterData.h"
 #include "core/dom/Document.h"
 #include "core/dom/Element.h"
+#include "core/dom/ElementShadow.h"
 #include "core/dom/ProcessingInstruction.h"
 #include "core/dom/ShadowRootInit.h"
 #include "core/editing/EditingUtilities.h"
diff --git a/third_party/WebKit/Source/core/editing/testing/SelectionSampleTest.cpp b/third_party/WebKit/Source/core/editing/testing/SelectionSampleTest.cpp
index b0f4a22..9718834 100644
--- a/third_party/WebKit/Source/core/editing/testing/SelectionSampleTest.cpp
+++ b/third_party/WebKit/Source/core/editing/testing/SelectionSampleTest.cpp
@@ -4,6 +4,7 @@
 
 #include "core/editing/testing/SelectionSample.h"
 
+#include "core/dom/ElementShadow.h"
 #include "core/dom/ProcessingInstruction.h"
 #include "core/editing/SelectionTemplate.h"
 #include "core/editing/testing/EditingTestBase.h"
diff --git a/third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp b/third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp
index 148e84f..320d773 100644
--- a/third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp
+++ b/third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp
@@ -353,7 +353,7 @@
   const ElementShadow* shadow = element.Shadow();
   if (!shadow)
     return std::pair<Node*, Element*>();
-  ShadowRoot& shadow_root = shadow->OldestShadowRoot();
+  ShadowRoot& shadow_root = shadow->GetShadowRoot();
 
   String shadow_mode;
   switch (shadow_root.GetType()) {
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
index 82ca2cc8..dbf424ec 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -1741,12 +1741,10 @@
     if (layer->IsPaintInvalidationContainer())
       continue;
 
-    if (layer->SubtreeIsInvisible())
-      continue;
-
-    // invalidate even if there is an ancestor with a filter that moves pixels.
-    layout_object
-        ->SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants();
+    // If the layer has no visible content, then we shouldn't invalidate; but
+    // if we're not compositing-inputs-clean, then we can't query
+    // layer->SubtreeIsInvisible() here.
+    layout_object->SetMayNeedPaintInvalidationSubtree();
 
     TRACE_EVENT_INSTANT1(
         TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"),
diff --git a/third_party/WebKit/Source/core/frame/MHTMLTest.cpp b/third_party/WebKit/Source/core/frame/MHTMLTest.cpp
index 37f992a4..f8aab16 100644
--- a/third_party/WebKit/Source/core/frame/MHTMLTest.cpp
+++ b/third_party/WebKit/Source/core/frame/MHTMLTest.cpp
@@ -475,23 +475,20 @@
   EXPECT_TRUE(IsShadowHost(document->getElementById("h1")));
   EXPECT_TRUE(IsShadowHost(document->getElementById("h2")));
   // The nested shadow DOM tree is created.
-  EXPECT_TRUE(IsShadowHost(document->getElementById("h2")
-                               ->Shadow()
-                               ->OldestShadowRoot()
-                               .getElementById("h3")));
+  EXPECT_TRUE(IsShadowHost(
+      document->getElementById("h2")->Shadow()->GetShadowRoot().getElementById(
+          "h3")));
 
   EXPECT_TRUE(IsShadowHost(document->getElementById("h4")));
   // The static element in the shadow dom template is found.
-  EXPECT_TRUE(document->getElementById("h4")
-                  ->Shadow()
-                  ->OldestShadowRoot()
-                  .getElementById("s1"));
+  EXPECT_TRUE(
+      document->getElementById("h4")->Shadow()->GetShadowRoot().getElementById(
+          "s1"));
   // The element to be created by the script in the shadow dom template is
   // not found because the script is blocked.
-  EXPECT_FALSE(document->getElementById("h4")
-                   ->Shadow()
-                   ->OldestShadowRoot()
-                   .getElementById("s2"));
+  EXPECT_FALSE(
+      document->getElementById("h4")->Shadow()->GetShadowRoot().getElementById(
+          "s2"));
 }
 
 TEST_F(MHTMLTest, FormControlElements) {
diff --git a/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp b/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp
index 2553f7f..dcf6824 100644
--- a/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp
@@ -194,7 +194,7 @@
   return IsFocusable();
 }
 
-bool HTMLAreaElement::LayoutObjectIsFocusable() const {
+bool HTMLAreaElement::IsFocusableStyle() const {
   HTMLImageElement* image = ImageElement();
   if (!image || !image->GetLayoutObject() ||
       image->GetLayoutObject()->Style()->Visibility() != EVisibility::kVisible)
diff --git a/third_party/WebKit/Source/core/html/HTMLAreaElement.h b/third_party/WebKit/Source/core/html/HTMLAreaElement.h
index 9057bb5..ec3452e 100644
--- a/third_party/WebKit/Source/core/html/HTMLAreaElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLAreaElement.h
@@ -64,7 +64,7 @@
   void ParseAttribute(const AttributeModificationParams&) override;
   bool IsKeyboardFocusable() const override;
   bool IsMouseFocusable() const override;
-  bool LayoutObjectIsFocusable() const override;
+  bool IsFocusableStyle() const override;
   void UpdateFocusAppearanceWithOptions(SelectionBehaviorOnFocus,
                                         const FocusOptions&) override;
   void SetFocused(bool, WebFocusType) override;
diff --git a/third_party/WebKit/Source/core/html/HTMLDetailsElement.h b/third_party/WebKit/Source/core/html/HTMLDetailsElement.h
index 30e4e64..dc99284 100644
--- a/third_party/WebKit/Source/core/html/HTMLDetailsElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLDetailsElement.h
@@ -45,6 +45,7 @@
   void DispatchPendingEvent();
 
   LayoutObject* CreateLayoutObject(const ComputedStyle&) override;
+  bool ShouldForceLegacyLayout() const final { return true; }
   void ParseAttribute(const AttributeModificationParams&) override;
   void DidAddUserAgentShadowRoot(ShadowRoot&) override;
   bool IsInteractiveContent() const override;
diff --git a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
index 6387e271..d44e1ca6 100644
--- a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
@@ -480,12 +480,12 @@
   SetPersistedPlugin(nullptr);
 }
 
-bool HTMLPlugInElement::LayoutObjectIsFocusable() const {
+bool HTMLPlugInElement::IsFocusableStyle() const {
   if (HTMLFrameOwnerElement::SupportsFocus() &&
-      HTMLFrameOwnerElement::LayoutObjectIsFocusable())
+      HTMLFrameOwnerElement::IsFocusableStyle())
     return true;
 
-  if (UseFallbackContent() || !HTMLFrameOwnerElement::LayoutObjectIsFocusable())
+  if (UseFallbackContent() || !HTMLFrameOwnerElement::IsFocusableStyle())
     return false;
   return plugin_is_available_;
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLPlugInElement.h b/third_party/WebKit/Source/core/html/HTMLPlugInElement.h
index f47ed5e..97213ca 100644
--- a/third_party/WebKit/Source/core/html/HTMLPlugInElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLPlugInElement.h
@@ -142,7 +142,7 @@
   // Element overrides:
   LayoutObject* CreateLayoutObject(const ComputedStyle&) override;
   bool SupportsFocus() const final { return true; }
-  bool LayoutObjectIsFocusable() const final;
+  bool IsFocusableStyle() const final;
   bool IsKeyboardFocusable() const final;
   void DidAddUserAgentShadowRoot(ShadowRoot&) final;
 
diff --git a/third_party/WebKit/Source/core/html/HTMLShadowElement.cpp b/third_party/WebKit/Source/core/html/HTMLShadowElement.cpp
index 56e14d53..cb95802d 100644
--- a/third_party/WebKit/Source/core/html/HTMLShadowElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLShadowElement.cpp
@@ -49,37 +49,4 @@
 
 HTMLShadowElement::~HTMLShadowElement() = default;
 
-ShadowRoot* HTMLShadowElement::OlderShadowRoot() {
-  ShadowRoot* containing_root = ContainingShadowRoot();
-  if (!containing_root)
-    return nullptr;
-
-  UpdateDistribution();
-
-  ShadowRoot* older = containing_root->OlderShadowRoot();
-  if (!older || !older->IsOpenOrV0() ||
-      older->ShadowInsertionPointOfYoungerShadowRoot() != this)
-    return nullptr;
-
-  DCHECK(older->IsOpenOrV0());
-  return older;
-}
-
-Node::InsertionNotificationRequest HTMLShadowElement::InsertedInto(
-    ContainerNode* insertion_point) {
-  if (insertion_point->isConnected()) {
-    // Warn if trying to reproject between user agent and author shadows.
-    ShadowRoot* root = ContainingShadowRoot();
-    if (root && root->OlderShadowRoot() &&
-        root->GetType() != root->OlderShadowRoot()->GetType()) {
-      String message =
-          String::Format("<shadow> doesn't work for %s element host.",
-                         root->host().tagName().Utf8().data());
-      GetDocument().AddConsoleMessage(ConsoleMessage::Create(
-          kRenderingMessageSource, kWarningMessageLevel, message));
-    }
-  }
-  return V0InsertionPoint::InsertedInto(insertion_point);
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLShadowElement.h b/third_party/WebKit/Source/core/html/HTMLShadowElement.h
index 3b831f36..38fd654 100644
--- a/third_party/WebKit/Source/core/html/HTMLShadowElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLShadowElement.h
@@ -43,12 +43,8 @@
   DECLARE_NODE_FACTORY(HTMLShadowElement);
   ~HTMLShadowElement() override;
 
-  ShadowRoot* OlderShadowRoot();
-
  private:
   explicit HTMLShadowElement(Document&);
-  InsertionNotificationRequest InsertedInto(
-      ContainerNode* insertion_point) override;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLSummaryElement.h b/third_party/WebKit/Source/core/html/HTMLSummaryElement.h
index e778009..1f142da 100644
--- a/third_party/WebKit/Source/core/html/HTMLSummaryElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLSummaryElement.h
@@ -39,6 +39,7 @@
   explicit HTMLSummaryElement(Document&);
 
   LayoutObject* CreateLayoutObject(const ComputedStyle&) override;
+  bool ShouldForceLegacyLayout() const final { return true; }
   void DefaultEventHandler(Event*) override;
   bool HasActivationBehavior() const override;
   void DidAddUserAgentShadowRoot(ShadowRoot&) override;
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLSelectElement.idl b/third_party/WebKit/Source/core/html/forms/HTMLSelectElement.idl
index ef30ae1..1fbc188b 100644
--- a/third_party/WebKit/Source/core/html/forms/HTMLSelectElement.idl
+++ b/third_party/WebKit/Source/core/html/forms/HTMLSelectElement.idl
@@ -22,7 +22,7 @@
 // https://html.spec.whatwg.org/#the-select-element
 
 interface HTMLSelectElement : HTMLElement {
-    // TODO(foolip): attribute DOMString autocomplete;
+    [CEReactions, Reflect] attribute DOMString autocomplete;
     [CEReactions, Reflect] attribute boolean autofocus;
     [CEReactions, Reflect] attribute boolean disabled;
     [ImplementedAs=formOwner] readonly attribute HTMLFormElement? form;
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.idl b/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.idl
index 9598eba..e5a49d5a 100644
--- a/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.idl
+++ b/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.idl
@@ -22,7 +22,7 @@
 // https://html.spec.whatwg.org/#the-textarea-element
 
 interface HTMLTextAreaElement : HTMLElement {
-    // attribute DOMString autocomplete;
+    [CEReactions, Reflect] attribute DOMString autocomplete;
     [CEReactions, Reflect] attribute boolean autofocus;
     [CEReactions] attribute unsigned long cols;
     [CEReactions, Reflect] attribute DOMString dirName;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
index 0822f86..03af63f5 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
@@ -309,8 +309,7 @@
       Unbind(content_document, nodes_map);
   }
 
-  for (ShadowRoot* root = node->YoungestShadowRoot(); root;
-       root = root->OlderShadowRoot())
+  if (ShadowRoot* root = node->GetShadowRoot())
     Unbind(root, nodes_map);
 
   if (node->IsElementNode()) {
@@ -928,7 +927,7 @@
     const Element& element = ToElement(current);
     ElementShadow* element_shadow = element.Shadow();
     if (element_shadow) {
-      ShadowRoot& shadow_root = element_shadow->YoungestShadowRoot();
+      ShadowRoot& shadow_root = element_shadow->GetShadowRoot();
       if (!shadow_root.IsUserAgent() || include_user_agent_shadow_dom)
         return &shadow_root;
     }
@@ -943,8 +942,6 @@
       return nullptr;
     if (node->IsShadowRoot()) {
       const ShadowRoot* shadow_root = ToShadowRoot(node);
-      if (shadow_root->OlderShadowRoot())
-        return shadow_root->OlderShadowRoot();
       Element& host = shadow_root->host();
       if (host.HasChildren())
         return host.firstChild();
@@ -1466,11 +1463,9 @@
     if (shadow) {
       std::unique_ptr<protocol::Array<protocol::DOM::Node>> shadow_roots =
           protocol::Array<protocol::DOM::Node>::create();
-      for (ShadowRoot* root = &shadow->YoungestShadowRoot(); root;
-           root = root->OlderShadowRoot()) {
-        shadow_roots->addItem(BuildObjectForNode(
-            root, pierce ? depth : 0, pierce, nodes_map, flatten_result));
-      }
+      ShadowRoot& root = shadow->GetShadowRoot();
+      shadow_roots->addItem(BuildObjectForNode(
+          &root, pierce ? depth : 0, pierce, nodes_map, flatten_result));
       value->setShadowRoots(std::move(shadow_roots));
       force_push_children = true;
     }
@@ -1756,10 +1751,7 @@
 
     ElementShadow* shadow = element->Shadow();
     if (pierce && shadow) {
-      for (ShadowRoot* root = &shadow->YoungestShadowRoot(); root;
-           root = root->OlderShadowRoot()) {
-        CollectNodes(root, depth, pierce, filter, result);
-      }
+      CollectNodes(&shadow->GetShadowRoot(), depth, pierce, filter, result);
     }
 
     if (auto* link_element = ToHTMLLinkElementOrNull(*element)) {
@@ -1988,8 +1980,7 @@
   if (!shadow_host_id)
     return;
 
-  for (ShadowRoot* root = shadow_host->YoungestShadowRoot(); root;
-       root = root->OlderShadowRoot()) {
+  if (ShadowRoot* root = shadow_host->GetShadowRoot()) {
     const HeapVector<Member<V0InsertionPoint>>& insertion_points =
         root->DescendantInsertionPoints();
     for (const auto& it : insertion_points) {
diff --git a/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp b/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp
index a73f974..946db30 100644
--- a/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp
+++ b/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp
@@ -463,7 +463,7 @@
 }
 
 bool ScrollAnchor::RestoreAnchor(const SerializedAnchor& serialized_anchor) {
-  if (!scroller_ || anchor_object_) {
+  if (!scroller_ || anchor_object_ || !serialized_anchor.IsValid()) {
     return false;
   }
 
diff --git a/third_party/WebKit/Source/core/page/FocusController.cpp b/third_party/WebKit/Source/core/page/FocusController.cpp
index 0aa9390..221e60a 100644
--- a/third_party/WebKit/Source/core/page/FocusController.cpp
+++ b/third_party/WebKit/Source/core/page/FocusController.cpp
@@ -45,7 +45,6 @@
 #include "core/frame/RemoteFrame.h"
 #include "core/frame/Settings.h"
 #include "core/html/HTMLPlugInElement.h"
-#include "core/html/HTMLShadowElement.h"
 #include "core/html/HTMLSlotElement.h"
 #include "core/html/forms/HTMLFormElement.h"
 #include "core/html/forms/TextControlElement.h"
@@ -68,11 +67,6 @@
 
 namespace {
 
-inline bool IsShadowInsertionPointFocusScopeOwner(Element& element) {
-  return IsActiveShadowInsertionPoint(element) &&
-         ToHTMLShadowElement(element).OlderShadowRoot();
-}
-
 // This class defines the navigation order.
 class FocusNavigation : public GarbageCollected<FocusNavigation> {
  public:
@@ -127,11 +121,8 @@
 
  private:
   Element* TreeOwner(ContainerNode* node) {
-    if (ShadowRoot* shadow_root = ToShadowRootOrNull(node)) {
-      return shadow_root->IsYoungest()
-                 ? &shadow_root->host()
-                 : shadow_root->ShadowInsertionPointOfYoungerShadowRoot();
-    }
+    if (ShadowRoot* shadow_root = ToShadowRootOrNull(node))
+      return &shadow_root->host();
     // FIXME: Figure out the right thing for OOPI here.
     if (Frame* frame = node->GetDocument().GetFrame())
       return frame->DeprecatedLocalOwner();
@@ -206,9 +197,6 @@
       FocusController::OwnerMap&);
   static ScopedFocusNavigation OwnedByShadowHost(const Element&,
                                                  FocusController::OwnerMap&);
-  static ScopedFocusNavigation OwnedByShadowInsertionPoint(
-      HTMLShadowElement&,
-      FocusController::OwnerMap&);
   static ScopedFocusNavigation OwnedByHTMLSlotElement(
       const HTMLSlotElement&,
       FocusController::OwnerMap&);
@@ -307,10 +295,6 @@
     FocusController::OwnerMap& owner_map) {
   if (IsShadowHost(element))
     return ScopedFocusNavigation::OwnedByShadowHost(element, owner_map);
-  if (IsShadowInsertionPointFocusScopeOwner(element)) {
-    return ScopedFocusNavigation::OwnedByShadowInsertionPoint(
-        ToHTMLShadowElement(element), owner_map);
-  }
   return ScopedFocusNavigation::OwnedByHTMLSlotElement(
       ToHTMLSlotElement(element), owner_map);
 }
@@ -319,7 +303,7 @@
     const Element& element,
     FocusController::OwnerMap& owner_map) {
   DCHECK(IsShadowHost(element));
-  return ScopedFocusNavigation(element.Shadow()->YoungestShadowRoot(), nullptr,
+  return ScopedFocusNavigation(element.Shadow()->GetShadowRoot(), nullptr,
                                owner_map);
 }
 
@@ -333,14 +317,6 @@
       *ToLocalFrame(frame.ContentFrame())->GetDocument(), nullptr, owner_map);
 }
 
-ScopedFocusNavigation ScopedFocusNavigation::OwnedByShadowInsertionPoint(
-    HTMLShadowElement& shadow_insertion_point,
-    FocusController::OwnerMap& owner_map) {
-  DCHECK(IsShadowInsertionPointFocusScopeOwner(shadow_insertion_point));
-  return ScopedFocusNavigation(*shadow_insertion_point.OlderShadowRoot(),
-                               nullptr, owner_map);
-}
-
 ScopedFocusNavigation ScopedFocusNavigation::OwnedByHTMLSlotElement(
     const HTMLSlotElement& element,
     FocusController::OwnerMap& owner_map) {
@@ -457,7 +433,6 @@
 
 inline bool IsNonFocusableFocusScopeOwner(Element& element) {
   return IsNonKeyboardFocusableShadowHost(element) ||
-         IsShadowInsertionPointFocusScopeOwner(element) ||
          IsHTMLSlotElement(element);
 }
 
@@ -467,10 +442,7 @@
 }
 
 inline int AdjustedTabIndex(Element& element) {
-  return (IsNonKeyboardFocusableShadowHost(element) ||
-          IsShadowInsertionPointFocusScopeOwner(element))
-             ? 0
-             : element.tabIndex();
+  return IsNonKeyboardFocusableShadowHost(element) ? 0 : element.tabIndex();
 }
 
 inline bool ShouldVisit(Element& element) {
diff --git a/third_party/WebKit/Source/core/paint/BoxPainter.cpp b/third_party/WebKit/Source/core/paint/BoxPainter.cpp
index 514f100..fe86c72 100644
--- a/third_party/WebKit/Source/core/paint/BoxPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxPainter.cpp
@@ -225,8 +225,9 @@
 
 void BoxPainter::PaintMask(const PaintInfo& paint_info,
                            const LayoutPoint& paint_offset) {
-  if (layout_box_.Style()->Visibility() != EVisibility::kVisible ||
-      paint_info.phase != PaintPhase::kMask)
+  DCHECK_EQ(PaintPhase::kMask, paint_info.phase);
+  DCHECK(layout_box_.HasMask());
+  if (layout_box_.Style()->Visibility() != EVisibility::kVisible)
     return;
 
   if (DrawingRecorder::UseCachedDrawingIfPossible(
@@ -242,16 +243,10 @@
                                  const LayoutRect& paint_rect) {
   // Figure out if we need to push a transparency layer to render our mask.
   bool push_transparency_layer = false;
-  bool flatten_compositing_layers =
-      paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers;
-  bool mask_blending_applied_by_compositor =
-      !flatten_compositing_layers && layout_box_.HasLayer() &&
-      layout_box_.Layer()->MaskBlendingAppliedByCompositor();
-
   bool all_mask_images_loaded = true;
 
-  if (!mask_blending_applied_by_compositor &&
-      !RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
+  DCHECK(layout_box_.HasLayer());
+  if (!layout_box_.Layer()->MaskBlendingAppliedByCompositor(paint_info)) {
     push_transparency_layer = true;
     StyleImage* mask_box_image = layout_box_.Style()->MaskBoxImage().GetImage();
     const FillLayer& mask_layers = layout_box_.Style()->MaskLayers();
diff --git a/third_party/WebKit/Source/core/paint/InlineFlowBoxPainter.cpp b/third_party/WebKit/Source/core/paint/InlineFlowBoxPainter.cpp
index d351362..8f672ea 100644
--- a/third_party/WebKit/Source/core/paint/InlineFlowBoxPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/InlineFlowBoxPainter.cpp
@@ -33,13 +33,6 @@
     return;
 
   if (paint_info.phase == PaintPhase::kMask) {
-    if (DrawingRecorder::UseCachedDrawingIfPossible(
-            paint_info.context, inline_flow_box_,
-            DisplayItem::PaintPhaseToDrawingType(paint_info.phase)))
-      return;
-    DrawingRecorder recorder(
-        paint_info.context, inline_flow_box_,
-        DisplayItem::PaintPhaseToDrawingType(paint_info.phase));
     PaintMask(paint_info, paint_offset);
     return;
   }
@@ -343,11 +336,21 @@
 
 void InlineFlowBoxPainter::PaintMask(const PaintInfo& paint_info,
                                      const LayoutPoint& paint_offset) {
-  if (inline_flow_box_.GetLineLayoutItem().Style()->Visibility() !=
-          EVisibility::kVisible ||
-      paint_info.phase != PaintPhase::kMask)
+  DCHECK_EQ(PaintPhase::kMask, paint_info.phase);
+  const auto& box_model = *ToLayoutBoxModelObject(
+      LineLayoutAPIShim::LayoutObjectFrom(inline_flow_box_.BoxModelObject()));
+  DCHECK(box_model.HasMask());
+  if (box_model.StyleRef().Visibility() != EVisibility::kVisible)
     return;
 
+  if (DrawingRecorder::UseCachedDrawingIfPossible(
+          paint_info.context, inline_flow_box_,
+          DisplayItem::PaintPhaseToDrawingType(paint_info.phase)))
+    return;
+  DrawingRecorder recorder(
+      paint_info.context, inline_flow_box_,
+      DisplayItem::PaintPhaseToDrawingType(paint_info.phase));
+
   LayoutRect frame_rect = FrameRectClampedToLineTopAndBottomIfNeeded();
 
   // Move x/y to our coordinates.
@@ -355,45 +358,32 @@
   inline_flow_box_.FlipForWritingMode(local_rect);
   LayoutPoint adjusted_paint_offset = paint_offset + local_rect.Location();
 
-  const NinePieceImage& mask_nine_piece_image =
-      inline_flow_box_.GetLineLayoutItem().Style()->MaskBoxImage();
-  StyleImage* mask_box_image =
-      inline_flow_box_.GetLineLayoutItem().Style()->MaskBoxImage().GetImage();
+  const auto& mask_nine_piece_image = box_model.StyleRef().MaskBoxImage();
+  const auto* mask_box_image = mask_nine_piece_image.GetImage();
 
   // Figure out if we need to push a transparency layer to render our mask.
   bool push_transparency_layer = false;
-  bool flatten_compositing_layers =
-      paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers;
-  bool mask_blending_applied_by_compositor =
-      !flatten_compositing_layers &&
-      inline_flow_box_.GetLineLayoutItem().HasLayer() &&
-      inline_flow_box_.BoxModelObject()
-          .Layer()
-          ->MaskBlendingAppliedByCompositor();
   SkBlendMode composite_op = SkBlendMode::kSrcOver;
-  if (!mask_blending_applied_by_compositor) {
-    if ((mask_box_image && inline_flow_box_.GetLineLayoutItem()
-                               .Style()
-                               ->MaskLayers()
-                               .HasImage()) ||
-        inline_flow_box_.GetLineLayoutItem().Style()->MaskLayers().Next()) {
+  DCHECK(box_model.HasLayer());
+  if (!box_model.Layer()->MaskBlendingAppliedByCompositor(paint_info)) {
+    if ((mask_box_image && box_model.StyleRef().MaskLayers().HasImage()) ||
+        box_model.StyleRef().MaskLayers().Next()) {
       push_transparency_layer = true;
       paint_info.context.BeginLayer(1.0f, SkBlendMode::kDstIn);
     } else {
       // TODO(fmalita): passing a dst-in xfer mode down to
-      // paintFillLayers/paintNinePieceImage seems dangerous: it is only correct
-      // if applied atomically (single draw call). While the heuristic above
-      // presumably ensures that is the case, this approach seems super fragile.
-      // We should investigate dropping this optimization in favour of the more
-      // robust layer branch above.
+      // paintFillLayers/paintNinePieceImage seems dangerous: it is only
+      // correct if applied atomically (single draw call). While the heuristic
+      // above presumably ensures that is the case, this approach seems super
+      // fragile. We should investigate dropping this optimization in favour
+      // of the more robust layer branch above.
       composite_op = SkBlendMode::kDstIn;
     }
   }
 
   LayoutRect paint_rect = LayoutRect(adjusted_paint_offset, frame_rect.Size());
   PaintFillLayers(paint_info, Color::kTransparent,
-                  inline_flow_box_.GetLineLayoutItem().Style()->MaskLayers(),
-                  paint_rect, composite_op);
+                  box_model.StyleRef().MaskLayers(), paint_rect, composite_op);
 
   bool has_box_image = mask_box_image && mask_box_image->CanRender();
   if (!has_box_image || !mask_box_image->IsLoaded()) {
@@ -402,16 +392,13 @@
     return;  // Don't paint anything while we wait for the image to load.
   }
 
-  LayoutBoxModelObject* box_model = ToLayoutBoxModelObject(
-      LineLayoutAPIShim::LayoutObjectFrom(inline_flow_box_.BoxModelObject()));
   // The simple case is where we are the only box for this object. In those
   // cases only a single call to draw is required.
   if (!inline_flow_box_.PrevLineBox() && !inline_flow_box_.NextLineBox()) {
-    NinePieceImagePainter::Paint(
-        paint_info.context, *box_model, box_model->GetDocument(),
-        GetNode(box_model), paint_rect,
-        inline_flow_box_.GetLineLayoutItem().StyleRef(), mask_nine_piece_image,
-        composite_op);
+    NinePieceImagePainter::Paint(paint_info.context, box_model,
+                                 box_model.GetDocument(), GetNode(&box_model),
+                                 paint_rect, box_model.StyleRef(),
+                                 mask_nine_piece_image, composite_op);
   } else {
     // We have a mask image that spans multiple lines.
     // FIXME: What the heck do we do with RTL here? The math we're using is
@@ -423,11 +410,10 @@
     GraphicsContextStateSaver state_saver(paint_info.context);
     // TODO(chrishtr): this should be pixel-snapped.
     paint_info.context.Clip(clip_rect);
-    NinePieceImagePainter::Paint(
-        paint_info.context, *box_model, box_model->GetDocument(),
-        GetNode(box_model), image_strip_paint_rect,
-        inline_flow_box_.GetLineLayoutItem().StyleRef(), mask_nine_piece_image,
-        composite_op);
+    NinePieceImagePainter::Paint(paint_info.context, box_model,
+                                 box_model.GetDocument(), GetNode(&box_model),
+                                 image_strip_paint_rect, box_model.StyleRef(),
+                                 mask_nine_piece_image, composite_op);
   }
 
   if (push_transparency_layer)
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
index 47746b03..bbe9f65 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -71,6 +71,7 @@
 #include "core/paint/ClipPathClipper.h"
 #include "core/paint/FilterEffectBuilder.h"
 #include "core/paint/ObjectPaintInvalidator.h"
+#include "core/paint/PaintInfo.h"
 #include "core/paint/compositing/CompositedLayerMapping.h"
 #include "core/paint/compositing/PaintLayerCompositor.h"
 #include "platform/LengthFunctions.h"
@@ -2677,10 +2678,15 @@
     grouped_mapping->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
 }
 
-bool PaintLayer::MaskBlendingAppliedByCompositor() const {
+bool PaintLayer::MaskBlendingAppliedByCompositor(
+    const PaintInfo& paint_info) const {
   DCHECK(layout_object_.HasMask());
-  if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
     return true;
+
+  if (paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers)
+    return false;
+
   return rare_data_ && rare_data_->composited_layer_mapping &&
          rare_data_->composited_layer_mapping->HasMaskLayer();
 }
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.h b/third_party/WebKit/Source/core/paint/PaintLayer.h
index d32d727..73b09a07 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayer.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayer.h
@@ -552,7 +552,7 @@
   };
   void SetGroupedMapping(CompositedLayerMapping*, SetGroupMappingOptions);
 
-  bool MaskBlendingAppliedByCompositor() const;
+  bool MaskBlendingAppliedByCompositor(const PaintInfo&) const;
   bool HasCompositedClippingMask() const;
   bool NeedsCompositedScrolling() const {
     return scrollable_area_ && scrollable_area_->NeedsCompositedScrolling();
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
index 7fbc847..0c7cbd1 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -546,8 +546,8 @@
   }
 
   if (requires_paint_invalidation) {
-    GetLayoutBox()
-        ->SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants();
+    GetLayoutBox()->SetShouldDoFullPaintInvalidation();
+    GetLayoutBox()->SetMayNeedPaintInvalidationSubtree();
   }
 }
 
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp
index 71937f4..bd527d1 100644
--- a/third_party/WebKit/Source/core/testing/Internals.cpp
+++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -757,38 +757,12 @@
 }
 
 ShadowRoot* Internals::shadowRoot(Element* host) {
-  // FIXME: Internals::shadowRoot() in tests should be converted to
-  // youngestShadowRoot() or oldestShadowRoot().
-  // https://bugs.webkit.org/show_bug.cgi?id=78465
-  return youngestShadowRoot(host);
-}
-
-ShadowRoot* Internals::youngestShadowRoot(Element* host) {
   DCHECK(host);
   if (ElementShadow* shadow = host->Shadow())
-    return &shadow->YoungestShadowRoot();
+    return &shadow->GetShadowRoot();
   return nullptr;
 }
 
-ShadowRoot* Internals::oldestShadowRoot(Element* host) {
-  DCHECK(host);
-  if (ElementShadow* shadow = host->Shadow())
-    return &shadow->OldestShadowRoot();
-  return nullptr;
-}
-
-ShadowRoot* Internals::youngerShadowRoot(Node* shadow,
-                                         ExceptionState& exception_state) {
-  DCHECK(shadow);
-  if (!shadow->IsShadowRoot()) {
-    exception_state.ThrowDOMException(
-        kInvalidAccessError, "The node provided is not a shadow root.");
-    return nullptr;
-  }
-
-  return ToShadowRoot(shadow)->YoungerShadowRoot();
-}
-
 String Internals::shadowRootType(const Node* root,
                                  ExceptionState& exception_state) const {
   DCHECK(root);
diff --git a/third_party/WebKit/Source/core/testing/Internals.h b/third_party/WebKit/Source/core/testing/Internals.h
index 4d2253a..c88d157 100644
--- a/third_party/WebKit/Source/core/testing/Internals.h
+++ b/third_party/WebKit/Source/core/testing/Internals.h
@@ -115,9 +115,6 @@
   ShadowRoot* createUserAgentShadowRoot(Element* host);
 
   ShadowRoot* shadowRoot(Element* host);
-  ShadowRoot* youngestShadowRoot(Element* host);
-  ShadowRoot* oldestShadowRoot(Element* host);
-  ShadowRoot* youngerShadowRoot(Node* shadow, ExceptionState&);
   String shadowRootType(const Node*, ExceptionState&) const;
   bool hasShadowInsertionPoint(const Node*, ExceptionState&) const;
   bool hasContentElement(const Node*, ExceptionState&) const;
diff --git a/third_party/WebKit/Source/core/testing/Internals.idl b/third_party/WebKit/Source/core/testing/Internals.idl
index 3096c81..cab779a 100644
--- a/third_party/WebKit/Source/core/testing/Internals.idl
+++ b/third_party/WebKit/Source/core/testing/Internals.idl
@@ -49,9 +49,6 @@
     ShadowRoot createUserAgentShadowRoot(Element host);
 
     ShadowRoot shadowRoot(Element host);
-    ShadowRoot youngestShadowRoot(Element host);
-    ShadowRoot oldestShadowRoot(Element host);
-    [RaisesException] ShadowRoot youngerShadowRoot(Node root);
 
     void setBrowserControlsState(float top_height, float bottom_height, boolean shrinksLayout);
     void setBrowserControlsShownRatio(float ratio);
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
index 56b15e1..f8e8731 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
@@ -548,19 +548,19 @@
    * @param {*|undefined} executionContextAuxData
    * @param {boolean} isLiveEdit
    * @param {string|undefined} sourceMapURL
-   * @param {boolean} hasSourceURL
+   * @param {boolean} hasSourceURLComment
    * @param {boolean} hasSyntaxError
    * @param {number} length
    * @return {!SDK.Script}
    */
   _parsedScriptSource(
       scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
-      executionContextAuxData, isLiveEdit, sourceMapURL, hasSourceURL, hasSyntaxError, length) {
+      executionContextAuxData, isLiveEdit, sourceMapURL, hasSourceURLComment, hasSyntaxError, length) {
     var isContentScript = false;
     if (executionContextAuxData && ('isDefault' in executionContextAuxData))
       isContentScript = !executionContextAuxData['isDefault'];
     // Support file URL for node.js.
-    if (this.target().isNodeJS() && sourceURL && sourceURL.startsWith('/')) {
+    if (this.target().isNodeJS() && sourceURL && !hasSourceURLComment) {
       var nodeJSPath = sourceURL;
       sourceURL = Common.ParsedURL.platformPathToURL(nodeJSPath);
       sourceURL = this._internString(sourceURL);
@@ -570,7 +570,7 @@
     }
     var script = new SDK.Script(
         this, scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId,
-        this._internString(hash), isContentScript, isLiveEdit, sourceMapURL, hasSourceURL, length);
+        this._internString(hash), isContentScript, isLiveEdit, sourceMapURL, hasSourceURLComment, length);
     this._registerScript(script);
     if (!hasSyntaxError)
       this.dispatchEventToListeners(SDK.DebuggerModel.Events.ParsedScriptSource, script);
diff --git a/third_party/WebKit/Source/modules/BUILD.gn b/third_party/WebKit/Source/modules/BUILD.gn
index 4b065843..ac6f56b 100644
--- a/third_party/WebKit/Source/modules/BUILD.gn
+++ b/third_party/WebKit/Source/modules/BUILD.gn
@@ -83,7 +83,6 @@
   deps = [
     ":make_modules_generated",
     ":module_names",
-    "//device/geolocation/public/interfaces:interfaces_blink",
     "//third_party/WebKit/Source/bindings/modules:generated",
     "//third_party/WebKit/Source/bindings/modules/v8:bindings_modules_impl",
     "//third_party/WebKit/Source/bindings/modules/v8:bindings_modules_origin_trial_features",
diff --git a/third_party/WebKit/Source/modules/geolocation/BUILD.gn b/third_party/WebKit/Source/modules/geolocation/BUILD.gn
index 5db851c..2aff52f 100644
--- a/third_party/WebKit/Source/modules/geolocation/BUILD.gn
+++ b/third_party/WebKit/Source/modules/geolocation/BUILD.gn
@@ -20,7 +20,4 @@
     "NavigatorGeolocation.h",
     "PositionError.h",
   ]
-  deps = [
-    "//device/geolocation/public/interfaces:interfaces_blink",
-  ]
 }
diff --git a/third_party/WebKit/Source/modules/geolocation/DEPS b/third_party/WebKit/Source/modules/geolocation/DEPS
index b42e08bd..d514f95 100644
--- a/third_party/WebKit/Source/modules/geolocation/DEPS
+++ b/third_party/WebKit/Source/modules/geolocation/DEPS
@@ -1,5 +1,5 @@
 include_rules = [
-    "+device/geolocation/public/interfaces",
+    "+services/device/public/interfaces",
     "-modules",
     "+modules/EventModules.h",
     "+modules/ModulesExport.h",
diff --git a/third_party/WebKit/Source/modules/geolocation/Geolocation.h b/third_party/WebKit/Source/modules/geolocation/Geolocation.h
index ff83f37..8bdddb6 100644
--- a/third_party/WebKit/Source/modules/geolocation/Geolocation.h
+++ b/third_party/WebKit/Source/modules/geolocation/Geolocation.h
@@ -31,7 +31,6 @@
 #include "bindings/modules/v8/v8_position_error_callback.h"
 #include "core/dom/ContextLifecycleObserver.h"
 #include "core/page/PageVisibilityObserver.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom-blink.h"
 #include "modules/ModulesExport.h"
 #include "modules/geolocation/GeoNotifier.h"
 #include "modules/geolocation/GeolocationWatchers.h"
@@ -42,6 +41,7 @@
 #include "platform/bindings/ScriptWrappable.h"
 #include "platform/heap/Handle.h"
 #include "public/platform/modules/geolocation/geolocation_service.mojom-blink.h"
+#include "services/device/public/interfaces/geolocation.mojom-blink.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlLoadingPanelElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlLoadingPanelElement.cpp
index 57df466a..d0422ee 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlLoadingPanelElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlLoadingPanelElement.cpp
@@ -54,7 +54,7 @@
 // +- #cutoff-4
 // +- #fake-timeline
 void MediaControlLoadingPanelElement::PopulateShadowDOM() {
-  ShadowRoot* shadow_root = YoungestShadowRoot();
+  ShadowRoot* shadow_root = GetShadowRoot();
   DCHECK(!shadow_root->HasChildren());
 
   // This stylesheet element and will contain rules that are specific to the
@@ -125,7 +125,7 @@
 
 void MediaControlLoadingPanelElement::CleanupShadowDOM() {
   // Clear the shadow DOM children and all references to it.
-  ShadowRoot* shadow_root = YoungestShadowRoot();
+  ShadowRoot* shadow_root = GetShadowRoot();
   DCHECK(shadow_root->HasChildren());
   event_listener_->Detach();
   shadow_root->RemoveChildren();
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlLoadingPanelElementTest.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlLoadingPanelElementTest.cpp
index 33226bc1..ffcec53 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlLoadingPanelElementTest.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlLoadingPanelElementTest.cpp
@@ -137,12 +137,12 @@
 
   void CheckIsHidden() {
     EXPECT_FALSE(loading_element_->IsWanted());
-    EXPECT_FALSE(loading_element_->YoungestShadowRoot()->HasChildren());
+    EXPECT_FALSE(loading_element_->GetShadowRoot()->HasChildren());
   }
 
   void CheckIsShown() {
     EXPECT_TRUE(loading_element_->IsWanted());
-    EXPECT_TRUE(loading_element_->YoungestShadowRoot()->HasChildren());
+    EXPECT_TRUE(loading_element_->GetShadowRoot()->HasChildren());
   }
 
   void ExpectAnimationIterationCount(Element* element, const String& value) {
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
index 4374402..d18bfd7 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
@@ -116,7 +116,7 @@
   SetShadowPseudoId(AtomicString("-webkit-media-controls-overlay-play-button"));
 
   if (MediaControlsImpl::IsModern()) {
-    ShadowRoot& shadow_root = Shadow()->OldestShadowRoot();
+    ShadowRoot& shadow_root = Shadow()->GetShadowRoot();
 
     // This stylesheet element and will contain rules that are specific to the
     // loading panel. The shadow DOM protects these rules from the parent DOM
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlSliderElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlSliderElement.cpp
index c47f064..0985994d 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlSliderElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlSliderElement.cpp
@@ -86,7 +86,7 @@
   // #shadow-root
   //   - div
   //     - div::-webkit-slider-runnable-track#track
-  ShadowRoot& shadow_root = Shadow()->OldestShadowRoot();
+  ShadowRoot& shadow_root = Shadow()->GetShadowRoot();
   Element* track = shadow_root.getElementById(AtomicString("track"));
   DCHECK(track);
   return *track;
diff --git a/third_party/WebKit/Source/platform/bindings/ScriptWrappableMarkingVisitor.cpp b/third_party/WebKit/Source/platform/bindings/ScriptWrappableMarkingVisitor.cpp
index 94ec1617..e27a426 100644
--- a/third_party/WebKit/Source/platform/bindings/ScriptWrappableMarkingVisitor.cpp
+++ b/third_party/WebKit/Source/platform/bindings/ScriptWrappableMarkingVisitor.cpp
@@ -173,8 +173,7 @@
 
   ScriptWrappable* script_wrappable =
       reinterpret_cast<ScriptWrappable*>(internal_fields.second);
-
-  wrapper_type_info->TraceWrappers(this, script_wrappable);
+  TraceWrappersFromGeneratedCode(script_wrappable);
 }
 
 void ScriptWrappableMarkingVisitor::RegisterV8References(
diff --git a/third_party/WebKit/Source/platform/bindings/WrapperTypeInfo.h b/third_party/WebKit/Source/platform/bindings/WrapperTypeInfo.h
index 45959ca..5a01dba 100644
--- a/third_party/WebKit/Source/platform/bindings/WrapperTypeInfo.h
+++ b/third_party/WebKit/Source/platform/bindings/WrapperTypeInfo.h
@@ -58,9 +58,6 @@
 
 typedef v8::Local<v8::FunctionTemplate> (
     *DomTemplateFunction)(v8::Isolate*, const DOMWrapperWorld&);
-typedef void (*TraceFunction)(Visitor*, ScriptWrappable*);
-typedef void (*TraceWrappersFunction)(ScriptWrappableVisitor*,
-                                      ScriptWrappable*);
 typedef ActiveScriptWrappableBase* (*ToActiveScriptWrappableFunction)(
     v8::Local<v8::Object>);
 typedef void (*ResolveWrapperReachabilityFunction)(
@@ -134,17 +131,6 @@
     return dom_template_function(isolate, world);
   }
 
-  void Trace(Visitor* visitor, ScriptWrappable* script_wrappable) const {
-    DCHECK(trace_function);
-    return trace_function(visitor, script_wrappable);
-  }
-
-  void TraceWrappers(ScriptWrappableVisitor* visitor,
-                     ScriptWrappable* script_wrappable) const {
-    DCHECK(trace_wrappers_function);
-    return trace_wrappers_function(visitor, script_wrappable);
-  }
-
   void InstallConditionalFeatures(
       v8::Local<v8::Context> context,
       const DOMWrapperWorld& world,
@@ -169,8 +155,6 @@
   const gin::GinEmbedder gin_embedder;
 
   DomTemplateFunction dom_template_function;
-  const TraceFunction trace_function;
-  const TraceWrappersFunction trace_wrappers_function;
   InstallConditionalFeaturesFunction install_conditional_features_function;
   const char* const interface_name;
   const WrapperTypeInfo* parent_class;
diff --git a/third_party/WebKit/Source/platform/exported/WebRuntimeFeatures.cpp b/third_party/WebKit/Source/platform/exported/WebRuntimeFeatures.cpp
index 06d3a59..2f9c7a7 100644
--- a/third_party/WebKit/Source/platform/exported/WebRuntimeFeatures.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebRuntimeFeatures.cpp
@@ -382,6 +382,10 @@
   RuntimeEnabledFeatures::SetScrollAnchoringEnabled(enable);
 }
 
+void WebRuntimeFeatures::EnableScrollAnchorSerialization(bool enable) {
+  RuntimeEnabledFeatures::SetScrollAnchorSerializationEnabled(enable);
+}
+
 void WebRuntimeFeatures::EnableServiceWorkerScriptStreaming(bool enable) {
   RuntimeEnabledFeatures::SetServiceWorkerScriptStreamingEnabled(enable);
 }
diff --git a/third_party/WebKit/Source/platform/heap/HeapTest.cpp b/third_party/WebKit/Source/platform/heap/HeapTest.cpp
index 8909ac82..15b15599 100644
--- a/third_party/WebKit/Source/platform/heap/HeapTest.cpp
+++ b/third_party/WebKit/Source/platform/heap/HeapTest.cpp
@@ -220,7 +220,8 @@
   template <typename VisitorDispatcher>
   bool TraceInCollection(VisitorDispatcher visitor,
                          WTF::ShouldWeakPointersBeMarkedStrongly strongify) {
-    visitor->TraceInCollection(second, strongify);
+    HashTraits<WeakMember<IntWrapper>>::TraceInCollection(visitor, second,
+                                                          strongify);
     if (!ThreadHeap::IsHeapObjectAlive(second))
       return true;
     // FIXME: traceInCollection is also called from WeakProcessing to check if
diff --git a/third_party/WebKit/Source/platform/heap/Visitor.h b/third_party/WebKit/Source/platform/heap/Visitor.h
index 10376020..9b792bd 100644
--- a/third_party/WebKit/Source/platform/heap/Visitor.h
+++ b/third_party/WebKit/Source/platform/heap/Visitor.h
@@ -133,12 +133,6 @@
     Trace(*(static_cast<const Member<T>*>(&t)));
   }
 
-  // Only called from automatically generated bindings code.
-  template <typename T>
-  void TraceFromGeneratedCode(const T* t) {
-    Mark(const_cast<T*>(t));
-  }
-
   // Fallback method used only when we need to trace raw pointers of T.
   // This is the case when a member is a union where we do not support members.
   template <typename T>
@@ -164,12 +158,6 @@
     RegisterWeakCell(const_cast<WeakMember<T>&>(t).Cell());
   }
 
-  template <typename T>
-  void TraceInCollection(T& t,
-                         WTF::ShouldWeakPointersBeMarkedStrongly strongify) {
-    HashTraits<T>::TraceInCollection(this, t, strongify);
-  }
-
   // Fallback trace method for part objects to allow individual trace methods
   // to trace through a part object with visitor->trace(m_partObject). This
   // takes a const argument, because otherwise it will match too eagerly: a
diff --git a/third_party/WebKit/Source/platform/wtf/ListHashSet.h b/third_party/WebKit/Source/platform/wtf/ListHashSet.h
index 95b2bb0b..df79753 100644
--- a/third_party/WebKit/Source/platform/wtf/ListHashSet.h
+++ b/third_party/WebKit/Source/platform/wtf/ListHashSet.h
@@ -463,8 +463,8 @@
     if (WasAlreadyDestructed())
       return;
     NodeAllocator::TraceValue(visitor, this);
-    visitor->Mark(Next());
-    visitor->Mark(Prev());
+    visitor->Trace(Next());
+    visitor->Trace(Prev());
   }
 
   ListHashSetNode* Next() const {
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index 036dc3c..7222f77 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -789,9 +789,9 @@
     ":web_feature_mojo_bindings",
     "//components/payments/mojom",
     "//device/bluetooth/public/interfaces",
-    "//device/geolocation/public/interfaces",
     "//device/screen_orientation/public/interfaces",
     "//mojo/common:common_custom_types",
+    "//services/device/public/interfaces",
     "//services/network/public/interfaces:interfaces",
     "//services/service_manager/public/interfaces",
     "//skia/public/interfaces",
diff --git a/third_party/WebKit/public/platform/WebRuntimeFeatures.h b/third_party/WebKit/public/platform/WebRuntimeFeatures.h
index cd52e3c..1e36ac6 100644
--- a/third_party/WebKit/public/platform/WebRuntimeFeatures.h
+++ b/third_party/WebKit/public/platform/WebRuntimeFeatures.h
@@ -129,6 +129,7 @@
   BLINK_PLATFORM_EXPORT static void EnableRootLayerScrolling(bool);
   BLINK_PLATFORM_EXPORT static void EnableScriptedSpeech(bool);
   BLINK_PLATFORM_EXPORT static void EnableScrollAnchoring(bool);
+  BLINK_PLATFORM_EXPORT static void EnableScrollAnchorSerialization(bool);
   BLINK_PLATFORM_EXPORT static void EnableServiceWorkerNavigationPreload(bool);
   BLINK_PLATFORM_EXPORT static void EnableServiceWorkerScriptStreaming(bool);
   BLINK_PLATFORM_EXPORT static void EnableServiceWorkerScriptFullCodeCache(
diff --git a/third_party/WebKit/public/platform/modules/geolocation/geolocation_service.mojom b/third_party/WebKit/public/platform/modules/geolocation/geolocation_service.mojom
index 976da97..1da67f5 100644
--- a/third_party/WebKit/public/platform/modules/geolocation/geolocation_service.mojom
+++ b/third_party/WebKit/public/platform/modules/geolocation/geolocation_service.mojom
@@ -4,7 +4,7 @@
 
 module blink.mojom;
 
-import "device/geolocation/public/interfaces/geolocation.mojom";
+import "services/device/public/interfaces/geolocation.mojom";
 
 // GeolocationService provides a Geolocation. It exists in order to examine the
 // environment (permissions, etc.) before creating a Geolocation.
diff --git a/third_party/android_crazy_linker/BUILD.gn b/third_party/android_crazy_linker/BUILD.gn
index 49729ea..ea03774a 100644
--- a/third_party/android_crazy_linker/BUILD.gn
+++ b/third_party/android_crazy_linker/BUILD.gn
@@ -2,6 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/android/config.gni")
+import("//testing/test.gni")
+
+assert(is_android)
+
 config("crazy_config") {
   include_dirs = [ "src/include" ]
   libs = [
@@ -10,63 +15,116 @@
   ]
 }
 
-source_set("android_crazy_linker") {
+# Template to define a source set for the crazy linker.
+# This takes a single boolean parameter:
+#
+#   unit_tests: if true, build a version with unit-testing support.
+#
+template("crazy_linker_library") {
+  source_set(target_name) {
+    forward_variables_from(invoker, [ "*" ])
+    sources = [
+      "src/include/crazy_linker.h",
+      "src/src/crazy_linker_api.cpp",
+      "src/src/crazy_linker_ashmem.cpp",
+      "src/src/crazy_linker_ashmem.h",
+      "src/src/crazy_linker_debug.cpp",
+      "src/src/crazy_linker_debug.h",
+      "src/src/crazy_linker_defines.h",
+      "src/src/crazy_linker_elf_loader.cpp",
+      "src/src/crazy_linker_elf_loader.h",
+      "src/src/crazy_linker_elf_relocations.cpp",
+      "src/src/crazy_linker_elf_relocations.h",
+      "src/src/crazy_linker_elf_relro.cpp",
+      "src/src/crazy_linker_elf_relro.h",
+      "src/src/crazy_linker_elf_symbols.cpp",
+      "src/src/crazy_linker_elf_symbols.h",
+      "src/src/crazy_linker_elf_view.cpp",
+      "src/src/crazy_linker_elf_view.h",
+      "src/src/crazy_linker_error.cpp",
+      "src/src/crazy_linker_error.h",
+      "src/src/crazy_linker_globals.cpp",
+      "src/src/crazy_linker_globals.h",
+      "src/src/crazy_linker_library_list.cpp",
+      "src/src/crazy_linker_library_list.h",
+      "src/src/crazy_linker_library_view.cpp",
+      "src/src/crazy_linker_library_view.h",
+      "src/src/crazy_linker_line_reader.cpp",
+      "src/src/crazy_linker_line_reader.h",
+      "src/src/crazy_linker_memory_mapping.h",
+      "src/src/crazy_linker_proc_maps.cpp",
+      "src/src/crazy_linker_proc_maps.h",
+      "src/src/crazy_linker_rdebug.cpp",
+      "src/src/crazy_linker_rdebug.h",
+      "src/src/crazy_linker_search_path_list.cpp",
+      "src/src/crazy_linker_search_path_list.h",
+      "src/src/crazy_linker_shared_library.cpp",
+      "src/src/crazy_linker_shared_library.h",
+      "src/src/crazy_linker_system.cpp",
+      "src/src/crazy_linker_system.h",
+      "src/src/crazy_linker_thread.cpp",
+      "src/src/crazy_linker_thread.h",
+      "src/src/crazy_linker_util.cpp",
+      "src/src/crazy_linker_util.h",
+      "src/src/crazy_linker_wrappers.cpp",
+      "src/src/crazy_linker_wrappers.h",
+      "src/src/crazy_linker_zip.cpp",
+      "src/src/crazy_linker_zip.h",
+      "src/src/elf_traits.h",
+      "src/src/linker_phdr.cpp",
+      "src/src/linker_phdr.h",
+      "src/src/linker_reloc_iterators.h",
+      "src/src/linker_sleb128.h",
+    ]
+
+    include_dirs = [ "src/src" ]
+
+    if (defined(invoker.unit_tests) && invoker.unit_tests) {
+      sources += [
+        "src/src/crazy_linker_system_mock.cpp",
+        "src/src/crazy_linker_system_mock.h",
+      ]
+      defines = [
+        "UNIT_TESTS",
+        "CRAZY_DEBUG=1",
+      ]
+    }
+
+    public_configs = [ ":crazy_config" ]
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
+  }
+}
+
+crazy_linker_library("android_crazy_linker") {
+}
+
+crazy_linker_library("android_crazy_linker_for_unittests") {
+  unit_tests = true
+}
+
+test("android_crazy_linker_unittests") {
   sources = [
-    "src/include/crazy_linker.h",
-    "src/src/crazy_linker_api.cpp",
-    "src/src/crazy_linker_ashmem.cpp",
-    "src/src/crazy_linker_ashmem.h",
-    "src/src/crazy_linker_debug.cpp",
-    "src/src/crazy_linker_debug.h",
-    "src/src/crazy_linker_elf_loader.cpp",
-    "src/src/crazy_linker_elf_loader.h",
-    "src/src/crazy_linker_elf_relocations.cpp",
-    "src/src/crazy_linker_elf_relocations.h",
-    "src/src/crazy_linker_elf_relro.cpp",
-    "src/src/crazy_linker_elf_relro.h",
-    "src/src/crazy_linker_elf_symbols.cpp",
-    "src/src/crazy_linker_elf_symbols.h",
-    "src/src/crazy_linker_elf_view.cpp",
-    "src/src/crazy_linker_elf_view.h",
-    "src/src/crazy_linker_error.cpp",
-    "src/src/crazy_linker_error.h",
-    "src/src/crazy_linker_globals.cpp",
-    "src/src/crazy_linker_globals.h",
-    "src/src/crazy_linker_library_list.cpp",
-    "src/src/crazy_linker_library_list.h",
-    "src/src/crazy_linker_library_view.cpp",
-    "src/src/crazy_linker_library_view.h",
-    "src/src/crazy_linker_line_reader.cpp",
-    "src/src/crazy_linker_line_reader.h",
-    "src/src/crazy_linker_memory_mapping.h",
-    "src/src/crazy_linker_proc_maps.cpp",
-    "src/src/crazy_linker_proc_maps.h",
-    "src/src/crazy_linker_rdebug.cpp",
-    "src/src/crazy_linker_rdebug.h",
-    "src/src/crazy_linker_search_path_list.cpp",
-    "src/src/crazy_linker_search_path_list.h",
-    "src/src/crazy_linker_shared_library.cpp",
-    "src/src/crazy_linker_shared_library.h",
-    "src/src/crazy_linker_system.cpp",
-    "src/src/crazy_linker_system.h",
-    "src/src/crazy_linker_thread.cpp",
-    "src/src/crazy_linker_thread.h",
-    "src/src/crazy_linker_util.cpp",
-    "src/src/crazy_linker_util.h",
-    "src/src/crazy_linker_wrappers.cpp",
-    "src/src/crazy_linker_wrappers.h",
-    "src/src/crazy_linker_zip.cpp",
-    "src/src/crazy_linker_zip.h",
-    "src/src/elf_traits.h",
-    "src/src/linker_phdr.cpp",
-    "src/src/linker_phdr.h",
-    "src/src/linker_reloc_iterators.h",
-    "src/src/linker_sleb128.h",
+    "src/src/crazy_linker_ashmem_unittest.cpp",
+    "src/src/crazy_linker_error_unittest.cpp",
+    "src/src/crazy_linker_globals_unittest.cpp",
+    "src/src/crazy_linker_line_reader_unittest.cpp",
+    "src/src/crazy_linker_proc_maps_unittest.cpp",
+    "src/src/crazy_linker_search_path_list_unittest.cpp",
+    "src/src/crazy_linker_system_unittest.cpp",
+    "src/src/crazy_linker_thread_unittest.cpp",
+    "src/src/crazy_linker_util_unittest.cpp",
   ]
 
   include_dirs = [ "src/src" ]
 
-  public_configs = [ ":crazy_config" ]
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [ "//build/config/compiler:no_chromium_code" ]
+  deps = [
+    ":android_crazy_linker_for_unittests",
+    "//testing/gtest",
+    "//testing/gtest:gtest_main",
+  ]
+
+  use_raw_android_executable = true
 }
diff --git a/third_party/android_crazy_linker/README.chromium b/third_party/android_crazy_linker/README.chromium
index 1589b139..e023c09 100644
--- a/third_party/android_crazy_linker/README.chromium
+++ b/third_party/android_crazy_linker/README.chromium
@@ -93,3 +93,5 @@
   reduce the size of the final binaries (24 kiB on ARM, 64 kiB on AARCH4).
 
 - Allow client disable debugger support.
+
+- Enable unit tests when building with Chromium.
diff --git a/third_party/android_crazy_linker/src/minitest b/third_party/android_crazy_linker/src/minitest
deleted file mode 100644
index 61f247d..0000000
--- a/third_party/android_crazy_linker/src/minitest
+++ /dev/null
@@ -1 +0,0 @@
-../../android_ndk/sources/android//support/tests/minitest
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_ashmem_unittest.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_ashmem_unittest.cpp
index 5697a4e..4f8da5d 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_ashmem_unittest.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_ashmem_unittest.cpp
@@ -6,7 +6,7 @@
 
 #include <sys/mman.h>
 
-#include <minitest/minitest.h>
+#include <gtest/gtest.h>
 
 namespace crazy {
 
@@ -28,8 +28,7 @@
   EXPECT_NE(MAP_FAILED, map);
 
   for (size_t n = 0; n < kSize; ++n) {
-    TEST_TEXT << "Checking region[" << n << "]";
-    EXPECT_EQ(0, ((char*)map)[n]);
+    EXPECT_EQ(0, ((char*)map)[n]) << "Checking region[" << n << "]";
   }
 
   EXPECT_EQ(0, ::munmap(map, kSize));
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_error_unittest.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_error_unittest.cpp
index 852cc6c..e540635 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_error_unittest.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_error_unittest.cpp
@@ -4,7 +4,7 @@
 
 #include "crazy_linker_error.h"
 
-#include <minitest/minitest.h>
+#include <gtest/gtest.h>
 
 namespace crazy {
 
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_globals_unittest.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_globals_unittest.cpp
index 0f41e18..9f8f99ed 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_globals_unittest.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_globals_unittest.cpp
@@ -4,7 +4,7 @@
 
 #include "crazy_linker_globals.h"
 
-#include <minitest/minitest.h>
+#include <gtest/gtest.h>
 
 #include "crazy_linker_system_mock.h"
 
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_line_reader_unittest.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_line_reader_unittest.cpp
index 0bcdb98..a69c1ea 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_line_reader_unittest.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_line_reader_unittest.cpp
@@ -4,7 +4,7 @@
 
 #include "crazy_linker_line_reader.h"
 
-#include <minitest/minitest.h>
+#include <gtest/gtest.h>
 
 #include "crazy_linker_system_mock.h"
 
@@ -12,6 +12,33 @@
 
 static const char kFilePath[] = "/tmp/foo.txt";
 
+static ::testing::AssertionResult AssertMemEqual(const char* expr1,
+                                                 const char* expr2,
+                                                 const char* expr3,
+                                                 const char* expr4,
+                                                 const char* expected_str,
+                                                 size_t expected_len,
+                                                 const char* arg_str,
+                                                 size_t arg_len) {
+  if (arg_len != expected_len) {
+    return ::testing::AssertionFailure()
+           << "Invalid value for '" << expr4 << "': " << arg_len
+           << " (expecting '" << expr2 << "' which is " << expected_len << ")";
+  }
+  for (size_t n = 0; n < arg_len; ++n) {
+    if (arg_str[n] != expected_str[n]) {
+      return ::testing::AssertionFailure()
+             << "Invalid value " << (unsigned)arg_str[n] << " at index " << n
+             << "\nWhen comparing " << expr3 << " with expected " << expr1;
+    }
+  }
+  return ::testing::AssertionSuccess();
+}
+
+#define EXPECT_MEMEQ(expected_str, expected_len, arg_str, arg_len)         \
+  EXPECT_PRED_FORMAT4(AssertMemEqual, expected_str, expected_len, arg_str, \
+                      arg_len)
+
 TEST(LineReader, EmptyConstructor) {
   LineReader reader;
   EXPECT_FALSE(reader.GetNextLine());
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_proc_maps_unittest.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_proc_maps_unittest.cpp
index 7276523..2e210a8b 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_proc_maps_unittest.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_proc_maps_unittest.cpp
@@ -4,8 +4,8 @@
 
 #include "crazy_linker_proc_maps.h"
 
+#include <gtest/gtest.h>
 #include <limits.h>
-#include <minitest/minitest.h>
 #include "crazy_linker_system_mock.h"
 
 namespace crazy {
@@ -84,13 +84,12 @@
                {0x40084000, true, PROT_READ | PROT_WRITE}, };
 
   int prot;
-  for (size_t n = 0; n < ARRAY_LEN(kData); ++n) {
-    void* address = reinterpret_cast<void*>(kData[n].address);
-    TEST_TEXT << minitest::Format("Checking address %p", address);
-    EXPECT_EQ(kData[n].success, FindProtectionFlagsForAddress(address, &prot));
-    if (kData[n].success) {
-      TEST_TEXT << minitest::Format("Checking address %p", address);
-      EXPECT_EQ(kData[n].prot, prot);
+  for (auto const& data : kData) {
+    void* address = reinterpret_cast<void*>(data.address);
+    EXPECT_EQ(data.success, FindProtectionFlagsForAddress(address, &prot))
+        << "Checking address " << address;
+    if (data.success) {
+      EXPECT_EQ(data.prot, prot) << "Checking address " << address;
     }
   }
 }
@@ -108,17 +107,13 @@
                {false, 0, 0, "bin/mksh"},
                {true, 0x4005c000, 0, "/system/bin/mksh"},
                {true, 0x40231000, 0x1000000, "libc.so"}, };
-  for (size_t n = 0; n < ARRAY_LEN(kData); ++n) {
+  for (auto const& data : kData) {
     uintptr_t address, offset;
-    TEST_TEXT << "Checking " << kData[n].name;
-    bool success = FindLoadAddressForFile(kData[n].name, &address, &offset);
-    EXPECT_EQ(kData[n].success, success);
+    bool success = FindLoadAddressForFile(data.name, &address, &offset);
+    EXPECT_EQ(data.success, success) << "Checking " << data.name;
     if (success) {
-      TEST_TEXT << "Checking " << kData[n].name;
-      EXPECT_EQ(kData[n].address, address);
-
-      TEST_TEXT << "Checking " << kData[n].name;
-      EXPECT_EQ(kData[n].offset, offset);
+      EXPECT_EQ(data.address, address) << "Checking " << data.name;
+      EXPECT_EQ(data.offset, offset) << "Checking " << data.name;
     }
   }
 }
@@ -184,29 +179,26 @@
   ProcMaps self_maps;
   ProcMaps::Entry entry;
 
-  for (size_t n = 0; n < ARRAY_LEN(kData); ++n) {
-    minitest::internal::String text =
-        minitest::Format("Checking entry #%d %p-%p",
-                         n + 1,
-                         kData[n].vma_start,
-                         kData[n].vma_end);
-    TEST_TEXT << text;
-    EXPECT_TRUE(self_maps.GetNextEntry(&entry));
-    TEST_TEXT << text;
-    EXPECT_EQ(kData[n].vma_start, entry.vma_start);
-    TEST_TEXT << text;
-    EXPECT_EQ(kData[n].vma_end, entry.vma_end);
-    TEST_TEXT << text;
-    EXPECT_EQ(kData[n].prot_flags, entry.prot_flags);
-    TEST_TEXT << text;
-    EXPECT_EQ(kData[n].load_offset, entry.load_offset);
+  size_t count = 0;
+  for (const auto& data : kData) {
+    std::string text = "Checking entry #";
+    text += std::to_string(++count);
+    text += " ";
+    text += std::to_string(data.vma_start);
+    text += "-";
+    text += std::to_string(data.vma_end);
 
-    if (!kData[n].path) {
-      TEST_TEXT << text;
-      EXPECT_FALSE(entry.path);
+    EXPECT_TRUE(self_maps.GetNextEntry(&entry)) << text;
+    EXPECT_EQ(data.vma_start, entry.vma_start) << text;
+    EXPECT_EQ(data.vma_end, entry.vma_end) << text;
+    EXPECT_EQ(data.prot_flags, entry.prot_flags) << text;
+    EXPECT_EQ(data.load_offset, entry.load_offset) << text;
+
+    if (!data.path) {
+      EXPECT_FALSE(entry.path) << text;
     } else {
-      EXPECT_MEMEQ(
-          kData[n].path, strlen(kData[n].path), entry.path, entry.path_len);
+      EXPECT_EQ(std::string(data.path), std::string(entry.path, entry.path_len))
+          << text;
     }
   }
   EXPECT_FALSE(self_maps.GetNextEntry(&entry));
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_search_path_list_unittest.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_search_path_list_unittest.cpp
index b4725ca..b51712a 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_search_path_list_unittest.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_search_path_list_unittest.cpp
@@ -4,7 +4,7 @@
 
 #include "crazy_linker_search_path_list.h"
 
-#include <minitest/minitest.h>
+#include <gtest/gtest.h>
 #include "crazy_linker_system_mock.h"
 
 namespace crazy {
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_system.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_system.cpp
index d676896..e1f3d4d9 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_system.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_system.cpp
@@ -18,10 +18,10 @@
 
 // Note: unit-testing support files are in crazy_linker_files_mock.cpp
 
-namespace crazy {
-
 #ifndef UNIT_TESTS
 
+namespace crazy {
+
 bool FileDescriptor::OpenReadOnly(const char* path) {
   Close();
   fd_ = TEMP_FAILURE_RETRY(::open(path, O_RDONLY));
@@ -96,8 +96,6 @@
   return S_ISREG(st.st_mode);
 }
 
-#endif  // !UNIT_TESTS
-
 }  // namespace crazy
 
 // Custom implementation of new and malloc, this prevents dragging
@@ -173,3 +171,5 @@
 void operator delete[](void* ptr) {
   ::free(ptr);
 }
+
+#endif  // !UNIT_TESTS
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_system_unittest.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_system_unittest.cpp
index 8bf082f..2fb7f9e 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_system_unittest.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_system_unittest.cpp
@@ -4,7 +4,7 @@
 
 #include "crazy_linker_system.h"
 
-#include <minitest/minitest.h>
+#include <gtest/gtest.h>
 #include <stdlib.h>
 #include "crazy_linker_system_mock.h"
 
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_thread_unittest.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_thread_unittest.cpp
index 5b9cd16..0e34e67 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_thread_unittest.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_thread_unittest.cpp
@@ -4,14 +4,13 @@
 
 #include "crazy_linker_thread.h"
 
-#include <minitest/minitest.h>
+#include <gtest/gtest.h>
 
 namespace crazy {
 
 TEST(Thread, GetThreadData) {
   ThreadData* data = GetThreadData();
-  TEST_TEXT << "Checking first GetThreadData() call";
-  EXPECT_TRUE(data);
+  EXPECT_TRUE(data) << "Checking first GetThreadData() call";
   EXPECT_EQ(data, GetThreadData());
   EXPECT_EQ(data, GetThreadDataFast());
 }
@@ -84,12 +83,11 @@
   const char* error = data->GetError();
   size_t error_len = strlen(error);
 
-  EXPECT_GT(0, error_len);
-  EXPECT_LT(kMaxCount * 10, error_len);
+  EXPECT_GT(error_len, 0U);
+  EXPECT_LT(error_len, kMaxCount * 10);
 
   for (size_t n = 0; n < error_len; ++n) {
-    TEST_TEXT << "Checking error[" << n << "]";
-    EXPECT_EQ('0' + (n % 10), error[n]);
+    EXPECT_EQ('0' + (n % 10), error[n]) << "Checking error[" << n << "]";
   }
 }
 
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_util_unittest.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_util_unittest.cpp
index 756bb3e..f375d71 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_util_unittest.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_util_unittest.cpp
@@ -4,7 +4,7 @@
 
 #include "crazy_linker_util.h"
 
-#include <minitest/minitest.h>
+#include <gtest/gtest.h>
 
 namespace crazy {
 
@@ -116,8 +116,7 @@
     v.PushBack(n * 100);
 
   for (int n = 0; n < kMaxCount; ++n) {
-    TEST_TEXT << "Checking v[" << n << "]";
-    EXPECT_EQ(n * 100, v[n]);
+    EXPECT_EQ(n * 100, v[n]) << "Checking v[" << n << "]";
   }
 }
 
@@ -128,8 +127,7 @@
     v.PushBack(n * 100);
 
   for (int n = 0; n < kMaxCount; ++n) {
-    TEST_TEXT << "Checking v.IndexOf(" << n * 100 << ")";
-    EXPECT_EQ(n, v.IndexOf(n * 100));
+    EXPECT_EQ(n, v.IndexOf(n * 100)) << "Checking v.IndexOf(" << n * 100 << ")";
   }
 }
 
@@ -145,7 +143,6 @@
 
     EXPECT_EQ(kMaxCount + 1, v.GetCount());
     for (int n = 0; n < v.GetCount(); ++n) {
-      TEST_TEXT << "Checking v[" << n << "]";
       int expected;
       if (n < k)
         expected = n * 100;
@@ -153,7 +150,7 @@
         expected = -1000;
       else
         expected = (n - 1) * 100;
-      EXPECT_EQ(expected, v[n]);
+      EXPECT_EQ(expected, v[n]) << "Checking v[" << n << "]";
     }
   }
 }
@@ -170,9 +167,8 @@
 
     EXPECT_EQ(kMaxCount - 1, v.GetCount());
     for (int n = 0; n < kMaxCount - 1; ++n) {
-      TEST_TEXT << "Checking v[" << n << "]";
       int expected = (n < k) ? (n * 100) : ((n + 1) * 100);
-      EXPECT_EQ(expected, v[n]);
+      EXPECT_EQ(expected, v[n]) << "Checking v[" << n << "]";
     }
   }
 }
@@ -185,9 +181,9 @@
 
   for (int n = 0; n < kMaxCount; ++n) {
     int first = v.PopFirst();
-    TEST_TEXT << "Checking " << n << "-th PopFirst()";
-    EXPECT_EQ(n * 100, first);
-    EXPECT_EQ(kMaxCount - 1 - n, v.GetCount());
+    EXPECT_EQ(n * 100, first) << "Checking " << n << "-th PopFirst()";
+    EXPECT_EQ(kMaxCount - 1 - n, v.GetCount())
+        << "Checking " << n << "-th PopFirst()";
   }
   EXPECT_EQ(0u, v.GetCount());
   EXPECT_TRUE(v.IsEmpty());
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp
index 5dcd6a8..3233c7b 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp
@@ -38,6 +38,7 @@
 
 namespace {
 
+#ifndef UNIT_TESTS
 // LLVM's demangler is large, and we have no need of it.  Overriding it with
 // our own stub version here stops a lot of code being pulled in from libc++.
 // This reduces the on-disk footprint of the crazy linker library by more than
@@ -55,6 +56,7 @@
     *status = kMemoryAllocFailure;
   return NULL;
 }
+#endif  // UNIT_TESTS
 
 #ifdef __arm__
 extern "C" int __cxa_atexit(void (*)(void*), void*, void*);
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index e063fc7..6c102457 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -5050,7 +5050,18 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="FocusInactivePopupForAccessibility">
+  <owner>dtseng@chromium.org</owner>
+  <description>
+    Places focus on non-modal UI such as info bars, bubble widgets for
+    accessibility.
+  </description>
+</action>
+
 <action name="FocusInfobars">
+  <obsolete>
+    No longer used. Generalized/renamed to FocusInactivePopupForAccessibility.
+  </obsolete>
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
 </action>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index d5e53be..6a7b87a 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -25684,6 +25684,7 @@
   <int value="-933316841" label="enable-permissions-blacklist"/>
   <int value="-928138978" label="IPH_DemoMode:disabled"/>
   <int value="-926422468" label="disable-embedded-shared-worker"/>
+  <int value="-920204598" label="ScrollAnchorSerialization:enabled"/>
   <int value="-918900957" label="AutofillCreditCardAssist:disabled"/>
   <int value="-918618075" label="enable-service-worker"/>
   <int value="-914210146" label="enable-web-based-signin"/>
@@ -26306,6 +26307,7 @@
   <int value="721225492" label="PolicyTool:enabled"/>
   <int value="723619383" label="TopSitesFromSiteEngagement:enabled"/>
   <int value="724208771" label="TabsInCBD:enabled"/>
+  <int value="725270017" label="ScrollAnchorSerialization:disabled"/>
   <int value="727571565" label="PasswordForceSaving"/>
   <int value="728656094" label="PasswordForceSaving:disabled"/>
   <int value="730024226" label="enable-out-of-process-pdf"/>
@@ -26534,6 +26536,7 @@
   <int value="1314681756" label="NoStatePrefetch:disabled"/>
   <int value="1317562265" label="SeccompSandboxAndroid:disabled"/>
   <int value="1318073661" label="MaterialDesignExtensions:enabled"/>
+  <int value="1319024729" label="ServiceWorkerServicification:disabled"/>
   <int value="1319068611" label="SecondaryUiMd:disabled"/>
   <int value="1319725131" label="enable-distance-field-text"/>
   <int value="1320201920" label="enable-touchpad-three-finger-click"/>
@@ -26720,6 +26723,7 @@
   <int value="1809940714" label="SpeculativeLaunchServiceWorker:disabled"/>
   <int value="1812368073" label="enable-new-app-list-mixer"/>
   <int value="1814671708" label="disable-password-manager-reauthentication"/>
+  <int value="1816843861" label="ServiceWorkerServicification:enabled"/>
   <int value="1817312143" label="num-raster-threads"/>
   <int value="1819256299" label="disable-webrtc-hw-decoding"/>
   <int value="1819536169" label="disable-cast-streaming-hw-encoding"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index f0955a06..1c012bb 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -95088,7 +95088,7 @@
   <owner>asvitkine@chromium.org</owner>
   <summary>
     The result of verifying the latest variations seed's signature, recorded
-    when the seed is loaded from Local State.  Not recorded when running in safe
+    when the seed is loaded from Local State. Not recorded when running in safe
     mode.
   </summary>
 </histogram>
@@ -95299,7 +95299,10 @@
   <owner>asvitkine@chromium.org</owner>
   <summary>
     The time interval between when the variations seed was downloaded and when
-    it was used. Not recorded for expired seeds.
+    it was loaded for use. Not recorded for expired seeds.
+
+    TODO(isherman): Implement this metric for safe seeds as well. (It's
+    currently not implemented; but also, safe mode is not triggerable.)
   </summary>
 </histogram>
 
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index 494bfda6..bbfa20e 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -227,7 +227,7 @@
 crbug.com/769809 [ All ] system_health.memory_desktop/browse_accessibility:tools:gmail_compose [ Skip ]
 crbug.com/673775 [ Win ] system_health.memory_desktop/browse:search:google [ Skip ]
 crbug.com/664661 [ Mac ] system_health.memory_desktop/load:games:miniclip [ Skip ]
-crbug.com/728464 [ Win ] system_health.memory_desktop/browse:social:twitter_infinite_scroll [ Skip ]
+crbug.com/728464 [ All ] system_health.memory_desktop/browse:social:twitter_infinite_scroll [ Skip ]
 crbug.com/799106 [ Win ] system_health.memory_desktop/browse:media:flickr_infinite_scroll [ Skip ]
 
 # Benchmark: system_health.memory_mobile
diff --git a/tools/traffic_annotation/scripts/check_annotations.py b/tools/traffic_annotation/scripts/check_annotations.py
index 7aa1420..f394a120 100755
--- a/tools/traffic_annotation/scripts/check_annotations.py
+++ b/tools/traffic_annotation/scripts/check_annotations.py
@@ -136,11 +136,15 @@
     """Gets the list of modified files from git. Returns None if any error
     happens."""
 
-    # List of files is extracted the same way as the following test recipe:
-    # https://cs.chromium.org/chromium/tools/depot_tools/recipes/recipe_modules/
-    # tryserver/api.py?l=66
+    # List of files is extracted almost the same way as the following test
+    # recipe: https://cs.chromium.org/chromium/tools/depot_tools/recipes/
+    # recipe_modules/tryserver/api.py
+    # '--no-renames' switch is added so that if a file is renamed, both old and
+    # new name would be given. Old name is needed to discard its data in
+    # annotations.xml and new name is needed for updating the XML and checking
+    # its content for possible changes.
     args = ["git.bat"] if sys.platform == "win32" else ["git"]
-    args += ["diff", "--cached", "--name-only"]
+    args += ["diff", "--cached", "--name-only", "--no-renames"]
 
     original_path = os.getcwd()
 
diff --git a/tools/v8_context_snapshot/v8_context_snapshot.gni b/tools/v8_context_snapshot/v8_context_snapshot.gni
index e53d7e2..04d498018 100644
--- a/tools/v8_context_snapshot/v8_context_snapshot.gni
+++ b/tools/v8_context_snapshot/v8_context_snapshot.gni
@@ -13,7 +13,12 @@
 
 declare_args() {
   # TODO(crbug.com/764576): Enable the feature on more environments.
-  use_v8_context_snapshot =
-      target_os != "chromeos" && target_os != "android" && !is_chromecast &&
-      v8_use_external_startup_data && (v8_target_cpu == target_cpu || is_msan)
+  use_v8_context_snapshot = !is_chromeos && !is_android && !is_chromecast &&
+                            !(host_os == "mac" && current_cpu == "x86") &&
+                            (v8_target_cpu == target_cpu || is_msan)
+}
+
+# We cannot use V8 context snapshot, if V8 doesn't use snapshot files.
+if (use_v8_context_snapshot && !v8_use_external_startup_data) {
+  use_v8_context_snapshot = false
 }
diff --git a/ui/app_list/views/app_list_main_view.cc b/ui/app_list/views/app_list_main_view.cc
index 73f1cef..fb39ff0 100644
--- a/ui/app_list/views/app_list_main_view.cc
+++ b/ui/app_list/views/app_list_main_view.cc
@@ -91,7 +91,7 @@
 }
 
 void AppListMainView::ResetForShow() {
-  contents_view_->SetActiveState(AppListModel::STATE_START);
+  contents_view_->SetActiveState(ash::AppListState::kStateStart);
   contents_view_->apps_container_view()->ResetForShowApps();
   // We clear the search when hiding so when app list appears it is not showing
   // search results.
diff --git a/ui/app_list/views/app_list_main_view_unittest.cc b/ui/app_list/views/app_list_main_view_unittest.cc
index 4da8b83..5c90a8a4 100644
--- a/ui/app_list/views/app_list_main_view_unittest.cc
+++ b/ui/app_list/views/app_list_main_view_unittest.cc
@@ -292,7 +292,7 @@
   AppListItemView* item1 = RootViewModel()->view_at(1);
 
   // Switch to All Apps page.
-  GetContentsView()->SetActiveState(AppListModel::STATE_APPS);
+  GetContentsView()->SetActiveState(ash::AppListState::kStateApps);
   GetContentsView()->Layout();
 
   generator.MoveMouseTo(item0->GetBoundsInScreen().CenterPoint());
@@ -323,7 +323,7 @@
   AppListItemView* item = RootViewModel()->view_at(0);
 
   // Switch to All Apps page.
-  GetContentsView()->SetActiveState(AppListModel::STATE_APPS);
+  GetContentsView()->SetActiveState(ash::AppListState::kStateApps);
   GetContentsView()->Layout();
 
   generator.set_current_location(item->GetBoundsInScreen().CenterPoint());
@@ -396,7 +396,7 @@
 
   // Ensure we are on the apps grid view page.
   app_list::ContentsView* contents_view = GetContentsView();
-  contents_view->SetActiveState(AppListModel::STATE_APPS);
+  contents_view->SetActiveState(ash::AppListState::kStateApps);
   contents_view->Layout();
 
   AppListItemView* folder_item_view = CreateAndOpenSingleItemFolder();
diff --git a/ui/app_list/views/app_list_page.cc b/ui/app_list/views/app_list_page.cc
index 77da2c3..0d8912e 100644
--- a/ui/app_list/views/app_list_page.cc
+++ b/ui/app_list/views/app_list_page.cc
@@ -21,8 +21,8 @@
 void AppListPage::OnWillBeHidden() {}
 
 void AppListPage::OnAnimationUpdated(double progress,
-                                     AppListModel::State from_state,
-                                     AppListModel::State to_state) {}
+                                     ash::AppListState from_state,
+                                     ash::AppListState to_state) {}
 
 gfx::Rect AppListPage::GetSearchBoxBounds() const {
   DCHECK(contents_view_);
@@ -30,12 +30,12 @@
 }
 
 gfx::Rect AppListPage::GetSearchBoxBoundsForState(
-    AppListModel::State state) const {
+    ash::AppListState state) const {
   return GetSearchBoxBounds();
 }
 
 gfx::Rect AppListPage::GetPageBoundsDuringDragging(
-    AppListModel::State state) const {
+    ash::AppListState state) const {
   return GetPageBoundsForState(state);
 }
 
diff --git a/ui/app_list/views/app_list_page.h b/ui/app_list/views/app_list_page.h
index efc8bba..35c1712 100644
--- a/ui/app_list/views/app_list_page.h
+++ b/ui/app_list/views/app_list_page.h
@@ -30,22 +30,21 @@
 
   // Triggered after the animation has updated.
   virtual void OnAnimationUpdated(double progress,
-                                  AppListModel::State from_state,
-                                  AppListModel::State to_state);
+                                  ash::AppListState from_state,
+                                  ash::AppListState to_state);
 
   // Returns where the search box should be when this page is shown. Is at the
   // top of the app list by default, in the contents view's coordinate space.
   virtual gfx::Rect GetSearchBoxBounds() const;
 
   // Returns the bounds of the search box according to |state|.
-  virtual gfx::Rect GetSearchBoxBoundsForState(AppListModel::State state) const;
+  virtual gfx::Rect GetSearchBoxBoundsForState(ash::AppListState state) const;
 
   // Returns where this page should move to when the given state is active.
-  virtual gfx::Rect GetPageBoundsForState(AppListModel::State state) const = 0;
+  virtual gfx::Rect GetPageBoundsForState(ash::AppListState state) const = 0;
 
   // Returns the bounds of the page during dragging.
-  virtual gfx::Rect GetPageBoundsDuringDragging(
-      AppListModel::State state) const;
+  virtual gfx::Rect GetPageBoundsDuringDragging(ash::AppListState state) const;
 
   const ContentsView* contents_view() const { return contents_view_; }
   void set_contents_view(ContentsView* contents_view) {
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc
index b6fea2af..bbbdbc6 100644
--- a/ui/app_list/views/app_list_view.cc
+++ b/ui/app_list/views/app_list_view.cc
@@ -695,7 +695,7 @@
 
   if (target_state == AppListViewState::PEEKING) {
     app_list_main_view_->contents_view()->SetActiveState(
-        AppListModel::STATE_START);
+        ash::AppListState::kStateStart);
     // Set the apps to first page at STATE_START state.
     PaginationModel* pagination_model = GetAppsPaginationModel();
     if (pagination_model->total_pages() > 0 &&
@@ -707,7 +707,7 @@
     GetRootAppsGridView()->StartTimerToIgnoreScrollEvents();
 
     app_list_main_view_->contents_view()->SetActiveState(
-        AppListModel::STATE_APPS, !is_side_shelf_);
+        ash::AppListState::kStateApps, !is_side_shelf_);
   }
 }
 
@@ -1173,7 +1173,7 @@
       if (search_box_is_empty) {
         SetState(AppListViewState::FULLSCREEN_ALL_APPS);
         app_list_main_view()->contents_view()->SetActiveState(
-            AppListModel::State::STATE_APPS);
+            ash::AppListState::kStateApps);
       }
       break;
     case AppListViewState::FULLSCREEN_ALL_APPS:
diff --git a/ui/app_list/views/app_list_view_unittest.cc b/ui/app_list/views/app_list_view_unittest.cc
index c090f1b..ff49462 100644
--- a/ui/app_list/views/app_list_view_unittest.cc
+++ b/ui/app_list/views/app_list_view_unittest.cc
@@ -117,7 +117,7 @@
   // Switches the launcher to |state| and lays out to ensure all launcher pages
   // are in the correct position. Checks that the state is where it should be
   // and returns false on failure.
-  bool SetAppListState(AppListModel::State state) {
+  bool SetAppListState(ash::AppListState state) {
     ContentsView* contents_view = view_->app_list_main_view()->contents_view();
     contents_view->SetActiveState(state);
     contents_view->Layout();
@@ -125,7 +125,7 @@
   }
 
   // Returns true if all of the pages are in their correct position for |state|.
-  bool IsStateShown(AppListModel::State state) {
+  bool IsStateShown(ash::AppListState state) {
     ContentsView* contents_view = view_->app_list_main_view()->contents_view();
     bool success = true;
     for (int i = 0; i < contents_view->NumLauncherPages(); ++i) {
@@ -1517,21 +1517,21 @@
       ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 0, delta_y));
   view_->OnGestureEvent(&update_event);
 
-  EXPECT_TRUE(IsStateShown(AppListModel::STATE_APPS));
+  EXPECT_TRUE(IsStateShown(ash::AppListState::kStateApps));
   EXPECT_EQ(kSearchBoxBorderCornerRadius,
             search_box_view()->GetSearchBoxBorderCornerRadiusForState(
-                AppListModel::STATE_APPS));
+                ash::AppListState::kStateApps));
 
   // Search box should keep |kSearchBoxCornerRadiusFullscreen| corner radius
   // during drag.
-  EXPECT_TRUE(SetAppListState(AppListModel::STATE_SEARCH_RESULTS));
+  EXPECT_TRUE(SetAppListState(ash::AppListState::kStateSearchResults));
   EXPECT_TRUE(view_->is_in_drag());
   EXPECT_EQ(kSearchBoxBorderCornerRadius,
             search_box_view()->GetSearchBoxBorderCornerRadiusForState(
-                AppListModel::STATE_SEARCH_RESULTS));
+                ash::AppListState::kStateSearchResults));
 
   // Ends to drag the launcher.
-  EXPECT_TRUE(SetAppListState(AppListModel::STATE_APPS));
+  EXPECT_TRUE(SetAppListState(ash::AppListState::kStateApps));
   timestamp += base::TimeDelta::FromMilliseconds(25);
   ui::GestureEvent end_event =
       ui::GestureEvent(start.x(), start.y() + delta_y, ui::EF_NONE, timestamp,
@@ -1543,7 +1543,7 @@
   EXPECT_FALSE(view_->is_in_drag());
   EXPECT_EQ(kSearchBoxBorderCornerRadius,
             search_box_view()->GetSearchBoxBorderCornerRadiusForState(
-                AppListModel::STATE_APPS));
+                ash::AppListState::kStateApps));
 }
 
 // Tests displaying the app list and performs a standard set of checks on its
@@ -1566,7 +1566,7 @@
   EXPECT_NO_FATAL_FAILURE(CheckView(main_view));
   EXPECT_NO_FATAL_FAILURE(CheckView(main_view->contents_view()));
 
-  AppListModel::State expected = AppListModel::STATE_START;
+  ash::AppListState expected = ash::AppListState::kStateStart;
   EXPECT_TRUE(main_view->contents_view()->IsStateActive(expected));
   EXPECT_EQ(expected, delegate_->GetModel()->state());
 }
@@ -1596,7 +1596,7 @@
   EXPECT_NO_FATAL_FAILURE(CheckView(start_page_view));
 
   // Show the start page view.
-  EXPECT_TRUE(SetAppListState(AppListModel::STATE_START));
+  EXPECT_TRUE(SetAppListState(ash::AppListState::kStateStart));
   gfx::Size view_size(view_->GetPreferredSize());
 
   // Hiding and showing the search box should not affect the app list's
@@ -1604,7 +1604,7 @@
   EXPECT_EQ(view_size.ToString(), view_->GetPreferredSize().ToString());
 
   // Check tiles hide and show on deletion and addition.
-  EXPECT_TRUE(SetAppListState(AppListModel::STATE_START));
+  EXPECT_TRUE(SetAppListState(ash::AppListState::kStateStart));
   model->results()->Add(std::make_unique<TestStartPageSearchResult>());
   start_page_view->UpdateForTesting();
   EXPECT_EQ(1u, GetVisibleViews(start_page_view->tile_views()));
@@ -1614,11 +1614,11 @@
 
   // Tiles should not update when the start page is not active but should be
   // correct once the start page is shown.
-  EXPECT_TRUE(SetAppListState(AppListModel::STATE_APPS));
+  EXPECT_TRUE(SetAppListState(ash::AppListState::kStateApps));
   model->results()->Add(std::make_unique<TestStartPageSearchResult>());
   start_page_view->UpdateForTesting();
   EXPECT_EQ(0u, GetVisibleViews(start_page_view->tile_views()));
-  EXPECT_TRUE(SetAppListState(AppListModel::STATE_START));
+  EXPECT_TRUE(SetAppListState(ash::AppListState::kStateStart));
   EXPECT_EQ(1u, GetVisibleViews(start_page_view->tile_views()));
 #endif
 }
@@ -1633,23 +1633,23 @@
 
   ContentsView* contents_view = main_view->contents_view();
 
-  contents_view->SetActiveState(AppListModel::STATE_START);
+  contents_view->SetActiveState(ash::AppListState::kStateStart);
   contents_view->Layout();
 
-  IsStateShown(AppListModel::STATE_START);
+  IsStateShown(ash::AppListState::kStateStart);
 
   // Change pages. View should not have moved without Layout().
-  contents_view->SetActiveState(AppListModel::STATE_SEARCH_RESULTS);
-  IsStateShown(AppListModel::STATE_START);
+  contents_view->SetActiveState(ash::AppListState::kStateSearchResults);
+  IsStateShown(ash::AppListState::kStateStart);
 
   // Change to a third page. This queues up the second animation behind the
   // first.
-  contents_view->SetActiveState(AppListModel::STATE_APPS);
-  IsStateShown(AppListModel::STATE_START);
+  contents_view->SetActiveState(ash::AppListState::kStateApps);
+  IsStateShown(ash::AppListState::kStateStart);
 
   // Call Layout(). Should jump to the third page.
   contents_view->Layout();
-  IsStateShown(AppListModel::STATE_APPS);
+  IsStateShown(ash::AppListState::kStateApps);
 }
 
 // Tests that the correct views are displayed for showing search results.
@@ -1669,26 +1669,27 @@
 
   AppListMainView* main_view = view_->app_list_main_view();
   ContentsView* contents_view = main_view->contents_view();
-  EXPECT_TRUE(SetAppListState(AppListModel::STATE_APPS));
+  EXPECT_TRUE(SetAppListState(ash::AppListState::kStateApps));
 
   // Show the search results.
   contents_view->ShowSearchResults(true);
   contents_view->Layout();
-  EXPECT_TRUE(contents_view->IsStateActive(AppListModel::STATE_SEARCH_RESULTS));
+  EXPECT_TRUE(
+      contents_view->IsStateActive(ash::AppListState::kStateSearchResults));
 
-  EXPECT_TRUE(IsStateShown(AppListModel::STATE_SEARCH_RESULTS));
+  EXPECT_TRUE(IsStateShown(ash::AppListState::kStateSearchResults));
 
   // Hide the search results.
   contents_view->ShowSearchResults(false);
   contents_view->Layout();
 
   // Check that we return to the page that we were on before the search.
-  EXPECT_TRUE(IsStateShown(AppListModel::STATE_APPS));
+  EXPECT_TRUE(IsStateShown(ash::AppListState::kStateApps));
 
   // Check that typing into the search box triggers the search page.
-  EXPECT_TRUE(SetAppListState(AppListModel::STATE_START));
+  EXPECT_TRUE(SetAppListState(ash::AppListState::kStateStart));
   view_->Layout();
-  EXPECT_TRUE(IsStateShown(AppListModel::STATE_START));
+  EXPECT_TRUE(IsStateShown(ash::AppListState::kStateStart));
 
   base::string16 search_text = base::UTF8ToUTF16("test");
   main_view->search_box_view()->search_box()->SetText(base::string16());
@@ -1697,13 +1698,14 @@
   EXPECT_EQ(search_text, delegate_->GetSearchModel()->search_box()->text());
   EXPECT_EQ(search_text, main_view->search_box_view()->search_box()->text());
   contents_view->Layout();
-  EXPECT_TRUE(contents_view->IsStateActive(AppListModel::STATE_SEARCH_RESULTS));
+  EXPECT_TRUE(
+      contents_view->IsStateActive(ash::AppListState::kStateSearchResults));
   EXPECT_TRUE(CheckSearchBoxWidget(contents_view->GetDefaultSearchBoxBounds()));
 
   // Check that typing into the search box triggers the search page.
-  EXPECT_TRUE(SetAppListState(AppListModel::STATE_APPS));
+  EXPECT_TRUE(SetAppListState(ash::AppListState::kStateApps));
   contents_view->Layout();
-  EXPECT_TRUE(IsStateShown(AppListModel::STATE_APPS));
+  EXPECT_TRUE(IsStateShown(ash::AppListState::kStateApps));
   EXPECT_TRUE(CheckSearchBoxWidget(contents_view->GetDefaultSearchBoxBounds()));
 
   base::string16 new_search_text = base::UTF8ToUTF16("apple");
@@ -1714,7 +1716,7 @@
   EXPECT_EQ(new_search_text,
             main_view->search_box_view()->search_box()->text());
   contents_view->Layout();
-  EXPECT_TRUE(IsStateShown(AppListModel::STATE_SEARCH_RESULTS));
+  EXPECT_TRUE(IsStateShown(ash::AppListState::kStateSearchResults));
   EXPECT_TRUE(CheckSearchBoxWidget(contents_view->GetDefaultSearchBoxBounds()));
 }
 
@@ -1736,23 +1738,23 @@
   SearchBoxView* search_box_view = main_view->search_box_view();
 
   // Show the apps grid.
-  SetAppListState(AppListModel::STATE_APPS);
+  SetAppListState(ash::AppListState::kStateApps);
   EXPECT_NO_FATAL_FAILURE(CheckView(search_box_view->back_button()));
 
   // The back button should return to the start page.
   EXPECT_TRUE(contents_view->Back());
   contents_view->Layout();
-  EXPECT_TRUE(IsStateShown(AppListModel::STATE_START));
+  EXPECT_TRUE(IsStateShown(ash::AppListState::kStateStart));
   EXPECT_FALSE(search_box_view->back_button()->visible());
 
   // Show the apps grid again.
-  SetAppListState(AppListModel::STATE_APPS);
+  SetAppListState(ash::AppListState::kStateApps);
   EXPECT_NO_FATAL_FAILURE(CheckView(search_box_view->back_button()));
 
   // Pressing ESC should return to the start page.
   view_->AcceleratorPressed(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
   contents_view->Layout();
-  EXPECT_TRUE(IsStateShown(AppListModel::STATE_START));
+  EXPECT_TRUE(IsStateShown(ash::AppListState::kStateStart));
   EXPECT_FALSE(search_box_view->back_button()->visible());
 
   // Pressing ESC from the start page should close the app list.
@@ -1765,13 +1767,13 @@
   search_box_view->search_box()->SetText(base::string16());
   search_box_view->search_box()->InsertText(new_search_text);
   contents_view->Layout();
-  EXPECT_TRUE(IsStateShown(AppListModel::STATE_SEARCH_RESULTS));
+  EXPECT_TRUE(IsStateShown(ash::AppListState::kStateSearchResults));
   EXPECT_NO_FATAL_FAILURE(CheckView(search_box_view->back_button()));
 
   // The back button should return to the start page.
   EXPECT_TRUE(contents_view->Back());
   contents_view->Layout();
-  EXPECT_TRUE(IsStateShown(AppListModel::STATE_START));
+  EXPECT_TRUE(IsStateShown(ash::AppListState::kStateStart));
   EXPECT_FALSE(search_box_view->back_button()->visible());
 }
 
diff --git a/ui/app_list/views/apps_container_view.cc b/ui/app_list/views/apps_container_view.cc
index 3fc0a24..32f14d0 100644
--- a/ui/app_list/views/apps_container_view.cc
+++ b/ui/app_list/views/apps_container_view.cc
@@ -231,7 +231,7 @@
 }
 
 gfx::Rect AppsContainerView::GetSearchBoxBoundsForState(
-    AppListModel::State state) const {
+    ash::AppListState state) const {
   gfx::Rect search_box_bounds(contents_view()->GetDefaultSearchBoxBounds());
   bool is_in_drag = false;
   if (contents_view()->app_list_view())
@@ -239,7 +239,7 @@
   if (is_in_drag) {
     search_box_bounds.set_y(GetSearchBoxTopPaddingDuringDragging());
   } else {
-    if (state == AppListModel::STATE_START)
+    if (state == ash::AppListState::kStateStart)
       search_box_bounds.set_y(kSearchBoxPeekingTopPadding);
     else
       search_box_bounds.set_y(GetSearchBoxFinalTopPadding());
@@ -249,13 +249,14 @@
 }
 
 gfx::Rect AppsContainerView::GetPageBoundsForState(
-    AppListModel::State state) const {
+    ash::AppListState state) const {
   gfx::Rect onscreen_bounds = GetDefaultContentsBounds();
 
   // Both STATE_START and STATE_APPS are AppsContainerView page.
-  if (state == AppListModel::STATE_APPS || state == AppListModel::STATE_START) {
+  if (state == ash::AppListState::kStateApps ||
+      state == ash::AppListState::kStateStart) {
     int y = GetSearchBoxBoundsForState(state).bottom();
-    if (state == AppListModel::STATE_START)
+    if (state == ash::AppListState::kStateStart)
       y -= (kSearchBoxBottomPadding - kSearchBoxPeekingBottomPadding);
     onscreen_bounds.set_y(y);
     return onscreen_bounds;
@@ -265,7 +266,7 @@
 }
 
 gfx::Rect AppsContainerView::GetPageBoundsDuringDragging(
-    AppListModel::State state) const {
+    ash::AppListState state) const {
   float app_list_y_position_in_screen =
       contents_view()->app_list_view()->app_list_y_position_in_screen();
   float drag_amount =
@@ -301,7 +302,8 @@
 
   gfx::Rect onscreen_bounds = GetPageBoundsForState(state);
   // Both STATE_START and STATE_APPS are AppsContainerView page.
-  if (state == AppListModel::STATE_APPS || state == AppListModel::STATE_START)
+  if (state == ash::AppListState::kStateApps ||
+      state == ash::AppListState::kStateStart)
     onscreen_bounds.set_y(y);
 
   return onscreen_bounds;
diff --git a/ui/app_list/views/apps_container_view.h b/ui/app_list/views/apps_container_view.h
index 400823aa..b335d45 100644
--- a/ui/app_list/views/apps_container_view.h
+++ b/ui/app_list/views/apps_container_view.h
@@ -84,11 +84,9 @@
   void OnWillBeShown() override;
   void OnWillBeHidden() override;
   gfx::Rect GetSearchBoxBounds() const override;
-  gfx::Rect GetSearchBoxBoundsForState(
-      AppListModel::State state) const override;
-  gfx::Rect GetPageBoundsForState(AppListModel::State state) const override;
-  gfx::Rect GetPageBoundsDuringDragging(
-      AppListModel::State state) const override;
+  gfx::Rect GetSearchBoxBoundsForState(ash::AppListState state) const override;
+  gfx::Rect GetPageBoundsForState(ash::AppListState state) const override;
+  gfx::Rect GetPageBoundsDuringDragging(ash::AppListState state) const override;
   views::View* GetSelectedView() const override;
 
   // TopIconAnimationObserver overrides:
diff --git a/ui/app_list/views/apps_grid_view.cc b/ui/app_list/views/apps_grid_view.cc
index eba96767..382be07 100644
--- a/ui/app_list/views/apps_grid_view.cc
+++ b/ui/app_list/views/apps_grid_view.cc
@@ -957,7 +957,7 @@
 
 void AppsGridView::OnGestureEvent(ui::GestureEvent* event) {
   // Bail on STATE_START or no apps page to make PaginationModel happy.
-  if (contents_view_->GetActiveState() == AppListModel::STATE_START ||
+  if (contents_view_->GetActiveState() == ash::AppListState::kStateStart ||
       pagination_model_.total_pages() <= 0) {
     return;
   }
@@ -1065,7 +1065,7 @@
     return false;
 
   // Bail on STATE_START or no apps page to make PaginationModel happy.
-  if (contents_view_->GetActiveState() == AppListModel::STATE_START ||
+  if (contents_view_->GetActiveState() == ash::AppListState::kStateStart ||
       pagination_model_.total_pages() <= 0) {
     return false;
   }
diff --git a/ui/app_list/views/contents_view.cc b/ui/app_list/views/contents_view.cc
index 627079e3..c532c165 100644
--- a/ui/app_list/views/contents_view.cc
+++ b/ui/app_list/views/contents_view.cc
@@ -68,7 +68,7 @@
 
   // Add |apps_container_view_| as STATE_START corresponding page for
   // fullscreen app list.
-  AddLauncherPage(apps_container_view_, AppListModel::STATE_START);
+  AddLauncherPage(apps_container_view_, ash::AppListState::kStateStart);
 
   // Search results UI.
   search_results_page_view_ = new SearchResultPageView();
@@ -96,11 +96,11 @@
       results, search_result_list_view_);
 
   AddLauncherPage(search_results_page_view_,
-                  AppListModel::STATE_SEARCH_RESULTS);
+                  ash::AppListState::kStateSearchResults);
 
-  AddLauncherPage(apps_container_view_, AppListModel::STATE_APPS);
+  AddLauncherPage(apps_container_view_, ash::AppListState::kStateApps);
 
-  int initial_page_index = GetPageIndexForState(AppListModel::STATE_START);
+  int initial_page_index = GetPageIndexForState(ash::AppListState::kStateStart);
   DCHECK_GE(initial_page_index, 0);
 
   page_before_search_ = initial_page_index;
@@ -133,11 +133,11 @@
   apps_container_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host);
 }
 
-void ContentsView::SetActiveState(AppListModel::State state) {
+void ContentsView::SetActiveState(ash::AppListState state) {
   SetActiveState(state, true);
 }
 
-void ContentsView::SetActiveState(AppListModel::State state, bool animate) {
+void ContentsView::SetActiveState(ash::AppListState state, bool animate) {
   if (IsStateActive(state))
     return;
 
@@ -149,19 +149,19 @@
   return pagination_model_.SelectedTargetPage();
 }
 
-AppListModel::State ContentsView::GetActiveState() const {
+ash::AppListState ContentsView::GetActiveState() const {
   return GetStateForPageIndex(GetActivePageIndex());
 }
 
-bool ContentsView::IsStateActive(AppListModel::State state) const {
+bool ContentsView::IsStateActive(ash::AppListState state) const {
   int active_page_index = GetActivePageIndex();
   return active_page_index >= 0 &&
          GetPageIndexForState(state) == active_page_index;
 }
 
-int ContentsView::GetPageIndexForState(AppListModel::State state) const {
+int ContentsView::GetPageIndexForState(ash::AppListState state) const {
   // Find the index of the view corresponding to the given state.
-  std::map<AppListModel::State, int>::const_iterator it =
+  std::map<ash::AppListState, int>::const_iterator it =
       state_to_view_.find(state);
   if (it == state_to_view_.end())
     return -1;
@@ -169,11 +169,11 @@
   return it->second;
 }
 
-AppListModel::State ContentsView::GetStateForPageIndex(int index) const {
-  std::map<int, AppListModel::State>::const_iterator it =
+ash::AppListState ContentsView::GetStateForPageIndex(int index) const {
+  std::map<int, ash::AppListState>::const_iterator it =
       view_to_state_.find(index);
   if (it == view_to_state_.end())
-    return AppListModel::INVALID_STATE;
+    return ash::AppListState::kInvalidState;
 
   return it->second;
 }
@@ -202,9 +202,9 @@
 }
 
 void ContentsView::ActivePageChanged() {
-  AppListModel::State state = AppListModel::INVALID_STATE;
+  ash::AppListState state = ash::AppListState::kInvalidState;
 
-  std::map<int, AppListModel::State>::const_iterator it =
+  std::map<int, ash::AppListState>::const_iterator it =
       view_to_state_.find(GetActivePageIndex());
   if (it != view_to_state_.end())
     state = it->second;
@@ -215,14 +215,15 @@
 }
 
 void ContentsView::ShowSearchResults(bool show) {
-  int search_page = GetPageIndexForState(AppListModel::STATE_SEARCH_RESULTS);
+  int search_page =
+      GetPageIndexForState(ash::AppListState::kStateSearchResults);
   DCHECK_GE(search_page, 0);
 
   SetActiveStateInternal(show ? search_page : page_before_search_, show, true);
 }
 
 bool ContentsView::IsShowingSearchResults() const {
-  return IsStateActive(AppListModel::STATE_SEARCH_RESULTS);
+  return IsStateActive(ash::AppListState::kStateSearchResults);
 }
 
 void ContentsView::UpdatePageBounds() {
@@ -240,8 +241,8 @@
     }
   }
 
-  AppListModel::State current_state = GetStateForPageIndex(current_page);
-  AppListModel::State target_state = GetStateForPageIndex(target_page);
+  ash::AppListState current_state = GetStateForPageIndex(current_page);
+  ash::AppListState target_state = GetStateForPageIndex(target_page);
 
   // Update app list pages.
   for (AppListPage* page : app_list_pages_) {
@@ -263,8 +264,8 @@
 }
 
 void ContentsView::UpdateSearchBox(double progress,
-                                   AppListModel::State current_state,
-                                   AppListModel::State target_state) {
+                                   ash::AppListState current_state,
+                                   ash::AppListState target_state) {
   AppListPage* from_page = GetPageView(GetPageIndexForState(current_state));
   AppListPage* to_page = GetPageView(GetPageIndexForState(target_state));
 
@@ -306,8 +307,7 @@
   return app_list_pages_.size() - 1;
 }
 
-int ContentsView::AddLauncherPage(AppListPage* view,
-                                  AppListModel::State state) {
+int ContentsView::AddLauncherPage(AppListPage* view, ash::AppListState state) {
   int page_index = AddLauncherPage(view);
   bool success =
       state_to_view_.insert(std::make_pair(state, page_index)).second;
@@ -329,7 +329,7 @@
 }
 
 gfx::Rect ContentsView::GetSearchBoxBoundsForState(
-    AppListModel::State state) const {
+    ash::AppListState state) const {
   AppListPage* page = GetPageView(GetPageIndexForState(state));
   return page->GetSearchBoxBoundsForState(state);
 }
@@ -353,25 +353,25 @@
 }
 
 bool ContentsView::Back() {
-  AppListModel::State state = view_to_state_[GetActivePageIndex()];
+  ash::AppListState state = view_to_state_[GetActivePageIndex()];
   switch (state) {
-    case AppListModel::STATE_START:
+    case ash::AppListState::kStateStart:
       // Close the app list when Back() is called from the start page.
       return false;
-    case AppListModel::STATE_APPS:
+    case ash::AppListState::kStateApps:
       if (apps_container_view_->IsInFolderView()) {
         apps_container_view_->app_list_folder_view()->CloseFolderPage();
       } else {
         app_list_view_->Dismiss();
       }
       break;
-    case AppListModel::STATE_SEARCH_RESULTS:
+    case ash::AppListState::kStateSearchResults:
       GetSearchBoxView()->ClearSearch();
       GetSearchBoxView()->SetSearchBoxActive(false);
       ShowSearchResults(false);
       break;
-    case AppListModel::STATE_CUSTOM_LAUNCHER_PAGE_DEPRECATED:
-    case AppListModel::INVALID_STATE:  // Falls through.
+    case ash::AppListState::kStateCustomLauncherPageDeprecated:
+    case ash::AppListState::kInvalidState:  // Falls through.
       NOTREACHED();
       break;
   }
diff --git a/ui/app_list/views/contents_view.h b/ui/app_list/views/contents_view.h
index 4f3226b..dfa8082 100644
--- a/ui/app_list/views/contents_view.h
+++ b/ui/app_list/views/contents_view.h
@@ -72,25 +72,25 @@
   void ShowFolderContent(AppListFolderItem* folder);
 
   // Sets the active launcher page and animates the pages into place.
-  void SetActiveState(AppListModel::State state);
-  void SetActiveState(AppListModel::State state, bool animate);
+  void SetActiveState(ash::AppListState state);
+  void SetActiveState(ash::AppListState state, bool animate);
 
   // The index of the currently active launcher page.
   int GetActivePageIndex() const;
 
   // The currently active state.
-  AppListModel::State GetActiveState() const;
+  ash::AppListState GetActiveState() const;
 
   // True if |state| is the current active laucher page.
-  bool IsStateActive(AppListModel::State state) const;
+  bool IsStateActive(ash::AppListState state) const;
 
   // Gets the index of a launcher page in |view_model_|, by State. Returns
   // -1 if there is no view for |state|.
-  int GetPageIndexForState(AppListModel::State state) const;
+  int GetPageIndexForState(ash::AppListState state) const;
 
   // Gets the state of a launcher page in |view_model_|, by index. Returns
   // INVALID_STATE if there is no state for |index|.
-  AppListModel::State GetStateForPageIndex(int index) const;
+  ash::AppListState GetStateForPageIndex(int index) const;
 
   int NumLauncherPages() const;
 
@@ -126,7 +126,7 @@
   gfx::Rect GetDefaultSearchBoxBounds() const;
 
   // Returns search box bounds to use for a given state.
-  gfx::Rect GetSearchBoxBoundsForState(AppListModel::State state) const;
+  gfx::Rect GetSearchBoxBoundsForState(ash::AppListState state) const;
 
   // Returns the content area bounds to use for content views that do not
   // specify their own custom layout.
@@ -181,8 +181,8 @@
   void UpdatePageBounds();
 
   void UpdateSearchBox(double progress,
-                       AppListModel::State current_state,
-                       AppListModel::State target_state);
+                       ash::AppListState current_state,
+                       ash::AppListState target_state);
 
   // Adds |view| as a new page to the end of the list of launcher pages. The
   // view is inserted as a child of the ContentsView. There is no name
@@ -192,7 +192,7 @@
   // Adds |view| as a new page to the end of the list of launcher pages. The
   // view is inserted as a child of the ContentsView. The page is associated
   // with the name |state|. Returns the index of the new page.
-  int AddLauncherPage(AppListPage* view, AppListModel::State state);
+  int AddLauncherPage(AppListPage* view, ash::AppListState state);
 
   // Gets the PaginationModel owned by the AppsGridView.
   // Note: This is different to |pagination_model_|, which manages top-level
@@ -219,10 +219,10 @@
   AppListView* const app_list_view_;
 
   // Maps State onto |view_model_| indices.
-  std::map<AppListModel::State, int> state_to_view_;
+  std::map<ash::AppListState, int> state_to_view_;
 
   // Maps |view_model_| indices onto State.
-  std::map<int, AppListModel::State> view_to_state_;
+  std::map<int, ash::AppListState> view_to_state_;
 
   // The page that was showing before ShowSearchResults(true) was invoked.
   int page_before_search_ = 0;
diff --git a/ui/app_list/views/expand_arrow_view.cc b/ui/app_list/views/expand_arrow_view.cc
index 02ada452..cb1ff3ed 100644
--- a/ui/app_list/views/expand_arrow_view.cc
+++ b/ui/app_list/views/expand_arrow_view.cc
@@ -4,6 +4,9 @@
 
 #include "ui/app_list/views/expand_arrow_view.h"
 
+#include <memory>
+#include <utility>
+
 #include "base/bind.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -251,11 +254,11 @@
 }
 
 void ExpandArrowView::TransitToFullscreenAllAppsState() {
-  UMA_HISTOGRAM_ENUMERATION(kPageOpenedHistogram, AppListModel::STATE_APPS,
-                            AppListModel::STATE_LAST);
+  UMA_HISTOGRAM_ENUMERATION(kPageOpenedHistogram, ash::AppListState::kStateApps,
+                            ash::AppListState::kStateLast);
   UMA_HISTOGRAM_ENUMERATION(kAppListPeekingToFullscreenHistogram, kExpandArrow,
                             kMaxPeekingToFullscreen);
-  contents_view_->SetActiveState(AppListModel::STATE_APPS);
+  contents_view_->SetActiveState(ash::AppListState::kStateApps);
   app_list_view_->SetState(AppListViewState::FULLSCREEN_ALL_APPS);
 }
 
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc
index b1b5c342..4759118 100644
--- a/ui/app_list/views/search_box_view.cc
+++ b/ui/app_list/views/search_box_view.cc
@@ -79,8 +79,8 @@
     SkColorSetARGBMacro(0x8A, 0x00, 0x00, 0x00);
 
 // Gets the box layout inset horizontal padding for the state of AppListModel.
-int GetBoxLayoutPaddingForState(AppListModel::State state) {
-  if (state == AppListModel::STATE_SEARCH_RESULTS)
+int GetBoxLayoutPaddingForState(ash::AppListState state) {
+  if (state == ash::AppListState::kStateSearchResults)
     return kPaddingSearchResult;
   return kPadding;
 }
@@ -470,8 +470,8 @@
 }
 
 void SearchBoxView::UpdateBackground(double progress,
-                                     AppListModel::State current_state,
-                                     AppListModel::State target_state) {
+                                     ash::AppListState current_state,
+                                     ash::AppListState target_state) {
   GetSearchBoxBackground()->set_corner_radius(gfx::Tween::LinearIntValueBetween(
       progress, GetSearchBoxBorderCornerRadiusForState(current_state),
       GetSearchBoxBorderCornerRadiusForState(target_state)));
@@ -482,8 +482,8 @@
 }
 
 void SearchBoxView::UpdateLayout(double progress,
-                                 AppListModel::State current_state,
-                                 AppListModel::State target_state) {
+                                 ash::AppListState current_state,
+                                 ash::AppListState target_state) {
   box_layout_->set_inside_border_insets(
       gfx::Insets(0, gfx::Tween::LinearIntValueBetween(
                          progress, GetBoxLayoutPaddingForState(current_state),
@@ -497,8 +497,8 @@
 }
 
 int SearchBoxView::GetSearchBoxBorderCornerRadiusForState(
-    AppListModel::State state) const {
-  if (state == AppListModel::STATE_SEARCH_RESULTS &&
+    ash::AppListState state) const {
+  if (state == ash::AppListState::kStateSearchResults &&
       !app_list_view_->is_in_drag()) {
     return kSearchBoxBorderCornerRadiusSearchResult;
   }
@@ -506,8 +506,8 @@
 }
 
 SkColor SearchBoxView::GetBackgroundColorForState(
-    AppListModel::State state) const {
-  if (state == AppListModel::STATE_SEARCH_RESULTS)
+    ash::AppListState state) const {
+  if (state == ash::AppListState::kStateSearchResults)
     return kCardBackgroundColor;
   return background_color_;
 }
diff --git a/ui/app_list/views/search_box_view.h b/ui/app_list/views/search_box_view.h
index 435294b..11e0f4f7 100644
--- a/ui/app_list/views/search_box_view.h
+++ b/ui/app_list/views/search_box_view.h
@@ -107,22 +107,22 @@
   // Updates the search box's background corner radius and color based on the
   // state of AppListModel.
   void UpdateBackground(double progress,
-                        AppListModel::State current_state,
-                        AppListModel::State target_state);
+                        ash::AppListState current_state,
+                        ash::AppListState target_state);
 
   // Updates the search box's layout based on the state of AppListModel.
   void UpdateLayout(double progress,
-                    AppListModel::State current_state,
-                    AppListModel::State target_state);
+                    ash::AppListState current_state,
+                    ash::AppListState target_state);
 
   // Called when tablet mode starts and ends.
   void OnTabletModeChanged(bool started);
 
   // Returns background border corner radius in the given state.
-  int GetSearchBoxBorderCornerRadiusForState(AppListModel::State state) const;
+  int GetSearchBoxBorderCornerRadiusForState(ash::AppListState state) const;
 
   // Returns background color for the given state.
-  SkColor GetBackgroundColorForState(AppListModel::State state) const;
+  SkColor GetBackgroundColorForState(ash::AppListState state) const;
 
   // Updates the opacity of the searchbox.
   void UpdateOpacity();
diff --git a/ui/app_list/views/search_result_page_view.cc b/ui/app_list/views/search_result_page_view.cc
index d1b50d2..83b65bfa 100644
--- a/ui/app_list/views/search_result_page_view.cc
+++ b/ui/app_list/views/search_result_page_view.cc
@@ -295,8 +295,8 @@
 }
 
 gfx::Rect SearchResultPageView::GetPageBoundsForState(
-    AppListModel::State state) const {
-  if (state != AppListModel::STATE_SEARCH_RESULTS) {
+    ash::AppListState state) const {
+  if (state != ash::AppListState::kStateSearchResults) {
     // Hides this view behind the search box by using the same bounds.
     return AppListPage::contents_view()->GetSearchBoxBoundsForState(state);
   }
@@ -308,10 +308,10 @@
 }
 
 void SearchResultPageView::OnAnimationUpdated(double progress,
-                                              AppListModel::State from_state,
-                                              AppListModel::State to_state) {
-  if (from_state != AppListModel::STATE_SEARCH_RESULTS &&
-      to_state != AppListModel::STATE_SEARCH_RESULTS) {
+                                              ash::AppListState from_state,
+                                              ash::AppListState to_state) {
+  if (from_state != ash::AppListState::kStateSearchResults &&
+      to_state != ash::AppListState::kStateSearchResults) {
     return;
   }
   const SearchBoxView* search_box =
@@ -330,7 +330,7 @@
           search_box->GetSearchBoxBorderCornerRadiusForState(to_state))));
 
   gfx::Rect onscreen_bounds(
-      GetPageBoundsForState(AppListModel::STATE_SEARCH_RESULTS));
+      GetPageBoundsForState(ash::AppListState::kStateSearchResults));
   onscreen_bounds -= bounds().OffsetFromOrigin();
   gfx::Path path;
   path.addRect(gfx::RectToSkRect(onscreen_bounds));
diff --git a/ui/app_list/views/search_result_page_view.h b/ui/app_list/views/search_result_page_view.h
index 1a66385..defb670 100644
--- a/ui/app_list/views/search_result_page_view.h
+++ b/ui/app_list/views/search_result_page_view.h
@@ -38,10 +38,10 @@
   gfx::Size CalculatePreferredSize() const override;
 
   // AppListPage overrides:
-  gfx::Rect GetPageBoundsForState(AppListModel::State state) const override;
+  gfx::Rect GetPageBoundsForState(ash::AppListState state) const override;
   void OnAnimationUpdated(double progress,
-                          AppListModel::State from_state,
-                          AppListModel::State to_state) override;
+                          ash::AppListState from_state,
+                          ash::AppListState to_state) override;
   gfx::Rect GetSearchBoxBounds() const override;
 
   // Overridden from SearchResultContainerView::Delegate :
diff --git a/ui/app_list/views/search_result_tile_item_view.cc b/ui/app_list/views/search_result_tile_item_view.cc
index b607b87..716b254 100644
--- a/ui/app_list/views/search_result_tile_item_view.cc
+++ b/ui/app_list/views/search_result_tile_item_view.cc
@@ -298,7 +298,7 @@
 
 void SearchResultTileItemView::OnFocus() {
   if (pagination_model_ && IsSuggestedAppTile() &&
-      view_delegate_->GetModel()->state() == AppListModel::STATE_APPS) {
+      view_delegate_->GetModel()->state() == ash::AppListState::kStateApps) {
     // Go back to first page when app in suggestions container is focused.
     pagination_model_->SelectPage(0, false);
   } else if (!IsSuggestedAppTile()) {
diff --git a/ui/app_list/views/suggestions_container_view.cc b/ui/app_list/views/suggestions_container_view.cc
index a909ccb..b01e8f89 100644
--- a/ui/app_list/views/suggestions_container_view.cc
+++ b/ui/app_list/views/suggestions_container_view.cc
@@ -4,6 +4,8 @@
 
 #include "ui/app_list/views/suggestions_container_view.h"
 
+#include <memory>
+
 #include "ui/app_list/app_list_constants.h"
 #include "ui/app_list/app_list_features.h"
 #include "ui/app_list/views/app_list_main_view.h"
@@ -33,8 +35,9 @@
 int SuggestionsContainerView::DoUpdate() {
   // Ignore updates and disable buttons when suggestions container view is not
   // shown.
-  const AppListModel::State state = contents_view_->GetActiveState();
-  if (state != AppListModel::STATE_START && state != AppListModel::STATE_APPS) {
+  const ash::AppListState state = contents_view_->GetActiveState();
+  if (state != ash::AppListState::kStateStart &&
+      state != ash::AppListState::kStateApps) {
     for (auto* view : search_result_tile_views_)
       view->SetEnabled(false);
 
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index 2584b5c..d3a863d 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -367,6 +367,8 @@
 }
 
 void Compositor::SetDisplayColorSpace(const gfx::ColorSpace& color_space) {
+  if (output_color_space_ == color_space)
+    return;
   output_color_space_ = color_space;
   blending_color_space_ = output_color_space_.GetBlendingColorSpace();
   // Do all ui::Compositor rasterization to sRGB because UI resources will not
@@ -374,6 +376,12 @@
   // image color conversions.
   // https://crbug.com/769677
   host_->SetRasterColorSpace(gfx::ColorSpace::CreateSRGB());
+  // Always force the ui::Compositor to re-draw all layers, because damage
+  // tracking bugs result in black flashes.
+  // https://crbug.com/804430
+  // TODO(ccameron): Remove this when the above bug is fixed.
+  host_->SetNeedsDisplayOnAllLayers();
+
   // Color space is reset when the output surface is lost, so this must also be
   // updated then.
   // TODO(fsamuel): Get rid of this.
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
index ef792f2b..a14ec3a 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -876,6 +876,33 @@
 });
 
 /**
+ * Pastes files from clipboard. This is basically same as 'paste'.
+ * This command is used for always showing the Paste command to gear menu.
+ * @type {Command}
+ */
+CommandHandler.COMMANDS_['paste-into-current-folder'] =
+    /** @type {Command} */ ({
+      /**
+       * @param {!Event} event Command event.
+       * @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
+       */
+      execute: function(event, fileManager) {
+        fileManager.document.execCommand('paste');
+      },
+      /**
+       * @param {!Event} event Command event.
+       * @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
+       */
+      canExecute: function(event, fileManager) {
+        var fileTransferController = fileManager.fileTransferController;
+
+        event.canExecute = !!fileTransferController &&
+            fileTransferController.queryPasteCommandEnabled(
+                fileManager.directoryModel.getCurrentDirEntry());
+      }
+    });
+
+/**
  * Pastes files from clipboard into the selected folder.
  * @type {Command}
  */
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html
index c56ba05..155a770f 100644
--- a/ui/file_manager/file_manager/main.html
+++ b/ui/file_manager/file_manager/main.html
@@ -89,6 +89,7 @@
                shortcut="c|Ctrl">
       <command id="paste" i18n-values="label:PASTE_BUTTON_LABEL"
                shortcut="v|Ctrl">
+      <command id="paste-into-current-folder" i18n-values="label:PASTE_BUTTON_LABEL">
       <command id="paste-into-folder"
                i18n-values="label:PASTE_INTO_FOLDER_BUTTON_LABEL">
       <command id="get-info" i18n-values="label:GET_INFO_BUTTON_LABEL"
@@ -233,6 +234,8 @@
 
     <cr-menu id="gear-menu" class="chrome-menu files-menu" showShortcuts
              menu-item-selector="cr-menu-item, hr">
+      <cr-menu-item command="#paste-into-current-folder" visibleif="full-page"></cr-menu-item>
+      <hr visibleif="full-page">
       <cr-menu-item id="gear-menu-newwindow" command="#new-window"></cr-menu-item>
       <cr-menu-item id="gear-menu-newfolder" command="#new-folder"></cr-menu-item>
       <hr>
diff --git a/ui/file_manager/integration_tests/file_manager/gear_menu.js b/ui/file_manager/integration_tests/file_manager/gear_menu.js
index cf0d38a..76c3783d 100644
--- a/ui/file_manager/integration_tests/file_manager/gear_menu.js
+++ b/ui/file_manager/integration_tests/file_manager/gear_menu.js
@@ -278,3 +278,128 @@
     },
   ]);
 };
+
+/**
+ * Test for the "paste-into-current-folder" menu item
+ */
+testcase.showPasteInGearMenu = function() {
+  const entrySet = [ENTRIES.hello, ENTRIES.world];
+  var appId;
+  StepsRunner.run([
+    function() {
+      addEntries(['local'], entrySet, this.next);
+    },
+    function(result) {
+      chrome.test.assertTrue(result);
+      openNewWindow(null, RootPath.DOWNLOADS).then(this.next);
+    },
+    function(inAppId) {
+      appId = inAppId;
+      remoteCall.waitForElement(appId, '#detail-table').then(this.next);
+    },
+    // Wait for the expected files to appear in the file list.
+    function() {
+      remoteCall.waitForFiles(appId, TestEntryInfo.getExpectedRows(entrySet))
+          .then(this.next);
+    },
+    function() {
+      remoteCall.waitForElement(appId, '#gear-button').then(this.next);
+    },
+
+    // 1. Before selecting entries
+    function() {
+      remoteCall.callRemoteTestUtil(
+          'fakeMouseClick', appId, ['#gear-button'], this.next);
+    },
+    // Wait for menu to appear.
+    function(result) {
+      chrome.test.assertTrue(result);
+      remoteCall.waitForElement(appId, '#gear-menu:not([hidden])')
+          .then(this.next);
+    },
+    // #paste-into-current-folder command is shown. It should be disabled
+    // because no file has been copied to clipboard.
+    function(result) {
+      remoteCall
+          .waitForElement(
+              appId,
+              '#gear-menu cr-menu-item' +
+                  '[command=\'#paste-into-current-folder\']' +
+                  '[disabled]:not([hidden])')
+          .then(this.next);
+    },
+    function() {
+      remoteCall.callRemoteTestUtil(
+          'fakeMouseClick', appId, ['#file-list'], this.next);
+    },
+    function() {
+      remoteCall.waitForElement(appId, '#gear-menu[hidden]').then(this.next);
+    },
+
+    // 2. Selecting a single regular file
+    function(result) {
+      remoteCall.callRemoteTestUtil(
+          'selectFile', appId, [ENTRIES.hello.nameText], this.next);
+    },
+    function(result) {
+      chrome.test.assertTrue(result);
+      remoteCall.callRemoteTestUtil(
+          'fakeMouseClick', appId, ['#gear-button'], this.next);
+    },
+    // Wait for menu to appear.
+    // The command is still shown.
+    function() {
+      remoteCall
+          .waitForElement(
+              appId,
+              '#gear-menu:not([hidden]) cr-menu-item' +
+                  '[command=\'#paste-into-current-folder\']' +
+                  '[disabled]:not([hidden])')
+          .then(this.next);
+    },
+    function() {
+      remoteCall.callRemoteTestUtil(
+          'fakeMouseClick', appId, ['#file-list'], this.next);
+    },
+    function() {
+      remoteCall.waitForElement(appId, '#gear-menu[hidden]').then(this.next);
+    },
+
+    // 3. When ready to paste a file
+    function(result) {
+      remoteCall.callRemoteTestUtil(
+          'selectFile', appId, [ENTRIES.hello.nameText], this.next);
+    },
+    // Ctrl-C to copy the selected file
+    function() {
+      remoteCall
+          .fakeKeyDown(appId, '#file-list', 'c', 'U+0043', true, false, false)
+          .then(this.next);
+    },
+    function() {
+      remoteCall.callRemoteTestUtil(
+          'fakeMouseClick', appId, ['#gear-button'], this.next);
+    },
+    // The command appears enabled.
+    function() {
+      remoteCall
+          .waitForElement(
+              appId,
+              '#gear-menu:not([hidden])' +
+                  ' cr-menu-item[command=\'#paste-into-current-folder\']' +
+                  ':not([disabled]):not([hidden])')
+          .then(this.next);
+    },
+    function() {
+      remoteCall.callRemoteTestUtil(
+          'fakeMouseClick', appId, ['#file-list'], this.next);
+    },
+    function() {
+      remoteCall.waitForElement(appId, '#gear-menu[hidden]').then(this.next);
+    },
+
+    function() {
+      checkIfNoErrorsOccured(this.next);
+    },
+  ]);
+};
diff --git a/ui/gl/gl_image_io_surface.mm b/ui/gl/gl_image_io_surface.mm
index b3a2342..5c7b79ae 100644
--- a/ui/gl/gl_image_io_surface.mm
+++ b/ui/gl/gl_image_io_surface.mm
@@ -39,6 +39,7 @@
     case GL_RG:
     case GL_BGRA_EXT:
     case GL_RGB:
+    case GL_RGB10_A2_EXT:
     case GL_RGB_YCBCR_420V_CHROMIUM:
     case GL_RGB_YCBCR_422_CHROMIUM:
     case GL_RGBA:
diff --git a/ui/message_center/views/message_popup_collection.cc b/ui/message_center/views/message_popup_collection.cc
index f3054dc..e411a81 100644
--- a/ui/message_center/views/message_popup_collection.cc
+++ b/ui/message_center/views/message_popup_collection.cc
@@ -129,26 +129,6 @@
       alignment_delegate_->IsPrimaryDisplayForNotification();
 #endif
 
-  // Check if the popups contain a new notification.
-  bool has_new_toasts = false;
-  for (auto* popup : popups) {
-    if (!FindToast(popup->id())) {
-      has_new_toasts = true;
-      break;
-    }
-  }
-
-  // If a new notification is found, collapse all existing notifications
-  // beforehand.
-  if (has_new_toasts) {
-    for (auto* toast : toasts_) {
-      if (toast->message_view()->IsMouseHovered() ||
-          toast->message_view()->manually_expanded_or_collapsed())
-        continue;
-      toast->message_view()->SetExpanded(false);
-    }
-  }
-
   // Iterate in the reverse order to keep the oldest toasts on screen. Newer
   // items may be ignored if there are no room to place them.
   for (NotificationList::PopupNotifications::const_reverse_iterator iter =
diff --git a/ui/message_center/views/message_view.h b/ui/message_center/views/message_view.h
index 0efc0f4..a2036cce2 100644
--- a/ui/message_center/views/message_view.h
+++ b/ui/message_center/views/message_view.h
@@ -94,10 +94,6 @@
   void set_scroller(views::ScrollView* scroller) { scroller_ = scroller; }
   std::string notification_id() const { return notification_id_; }
 
-  bool manually_expanded_or_collapsed() const {
-    return manually_expanded_or_collapsed_;
-  }
-
  protected:
   // Creates and add close button to view hierarchy when necessary. Derived
   // classes should call this after its view hierarchy is populated to ensure
@@ -111,10 +107,6 @@
   views::View* background_view() { return background_view_; }
   views::ScrollView* scroller() { return scroller_; }
 
-  void set_manually_expanded_or_collapsed() {
-    manually_expanded_or_collapsed_ = true;
-  }
-
  private:
   std::string notification_id_;
   views::View* background_view_ = nullptr;  // Owned by views hierarchy.
@@ -125,10 +117,6 @@
   // Flag if the notification is set to pinned or not.
   bool pinned_ = false;
 
-  // True if the notification is expanded/collapsed by user interaction.
-  // If true, MessagePopupCollection will not auto-collapse the notification.
-  bool manually_expanded_or_collapsed_ = false;
-
   std::unique_ptr<views::Painter> focus_painter_;
 
   views::SlideOutController slide_out_controller_;
diff --git a/ui/message_center/views/notification_view_md.cc b/ui/message_center/views/notification_view_md.cc
index a0219f4..fa12e58 100644
--- a/ui/message_center/views/notification_view_md.cc
+++ b/ui/message_center/views/notification_view_md.cc
@@ -655,7 +655,6 @@
   // |expand_button| can be focused by TAB.
   if (sender == header_row_) {
     if (IsExpandable()) {
-      set_manually_expanded_or_collapsed();
       ToggleExpanded();
       Layout();
       SchedulePaint();
diff --git a/ui/message_center/views/notification_view_md_unittest.cc b/ui/message_center/views/notification_view_md_unittest.cc
index 02d4fc0..f4d8a89d 100644
--- a/ui/message_center/views/notification_view_md_unittest.cc
+++ b/ui/message_center/views/notification_view_md_unittest.cc
@@ -637,20 +637,6 @@
   EXPECT_EQ(collapsed_height, notification_view()->message_view_->height());
   EXPECT_EQ(collapsed_preferred_height,
             notification_view()->GetPreferredSize().height());
-
-  // Test |manually_expanded_or_collapsed| being set when the toggle is done by
-  // user interaction.
-  EXPECT_FALSE(notification_view()->manually_expanded_or_collapsed());
-
-  // Construct a mouse click event 1 pixel inside the header.
-  gfx::Point done_cursor_location(1, 1);
-  views::View::ConvertPointToScreen(notification_view()->header_row_,
-                                    &done_cursor_location);
-  ui::test::EventGenerator generator(widget()->GetNativeWindow());
-  generator.MoveMouseTo(done_cursor_location);
-  generator.ClickLeftButton();
-
-  EXPECT_TRUE(notification_view()->manually_expanded_or_collapsed());
 }
 
 TEST_F(NotificationViewMDTest, TestAccentColor) {
diff --git a/ui/message_center/views/toast_contents_view.cc b/ui/message_center/views/toast_contents_view.cc
index ab73e0a1..1517157 100644
--- a/ui/message_center/views/toast_contents_view.cc
+++ b/ui/message_center/views/toast_contents_view.cc
@@ -83,7 +83,6 @@
 
 void ToastContentsView::SetContents(MessageView* view,
                                     bool a11y_feedback_for_updates) {
-  message_view_ = view;
   bool already_has_contents = child_count() > 0;
   RemoveAllChildViews(true);
   AddChildView(view);
diff --git a/ui/message_center/views/toast_contents_view.h b/ui/message_center/views/toast_contents_view.h
index 87c0aa9b..8322754 100644
--- a/ui/message_center/views/toast_contents_view.h
+++ b/ui/message_center/views/toast_contents_view.h
@@ -80,8 +80,6 @@
 
   const std::string& id() const { return id_; }
 
-  MessageView* message_view() { return message_view_; }
-
   // Overridden from views::View:
   void OnMouseEntered(const ui::MouseEvent& event) override;
   void OnMouseExited(const ui::MouseEvent& event) override;
@@ -143,9 +141,6 @@
   gfx::Point origin_;
   gfx::Size preferred_size_;
 
-  // Weak reference to the MessageView.
-  MessageView* message_view_ = nullptr;
-
   DISALLOW_COPY_AND_ASSIGN(ToastContentsView);
 };
 
diff --git a/ui/views/accessibility/view_accessibility.cc b/ui/views/accessibility/view_accessibility.cc
index 81f3b39f..1d29ad82 100644
--- a/ui/views/accessibility/view_accessibility.cc
+++ b/ui/views/accessibility/view_accessibility.cc
@@ -61,6 +61,11 @@
     data->role = custom_data_.role;
   if (custom_data_.HasStringAttribute(ui::AX_ATTR_NAME))
     data->SetName(custom_data_.GetStringAttribute(ui::AX_ATTR_NAME));
+  if (custom_data_.HasStringAttribute(ui::AX_ATTR_DESCRIPTION)) {
+    data->AddStringAttribute(
+        ui::AX_ATTR_DESCRIPTION,
+        custom_data_.GetStringAttribute(ui::AX_ATTR_DESCRIPTION));
+  }
 
   data->location = gfx::RectF(owner_view_->GetBoundsInScreen());
   if (!data->HasStringAttribute(ui::AX_ATTR_DESCRIPTION)) {
@@ -99,6 +104,11 @@
   custom_data_.SetName(base::UTF16ToUTF8(name));
 }
 
+void ViewAccessibility::OverrideDescription(const std::string& description) {
+  DCHECK(!custom_data_.HasStringAttribute(ui::AX_ATTR_DESCRIPTION));
+  custom_data_.AddStringAttribute(ui::AX_ATTR_DESCRIPTION, description);
+}
+
 gfx::NativeViewAccessible ViewAccessibility::GetNativeObject() {
   return nullptr;
 }
diff --git a/ui/views/accessibility/view_accessibility.h b/ui/views/accessibility/view_accessibility.h
index 43efb57..a548bbb 100644
--- a/ui/views/accessibility/view_accessibility.h
+++ b/ui/views/accessibility/view_accessibility.h
@@ -47,6 +47,7 @@
   void OverrideRole(ui::AXRole role);
   void OverrideName(const std::string& name);
   void OverrideName(const base::string16& name);
+  void OverrideDescription(const std::string& description);
 
   virtual gfx::NativeViewAccessible GetNativeObject();
   virtual void NotifyAccessibilityEvent(ui::AXEvent event_type) {}
diff --git a/ui/views/animation/ink_drop_host_view.cc b/ui/views/animation/ink_drop_host_view.cc
index 31f307b..85c14111 100644
--- a/ui/views/animation/ink_drop_host_view.cc
+++ b/ui/views/animation/ink_drop_host_view.cc
@@ -221,6 +221,17 @@
   GetInkDrop()->AnimateToState(state);
 }
 
+void InkDropHostView::ViewHierarchyChanged(
+    const ViewHierarchyChangedDetails& details) {
+  // If we're being removed hide the ink-drop so if we're highlighted now the
+  // highlight won't be active if we're added back again.
+  if (!details.is_add && details.child == this && ink_drop_) {
+    GetInkDrop()->AnimateToState(InkDropState::HIDDEN);
+    GetInkDrop()->SetHovered(false);
+  }
+  View::ViewHierarchyChanged(details);
+}
+
 void InkDropHostView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
   if (ink_drop_)
     ink_drop_->HostSizeChanged(size());
diff --git a/ui/views/animation/ink_drop_host_view.h b/ui/views/animation/ink_drop_host_view.h
index 8ac475f..52faefff 100644
--- a/ui/views/animation/ink_drop_host_view.h
+++ b/ui/views/animation/ink_drop_host_view.h
@@ -95,6 +95,8 @@
   gfx::Point GetInkDropCenterBasedOnLastEvent() const;
 
   // View:
+  void ViewHierarchyChanged(
+      const ViewHierarchyChangedDetails& details) override;
   void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
   void VisibilityChanged(View* starting_from, bool is_visible) override;
   void OnFocus() override;
diff --git a/ui/views/controls/button/button.cc b/ui/views/controls/button/button.cc
index e8b9a13..8dc19794 100644
--- a/ui/views/controls/button/button.cc
+++ b/ui/views/controls/button/button.cc
@@ -425,6 +425,7 @@
 void Button::ViewHierarchyChanged(const ViewHierarchyChangedDetails& details) {
   if (!details.is_add && state_ != STATE_DISABLED && details.child == this)
     SetState(STATE_NORMAL);
+  InkDropHostView::ViewHierarchyChanged(details);
 }
 
 void Button::OnFocus() {
diff --git a/ui/views/controls/button/button_unittest.cc b/ui/views/controls/button/button_unittest.cc
index 20f610f..dc91808 100644
--- a/ui/views/controls/button/button_unittest.cc
+++ b/ui/views/controls/button/button_unittest.cc
@@ -510,6 +510,50 @@
   EXPECT_EQ(InkDropState::ACTION_PENDING, ink_drop->GetTargetInkDropState());
 }
 
+TEST_F(ButtonTest, HideInkDropHighlightWhenRemoved) {
+  views::View test_container;
+  test_container.set_owned_by_client();
+  TestInkDrop* ink_drop = new TestInkDrop();
+  CreateButtonWithInkDrop(base::WrapUnique(ink_drop), false);
+  // Mark the button as owned by client so we can remove it from widget()
+  // without it being deleted.
+  button()->set_owned_by_client();
+
+  // Make sure that the button ink drop is hidden after the button gets removed.
+  widget()->SetContentsView(&test_container);
+  test_container.AddChildView(button());
+  ui::test::EventGenerator generator(widget()->GetNativeWindow());
+  generator.MoveMouseToInHost(2, 2);
+  EXPECT_TRUE(ink_drop->is_hovered());
+  test_container.RemoveAllChildViews(false);
+  EXPECT_FALSE(ink_drop->is_hovered());
+
+  // Make sure hiding the ink drop happens even if the button is indirectly
+  // being removed.
+  views::View parent_test_container;
+  parent_test_container.set_owned_by_client();
+  parent_test_container.AddChildView(&test_container);
+  test_container.AddChildView(button());
+  widget()->SetContentsView(&parent_test_container);
+
+  // Trigger hovering and then remove from the indirect parent. This should
+  // propagate down to Button which should remove the highlight effect.
+  EXPECT_FALSE(ink_drop->is_hovered());
+  generator.MoveMouseToInHost(10, 10);
+  EXPECT_TRUE(ink_drop->is_hovered());
+  parent_test_container.RemoveAllChildViews(false);
+  EXPECT_FALSE(ink_drop->is_hovered());
+
+  // Remove references to and delete button() which cannot be removed by owned
+  // containers as it's permanently set as owned by client.
+  test_container.RemoveAllChildViews(false);
+  delete button();
+
+  // Set the widget contents view to a new View so widget() doesn't contain a
+  // stale reference to the test containers that are about to go out of scope.
+  widget()->SetContentsView(new View());
+}
+
 // Tests that when button is set to notify on release, dragging mouse out and
 // back transitions ink drop states correctly.
 TEST_F(ButtonTest, InkDropShowHideOnMouseDraggedNotifyOnRelease) {