diff --git a/DEPS b/DEPS
index 5df82451..db4d7c4f 100644
--- a/DEPS
+++ b/DEPS
@@ -172,11 +172,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': '6c4c685b2b8b36995176dffd4222402d2fca20a9',
+  'skia_revision': '9c0c92b2db869727fd28077960e004a950bf9616',
   # 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': '2cab5168bc8d0b6f37aa49a57153f4189babf7b3',
+  'v8_revision': '7b44da5f0241b6af38971d173590d7fa4cd63ee0',
   # 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.
@@ -184,11 +184,11 @@
   # 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': 'e9b68f332a30f60ba722c511b7335a38da6fa009',
+  'angle_revision': '04e074d1aae0aa1c3d9990ca147b17d5b6f96529',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '4584a9c2ccb9f2a7bc7cd3c55f5b95507901e035',
+  'swiftshader_revision': 'afc52b0b26d7d34baee77ce7b75aa3c5625abca9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -235,7 +235,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': '5459c3891e2c1e3b0cb1a24d68bf33c798191852',
+  'catapult_revision': '56b1f53bcd83d9163cd56f968c43630c33e59052',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -243,7 +243,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '693bde6a69a2717a7fbfa5793489f4af6f8a13e5',
+  'devtools_frontend_revision': '204f9ad496e5f930727c5f7836a91ae79afe72cc',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -287,7 +287,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': '45dde9ad6dde133db9bd6942c46df692ca539186',
+  'spv_tools_revision': '85f3e93d13f32d45bd7f9999aa51baddf2452aae',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -1293,7 +1293,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '4a0fd75b105f7732ab26f9bc05f8067cb11e37f2',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'b245e85651ebb1909568db2cf573322ef285935a',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1494,7 +1494,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'dd55f3ca8f2ea716ca917a4aaf36f0729fe902b1',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'e43b53126600d247fbfde8b5c29b22ee22e59c86',
+    Var('webrtc_git') + '/src.git' + '@' + 'eac63e7e026216b8e26ce875cd8a908372277794',
 
   # Wuffs' canonical repository is at github.com/google/wuffs, but we use
   # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
@@ -1561,7 +1561,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@4fae2545ff9e766ff109ea9bd68844a5733099e1',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f1d198eaf22fb6a5794c202cd26decea0c8672bd',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/WATCHLISTS b/WATCHLISTS
index cc4d698..d0b1b0fdb 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -795,8 +795,7 @@
                   'ui/login/',
     },
     'chromeos_media_app': {
-      'filepath': 'chromeos/components/media_app_ui/|'\
-                  'chromeos/resources/media_app_resources.grdp',
+      'filepath': 'chromeos/components/media_app_ui/',
     },
     'chromeos_net': {
       'filepath': 'ash/system/network/|'\
diff --git a/ash/host/ash_window_tree_host_platform.cc b/ash/host/ash_window_tree_host_platform.cc
index f3b4dde..f398b06 100644
--- a/ash/host/ash_window_tree_host_platform.cc
+++ b/ash/host/ash_window_tree_host_platform.cc
@@ -25,7 +25,7 @@
 #include "ui/gfx/transform.h"
 #include "ui/ozone/public/input_controller.h"
 #include "ui/ozone/public/ozone_platform.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
 namespace ash {
diff --git a/ash/host/ash_window_tree_host_unified.cc b/ash/host/ash_window_tree_host_unified.cc
index 7e46505..fe31c6c8a 100644
--- a/ash/host/ash_window_tree_host_unified.cc
+++ b/ash/host/ash_window_tree_host_unified.cc
@@ -65,7 +65,7 @@
     AshWindowTreeHostMirroringDelegate* delegate)
     : AshWindowTreeHostPlatform(), delegate_(delegate) {
   DCHECK(delegate);
-  std::unique_ptr<ui::PlatformWindowBase> window(new ui::StubWindow(this));
+  std::unique_ptr<ui::PlatformWindow> window(new ui::StubWindow(this));
   window->SetBounds(initial_bounds);
   SetPlatformWindow(std::move(window));
 }
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index b0fa8b3a..8332b0df 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1549,13 +1549,6 @@
           # TODO(https://crbug.com/995993): Clean up and enable.
           "-Wno-implicit-fallthrough",
         ]
-
-        if (llvm_force_head_revision) {
-          cflags += [
-            # TODO(https://crbug.com/1026283): Clean up, enable.
-            "-Wno-switch-bool",
-          ]
-        }
       }
     }
   }
diff --git a/chrome/VERSION b/chrome/VERSION
index 17e824e..654405a 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=80
 MINOR=0
-BUILD=3977
+BUILD=3978
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninView.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninView.java
index 764e292..4dd00465 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninView.java
@@ -68,7 +68,7 @@
         mMoreButton = findViewById(R.id.more_button);
         mAcceptButtonEndPadding = findViewById(R.id.positive_button_end_padding);
 
-        mAnimationLooper = AnimationLooper.create(mHeaderImage.getDrawable());
+        mAnimationLooper = new AnimationLooper(mHeaderImage.getDrawable());
     }
 
     SigninScrollView getScrollView() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionTestUtils.java
index 6ce50e24..1947675 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionTestUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionTestUtils.java
@@ -75,11 +75,12 @@
 
         // Any built-in page that is not about:blank and is reasonably cheap to render will do,
         // here.
+        Tab tab = activity.getTabModelSelector().getCurrentTab();
         String visitedUrl = "chrome://version/";
         assertThat(initialUrl, Matchers.not(Matchers.equalTo(visitedUrl)));
         rule.loadUrl(visitedUrl);
+        ChromeTabUtils.waitForTabPageLoaded(tab, visitedUrl);
 
-        Tab tab = activity.getTabModelSelector().getCurrentTab();
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> activity.getCurrentWebContents().getNavigationController().goBack());
         ChromeTabUtils.waitForTabPageLoaded(tab, initialUrl);
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 54b04c0..cc1dd0fc 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -4142,7 +4142,7 @@
 
   <!-- Strings for login screen extension UI -->
   <message name="IDS_LOGIN_EXTENSION_UI_DIALOG_TITLE" desc="Dialog title for windows opened from a login screen extension. These windows will be displayed over the login screen.">
-    Login provided by <ph name="EXTENSION_NAME">$1<ex>Identity Provider Name</ex></ph>
+    Sign-in provided by <ph name="EXTENSION_NAME">$1<ex>Identity Provider Name</ex></ph>
   </message>
 
   <!-- Strings for notifications about features which aren't supported in Crostini -->
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOGIN_EXTENSION_UI_DIALOG_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_EXTENSION_UI_DIALOG_TITLE.png.sha1
index 6049106..2e831e8 100644
--- a/chrome/app/chromeos_strings_grdp/IDS_LOGIN_EXTENSION_UI_DIALOG_TITLE.png.sha1
+++ b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_EXTENSION_UI_DIALOG_TITLE.png.sha1
@@ -1 +1 @@
-b57850c1bda68685bf6d523f7cfda5e649f03b5e
\ No newline at end of file
+4defee827fd463263417636d1db8d28d316eecab
\ No newline at end of file
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn
index 70ba608..45f9d19 100644
--- a/chrome/app/vector_icons/BUILD.gn
+++ b/chrome/app/vector_icons/BUILD.gn
@@ -170,10 +170,16 @@
 
   if (is_win) {
     icons += [
+      "back_arrow_windows.icon",
+      "back_arrow_windows_touch.icon",
       "inactive_toast_arrow.icon",
       "inactive_toast_close.icon",
       "inactive_toast_logo.icon",
+      "navigate_stop_windows.icon",
+      "navigate_stop_windows_touch.icon",
       "open_in_phone.icon",
+      "reload_windows.icon",
+      "reload_windows_touch.icon",
     ]
   }
 
diff --git a/chrome/app/vector_icons/back_arrow_windows.icon b/chrome/app/vector_icons/back_arrow_windows.icon
new file mode 100644
index 0000000..a88047e
--- /dev/null
+++ b/chrome/app/vector_icons/back_arrow_windows.icon
@@ -0,0 +1,15 @@
+// Copyright 2019 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.
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 1, 8.5f,
+LINE_TO, 8.2f, 1.3f,
+LINE_TO, 9.08f, 2.18f,
+LINE_TO, 3.39f, 7.88f,
+LINE_TO, 16, 7.88f,
+LINE_TO, 16, 9.13f,
+LINE_TO, 3.39f, 9.13f,
+LINE_TO, 9.08f, 14.82f,
+LINE_TO, 8.2f, 15.7f,
+CLOSE
diff --git a/chrome/app/vector_icons/back_arrow_windows_touch.icon b/chrome/app/vector_icons/back_arrow_windows_touch.icon
new file mode 100644
index 0000000..a60d0d4
--- /dev/null
+++ b/chrome/app/vector_icons/back_arrow_windows_touch.icon
@@ -0,0 +1,15 @@
+// Copyright 2019 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.
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 3, 12.5f,
+LINE_TO, 12.12f, 3.38f,
+LINE_TO, 13.24f, 4.5f,
+LINE_TO, 6.03f, 11.71f,
+LINE_TO, 22, 11.71f,
+LINE_TO, 22, 13.29f,
+LINE_TO, 6.03f, 13.29f,
+LINE_TO, 13.24f, 20.5f,
+LINE_TO, 12.12f, 21.62f,
+CLOSE
diff --git a/chrome/app/vector_icons/incognito.icon b/chrome/app/vector_icons/incognito.icon
index 0911bfb7..04c7357 100644
--- a/chrome/app/vector_icons/incognito.icon
+++ b/chrome/app/vector_icons/incognito.icon
@@ -1,6 +1,48 @@
 // Copyright 2015 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.
+
+// Size 25 is added for better appearance at 125% scale.
+CANVAS_DIMENSIONS, 25,
+CIRCLE, 12.5, 12.5, 12.5,
+MOVE_TO, 16.41f, 13.37f,
+R_ARC_TO, 3.04f, 3.04f, 0, 0, 1, 3.04f, 3.04f,
+R_ARC_TO, 3.04f, 3.04f, 0, 0, 1, -3.04f, 3.04f,
+R_CUBIC_TO, -1.59f, 0, -2.87f, -1.22f, -3.01f, -2.78f,
+R_CUBIC_TO, -0.84f, -0.54f, -1.53f, -0.2f, -1.79f, -0.02f,
+R_ARC_TO, 3.02f, 3.02f, 0, 0, 1, -3.01f, 2.8f,
+R_ARC_TO, 3.04f, 3.04f, 0, 0, 1, -3.04f, -3.04f,
+R_ARC_TO, 3.04f, 3.04f, 0, 0, 1, 3.04f, -3.04f,
+R_ARC_TO, 3.04f, 3.04f, 0, 0, 1, 2.95f, 2.34f,
+R_ARC_TO, 2.38f, 2.38f, 0, 0, 1, 1.91f, 0.01f,
+R_ARC_TO, 3.03f, 3.03f, 0, 0, 1, 2.95f, -2.35f,
+CLOSE,
+R_MOVE_TO, -7.81f, 0.87f,
+R_ARC_TO, 2.17f, 2.17f, 0, 1, 0, 0, 4.34f,
+R_ARC_TO, 2.17f, 2.17f, 0, 0, 0, 0, -4.34f,
+CLOSE,
+R_MOVE_TO, 7.81f, 0,
+R_ARC_TO, 2.17f, 2.17f, 0, 1, 0, 0, 4.34f,
+R_ARC_TO, 2.17f, 2.17f, 0, 0, 0, 0, -4.34f,
+CLOSE,
+MOVE_TO, 20.31f, 11,
+R_V_LINE_TO, 1,
+H_LINE_TO, 4.69f,
+R_V_LINE_TO, -1,
+R_H_LINE_TO, 15.63f,
+CLOSE,
+R_MOVE_TO, -4.97f, -5.64f,
+R_LINE_TO, 0.05f, 0.11f,
+LINE_TO, 17.05f, 10,
+H_LINE_TO, 7.95f,
+R_LINE_TO, 1.65f, -4.53f,
+R_ARC_TO, 0.87f, 0.87f, 0, 0, 1, 0.96f, -0.55f,
+R_LINE_TO, 0.12f, 0.03f,
+R_LINE_TO, 1.81f, 0.61f,
+R_LINE_TO, 1.81f, -0.61f,
+R_ARC_TO, 0.87f, 0.87f, 0, 0, 1, 1.03f, 0.41f,
+CLOSE
+
 CANVAS_DIMENSIONS, 24,
 CIRCLE, 12, 12, 12,
 MOVE_TO, 15.75f, 12.83f,
diff --git a/chrome/app/vector_icons/navigate_stop_windows.icon b/chrome/app/vector_icons/navigate_stop_windows.icon
new file mode 100644
index 0000000..3ee9ba79
--- /dev/null
+++ b/chrome/app/vector_icons/navigate_stop_windows.icon
@@ -0,0 +1,22 @@
+// Copyright 2019 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.
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 7.62f, 8.5f,
+LINE_TO, 2, 2.88f,
+LINE_TO, 2, 2,
+LINE_TO, 2.88f, 2,
+LINE_TO, 8.5f, 7.62f,
+LINE_TO, 14.12f, 2,
+LINE_TO, 15, 2,
+LINE_TO, 15, 2.88f,
+LINE_TO, 9.38f, 8.5f,
+LINE_TO, 15, 14.12f,
+LINE_TO, 15, 15,
+LINE_TO, 14.12f, 15,
+LINE_TO, 8.5f, 9.38f,
+LINE_TO, 2.88f, 15,
+LINE_TO, 2, 15,
+LINE_TO, 2, 14.12f,
+CLOSE
diff --git a/chrome/app/vector_icons/navigate_stop_windows_touch.icon b/chrome/app/vector_icons/navigate_stop_windows_touch.icon
new file mode 100644
index 0000000..67936ac
--- /dev/null
+++ b/chrome/app/vector_icons/navigate_stop_windows_touch.icon
@@ -0,0 +1,22 @@
+// Copyright 2019 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.
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 11.38f, 12.5f,
+LINE_TO, 4.27f, 5.39f,
+LINE_TO, 4.27f, 4.27f,
+LINE_TO, 5.39f, 4.27f,
+LINE_TO, 12.5f, 11.38f,
+LINE_TO, 19.61f, 4.27f,
+LINE_TO, 20.73f, 4.27f,
+LINE_TO, 20.73f, 5.39f,
+LINE_TO, 13.62f, 12.5f,
+LINE_TO, 20.73f, 19.61f,
+LINE_TO, 20.73f, 20.73f,
+LINE_TO, 19.61f, 20.73f,
+LINE_TO, 12.5f, 13.62f,
+LINE_TO, 5.39f, 20.73f,
+LINE_TO, 4.27f, 20.73f,
+LINE_TO, 4.27f, 19.61f,
+CLOSE
diff --git a/chrome/app/vector_icons/reload_windows.icon b/chrome/app/vector_icons/reload_windows.icon
new file mode 100644
index 0000000..a92c453
--- /dev/null
+++ b/chrome/app/vector_icons/reload_windows.icon
@@ -0,0 +1,25 @@
+// Copyright 2019 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.
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 1.6f, 6,
+ARC_TO, 7.34f, 7.34f, 0, 0, 1, 15, 5.08f,
+LINE_TO, 15, 3,
+LINE_TO, 16, 3,
+LINE_TO, 16, 7,
+LINE_TO, 12, 7,
+LINE_TO, 12, 6,
+LINE_TO, 14.06f, 6,
+ARC_TO, 6.09f, 6.09f, 0, 0, 0, 2.94f, 6,
+CLOSE,
+MOVE_TO, 15.4f, 11,
+ARC_TO, 7.34f, 7.34f, 0, 0, 1, 2, 11.92f,
+LINE_TO, 2, 14,
+LINE_TO, 1, 14,
+LINE_TO, 1, 10,
+LINE_TO, 5, 10,
+LINE_TO, 5, 11,
+LINE_TO, 2.94f, 11,
+ARC_TO, 6.09f, 6.09f, 0, 0, 0, 14.06f, 11,
+CLOSE
diff --git a/chrome/app/vector_icons/reload_windows_touch.icon b/chrome/app/vector_icons/reload_windows_touch.icon
new file mode 100644
index 0000000..ec192a7
--- /dev/null
+++ b/chrome/app/vector_icons/reload_windows_touch.icon
@@ -0,0 +1,25 @@
+// Copyright 2019 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.
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 3.76f, 9.33f,
+ARC_TO, 9.3f, 9.3f, 0, 0, 1, 20.73f, 8.17f,
+LINE_TO, 20.73f, 5.53f,
+LINE_TO, 22, 5.53f,
+LINE_TO, 22, 10.6f,
+LINE_TO, 16.93f, 10.6f,
+LINE_TO, 16.93f, 9.33f,
+LINE_TO, 19.54f, 9.33f,
+ARC_TO, 7.72f, 7.72f, 0, 0, 0, 5.46f, 9.33f,
+CLOSE,
+MOVE_TO, 21.24f, 15.67f,
+ARC_TO, 9.3f, 9.3f, 0, 0, 1, 4.27f, 16.83f,
+LINE_TO, 4.27f, 19.47f,
+LINE_TO, 3, 19.47f,
+LINE_TO, 3, 14.4f,
+LINE_TO, 8.07f, 14.4f,
+LINE_TO, 8.07f, 15.67f,
+LINE_TO, 5.46f, 15.67f,
+ARC_TO, 7.72f, 7.72f, 0, 0, 0, 19.54f, 15.67f,
+CLOSE
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 8727d27..f079f5e 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -5565,8 +5565,6 @@
     "signin/e2e_tests/test_accounts_util.h",
     "signin/identity_test_environment_profile_adaptor.cc",
     "signin/identity_test_environment_profile_adaptor.h",
-    "signin/scoped_account_consistency.cc",
-    "signin/scoped_account_consistency.h",
     "ssl/ssl_client_auth_requestor_mock.cc",
     "ssl/ssl_client_auth_requestor_mock.h",
     "ssl/tls_deprecation_test_utils.cc",
diff --git a/chrome/browser/autofill/captured_sites_test_utils.cc b/chrome/browser/autofill/captured_sites_test_utils.cc
index 55d2837..5049bc6 100644
--- a/chrome/browser/autofill/captured_sites_test_utils.cc
+++ b/chrome/browser/autofill/captured_sites_test_utils.cc
@@ -1148,13 +1148,14 @@
 
     // If we are validating the value of a Chrome autofilled field, print the
     // Chrome Autofill's field annotation for debugging purpose.
-    std::string title;
-    if (GetElementProperty(frame, xpath, "return target.getAttribute('title');",
-                           &title)) {
-      VLOG(1) << title;
+    std::string autofill_information;
+    if (GetElementProperty(
+            frame, xpath, "return target.getAttribute('autofill-information');",
+            &autofill_information)) {
+      VLOG(1) << autofill_information;
     } else {
-      ADD_FAILURE()
-          << "Failed to obtain the field's Chrome Autofill annotation!";
+      // Only used for logging purposes, so don't ADD_FAILURE() if it fails.
+      VLOG(1) << "Failed to obtain the field's Chrome Autofill annotation!";
     }
 
     std::string expected_autofill_prediction_type =
diff --git a/chrome/browser/autofill/credit_card_accessory_controller_impl.cc b/chrome/browser/autofill/credit_card_accessory_controller_impl.cc
index 831f5e9d..f67fa68a2 100644
--- a/chrome/browser/autofill/credit_card_accessory_controller_impl.cc
+++ b/chrome/browser/autofill/credit_card_accessory_controller_impl.cc
@@ -77,6 +77,8 @@
 
 void CreditCardAccessoryControllerImpl::OnFillingTriggered(
     const UserInfo::Field& selection) {
+  if (!web_contents_->GetFocusedFrame())
+    return;  // Without focused frame, driver and manager will be undefined.
   DCHECK(GetDriver());
 
   // Credit card number fields have a GUID populated to allow deobfuscation
@@ -147,10 +149,16 @@
 }
 
 void CreditCardAccessoryControllerImpl::RefreshSuggestions() {
-  FetchSuggestionsFromPersonalDataManager();
+  bool valid_manager = web_contents_->GetFocusedFrame() && GetManager();
+  if (valid_manager) {
+    FetchSuggestionsFromPersonalDataManager();
+  } else {
+    cards_cache_.clear();  // If cards cannot be filled, don't show them.
+  }
   std::vector<UserInfo> info_to_add;
-  bool allow_filling = ShouldAllowCreditCardFallbacks(
-      GetManager()->client(), GetManager()->last_query_form());
+  bool allow_filling = valid_manager && ShouldAllowCreditCardFallbacks(
+                                            GetManager()->client(),
+                                            GetManager()->last_query_form());
   std::transform(cards_cache_.begin(), cards_cache_.end(),
                  std::back_inserter(info_to_add),
                  [allow_filling](const CreditCard* data) {
@@ -167,7 +175,7 @@
   AccessorySheetData data = autofill::CreateAccessorySheetData(
       AccessoryTabType::CREDIT_CARDS, GetTitle(has_suggestions),
       std::move(info_to_add), std::move(footer_commands));
-  if (has_suggestions && !allow_filling) {
+  if (has_suggestions && !allow_filling && valid_manager) {
     data.set_warning(
         l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION));
   }
@@ -184,6 +192,8 @@
     const base::string16& cvc) {
   if (!did_succeed)
     return;
+  if (!web_contents_->GetFocusedFrame())
+    return;  // If frame isn't focused anymore, don't attempt to fill.
   DCHECK(credit_card);
   DCHECK(GetDriver());
 
@@ -252,6 +262,7 @@
 }
 
 autofill::AutofillDriver* CreditCardAccessoryControllerImpl::GetDriver() {
+  DCHECK(web_contents_->GetFocusedFrame());
   return af_driver_for_testing_
              ? af_driver_for_testing_
              : autofill::ContentAutofillDriver::GetForRenderFrameHost(
@@ -259,6 +270,7 @@
 }
 
 autofill::AutofillManager* CreditCardAccessoryControllerImpl::GetManager() {
+  DCHECK(web_contents_->GetFocusedFrame());
   return af_manager_for_testing_
              ? af_manager_for_testing_
              : autofill::ContentAutofillDriver::GetForRenderFrameHost(
diff --git a/chrome/browser/browsing_data/counters/browsing_data_counter_utils_browsertest.cc b/chrome/browser/browsing_data/counters/browsing_data_counter_utils_browsertest.cc
index 999f01c1..1b97453f1 100644
--- a/chrome/browser/browsing_data/counters/browsing_data_counter_utils_browsertest.cc
+++ b/chrome/browser/browsing_data/counters/browsing_data_counter_utils_browsertest.cc
@@ -15,10 +15,6 @@
 #include "components/sync/test/fake_server/fake_server_network_resources.h"
 
 #if defined(OS_CHROMEOS)
-#include "chrome/browser/signin/scoped_account_consistency.h"
-#endif
-
-#if defined(OS_CHROMEOS)
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #endif
@@ -27,22 +23,10 @@
 
 class BrowsingDataCounterUtilsBrowserTest : public SyncTest {
  public:
-  BrowsingDataCounterUtilsBrowserTest()
-      : SyncTest(SINGLE_CLIENT)
-#if defined(OS_CHROMEOS)
-        ,
-        scoped_mirror_(std::make_unique<ScopedAccountConsistencyMirror>())
-#endif
-  {
-  }
+  BrowsingDataCounterUtilsBrowserTest() : SyncTest(SINGLE_CLIENT) {}
   ~BrowsingDataCounterUtilsBrowserTest() override = default;
 
  private:
-#if defined(OS_CHROMEOS)
-  // Need to manually turn on mirror for now.
-  const std::unique_ptr<ScopedAccountConsistencyMirror> scoped_mirror_;
-#endif
-
   DISALLOW_COPY_AND_ASSIGN(BrowsingDataCounterUtilsBrowserTest);
 };
 
diff --git a/chrome/browser/certificate_manager_model_unittest.cc b/chrome/browser/certificate_manager_model_unittest.cc
index 2b5ca9f..9d42415 100644
--- a/chrome/browser/certificate_manager_model_unittest.cc
+++ b/chrome/browser/certificate_manager_model_unittest.cc
@@ -113,9 +113,7 @@
 
 // CertificateManagerModel correctly lists CA certificates from the platform NSS
 // Database.
-// TODO(https://crbug.com/787602): Re-enable this test when it is identified why
-// it was flaky.
-TEST_F(CertificateManagerModelTest, DISABLED_ListsCertsFromPlatform) {
+TEST_F(CertificateManagerModelTest, ListsCertsFromPlatform) {
   net::ScopedCERTCertificateList certs = CreateCERTCertificateListFromFile(
       net::GetTestCertsDirectory(), "websocket_cacert.pem",
       net::X509Certificate::FORMAT_AUTO);
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 1267542f..99d2a451 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -3226,6 +3226,7 @@
       ":policy_fuzzer_proto",
       "//chrome/browser",
       "//chrome/browser/chromeos",
+      "//chromeos/dbus:dbus",
       "//third_party/libprotobuf-mutator",
     ]
   }
diff --git a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_installer_utils_unittest.cc b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_installer_utils_unittest.cc
index 7a2eb4e8..126e8fc 100644
--- a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_installer_utils_unittest.cc
+++ b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_installer_utils_unittest.cc
@@ -146,7 +146,7 @@
   RSA_free(rsa);
 }
 
-INSTANTIATE_TEST_SUITE_P(,
+INSTANTIATE_TEST_SUITE_P(All,
                          ArcCertInstallerUtilsTest,
                          testing::Values("",
                                          "name of the smart card",
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index d32558f3..8aee866 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -413,11 +413,8 @@
         TestCase("openQuickViewImageExif"),
         TestCase("openQuickViewImageRaw"),
         TestCase("openQuickViewVideo"),
-// QuickView PDF test fails on MSAN, crbug.com/768070
-#if !defined(MEMORY_SANITIZER)
         TestCase("openQuickViewPdf"),
         TestCase("openQuickViewPdfPreviewsDisabled"),
-#endif
         TestCase("openQuickViewKeyboardUpDownChangesView"),
         TestCase("openQuickViewKeyboardLeftRightChangesView"),
         TestCase("openQuickViewSniffedText"),
diff --git a/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc b/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc
index 7601b0ab..81be5098 100644
--- a/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc
+++ b/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc
@@ -191,7 +191,8 @@
   location_bar_ = location_bar.get();
 
   // Reload button.
-  auto reload = std::make_unique<ReloadButton>(command_updater_.get());
+  auto reload = std::make_unique<ReloadButton>(
+      command_updater_.get(), ReloadButton::IconStyle::kBrowser);
   reload->set_triggerable_event_flags(ui::EF_LEFT_MOUSE_BUTTON |
                                       ui::EF_MIDDLE_MOUSE_BUTTON);
   reload->set_tag(IDC_RELOAD);
diff --git a/chrome/browser/chromeos/policy/fuzzer/policy_fuzzer.cc b/chrome/browser/chromeos/policy/fuzzer/policy_fuzzer.cc
index 166ce89..eb0f5a543 100644
--- a/chrome/browser/chromeos/policy/fuzzer/policy_fuzzer.cc
+++ b/chrome/browser/chromeos/policy/fuzzer/policy_fuzzer.cc
@@ -2,10 +2,12 @@
 // 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/logging.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/policy/device_policy_decoder_chromeos.h"
 #include "chrome/browser/chromeos/policy/fuzzer/policy_fuzzer.pb.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/policy/core/common/external_data_manager.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_types.h"
@@ -13,13 +15,21 @@
 
 namespace policy {
 
+bool FuzzTestInitializer() {
+  base::CommandLine::Init(0, nullptr);
+  chromeos::DBusThreadManager::Initialize();
+  return true;
+}
+
 DEFINE_PROTO_FUZZER(const PolicyFuzzerProto& proto) {
+  static bool initialized = FuzzTestInitializer();
+  CHECK(initialized);
+
   if (!proto.has_chrome_device_settings())
     return;
 
   const enterprise_management::ChromeDeviceSettingsProto&
       chrome_device_settings = proto.chrome_device_settings();
-
   base::WeakPtr<ExternalDataManager> data_manager;
   PolicyMap policy_map;
   DecodeDevicePolicy(chrome_device_settings, data_manager, &policy_map);
diff --git a/chrome/browser/download/download_frame_policy_browsertest.cc b/chrome/browser/download/download_frame_policy_browsertest.cc
index f927903..a9ca8ea7 100644
--- a/chrome/browser/download/download_frame_policy_browsertest.cc
+++ b/chrome/browser/download/download_frame_policy_browsertest.cc
@@ -71,18 +71,18 @@
 
 enum class SandboxOption {
   kNotSandboxed,
-  kDisallowDownloadsWithoutUserActivation,
-  kAllowDownloadsWithoutUserActivation,
+  kDisallowDownloads,
+  kAllowDownloads,
 };
 
 std::ostream& operator<<(std::ostream& os, SandboxOption sandbox_option) {
   switch (sandbox_option) {
     case SandboxOption::kNotSandboxed:
       return os << "NotSandboxed";
-    case SandboxOption::kDisallowDownloadsWithoutUserActivation:
-      return os << "DisallowDownloadsWithoutUserActivation";
-    case SandboxOption::kAllowDownloadsWithoutUserActivation:
-      return os << "AllowDownloadsWithoutUserActivation";
+    case SandboxOption::kDisallowDownloads:
+      return os << "DisallowDownloads";
+    case SandboxOption::kAllowDownloads:
+      return os << "AllowDownloads";
   }
 }
 
@@ -90,7 +90,7 @@
     "'allow-scripts allow-same-origin allow-top-navigation allow-popups'";
 const char kSandboxTokensAllowDownloads[] =
     "'allow-scripts allow-same-origin allow-top-navigation allow-popups "
-    "allow-downloads-without-user-activation'";
+    "allow-downloads'";
 
 // Allow PageLoadMetricsTestWaiter to be initialized for a new web content
 // before the first commit.
@@ -193,8 +193,7 @@
     std::string sandbox_param =
         sandbox_option == SandboxOption::kNotSandboxed
             ? "undefined"
-            : sandbox_option ==
-                      SandboxOption::kDisallowDownloadsWithoutUserActivation
+            : sandbox_option == SandboxOption::kDisallowDownloads
                   ? kSandboxTokensDisallowDownloads
                   : kSandboxTokensAllowDownloads;
     std::string script =
@@ -286,23 +285,20 @@
 
 class SubframeSameFrameDownloadBrowserTest_Sandbox
     : public DownloadFramePolicyBrowserTest,
-      public ::testing::WithParamInterface<std::tuple<
-          DownloadSource,
-          bool /*
-          enable_blocking_downloads_in_sandbox_without_user_activation
-                */
-          ,
-          SandboxOption,
-          bool /* is_cross_origin */,
-          bool /* initiate_with_gesture */>> {
+      public ::testing::WithParamInterface<
+          std::tuple<DownloadSource,
+                     bool /*
+                     enable_blocking_downloads_in_sandbox
+                           */
+                     ,
+                     SandboxOption,
+                     bool /* is_cross_origin */>> {
   void SetUpCommandLine(base::CommandLine* command_line) override {
-    bool enable_blocking_downloads_in_sandbox_without_user_activation;
-    std::tie(std::ignore,
-             enable_blocking_downloads_in_sandbox_without_user_activation,
-             std::ignore, std::ignore, std::ignore) = GetParam();
-    SetRuntimeFeatureCommand(
-        enable_blocking_downloads_in_sandbox_without_user_activation,
-        "BlockingDownloadsInSandboxWithoutUserActivation", command_line);
+    bool enable_blocking_downloads_in_sandbox;
+    std::tie(std::ignore, enable_blocking_downloads_in_sandbox, std::ignore,
+             std::ignore) = GetParam();
+    SetRuntimeFeatureCommand(enable_blocking_downloads_in_sandbox,
+                             "BlockingDownloadsInSandbox", command_line);
   }
 };
 
@@ -310,29 +306,21 @@
 // correctly. This test specifically tests sandbox related behaviors.
 IN_PROC_BROWSER_TEST_P(SubframeSameFrameDownloadBrowserTest_Sandbox, Download) {
   DownloadSource source;
-  bool enable_blocking_downloads_in_sandbox_without_user_activation;
+  bool enable_blocking_downloads_in_sandbox;
   SandboxOption sandbox_option;
   bool is_cross_origin;
-  bool initiate_with_gesture;
-  std::tie(source, enable_blocking_downloads_in_sandbox_without_user_activation,
-           sandbox_option, is_cross_origin, initiate_with_gesture) = GetParam();
-  SCOPED_TRACE(
-      ::testing::Message()
-      << "source = " << source << ", "
-      << "enable_blocking_downloads_in_sandbox_without_user_activation = "
-      << enable_blocking_downloads_in_sandbox_without_user_activation << ", "
-      << "sandbox_option = " << sandbox_option << ", "
-      << "is_cross_origin = " << is_cross_origin << ", "
-      << "initiate_with_gesture = " << initiate_with_gesture);
+  std::tie(source, enable_blocking_downloads_in_sandbox, sandbox_option,
+           is_cross_origin) = GetParam();
+  SCOPED_TRACE(::testing::Message()
+               << "source = " << source << ", "
+               << "enable_blocking_downloads_in_sandbox = "
+               << enable_blocking_downloads_in_sandbox << ", "
+               << "sandbox_option = " << sandbox_option << ", "
+               << "is_cross_origin = " << is_cross_origin);
 
-  bool expect_download =
-      !enable_blocking_downloads_in_sandbox_without_user_activation ||
-      initiate_with_gesture ||
-      sandbox_option != SandboxOption::kDisallowDownloadsWithoutUserActivation;
-  bool sandboxed =
-      sandbox_option == SandboxOption::kDisallowDownloadsWithoutUserActivation;
-  bool expect_download_in_sandbox_without_user_activation =
-      sandboxed && !initiate_with_gesture;
+  bool expect_download = !enable_blocking_downloads_in_sandbox ||
+                         sandbox_option != SandboxOption::kDisallowDownloads;
+  bool sandboxed = sandbox_option == SandboxOption::kDisallowDownloads;
 
   InitializeHistogramTesterAndWebFeatureWaiter();
   SetNumDownloadsExpectation(expect_download);
@@ -349,12 +337,9 @@
     GetWebFeatureWaiter()->AddWebFeatureExpectation(
         blink::mojom::WebFeature::kDownloadInSandbox);
   }
-  if (expect_download_in_sandbox_without_user_activation) {
-    GetWebFeatureWaiter()->AddWebFeatureExpectation(
-        blink::mojom::WebFeature::kDownloadInSandboxWithoutUserGesture);
-  }
 
-  TriggerDownloadSameFrame(GetSubframeRfh(), source, initiate_with_gesture);
+  TriggerDownloadSameFrame(GetSubframeRfh(), source,
+                           true /* initiate_with_gesture */);
 
   GetWebFeatureWaiter()->Wait();
 
@@ -364,16 +349,13 @@
 INSTANTIATE_TEST_SUITE_P(
     /* no prefix */,
     SubframeSameFrameDownloadBrowserTest_Sandbox,
-    ::testing::Combine(
-        ::testing::Values(DownloadSource::kNavigation,
-                          DownloadSource::kAnchorAttribute),
-        ::testing::Bool(),
-        ::testing::Values(
-            SandboxOption::kNotSandboxed,
-            SandboxOption::kDisallowDownloadsWithoutUserActivation,
-            SandboxOption::kAllowDownloadsWithoutUserActivation),
-        ::testing::Bool(),
-        ::testing::Bool()));
+    ::testing::Combine(::testing::Values(DownloadSource::kNavigation,
+                                         DownloadSource::kAnchorAttribute),
+                       ::testing::Bool(),
+                       ::testing::Values(SandboxOption::kNotSandboxed,
+                                         SandboxOption::kDisallowDownloads,
+                                         SandboxOption::kAllowDownloads),
+                       ::testing::Bool()));
 
 class SubframeSameFrameDownloadBrowserTest_AdFrame
     : public DownloadFramePolicyBrowserTest,
@@ -466,20 +448,18 @@
 
 class OtherFrameNavigationDownloadBrowserTest_Sandbox
     : public DownloadFramePolicyBrowserTest,
-      public ::testing::WithParamInterface<std::tuple<
-          bool /* enable_blocking_downloads_in_sandbox_without_user_activation
-                */
-          ,
-          bool /* is_cross_origin */,
-          bool /* initiate_with_gesture */,
-          OtherFrameNavigationType>> {
+      public ::testing::WithParamInterface<
+          std::tuple<bool /* enable_blocking_downloads_in_sandbox
+                           */
+                     ,
+                     bool /* is_cross_origin */,
+                     OtherFrameNavigationType>> {
   void SetUpCommandLine(base::CommandLine* command_line) override {
-    bool enable_blocking_downloads_in_sandbox_without_user_activation;
-    std::tie(enable_blocking_downloads_in_sandbox_without_user_activation,
-             std::ignore, std::ignore, std::ignore) = GetParam();
-    SetRuntimeFeatureCommand(
-        enable_blocking_downloads_in_sandbox_without_user_activation,
-        "BlockingDownloadsInSandboxWithoutUserActivation", command_line);
+    bool enable_blocking_downloads_in_sandbox;
+    std::tie(enable_blocking_downloads_in_sandbox, std::ignore, std::ignore) =
+        GetParam();
+    SetRuntimeFeatureCommand(enable_blocking_downloads_in_sandbox,
+                             "BlockingDownloadsInSandbox", command_line);
   }
 };
 
@@ -487,43 +467,30 @@
 // only one frame being sandboxed. Also covers the remote frame navigation path.
 IN_PROC_BROWSER_TEST_P(OtherFrameNavigationDownloadBrowserTest_Sandbox,
                        Download) {
-  bool enable_blocking_downloads_in_sandbox_without_user_activation;
+  bool enable_blocking_downloads_in_sandbox;
   bool is_cross_origin;
-  bool initiate_with_gesture;
   OtherFrameNavigationType other_frame_navigation_type;
-  std::tie(enable_blocking_downloads_in_sandbox_without_user_activation,
-           is_cross_origin, initiate_with_gesture,
+  std::tie(enable_blocking_downloads_in_sandbox, is_cross_origin,
            other_frame_navigation_type) = GetParam();
-  SCOPED_TRACE(
-      ::testing::Message()
-      << "enable_blocking_downloads_in_sandbox_without_user_activation = "
-      << enable_blocking_downloads_in_sandbox_without_user_activation << ", "
-      << "is_cross_origin = " << is_cross_origin << ", "
-      << "initiate_with_gesture = " << initiate_with_gesture << ", "
-      << "other_frame_navigation_type = " << other_frame_navigation_type);
+  SCOPED_TRACE(::testing::Message()
+               << "enable_blocking_downloads_in_sandbox = "
+               << enable_blocking_downloads_in_sandbox << ", "
+               << "is_cross_origin = " << is_cross_origin << ", "
+               << "other_frame_navigation_type = "
+               << other_frame_navigation_type);
 
-  // Currently, cross-process navigation doesn't carry the gesture regardless
-  // whether the initiator frame has gesture or not.
-  bool expect_gesture = initiate_with_gesture && !is_cross_origin;
-
-  bool expect_download =
-      !enable_blocking_downloads_in_sandbox_without_user_activation ||
-      expect_gesture;
+  bool expect_download = !enable_blocking_downloads_in_sandbox;
 
   InitializeHistogramTesterAndWebFeatureWaiter();
   SetNumDownloadsExpectation(expect_download);
-  InitializeOneSubframeSetup(
-      SandboxOption::kDisallowDownloadsWithoutUserActivation,
-      false /* is_ad_frame */, is_cross_origin /* is_cross_origin */);
+  InitializeOneSubframeSetup(SandboxOption::kDisallowDownloads,
+                             false /* is_ad_frame */,
+                             is_cross_origin /* is_cross_origin */);
 
   GetWebFeatureWaiter()->AddWebFeatureExpectation(
       blink::mojom::WebFeature::kDownloadPrePolicyCheck);
   GetWebFeatureWaiter()->AddWebFeatureExpectation(
       blink::mojom::WebFeature::kDownloadInSandbox);
-  if (!expect_gesture) {
-    GetWebFeatureWaiter()->AddWebFeatureExpectation(
-        blink::mojom::WebFeature::kDownloadInSandboxWithoutUserGesture);
-  }
   if (expect_download) {
     GetWebFeatureWaiter()->AddWebFeatureExpectation(
         blink::mojom::WebFeature::kDownloadPostPolicyCheck);
@@ -533,19 +500,11 @@
       OtherFrameNavigationType::
           kRestrictedSubframeNavigatesUnrestrictedTopFrame) {
     std::string script = "top.location = 'allow.zip';";
-    if (initiate_with_gesture) {
-      EXPECT_TRUE(ExecJs(GetSubframeRfh(), script));
-    } else {
-      EXPECT_TRUE(ExecuteScriptWithoutUserGesture(GetSubframeRfh(), script));
-    }
+    EXPECT_TRUE(ExecJs(GetSubframeRfh(), script));
   } else {
     std::string script =
         "document.getElementById('" + GetSubframeId() + "').src = 'allow.zip';";
-    if (initiate_with_gesture) {
-      EXPECT_TRUE(ExecJs(web_contents(), script));
-    } else {
-      EXPECT_TRUE(ExecuteScriptWithoutUserGesture(web_contents(), script));
-    }
+    EXPECT_TRUE(ExecJs(web_contents(), script));
   }
 
   GetWebFeatureWaiter()->Wait();
@@ -559,7 +518,6 @@
     ::testing::Combine(
         ::testing::Bool(),
         ::testing::Bool(),
-        ::testing::Bool(),
         ::testing::Values(
             OtherFrameNavigationType::
                 kRestrictedSubframeNavigatesUnrestrictedTopFrame,
@@ -686,21 +644,18 @@
 
 class TopFrameSameFrameDownloadBrowserTest
     : public DownloadFramePolicyBrowserTest,
-      public ::testing::WithParamInterface<std::tuple<
-          DownloadSource,
-          bool /* enable_blocking_downloads_in_sandbox_without_user_activation
-                */
-          ,
-          SandboxOption,
-          bool /* initiate_with_gesture */>> {
+      public ::testing::WithParamInterface<
+          std::tuple<DownloadSource,
+                     bool /* enable_blocking_downloads_in_sandbox
+                           */
+                     ,
+                     SandboxOption>> {
   void SetUpCommandLine(base::CommandLine* command_line) override {
-    bool enable_blocking_downloads_in_sandbox_without_user_activation;
-    std::tie(std::ignore,
-             enable_blocking_downloads_in_sandbox_without_user_activation,
-             std::ignore, std::ignore) = GetParam();
-    SetRuntimeFeatureCommand(
-        enable_blocking_downloads_in_sandbox_without_user_activation,
-        "BlockingDownloadsInSandboxWithoutUserActivation", command_line);
+    bool enable_blocking_downloads_in_sandbox;
+    std::tie(std::ignore, enable_blocking_downloads_in_sandbox, std::ignore) =
+        GetParam();
+    SetRuntimeFeatureCommand(enable_blocking_downloads_in_sandbox,
+                             "BlockingDownloadsInSandbox", command_line);
   }
 };
 
@@ -708,27 +663,19 @@
 // correctly.
 IN_PROC_BROWSER_TEST_P(TopFrameSameFrameDownloadBrowserTest, Download) {
   DownloadSource source;
-  bool enable_blocking_downloads_in_sandbox_without_user_activation;
+  bool enable_blocking_downloads_in_sandbox;
   SandboxOption sandbox_option;
-  bool initiate_with_gesture;
-  std::tie(source, enable_blocking_downloads_in_sandbox_without_user_activation,
-           sandbox_option, initiate_with_gesture) = GetParam();
-  SCOPED_TRACE(
-      ::testing::Message()
-      << "source = " << source << ", "
-      << "enable_blocking_downloads_in_sandbox_without_user_activation = "
-      << enable_blocking_downloads_in_sandbox_without_user_activation << ", "
-      << "sandbox_option = " << sandbox_option << ", "
-      << "initiate_with_gesture = " << initiate_with_gesture);
+  std::tie(source, enable_blocking_downloads_in_sandbox, sandbox_option) =
+      GetParam();
+  SCOPED_TRACE(::testing::Message()
+               << "source = " << source << ", "
+               << "enable_blocking_downloads_in_sandbox = "
+               << enable_blocking_downloads_in_sandbox << ", "
+               << "sandbox_option = " << sandbox_option);
 
-  bool expect_download =
-      !enable_blocking_downloads_in_sandbox_without_user_activation ||
-      initiate_with_gesture ||
-      sandbox_option != SandboxOption::kDisallowDownloadsWithoutUserActivation;
-  bool sandboxed =
-      sandbox_option == SandboxOption::kDisallowDownloadsWithoutUserActivation;
-  bool expect_download_in_sandbox_without_user_activation =
-      sandboxed && !initiate_with_gesture;
+  bool expect_download = !enable_blocking_downloads_in_sandbox ||
+                         sandbox_option != SandboxOption::kDisallowDownloads;
+  bool sandboxed = sandbox_option == SandboxOption::kDisallowDownloads;
 
   InitializeHistogramTesterAndWebFeatureWaiter();
   SetNumDownloadsExpectation(expect_download);
@@ -744,12 +691,9 @@
     GetWebFeatureWaiter()->AddWebFeatureExpectation(
         blink::mojom::WebFeature::kDownloadInSandbox);
   }
-  if (expect_download_in_sandbox_without_user_activation) {
-    GetWebFeatureWaiter()->AddWebFeatureExpectation(
-        blink::mojom::WebFeature::kDownloadInSandboxWithoutUserGesture);
-  }
 
-  TriggerDownloadSameFrame(web_contents(), source, initiate_with_gesture);
+  TriggerDownloadSameFrame(web_contents(), source,
+                           true /* initiate_with_gesture */);
 
   GetWebFeatureWaiter()->Wait();
 
@@ -759,15 +703,12 @@
 INSTANTIATE_TEST_SUITE_P(
     /* no prefix */,
     TopFrameSameFrameDownloadBrowserTest,
-    ::testing::Combine(
-        ::testing::Values(DownloadSource::kNavigation,
-                          DownloadSource::kAnchorAttribute),
-        ::testing::Bool(),
-        ::testing::Values(
-            SandboxOption::kNotSandboxed,
-            SandboxOption::kDisallowDownloadsWithoutUserActivation,
-            SandboxOption::kAllowDownloadsWithoutUserActivation),
-        ::testing::Bool()));
+    ::testing::Combine(::testing::Values(DownloadSource::kNavigation,
+                                         DownloadSource::kAnchorAttribute),
+                       ::testing::Bool(),
+                       ::testing::Values(SandboxOption::kNotSandboxed,
+                                         SandboxOption::kDisallowDownloads,
+                                         SandboxOption::kAllowDownloads)));
 
 // Download gets blocked when LoadPolicy is DISALLOW for the navigation to
 // download. This test is technically unrelated to policy on frame, but stays
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc b/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
index 04622a3..797f32a0 100644
--- a/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
+++ b/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/account_reconcilor_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
-#include "chrome/browser/signin/scoped_account_consistency.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/sync_ui_util.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/extensions/api/file_handlers/non_native_file_system_delegate_chromeos.cc b/chrome/browser/extensions/api/file_handlers/non_native_file_system_delegate_chromeos.cc
index f4edcbf..f0897056 100644
--- a/chrome/browser/extensions/api/file_handlers/non_native_file_system_delegate_chromeos.cc
+++ b/chrome/browser/extensions/api/file_handlers/non_native_file_system_delegate_chromeos.cc
@@ -44,9 +44,9 @@
 void NonNativeFileSystemDelegateChromeOS::IsNonNativeLocalPathDirectory(
     content::BrowserContext* context,
     const base::FilePath& path,
-    const base::Callback<void(bool)>& callback) {
+    base::OnceCallback<void(bool)> callback) {
   file_manager::util::IsNonNativeLocalPathDirectory(
-      Profile::FromBrowserContext(context), path, callback);
+      Profile::FromBrowserContext(context), path, std::move(callback));
 }
 
 // Ensures a non-local file exists at |path|, i.e., it does nothing if a file
@@ -56,9 +56,9 @@
     PrepareNonNativeLocalFileForWritableApp(
         content::BrowserContext* context,
         const base::FilePath& path,
-        const base::Callback<void(bool)>& callback) {
+        base::OnceCallback<void(bool)> callback) {
   file_manager::util::PrepareNonNativeLocalFileForWritableApp(
-      Profile::FromBrowserContext(context), path, callback);
+      Profile::FromBrowserContext(context), path, std::move(callback));
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/file_handlers/non_native_file_system_delegate_chromeos.h b/chrome/browser/extensions/api/file_handlers/non_native_file_system_delegate_chromeos.h
index d9405f8..abcde24 100644
--- a/chrome/browser/extensions/api/file_handlers/non_native_file_system_delegate_chromeos.h
+++ b/chrome/browser/extensions/api/file_handlers/non_native_file_system_delegate_chromeos.h
@@ -37,11 +37,11 @@
   void IsNonNativeLocalPathDirectory(
       content::BrowserContext* context,
       const base::FilePath& path,
-      const base::Callback<void(bool)>& callback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void PrepareNonNativeLocalFileForWritableApp(
       content::BrowserContext* context,
       const base::FilePath& path,
-      const base::Callback<void(bool)>& callback) override;
+      base::OnceCallback<void(bool)> callback) override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(NonNativeFileSystemDelegateChromeOS);
diff --git a/chrome/browser/extensions/api/identity/identity_api_unittest.cc b/chrome/browser/extensions/api/identity/identity_api_unittest.cc
index 40c2b16..72d96fcf 100644
--- a/chrome/browser/extensions/api/identity/identity_api_unittest.cc
+++ b/chrome/browser/extensions/api/identity/identity_api_unittest.cc
@@ -6,7 +6,6 @@
 
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
-#include "chrome/browser/signin/scoped_account_consistency.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/signin/public/base/signin_buildflags.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/extensions/api/image_writer_private/test_utils.cc b/chrome/browser/extensions/api/image_writer_private/test_utils.cc
index 4828d5c..6a22377 100644
--- a/chrome/browser/extensions/api/image_writer_private/test_utils.cc
+++ b/chrome/browser/extensions/api/image_writer_private/test_utils.cc
@@ -42,7 +42,7 @@
 
   void BurnImage(const std::string& from_path,
                  const std::string& to_path,
-                 const ErrorCallback& error_callback) override {
+                 ErrorCallback error_callback) override {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
         base::BindOnce(burn_progress_update_handler_, to_path, 0, 100));
diff --git a/chrome/browser/metrics/ukm_browsertest.cc b/chrome/browser/metrics/ukm_browsertest.cc
index 37ae356..0567ed3 100644
--- a/chrome/browser/metrics/ukm_browsertest.cc
+++ b/chrome/browser/metrics/ukm_browsertest.cc
@@ -57,10 +57,6 @@
 #include "third_party/zlib/google/compression_utils.h"
 #include "url/url_constants.h"
 
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
-#include "chrome/browser/signin/scoped_account_consistency.h"
-#endif
-
 namespace metrics {
 
 namespace {
diff --git a/chrome/browser/policy/content_settings_policy_browsertest.cc b/chrome/browser/policy/content_settings_policy_browsertest.cc
new file mode 100644
index 0000000..344887f5
--- /dev/null
+++ b/chrome/browser/policy/content_settings_policy_browsertest.cc
@@ -0,0 +1,272 @@
+// Copyright 2019 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 <string>
+
+#include "base/command_line.h"
+#include "base/strings/strcat.h"
+#include "base/values.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+#include "chrome/browser/policy/policy_test_utils.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/usb/usb_chooser_context.h"
+#include "chrome/browser/usb/usb_chooser_context_factory.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/policy_constants.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "device/bluetooth/bluetooth_adapter_factory.h"
+#include "device/bluetooth/test/mock_bluetooth_adapter.h"
+#include "services/device/public/cpp/test/fake_usb_device_info.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace policy {
+
+namespace {
+const char kURL[] = "http://example.com";
+const char kCookieValue[] = "converted=true";
+// Assigned to Philip J. Fry to fix eventually.
+// TODO(maksims): use year 3000 when we get rid off the 32-bit
+// versions. https://crbug.com/619828
+const char kCookieOptions[] = ";expires=Wed Jan 01 2038 00:00:00 GMT";
+
+bool IsJavascriptEnabled(content::WebContents* contents) {
+  base::Value value =
+      content::ExecuteScriptAndGetValue(contents->GetMainFrame(), "123");
+  return value.is_int() && value.GetInt() == 123;
+}
+
+}  // namespace
+
+IN_PROC_BROWSER_TEST_F(PolicyTest, PRE_PRE_DefaultCookiesSetting) {
+  // Verifies that cookies are deleted on shutdown. This test is split in 3
+  // parts because it spans 2 browser restarts.
+
+  Profile* profile = browser()->profile();
+  GURL url(kURL);
+  // No cookies at startup.
+  EXPECT_TRUE(content::GetCookies(profile, url).empty());
+  // Set a cookie now.
+  std::string value = base::StrCat({kCookieValue, kCookieOptions});
+  EXPECT_TRUE(content::SetCookie(profile, url, value));
+  // Verify it was set.
+  EXPECT_EQ(kCookieValue, GetCookies(profile, url));
+}
+
+IN_PROC_BROWSER_TEST_F(PolicyTest, PRE_DefaultCookiesSetting) {
+  // Verify that the cookie persists across restarts.
+  EXPECT_EQ(kCookieValue, GetCookies(browser()->profile(), GURL(kURL)));
+  // Now set the policy and the cookie should be gone after another restart.
+  PolicyMap policies;
+  policies.Set(key::kDefaultCookiesSetting, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               std::make_unique<base::Value>(CONTENT_SETTING_SESSION_ONLY),
+               nullptr);
+  UpdateProviderPolicy(policies);
+}
+
+IN_PROC_BROWSER_TEST_F(PolicyTest, DefaultCookiesSetting) {
+  // Verify that the cookie is gone.
+  EXPECT_TRUE(GetCookies(browser()->profile(), GURL(kURL)).empty());
+}
+
+IN_PROC_BROWSER_TEST_F(PolicyTest, PRE_PRE_WebsiteCookiesSetting) {
+  // Verifies that cookies are deleted on shutdown. This test is split in 3
+  // parts because it spans 2 browser restarts.
+
+  Profile* profile = browser()->profile();
+  GURL url(kURL);
+  // No cookies at startup.
+  EXPECT_TRUE(content::GetCookies(profile, url).empty());
+  // Set a cookie now.
+  std::string value = base::StrCat({kCookieValue, kCookieOptions});
+  EXPECT_TRUE(content::SetCookie(profile, url, value));
+  // Verify it was set.
+  EXPECT_EQ(kCookieValue, GetCookies(profile, url));
+}
+
+IN_PROC_BROWSER_TEST_F(PolicyTest, PRE_WebsiteCookiesSetting) {
+  // Verify that the cookie persists across restarts.
+  EXPECT_EQ(kCookieValue, GetCookies(browser()->profile(), GURL(kURL)));
+  // Now set the policy and the cookie should be gone after another restart.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->SetWebsiteSettingDefaultScope(
+          GURL(kURL), GURL(kURL), ContentSettingsType::COOKIES, std::string(),
+          std::make_unique<base::Value>(CONTENT_SETTING_SESSION_ONLY));
+}
+
+IN_PROC_BROWSER_TEST_F(PolicyTest, WebsiteCookiesSetting) {
+  // Verify that the cookie is gone.
+  EXPECT_TRUE(GetCookies(browser()->profile(), GURL(kURL)).empty());
+}
+
+IN_PROC_BROWSER_TEST_F(PolicyTest, Javascript) {
+  // Verifies that Javascript can be disabled.
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(IsJavascriptEnabled(contents));
+  EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEV_TOOLS));
+  EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEV_TOOLS_CONSOLE));
+  EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEV_TOOLS_DEVICES));
+
+  // Disable Javascript via policy.
+  PolicyMap policies;
+  policies.Set(key::kJavascriptEnabled, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               std::make_unique<base::Value>(false), nullptr);
+  UpdateProviderPolicy(policies);
+  // Reload the page.
+  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+  EXPECT_FALSE(IsJavascriptEnabled(contents));
+  // Developer tools still work when javascript is disabled.
+  EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEV_TOOLS));
+  EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEV_TOOLS_CONSOLE));
+  EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEV_TOOLS_DEVICES));
+  // Javascript is always enabled for the internal pages.
+  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIAboutURL));
+  EXPECT_TRUE(IsJavascriptEnabled(contents));
+
+  // The javascript content setting policy overrides the javascript policy.
+  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+  EXPECT_FALSE(IsJavascriptEnabled(contents));
+  policies.Set(key::kDefaultJavaScriptSetting, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               std::make_unique<base::Value>(CONTENT_SETTING_ALLOW), nullptr);
+  UpdateProviderPolicy(policies);
+  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+  EXPECT_TRUE(IsJavascriptEnabled(contents));
+}
+
+class WebBluetoothPolicyTest : public PolicyTest {
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    // TODO(juncai): Remove this switch once Web Bluetooth is supported on Linux
+    // and Windows.
+    // https://crbug.com/570344
+    // https://crbug.com/507419
+    command_line->AppendSwitch(
+        switches::kEnableExperimentalWebPlatformFeatures);
+    PolicyTest::SetUpCommandLine(command_line);
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(WebBluetoothPolicyTest, Block) {
+  // Fake the BluetoothAdapter to say it's present.
+  scoped_refptr<device::MockBluetoothAdapter> adapter =
+      new testing::NiceMock<device::MockBluetoothAdapter>;
+  EXPECT_CALL(*adapter, IsPresent()).WillRepeatedly(testing::Return(true));
+  auto bt_global_values =
+      device::BluetoothAdapterFactory::Get().InitGlobalValuesForTesting();
+  bt_global_values->SetLESupported(true);
+  device::BluetoothAdapterFactory::SetAdapterForTesting(adapter);
+
+  // Navigate to a secure context.
+  embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
+  ASSERT_TRUE(embedded_test_server()->Start());
+  ui_test_utils::NavigateToURL(
+      browser(),
+      embedded_test_server()->GetURL("localhost", "/simple_page.html"));
+  content::WebContents* const web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_THAT(
+      web_contents->GetMainFrame()->GetLastCommittedOrigin().Serialize(),
+      testing::StartsWith("http://localhost:"));
+
+  // Set the policy to block Web Bluetooth.
+  PolicyMap policies;
+  policies.Set(key::kDefaultWebBluetoothGuardSetting, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               std::make_unique<base::Value>(2), nullptr);
+  UpdateProviderPolicy(policies);
+
+  std::string rejection;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      web_contents,
+      "navigator.bluetooth.requestDevice({filters: [{name: 'Hello'}]})"
+      "  .then(() => { domAutomationController.send('Success'); },"
+      "        reason => {"
+      "      domAutomationController.send(reason.name + ': ' + reason.message);"
+      "  });",
+      &rejection));
+  EXPECT_THAT(rejection, testing::MatchesRegex("NotFoundError: .*policy.*"));
+}
+
+IN_PROC_BROWSER_TEST_F(PolicyTest, WebUsbDefault) {
+  const auto kTestOrigin = url::Origin::Create(GURL("https://foo.com:443"));
+
+  // Expect the default permission value to be 'ask'.
+  auto* context = UsbChooserContextFactory::GetForProfile(browser()->profile());
+  EXPECT_TRUE(context->CanRequestObjectPermission(kTestOrigin, kTestOrigin));
+
+  // Update policy to change the default permission value to 'block'.
+  PolicyMap policies;
+  SetPolicy(&policies, key::kDefaultWebUsbGuardSetting,
+            std::make_unique<base::Value>(2));
+  UpdateProviderPolicy(policies);
+  EXPECT_FALSE(context->CanRequestObjectPermission(kTestOrigin, kTestOrigin));
+
+  // Update policy to change the default permission value to 'ask'.
+  SetPolicy(&policies, key::kDefaultWebUsbGuardSetting,
+            std::make_unique<base::Value>(3));
+  UpdateProviderPolicy(policies);
+  EXPECT_TRUE(context->CanRequestObjectPermission(kTestOrigin, kTestOrigin));
+}
+
+IN_PROC_BROWSER_TEST_F(PolicyTest, WebUsbAllowDevicesForUrls) {
+  const auto kTestOrigin = url::Origin::Create(GURL("https://foo.com:443"));
+  scoped_refptr<device::FakeUsbDeviceInfo> device =
+      base::MakeRefCounted<device::FakeUsbDeviceInfo>(0, 0, "Google", "Gizmo",
+                                                      "123ABC");
+  const auto& device_info = device->GetDeviceInfo();
+
+  // Expect the default permission value to be empty.
+  auto* context = UsbChooserContextFactory::GetForProfile(browser()->profile());
+  EXPECT_FALSE(
+      context->HasDevicePermission(kTestOrigin, kTestOrigin, device_info));
+
+  // Update policy to add an entry to the permission value to allow
+  // |kTestOrigin| to access the device described by |device_info|.
+  PolicyMap policies;
+
+  base::Value device_value(base::Value::Type::DICTIONARY);
+  device_value.SetKey("vendor_id", base::Value(0));
+  device_value.SetKey("product_id", base::Value(0));
+
+  base::Value devices_value(base::Value::Type::LIST);
+  devices_value.Append(std::move(device_value));
+
+  base::Value urls_value(base::Value::Type::LIST);
+  urls_value.Append(base::Value("https://foo.com"));
+
+  base::Value entry(base::Value::Type::DICTIONARY);
+  entry.SetKey("devices", std::move(devices_value));
+  entry.SetKey("urls", std::move(urls_value));
+
+  auto policy_value = std::make_unique<base::Value>(base::Value::Type::LIST);
+  policy_value->Append(std::move(entry));
+
+  SetPolicy(&policies, key::kWebUsbAllowDevicesForUrls,
+            std::move(policy_value));
+  UpdateProviderPolicy(policies);
+
+  EXPECT_TRUE(
+      context->HasDevicePermission(kTestOrigin, kTestOrigin, device_info));
+
+  // Remove the policy to ensure that it can be dynamically updated.
+  SetPolicy(&policies, key::kWebUsbAllowDevicesForUrls,
+            std::make_unique<base::Value>(base::Value::Type::LIST));
+  UpdateProviderPolicy(policies);
+
+  EXPECT_FALSE(
+      context->HasDevicePermission(kTestOrigin, kTestOrigin, device_info));
+}
+
+}  // namespace policy
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 3e12f8a..2fd05c0 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -67,7 +67,6 @@
 #include "chrome/browser/chromeos/login/test/session_manager_state_waiter.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
 #include "chrome/browser/component_updater/chrome_component_updater_configurator.h"
-#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
 #include "chrome/browser/devtools/devtools_window_testing.h"
 #include "chrome/browser/download/download_prefs.h"
@@ -85,7 +84,6 @@
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/resource_coordinator/tab_load_tracker_test_support.h"
-#include "chrome/browser/safe_browsing/chrome_password_protection_service.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/task_manager/task_manager_interface.h"
@@ -102,8 +100,6 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_model.h"
 #include "chrome/browser/ui/webui/welcome/helpers.h"
-#include "chrome/browser/usb/usb_chooser_context.h"
-#include "chrome/browser/usb/usb_chooser_context_factory.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
@@ -123,7 +119,6 @@
 #include "components/browsing_data/core/pref_names.h"
 #include "components/component_updater/component_updater_service.h"
 #include "components/component_updater/component_updater_switches.h"
-#include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/content_settings_pattern.h"
 #include "components/content_settings/core/common/pref_names.h"
@@ -145,8 +140,6 @@
 #include "components/policy/core/common/policy_types.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_service.h"
-#include "components/safe_browsing/features.h"
-#include "components/safe_browsing/realtime/policy_engine.h"
 #include "components/search_engines/template_url.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/security_interstitials/content/security_interstitial_page.h"
@@ -194,8 +187,6 @@
 #include "content/public/test/signed_exchange_browser_test_helper.h"
 #include "content/public/test/test_utils.h"
 #include "content/public/test/url_loader_interceptor.h"
-#include "device/bluetooth/bluetooth_adapter_factory.h"
-#include "device/bluetooth/test/mock_bluetooth_adapter.h"
 #include "extensions/browser/api/messaging/messaging_delegate.h"
 #include "extensions/browser/disable_reason.h"
 #include "extensions/browser/extension_prefs.h"
@@ -214,7 +205,6 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
-#include "services/device/public/cpp/test/fake_usb_device_info.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/network_switches.h"
 #include "services/network/public/mojom/network_service.mojom.h"
@@ -281,7 +271,6 @@
 #endif
 
 using content::BrowserThread;
-using safe_browsing::ReusedPasswordAccountType;
 using testing::_;
 using testing::AtLeast;
 using testing::Mock;
@@ -297,13 +286,6 @@
 const int kThreeHoursInMs = 180 * 60 * 1000;
 #endif
 
-const char kURL[] = "http://example.com";
-const char kCookieValue[] = "converted=true";
-// Assigned to Philip J. Fry to fix eventually.
-// TODO(maksims): use year 3000 when we get rid off the 32-bit
-// versions. https://crbug.com/619828
-const char kCookieOptions[] = ";expires=Wed Jan 01 2038 00:00:00 GMT";
-
 #if !defined(OS_MACOSX)
 const base::FilePath::CharType kUnpackedFullscreenAppName[] =
     FILE_PATH_LITERAL("fullscreen_app");
@@ -429,12 +411,6 @@
   return result;
 }
 
-bool IsJavascriptEnabled(content::WebContents* contents) {
-  base::Value value =
-      content::ExecuteScriptAndGetValue(contents->GetMainFrame(), "123");
-  return value.is_int() && value.GetInt() == 123;
-}
-
 bool IsNetworkPredictionEnabled(PrefService* prefs) {
   return chrome_browser_net::CanPrefetchAndPrerenderUI(prefs) ==
       chrome_browser_net::NetworkPredictionStatus::ENABLED;
@@ -551,23 +527,6 @@
 }
 #endif
 
-class MockPasswordProtectionService
-    : public safe_browsing::ChromePasswordProtectionService {
- public:
-  MockPasswordProtectionService(safe_browsing::SafeBrowsingService* sb_service,
-                                Profile* profile)
-      : safe_browsing::ChromePasswordProtectionService(sb_service, profile) {}
-  ~MockPasswordProtectionService() override {}
-
-  MOCK_CONST_METHOD0(IsPrimaryAccountGmail, bool());
-
-  AccountInfo GetAccountInfo() const override {
-    AccountInfo info;
-    info.email = "user@mycompany.com";
-    return info;
-  }
-};
-
 }  // namespace
 
 #if defined(OS_WIN)
@@ -855,68 +814,6 @@
   EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state());
 }
 
-IN_PROC_BROWSER_TEST_F(PolicyTest, PRE_PRE_DefaultCookiesSetting) {
-  // Verifies that cookies are deleted on shutdown. This test is split in 3
-  // parts because it spans 2 browser restarts.
-
-  Profile* profile = browser()->profile();
-  GURL url(kURL);
-  // No cookies at startup.
-  EXPECT_TRUE(content::GetCookies(profile, url).empty());
-  // Set a cookie now.
-  std::string value = base::StrCat({kCookieValue, kCookieOptions});
-  EXPECT_TRUE(content::SetCookie(profile, url, value));
-  // Verify it was set.
-  EXPECT_EQ(kCookieValue, GetCookies(profile, url));
-}
-
-IN_PROC_BROWSER_TEST_F(PolicyTest, PRE_DefaultCookiesSetting) {
-  // Verify that the cookie persists across restarts.
-  EXPECT_EQ(kCookieValue, GetCookies(browser()->profile(), GURL(kURL)));
-  // Now set the policy and the cookie should be gone after another restart.
-  PolicyMap policies;
-  policies.Set(key::kDefaultCookiesSetting, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(CONTENT_SETTING_SESSION_ONLY),
-               nullptr);
-  UpdateProviderPolicy(policies);
-}
-
-IN_PROC_BROWSER_TEST_F(PolicyTest, DefaultCookiesSetting) {
-  // Verify that the cookie is gone.
-  EXPECT_TRUE(GetCookies(browser()->profile(), GURL(kURL)).empty());
-}
-
-IN_PROC_BROWSER_TEST_F(PolicyTest, PRE_PRE_WebsiteCookiesSetting) {
-  // Verifies that cookies are deleted on shutdown. This test is split in 3
-  // parts because it spans 2 browser restarts.
-
-  Profile* profile = browser()->profile();
-  GURL url(kURL);
-  // No cookies at startup.
-  EXPECT_TRUE(content::GetCookies(profile, url).empty());
-  // Set a cookie now.
-  std::string value = base::StrCat({kCookieValue, kCookieOptions});
-  EXPECT_TRUE(content::SetCookie(profile, url, value));
-  // Verify it was set.
-  EXPECT_EQ(kCookieValue, GetCookies(profile, url));
-}
-
-IN_PROC_BROWSER_TEST_F(PolicyTest, PRE_WebsiteCookiesSetting) {
-  // Verify that the cookie persists across restarts.
-  EXPECT_EQ(kCookieValue, GetCookies(browser()->profile(), GURL(kURL)));
-  // Now set the policy and the cookie should be gone after another restart.
-  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
-      ->SetWebsiteSettingDefaultScope(
-          GURL(kURL), GURL(kURL), ContentSettingsType::COOKIES, std::string(),
-          std::make_unique<base::Value>(CONTENT_SETTING_SESSION_ONLY));
-}
-
-IN_PROC_BROWSER_TEST_F(PolicyTest, WebsiteCookiesSetting) {
-  // Verify that the cookie is gone.
-  EXPECT_TRUE(GetCookies(browser()->profile(), GURL(kURL)).empty());
-}
-
 IN_PROC_BROWSER_TEST_F(PolicyTest, DefaultSearchProvider) {
   // Verifies that a default search is made using the provider configured via
   // policy. Also checks that default search can be completely disabled.
@@ -1656,43 +1553,6 @@
   EXPECT_TRUE(BrowserList::IsIncognitoSessionActive());
 }
 
-IN_PROC_BROWSER_TEST_F(PolicyTest, Javascript) {
-  // Verifies that Javascript can be disabled.
-  content::WebContents* contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_TRUE(IsJavascriptEnabled(contents));
-  EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEV_TOOLS));
-  EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEV_TOOLS_CONSOLE));
-  EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEV_TOOLS_DEVICES));
-
-  // Disable Javascript via policy.
-  PolicyMap policies;
-  policies.Set(key::kJavascriptEnabled, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(false), nullptr);
-  UpdateProviderPolicy(policies);
-  // Reload the page.
-  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
-  EXPECT_FALSE(IsJavascriptEnabled(contents));
-  // Developer tools still work when javascript is disabled.
-  EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEV_TOOLS));
-  EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEV_TOOLS_CONSOLE));
-  EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEV_TOOLS_DEVICES));
-  // Javascript is always enabled for the internal pages.
-  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIAboutURL));
-  EXPECT_TRUE(IsJavascriptEnabled(contents));
-
-  // The javascript content setting policy overrides the javascript policy.
-  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
-  EXPECT_FALSE(IsJavascriptEnabled(contents));
-  policies.Set(key::kDefaultJavaScriptSetting, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(CONTENT_SETTING_ALLOW), nullptr);
-  UpdateProviderPolicy(policies);
-  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
-  EXPECT_TRUE(IsJavascriptEnabled(contents));
-}
-
 IN_PROC_BROWSER_TEST_F(PolicyTest, NetworkPrediction) {
   PrefService* prefs = browser()->profile()->GetPrefs();
 
@@ -2972,59 +2832,6 @@
                          MediaStreamDevicesControllerBrowserTest,
                          testing::Bool());
 
-class WebBluetoothPolicyTest : public PolicyTest {
-  void SetUpCommandLine(base::CommandLine* command_line)override {
-    // TODO(juncai): Remove this switch once Web Bluetooth is supported on Linux
-    // and Windows.
-    // https://crbug.com/570344
-    // https://crbug.com/507419
-    command_line->AppendSwitch(
-        switches::kEnableExperimentalWebPlatformFeatures);
-    PolicyTest::SetUpCommandLine(command_line);
-  }
-};
-
-IN_PROC_BROWSER_TEST_F(WebBluetoothPolicyTest, Block) {
-  // Fake the BluetoothAdapter to say it's present.
-  scoped_refptr<device::MockBluetoothAdapter> adapter =
-      new testing::NiceMock<device::MockBluetoothAdapter>;
-  EXPECT_CALL(*adapter, IsPresent()).WillRepeatedly(testing::Return(true));
-  auto bt_global_values =
-      device::BluetoothAdapterFactory::Get().InitGlobalValuesForTesting();
-  bt_global_values->SetLESupported(true);
-  device::BluetoothAdapterFactory::SetAdapterForTesting(adapter);
-
-  // Navigate to a secure context.
-  embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
-  ASSERT_TRUE(embedded_test_server()->Start());
-  ui_test_utils::NavigateToURL(
-      browser(),
-      embedded_test_server()->GetURL("localhost", "/simple_page.html"));
-  content::WebContents* const web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_THAT(
-      web_contents->GetMainFrame()->GetLastCommittedOrigin().Serialize(),
-      testing::StartsWith("http://localhost:"));
-
-  // Set the policy to block Web Bluetooth.
-  PolicyMap policies;
-  policies.Set(key::kDefaultWebBluetoothGuardSetting, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(2), nullptr);
-  UpdateProviderPolicy(policies);
-
-  std::string rejection;
-  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
-      web_contents,
-      "navigator.bluetooth.requestDevice({filters: [{name: 'Hello'}]})"
-      "  .then(() => { domAutomationController.send('Success'); },"
-      "        reason => {"
-      "      domAutomationController.send(reason.name + ': ' + reason.message);"
-      "  });",
-      &rejection));
-  EXPECT_THAT(rejection, testing::MatchesRegex("NotFoundError: .*policy.*"));
-}
-
 class CertificateTransparencyPolicyTest : public PolicyTest {
  public:
   CertificateTransparencyPolicyTest() : PolicyTest() {
@@ -3155,88 +2962,6 @@
             browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
 }
 
-// Test that when extended reporting opt-in is disabled by policy, the
-// opt-in checkbox does not appear on SSL blocking pages.
-// Note: SafeBrowsingExtendedReportingOptInAllowed policy is being deprecated.
-IN_PROC_BROWSER_TEST_F(PolicyTest, SafeBrowsingExtendedReportingOptInAllowed) {
-  net::EmbeddedTestServer https_server_expired(
-      net::EmbeddedTestServer::TYPE_HTTPS);
-  https_server_expired.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
-  https_server_expired.ServeFilesFromSourceDirectory("chrome/test/data");
-  ASSERT_TRUE(https_server_expired.Start());
-
-  // First, navigate to an SSL error page and make sure the checkbox appears by
-  // default.
-  ui_test_utils::NavigateToURL(browser(), https_server_expired.GetURL("/"));
-  EXPECT_EQ(security_interstitials::CMD_TEXT_FOUND,
-            IsExtendedReportingCheckboxVisibleOnInterstitial());
-
-  // Set the enterprise policy to disallow opt-in.
-  const PrefService* const prefs = browser()->profile()->GetPrefs();
-  EXPECT_TRUE(
-      prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingOptInAllowed));
-  PolicyMap policies;
-  policies.Set(key::kSafeBrowsingExtendedReportingOptInAllowed,
-               POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               base::WrapUnique(new base::Value(false)), nullptr);
-  UpdateProviderPolicy(policies);
-  EXPECT_FALSE(
-      prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingOptInAllowed));
-
-  // Navigate to an SSL error page, the checkbox should not appear.
-  ui_test_utils::NavigateToURL(browser(), https_server_expired.GetURL("/"));
-  EXPECT_EQ(security_interstitials::CMD_TEXT_NOT_FOUND,
-            IsExtendedReportingCheckboxVisibleOnInterstitial());
-}
-
-// Test that when extended reporting is managed by policy, the opt-in checkbox
-// does not appear on SSL blocking pages.
-IN_PROC_BROWSER_TEST_F(PolicyTest, SafeBrowsingExtendedReportingPolicyManaged) {
-  net::EmbeddedTestServer https_server_expired(
-      net::EmbeddedTestServer::TYPE_HTTPS);
-  https_server_expired.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
-  https_server_expired.ServeFilesFromSourceDirectory("chrome/test/data");
-  ASSERT_TRUE(https_server_expired.Start());
-
-  // Set the extended reporting pref to True and ensure the enterprise policy
-  // can overwrite it.
-  PrefService* prefs = browser()->profile()->GetPrefs();
-  prefs->SetBoolean(prefs::kSafeBrowsingScoutReportingEnabled, true);
-
-  // First, navigate to an SSL error page and make sure the checkbox appears by
-  // default.
-  ui_test_utils::NavigateToURL(browser(), https_server_expired.GetURL("/"));
-  EXPECT_EQ(security_interstitials::CMD_TEXT_FOUND,
-            IsExtendedReportingCheckboxVisibleOnInterstitial());
-
-  // Set the enterprise policy to disable extended reporting.
-  EXPECT_TRUE(
-      prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingOptInAllowed));
-  PolicyMap policies;
-  policies.Set(key::kSafeBrowsingExtendedReportingEnabled,
-               POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               base::WrapUnique(new base::Value(false)), nullptr);
-  UpdateProviderPolicy(policies);
-  // Policy should have overwritten the pref, and it should be managed.
-  EXPECT_FALSE(prefs->GetBoolean(prefs::kSafeBrowsingScoutReportingEnabled));
-  EXPECT_TRUE(
-      prefs->IsManagedPreference(prefs::kSafeBrowsingScoutReportingEnabled));
-
-  // Also make sure the SafeBrowsing prefs helper functions agree with the
-  // policy.
-  EXPECT_TRUE(safe_browsing::IsExtendedReportingPolicyManaged(*prefs));
-  // Note that making SBER policy managed does NOT affect the SBEROptInAllowed
-  // setting, which is intentionally kept distinct for now. When the latter is
-  // deprecated, then SBER's policy management will imply whether the checkbox
-  // is visible.
-  EXPECT_TRUE(safe_browsing::IsExtendedReportingOptInAllowed(*prefs));
-
-  // Navigate to an SSL error page, the checkbox should not appear.
-  ui_test_utils::NavigateToURL(browser(), https_server_expired.GetURL("/"));
-  EXPECT_EQ(security_interstitials::CMD_TEXT_NOT_FOUND,
-            IsExtendedReportingCheckboxVisibleOnInterstitial());
-}
-
 // Test that when SSL error overriding is allowed by policy (default), the
 // proceed link appears on SSL blocking pages.
 IN_PROC_BROWSER_TEST_F(PolicyTest, SSLErrorOverridingAllowed) {
@@ -3330,248 +3055,6 @@
   EXPECT_TRUE(task_manager::TaskManagerInterface::IsEndProcessEnabled());
 }
 
-// Test that when password protection warning trigger is set for users who are
-// not signed-into Chrome, Chrome password protection service gets the correct
-// value.
-IN_PROC_BROWSER_TEST_F(PolicyTest,
-                       PasswordProtectionWarningTriggerNotLoggedIn) {
-  MockPasswordProtectionService mock_service(
-      g_browser_process->safe_browsing_service(), browser()->profile());
-
-  // If user is not signed-in, |GetPasswordProtectionWarningTriggerPref(...)|
-  // should return |PHISHING_REUSE| unless specified by policy.
-  const PrefService* const prefs = browser()->profile()->GetPrefs();
-  EXPECT_FALSE(prefs->FindPreference(prefs::kPasswordProtectionWarningTrigger)
-                   ->IsManaged());
-  EXPECT_EQ(safe_browsing::PHISHING_REUSE,
-            mock_service.GetPasswordProtectionWarningTriggerPref(
-                ReusedPasswordAccountType()));
-  // Sets the enterprise policy to 1 (a.k.a PASSWORD_REUSE).
-  PolicyMap policies;
-  policies.Set(key::kPasswordProtectionWarningTrigger, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(1), nullptr);
-  UpdateProviderPolicy(policies);
-  EXPECT_TRUE(prefs->FindPreference(prefs::kPasswordProtectionWarningTrigger)
-                  ->IsManaged());
-  EXPECT_EQ(safe_browsing::PASSWORD_REUSE,
-            mock_service.GetPasswordProtectionWarningTriggerPref(
-                ReusedPasswordAccountType()));
-  // Sets the enterprise policy to 2 (a.k.a PHISHING_REUSE).
-  policies.Set(key::kPasswordProtectionWarningTrigger, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(2), nullptr);
-  UpdateProviderPolicy(policies);
-  EXPECT_EQ(safe_browsing::PHISHING_REUSE,
-            mock_service.GetPasswordProtectionWarningTriggerPref(
-                ReusedPasswordAccountType()));
-}
-
-// Test that when password protection warning trigger is set for Gmail users,
-// Chrome password protection service gets the correct
-// value.
-IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionWarningTriggerGmail) {
-  MockPasswordProtectionService mock_service(
-      g_browser_process->safe_browsing_service(), browser()->profile());
-
-  // If user is a Gmail user, |GetPasswordProtectionWarningTriggerPref(...)|
-  // should return |PHISHING_REUSE| unless specified by policy.
-  EXPECT_CALL(mock_service, IsPrimaryAccountGmail())
-      .WillRepeatedly(Return(true));
-  const PrefService* const prefs = browser()->profile()->GetPrefs();
-  EXPECT_FALSE(prefs->FindPreference(prefs::kPasswordProtectionWarningTrigger)
-                   ->IsManaged());
-  ReusedPasswordAccountType account_type;
-  account_type.set_account_type(ReusedPasswordAccountType::GMAIL);
-  account_type.set_is_account_syncing(true);
-  EXPECT_EQ(safe_browsing::PHISHING_REUSE,
-            mock_service.GetPasswordProtectionWarningTriggerPref(account_type));
-  // Sets the enterprise policy to 1 (a.k.a PASSWORD_REUSE). Gmail accounts
-  // should always return PHISHING_REUSE regardless of what the policy is set
-  // to.
-  PolicyMap policies;
-  policies.Set(key::kPasswordProtectionWarningTrigger, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(1), nullptr);
-  UpdateProviderPolicy(policies);
-  EXPECT_TRUE(prefs->FindPreference(prefs::kPasswordProtectionWarningTrigger)
-                  ->IsManaged());
-  EXPECT_EQ(safe_browsing::PHISHING_REUSE,
-            mock_service.GetPasswordProtectionWarningTriggerPref(account_type));
-  // Sets the enterprise policy to 2 (a.k.a PHISHING_REUSE).
-  policies.Set(key::kPasswordProtectionWarningTrigger, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(2), nullptr);
-  UpdateProviderPolicy(policies);
-  EXPECT_EQ(safe_browsing::PHISHING_REUSE,
-            mock_service.GetPasswordProtectionWarningTriggerPref(account_type));
-}
-
-// Test that when password protection warning trigger is set for GSuite users,
-// Chrome password protection service gets the correct value.
-IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionWarningTriggerGSuite) {
-  MockPasswordProtectionService mock_service(
-      g_browser_process->safe_browsing_service(), browser()->profile());
-  const PrefService* const prefs = browser()->profile()->GetPrefs();
-  PolicyMap policies;
-
-  // If user is a GSuite user, |GetPasswordProtectionWarningTriggerPref(...)|
-  // should return |PHISHING_REUSE| unless specified by policy.
-  EXPECT_FALSE(prefs->FindPreference(prefs::kPasswordProtectionWarningTrigger)
-                   ->IsManaged());
-  EXPECT_EQ(safe_browsing::PHISHING_REUSE,
-            mock_service.GetPasswordProtectionWarningTriggerPref(
-                ReusedPasswordAccountType()));
-  // Sets the enterprise policy to 1 (a.k.a PASSWORD_REUSE).
-  policies.Set(key::kPasswordProtectionWarningTrigger, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(1), nullptr);
-  UpdateProviderPolicy(policies);
-  EXPECT_TRUE(prefs->FindPreference(prefs::kPasswordProtectionWarningTrigger)
-                  ->IsManaged());
-  EXPECT_EQ(safe_browsing::PASSWORD_REUSE,
-            mock_service.GetPasswordProtectionWarningTriggerPref(
-                ReusedPasswordAccountType()));
-  // Sets the enterprise policy to 2 (a.k.a PHISHING_REUSE).
-  policies.Set(key::kPasswordProtectionWarningTrigger, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               std::make_unique<base::Value>(2), nullptr);
-  UpdateProviderPolicy(policies);
-  EXPECT_EQ(safe_browsing::PHISHING_REUSE,
-            mock_service.GetPasswordProtectionWarningTriggerPref(
-                ReusedPasswordAccountType()));
-}
-
-// Test that when safe browsing whitelist domains are set by policy, safe
-// browsing service gets the correct value.
-IN_PROC_BROWSER_TEST_F(PolicyTest, SafeBrowsingWhitelistDomains) {
-  // Without setting up the enterprise policy,
-  // |GetSafeBrowsingDomainsPref(..) should return empty list.
-  const PrefService* const prefs = browser()->profile()->GetPrefs();
-  EXPECT_FALSE(
-      prefs->FindPreference(prefs::kSafeBrowsingWhitelistDomains)->IsManaged());
-  std::vector<std::string> canonicalized_domains;
-  safe_browsing::GetSafeBrowsingWhitelistDomainsPref(*prefs,
-                                                     &canonicalized_domains);
-  EXPECT_TRUE(canonicalized_domains.empty());
-
-  // Add 2 whitelisted domains to this policy.
-  PolicyMap policies;
-  base::ListValue whitelist_domains;
-  whitelist_domains.AppendString("mydomain.com");
-  whitelist_domains.AppendString("mydomain.net");
-  policies.Set(key::kSafeBrowsingWhitelistDomains, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               whitelist_domains.CreateDeepCopy(), nullptr);
-  UpdateProviderPolicy(policies);
-  EXPECT_TRUE(
-      prefs->FindPreference(prefs::kSafeBrowsingWhitelistDomains)->IsManaged());
-  safe_browsing::GetSafeBrowsingWhitelistDomainsPref(*prefs,
-                                                     &canonicalized_domains);
-  EXPECT_EQ(2u, canonicalized_domains.size());
-  EXPECT_EQ("mydomain.com", canonicalized_domains[0]);
-  EXPECT_EQ("mydomain.net", canonicalized_domains[1]);
-
-  // Invalid domains will be skipped.
-  whitelist_domains.Clear();
-  whitelist_domains.AppendString(std::string("%EF%BF%BDzyx.com"));
-  policies.Set(key::kSafeBrowsingWhitelistDomains, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               whitelist_domains.CreateDeepCopy(), nullptr);
-  UpdateProviderPolicy(policies);
-  EXPECT_TRUE(
-      prefs->FindPreference(prefs::kSafeBrowsingWhitelistDomains)->IsManaged());
-  canonicalized_domains.clear();
-  safe_browsing::GetSafeBrowsingWhitelistDomainsPref(*prefs,
-                                                     &canonicalized_domains);
-  EXPECT_TRUE(canonicalized_domains.empty());
-}
-
-// Test that when password protection login URLs are set by policy, password
-// protection service gets the correct value.
-IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionLoginURLs) {
-  // Without setting up the enterprise policy,
-  // |GetPasswordProtectionLoginURLsPref(..) should return empty list.
-  const PrefService* const prefs = browser()->profile()->GetPrefs();
-  EXPECT_FALSE(
-      prefs->FindPreference(prefs::kPasswordProtectionLoginURLs)->IsManaged());
-  std::vector<GURL> login_urls;
-  safe_browsing::GetPasswordProtectionLoginURLsPref(*prefs, &login_urls);
-  EXPECT_TRUE(login_urls.empty());
-
-  // Add 2 login URLs to this enterprise policy .
-  PolicyMap policies;
-  base::ListValue login_url_values;
-  login_url_values.AppendString("https://login.mydomain.com");
-  login_url_values.AppendString("https://mydomian.com/login.html");
-  policies.Set(key::kPasswordProtectionLoginURLs, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               login_url_values.CreateDeepCopy(), nullptr);
-  UpdateProviderPolicy(policies);
-  EXPECT_TRUE(
-      prefs->FindPreference(prefs::kPasswordProtectionLoginURLs)->IsManaged());
-  safe_browsing::GetPasswordProtectionLoginURLsPref(*prefs, &login_urls);
-  EXPECT_EQ(2u, login_urls.size());
-  EXPECT_EQ(GURL("https://login.mydomain.com"), login_urls[0]);
-  EXPECT_EQ(GURL("https://mydomian.com/login.html"), login_urls[1]);
-
-  // Verify non-http/https schemes, or invalid URLs will be skipped.
-  login_url_values.Clear();
-  login_url_values.AppendString(std::string("invalid"));
-  login_url_values.AppendString(std::string("ftp://login.mydomain.com"));
-  policies.Set(key::kPasswordProtectionLoginURLs, POLICY_LEVEL_MANDATORY,
-               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               login_url_values.CreateDeepCopy(), nullptr);
-  UpdateProviderPolicy(policies);
-  EXPECT_TRUE(
-      prefs->FindPreference(prefs::kPasswordProtectionLoginURLs)->IsManaged());
-  login_urls.clear();
-  safe_browsing::GetPasswordProtectionLoginURLsPref(*prefs, &login_urls);
-  EXPECT_TRUE(login_urls.empty());
-}
-
-// Test that when password protection change password URL is set by policy,
-// password protection service gets the correct value.
-IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionChangePasswordURL) {
-  // Without setting up the enterprise policy,
-  // |GetEnterpriseChangePasswordURL(..) should return default GAIA change
-  // password URL.
-  const PrefService* const prefs = browser()->profile()->GetPrefs();
-  const safe_browsing::ChromePasswordProtectionService* const service =
-      safe_browsing::ChromePasswordProtectionService::
-          GetPasswordProtectionService(browser()->profile());
-  EXPECT_FALSE(
-      prefs->FindPreference(prefs::kPasswordProtectionChangePasswordURL)
-          ->IsManaged());
-  EXPECT_FALSE(prefs->HasPrefPath(prefs::kPasswordProtectionChangePasswordURL));
-  EXPECT_TRUE(service->GetEnterpriseChangePasswordURL().DomainIs(
-      "accounts.google.com"));
-
-  // Add change password URL to this enterprise policy .
-  PolicyMap policies;
-  policies.Set(
-      key::kPasswordProtectionChangePasswordURL, POLICY_LEVEL_MANDATORY,
-      POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-      base::WrapUnique(new base::Value("https://changepassword.mydomain.com")),
-      nullptr);
-  UpdateProviderPolicy(policies);
-  EXPECT_TRUE(prefs->FindPreference(prefs::kPasswordProtectionChangePasswordURL)
-                  ->IsManaged());
-  EXPECT_EQ(GURL("https://changepassword.mydomain.com"),
-            service->GetEnterpriseChangePasswordURL());
-
-  // Verify non-http/https change password URL will be skipped.
-  policies.Set(key::kPasswordProtectionChangePasswordURL,
-               POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-               base::WrapUnique(new base::Value("data:text/html,login page")),
-               nullptr);
-  UpdateProviderPolicy(policies);
-  EXPECT_TRUE(prefs->FindPreference(prefs::kPasswordProtectionChangePasswordURL)
-                  ->IsManaged());
-  EXPECT_TRUE(service->GetEnterpriseChangePasswordURL().DomainIs(
-      "accounts.google.com"));
-}
-
 // Sets the proper policy before the browser is started.
 template<bool enable>
 class MediaRouterPolicyTest : public PolicyTest {
@@ -4383,76 +3866,6 @@
 
 #endif  // defined(OS_CHROMEOS)
 
-IN_PROC_BROWSER_TEST_F(PolicyTest, WebUsbDefault) {
-  const auto kTestOrigin = url::Origin::Create(GURL("https://foo.com:443"));
-
-  // Expect the default permission value to be 'ask'.
-  auto* context = UsbChooserContextFactory::GetForProfile(browser()->profile());
-  EXPECT_TRUE(context->CanRequestObjectPermission(kTestOrigin, kTestOrigin));
-
-  // Update policy to change the default permission value to 'block'.
-  PolicyMap policies;
-  SetPolicy(&policies, key::kDefaultWebUsbGuardSetting,
-            std::make_unique<base::Value>(2));
-  UpdateProviderPolicy(policies);
-  EXPECT_FALSE(context->CanRequestObjectPermission(kTestOrigin, kTestOrigin));
-
-  // Update policy to change the default permission value to 'ask'.
-  SetPolicy(&policies, key::kDefaultWebUsbGuardSetting,
-            std::make_unique<base::Value>(3));
-  UpdateProviderPolicy(policies);
-  EXPECT_TRUE(context->CanRequestObjectPermission(kTestOrigin, kTestOrigin));
-}
-
-IN_PROC_BROWSER_TEST_F(PolicyTest, WebUsbAllowDevicesForUrls) {
-  const auto kTestOrigin = url::Origin::Create(GURL("https://foo.com:443"));
-  scoped_refptr<device::FakeUsbDeviceInfo> device =
-      base::MakeRefCounted<device::FakeUsbDeviceInfo>(0, 0, "Google", "Gizmo",
-                                                      "123ABC");
-  const auto& device_info = device->GetDeviceInfo();
-
-  // Expect the default permission value to be empty.
-  auto* context = UsbChooserContextFactory::GetForProfile(browser()->profile());
-  EXPECT_FALSE(
-      context->HasDevicePermission(kTestOrigin, kTestOrigin, device_info));
-
-  // Update policy to add an entry to the permission value to allow
-  // |kTestOrigin| to access the device described by |device_info|.
-  PolicyMap policies;
-
-  base::Value device_value(base::Value::Type::DICTIONARY);
-  device_value.SetKey("vendor_id", base::Value(0));
-  device_value.SetKey("product_id", base::Value(0));
-
-  base::Value devices_value(base::Value::Type::LIST);
-  devices_value.Append(std::move(device_value));
-
-  base::Value urls_value(base::Value::Type::LIST);
-  urls_value.Append(base::Value("https://foo.com"));
-
-  base::Value entry(base::Value::Type::DICTIONARY);
-  entry.SetKey("devices", std::move(devices_value));
-  entry.SetKey("urls", std::move(urls_value));
-
-  auto policy_value = std::make_unique<base::Value>(base::Value::Type::LIST);
-  policy_value->Append(std::move(entry));
-
-  SetPolicy(&policies, key::kWebUsbAllowDevicesForUrls,
-            std::move(policy_value));
-  UpdateProviderPolicy(policies);
-
-  EXPECT_TRUE(
-      context->HasDevicePermission(kTestOrigin, kTestOrigin, device_info));
-
-  // Remove the policy to ensure that it can be dynamically updated.
-  SetPolicy(&policies, key::kWebUsbAllowDevicesForUrls,
-            std::make_unique<base::Value>(base::Value::Type::LIST));
-  UpdateProviderPolicy(policies);
-
-  EXPECT_FALSE(
-      context->HasDevicePermission(kTestOrigin, kTestOrigin, device_info));
-}
-
 // Handler for embedded http-server, returns a small page with javascript
 // variable and a link to increment it. It's for JavascriptBlacklistable test.
 std::unique_ptr<net::test_server::HttpResponse> JSIncrementerPageHandler(
@@ -4879,31 +4292,6 @@
   ASSERT_TRUE(HadSignedExchangeInAcceptHeader(url));
 }
 
-class PolicyTestWithRealTimeUrlLookupFetchAllowList : public PolicyTest {
- public:
-  PolicyTestWithRealTimeUrlLookupFetchAllowList() {
-    feature_list_.InitWithFeatures({safe_browsing::kRealTimeUrlLookupEnabled},
-                                   {});
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
-IN_PROC_BROWSER_TEST_F(PolicyTestWithRealTimeUrlLookupFetchAllowList,
-                       CheckURLsInRealTime) {
-  EXPECT_FALSE(safe_browsing::RealTimePolicyEngine::CanPerformFullURLLookup(
-      browser()->profile()));
-
-  PolicyMap policies;
-  SetPolicy(&policies, key::kSafeBrowsingRealTimeLookupEnabled,
-            std::make_unique<base::Value>(true));
-  UpdateProviderPolicy(policies);
-
-  EXPECT_TRUE(safe_browsing::RealTimePolicyEngine::CanPerformFullURLLookup(
-      browser()->profile()));
-}
-
 class HSTSPolicyTest : public PolicyTest {
   void SetUpInProcessBrowserTestFixture() override {
     PolicyTest::SetUpInProcessBrowserTestFixture();
diff --git a/chrome/browser/policy/safe_browsing_policy_browsertest.cc b/chrome/browser/policy/safe_browsing_policy_browsertest.cc
new file mode 100644
index 0000000..628f9b4a
--- /dev/null
+++ b/chrome/browser/policy/safe_browsing_policy_browsertest.cc
@@ -0,0 +1,394 @@
+// Copyright 2019 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 <string>
+#include <vector>
+
+#include "base/memory/ptr_util.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/policy/policy_test_utils.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/safe_browsing/chrome_password_protection_service.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/policy_constants.h"
+#include "components/prefs/pref_service.h"
+#include "components/safe_browsing/features.h"
+#include "components/safe_browsing/realtime/policy_engine.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "url/gurl.h"
+
+using safe_browsing::ReusedPasswordAccountType;
+using testing::Return;
+
+namespace policy {
+
+// Test that when extended reporting opt-in is disabled by policy, the
+// opt-in checkbox does not appear on SSL blocking pages.
+// Note: SafeBrowsingExtendedReportingOptInAllowed policy is being deprecated.
+IN_PROC_BROWSER_TEST_F(PolicyTest, SafeBrowsingExtendedReportingOptInAllowed) {
+  net::EmbeddedTestServer https_server_expired(
+      net::EmbeddedTestServer::TYPE_HTTPS);
+  https_server_expired.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
+  https_server_expired.ServeFilesFromSourceDirectory("chrome/test/data");
+  ASSERT_TRUE(https_server_expired.Start());
+
+  // First, navigate to an SSL error page and make sure the checkbox appears by
+  // default.
+  ui_test_utils::NavigateToURL(browser(), https_server_expired.GetURL("/"));
+  EXPECT_EQ(security_interstitials::CMD_TEXT_FOUND,
+            IsExtendedReportingCheckboxVisibleOnInterstitial());
+
+  // Set the enterprise policy to disallow opt-in.
+  const PrefService* const prefs = browser()->profile()->GetPrefs();
+  EXPECT_TRUE(
+      prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingOptInAllowed));
+  PolicyMap policies;
+  policies.Set(key::kSafeBrowsingExtendedReportingOptInAllowed,
+               POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               base::WrapUnique(new base::Value(false)), nullptr);
+  UpdateProviderPolicy(policies);
+  EXPECT_FALSE(
+      prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingOptInAllowed));
+
+  // Navigate to an SSL error page, the checkbox should not appear.
+  ui_test_utils::NavigateToURL(browser(), https_server_expired.GetURL("/"));
+  EXPECT_EQ(security_interstitials::CMD_TEXT_NOT_FOUND,
+            IsExtendedReportingCheckboxVisibleOnInterstitial());
+}
+
+// Test that when extended reporting is managed by policy, the opt-in checkbox
+// does not appear on SSL blocking pages.
+IN_PROC_BROWSER_TEST_F(PolicyTest, SafeBrowsingExtendedReportingPolicyManaged) {
+  net::EmbeddedTestServer https_server_expired(
+      net::EmbeddedTestServer::TYPE_HTTPS);
+  https_server_expired.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
+  https_server_expired.ServeFilesFromSourceDirectory("chrome/test/data");
+  ASSERT_TRUE(https_server_expired.Start());
+
+  // Set the extended reporting pref to True and ensure the enterprise policy
+  // can overwrite it.
+  PrefService* prefs = browser()->profile()->GetPrefs();
+  prefs->SetBoolean(prefs::kSafeBrowsingScoutReportingEnabled, true);
+
+  // First, navigate to an SSL error page and make sure the checkbox appears by
+  // default.
+  ui_test_utils::NavigateToURL(browser(), https_server_expired.GetURL("/"));
+  EXPECT_EQ(security_interstitials::CMD_TEXT_FOUND,
+            IsExtendedReportingCheckboxVisibleOnInterstitial());
+
+  // Set the enterprise policy to disable extended reporting.
+  EXPECT_TRUE(
+      prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingOptInAllowed));
+  PolicyMap policies;
+  policies.Set(key::kSafeBrowsingExtendedReportingEnabled,
+               POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               base::WrapUnique(new base::Value(false)), nullptr);
+  UpdateProviderPolicy(policies);
+  // Policy should have overwritten the pref, and it should be managed.
+  EXPECT_FALSE(prefs->GetBoolean(prefs::kSafeBrowsingScoutReportingEnabled));
+  EXPECT_TRUE(
+      prefs->IsManagedPreference(prefs::kSafeBrowsingScoutReportingEnabled));
+
+  // Also make sure the SafeBrowsing prefs helper functions agree with the
+  // policy.
+  EXPECT_TRUE(safe_browsing::IsExtendedReportingPolicyManaged(*prefs));
+  // Note that making SBER policy managed does NOT affect the SBEROptInAllowed
+  // setting, which is intentionally kept distinct for now. When the latter is
+  // deprecated, then SBER's policy management will imply whether the checkbox
+  // is visible.
+  EXPECT_TRUE(safe_browsing::IsExtendedReportingOptInAllowed(*prefs));
+
+  // Navigate to an SSL error page, the checkbox should not appear.
+  ui_test_utils::NavigateToURL(browser(), https_server_expired.GetURL("/"));
+  EXPECT_EQ(security_interstitials::CMD_TEXT_NOT_FOUND,
+            IsExtendedReportingCheckboxVisibleOnInterstitial());
+}
+
+// Test that when safe browsing whitelist domains are set by policy, safe
+// browsing service gets the correct value.
+IN_PROC_BROWSER_TEST_F(PolicyTest, SafeBrowsingWhitelistDomains) {
+  // Without setting up the enterprise policy,
+  // |GetSafeBrowsingDomainsPref(..) should return empty list.
+  const PrefService* const prefs = browser()->profile()->GetPrefs();
+  EXPECT_FALSE(
+      prefs->FindPreference(prefs::kSafeBrowsingWhitelistDomains)->IsManaged());
+  std::vector<std::string> canonicalized_domains;
+  safe_browsing::GetSafeBrowsingWhitelistDomainsPref(*prefs,
+                                                     &canonicalized_domains);
+  EXPECT_TRUE(canonicalized_domains.empty());
+
+  // Add 2 whitelisted domains to this policy.
+  PolicyMap policies;
+  base::ListValue whitelist_domains;
+  whitelist_domains.AppendString("mydomain.com");
+  whitelist_domains.AppendString("mydomain.net");
+  policies.Set(key::kSafeBrowsingWhitelistDomains, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               whitelist_domains.CreateDeepCopy(), nullptr);
+  UpdateProviderPolicy(policies);
+  EXPECT_TRUE(
+      prefs->FindPreference(prefs::kSafeBrowsingWhitelistDomains)->IsManaged());
+  safe_browsing::GetSafeBrowsingWhitelistDomainsPref(*prefs,
+                                                     &canonicalized_domains);
+  EXPECT_EQ(2u, canonicalized_domains.size());
+  EXPECT_EQ("mydomain.com", canonicalized_domains[0]);
+  EXPECT_EQ("mydomain.net", canonicalized_domains[1]);
+
+  // Invalid domains will be skipped.
+  whitelist_domains.Clear();
+  whitelist_domains.AppendString(std::string("%EF%BF%BDzyx.com"));
+  policies.Set(key::kSafeBrowsingWhitelistDomains, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               whitelist_domains.CreateDeepCopy(), nullptr);
+  UpdateProviderPolicy(policies);
+  EXPECT_TRUE(
+      prefs->FindPreference(prefs::kSafeBrowsingWhitelistDomains)->IsManaged());
+  canonicalized_domains.clear();
+  safe_browsing::GetSafeBrowsingWhitelistDomainsPref(*prefs,
+                                                     &canonicalized_domains);
+  EXPECT_TRUE(canonicalized_domains.empty());
+}
+
+// Test that when password protection login URLs are set by policy, password
+// protection service gets the correct value.
+IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionLoginURLs) {
+  // Without setting up the enterprise policy,
+  // |GetPasswordProtectionLoginURLsPref(..) should return empty list.
+  const PrefService* const prefs = browser()->profile()->GetPrefs();
+  EXPECT_FALSE(
+      prefs->FindPreference(prefs::kPasswordProtectionLoginURLs)->IsManaged());
+  std::vector<GURL> login_urls;
+  safe_browsing::GetPasswordProtectionLoginURLsPref(*prefs, &login_urls);
+  EXPECT_TRUE(login_urls.empty());
+
+  // Add 2 login URLs to this enterprise policy .
+  PolicyMap policies;
+  base::ListValue login_url_values;
+  login_url_values.AppendString("https://login.mydomain.com");
+  login_url_values.AppendString("https://mydomian.com/login.html");
+  policies.Set(key::kPasswordProtectionLoginURLs, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               login_url_values.CreateDeepCopy(), nullptr);
+  UpdateProviderPolicy(policies);
+  EXPECT_TRUE(
+      prefs->FindPreference(prefs::kPasswordProtectionLoginURLs)->IsManaged());
+  safe_browsing::GetPasswordProtectionLoginURLsPref(*prefs, &login_urls);
+  EXPECT_EQ(2u, login_urls.size());
+  EXPECT_EQ(GURL("https://login.mydomain.com"), login_urls[0]);
+  EXPECT_EQ(GURL("https://mydomian.com/login.html"), login_urls[1]);
+
+  // Verify non-http/https schemes, or invalid URLs will be skipped.
+  login_url_values.Clear();
+  login_url_values.AppendString(std::string("invalid"));
+  login_url_values.AppendString(std::string("ftp://login.mydomain.com"));
+  policies.Set(key::kPasswordProtectionLoginURLs, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               login_url_values.CreateDeepCopy(), nullptr);
+  UpdateProviderPolicy(policies);
+  EXPECT_TRUE(
+      prefs->FindPreference(prefs::kPasswordProtectionLoginURLs)->IsManaged());
+  login_urls.clear();
+  safe_browsing::GetPasswordProtectionLoginURLsPref(*prefs, &login_urls);
+  EXPECT_TRUE(login_urls.empty());
+}
+
+// Test that when password protection change password URL is set by policy,
+// password protection service gets the correct value.
+IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionChangePasswordURL) {
+  // Without setting up the enterprise policy,
+  // |GetEnterpriseChangePasswordURL(..) should return default GAIA change
+  // password URL.
+  const PrefService* const prefs = browser()->profile()->GetPrefs();
+  const safe_browsing::ChromePasswordProtectionService* const service =
+      safe_browsing::ChromePasswordProtectionService::
+          GetPasswordProtectionService(browser()->profile());
+  EXPECT_FALSE(
+      prefs->FindPreference(prefs::kPasswordProtectionChangePasswordURL)
+          ->IsManaged());
+  EXPECT_FALSE(prefs->HasPrefPath(prefs::kPasswordProtectionChangePasswordURL));
+  EXPECT_TRUE(service->GetEnterpriseChangePasswordURL().DomainIs(
+      "accounts.google.com"));
+
+  // Add change password URL to this enterprise policy .
+  PolicyMap policies;
+  policies.Set(
+      key::kPasswordProtectionChangePasswordURL, POLICY_LEVEL_MANDATORY,
+      POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+      base::WrapUnique(new base::Value("https://changepassword.mydomain.com")),
+      nullptr);
+  UpdateProviderPolicy(policies);
+  EXPECT_TRUE(prefs->FindPreference(prefs::kPasswordProtectionChangePasswordURL)
+                  ->IsManaged());
+  EXPECT_EQ(GURL("https://changepassword.mydomain.com"),
+            service->GetEnterpriseChangePasswordURL());
+
+  // Verify non-http/https change password URL will be skipped.
+  policies.Set(key::kPasswordProtectionChangePasswordURL,
+               POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               base::WrapUnique(new base::Value("data:text/html,login page")),
+               nullptr);
+  UpdateProviderPolicy(policies);
+  EXPECT_TRUE(prefs->FindPreference(prefs::kPasswordProtectionChangePasswordURL)
+                  ->IsManaged());
+  EXPECT_TRUE(service->GetEnterpriseChangePasswordURL().DomainIs(
+      "accounts.google.com"));
+}
+
+class MockPasswordProtectionService
+    : public safe_browsing::ChromePasswordProtectionService {
+ public:
+  MockPasswordProtectionService(safe_browsing::SafeBrowsingService* sb_service,
+                                Profile* profile)
+      : safe_browsing::ChromePasswordProtectionService(sb_service, profile) {}
+  ~MockPasswordProtectionService() override {}
+
+  MOCK_CONST_METHOD0(IsPrimaryAccountGmail, bool());
+
+  AccountInfo GetAccountInfo() const override {
+    AccountInfo info;
+    info.email = "user@mycompany.com";
+    return info;
+  }
+};
+
+// Test that when password protection warning trigger is set for users who are
+// not signed-into Chrome, Chrome password protection service gets the correct
+// value.
+IN_PROC_BROWSER_TEST_F(PolicyTest,
+                       PasswordProtectionWarningTriggerNotLoggedIn) {
+  MockPasswordProtectionService mock_service(
+      g_browser_process->safe_browsing_service(), browser()->profile());
+
+  // If user is not signed-in, |GetPasswordProtectionWarningTriggerPref(...)|
+  // should return |PHISHING_REUSE| unless specified by policy.
+  const PrefService* const prefs = browser()->profile()->GetPrefs();
+  EXPECT_FALSE(prefs->FindPreference(prefs::kPasswordProtectionWarningTrigger)
+                   ->IsManaged());
+  EXPECT_EQ(safe_browsing::PHISHING_REUSE,
+            mock_service.GetPasswordProtectionWarningTriggerPref(
+                ReusedPasswordAccountType()));
+  // Sets the enterprise policy to 1 (a.k.a PASSWORD_REUSE).
+  PolicyMap policies;
+  policies.Set(key::kPasswordProtectionWarningTrigger, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               std::make_unique<base::Value>(1), nullptr);
+  UpdateProviderPolicy(policies);
+  EXPECT_TRUE(prefs->FindPreference(prefs::kPasswordProtectionWarningTrigger)
+                  ->IsManaged());
+  EXPECT_EQ(safe_browsing::PASSWORD_REUSE,
+            mock_service.GetPasswordProtectionWarningTriggerPref(
+                ReusedPasswordAccountType()));
+  // Sets the enterprise policy to 2 (a.k.a PHISHING_REUSE).
+  policies.Set(key::kPasswordProtectionWarningTrigger, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               std::make_unique<base::Value>(2), nullptr);
+  UpdateProviderPolicy(policies);
+  EXPECT_EQ(safe_browsing::PHISHING_REUSE,
+            mock_service.GetPasswordProtectionWarningTriggerPref(
+                ReusedPasswordAccountType()));
+}
+
+// Test that when password protection warning trigger is set for Gmail users,
+// Chrome password protection service gets the correct
+// value.
+IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionWarningTriggerGmail) {
+  MockPasswordProtectionService mock_service(
+      g_browser_process->safe_browsing_service(), browser()->profile());
+
+  // If user is a Gmail user, |GetPasswordProtectionWarningTriggerPref(...)|
+  // should return |PHISHING_REUSE| unless specified by policy.
+  EXPECT_CALL(mock_service, IsPrimaryAccountGmail())
+      .WillRepeatedly(Return(true));
+  const PrefService* const prefs = browser()->profile()->GetPrefs();
+  EXPECT_FALSE(prefs->FindPreference(prefs::kPasswordProtectionWarningTrigger)
+                   ->IsManaged());
+  ReusedPasswordAccountType account_type;
+  account_type.set_account_type(ReusedPasswordAccountType::GMAIL);
+  account_type.set_is_account_syncing(true);
+  EXPECT_EQ(safe_browsing::PHISHING_REUSE,
+            mock_service.GetPasswordProtectionWarningTriggerPref(account_type));
+  // Sets the enterprise policy to 1 (a.k.a PASSWORD_REUSE). Gmail accounts
+  // should always return PHISHING_REUSE regardless of what the policy is set
+  // to.
+  PolicyMap policies;
+  policies.Set(key::kPasswordProtectionWarningTrigger, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               std::make_unique<base::Value>(1), nullptr);
+  UpdateProviderPolicy(policies);
+  EXPECT_TRUE(prefs->FindPreference(prefs::kPasswordProtectionWarningTrigger)
+                  ->IsManaged());
+  EXPECT_EQ(safe_browsing::PHISHING_REUSE,
+            mock_service.GetPasswordProtectionWarningTriggerPref(account_type));
+  // Sets the enterprise policy to 2 (a.k.a PHISHING_REUSE).
+  policies.Set(key::kPasswordProtectionWarningTrigger, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               std::make_unique<base::Value>(2), nullptr);
+  UpdateProviderPolicy(policies);
+  EXPECT_EQ(safe_browsing::PHISHING_REUSE,
+            mock_service.GetPasswordProtectionWarningTriggerPref(account_type));
+}
+
+// Test that when password protection warning trigger is set for GSuite users,
+// Chrome password protection service gets the correct value.
+IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionWarningTriggerGSuite) {
+  MockPasswordProtectionService mock_service(
+      g_browser_process->safe_browsing_service(), browser()->profile());
+  const PrefService* const prefs = browser()->profile()->GetPrefs();
+  PolicyMap policies;
+
+  // If user is a GSuite user, |GetPasswordProtectionWarningTriggerPref(...)|
+  // should return |PHISHING_REUSE| unless specified by policy.
+  EXPECT_FALSE(prefs->FindPreference(prefs::kPasswordProtectionWarningTrigger)
+                   ->IsManaged());
+  EXPECT_EQ(safe_browsing::PHISHING_REUSE,
+            mock_service.GetPasswordProtectionWarningTriggerPref(
+                ReusedPasswordAccountType()));
+  // Sets the enterprise policy to 1 (a.k.a PASSWORD_REUSE).
+  policies.Set(key::kPasswordProtectionWarningTrigger, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               std::make_unique<base::Value>(1), nullptr);
+  UpdateProviderPolicy(policies);
+  EXPECT_TRUE(prefs->FindPreference(prefs::kPasswordProtectionWarningTrigger)
+                  ->IsManaged());
+  EXPECT_EQ(safe_browsing::PASSWORD_REUSE,
+            mock_service.GetPasswordProtectionWarningTriggerPref(
+                ReusedPasswordAccountType()));
+  // Sets the enterprise policy to 2 (a.k.a PHISHING_REUSE).
+  policies.Set(key::kPasswordProtectionWarningTrigger, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               std::make_unique<base::Value>(2), nullptr);
+  UpdateProviderPolicy(policies);
+  EXPECT_EQ(safe_browsing::PHISHING_REUSE,
+            mock_service.GetPasswordProtectionWarningTriggerPref(
+                ReusedPasswordAccountType()));
+}
+
+class PolicyTestWithRealTimeUrlLookupFetchAllowList : public PolicyTest {
+ public:
+  PolicyTestWithRealTimeUrlLookupFetchAllowList() {
+    feature_list_.InitWithFeatures({safe_browsing::kRealTimeUrlLookupEnabled},
+                                   {});
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(PolicyTestWithRealTimeUrlLookupFetchAllowList,
+                       CheckURLsInRealTime) {
+  EXPECT_FALSE(safe_browsing::RealTimePolicyEngine::CanPerformFullURLLookup(
+      browser()->profile()));
+
+  PolicyMap policies;
+  SetPolicy(&policies, key::kSafeBrowsingRealTimeLookupEnabled,
+            std::make_unique<base::Value>(true));
+  UpdateProviderPolicy(policies);
+
+  EXPECT_TRUE(safe_browsing::RealTimePolicyEngine::CanPerformFullURLLookup(
+      browser()->profile()));
+}
+
+}  // namespace policy
diff --git a/chrome/browser/resources/chromeos/login/oobe_back_button.css b/chrome/browser/resources/chromeos/login/oobe_back_button.css
index 7ca7bc1..1153b59 100644
--- a/chrome/browser/resources/chromeos/login/oobe_back_button.css
+++ b/chrome/browser/resources/chromeos/login/oobe_back_button.css
@@ -7,7 +7,11 @@
   padding-inline-start: 8px;
 }
 
-hd-iron-icon {
+:host-context([dir=ltr]) hd-iron-icon {
   padding-inline-start: 4px; /* transform(180deg) will make it inline-end. */
   transform: rotate(180deg);
 }
+
+:host-context([dir=rtl]) hd-iron-icon {
+  padding-inline-end: 4px;
+}
diff --git a/chrome/browser/resources/chromeos/login/oobe_next_button.css b/chrome/browser/resources/chromeos/login/oobe_next_button.css
index 84855d1..84e668d 100644
--- a/chrome/browser/resources/chromeos/login/oobe_next_button.css
+++ b/chrome/browser/resources/chromeos/login/oobe_next_button.css
@@ -7,6 +7,11 @@
   padding-inline-start: 16px;
 }
 
-hd-iron-icon {
+:host-context([dir=ltr]) hd-iron-icon {
   padding-inline-start: 4px;
 }
+
+:host-context([dir=rtl]) hd-iron-icon {
+  padding-inline-end: 4px;
+  transform: rotate(180deg);
+}
diff --git a/chrome/browser/resources/chromeos/login/screen_error_message.css b/chrome/browser/resources/chromeos/login/screen_error_message.css
index ab4b158..a8af5b3 100644
--- a/chrome/browser/resources/chromeos/login/screen_error_message.css
+++ b/chrome/browser/resources/chromeos/login/screen_error_message.css
@@ -47,14 +47,8 @@
   display: none;
 }
 
-.error-message-paragraph {
-  font-size: 12px;
-  line-height: 18px;
-  margin-bottom: 20px;
-}
-
-.error-message-paragraph a {
-  color: rgb(17,85,204);
+#error-message-md-subtitle a {
+  color: var(--google-blue-600);
   text-decoration: none;
 }
 
diff --git a/chrome/browser/resources/chromeos/login/screen_error_message.html b/chrome/browser/resources/chromeos/login/screen_error_message.html
index e2aecd1..6feafef 100644
--- a/chrome/browser/resources/chromeos/login/screen_error_message.html
+++ b/chrome/browser/resources/chromeos/login/screen_error_message.html
@@ -39,95 +39,90 @@
         </div>
       </div>
     </h1>
+    <div id="error-message-md-subtitle" slot="subtitle">
+      <div id="kiosk-online-message-body"
+          class="show-with-error-state-kiosk-online">
+        <span i18n-content="kioskOnlineMessageBody"
+            class="show-with-error-state-kiosk-online"></span>
+      </div>
+      <div id="offline-message-body"
+          class="show-with-error-state-offline
+                 show-with-error-state-auth-ext-timeout">
+        <span id="update-offline-message-text"
+            i18n-content="updateOfflineMessageBody"
+            class="show-with-ui-state-update"></span>
+        <span id="signin-offline-message-text"
+            i18n-content="signinOfflineMessageBody"
+            class="show-with-ui-state-signin
+                   show-with-ui-state-supervised"></span>
+        <span id="kiosk-offline-message-text"
+            i18n-content="kioskOfflineMessageBody"
+            class="show-with-ui-state-kiosk-mode"></span>
+        <span id="auto-enrollment-offline-message-text"
+            class="show-with-ui-state-auto-enrollment-error"></span>
+      </div>
+      <div id="captive-portal-message-body"
+          class="show-with-error-state-portal">
+        <span id="captive-portal-message-text"
+            class="show-with-ui-state-update
+                   show-with-ui-state-signin
+                   show-with-ui-state-supervised
+                   show-with-ui-state-kiosk-mode
+                   show-with-ui-state-auto-enrollment-error"></span>
+      </div>
+      <div id="captive-portal-proxy-message-body"
+          class="show-with-error-state-portal
+                 show-with-error-state-auth-ext-timeout">
+        <span id="captive-portal-proxy-message-text"
+            class="show-with-ui-state-update
+                   show-with-ui-state-signin
+                   show-with-ui-state-supervised
+                   show-with-ui-state-kiosk-mode
+                   show-with-ui-state-auto-enrollment-error"></span>
+      </div>
+      <div id="proxy-message-body"
+          class="show-with-error-state-proxy">
+        <span id="update-proxy-message-text"
+            class="show-with-ui-state-update
+                   show-with-ui-state-auto-enrollment-error"></span>
+        <span id="signin-proxy-message-text"
+            class="show-with-ui-state-signin
+                   show-with-ui-state-supervised
+                   show-with-ui-state-kiosk-mode"></span>
+      </div>
+      <div id="local-state-error-body"
+          class="show-with-ui-state-local-state-error">
+        <div i18n-content="localStateErrorText0">
+        </div>
+        <div i18n-content="localStateErrorText1">
+        </div>
+      </div>
+      <div id="rollback-error-message-body"
+          class="show-with-ui-state-rollback-error">
+        <span i18n-content="rollbackErrorMessageBody"
+            class="show-with-ui-state-rollback-error"></span>
+      </div>
+      <div class="show-with-ui-state-update
+                  show-with-ui-state-signin
+                  show-with-ui-state-supervised
+                  show-with-ui-state-kiosk-mode
+                  show-with-ui-local-state-error">
+        <span id="error-guest-signin"
+            class="guest-signin"></span>
+      </div>
+      <div class="show-with-ui-state-auto-enrollment-error">
+        <span id="error-guest-signin-fix-network"
+            class="guest-signin"></span>
+      </div>
+      <div id="error-offline-login"
+          class="offline-login"></div>
+      <div id="connecting-indicator"
+          class="connecting-indicator">
+      </div>
+    </div>
     <div id="error-message-md-footer" slot="footer"
-        class="flex layout vertical scrollable">
+        class="flex layout vertical">
       <div id="error-body-id" class="error-body" aria-live="assertive">
-        <div id="kiosk-online-message-body"
-            class="error-message-paragraph
-                   show-with-error-state-kiosk-online">
-          <span i18n-content="kioskOnlineMessageBody"
-              class="show-with-error-state-kiosk-online"></span>
-        </div>
-        <div id="offline-message-body"
-            class="error-message-paragraph
-                   show-with-error-state-offline
-                   show-with-error-state-auth-ext-timeout">
-          <span id="update-offline-message-text"
-              i18n-content="updateOfflineMessageBody"
-              class="show-with-ui-state-update"></span>
-          <span id="signin-offline-message-text"
-              i18n-content="signinOfflineMessageBody"
-              class="show-with-ui-state-signin
-                     show-with-ui-state-supervised"></span>
-          <span id="kiosk-offline-message-text"
-              i18n-content="kioskOfflineMessageBody"
-              class="show-with-ui-state-kiosk-mode"></span>
-          <span id="auto-enrollment-offline-message-text"
-              class="show-with-ui-state-auto-enrollment-error"></span>
-        </div>
-        <div id="captive-portal-message-body"
-            class="error-message-paragraph
-                   show-with-error-state-portal">
-          <span id="captive-portal-message-text"
-              class="show-with-ui-state-update
-                     show-with-ui-state-signin
-                     show-with-ui-state-supervised
-                     show-with-ui-state-kiosk-mode
-                     show-with-ui-state-auto-enrollment-error"></span>
-        </div>
-        <div id="captive-portal-proxy-message-body"
-            class="error-message-paragraph
-                   show-with-error-state-portal
-                   show-with-error-state-auth-ext-timeout">
-          <span id="captive-portal-proxy-message-text"
-              class="show-with-ui-state-update
-                     show-with-ui-state-signin
-                     show-with-ui-state-supervised
-                     show-with-ui-state-kiosk-mode
-                     show-with-ui-state-auto-enrollment-error"></span>
-        </div>
-        <div id="proxy-message-body"
-            class="error-message-paragraph
-                   show-with-error-state-proxy">
-          <span id="update-proxy-message-text"
-              class="show-with-ui-state-update
-                     show-with-ui-state-auto-enrollment-error"></span>
-          <span id="signin-proxy-message-text"
-              class="show-with-ui-state-signin
-                     show-with-ui-state-supervised
-                     show-with-ui-state-kiosk-mode"></span>
-        </div>
-        <div id="local-state-error-body"
-            class="show-with-ui-state-local-state-error">
-          <div i18n-content="localStateErrorText0"
-              class="error-message-paragraph">
-          </div>
-          <div i18n-content="localStateErrorText1"
-              class="error-message-paragraph">
-          </div>
-        </div>
-        <div id="rollback-error-message-body"
-            class="error-message-paragraph
-                   show-with-ui-state-rollback-error">
-          <span i18n-content="rollbackErrorMessageBody"
-              class="show-with-ui-state-rollback-error"></span>
-        </div>
-        <div class="show-with-ui-state-update
-                    show-with-ui-state-signin
-                    show-with-ui-state-supervised
-                    show-with-ui-state-kiosk-mode
-                    show-with-ui-local-state-error">
-          <span id="error-guest-signin"
-              class="error-message-paragraph guest-signin"></span>
-        </div>
-        <div class="show-with-ui-state-auto-enrollment-error">
-          <span id="error-guest-signin-fix-network"
-              class="error-message-paragraph guest-signin"></span>
-        </div>
-        <div id="error-offline-login"
-            class="error-message-paragraph offline-login"></div>
-        <div id="connecting-indicator"
-            class="connecting-indicator error-message-paragraph"></div>
         <div id="offline-network-control-body"
             class="show-with-ui-state-update
                    show-with-ui-state-signin
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc
index 9159a43..bab0c9c7 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h"
 #include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
 #include "chrome/browser/safe_browsing/ui_manager.h"
-#include "chrome/browser/signin/scoped_account_consistency.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
diff --git a/chrome/browser/signin/account_consistency_mode_manager.cc b/chrome/browser/signin/account_consistency_mode_manager.cc
index 5343f6b..75bd8332 100644
--- a/chrome/browser/signin/account_consistency_mode_manager.cc
+++ b/chrome/browser/signin/account_consistency_mode_manager.cc
@@ -27,13 +27,6 @@
 
 using signin::AccountConsistencyMethod;
 
-// TODO(droger): Verify if this feature flag is still required now that
-// DICE migration was enabled by default for all users.
-const base::Feature kAccountConsistencyFeature{
-    "AccountConsistency", base::FEATURE_ENABLED_BY_DEFAULT};
-const char kAccountConsistencyFeatureMethodParameter[] = "method";
-const char kAccountConsistencyFeatureMethodMirror[] = "mirror";
-
 namespace {
 
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
@@ -59,9 +52,6 @@
   switch (account_consistency) {
     case AccountConsistencyMethod::kDice:
       return DiceMigrationStatus::kEnabled;
-    case AccountConsistencyMethod::kDiceMigration:
-      NOTREACHED();  // Dice migration is now complete.
-      return DiceMigrationStatus::kDisabledNotReadyForMigration;
     case AccountConsistencyMethod::kDisabled:
       return DiceMigrationStatus::kDisabled;
     case AccountConsistencyMethod::kMirror:
@@ -208,14 +198,8 @@
   return AccountConsistencyMethod::kMirror;
 #endif
 
-  std::string method_value = base::GetFieldTrialParamValueByFeature(
-      kAccountConsistencyFeature, kAccountConsistencyFeatureMethodParameter);
-
 #if defined(OS_CHROMEOS)
-  if (chromeos::IsAccountManagerAvailable(profile))
-    return AccountConsistencyMethod::kMirror;
-
-  return (method_value == kAccountConsistencyFeatureMethodMirror ||
+  return (chromeos::IsAccountManagerAvailable(profile) ||
           profile->GetPrefs()->GetBoolean(
               prefs::kAccountConsistencyMirrorRequired))
              ? AccountConsistencyMethod::kMirror
diff --git a/chrome/browser/signin/account_consistency_mode_manager.h b/chrome/browser/signin/account_consistency_mode_manager.h
index ad41fcd..5d748aa8 100644
--- a/chrome/browser/signin/account_consistency_mode_manager.h
+++ b/chrome/browser/signin/account_consistency_mode_manager.h
@@ -20,16 +20,6 @@
 
 class Profile;
 
-// Account consistency feature. Only used on platforms where Mirror is not
-// always enabled (ENABLE_MIRROR is false).
-extern const base::Feature kAccountConsistencyFeature;
-
-// The account consistency method feature parameter name.
-extern const char kAccountConsistencyFeatureMethodParameter[];
-
-// Account consistency method feature values.
-extern const char kAccountConsistencyFeatureMethodMirror[];
-
 // Manages the account consistency mode for each profile.
 class AccountConsistencyModeManager : public KeyedService {
  public:
diff --git a/chrome/browser/signin/account_consistency_mode_manager_unittest.cc b/chrome/browser/signin/account_consistency_mode_manager_unittest.cc
index 3407837..1693dbd 100644
--- a/chrome/browser/signin/account_consistency_mode_manager_unittest.cc
+++ b/chrome/browser/signin/account_consistency_mode_manager_unittest.cc
@@ -12,7 +12,6 @@
 #include "build/build_config.h"
 #include "build/buildflag.h"
 #include "chrome/browser/prefs/browser_prefs.h"
-#include "chrome/browser/signin/scoped_account_consistency.h"
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
diff --git a/chrome/browser/signin/account_reconcilor_factory.cc b/chrome/browser/signin/account_reconcilor_factory.cc
index 115dfd4..b145bdfe 100644
--- a/chrome/browser/signin/account_reconcilor_factory.cc
+++ b/chrome/browser/signin/account_reconcilor_factory.cc
@@ -196,14 +196,11 @@
     case signin::AccountConsistencyMethod::kDisabled:
       return std::make_unique<signin::AccountReconcilorDelegate>();
 
-    case signin::AccountConsistencyMethod::kDiceMigration:
     case signin::AccountConsistencyMethod::kDice:
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
       return std::make_unique<signin::DiceAccountReconcilorDelegate>(
           ChromeSigninClientFactory::GetForProfile(profile),
-          account_consistency,
-          account_consistency == signin::AccountConsistencyMethod::kDice &&
-              AccountConsistencyModeManager::IsDiceMigrationCompleted(profile));
+          AccountConsistencyModeManager::IsDiceMigrationCompleted(profile));
 #else
       NOTREACHED();
       return nullptr;
diff --git a/chrome/browser/signin/chrome_signin_helper.cc b/chrome/browser/signin/chrome_signin_helper.cc
index e03f0c16..1d23530 100644
--- a/chrome/browser/signin/chrome_signin_helper.cc
+++ b/chrome/browser/signin/chrome_signin_helper.cc
@@ -349,8 +349,8 @@
   dice_response_handler->ProcessDiceHeader(
       dice_params,
       std::make_unique<ProcessDiceHeaderDelegateImpl>(
-          web_contents, account_consistency,
-          IdentityManagerFactory::GetForProfile(profile), is_sync_signin_tab,
+          web_contents, IdentityManagerFactory::GetForProfile(profile),
+          is_sync_signin_tab,
           base::BindOnce(&CreateDiceTurnOnSyncHelper, base::Unretained(profile),
                          access_point, promo_action, reason),
           base::BindOnce(&ShowDiceSigninError, base::Unretained(profile)),
diff --git a/chrome/browser/signin/chrome_signin_helper_unittest.cc b/chrome/browser/signin/chrome_signin_helper_unittest.cc
index c598c0d8..c17c013 100644
--- a/chrome/browser/signin/chrome_signin_helper_unittest.cc
+++ b/chrome/browser/signin/chrome_signin_helper_unittest.cc
@@ -9,7 +9,6 @@
 
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
-#include "chrome/browser/signin/scoped_account_consistency.h"
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "components/signin/public/base/signin_buildflags.h"
 #include "content/public/test/browser_task_environment.h"
@@ -26,8 +25,11 @@
 
 namespace {
 
+#if BUILDFLAG(ENABLE_MIRROR) || defined(OS_CHROMEOS)
 const char kChromeManageAccountsHeader[] = "X-Chrome-Manage-Accounts";
 const char kMirrorAction[] = "action=ADDSESSION";
+#endif
+
 const GURL kGaiaUrl("https://accounts.google.com");
 
 // URLRequestInterceptor adding a account consistency response header to Gaia
@@ -125,10 +127,9 @@
 }
 #endif  // BUILDFLAG(ENABLE_DICE_SUPPORT)
 
+#if BUILDFLAG(ENABLE_MIRROR) || defined(OS_CHROMEOS)
 // Tests that user data is set on Mirror requests.
 TEST_F(ChromeSigninHelperTest, MirrorMainFrame) {
-  ScopedAccountConsistencyMirror scoped_mirror;
-
   // Process the header.
   TestResponseAdapter response_adapter(kChromeManageAccountsHeader,
                                        kMirrorAction,
@@ -145,8 +146,6 @@
 
 // Tests that user data is not set on Mirror requests for sub frames.
 TEST_F(ChromeSigninHelperTest, MirrorSubFrame) {
-  ScopedAccountConsistencyMirror scoped_mirror;
-
   // Process the header.
   TestResponseAdapter response_adapter(kChromeManageAccountsHeader,
                                        kMirrorAction,
@@ -157,3 +156,4 @@
   EXPECT_FALSE(response_adapter.GetUserData(
       signin::kManageAccountsHeaderReceivedUserDataKey));
 }
+#endif  // BUILDFLAG(ENABLE_MIRROR) || defined(OS_CHROMEOS)
diff --git a/chrome/browser/signin/dice_response_handler.cc b/chrome/browser/signin/dice_response_handler.cc
index c503ba8..0d09adf 100644
--- a/chrome/browser/signin/dice_response_handler.cc
+++ b/chrome/browser/signin/dice_response_handler.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/signin/about_signin_internals_factory.h"
-#include "chrome/browser/signin/account_consistency_mode_manager.h"
 #include "chrome/browser/signin/account_reconcilor_factory.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
@@ -109,7 +108,6 @@
         IdentityManagerFactory::GetForProfile(profile),
         AccountReconcilorFactory::GetForProfile(profile),
         AboutSigninInternalsFactory::GetForProfile(profile),
-        AccountConsistencyModeManager::GetMethodForProfile(profile),
         profile->GetPath());
   }
 };
@@ -206,20 +204,16 @@
     signin::IdentityManager* identity_manager,
     AccountReconcilor* account_reconcilor,
     AboutSigninInternals* about_signin_internals,
-    signin::AccountConsistencyMethod account_consistency,
     const base::FilePath& profile_path)
     : signin_client_(signin_client),
       identity_manager_(identity_manager),
       account_reconcilor_(account_reconcilor),
       about_signin_internals_(about_signin_internals),
-      account_consistency_(account_consistency),
       profile_path_(profile_path) {
   DCHECK(signin_client_);
   DCHECK(identity_manager_);
   DCHECK(account_reconcilor_);
   DCHECK(about_signin_internals_);
-  DCHECK(signin::DiceMethodGreaterOrEqual(
-      account_consistency_, signin::AccountConsistencyMethod::kDiceMigration));
 }
 
 DiceResponseHandler::~DiceResponseHandler() {}
@@ -318,16 +312,10 @@
       primary_account_signed_out = true;
       RecordDiceResponseHeader(kSignoutPrimary);
 
-      if (account_consistency_ == signin::AccountConsistencyMethod::kDice) {
-        // Put the account in error state.
-        accounts_mutator->InvalidateRefreshTokenForPrimaryAccount(
-            signin_metrics::SourceForRefreshTokenOperation::
-                kDiceResponseHandler_Signout);
-      } else {
-        // If Dice migration is not complete, the token for the main account
-        // must not be deleted when signing out of the web.
-        continue;
-      }
+      // Put the account in error state.
+      accounts_mutator->InvalidateRefreshTokenForPrimaryAccount(
+          signin_metrics::SourceForRefreshTokenOperation::
+              kDiceResponseHandler_Signout);
     } else {
       accounts_mutator->RemoveAccount(
           signed_out_account, signin_metrics::SourceForRefreshTokenOperation::
diff --git a/chrome/browser/signin/dice_response_handler.h b/chrome/browser/signin/dice_response_handler.h
index b80bf4f..dd17deb 100644
--- a/chrome/browser/signin/dice_response_handler.h
+++ b/chrome/browser/signin/dice_response_handler.h
@@ -58,7 +58,6 @@
                       signin::IdentityManager* identity_manager,
                       AccountReconcilor* account_reconcilor,
                       AboutSigninInternals* about_signin_internals,
-                      signin::AccountConsistencyMethod account_consistency,
                       const base::FilePath& profile_path_);
   ~DiceResponseHandler() override;
 
@@ -150,7 +149,6 @@
   signin::IdentityManager* identity_manager_;
   AccountReconcilor* account_reconcilor_;
   AboutSigninInternals* about_signin_internals_;
-  signin::AccountConsistencyMethod account_consistency_;
   base::FilePath profile_path_;
   std::vector<std::unique_ptr<DiceTokenFetcher>> token_fetchers_;
 
diff --git a/chrome/browser/signin/dice_response_handler_unittest.cc b/chrome/browser/signin/dice_response_handler_unittest.cc
index 8ae4b89e..ddc5f2b 100644
--- a/chrome/browser/signin/dice_response_handler_unittest.cc
+++ b/chrome/browser/signin/dice_response_handler_unittest.cc
@@ -22,7 +22,6 @@
 #include "components/signin/core/browser/dice_account_reconcilor_delegate.h"
 #include "components/signin/core/browser/signin_error_controller.h"
 #include "components/signin/core/browser/signin_header_helper.h"
-#include "components/signin/public/base/account_consistency_method.h"
 #include "components/signin/public/base/test_signin_client.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
 #include "components/signin/public/identity_manager/identity_test_utils.h"
@@ -115,13 +114,17 @@
     AboutSigninInternals::RegisterPrefs(pref_service_.registry());
     auto account_reconcilor_delegate =
         std::make_unique<signin::DiceAccountReconcilorDelegate>(
-            &signin_client_, signin::AccountConsistencyMethod::kDiceMigration,
+            &signin_client_,
             /*migration_completed=*/false);
     account_reconcilor_ = std::make_unique<AccountReconcilor>(
         identity_test_env_.identity_manager(), &signin_client_,
         std::move(account_reconcilor_delegate));
     about_signin_internals_.Initialize(&signin_client_);
     account_reconcilor_->AddObserver(this);
+    dice_response_handler_ = std::make_unique<DiceResponseHandler>(
+        &signin_client_, identity_test_env_.identity_manager(),
+        account_reconcilor_.get(), &about_signin_internals_,
+        temp_dir_.GetPath());
   }
 
   ~DiceResponseHandlerTest() override {
@@ -131,15 +134,6 @@
     signin_error_controller_.Shutdown();
   }
 
-  void InitializeDiceResponseHandler(
-      signin::AccountConsistencyMethod account_consistency) {
-    DCHECK(!dice_response_handler_);
-    dice_response_handler_ = std::make_unique<DiceResponseHandler>(
-        &signin_client_, identity_test_env_.identity_manager(),
-        account_reconcilor_.get(), &about_signin_internals_,
-        account_consistency, temp_dir_.GetPath());
-  }
-
   DiceResponseParams MakeDiceParams(DiceAction action) {
     DiceResponseParams dice_params;
     dice_params.user_intention = action;
@@ -219,7 +213,6 @@
 
 // Checks that a SIGNIN action triggers a token exchange request.
 TEST_F(DiceResponseHandlerTest, Signin) {
-  InitializeDiceResponseHandler(signin::AccountConsistencyMethod::kDice);
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN);
   const auto& account_info = dice_params.signin_info->account_info;
   CoreAccountId account_id = identity_manager()->PickAccountIdForAccount(
@@ -254,7 +247,6 @@
 
 // Checks that a GaiaAuthFetcher failure is handled correctly.
 TEST_F(DiceResponseHandlerTest, SigninFailure) {
-  InitializeDiceResponseHandler(signin::AccountConsistencyMethod::kDice);
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN);
   const auto& account_info = dice_params.signin_info->account_info;
   CoreAccountId account_id = identity_manager()->PickAccountIdForAccount(
@@ -282,7 +274,6 @@
 // Checks that a second token for the same account is not requested when a
 // request is already in flight.
 TEST_F(DiceResponseHandlerTest, SigninRepeatedWithSameAccount) {
-  InitializeDiceResponseHandler(signin::AccountConsistencyMethod::kDice);
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN);
   const auto& account_info = dice_params.signin_info->account_info;
   CoreAccountId account_id = identity_manager()->PickAccountIdForAccount(
@@ -315,7 +306,6 @@
 
 // Checks that two SIGNIN requests can happen concurrently.
 TEST_F(DiceResponseHandlerTest, SigninWithTwoAccounts) {
-  InitializeDiceResponseHandler(signin::AccountConsistencyMethod::kDice);
   DiceResponseParams dice_params_1 = MakeDiceParams(DiceAction::SIGNIN);
   const auto& account_info_1 = dice_params_1.signin_info->account_info;
   DiceResponseParams dice_params_2 = MakeDiceParams(DiceAction::SIGNIN);
@@ -373,7 +363,6 @@
 // Checks that a ENABLE_SYNC action received after the refresh token is added
 // to the token service, triggers a call to enable sync on the delegate.
 TEST_F(DiceResponseHandlerTest, SigninEnableSyncAfterRefreshTokenFetched) {
-  InitializeDiceResponseHandler(signin::AccountConsistencyMethod::kDice);
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN);
   const auto& account_info = dice_params.signin_info->account_info;
   CoreAccountId account_id = identity_manager()->PickAccountIdForAccount(
@@ -405,7 +394,6 @@
 // to the token service, is schedules a call to enable sync on the delegate
 // once the refresh token is received.
 TEST_F(DiceResponseHandlerTest, SigninEnableSyncBeforeRefreshTokenFetched) {
-  InitializeDiceResponseHandler(signin::AccountConsistencyMethod::kDice);
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN);
   const auto& account_info = dice_params.signin_info->account_info;
   CoreAccountId account_id = identity_manager()->PickAccountIdForAccount(
@@ -435,7 +423,6 @@
 }
 
 TEST_F(DiceResponseHandlerTest, Timeout) {
-  InitializeDiceResponseHandler(signin::AccountConsistencyMethod::kDice);
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN);
   const auto& account_info = dice_params.signin_info->account_info;
   CoreAccountId account_id = identity_manager()->PickAccountIdForAccount(
@@ -461,7 +448,6 @@
 }
 
 TEST_F(DiceResponseHandlerTest, SignoutMainAccount) {
-  InitializeDiceResponseHandler(signin::AccountConsistencyMethod::kDice);
   const char kSecondaryEmail[] = "other@gmail.com";
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNOUT);
   const auto& dice_account_info = dice_params.signout_info->account_infos[0];
@@ -506,44 +492,7 @@
   EXPECT_EQ(0, reconcilor_unblocked_count_);
 }
 
-TEST_F(DiceResponseHandlerTest, MigrationSignout) {
-  InitializeDiceResponseHandler(
-      signin::AccountConsistencyMethod::kDiceMigration);
-  const char kSecondaryEmail[] = "other@gmail.com";
-  DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNOUT);
-  dice_params.signout_info->account_infos.emplace_back(
-      signin::GetTestGaiaIdForEmail(kSecondaryEmail), kSecondaryEmail, 1);
-  const auto& main_account_info = dice_params.signout_info->account_infos[0];
-
-  // User is signed in to Chrome, and has some refresh token for a secondary
-  // account.
-  AccountInfo account_info =
-      identity_test_env_.MakePrimaryAccountAvailable(main_account_info.email);
-  AccountInfo secondary_account_info =
-      identity_test_env_.MakeAccountAvailable(kSecondaryEmail);
-  EXPECT_TRUE(
-      identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
-  EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(
-      secondary_account_info.account_id));
-  EXPECT_TRUE(identity_manager()->HasPrimaryAccount());
-
-  // Receive signout response for all accounts.
-  dice_response_handler_->ProcessDiceHeader(
-      dice_params, std::make_unique<TestProcessDiceHeaderDelegate>(this));
-
-  // User is not signed out from Chrome, only the secondary token is deleted.
-  EXPECT_TRUE(
-      identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
-  EXPECT_FALSE(identity_manager()->HasAccountWithRefreshToken(
-      secondary_account_info.account_id));
-  EXPECT_TRUE(identity_manager()->HasPrimaryAccount());
-  // Check that the reconcilor was not blocked.
-  EXPECT_EQ(0, reconcilor_blocked_count_);
-  EXPECT_EQ(0, reconcilor_unblocked_count_);
-}
-
 TEST_F(DiceResponseHandlerTest, SignoutSecondaryAccount) {
-  InitializeDiceResponseHandler(signin::AccountConsistencyMethod::kDice);
   const char kMainEmail[] = "main@gmail.com";
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNOUT);
   const auto& secondary_dice_account_info =
@@ -573,7 +522,6 @@
 }
 
 TEST_F(DiceResponseHandlerTest, SignoutWebOnly) {
-  InitializeDiceResponseHandler(signin::AccountConsistencyMethod::kDice);
   const char kSecondaryEmail[] = "other@gmail.com";
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNOUT);
   const auto& dice_account_info = dice_params.signout_info->account_infos[0];
@@ -601,7 +549,6 @@
 
 // Checks that signin in progress is canceled by a signout.
 TEST_F(DiceResponseHandlerTest, SigninSignoutSameAccount) {
-  InitializeDiceResponseHandler(signin::AccountConsistencyMethod::kDice);
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNOUT);
   const auto& dice_account_info = dice_params.signout_info->account_infos[0];
 
@@ -643,7 +590,6 @@
 // Checks that signin in progress is not canceled by a signout for a different
 // account.
 TEST_F(DiceResponseHandlerTest, SigninSignoutDifferentAccount) {
-  InitializeDiceResponseHandler(signin::AccountConsistencyMethod::kDice);
   // User starts signin in the web with two accounts.
   DiceResponseParams signout_params_1 = MakeDiceParams(DiceAction::SIGNOUT);
   DiceResponseParams signin_params_1 = MakeDiceParams(DiceAction::SIGNIN);
diff --git a/chrome/browser/signin/mirror_browsertest.cc b/chrome/browser/signin/mirror_browsertest.cc
index d5284c2..30aa1f0 100644
--- a/chrome/browser/signin/mirror_browsertest.cc
+++ b/chrome/browser/signin/mirror_browsertest.cc
@@ -21,7 +21,6 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_content_browser_client.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/scoped_account_consistency.h"
 #include "chrome/browser/signin/signin_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_paths.h"
@@ -103,8 +102,6 @@
     // load pages from "www.google.com" without an interstitial.
     command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
   }
-
-  ScopedAccountConsistencyMirror scoped_mirror_;
 };
 
 // Verify the following items:
diff --git a/chrome/browser/signin/process_dice_header_delegate_impl.cc b/chrome/browser/signin/process_dice_header_delegate_impl.cc
index 086ffee0..b5731c49 100644
--- a/chrome/browser/signin/process_dice_header_delegate_impl.cc
+++ b/chrome/browser/signin/process_dice_header_delegate_impl.cc
@@ -27,14 +27,12 @@
 
 ProcessDiceHeaderDelegateImpl::ProcessDiceHeaderDelegateImpl(
     content::WebContents* web_contents,
-    signin::AccountConsistencyMethod account_consistency,
     signin::IdentityManager* identity_manager,
     bool is_sync_signin_tab,
     EnableSyncCallback enable_sync_callback,
     ShowSigninErrorCallback show_signin_error_callback,
     const GURL& redirect_url)
     : content::WebContentsObserver(web_contents),
-      account_consistency_(account_consistency),
       identity_manager_(identity_manager),
       enable_sync_callback_(std::move(enable_sync_callback)),
       show_signin_error_callback_(std::move(show_signin_error_callback)),
@@ -42,8 +40,6 @@
       redirect_url_(redirect_url) {
   DCHECK(web_contents);
   DCHECK(identity_manager_);
-  DCHECK(signin::DiceMethodGreaterOrEqual(
-      account_consistency_, signin::AccountConsistencyMethod::kDiceMigration));
 }
 
 ProcessDiceHeaderDelegateImpl::~ProcessDiceHeaderDelegateImpl() = default;
@@ -95,9 +91,6 @@
     const GoogleServiceAuthError& error) {
   DCHECK_NE(GoogleServiceAuthError::NONE, error.state());
   bool should_enable_sync = ShouldEnableSync();
-  if (!should_enable_sync &&
-      account_consistency_ != signin::AccountConsistencyMethod::kDice)
-    return;
 
   content::WebContents* web_contents = this->web_contents();
   if (should_enable_sync && web_contents)
diff --git a/chrome/browser/signin/process_dice_header_delegate_impl.h b/chrome/browser/signin/process_dice_header_delegate_impl.h
index 53b7a50..fc0dee0 100644
--- a/chrome/browser/signin/process_dice_header_delegate_impl.h
+++ b/chrome/browser/signin/process_dice_header_delegate_impl.h
@@ -41,7 +41,6 @@
   // tab.
   ProcessDiceHeaderDelegateImpl(
       content::WebContents* web_contents,
-      signin::AccountConsistencyMethod account_consistency,
       signin::IdentityManager* identity_manager,
       bool is_sync_signin_tab,
       EnableSyncCallback enable_sync_callback,
@@ -58,7 +57,6 @@
   // Returns true if sync should be enabled after the user signs in.
   bool ShouldEnableSync();
 
-  signin::AccountConsistencyMethod account_consistency_;
   signin::IdentityManager* identity_manager_;
   EnableSyncCallback enable_sync_callback_;
   ShowSigninErrorCallback show_signin_error_callback_;
diff --git a/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc b/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc
index 75aff8a..eb61e5f 100644
--- a/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc
+++ b/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc
@@ -20,12 +20,6 @@
 
 namespace {
 
-// Constants defined for a better formatting of the test tables:
-const signin::AccountConsistencyMethod kDice =
-    signin::AccountConsistencyMethod::kDice;
-const signin::AccountConsistencyMethod kDiceMigration =
-    signin::AccountConsistencyMethod::kDiceMigration;
-
 class ProcessDiceHeaderDelegateImplTest
     : public ChromeRenderViewHostTestHarness {
  public:
@@ -40,11 +34,10 @@
 
   // Creates a ProcessDiceHeaderDelegateImpl instance.
   std::unique_ptr<ProcessDiceHeaderDelegateImpl> CreateDelegate(
-      bool is_sync_signin_tab,
-      signin::AccountConsistencyMethod account_consistency) {
+      bool is_sync_signin_tab) {
     return std::make_unique<ProcessDiceHeaderDelegateImpl>(
-        web_contents(), account_consistency,
-        identity_test_environment_.identity_manager(), is_sync_signin_tab,
+        web_contents(), identity_test_environment_.identity_manager(),
+        is_sync_signin_tab,
         base::BindOnce(&ProcessDiceHeaderDelegateImplTest::StartSyncCallback,
                        base::Unretained(this)),
         base::BindOnce(
@@ -86,7 +79,7 @@
   NavigateAndCommit(kSigninURL);
   ASSERT_EQ(kSigninURL, web_contents()->GetVisibleURL());
   std::unique_ptr<ProcessDiceHeaderDelegateImpl> delegate =
-      CreateDelegate(true, signin::AccountConsistencyMethod::kDice);
+      CreateDelegate(true);
 
   // Close the tab.
   DeleteContents();
@@ -105,7 +98,7 @@
   NavigateAndCommit(kSigninURL);
   ASSERT_EQ(kSigninURL, web_contents()->GetVisibleURL());
   std::unique_ptr<ProcessDiceHeaderDelegateImpl> delegate =
-      CreateDelegate(true, signin::AccountConsistencyMethod::kDice);
+      CreateDelegate(true);
 
   // Close the tab.
   DeleteContents();
@@ -118,7 +111,6 @@
 
 struct TestConfiguration {
   // Test setup.
-  signin::AccountConsistencyMethod account_consistency;
   bool signed_in;   // User was already signed in at the start of the flow.
   bool signin_tab;  // The tab is marked as a Sync signin tab.
 
@@ -129,15 +121,11 @@
 
 TestConfiguration kEnableSyncTestCases[] = {
     // clang-format off
-    // AccountConsistency | signed_in | signin_tab | callback_called | show_ntp
-    {kDiceMigration,        false,      false,       false,            false},
-    {kDiceMigration,        false,      true,        true,             true},
-    {kDice,                 false,      false,       false,            false},
-    {kDice,                 false,      true,        true,             true},
-    {kDiceMigration,        true,       false,       false,            false},
-    {kDiceMigration,        true,       false,       false,            false},
-    {kDice,                 true,       false,       false,            false},
-    {kDice,                 true,       true,        false,            false},
+    // signed_in | signin_tab | callback_called | show_ntp
+    {  false,      false,       false,            false},
+    {  false,      true,        true,             true},
+    {  true,       false,       false,            false},
+    {  true,       true,        false,            false},
     // clang-format on
 };
 
@@ -155,7 +143,7 @@
   if (GetParam().signed_in)
     identity_test_environment_.SetPrimaryAccount(email_);
   std::unique_ptr<ProcessDiceHeaderDelegateImpl> delegate =
-      CreateDelegate(GetParam().signin_tab, GetParam().account_consistency);
+      CreateDelegate(GetParam().signin_tab);
 
   // Check expectations.
   delegate->EnableSync(account_id_);
@@ -172,15 +160,11 @@
 
 TestConfiguration kHandleTokenExchangeFailureTestCases[] = {
     // clang-format off
-    // AccountConsistency | signed_in | signin_tab | callback_called | show_ntp
-    {kDiceMigration,        false,      false,       false,            false},
-    {kDiceMigration,        false,      true,        true,             true},
-    {kDice,                 false,      false,       true,             false},
-    {kDice,                 false,      true,        true,             true},
-    {kDiceMigration,        true,       false,       false,            false},
-    {kDiceMigration,        true,       false,       false,            false},
-    {kDice,                 true,       false,       true,             false},
-    {kDice,                 true,       true,        true,             false},
+    // signed_in | signin_tab | callback_called | show_ntp
+    {  false,      false,       true,             false},
+    {  false,      true,        true,             true},
+    {  true,       false,       true,             false},
+    {  true,       true,        true,             false},
     // clang-format on
 };
 
@@ -199,7 +183,7 @@
   if (GetParam().signed_in)
     identity_test_environment_.SetPrimaryAccount(email_);
   std::unique_ptr<ProcessDiceHeaderDelegateImpl> delegate =
-      CreateDelegate(GetParam().signin_tab, GetParam().account_consistency);
+      CreateDelegate(GetParam().signin_tab);
 
   // Check expectations.
   delegate->HandleTokenExchangeFailure(email_, auth_error_);
diff --git a/chrome/browser/signin/scoped_account_consistency.cc b/chrome/browser/signin/scoped_account_consistency.cc
deleted file mode 100644
index 6d8bc66b..0000000
--- a/chrome/browser/signin/scoped_account_consistency.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/signin/scoped_account_consistency.h"
-
-#include <map>
-#include <string>
-#include <utility>
-
-#include "base/feature_list.h"
-#include "base/logging.h"
-#include "chrome/browser/signin/account_consistency_mode_manager.h"
-#include "components/signin/public/base/signin_buildflags.h"
-
-using signin::AccountConsistencyMethod;
-
-ScopedAccountConsistencyMirror::ScopedAccountConsistencyMirror() {
-#if BUILDFLAG(ENABLE_MIRROR)
-  return;
-#endif
-
-  std::map<std::string, std::string> feature_params;
-  feature_params[kAccountConsistencyFeatureMethodParameter] =
-      kAccountConsistencyFeatureMethodMirror;
-
-  scoped_feature_list_.InitAndEnableFeatureWithParameters(
-      kAccountConsistencyFeature, feature_params);
-}
-
-ScopedAccountConsistencyMirror::~ScopedAccountConsistencyMirror() {}
diff --git a/chrome/browser/signin/scoped_account_consistency.h b/chrome/browser/signin/scoped_account_consistency.h
deleted file mode 100644
index fec426e..0000000
--- a/chrome/browser/signin/scoped_account_consistency.h
+++ /dev/null
@@ -1,27 +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 CHROME_BROWSER_SIGNIN_SCOPED_ACCOUNT_CONSISTENCY_H_
-#define CHROME_BROWSER_SIGNIN_SCOPED_ACCOUNT_CONSISTENCY_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/test/scoped_feature_list.h"
-#include "components/signin/public/base/account_consistency_method.h"
-
-// Changes the account consistency method while it is in scope. Useful for
-// tests.
-class ScopedAccountConsistencyMirror {
- public:
-  ScopedAccountConsistencyMirror();
-  ~ScopedAccountConsistencyMirror();
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedAccountConsistencyMirror);
-};
-
-#endif  // CHROME_BROWSER_SIGNIN_SCOPED_ACCOUNT_CONSISTENCY_H_
diff --git a/chrome/browser/signin/signin_ui_util_unittest.cc b/chrome/browser/signin/signin_ui_util_unittest.cc
index 297c794..2d8336c5d3 100644
--- a/chrome/browser/signin/signin_ui_util_unittest.cc
+++ b/chrome/browser/signin/signin_ui_util_unittest.cc
@@ -170,8 +170,6 @@
     histogram_tester.ExpectTotalCount(
         "Signin.SigninStartedAccessPoint.NotDefault", 0);
     histogram_tester.ExpectTotalCount(
-        "Signin.SigninStartedAccessPoint.NewAccountPreDice", 0);
-    histogram_tester.ExpectTotalCount(
         "Signin.SigninStartedAccessPoint.NewAccountNoExistingAccount", 0);
     histogram_tester.ExpectTotalCount(
         "Signin.SigninStartedAccessPoint.NewAccountExistingAccount", 0);
@@ -189,8 +187,6 @@
         histogram_tester.ExpectTotalCount(
             "Signin.SigninStartedAccessPoint.WithDefault", 0);
         histogram_tester.ExpectTotalCount(
-            "Signin.SigninStartedAccessPoint.NewAccountPreDice", 0);
-        histogram_tester.ExpectTotalCount(
             "Signin.SigninStartedAccessPoint.NewAccountNoExistingAccount", 0);
         histogram_tester.ExpectTotalCount(
             "Signin.SigninStartedAccessPoint.NewAccountExistingAccount", 0);
@@ -201,8 +197,6 @@
         histogram_tester.ExpectUniqueSample(
             "Signin.SigninStartedAccessPoint.WithDefault", access_point_, 1);
         histogram_tester.ExpectTotalCount(
-            "Signin.SigninStartedAccessPoint.NewAccountPreDice", 0);
-        histogram_tester.ExpectTotalCount(
             "Signin.SigninStartedAccessPoint.NewAccountNoExistingAccount", 0);
         histogram_tester.ExpectTotalCount(
             "Signin.SigninStartedAccessPoint.NewAccountExistingAccount", 0);
@@ -213,21 +207,6 @@
         histogram_tester.ExpectUniqueSample(
             "Signin.SigninStartedAccessPoint.NotDefault", access_point_, 1);
         histogram_tester.ExpectTotalCount(
-            "Signin.SigninStartedAccessPoint.NewAccountPreDice", 0);
-        histogram_tester.ExpectTotalCount(
-            "Signin.SigninStartedAccessPoint.NewAccountNoExistingAccount", 0);
-        histogram_tester.ExpectTotalCount(
-            "Signin.SigninStartedAccessPoint.NewAccountExistingAccount", 0);
-        break;
-      case signin_metrics::PromoAction::PROMO_ACTION_NEW_ACCOUNT_PRE_DICE:
-        histogram_tester.ExpectTotalCount(
-            "Signin.SigninStartedAccessPoint.WithDefault", 0);
-        histogram_tester.ExpectTotalCount(
-            "Signin.SigninStartedAccessPoint.NotDefault", 0);
-        histogram_tester.ExpectUniqueSample(
-            "Signin.SigninStartedAccessPoint.NewAccountPreDice", access_point_,
-            1);
-        histogram_tester.ExpectTotalCount(
             "Signin.SigninStartedAccessPoint.NewAccountNoExistingAccount", 0);
         histogram_tester.ExpectTotalCount(
             "Signin.SigninStartedAccessPoint.NewAccountExistingAccount", 0);
@@ -238,8 +217,6 @@
             "Signin.SigninStartedAccessPoint.WithDefault", 0);
         histogram_tester.ExpectTotalCount(
             "Signin.SigninStartedAccessPoint.NotDefault", 0);
-        histogram_tester.ExpectTotalCount(
-            "Signin.SigninStartedAccessPoint.NewAccountPreDice", 0);
         histogram_tester.ExpectUniqueSample(
             "Signin.SigninStartedAccessPoint.NewAccountNoExistingAccount",
             access_point_, 1);
@@ -253,8 +230,6 @@
         histogram_tester.ExpectTotalCount(
             "Signin.SigninStartedAccessPoint.NotDefault", 0);
         histogram_tester.ExpectTotalCount(
-            "Signin.SigninStartedAccessPoint.NewAccountPreDice", 0);
-        histogram_tester.ExpectTotalCount(
             "Signin.SigninStartedAccessPoint.NewAccountNoExistingAccount", 0);
         histogram_tester.ExpectUniqueSample(
             "Signin.SigninStartedAccessPoint.NewAccountExistingAccount",
diff --git a/chrome/browser/ssl/captive_portal_blocking_page.cc b/chrome/browser/ssl/captive_portal_blocking_page.cc
index 22c764a7..f2fac9c 100644
--- a/chrome/browser/ssl/captive_portal_blocking_page.cc
+++ b/chrome/browser/ssl/captive_portal_blocking_page.cc
@@ -13,10 +13,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "build/build_config.h"
-#include "chrome/browser/captive_portal/captive_portal_tab_helper.h"
 #include "chrome/browser/interstitials/chrome_metrics_helper.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ssl/certificate_error_reporter.h"
 #include "chrome/browser/ssl/chrome_ssl_blocking_page.h"
 #include "chrome/browser/ssl/ssl_error_controller_client.h"
 #include "components/captive_portal/captive_portal_detector.h"
@@ -43,6 +40,8 @@
 #include "content/public/common/referrer.h"
 #include "net/android/network_library.h"
 #include "ui/base/window_open_disposition.h"
+#else
+#include "chrome/browser/captive_portal/captive_portal_tab_helper.h"
 #endif
 
 namespace {
diff --git a/chrome/browser/ui/libgtkui/native_theme_gtk.cc b/chrome/browser/ui/libgtkui/native_theme_gtk.cc
index b4320c4a..b3396c6 100644
--- a/chrome/browser/ui/libgtkui/native_theme_gtk.cc
+++ b/chrome/browser/ui/libgtkui/native_theme_gtk.cc
@@ -132,6 +132,7 @@
     case ui::NativeTheme::kColorId_LabelEnabledColor:
       return GetFgColor("GtkLabel");
     case ui::NativeTheme::kColorId_LabelDisabledColor:
+    case ui::NativeTheme::kColorId_LabelSecondaryColor:
       return GetFgColor("GtkLabel:disabled");
     case ui::NativeTheme::kColorId_LabelTextSelectionColor:
       return GetFgColor(GtkVersionCheck(3, 20) ? "GtkLabel #selection"
diff --git a/chrome/browser/ui/signin_view_controller.cc b/chrome/browser/ui/signin_view_controller.cc
index 1d5755b..84e4d9ac 100644
--- a/chrome/browser/ui/signin_view_controller.cc
+++ b/chrome/browser/ui/signin_view_controller.cc
@@ -84,11 +84,7 @@
 
 // Returns the promo action to be used when signing with a new account.
 signin_metrics::PromoAction GetPromoActionForNewAccount(
-    signin::IdentityManager* identity_manager,
-    signin::AccountConsistencyMethod account_consistency) {
-  if (account_consistency != signin::AccountConsistencyMethod::kDice)
-    return signin_metrics::PromoAction::PROMO_ACTION_NEW_ACCOUNT_PRE_DICE;
-
+    signin::IdentityManager* identity_manager) {
   return !identity_manager->GetAccountsWithRefreshTokens().empty()
              ? signin_metrics::PromoAction::
                    PROMO_ACTION_NEW_ACCOUNT_EXISTING_ACCOUNT
@@ -119,16 +115,15 @@
   DCHECK(ShouldShowSigninForMode(mode));
 
   Profile* profile = browser->profile();
-  signin::AccountConsistencyMethod account_consistency =
-      AccountConsistencyModeManager::GetMethodForProfile(profile);
   std::string email;
   signin_metrics::Reason signin_reason = GetSigninReasonFromMode(mode);
+  signin::IdentityManager* identity_manager =
+      IdentityManagerFactory::GetForProfile(profile);
   if (signin_reason == signin_metrics::Reason::REASON_REAUTHENTICATION) {
-    auto* manager = IdentityManagerFactory::GetForProfile(profile);
-    email = manager->GetPrimaryAccountInfo().email;
+    email = identity_manager->GetPrimaryAccountInfo().email;
   }
-  signin_metrics::PromoAction promo_action = GetPromoActionForNewAccount(
-      IdentityManagerFactory::GetForProfile(profile), account_consistency);
+  signin_metrics::PromoAction promo_action =
+      GetPromoActionForNewAccount(identity_manager);
   ShowDiceSigninTab(browser, signin_reason, access_point, promo_action, email,
                     redirect_url);
 }
@@ -180,10 +175,8 @@
     const std::string& email_hint,
     const GURL& redirect_url) {
 #if DCHECK_IS_ON()
-  if (!signin::DiceMethodGreaterOrEqual(
-          AccountConsistencyModeManager::GetMethodForProfile(
-              browser->profile()),
-          signin::AccountConsistencyMethod::kDiceMigration)) {
+  if (AccountConsistencyModeManager::GetMethodForProfile(browser->profile()) !=
+      signin::AccountConsistencyMethod::kDice) {
     // Developers often fall into the trap of not configuring the OAuth client
     // ID and client secret and then attempt to sign in to Chromium, which
     // fail as the account consistency is disabled. Explicitly check that the
diff --git a/chrome/browser/ui/views/chrome_typography_provider.cc b/chrome/browser/ui/views/chrome_typography_provider.cc
index 0cc5ecf..16d4a02 100644
--- a/chrome/browser/ui/views/chrome_typography_provider.cc
+++ b/chrome/browser/ui/views/chrome_typography_provider.cc
@@ -110,7 +110,7 @@
   ui::NativeTheme::ColorId color_id;
   switch (style) {
     case STYLE_HINT:
-      color_id = ui::NativeTheme::kColorId_LabelDisabledColor;
+      color_id = ui::NativeTheme::kColorId_LabelSecondaryColor;
       break;
     case STYLE_RED:
       color_id = ui::NativeTheme::kColorId_AlertSeverityHigh;
diff --git a/chrome/browser/ui/views/toolbar/button_utils.cc b/chrome/browser/ui/views/toolbar/button_utils.cc
index 9881e17..adf2ad9 100644
--- a/chrome/browser/ui/views/toolbar/button_utils.cc
+++ b/chrome/browser/ui/views/toolbar/button_utils.cc
@@ -10,7 +10,6 @@
 #include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/toolbar/home_button.h"
-#include "chrome/browser/ui/views/toolbar/reload_button.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_button.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
@@ -18,6 +17,10 @@
 #include "ui/events/event_constants.h"
 #include "ui/views/accessibility/view_accessibility.h"
 
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
 std::unique_ptr<ToolbarButton> CreateBackButton(views::ButtonListener* listener,
                                                 Browser* browser) {
   auto back = std::make_unique<ToolbarButton>(
@@ -59,8 +62,11 @@
   return forward;
 }
 
-std::unique_ptr<ReloadButton> CreateReloadButton(Browser* browser) {
-  auto reload = std::make_unique<ReloadButton>(browser->command_controller());
+std::unique_ptr<ReloadButton> CreateReloadButton(
+    Browser* browser,
+    ReloadButton::IconStyle icon_style) {
+  auto reload =
+      std::make_unique<ReloadButton>(browser->command_controller(), icon_style);
   reload->set_triggerable_event_flags(ui::EF_LEFT_MOUSE_BUTTON |
                                       ui::EF_MIDDLE_MOUSE_BUTTON);
   reload->set_tag(IDC_RELOAD);
@@ -83,3 +89,9 @@
   home->SizeToPreferredSize();
   return home;
 }
+
+#if defined(OS_WIN)
+bool UseWindowsIconsForMinimalUI() {
+  return base::win::GetVersion() >= base::win::Version::WIN10;
+}
+#endif
diff --git a/chrome/browser/ui/views/toolbar/button_utils.h b/chrome/browser/ui/views/toolbar/button_utils.h
index 84a857ac..b4a7b3f 100644
--- a/chrome/browser/ui/views/toolbar/button_utils.h
+++ b/chrome/browser/ui/views/toolbar/button_utils.h
@@ -7,13 +7,15 @@
 
 #include <memory>
 
+#include "build/build_config.h"
+#include "chrome/browser/ui/views/toolbar/reload_button.h"
+
 namespace views {
 class ButtonListener;
 }  // namespace views
 
 class Browser;
 class HomeButton;
-class ReloadButton;
 class ToolbarButton;
 
 std::unique_ptr<ToolbarButton> CreateBackButton(views::ButtonListener* listener,
@@ -21,8 +23,17 @@
 std::unique_ptr<ToolbarButton> CreateForwardButton(
     views::ButtonListener* listener,
     Browser* browser);
-std::unique_ptr<ReloadButton> CreateReloadButton(Browser* browser);
+std::unique_ptr<ReloadButton> CreateReloadButton(
+    Browser* browser,
+    ReloadButton::IconStyle icon_style);
 std::unique_ptr<HomeButton> CreateHomeButton(views::ButtonListener* listener,
                                              Browser* browser);
 
+#if defined(OS_WIN)
+// For Windows 10 and later, we use custom icons for minimal-ui web app
+// Back and Reload buttons, to conform to the native OS' appearance.
+// https://w3c.github.io/manifest/#dom-displaymodetype-minimal-ui
+bool UseWindowsIconsForMinimalUI();
+#endif
+
 #endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_BUTTON_UTILS_H_
diff --git a/chrome/browser/ui/views/toolbar/reload_button.cc b/chrome/browser/ui/views/toolbar/reload_button.cc
index c74721d..9a4b628 100644
--- a/chrome/browser/ui/views/toolbar/reload_button.cc
+++ b/chrome/browser/ui/views/toolbar/reload_button.cc
@@ -8,10 +8,12 @@
 
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/command_updater.h"
 #include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/ui/views/toolbar/button_utils.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -33,7 +35,20 @@
   IDS_RELOAD_MENU_EMPTY_AND_HARD_RELOAD_ITEM,
 };
 
-const gfx::VectorIcon& GetIconForMode(bool is_reload) {
+const gfx::VectorIcon& GetIconForMode(ReloadButton::IconStyle icon_style,
+                                      bool is_reload) {
+#if defined(OS_WIN)
+  if (icon_style == ReloadButton::IconStyle::kMinimalUi &&
+      UseWindowsIconsForMinimalUI()) {
+    if (ui::MaterialDesignController::touch_ui()) {
+      return is_reload ? kReloadWindowsTouchIcon
+                       : kNavigateStopWindowsTouchIcon;
+    }
+
+    return is_reload ? kReloadWindowsIcon : kNavigateStopWindowsIcon;
+  }
+#endif
+
   if (ui::MaterialDesignController::touch_ui())
     return is_reload ? kReloadTouchIcon : kNavigateStopTouchIcon;
 
@@ -47,9 +62,11 @@
 // static
 const char ReloadButton::kViewClassName[] = "ReloadButton";
 
-ReloadButton::ReloadButton(CommandUpdater* command_updater)
+ReloadButton::ReloadButton(CommandUpdater* command_updater,
+                           IconStyle icon_style)
     : ToolbarButton(this, CreateMenuModel(), nullptr),
       command_updater_(command_updater),
+      icon_style_(icon_style),
       double_click_timer_delay_(
           base::TimeDelta::FromMilliseconds(views::GetDoubleClickInterval())),
       mode_switch_timer_delay_(base::TimeDelta::FromMilliseconds(1350)),
@@ -229,7 +246,8 @@
 }
 
 void ReloadButton::ChangeModeInternal(Mode mode) {
-  const gfx::VectorIcon& icon = GetIconForMode(mode == Mode::kReload);
+  const gfx::VectorIcon& icon =
+      GetIconForMode(icon_style_, mode == Mode::kReload);
   SetImage(views::Button::STATE_NORMAL,
            gfx::CreateVectorIcon(icon, normal_color_));
   SetImage(views::Button::STATE_DISABLED,
diff --git a/chrome/browser/ui/views/toolbar/reload_button.h b/chrome/browser/ui/views/toolbar/reload_button.h
index a976451c..dc263af 100644
--- a/chrome/browser/ui/views/toolbar/reload_button.h
+++ b/chrome/browser/ui/views/toolbar/reload_button.h
@@ -26,12 +26,13 @@
                      public views::ButtonListener,
                      public ui::SimpleMenuModel::Delegate {
  public:
+  enum class IconStyle { kBrowser, kMinimalUi };
   enum class Mode { kReload = 0, kStop };
 
   // The button's class name.
   static const char kViewClassName[];
 
-  explicit ReloadButton(CommandUpdater* command_updater);
+  explicit ReloadButton(CommandUpdater* command_updater, IconStyle icon_style);
   ReloadButton(const ReloadButton&) = delete;
   ReloadButton& operator=(const ReloadButton&) = delete;
   ~ReloadButton() override;
@@ -85,6 +86,8 @@
   // This may be NULL when testing.
   CommandUpdater* command_updater_;
 
+  const IconStyle icon_style_;
+
   // The mode we should be in assuming no timers are running.
   Mode intended_mode_ = Mode::kReload;
 
diff --git a/chrome/browser/ui/views/toolbar/reload_button_unittest.cc b/chrome/browser/ui/views/toolbar/reload_button_unittest.cc
index 64f8bb3..af9d1a42 100644
--- a/chrome/browser/ui/views/toolbar/reload_button_unittest.cc
+++ b/chrome/browser/ui/views/toolbar/reload_button_unittest.cc
@@ -38,7 +38,8 @@
   ReloadButton reload_;
 };
 
-ReloadButtonTest::ReloadButtonTest() : reload_(nullptr) {
+ReloadButtonTest::ReloadButtonTest()
+    : reload_(nullptr, ReloadButton::IconStyle::kBrowser) {
   // Set the timer delays to 0 so that timers will fire as soon as we tell the
   // message loop to run pending tasks.
   reload_.double_click_timer_delay_ = base::TimeDelta();
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index 29c95c1..0e6cd8f 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -187,7 +187,8 @@
 
   std::unique_ptr<ToolbarButton> forward = CreateForwardButton(this, browser_);
 
-  std::unique_ptr<ReloadButton> reload = CreateReloadButton(browser_);
+  std::unique_ptr<ReloadButton> reload =
+      CreateReloadButton(browser_, ReloadButton::IconStyle::kBrowser);
 
   std::unique_ptr<HomeButton> home = CreateHomeButton(this, browser_);
 
diff --git a/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc b/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc
index 2b80d2c..cb23899 100644
--- a/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc
@@ -9,6 +9,7 @@
 #include "base/numerics/ranges.h"
 #include "base/task_runner.h"
 #include "base/threading/sequenced_task_runner_handle.h"
+#include "build/build_config.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ui/browser_command_controller.h"
@@ -113,6 +114,15 @@
   }
 }
 
+const gfx::VectorIcon& GetBackImage(bool touch_ui) {
+#if defined(OS_WIN)
+  if (UseWindowsIconsForMinimalUI())
+    return touch_ui ? kBackArrowWindowsTouchIcon : kBackArrowWindowsIcon;
+#endif
+
+  return touch_ui ? kBackArrowTouchIcon : vector_icons::kBackArrowIcon;
+}
+
 }  // namespace
 
 // Holds controls in the far left or far right of the toolbar.
@@ -296,8 +306,8 @@
 
     back_ = left_container_->AddChildView(
         CreateBackButton(this, browser_view_->browser()));
-    reload_ = left_container_->AddChildView(
-        CreateReloadButton(browser_view_->browser()));
+    reload_ = left_container_->AddChildView(CreateReloadButton(
+        browser_view_->browser(), ReloadButton::IconStyle::kMinimalUi));
 
     SetInsetsForWebAppToolbarButton(back_, is_browser_focus_mode);
     SetInsetsForWebAppToolbarButton(reload_, is_browser_focus_mode);
@@ -712,8 +722,7 @@
 
   if (back_) {
     const bool touch_ui = ui::MaterialDesignController::touch_ui();
-    const gfx::VectorIcon& back_image =
-        touch_ui ? kBackArrowTouchIcon : vector_icons::kBackArrowIcon;
+    const gfx::VectorIcon& back_image = GetBackImage(touch_ui);
     back_->SetImage(views::Button::STATE_NORMAL,
                     gfx::CreateVectorIcon(back_image, normal_color));
     back_->SetImage(views::Button::STATE_DISABLED,
diff --git a/chrome/browser/ui/web_applications/web_app_dialog_manager.cc b/chrome/browser/ui/web_applications/web_app_dialog_manager.cc
index 432ffabb..1a534f5 100644
--- a/chrome/browser/ui/web_applications/web_app_dialog_manager.cc
+++ b/chrome/browser/ui/web_applications/web_app_dialog_manager.cc
@@ -88,7 +88,7 @@
   if (!provider)
     return false;
 
-  return provider->install_finalizer().CanUserUninstallFromSync(app_id);
+  return provider->install_finalizer().CanUserUninstallExternalApp(app_id);
 }
 
 void WebAppDialogManager::UninstallWebApp(const AppId& app_id,
@@ -97,6 +97,8 @@
                                           Callback callback) {
   auto dialog = std::make_unique<DialogInstance>();
 
+  // TODO(loyso): Use install_finalizer().UninstallExternalAppByUser() in
+  // upcoming WebAppUninstallDialog.
   dialog->UninstallWebApp(
       profile_, parent_window, app_id, uninstall_source,
       base::BindOnce(&WebAppDialogManager::OnDialogCompleted,
diff --git a/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
index 9d40fea..c25a7ab 100644
--- a/chrome/browser/ui/webui/settings/people_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
@@ -20,7 +20,6 @@
 #include "chrome/browser/first_run/first_run.h"
 #include "chrome/browser/signin/account_consistency_mode_manager.h"
 #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
-#include "chrome/browser/signin/scoped_account_consistency.h"
 #include "chrome/browser/signin/signin_error_controller_factory.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/chrome_pages.h"
diff --git a/chrome/browser/vr/testapp/vr_testapp.cc b/chrome/browser/vr/testapp/vr_testapp.cc
index 0a6209b0..f4929f5 100644
--- a/chrome/browser/vr/testapp/vr_testapp.cc
+++ b/chrome/browser/vr/testapp/vr_testapp.cc
@@ -32,7 +32,7 @@
 #include "ui/ozone/public/cursor_factory_ozone.h"
 #include "ui/ozone/public/ozone_gpu_test_helper.h"
 #include "ui/ozone/public/ozone_platform.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
@@ -166,7 +166,7 @@
   std::unique_ptr<vr::GlRenderer> renderer_;
 
   // Window-related state.
-  std::unique_ptr<ui::PlatformWindowBase> platform_window_;
+  std::unique_ptr<ui::PlatformWindow> platform_window_;
   gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
 
   base::WeakPtrFactory<AppWindow> weak_ptr_factory_;
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index 767ce88..947055d 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -57,6 +57,7 @@
     "//components/pref_registry",
     "//components/sync",
     "//content/public/browser",
+    "//services/preferences/public/cpp",
     "//skia",
   ]
 
diff --git a/chrome/browser/web_applications/components/install_finalizer.h b/chrome/browser/web_applications/components/install_finalizer.h
index 60475c9..003ecea 100644
--- a/chrome/browser/web_applications/components/install_finalizer.h
+++ b/chrome/browser/web_applications/components/install_finalizer.h
@@ -67,6 +67,10 @@
   virtual void UninstallWebAppFromSyncByUser(const AppId& app_id,
                                              UninstallWebAppCallback) = 0;
 
+  virtual bool CanUserUninstallExternalApp(const AppId& app_id) const = 0;
+  // If external app is synced, uninstalls it from sync and from all devices.
+  virtual void UninstallExternalAppByUser(const AppId& app_id,
+                                          UninstallWebAppCallback callback) = 0;
   // Returns true if the app with |app_id| was previously uninstalled by the
   // user. For example, if a user uninstalls a default app ('default apps' are
   // considered external apps), then this will return true.
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc
index ebeb920f..b195f048 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc
@@ -167,6 +167,22 @@
 
 bool BookmarkAppInstallFinalizer::CanUserUninstallFromSync(
     const web_app::AppId& app_id) const {
+  // Bookmark apps don't support app installation from different sources.
+  // The old system uninstalls extension completely, the implementation is
+  // the same:
+  return CanUserUninstallExternalApp(app_id);
+}
+
+void BookmarkAppInstallFinalizer::UninstallWebAppFromSyncByUser(
+    const web_app::AppId& app_id,
+    UninstallWebAppCallback callback) {
+  // Bookmark apps don't support app installation from different sources.
+  // Uninstall extension completely:
+  UninstallExtension(app_id, std::move(callback));
+}
+
+bool BookmarkAppInstallFinalizer::CanUserUninstallExternalApp(
+    const web_app::AppId& app_id) const {
   const Extension* app = GetEnabledExtension(app_id);
   DCHECK(app);
   return extensions::ExtensionSystem::Get(profile_)
@@ -174,7 +190,7 @@
       ->UserMayModifySettings(app, nullptr);
 }
 
-void BookmarkAppInstallFinalizer::UninstallWebAppFromSyncByUser(
+void BookmarkAppInstallFinalizer::UninstallExternalAppByUser(
     const web_app::AppId& app_id,
     UninstallWebAppCallback callback) {
   // Bookmark apps don't support app installation from different sources.
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h
index a964f6c1..65a31c60 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h
+++ b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h
@@ -48,7 +48,10 @@
       UninstallWebAppCallback callback) override;
   bool CanUserUninstallFromSync(const web_app::AppId& app_id) const override;
   void UninstallWebAppFromSyncByUser(const web_app::AppId& app_id,
-                                     UninstallWebAppCallback) override;
+                                     UninstallWebAppCallback callback) override;
+  bool CanUserUninstallExternalApp(const web_app::AppId& app_id) const override;
+  void UninstallExternalAppByUser(const web_app::AppId& app_id,
+                                  UninstallWebAppCallback callback) override;
   bool WasExternalAppUninstalledByUser(
       const web_app::AppId& app_id) const override;
   bool CanRevealAppShim() const override;
diff --git a/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc b/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc
index 7ea858b..7fbfed0 100644
--- a/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc
+++ b/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc
@@ -210,6 +210,16 @@
     NOTIMPLEMENTED();
   }
 
+  bool CanUserUninstallExternalApp(const AppId& app_id) const override {
+    NOTIMPLEMENTED();
+    return false;
+  }
+
+  void UninstallExternalAppByUser(const AppId& app_id,
+                                  UninstallWebAppCallback callback) override {
+    NOTIMPLEMENTED();
+  }
+
   bool WasExternalAppUninstalledByUser(const AppId& app_id) const override {
     NOTIMPLEMENTED();
     return false;
diff --git a/chrome/browser/web_applications/test/test_install_finalizer.cc b/chrome/browser/web_applications/test/test_install_finalizer.cc
index adb2d92..5b1e04a 100644
--- a/chrome/browser/web_applications/test/test_install_finalizer.cc
+++ b/chrome/browser/web_applications/test/test_install_finalizer.cc
@@ -81,6 +81,17 @@
   NOTIMPLEMENTED();
 }
 
+bool TestInstallFinalizer::CanUserUninstallExternalApp(
+    const AppId& app_id) const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+void TestInstallFinalizer::UninstallExternalAppByUser(const AppId& app_id,
+                                                      UninstallWebAppCallback) {
+  NOTIMPLEMENTED();
+}
+
 bool TestInstallFinalizer::WasExternalAppUninstalledByUser(
     const AppId& app_id) const {
   return base::Contains(user_uninstalled_external_apps_, app_id);
diff --git a/chrome/browser/web_applications/test/test_install_finalizer.h b/chrome/browser/web_applications/test/test_install_finalizer.h
index 2f41e40..c070253 100644
--- a/chrome/browser/web_applications/test/test_install_finalizer.h
+++ b/chrome/browser/web_applications/test/test_install_finalizer.h
@@ -42,6 +42,9 @@
   bool CanUserUninstallFromSync(const AppId& app_id) const override;
   void UninstallWebAppFromSyncByUser(const AppId& app_id,
                                      UninstallWebAppCallback callback) override;
+  bool CanUserUninstallExternalApp(const AppId& app_id) const override;
+  void UninstallExternalAppByUser(const AppId& app_id,
+                                  UninstallWebAppCallback callback) override;
   bool WasExternalAppUninstalledByUser(const AppId& app_id) const override;
   bool CanAddAppToQuickLaunchBar() const override;
   void AddAppToQuickLaunchBar(const AppId& app_id) override;
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc
index 9760378..48037cc 100644
--- a/chrome/browser/web_applications/web_app.cc
+++ b/chrome/browser/web_applications/web_app.cc
@@ -48,15 +48,34 @@
 }
 
 bool WebApp::HasOnlySource(Source::Type source) const {
-  Sources mask;
-  mask[source] = true;
-  return (sources_ & ~mask).none() && sources_[source];
+  Sources specified_sources;
+  specified_sources[source] = true;
+  return HasAnySpecifiedSourcesAndNoOtherSources(specified_sources);
 }
 
 bool WebApp::IsSynced() const {
   return sources_[Source::kSync];
 }
 
+bool WebApp::IsDefaultApp() const {
+  return sources_[Source::kDefault];
+}
+
+bool WebApp::CanUserUninstallExternalApp() const {
+  Sources specified_sources;
+  specified_sources[Source::kDefault] = true;
+  specified_sources[Source::kSync] = true;
+  specified_sources[Source::kWebAppStore] = true;
+  return HasAnySpecifiedSourcesAndNoOtherSources(specified_sources);
+}
+
+bool WebApp::HasAnySpecifiedSourcesAndNoOtherSources(
+    Sources specified_sources) const {
+  bool has_any_specified_sources = (sources_ & specified_sources).any();
+  bool has_no_other_sources = (sources_ & ~specified_sources).none();
+  return has_any_specified_sources && has_no_other_sources;
+}
+
 bool WebApp::WasInstalledByUser() const {
   return sources_[Source::kSync] || sources_[Source::kWebAppStore];
 }
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h
index a56bbfe..88a38bc 100644
--- a/chrome/browser/web_applications/web_app.h
+++ b/chrome/browser/web_applications/web_app.h
@@ -91,6 +91,8 @@
   bool HasOnlySource(Source::Type source) const;
 
   bool IsSynced() const;
+  bool IsDefaultApp() const;
+  bool CanUserUninstallExternalApp() const;
   bool WasInstalledByUser() const;
 
   void SetName(const std::string& name);
@@ -107,6 +109,9 @@
   void SetSyncData(SyncData sync_data);
 
  private:
+  using Sources = std::bitset<Source::kMaxValue + 1>;
+  bool HasAnySpecifiedSourcesAndNoOtherSources(Sources specified_sources) const;
+
   friend class WebAppDatabase;
   friend bool operator==(const WebApp&, const WebApp&);
   friend std::ostream& operator<<(std::ostream&, const WebApp&);
@@ -114,7 +119,6 @@
   AppId app_id_;
 
   // This set always contains at least one source.
-  using Sources = std::bitset<Source::kMaxValue + 1>;
   Sources sources_;
 
   std::string name_;
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc
index 0992d17..570c932 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -10,17 +10,25 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/values.h"
 #include "chrome/browser/installable/installable_metrics.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
 #include "chrome/browser/web_applications/components/web_app_icon_generator.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/common/web_application_info.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
+#include "services/preferences/public/cpp/dictionary_value_update.h"
+#include "services/preferences/public/cpp/scoped_pref_update.h"
 #include "third_party/skia/include/core/SkColor.h"
 
 namespace web_app {
@@ -104,14 +112,92 @@
   web_app->SetIcons(std::move(web_app_icons));
 }
 
+// The stored preferences look like:
+// "web_apps": {
+//   "web_app_ids": {
+//     "<app_id_1>": {
+//       "was_external_app_uninstalled_by_user": true,
+//     },
+//     "<app_id_N>": {
+//       "was_external_app_uninstalled_by_user": false,
+//     }
+//   }
+// }
+//
+
+constexpr char kWasExternalAppUninstalledByUser[] =
+    "was_external_app_uninstalled_by_user";
+
+const base::DictionaryValue* GetWebAppDictionary(
+    const PrefService* pref_service,
+    const AppId& app_id) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  const base::DictionaryValue* web_apps_prefs =
+      pref_service->GetDictionary(prefs::kWebAppsPreferences);
+  if (!web_apps_prefs)
+    return nullptr;
+
+  const base::Value* web_app_prefs = web_apps_prefs->FindDictKey(app_id);
+  if (!web_app_prefs)
+    return nullptr;
+
+  return &base::Value::AsDictionaryValue(*web_app_prefs);
+}
+
+std::unique_ptr<prefs::DictionaryValueUpdate> UpdateWebAppDictionary(
+    std::unique_ptr<prefs::DictionaryValueUpdate> web_apps_prefs_update,
+    const AppId& app_id) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  std::unique_ptr<prefs::DictionaryValueUpdate> web_app_prefs_update;
+  if (!web_apps_prefs_update->GetDictionaryWithoutPathExpansion(
+          app_id, &web_app_prefs_update)) {
+    web_app_prefs_update =
+        web_apps_prefs_update->SetDictionaryWithoutPathExpansion(
+            app_id, std::make_unique<base::DictionaryValue>());
+  }
+  return web_app_prefs_update;
+}
+
+bool GetBoolWebAppPref(const PrefService* pref_service,
+                       const AppId& app_id,
+                       base::StringPiece path) {
+  const base::DictionaryValue* web_app_prefs =
+      GetWebAppDictionary(pref_service, app_id);
+  bool pref_value = false;
+  if (web_app_prefs)
+    web_app_prefs->GetBoolean(path, &pref_value);
+  return pref_value;
+}
+
+void UpdateBoolWebAppPref(PrefService* pref_service,
+                          const AppId& app_id,
+                          base::StringPiece path,
+                          bool value) {
+  prefs::ScopedDictionaryPrefUpdate update(pref_service,
+                                           prefs::kWebAppsPreferences);
+
+  std::unique_ptr<prefs::DictionaryValueUpdate> web_app_prefs =
+      UpdateWebAppDictionary(update.Get(), app_id);
+  web_app_prefs->SetBoolean(path, value);
+}
+
 }  // namespace
 
-WebAppInstallFinalizer::WebAppInstallFinalizer(WebAppSyncBridge* sync_bridge,
+WebAppInstallFinalizer::WebAppInstallFinalizer(Profile* profile,
+                                               WebAppSyncBridge* sync_bridge,
                                                WebAppIconManager* icon_manager)
-    : sync_bridge_(sync_bridge), icon_manager_(icon_manager) {}
+    : profile_(profile),
+      sync_bridge_(sync_bridge),
+      icon_manager_(icon_manager) {}
 
 WebAppInstallFinalizer::~WebAppInstallFinalizer() = default;
 
+// static
+void WebAppInstallFinalizer::RegisterProfilePrefs(
+    user_prefs::PrefRegistrySyncable* registry) {
+  registry->RegisterDictionaryPref(prefs::kWebAppsPreferences);
+}
+
 void WebAppInstallFinalizer::FinalizeInstall(
     const WebApplicationInfo& web_app_info,
     const FinalizeOptions& options,
@@ -264,8 +350,6 @@
 
 bool WebAppInstallFinalizer::CanUserUninstallFromSync(
     const AppId& app_id) const {
-  // TODO(loyso): Policy Apps: Implement web_app::ManagementPolicy taking
-  // extensions::ManagementPolicy::UserMayModifySettings as inspiration.
   const WebApp* app = sync_bridge_->registrar().GetAppById(app_id);
   return app ? app->IsSynced() : false;
 }
@@ -277,10 +361,40 @@
   UninstallWebAppOrRemoveSource(app_id, Source::kSync, std::move(callback));
 }
 
+bool WebAppInstallFinalizer::CanUserUninstallExternalApp(
+    const AppId& app_id) const {
+  // TODO(loyso): Policy Apps: Implement web_app::ManagementPolicy taking
+  // extensions::ManagementPolicy::UserMayModifySettings as inspiration.
+  const WebApp* app = sync_bridge_->registrar().GetAppById(app_id);
+  return app ? app->CanUserUninstallExternalApp() : false;
+}
+
+void WebAppInstallFinalizer::UninstallExternalAppByUser(
+    const AppId& app_id,
+    UninstallWebAppCallback callback) {
+  const WebApp* app = sync_bridge_->registrar().GetAppById(app_id);
+  DCHECK(app);
+  DCHECK(app->CanUserUninstallExternalApp());
+
+  if (app->IsDefaultApp()) {
+    UpdateBoolWebAppPref(profile_->GetPrefs(), app_id,
+                         kWasExternalAppUninstalledByUser, true);
+  }
+
+  // UninstallExternalAppByUser can wipe out an app with multiple sources. This
+  // is the behavior from the old bookmark-app based system, which does not
+  // support incremental AddSource/RemoveSource. Here we are preserving that
+  // behavior for now.
+  // TODO(loyso): Implement different uninstall flows in UI. For example, we
+  // should separate UninstallWebAppFromSyncByUser from
+  // UninstallExternalAppByUser.
+  UninstallWebApp(app_id, std::move(callback));
+}
+
 bool WebAppInstallFinalizer::WasExternalAppUninstalledByUser(
     const AppId& app_id) const {
-  NOTIMPLEMENTED();
-  return false;
+  return GetBoolWebAppPref(profile_->GetPrefs(), app_id,
+                           kWasExternalAppUninstalledByUser);
 }
 
 void WebAppInstallFinalizer::FinalizeUpdate(
@@ -291,6 +405,17 @@
   NOTIMPLEMENTED();
 }
 
+void WebAppInstallFinalizer::UninstallWebApp(const AppId& app_id,
+                                             UninstallWebAppCallback callback) {
+  ScopedRegistryUpdate update(sync_bridge_);
+  update->DeleteApp(app_id);
+
+  icon_manager_->DeleteData(
+      app_id, base::BindOnce(&WebAppInstallFinalizer::OnIconsDataDeleted,
+                             weak_ptr_factory_.GetWeakPtr(), app_id,
+                             std::move(callback)));
+}
+
 void WebAppInstallFinalizer::UninstallWebAppOrRemoveSource(
     const AppId& app_id,
     Source::Type source,
@@ -302,17 +427,10 @@
                                   /*uninstalled=*/false));
   }
 
-  ScopedRegistryUpdate update(sync_bridge_);
-
   if (app->HasOnlySource(source)) {
-    update->DeleteApp(app_id);
-
-    icon_manager_->DeleteData(
-        app_id, base::BindOnce(&WebAppInstallFinalizer::OnIconsDataDeleted,
-                               weak_ptr_factory_.GetWeakPtr(), app_id,
-                               std::move(callback)));
-
+    UninstallWebApp(app_id, std::move(callback));
   } else {
+    ScopedRegistryUpdate update(sync_bridge_);
     WebApp* app_to_update = update->UpdateApp(app_id);
     app_to_update->RemoveSource(source);
 
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.h b/chrome/browser/web_applications/web_app_install_finalizer.h
index b91f839..f3fb91f 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.h
+++ b/chrome/browser/web_applications/web_app_install_finalizer.h
@@ -12,8 +12,13 @@
 #include "chrome/browser/web_applications/components/install_finalizer.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
 
+class Profile;
 struct WebApplicationInfo;
 
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
 namespace web_app {
 
 class WebApp;
@@ -22,10 +27,13 @@
 
 class WebAppInstallFinalizer final : public InstallFinalizer {
  public:
-  WebAppInstallFinalizer(WebAppSyncBridge* sync_bridge,
+  WebAppInstallFinalizer(Profile* profile,
+                         WebAppSyncBridge* sync_bridge,
                          WebAppIconManager* icon_manager);
   ~WebAppInstallFinalizer() override;
 
+  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
   // InstallFinalizer:
   void FinalizeInstall(const WebApplicationInfo& web_app_info,
                        const FinalizeOptions& options,
@@ -43,11 +51,15 @@
   bool CanUserUninstallFromSync(const AppId& app_id) const override;
   void UninstallWebAppFromSyncByUser(const AppId& app_id,
                                      UninstallWebAppCallback callback) override;
+  bool CanUserUninstallExternalApp(const AppId& app_id) const override;
+  void UninstallExternalAppByUser(const AppId& app_id,
+                                  UninstallWebAppCallback callback) override;
   bool WasExternalAppUninstalledByUser(const AppId& app_id) const override;
   bool CanRevealAppShim() const override;
   void RevealAppShim(const AppId& app_id) override;
 
  private:
+  void UninstallWebApp(const AppId& app_id, UninstallWebAppCallback callback);
   void UninstallWebAppOrRemoveSource(const AppId& app_id,
                                      Source::Type source,
                                      UninstallWebAppCallback callback);
@@ -66,6 +78,7 @@
                                   const AppId& installed_app_id,
                                   InstallResultCode code);
 
+  Profile* const profile_;
   WebAppSyncBridge* const sync_bridge_;
   WebAppIconManager* const icon_manager_;
 
diff --git a/chrome/browser/web_applications/web_app_install_manager_unittest.cc b/chrome/browser/web_applications/web_app_install_manager_unittest.cc
index 1cae15a..3a94241 100644
--- a/chrome/browser/web_applications/web_app_install_manager_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_manager_unittest.cc
@@ -122,7 +122,8 @@
                                                         std::move(file_utils));
 
     install_finalizer_ = std::make_unique<WebAppInstallFinalizer>(
-        &test_registry_controller_->sync_bridge(), icon_manager_.get());
+        profile(), &test_registry_controller_->sync_bridge(),
+        icon_manager_.get());
 
     shortcut_manager_ = std::make_unique<TestAppShortcutManager>(profile());
 
@@ -293,6 +294,18 @@
     return result;
   }
 
+  bool UninstallExternalAppByUser(const AppId& app_id) {
+    bool result = false;
+    base::RunLoop run_loop;
+    finalizer().UninstallExternalAppByUser(
+        app_id, base::BindLambdaForTesting([&](bool uninstalled) {
+          result = uninstalled;
+          run_loop.Quit();
+        }));
+    run_loop.Run();
+    return result;
+  }
+
   void DestroyManagers() {
     // The reverse order of creation:
     ui_manager_.reset();
@@ -678,6 +691,7 @@
   InitRegistrarWithApp(std::move(policy_and_user_app));
 
   EXPECT_TRUE(finalizer().CanUserUninstallFromSync(app_id));
+  EXPECT_FALSE(finalizer().WasExternalAppUninstalledByUser(app_id));
 
   bool observer_uninstall_called = false;
   WebAppInstallObserver observer(&registrar());
@@ -697,6 +711,8 @@
   EXPECT_TRUE(registrar().GetAppById(app_id));
   EXPECT_FALSE(observer_uninstall_called);
   EXPECT_TRUE(finalizer().CanUserUninstallFromSync(app_id));
+  EXPECT_FALSE(finalizer().WasExternalAppUninstalledByUser(app_id));
+  EXPECT_TRUE(finalizer().CanUserUninstallExternalApp(app_id));
 
   // Uninstall user app last.
   file_utils().SetNextDeleteFileRecursivelyResult(true);
@@ -706,6 +722,8 @@
   EXPECT_FALSE(registrar().GetAppById(app_id));
   EXPECT_TRUE(observer_uninstall_called);
   EXPECT_FALSE(finalizer().CanUserUninstallFromSync(app_id));
+  EXPECT_FALSE(finalizer().WasExternalAppUninstalledByUser(app_id));
+  EXPECT_FALSE(finalizer().CanUserUninstallExternalApp(app_id));
 }
 
 TEST_F(WebAppInstallManagerTest, PolicyAndUser_UninstallWebAppFromSyncByUser) {
@@ -722,6 +740,7 @@
   InitRegistrarWithApp(std::move(policy_and_user_app));
 
   EXPECT_TRUE(finalizer().CanUserUninstallFromSync(app_id));
+  EXPECT_FALSE(finalizer().CanUserUninstallExternalApp(app_id));
 
   bool observer_uninstall_called = false;
   WebAppInstallObserver observer(&registrar());
@@ -736,6 +755,8 @@
   EXPECT_TRUE(registrar().GetAppById(app_id));
   EXPECT_FALSE(observer_uninstall_called);
   EXPECT_FALSE(finalizer().CanUserUninstallFromSync(app_id));
+  EXPECT_FALSE(finalizer().WasExternalAppUninstalledByUser(app_id));
+  EXPECT_FALSE(finalizer().CanUserUninstallExternalApp(app_id));
 
   // Uninstall policy app last.
   file_utils().SetNextDeleteFileRecursivelyResult(true);
@@ -744,6 +765,41 @@
                                       ExternalInstallSource::kExternalPolicy));
   EXPECT_FALSE(registrar().GetAppById(app_id));
   EXPECT_TRUE(observer_uninstall_called);
+  EXPECT_FALSE(finalizer().WasExternalAppUninstalledByUser(app_id));
+  EXPECT_FALSE(finalizer().CanUserUninstallExternalApp(app_id));
+}
+
+TEST_F(WebAppInstallManagerTest, DefaultAndUser_UninstallExternalAppByUser) {
+  std::unique_ptr<WebApp> default_and_user_app =
+      CreateWebApp(GURL("https://example.com/path"), Source::kSync,
+                   /*user_display_mode=*/DisplayMode::kStandalone);
+  default_and_user_app->AddSource(Source::kDefault);
+
+  const AppId app_id = default_and_user_app->app_id();
+  const GURL external_app_url("https://example.com/path/default");
+
+  externally_installed_app_prefs().Insert(
+      external_app_url, app_id, ExternalInstallSource::kExternalDefault);
+  InitRegistrarWithApp(std::move(default_and_user_app));
+
+  EXPECT_TRUE(finalizer().CanUserUninstallExternalApp(app_id));
+  EXPECT_FALSE(finalizer().WasExternalAppUninstalledByUser(app_id));
+
+  bool observer_uninstall_called = false;
+  WebAppInstallObserver observer(&registrar());
+  observer.SetWebAppUninstalledDelegate(
+      base::BindLambdaForTesting([&](const AppId& uninstalled_app_id) {
+        observer_uninstall_called = true;
+      }));
+
+  file_utils().SetNextDeleteFileRecursivelyResult(true);
+
+  EXPECT_TRUE(UninstallExternalAppByUser(app_id));
+
+  EXPECT_FALSE(registrar().GetAppById(app_id));
+  EXPECT_TRUE(observer_uninstall_called);
+  EXPECT_FALSE(finalizer().CanUserUninstallExternalApp(app_id));
+  EXPECT_TRUE(finalizer().WasExternalAppUninstalledByUser(app_id));
 }
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_install_task_unittest.cc b/chrome/browser/web_applications/web_app_install_task_unittest.cc
index 5d7f724..b91cf383 100644
--- a/chrome/browser/web_applications/web_app_install_task_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_task_unittest.cc
@@ -142,7 +142,7 @@
     ui_manager_ = std::make_unique<TestWebAppUiManager>();
 
     install_finalizer_ = std::make_unique<WebAppInstallFinalizer>(
-        &controller().sync_bridge(), icon_manager_.get());
+        profile(), &controller().sync_bridge(), icon_manager_.get());
     shortcut_manager_ = std::make_unique<TestAppShortcutManager>(profile());
 
     install_finalizer_->SetSubsystems(&registrar(), ui_manager_.get());
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc
index 32ca150..3a3fdb5 100644
--- a/chrome/browser/web_applications/web_app_provider.cc
+++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -187,7 +187,7 @@
   auto icon_manager = std::make_unique<WebAppIconManager>(
       profile, *registrar, std::make_unique<FileUtilsWrapper>());
   install_finalizer_ = std::make_unique<WebAppInstallFinalizer>(
-      sync_bridge.get(), icon_manager.get());
+      profile, sync_bridge.get(), icon_manager.get());
   file_handler_manager_ = std::make_unique<WebAppFileHandlerManager>(profile);
   shortcut_manager_ = std::make_unique<WebAppShortcutManager>(profile);
 
@@ -262,6 +262,7 @@
 void WebAppProvider::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
   ExternallyInstalledWebAppPrefs::RegisterProfilePrefs(registry);
+  WebAppInstallFinalizer::RegisterProfilePrefs(registry);
   WebAppPolicyManager::RegisterProfilePrefs(registry);
   SystemWebAppManager::RegisterProfilePrefs(registry);
   RegisterInstallBounceMetricProfilePrefs(registry);
diff --git a/chrome/browser/web_applications/web_app_unittest.cc b/chrome/browser/web_applications/web_app_unittest.cc
index a819e7c..7ae33c8 100644
--- a/chrome/browser/web_applications/web_app_unittest.cc
+++ b/chrome/browser/web_applications/web_app_unittest.cc
@@ -96,4 +96,37 @@
   EXPECT_FALSE(app.WasInstalledByUser());
 }
 
+TEST(WebAppTest, CanUserUninstallExternalApp) {
+  WebApp app{GenerateAppIdFromURL(GURL("https://example.com"))};
+
+  app.AddSource(Source::kDefault);
+  EXPECT_TRUE(app.IsDefaultApp());
+  EXPECT_TRUE(app.CanUserUninstallExternalApp());
+
+  app.AddSource(Source::kSync);
+  EXPECT_TRUE(app.CanUserUninstallExternalApp());
+  app.AddSource(Source::kWebAppStore);
+  EXPECT_TRUE(app.CanUserUninstallExternalApp());
+
+  app.AddSource(Source::kPolicy);
+  EXPECT_FALSE(app.CanUserUninstallExternalApp());
+  app.AddSource(Source::kSystem);
+  EXPECT_FALSE(app.CanUserUninstallExternalApp());
+
+  app.RemoveSource(Source::kSync);
+  EXPECT_FALSE(app.CanUserUninstallExternalApp());
+  app.RemoveSource(Source::kWebAppStore);
+  EXPECT_FALSE(app.CanUserUninstallExternalApp());
+
+  app.RemoveSource(Source::kSystem);
+  EXPECT_FALSE(app.CanUserUninstallExternalApp());
+
+  app.RemoveSource(Source::kPolicy);
+  EXPECT_TRUE(app.CanUserUninstallExternalApp());
+
+  EXPECT_TRUE(app.IsDefaultApp());
+  app.RemoveSource(Source::kDefault);
+  EXPECT_FALSE(app.IsDefaultApp());
+}
+
 }  // namespace web_app
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 8b0ab89..602a1c7 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1776,6 +1776,11 @@
 // Dictionary that maps web app URLs to Chrome extension IDs.
 const char kWebAppsExtensionIDs[] = "web_apps.extension_ids";
 
+// Dictionary that maps web app ID to a dictionary of various preferences.
+// Used only in the new web applications system to store app preferences which
+// outlive the app installation and uninstallation.
+const char kWebAppsPreferences[] = "web_apps.web_app_ids";
+
 // A string representing the last version of Chrome that System Web Apps were
 // updated for.
 const char kSystemWebAppLastUpdateVersion[] =
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index e6ca61d..b002eb8e 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -608,6 +608,7 @@
 extern const char kWebAppInstallMetrics[];
 
 extern const char kWebAppsExtensionIDs[];
+extern const char kWebAppsPreferences[];
 extern const char kSystemWebAppLastUpdateVersion[];
 extern const char kSystemWebAppLastInstalledLocale[];
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 10df019..8f9cadc 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1062,6 +1062,7 @@
       "../browser/policy/cloud/cloud_policy_test_utils.h",
       "../browser/policy/cloud/component_cloud_policy_browsertest.cc",
       "../browser/policy/cloud/device_management_service_browsertest.cc",
+      "../browser/policy/content_settings_policy_browsertest.cc",
       "../browser/policy/policy_browsertest.cc",
       "../browser/policy/policy_initialization_browsertest.cc",
       "../browser/policy/policy_network_browsertest.cc",
@@ -1069,6 +1070,7 @@
       "../browser/policy/policy_startup_browsertest.cc",
       "../browser/policy/policy_test_utils.cc",
       "../browser/policy/policy_test_utils.h",
+      "../browser/policy/safe_browsing_policy_browsertest.cc",
       "../browser/policy/site_isolation_policy_browsertest.cc",
       "../browser/portal/portal_browsertest.cc",
       "../browser/predictors/loading_predictor_browsertest.cc",
diff --git a/chrome/test/data/downloads/multiple_download_from_iframe_srcdoc.html b/chrome/test/data/downloads/multiple_download_from_iframe_srcdoc.html
index 3f0efb0..7690142b 100644
--- a/chrome/test/data/downloads/multiple_download_from_iframe_srcdoc.html
+++ b/chrome/test/data/downloads/multiple_download_from_iframe_srcdoc.html
@@ -3,7 +3,7 @@
 function iframe_srcdoc_download() {
   iframe = document.createElement("iframe");
   iframe.srcdoc = `<body><iframe src='tiny_binary.bin'></iframe></body>`;
-  iframe.sandbox = "allow-scripts allow-downloads-without-user-activation";
+  iframe.sandbox = "allow-scripts allow-downloads";
   iframe.height = "0";
   iframe.width = "0";
   iframe.scrolling = "no";
diff --git a/chromeos/components/media_app_ui/media_app_guest_ui.cc b/chromeos/components/media_app_ui/media_app_guest_ui.cc
index d17fb80..b2ed265 100644
--- a/chromeos/components/media_app_ui/media_app_guest_ui.cc
+++ b/chromeos/components/media_app_ui/media_app_guest_ui.cc
@@ -18,14 +18,14 @@
 content::WebUIDataSource* MediaAppGuestUI::CreateDataSource() {
   content::WebUIDataSource* source =
       content::WebUIDataSource::Create(kChromeUIMediaAppGuestHost);
-  // Add resources from chromeos_resources.pak.
+  // Add resources from chromeos_media_app_resources.pak.
   source->AddResourcePath("app.html", IDR_MEDIA_APP_APP_HTML);
   source->AddResourcePath("receiver.js", IDR_MEDIA_APP_RECEIVER_JS);
 
-  // Add resources from chromeos_media_app_bundle.pak that are also needed for
-  // mocks. If enable_cros_media_app = true, then these calls will happen a
-  // second time with the same parameters. When false, we need these to specify
-  // what routes are mocked by files in ./resources/mock/js. The loop is
+  // Add resources from chromeos_media_app_bundle_resources.pak that are also
+  // needed for mocks. If enable_cros_media_app = true, then these calls will
+  // happen a second time with the same parameters. When false, we need these to
+  // specify what routes are mocked by files in ./resources/mock/js. The loop is
   // irrelevant in that case.
   source->AddResourcePath("js/app_main.js", IDR_MEDIA_APP_APP_MAIN_JS);
   source->AddResourcePath("js/app_image_handler_module.js",
@@ -33,7 +33,7 @@
   source->AddResourcePath("js/app_drop_target_module.js",
                           IDR_MEDIA_APP_APP_DROP_TARGET_MODULE_JS);
 
-  // Add all resources from chromeos_media_app_bundle.pak.
+  // Add all resources from chromeos_media_app_bundle_resources.pak.
   for (size_t i = 0; i < kChromeosMediaAppBundleResourcesSize; i++) {
     source->AddResourcePath(kChromeosMediaAppBundleResources[i].name,
                             kChromeosMediaAppBundleResources[i].value);
diff --git a/chromeos/components/media_app_ui/media_app_ui.cc b/chromeos/components/media_app_ui/media_app_ui.cc
index 2cd6a4c..82cdcc1 100644
--- a/chromeos/components/media_app_ui/media_app_ui.cc
+++ b/chromeos/components/media_app_ui/media_app_ui.cc
@@ -19,13 +19,13 @@
   content::WebUIDataSource* source =
       content::WebUIDataSource::Create(kChromeUIMediaAppHost);
 
-  // Add resources from chromeos_resources.pak.
+  // Add resources from chromeos_media_app_resources.pak.
   source->SetDefaultResource(IDR_MEDIA_APP_INDEX_HTML);
   source->AddResourcePath("pwa.html", IDR_MEDIA_APP_PWA_HTML);
   source->AddResourcePath("manifest.json", IDR_MEDIA_APP_MANIFEST);
   source->AddResourcePath("launch.js", IDR_MEDIA_APP_LAUNCH_JS);
 
-  // Add resources from chromeos_media_app_bundle.pak.
+  // Add resources from chromeos_media_app_bundle_resources.pak.
   source->AddResourcePath("system_assets/app_icon_256.png",
                           IDR_MEDIA_APP_APP_ICON_256_PNG);
   return source;
diff --git a/chromeos/dbus/blocking_method_caller.cc b/chromeos/dbus/blocking_method_caller.cc
index 37b94d4a..9447a194 100644
--- a/chromeos/dbus/blocking_method_caller.cc
+++ b/chromeos/dbus/blocking_method_caller.cc
@@ -51,11 +51,11 @@
     dbus::ScopedDBusError* error_out) {
   // on_blocking_method_call_->Signal() will be called when |signaler| is
   // destroyed.
-  base::Closure signal_task(
-      base::Bind(&base::WaitableEvent::Signal,
-                 base::Unretained(&on_blocking_method_call_)));
+  base::OnceClosure signal_task =
+      base::BindOnce(&base::WaitableEvent::Signal,
+                     base::Unretained(&on_blocking_method_call_));
   base::ScopedClosureRunner* signaler =
-      new base::ScopedClosureRunner(signal_task);
+      new base::ScopedClosureRunner(std::move(signal_task));
 
   std::unique_ptr<dbus::Response> response;
   bus_->GetDBusTaskRunner()->PostTask(
diff --git a/chromeos/dbus/fake_image_burner_client.cc b/chromeos/dbus/fake_image_burner_client.cc
index ceb17df..1bba114 100644
--- a/chromeos/dbus/fake_image_burner_client.cc
+++ b/chromeos/dbus/fake_image_burner_client.cc
@@ -20,8 +20,7 @@
 
 void FakeImageBurnerClient::BurnImage(const std::string& from_path,
                                       const std::string& to_path,
-                                      const ErrorCallback& error_callback) {
-}
+                                      ErrorCallback error_callback) {}
 
 void FakeImageBurnerClient::SetEventHandlers(
     const BurnFinishedHandler& burn_finished_handler,
diff --git a/chromeos/dbus/fake_image_burner_client.h b/chromeos/dbus/fake_image_burner_client.h
index a508082..83a0ed6 100644
--- a/chromeos/dbus/fake_image_burner_client.h
+++ b/chromeos/dbus/fake_image_burner_client.h
@@ -23,7 +23,7 @@
   void Init(dbus::Bus* bus) override;
   void BurnImage(const std::string& from_path,
                  const std::string& to_path,
-                 const ErrorCallback& error_callback) override;
+                 ErrorCallback error_callback) override;
   void SetEventHandlers(
       const BurnFinishedHandler& burn_finished_handler,
       const BurnProgressUpdateHandler& burn_progress_update_handler) override;
diff --git a/chromeos/dbus/fake_update_engine_client.cc b/chromeos/dbus/fake_update_engine_client.cc
index 2373c27..ba57e93 100644
--- a/chromeos/dbus/fake_update_engine_client.cc
+++ b/chromeos/dbus/fake_update_engine_client.cc
@@ -28,20 +28,18 @@
   return observers_.HasObserver(observer);
 }
 
-void FakeUpdateEngineClient::RequestUpdateCheck(
-    const UpdateCheckCallback& callback) {
+void FakeUpdateEngineClient::RequestUpdateCheck(UpdateCheckCallback callback) {
   request_update_check_call_count_++;
-  callback.Run(update_check_result_);
+  std::move(callback).Run(update_check_result_);
 }
 
 void FakeUpdateEngineClient::Rollback() {
   rollback_call_count_++;
 }
 
-void FakeUpdateEngineClient::CanRollbackCheck(
-    const RollbackCheckCallback& callback) {
+void FakeUpdateEngineClient::CanRollbackCheck(RollbackCheckCallback callback) {
   can_rollback_call_count_++;
-  callback.Run(can_rollback_stub_result_);
+  std::move(callback).Run(can_rollback_stub_result_);
 }
 
 void FakeUpdateEngineClient::RebootAfterUpdate() {
@@ -74,9 +72,9 @@
 }
 
 void FakeUpdateEngineClient::GetChannel(bool get_current_channel,
-                                        const GetChannelCallback& callback) {
+                                        GetChannelCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(callback, std::string()));
+      FROM_HERE, base::BindOnce(std::move(callback), std::string()));
 }
 
 void FakeUpdateEngineClient::GetEolInfo(GetEolInfoCallback callback) {
@@ -88,17 +86,17 @@
 
 void FakeUpdateEngineClient::SetUpdateOverCellularPermission(
     bool allowed,
-    const base::Closure& callback) {
+    base::OnceClosure callback) {
   update_over_cellular_permission_count_++;
-  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
+  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
 }
 
 void FakeUpdateEngineClient::SetUpdateOverCellularOneTimePermission(
     const std::string& target_version,
     int64_t target_size,
-    const UpdateOverCellularOneTimePermissionCallback& callback) {
+    UpdateOverCellularOneTimePermissionCallback callback) {
   update_over_cellular_one_time_permission_count_++;
-  callback.Run(true);
+  std::move(callback).Run(true);
 }
 
 void FakeUpdateEngineClient::set_default_status(
diff --git a/chromeos/dbus/fake_update_engine_client.h b/chromeos/dbus/fake_update_engine_client.h
index c7a8b325..90c7d614 100644
--- a/chromeos/dbus/fake_update_engine_client.h
+++ b/chromeos/dbus/fake_update_engine_client.h
@@ -28,22 +28,22 @@
   void AddObserver(Observer* observer) override;
   void RemoveObserver(Observer* observer) override;
   bool HasObserver(const Observer* observer) const override;
-  void RequestUpdateCheck(const UpdateCheckCallback& callback) override;
+  void RequestUpdateCheck(UpdateCheckCallback callback) override;
   void RebootAfterUpdate() override;
   void Rollback() override;
-  void CanRollbackCheck(const RollbackCheckCallback& callback) override;
+  void CanRollbackCheck(RollbackCheckCallback callback) override;
   update_engine::StatusResult GetLastStatus() override;
   void SetChannel(const std::string& target_channel,
                   bool is_powerwash_allowed) override;
   void GetChannel(bool get_current_channel,
-                  const GetChannelCallback& callback) override;
+                  GetChannelCallback callback) override;
   void GetEolInfo(GetEolInfoCallback callback) override;
   void SetUpdateOverCellularPermission(bool allowed,
-                                       const base::Closure& callback) override;
+                                       base::OnceClosure callback) override;
   void SetUpdateOverCellularOneTimePermission(
       const std::string& target_version,
       int64_t target_size,
-      const UpdateOverCellularOneTimePermissionCallback& callback) override;
+      UpdateOverCellularOneTimePermissionCallback callback) override;
   // Pushes update_engine::StatusResult in the queue to test changing status.
   // GetLastStatus() returns the status set by this method in FIFO order.
   // See set_default_status().
diff --git a/chromeos/dbus/image_burner_client.cc b/chromeos/dbus/image_burner_client.cc
index 47ca2ec..702ada7 100644
--- a/chromeos/dbus/image_burner_client.cc
+++ b/chromeos/dbus/image_burner_client.cc
@@ -29,16 +29,16 @@
   // ImageBurnerClient override.
   void BurnImage(const std::string& from_path,
                  const std::string& to_path,
-                 const ErrorCallback& error_callback) override {
+                 ErrorCallback error_callback) override {
     dbus::MethodCall method_call(imageburn::kImageBurnServiceInterface,
                                  imageburn::kBurnImage);
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(from_path);
     writer.AppendString(to_path);
-    proxy_->CallMethod(
-        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
-        base::BindOnce(&ImageBurnerClientImpl::OnBurnImage,
-                       weak_ptr_factory_.GetWeakPtr(), error_callback));
+    proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+                       base::BindOnce(&ImageBurnerClientImpl::OnBurnImage,
+                                      weak_ptr_factory_.GetWeakPtr(),
+                                      std::move(error_callback)));
   }
 
   // ImageBurnerClient override.
@@ -63,14 +63,14 @@
     proxy_->ConnectToSignal(
         imageburn::kImageBurnServiceInterface,
         imageburn::kSignalBurnFinishedName,
-        base::Bind(&ImageBurnerClientImpl::OnBurnFinished,
-                   weak_ptr_factory_.GetWeakPtr()),
+        base::BindRepeating(&ImageBurnerClientImpl::OnBurnFinished,
+                            weak_ptr_factory_.GetWeakPtr()),
         base::BindOnce(&ImageBurnerClientImpl::OnSignalConnected,
                        weak_ptr_factory_.GetWeakPtr()));
     proxy_->ConnectToSignal(
         imageburn::kImageBurnServiceInterface, imageburn::kSignalBurnUpdateName,
-        base::Bind(&ImageBurnerClientImpl::OnBurnProgressUpdate,
-                   weak_ptr_factory_.GetWeakPtr()),
+        base::BindRepeating(&ImageBurnerClientImpl::OnBurnProgressUpdate,
+                            weak_ptr_factory_.GetWeakPtr()),
         base::BindOnce(&ImageBurnerClientImpl::OnSignalConnected,
                        weak_ptr_factory_.GetWeakPtr()));
   }
@@ -79,7 +79,7 @@
   // Called when a response for BurnImage is received
   void OnBurnImage(ErrorCallback error_callback, dbus::Response* response) {
     if (!response) {
-      error_callback.Run();
+      std::move(error_callback).Run();
       return;
     }
   }
diff --git a/chromeos/dbus/image_burner_client.h b/chromeos/dbus/image_burner_client.h
index 8e6632a..eb77810 100644
--- a/chromeos/dbus/image_burner_client.h
+++ b/chromeos/dbus/image_burner_client.h
@@ -25,22 +25,24 @@
   ~ImageBurnerClient() override;
 
   // A callback to be called when DBus method call fails.
-  typedef base::Callback<void()> ErrorCallback;
+  using ErrorCallback = base::OnceCallback<void()>;
 
   // A callback to handle burn_finished signal.
-  typedef base::Callback<void(const std::string& target_path,
-                              bool success,
-                              const std::string& error)> BurnFinishedHandler;
+  using BurnFinishedHandler =
+      base::RepeatingCallback<void(const std::string& target_path,
+                                   bool success,
+                                   const std::string& error)>;
 
   // A callback to handle burn_progress_update signal.
-  typedef base::Callback<void(const std::string& target_path,
-                              int64_t num_bytes_burnt,
-                              int64_t total_size)> BurnProgressUpdateHandler;
+  using BurnProgressUpdateHandler =
+      base::RepeatingCallback<void(const std::string& target_path,
+                                   int64_t num_bytes_burnt,
+                                   int64_t total_size)>;
 
   // Burns the image |from_path| to the disk |to_path|.
   virtual void BurnImage(const std::string& from_path,
                          const std::string& to_path,
-                         const ErrorCallback& error_callback) = 0;
+                         ErrorCallback error_callback) = 0;
 
   // Sets callbacks as event handlers.
   // |burn_finished_handler| is called when burn_finished signal is received.
diff --git a/chromeos/dbus/update_engine_client.cc b/chromeos/dbus/update_engine_client.cc
index 4983af35..d4c07b2 100644
--- a/chromeos/dbus/update_engine_client.cc
+++ b/chromeos/dbus/update_engine_client.cc
@@ -82,14 +82,14 @@
     return observers_.HasObserver(observer);
   }
 
-  void RequestUpdateCheck(const UpdateCheckCallback& callback) override {
+  void RequestUpdateCheck(UpdateCheckCallback callback) override {
     if (!service_available_) {
       // TODO(alemate): we probably need to remember callbacks only.
       // When service becomes available, we can do a single request,
       // and trigger all callbacks with the same return value.
       pending_tasks_.push_back(
-          base::Bind(&UpdateEngineClientImpl::RequestUpdateCheck,
-                     weak_ptr_factory_.GetWeakPtr(), callback));
+          base::BindOnce(&UpdateEngineClientImpl::RequestUpdateCheck,
+                         weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
       return;
     }
     // TODO(crbug.com/982438): Use newer version of kAttemptUpdate instead once
@@ -106,7 +106,7 @@
     update_engine_proxy_->CallMethod(
         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::BindOnce(&UpdateEngineClientImpl::OnRequestUpdateCheck,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void RebootAfterUpdate() override {
@@ -135,7 +135,7 @@
                        weak_ptr_factory_.GetWeakPtr()));
   }
 
-  void CanRollbackCheck(const RollbackCheckCallback& callback) override {
+  void CanRollbackCheck(RollbackCheckCallback callback) override {
     dbus::MethodCall method_call(
         update_engine::kUpdateEngineInterface,
         update_engine::kCanRollback);
@@ -144,7 +144,7 @@
     update_engine_proxy_->CallMethod(
         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::BindOnce(&UpdateEngineClientImpl::OnCanRollbackCheck,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   update_engine::StatusResult GetLastStatus() override { return last_status_; }
@@ -173,7 +173,7 @@
   }
 
   void GetChannel(bool get_current_channel,
-                  const GetChannelCallback& callback) override {
+                  GetChannelCallback callback) override {
     dbus::MethodCall method_call(
         update_engine::kUpdateEngineInterface,
         update_engine::kGetChannel);
@@ -185,7 +185,7 @@
     update_engine_proxy_->CallMethod(
         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::BindOnce(&UpdateEngineClientImpl::OnGetChannel,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void GetEolInfo(GetEolInfoCallback callback) override {
@@ -200,7 +200,7 @@
   }
 
   void SetUpdateOverCellularPermission(bool allowed,
-                                       const base::Closure& callback) override {
+                                       base::OnceClosure callback) override {
     dbus::MethodCall method_call(
         update_engine::kUpdateEngineInterface,
         update_engine::kSetUpdateOverCellularPermission);
@@ -214,13 +214,13 @@
         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::BindOnce(
             &UpdateEngineClientImpl::OnSetUpdateOverCellularPermission,
-            weak_ptr_factory_.GetWeakPtr(), callback));
+            weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void SetUpdateOverCellularOneTimePermission(
       const std::string& update_version,
       int64_t update_size,
-      const UpdateOverCellularOneTimePermissionCallback& callback) override {
+      UpdateOverCellularOneTimePermissionCallback callback) override {
     // TODO(https://crbug.com/927439): Change 'kSetUpdateOverCellularTarget' to
     // 'kSetUpdateOverCellularOneTimePermission'
     dbus::MethodCall method_call(update_engine::kUpdateEngineInterface,
@@ -233,11 +233,11 @@
             << "to target version: \"" << update_version << "\" "
             << "target_size: " << update_size;
 
-    return update_engine_proxy_->CallMethod(
+    update_engine_proxy_->CallMethod(
         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::BindOnce(
             &UpdateEngineClientImpl::OnSetUpdateOverCellularOneTimePermission,
-            weak_ptr_factory_.GetWeakPtr(), callback));
+            weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
  protected:
@@ -248,8 +248,8 @@
     update_engine_proxy_->ConnectToSignal(
         update_engine::kUpdateEngineInterface,
         update_engine::kStatusUpdateAdvanced,
-        base::Bind(&UpdateEngineClientImpl::StatusUpdateReceived,
-                   weak_ptr_factory_.GetWeakPtr()),
+        base::BindRepeating(&UpdateEngineClientImpl::StatusUpdateReceived,
+                            weak_ptr_factory_.GetWeakPtr()),
         base::BindOnce(&UpdateEngineClientImpl::StatusUpdateConnected,
                        weak_ptr_factory_.GetWeakPtr()));
     update_engine_proxy_->WaitForServiceToBeAvailable(
@@ -261,10 +261,10 @@
   void OnServiceInitiallyAvailable(bool service_is_available) {
     if (service_is_available) {
       service_available_ = true;
-      std::vector<base::Closure> callbacks;
+      std::vector<base::OnceClosure> callbacks;
       callbacks.swap(pending_tasks_);
-      for (const auto& callback : callbacks) {
-        callback.Run();
+      for (auto& callback : callbacks) {
+        std::move(callback).Run();
       }
 
       // Get update engine status for the initial status. Update engine won't
@@ -292,14 +292,14 @@
   }
 
   // Called when a response for RequestUpdateCheck() is received.
-  void OnRequestUpdateCheck(const UpdateCheckCallback& callback,
+  void OnRequestUpdateCheck(UpdateCheckCallback callback,
                             dbus::Response* response) {
     if (!response) {
       LOG(ERROR) << "Failed to request update check";
-      callback.Run(UPDATE_RESULT_FAILED);
+      std::move(callback).Run(UPDATE_RESULT_FAILED);
       return;
     }
-    callback.Run(UPDATE_RESULT_SUCCESS);
+    std::move(callback).Run(UPDATE_RESULT_SUCCESS);
   }
 
   // Called when a response for RebootAfterUpdate() is received.
@@ -319,22 +319,22 @@
   }
 
   // Called when a response for CanRollbackCheck() is received.
-  void OnCanRollbackCheck(const RollbackCheckCallback& callback,
+  void OnCanRollbackCheck(RollbackCheckCallback callback,
                           dbus::Response* response) {
     if (!response) {
       LOG(ERROR) << "Failed to request rollback availability status";
-      callback.Run(false);
+      std::move(callback).Run(false);
       return;
     }
     dbus::MessageReader reader(response);
     bool can_rollback;
     if (!reader.PopBool(&can_rollback)) {
       LOG(ERROR) << "Incorrect response: " << response->ToString();
-      callback.Run(false);
+      std::move(callback).Run(false);
       return;
     }
     VLOG(1) << "Rollback availability status received: " << can_rollback;
-    callback.Run(can_rollback);
+    std::move(callback).Run(can_rollback);
   }
 
   // Called when a response for GetStatus is received.
@@ -383,22 +383,21 @@
   }
 
   // Called when a response for GetChannel() is received.
-  void OnGetChannel(const GetChannelCallback& callback,
-                    dbus::Response* response) {
+  void OnGetChannel(GetChannelCallback callback, dbus::Response* response) {
     if (!response) {
       LOG(ERROR) << "Failed to request getting channel";
-      callback.Run("");
+      std::move(callback).Run("");
       return;
     }
     dbus::MessageReader reader(response);
     std::string channel;
     if (!reader.PopString(&channel)) {
       LOG(ERROR) << "Incorrect response: " << response->ToString();
-      callback.Run("");
+      std::move(callback).Run("");
       return;
     }
     VLOG(1) << "The channel received: " << channel;
-    callback.Run(channel);
+    std::move(callback).Run(channel);
   }
 
   // Called when a response for GetStatusAdvanced() is
@@ -429,7 +428,7 @@
   }
 
   // Called when a response for SetUpdateOverCellularPermission() is received.
-  void OnSetUpdateOverCellularPermission(const base::Closure& callback,
+  void OnSetUpdateOverCellularPermission(base::OnceClosure callback,
                                          dbus::Response* response) {
     if (!response) {
       LOG(ERROR) << update_engine::kSetUpdateOverCellularPermission
@@ -438,13 +437,13 @@
 
     // Callback should run anyway, regardless of whether DBus call to enable
     // update over cellular succeeded or failed.
-    callback.Run();
+    std::move(callback).Run();
   }
 
   // Called when a response for SetUpdateOverCellularOneTimePermission() is
   // received.
   void OnSetUpdateOverCellularOneTimePermission(
-      const UpdateOverCellularOneTimePermissionCallback& callback,
+      UpdateOverCellularOneTimePermissionCallback callback,
       dbus::Response* response) {
     bool success = true;
     if (!response) {
@@ -459,7 +458,7 @@
       }
     }
 
-    callback.Run(success);
+    std::move(callback).Run(success);
   }
 
   // Called when a status update signal is received.
@@ -505,7 +504,7 @@
 
   // This is a list of postponed calls to update engine to be called
   // after it becomes available.
-  std::vector<base::Closure> pending_tasks_;
+  std::vector<base::OnceClosure> pending_tasks_;
 
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
@@ -537,12 +536,12 @@
     return observers_.HasObserver(observer);
   }
 
-  void RequestUpdateCheck(const UpdateCheckCallback& callback) override {
+  void RequestUpdateCheck(UpdateCheckCallback callback) override {
     if (last_status_.current_operation() != update_engine::Operation::IDLE) {
-      callback.Run(UPDATE_RESULT_FAILED);
+      std::move(callback).Run(UPDATE_RESULT_FAILED);
       return;
     }
-    callback.Run(UPDATE_RESULT_SUCCESS);
+    std::move(callback).Run(UPDATE_RESULT_SUCCESS);
     last_status_.set_current_operation(
         update_engine::Operation::CHECKING_FOR_UPDATE);
     last_status_.set_progress(0.0);
@@ -561,8 +560,8 @@
 
   void Rollback() override {}
 
-  void CanRollbackCheck(const RollbackCheckCallback& callback) override {
-    callback.Run(true);
+  void CanRollbackCheck(RollbackCheckCallback callback) override {
+    std::move(callback).Run(true);
   }
 
   update_engine::StatusResult GetLastStatus() override { return last_status_; }
@@ -575,13 +574,13 @@
     target_channel_ = target_channel;
   }
   void GetChannel(bool get_current_channel,
-                  const GetChannelCallback& callback) override {
+                  GetChannelCallback callback) override {
     VLOG(1) << "Requesting to get channel, get_current_channel="
             << get_current_channel;
     if (get_current_channel)
-      callback.Run(current_channel_);
+      std::move(callback).Run(current_channel_);
     else
-      callback.Run(target_channel_);
+      std::move(callback).Run(target_channel_);
   }
 
   void GetEolInfo(GetEolInfoCallback callback) override {
@@ -589,14 +588,14 @@
   }
 
   void SetUpdateOverCellularPermission(bool allowed,
-                                       const base::Closure& callback) override {
-    callback.Run();
+                                       base::OnceClosure callback) override {
+    std::move(callback).Run();
   }
 
   void SetUpdateOverCellularOneTimePermission(
       const std::string& update_version,
       int64_t update_size,
-      const UpdateOverCellularOneTimePermissionCallback& callback) override {}
+      UpdateOverCellularOneTimePermissionCallback callback) override {}
 
  private:
   void StateTransition() {
diff --git a/chromeos/dbus/update_engine_client.h b/chromeos/dbus/update_engine_client.h
index c9be483..36af7e0 100644
--- a/chromeos/dbus/update_engine_client.h
+++ b/chromeos/dbus/update_engine_client.h
@@ -65,10 +65,10 @@
 
   // Called once RequestUpdateCheck() is complete. Takes one parameter:
   // - UpdateCheckResult: the result of the update check.
-  using UpdateCheckCallback = base::Callback<void(UpdateCheckResult)>;
+  using UpdateCheckCallback = base::OnceCallback<void(UpdateCheckResult)>;
 
   // Requests an update check and calls |callback| when completed.
-  virtual void RequestUpdateCheck(const UpdateCheckCallback& callback) = 0;
+  virtual void RequestUpdateCheck(UpdateCheckCallback callback) = 0;
 
   // Reboots if update has been performed.
   virtual void RebootAfterUpdate() = 0;
@@ -78,16 +78,15 @@
 
   // Called once CanRollbackCheck() is complete. Takes one parameter:
   // - bool: the result of the rollback availability check.
-  using RollbackCheckCallback = base::Callback<void(bool can_rollback)>;
+  using RollbackCheckCallback = base::OnceCallback<void(bool can_rollback)>;
 
   // Checks if Rollback is available and calls |callback| when completed.
-  virtual void CanRollbackCheck(
-      const RollbackCheckCallback& callback) = 0;
+  virtual void CanRollbackCheck(RollbackCheckCallback callback) = 0;
 
   // Called once GetChannel() is complete. Takes one parameter;
   // - string: the channel name like "beta-channel".
   using GetChannelCallback =
-      base::Callback<void(const std::string& channel_name)>;
+      base::OnceCallback<void(const std::string& channel_name)>;
 
   // Returns the last status the object received from the update engine.
   //
@@ -114,7 +113,7 @@
   // device is supposed to be (in case of a pending channel
   // change). On error, calls |callback| with an empty string.
   virtual void GetChannel(bool get_current_channel,
-                          const GetChannelCallback& callback) = 0;
+                          GetChannelCallback callback) = 0;
 
   // Called once GetStatusAdvanced() is complete. Takes one parameter;
   // - EolInfo: Please look at EolInfo for param details, all params related to
@@ -127,15 +126,14 @@
 
   // Either allow or disallow receiving updates over cellular connections.
   // Synchronous (blocking) method.
-  virtual void SetUpdateOverCellularPermission(
-      bool allowed,
-      const base::Closure& callback) = 0;
+  virtual void SetUpdateOverCellularPermission(bool allowed,
+                                               base::OnceClosure callback) = 0;
 
   // Called once SetUpdateOverCellularOneTimePermission() is complete. Takes one
   // parameter;
   // - success: indicates whether the permission is set successfully.
   using UpdateOverCellularOneTimePermissionCallback =
-      base::Callback<void(bool success)>;
+      base::OnceCallback<void(bool success)>;
 
   // Sets a one time permission on a certain update in Update Engine which then
   // performs downloading of that update after RequestUpdateCheck() is invoked
@@ -151,7 +149,7 @@
   virtual void SetUpdateOverCellularOneTimePermission(
       const std::string& update_version,
       int64_t update_size,
-      const UpdateOverCellularOneTimePermissionCallback& callback) = 0;
+      UpdateOverCellularOneTimePermissionCallback callback) = 0;
 
   // Creates the instance.
   static UpdateEngineClient* Create(DBusClientImplementationType type);
diff --git a/components/autofill_assistant/browser/BUILD.gn b/components/autofill_assistant/browser/BUILD.gn
index f725608..77745d66 100644
--- a/components/autofill_assistant/browser/BUILD.gn
+++ b/components/autofill_assistant/browser/BUILD.gn
@@ -2,32 +2,19 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/android/rules.gni")
 import("//build/config/jumbo.gni")
 import("//third_party/protobuf/proto_library.gni")
 
+if (is_android) {
+  import("//build/config/android/rules.gni")
+}
+
 proto_library("proto") {
   sources = [
     "service.proto",
   ]
 }
 
-proto_java_library("proto_java") {
-  proto_path = "//components/autofill_assistant/browser/"
-  sources = [
-    "$proto_path/service.proto",
-  ]
-}
-
-java_cpp_enum("autofill_assistant_enums_java") {
-  sources = [
-    "metrics.h",
-    "overlay_state.h",
-    "user_data.h",
-    "viewport_mode.h",
-  ]
-}
-
 jumbo_static_library("browser") {
   sources = [
     "access_token_fetcher.h",
@@ -245,18 +232,36 @@
   ]
 }
 
-static_library("test_support") {
-  testonly = true
-  sources = [
-    "java_service.cc",
-    "java_service.h",
-  ]
+if (is_android) {
+  proto_java_library("proto_java") {
+    proto_path = "//components/autofill_assistant/browser/"
+    sources = [
+      "$proto_path/service.proto",
+    ]
+  }
 
-  deps = [
-    ":browser",
-    ":proto",
-    "//base",
-    "//chrome/android/features/autofill_assistant:test_support_jni_headers",
-    "//url:url",
-  ]
+  java_cpp_enum("autofill_assistant_enums_java") {
+    sources = [
+      "metrics.h",
+      "overlay_state.h",
+      "user_data.h",
+      "viewport_mode.h",
+    ]
+  }
+
+  static_library("test_support") {
+    testonly = true
+    sources = [
+      "java_service.cc",
+      "java_service.h",
+    ]
+
+    deps = [
+      ":browser",
+      ":proto",
+      "//base",
+      "//chrome/android/features/autofill_assistant:test_support_jni_headers",
+      "//url:url",
+    ]
+  }
 }
diff --git a/components/autofill_assistant_strings.grdp b/components/autofill_assistant_strings.grdp
index f18b0a7..e34248c 100644
--- a/components/autofill_assistant_strings.grdp
+++ b/components/autofill_assistant_strings.grdp
@@ -1,23 +1,23 @@
 <?xml version="1.0" encoding="utf-8"?>
 <grit-part>
+  <message name="IDS_AUTOFILL_ASSISTANT_PAYMENT_INFO_CONFIRM" desc="Text on the payment request primary button to confirm payment information [CHAR-LIMIT=32]">
+    Continue
+  </message>
+  <message name="IDS_AUTOFILL_ASSISTANT_DEFAULT_ERROR" desc="Text label that is shown when autofill assistant cannot help anymore, because something went wrong.">
+    Sorry, something went wrong.
+  </message>
+  <message name="IDS_AUTOFILL_ASSISTANT_LOADING" desc="Text label that is shown during the loading of the first page, right after being triggered.">
+    Opening <ph name="SITE_NAME">$1<ex>google.com</ex></ph>…
+  </message>
+  <message name="IDS_AUTOFILL_ASSISTANT_GIVE_UP"
+           desc="Text label that is shown when autofill assistant cannot help anymore, because of a user action."
+           internal_comment="TODO(wnwen): Remove duplication in chrome/android/features/autofill_assistant/strings/android_chrome_autofill_assistant_strings.grd">
+    Sorry I'm not able to help, please continue on your own.
+  </message>
   <if expr="is_android">
-    <message name="IDS_AUTOFILL_ASSISTANT_DEFAULT_ERROR" desc="Text label that is shown when autofill assistant cannot help anymore, because something went wrong.">
-      Sorry, something went wrong.
-    </message>
-    <message name="IDS_AUTOFILL_ASSISTANT_GIVE_UP"
-             desc="Text label that is shown when autofill assistant cannot help anymore, because of a user action."
-             internal_comment="TODO(wnwen): Remove duplication in chrome/android/features/autofill_assistant/strings/android_chrome_autofill_assistant_strings.grd">
-      Sorry I'm not able to help, please continue on your own.
-    </message>
     <message name="IDS_AUTOFILL_ASSISTANT_MAYBE_GIVE_UP" desc="Text label shown next to an UNDO button when user action indicate they want to continue on their own.">
       Continue manually?
     </message>
-    <message name="IDS_AUTOFILL_ASSISTANT_LOADING" desc="Text label that is shown during the loading of the first page, right after being triggered.">
-      Opening <ph name="SITE_NAME">$1<ex>google.com</ex></ph>…
-    </message>
-    <message name="IDS_AUTOFILL_ASSISTANT_PAYMENT_INFO_CONFIRM" desc="Text on the payment request primary button to confirm payment information [CHAR-LIMIT=32]">
-      Continue
-    </message>
     <message name="IDS_AUTOFILL_ASSISTANT_DETAILS_DIFFER" desc="Shown as Status Message when details differ.">
       The screening is different from what you selected. Continue?
     </message>
diff --git a/components/invalidation/impl/per_user_topic_registration_manager.cc b/components/invalidation/impl/per_user_topic_registration_manager.cc
index a2fa2741..a79a793 100644
--- a/components/invalidation/impl/per_user_topic_registration_manager.cc
+++ b/components/invalidation/impl/per_user_topic_registration_manager.cc
@@ -15,6 +15,7 @@
 
 #include "base/bind.h"
 #include "base/feature_list.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/rand_util.h"
 #include "base/stl_util.h"
 #include "base/strings/strcat.h"
@@ -150,6 +151,15 @@
   registry->RegisterDictionaryPref(kActiveRegistrationTokens);
 }
 
+// State of the instance ID token when registration is requested.
+// Used by UMA histogram, so entries shouldn't be reordered or removed.
+enum class PerUserTopicRegistrationManager::TokenStateOnRegistrationRequest {
+  kTokenWasEmpty = 0,
+  kUnchangedToken = 1,
+  kTokenChanged = 2,
+  kMaxValue = kTokenChanged,
+};
+
 struct PerUserTopicRegistrationManager::RegistrationEntry {
   RegistrationEntry(const Topic& topic,
                     SubscriptionFinishedCallback completion_callback,
@@ -264,7 +274,8 @@
     const std::string& instance_id_token) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   instance_id_token_ = instance_id_token;
-  DropAllSavedRegistrationsOnTokenChange();
+  UMA_HISTOGRAM_ENUMERATION("FCMInvalidations.TokenStateOnRegistrationRequest",
+                            DropAllSavedRegistrationsOnTokenChange());
 
   for (const auto& topic : topics) {
     // If the topic isn't registered yet, schedule the registration.
@@ -491,18 +502,20 @@
                           base::Unretained(this)));
 }
 
-void PerUserTopicRegistrationManager::DropAllSavedRegistrationsOnTokenChange() {
+PerUserTopicRegistrationManager::TokenStateOnRegistrationRequest
+PerUserTopicRegistrationManager::DropAllSavedRegistrationsOnTokenChange() {
   {
     DictionaryPrefUpdate token_update(local_state_, kActiveRegistrationTokens);
     std::string current_token;
     token_update->GetString(project_id_, &current_token);
     if (current_token.empty()) {
       token_update->SetString(project_id_, instance_id_token_);
-      return;
+      return TokenStateOnRegistrationRequest::kTokenWasEmpty;
     }
     if (current_token == instance_id_token_) {
-      return;
+      return TokenStateOnRegistrationRequest::kUnchangedToken;
     }
+
     token_update->SetString(project_id_, instance_id_token_);
   }
 
@@ -510,6 +523,7 @@
   *update = base::Value(base::Value::Type::DICTIONARY);
   topic_to_private_topic_.clear();
   private_topic_to_topic_.clear();
+  return TokenStateOnRegistrationRequest::kTokenChanged;
   // TODO(melandory): Figure out if the unsubscribe request should be
   // sent with the old token.
 }
diff --git a/components/invalidation/impl/per_user_topic_registration_manager.h b/components/invalidation/impl/per_user_topic_registration_manager.h
index 8c0c485..1233cc246 100644
--- a/components/invalidation/impl/per_user_topic_registration_manager.h
+++ b/components/invalidation/impl/per_user_topic_registration_manager.h
@@ -59,6 +59,8 @@
 
   virtual ~PerUserTopicRegistrationManager();
 
+  enum class TokenStateOnRegistrationRequest;
+
   // Just calls std::make_unique. For ease of base::Bind'ing
   static std::unique_ptr<PerUserTopicRegistrationManager> Create(
       invalidation::IdentityProvider* identity_provider,
@@ -122,7 +124,7 @@
   void OnAccessTokenRequestSucceeded(std::string access_token);
   void OnAccessTokenRequestFailed(GoogleServiceAuthError error);
 
-  void DropAllSavedRegistrationsOnTokenChange();
+  TokenStateOnRegistrationRequest DropAllSavedRegistrationsOnTokenChange();
   void NotifySubscriptionChannelStateChange(
       SubscriptionChannelState invalidator_state);
 
diff --git a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
index 364df6f7..6ef356f 100644
--- a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
+++ b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
@@ -99,7 +99,6 @@
           WebFeature::kOpenerNavigationDownloadCrossOrigin,
           WebFeature::kLinkRelPrerender,
           WebFeature::kAdClickNavigation,
-          WebFeature::kDownloadInSandboxWithoutUserGesture,
           WebFeature::kV8HTMLVideoElement_RequestPictureInPicture_Method,
           WebFeature::kMediaCapabilitiesDecodingInfoWithKeySystemConfig,
           WebFeature::kTextFragmentAnchor,
diff --git a/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.cc b/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.cc
index 65da30a9..9da7543 100644
--- a/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.cc
+++ b/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.cc
@@ -57,15 +57,14 @@
 void PossiblyWarnFeatureDeprecation(content::RenderFrameHost* rfh,
                                     WebFeature feature) {
   switch (feature) {
-    case WebFeature::kDownloadInSandboxWithoutUserGesture:
+    case WebFeature::kDownloadInSandbox:
       rfh->AddMessageToConsole(
           blink::mojom::ConsoleMessageLevel::kWarning,
-          "[Deprecation] Download in sandbox without user activation is "
-          "deprecated and will be removed in M76, around July 2019. You may "
-          "consider adding "
-          "'allow-downloads-without-user-activation' to the sandbox attribute "
-          "list. See https://www.chromestatus.com/feature/5706745674465280 for "
-          "more details.");
+          "[Deprecation] Download in sandbox is deprecated and will be removed "
+          "in M81. You may consider adding 'allow-downloads' to the sandbox "
+          "attribute list. See "
+          "https://www.chromestatus.com/feature/5706745674465280 for more "
+          "details.");
       return;
     case WebFeature::kDownloadInAdFrameWithoutUserGesture:
       rfh->AddMessageToConsole(
diff --git a/components/services/font/font_service_app.cc b/components/services/font/font_service_app.cc
index fb23694..54a7f8d 100644
--- a/components/services/font/font_service_app.cc
+++ b/components/services/font/font_service_app.cc
@@ -152,16 +152,20 @@
     FallbackFontForCharacterCallback callback) {
   TRACE_EVENT0("fonts", "FontServiceApp::FallbackFontForCharacter");
 
-  auto fallback_font = gfx::GetFallbackFontForChar(character, locale);
-  size_t index = FindOrAddPath(fallback_font.filepath);
+  gfx::FallbackFontData fallback_font;
+  if (gfx::GetFallbackFontForChar(character, locale, &fallback_font)) {
+    size_t index = FindOrAddPath(fallback_font.filepath);
 
-  mojom::FontIdentityPtr identity(mojom::FontIdentity::New());
-  identity->id = static_cast<uint32_t>(index);
-  identity->ttc_index = fallback_font.ttc_index;
-  identity->filepath = fallback_font.filepath;
+    mojom::FontIdentityPtr identity(mojom::FontIdentity::New());
+    identity->id = static_cast<uint32_t>(index);
+    identity->ttc_index = fallback_font.ttc_index;
+    identity->filepath = fallback_font.filepath;
 
-  std::move(callback).Run(std::move(identity), fallback_font.name,
-                          fallback_font.is_bold, fallback_font.is_italic);
+    std::move(callback).Run(std::move(identity), fallback_font.name,
+                            fallback_font.is_bold, fallback_font.is_italic);
+  } else {
+    std::move(callback).Run(nullptr, "", false, false);
+  }
 }
 
 void FontServiceApp::FontRenderStyleForStrike(
diff --git a/components/signin/core/browser/about_signin_internals.cc b/components/signin/core/browser/about_signin_internals.cc
index 12982cbf..e9dc7b8 100644
--- a/components/signin/core/browser/about_signin_internals.cc
+++ b/components/signin/core/browser/about_signin_internals.cc
@@ -194,8 +194,6 @@
       return "None";
     case signin::AccountConsistencyMethod::kMirror:
       return "Mirror";
-    case signin::AccountConsistencyMethod::kDiceMigration:
-      return "DICE migration";
     case signin::AccountConsistencyMethod::kDice:
       return "DICE";
   }
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc
index d1792d3..ff5b0e6 100644
--- a/components/signin/core/browser/account_reconcilor.cc
+++ b/components/signin/core/browser/account_reconcilor.cc
@@ -736,9 +736,6 @@
   DCHECK(delegate_->IsUnknownInvalidAccountInCookieAllowed())
       << "Only supported in UPDATE mode";
 
-  delegate_->MaybeLogInconsistencyReason(primary_account, chrome_accounts,
-                                         gaia_accounts, first_execution_);
-
   size_t number_gaia_accounts = gaia_accounts.size();
   // If there are any accounts in the gaia cookie but not in chrome, then
   // those accounts need to be removed from the cookie.  This means we need
diff --git a/components/signin/core/browser/account_reconcilor_delegate.cc b/components/signin/core/browser/account_reconcilor_delegate.cc
index 3424d04..1c672b5 100644
--- a/components/signin/core/browser/account_reconcilor_delegate.cc
+++ b/components/signin/core/browser/account_reconcilor_delegate.cc
@@ -22,12 +22,6 @@
   return false;
 }
 
-void AccountReconcilorDelegate::MaybeLogInconsistencyReason(
-    const CoreAccountId& primary_account,
-    const std::vector<CoreAccountId>& chrome_accounts,
-    const std::vector<gaia::ListedAccount>& gaia_accounts,
-    bool first_execution) const {}
-
 gaia::GaiaSource AccountReconcilorDelegate::GetGaiaApiSource() const {
   NOTREACHED() << "Reconcile is not enabled, no Gaia API calls should be made.";
   return gaia::GaiaSource::kChrome;
diff --git a/components/signin/core/browser/account_reconcilor_delegate.h b/components/signin/core/browser/account_reconcilor_delegate.h
index b5ef3668..d666b2e 100644
--- a/components/signin/core/browser/account_reconcilor_delegate.h
+++ b/components/signin/core/browser/account_reconcilor_delegate.h
@@ -57,13 +57,6 @@
   // changes to the accounts are made. Defaults to false.
   virtual bool IsAccountConsistencyEnforced() const;
 
-  // Computes inconsistency reason and uploads it to UMA.
-  virtual void MaybeLogInconsistencyReason(
-      const CoreAccountId& primary_account,
-      const std::vector<CoreAccountId>& chrome_accounts,
-      const std::vector<gaia::ListedAccount>& gaia_accounts,
-      bool first_execution) const;
-
   // Returns the value to set in the "source" parameter for Gaia API calls.
   virtual gaia::GaiaSource GetGaiaApiSource() const;
 
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc
index 73084b00..dd533b1c 100644
--- a/components/signin/core/browser/account_reconcilor_unittest.cc
+++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -152,11 +152,10 @@
             identity_manager);
       case signin::AccountConsistencyMethod::kDisabled:
         return std::make_unique<signin::AccountReconcilorDelegate>();
-      case signin::AccountConsistencyMethod::kDiceMigration:
       case signin::AccountConsistencyMethod::kDice:
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
         return std::make_unique<signin::DiceAccountReconcilorDelegate>(
-            signin_client, account_consistency, dice_migration_completed);
+            signin_client, dice_migration_completed);
 #else
         NOTREACHED();
         return nullptr;
@@ -1055,47 +1054,6 @@
                                        0);
 }
 
-// Checks one row of the kDiceParams table above.
-TEST_P(AccountReconcilorTestTable, InconsistencyReasonLogging) {
-  // Enable Dice Migration.
-  SetAccountConsistency(signin::AccountConsistencyMethod::kDiceMigration);
-  // Setup cookies.
-  std::vector<Cookie> cookies = ParseCookieString(cookies_);
-  ConfigureCookieManagerService(cookies);
-  // Setup tokens. This triggers listing cookies so we need to setup cookies
-  // before that.
-  SetupTokens(tokens_);
-  // Call list accounts now so that the next call completes synchronously.
-  identity_test_env()->identity_manager()->GetAccountsInCookieJar();
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(testing::_))
-      .WillRepeatedly(testing::Return());
-  EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
-      .WillRepeatedly(testing::Return());
-  // Reconcile.
-  AccountReconcilor* reconcilor = GetMockReconcilor();
-  bool first_execution =
-      GetParam().is_first_reconcile == IsFirstReconcile::kFirst;
-  reconcilor->first_execution_ = first_execution;
-  reconcilor->StartReconcile();
-  reconcilor->add_to_cookie_.clear();
-  reconcilor->CalculateIfReconcileIsDone();
-  ASSERT_FALSE(reconcilor->is_reconcile_started_);
-  std::string histogram_name_suffix =
-      first_execution ? "FirstExecution" : "NotFirstExecution";
-
-  histogram_tester()->ExpectUniqueSample(
-      "Signin.DiceMigrationNotReady.Reason." + histogram_name_suffix,
-      GetParam().inconsistency_reason, 1);
-
-  histogram_tester()->ExpectTotalCount("ForceDiceMigration.RevokeTokenAction",
-                                       0);
-
-  ConfigureCookieManagerService({});
-  base::RunLoop().RunUntilIdle();
-}
-
 INSTANTIATE_TEST_SUITE_P(
     DiceTable,
     AccountReconcilorTestTable,
@@ -2760,7 +2718,6 @@
         break;
       }
       case signin::AccountConsistencyMethod::kDisabled:
-      case signin::AccountConsistencyMethod::kDiceMigration:
         NOTREACHED();
         break;
     }
@@ -2826,7 +2783,6 @@
         break;
       }
       case signin::AccountConsistencyMethod::kDisabled:
-      case signin::AccountConsistencyMethod::kDiceMigration:
         NOTREACHED();
         break;
     }
diff --git a/components/signin/core/browser/dice_account_reconcilor_delegate.cc b/components/signin/core/browser/dice_account_reconcilor_delegate.cc
index ec86dca..8c2749be 100644
--- a/components/signin/core/browser/dice_account_reconcilor_delegate.cc
+++ b/components/signin/core/browser/dice_account_reconcilor_delegate.cc
@@ -20,16 +20,10 @@
 
 DiceAccountReconcilorDelegate::DiceAccountReconcilorDelegate(
     SigninClient* signin_client,
-    AccountConsistencyMethod account_consistency,
     bool migration_completed)
     : signin_client_(signin_client),
-      account_consistency_(account_consistency),
       migration_completed_(migration_completed) {
   DCHECK(signin_client_);
-  DCHECK(DiceMethodGreaterOrEqual(account_consistency_,
-                                  AccountConsistencyMethod::kDiceMigration));
-  DCHECK(account_consistency == AccountConsistencyMethod::kDice ||
-         !migration_completed);
 }
 
 bool DiceAccountReconcilorDelegate::IsReconcileEnabled() const {
@@ -41,7 +35,7 @@
 }
 
 bool DiceAccountReconcilorDelegate::IsAccountConsistencyEnforced() const {
-  return account_consistency_ == AccountConsistencyMethod::kDice;
+  return true;
 }
 
 DiceAccountReconcilorDelegate::InconsistencyReason
@@ -101,28 +95,6 @@
   return InconsistencyReason::kNone;
 }
 
-void DiceAccountReconcilorDelegate::MaybeLogInconsistencyReason(
-    const CoreAccountId& primary_account,
-    const std::vector<CoreAccountId>& chrome_accounts,
-    const std::vector<gaia::ListedAccount>& gaia_accounts,
-    bool first_execution) const {
-  if (account_consistency_ != AccountConsistencyMethod::kDiceMigration)
-    return;
-
-  InconsistencyReason inconsistency_reason = GetInconsistencyReason(
-      primary_account, chrome_accounts, gaia_accounts, first_execution);
-
-  if (first_execution) {
-    UMA_HISTOGRAM_ENUMERATION(
-        "Signin.DiceMigrationNotReady.Reason.FirstExecution",
-        inconsistency_reason);
-  } else {
-    UMA_HISTOGRAM_ENUMERATION(
-        "Signin.DiceMigrationNotReady.Reason.NotFirstExecution",
-        inconsistency_reason);
-  }
-}
-
 gaia::GaiaSource DiceAccountReconcilorDelegate::GetGaiaApiSource() const {
   return gaia::GaiaSource::kAccountReconcilorDice;
 }
@@ -240,21 +212,11 @@
 AccountReconcilorDelegate::RevokeTokenOption
 DiceAccountReconcilorDelegate::ShouldRevokeSecondaryTokensBeforeReconcile(
     const std::vector<gaia::ListedAccount>& gaia_accounts) {
-  // During the Dice migration step, before Dice is actually enabled, chrome
-  // tokens must be cleared when the cookies are cleared.
-  if ((account_consistency_ == AccountConsistencyMethod::kDiceMigration) &&
-      gaia_accounts.empty()) {
-    return RevokeTokenOption::kRevoke;
-  }
-
-  return account_consistency_ == AccountConsistencyMethod::kDice
-             ? RevokeTokenOption::kRevokeIfInError
-             : RevokeTokenOption::kDoNotRevoke;
+  return RevokeTokenOption::kRevokeIfInError;
 }
 
 bool DiceAccountReconcilorDelegate::ShouldRevokeTokensNotInCookies() const {
-  return account_consistency_ == AccountConsistencyMethod::kDice &&
-         !migration_completed_;
+  return !migration_completed_;
 }
 
 void DiceAccountReconcilorDelegate::OnRevokeTokensNotInCookiesCompleted(
@@ -266,7 +228,7 @@
 }
 
 bool DiceAccountReconcilorDelegate::ShouldRevokeTokensOnCookieDeleted() {
-  return account_consistency_ == AccountConsistencyMethod::kDice;
+  return true;
 }
 
 void DiceAccountReconcilorDelegate::OnReconcileFinished(
diff --git a/components/signin/core/browser/dice_account_reconcilor_delegate.h b/components/signin/core/browser/dice_account_reconcilor_delegate.h
index 587bbdf..fa98b9f3 100644
--- a/components/signin/core/browser/dice_account_reconcilor_delegate.h
+++ b/components/signin/core/browser/dice_account_reconcilor_delegate.h
@@ -22,7 +22,6 @@
 class DiceAccountReconcilorDelegate : public AccountReconcilorDelegate {
  public:
   DiceAccountReconcilorDelegate(SigninClient* signin_client,
-                                AccountConsistencyMethod account_consistency,
                                 bool migration_completed);
   ~DiceAccountReconcilorDelegate() override {}
 
@@ -30,11 +29,6 @@
   bool IsReconcileEnabled() const override;
   bool IsMultiloginEndpointEnabled() const override;
   bool IsAccountConsistencyEnforced() const override;
-  void MaybeLogInconsistencyReason(
-      const CoreAccountId& primary_account,
-      const std::vector<CoreAccountId>& chrome_accounts,
-      const std::vector<gaia::ListedAccount>& gaia_accounts,
-      bool first_execution) const override;
   gaia::GaiaSource GetGaiaApiSource() const override;
   CoreAccountId GetFirstGaiaAccountForReconcile(
       const std::vector<CoreAccountId>& chrome_accounts,
@@ -90,7 +84,6 @@
       bool primary_has_error) const override;
 
   SigninClient* signin_client_;
-  AccountConsistencyMethod account_consistency_;
   bool migration_completed_;
 
   // Last known "first account". Used when cookies are lost as a best guess.
diff --git a/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc b/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
index 1de985d5..8aeea7d 100644
--- a/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
+++ b/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
@@ -21,30 +21,11 @@
   TestSigninClient client(&pref_service);
   gaia::ListedAccount gaia_account;
   gaia_account.id = CoreAccountId("other");
-  {
-    // Dice is enabled, revoke only tokens in error state.
-    DiceAccountReconcilorDelegate delegate(
-        &client, AccountConsistencyMethod::kDice, /*migration_completed=*/true);
-    EXPECT_EQ(
-        signin::AccountReconcilorDelegate::RevokeTokenOption::kRevokeIfInError,
-        delegate.ShouldRevokeSecondaryTokensBeforeReconcile(
-            std::vector<gaia::ListedAccount>()));
-  }
-  {
-    DiceAccountReconcilorDelegate delegate(
-        &client, AccountConsistencyMethod::kDiceMigration,
-        /*migration_completed=*/false);
-    // Gaia accounts are not empty, don't revoke.
-    gaia::ListedAccount gaia_account;
-    gaia_account.id = CoreAccountId("other");
-    EXPECT_EQ(AccountReconcilorDelegate::RevokeTokenOption::kDoNotRevoke,
-              delegate.ShouldRevokeSecondaryTokensBeforeReconcile(
-                  std::vector<gaia::ListedAccount>{gaia_account}));
-    // Revoke.
-    EXPECT_EQ(AccountReconcilorDelegate::RevokeTokenOption::kRevoke,
-              delegate.ShouldRevokeSecondaryTokensBeforeReconcile(
-                  std::vector<gaia::ListedAccount>()));
-  }
+  DiceAccountReconcilorDelegate delegate(&client, /*migration_completed=*/true);
+  EXPECT_EQ(
+      signin::AccountReconcilorDelegate::RevokeTokenOption::kRevokeIfInError,
+      delegate.ShouldRevokeSecondaryTokensBeforeReconcile(
+          std::vector<gaia::ListedAccount>()));
 }
 
 TEST(DiceAccountReconcilorDelegateTest, ShouldRevokeTokensBasedOnCookies) {
@@ -52,8 +33,8 @@
   TestSigninClient client(&pref_service);
   {
     // Dice is enabled, revoke tokens when Gaia cookie is deleted.
-    DiceAccountReconcilorDelegate delegate(
-        &client, AccountConsistencyMethod::kDice, /*migration_completed=*/true);
+    DiceAccountReconcilorDelegate delegate(&client,
+                                           /*migration_completed=*/true);
     EXPECT_EQ(true, delegate.ShouldRevokeTokensOnCookieDeleted());
     EXPECT_EQ(false, delegate.ShouldRevokeTokensNotInCookies());
   }
@@ -61,19 +42,10 @@
     // Dice is enabled, migration not completed, revoke tokens when
     // Gaia cookie is deleted.
     DiceAccountReconcilorDelegate delegate(&client,
-                                           AccountConsistencyMethod::kDice,
                                            /*migration_completed=*/false);
     EXPECT_EQ(true, delegate.ShouldRevokeTokensOnCookieDeleted());
     EXPECT_EQ(true, delegate.ShouldRevokeTokensNotInCookies());
   }
-  {
-    // Dice is not enabled, do not revoke tokens when Gaia cookie is deleted.
-    DiceAccountReconcilorDelegate delegate(
-        &client, AccountConsistencyMethod::kDiceMigration,
-        /*migration_completed=*/false);
-    EXPECT_EQ(false, delegate.ShouldRevokeTokensOnCookieDeleted());
-    EXPECT_EQ(false, delegate.ShouldRevokeTokensNotInCookies());
-  }
 }
 
 }  // namespace signin
diff --git a/components/signin/core/browser/dice_header_helper.cc b/components/signin/core/browser/dice_header_helper.cc
index 4d1bc24..bb562dd 100644
--- a/components/signin/core/browser/dice_header_helper.cc
+++ b/components/signin/core/browser/dice_header_helper.cc
@@ -20,8 +20,6 @@
 
 // Request parameters.
 const char kRequestSigninAll[] = "all_accounts";
-const char kRequestSignoutNoConfirmation[] = "no_confirmation";
-const char kRequestSignoutShowConfirmation[] = "show_confirmation";
 
 // Signin response parameters.
 const char kSigninActionAttrName[] = "action";
@@ -209,12 +207,8 @@
   std::string signin_mode = kRequestSigninAll;
   parts.push_back("signin_mode=" + signin_mode);
 
-  // Show the signout confirmation only when Dice is fully enabled.
-  const char* signout_mode_value =
-      (account_consistency_ == AccountConsistencyMethod::kDice)
-          ? kRequestSignoutShowConfirmation
-          : kRequestSignoutNoConfirmation;
-  parts.push_back(base::StringPrintf("signout_mode=%s", signout_mode_value));
+  // Show the signout confirmation when Dice is enabled.
+  parts.push_back("signout_mode=show_confirmation");
 
   return base::JoinString(parts, ",");
 }
diff --git a/components/signin/core/browser/signin_header_helper_unittest.cc b/components/signin/core/browser/signin_header_helper_unittest.cc
index 91eb1bf2..1dcb4c5352 100644
--- a/components/signin/core/browser/signin_header_helper_unittest.cc
+++ b/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -319,7 +319,7 @@
 }
 
 TEST_F(SigninHeaderHelperTest, TestDiceEmptyDeviceID) {
-  account_consistency_ = AccountConsistencyMethod::kDiceMigration;
+  account_consistency_ = AccountConsistencyMethod::kDice;
   std::string client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
   ASSERT_FALSE(client_id.empty());
 
@@ -330,29 +330,16 @@
       "mode=0,enable_account_consistency=false,"
       "consistency_enabled_by_default=false",
       base::StringPrintf("version=%s,client_id=%s,signin_mode=all_accounts,"
-                         "signout_mode=no_confirmation",
+                         "signout_mode=show_confirmation",
                          kDiceProtocolVersion, client_id.c_str()));
 }
 
-// Tests that the signout confirmation is requested iff the Dice migration is
-// complete.
-TEST_F(SigninHeaderHelperTest, TestDiceMigration) {
-  account_consistency_ = AccountConsistencyMethod::kDiceMigration;
+// Tests that the signout confirmation is requested.
+TEST_F(SigninHeaderHelperTest, TestSignoutConfirmation) {
+  account_consistency_ = AccountConsistencyMethod::kDice;
   std::string client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
   ASSERT_FALSE(client_id.empty());
 
-  // No signout confirmation by default.
-  CheckDiceHeaderRequest(
-      GURL("https://accounts.google.com"), "0123456789",
-      "mode=0,enable_account_consistency=false,"
-      "consistency_enabled_by_default=false",
-      base::StringPrintf(
-          "version=%s,client_id=%s,device_id=DeviceID,signin_mode=all_accounts,"
-          "signout_mode=no_confirmation",
-          kDiceProtocolVersion, client_id.c_str()));
-
-  // Signout confirmation after the migration is complete.
-  account_consistency_ = AccountConsistencyMethod::kDice;
   CheckDiceHeaderRequest(
       GURL("https://accounts.google.com"), "0123456789",
       "mode=0,enable_account_consistency=false,"
diff --git a/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc b/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc
index 359ad73..f8373a1 100644
--- a/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc
+++ b/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc
@@ -117,10 +117,7 @@
 // TODO(droger): Remove this code once Dice is fully enabled.
 bool ShouldMigrateToDice(signin::AccountConsistencyMethod account_consistency,
                          PrefService* prefs) {
-  return (account_consistency != signin::AccountConsistencyMethod::kMirror) &&
-         signin::DiceMethodGreaterOrEqual(
-             account_consistency,
-             signin::AccountConsistencyMethod::kDiceMigration) &&
+  return account_consistency == signin::AccountConsistencyMethod::kDice &&
          !prefs->GetBoolean(prefs::kTokenServiceDiceCompatible);
 }
 
@@ -588,12 +585,9 @@
 
         // Only load secondary accounts when account consistency is enabled.
         bool load_account =
-            (account_id == loading_primary_account_id_) ||
-            (account_consistency_ ==
-             signin::AccountConsistencyMethod::kMirror) ||
-            signin::DiceMethodGreaterOrEqual(
-                account_consistency_,
-                signin::AccountConsistencyMethod::kDiceMigration);
+            account_id == loading_primary_account_id_ ||
+            account_consistency_ == signin::AccountConsistencyMethod::kMirror ||
+            account_consistency_ == signin::AccountConsistencyMethod::kDice;
         LoadTokenFromDBStatus load_token_status =
             load_account
                 ? LoadTokenFromDBStatus::TOKEN_LOADED
diff --git a/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc b/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc
index 1115d73..1ebf8a3 100644
--- a/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc
+++ b/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc
@@ -526,187 +526,6 @@
   ResetObserverCounts();
 }
 
-// Tests that Dice migration does not happen if an account is invalid. In
-// particular, no hosted domain tokens are revoked.
-TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
-       DiceMigrationWithMissingHostedDomain) {
-  ASSERT_FALSE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
-  InitializeOAuth2ServiceDelegate(
-      signin::AccountConsistencyMethod::kDiceMigration);
-  oauth2_service_delegate_->RevokeAllCredentials();
-
-  // Add incomplete accounts info to the account tracker.
-  AccountInfo account_info_consummer;
-  account_info_consummer.account_id = CoreAccountId("consummer");
-  account_info_consummer.gaia = "consummer";
-  // gmail.com is known as a non-enterprise domain.
-  account_info_consummer.email = "consummer@gmail.com";
-  account_tracker_service_.SeedAccountInfo(account_info_consummer);
-
-  AccountInfo account_info_enterprise;
-  account_info_enterprise.account_id = CoreAccountId("enterprise");
-  account_info_enterprise.gaia = "enterprise";
-  account_info_enterprise.email = "enterprise@email.com";
-  account_tracker_service_.SeedAccountInfo(account_info_enterprise);
-
-  ResetObserverCounts();
-  AddAuthTokenManually("AccountId-" + account_info_consummer.account_id.id,
-                       "refresh_token");
-  AddAuthTokenManually("AccountId-" + account_info_enterprise.account_id.id,
-                       "refresh_token");
-  oauth2_service_delegate_->LoadCredentials(account_info_consummer.account_id);
-  base::RunLoop().RunUntilIdle();
-
-  // Only the enterprise token is revoked.
-  EXPECT_EQ(1, tokens_loaded_count_);
-  EXPECT_EQ(1, token_available_count_);
-  EXPECT_EQ(1, token_revoked_count_);
-  EXPECT_EQ(1, end_batch_changes_);
-  EXPECT_EQ(1, auth_error_changed_count_);
-  EXPECT_FALSE(oauth2_service_delegate_->RefreshTokenIsAvailable(
-      account_info_enterprise.account_id));
-  EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(
-      account_info_consummer.account_id));
-  EXPECT_EQ("refresh_token",
-            oauth2_service_delegate_
-                ->refresh_tokens_[account_info_consummer.account_id]
-                .refresh_token);
-  EXPECT_EQ(
-      signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
-      oauth2_service_delegate_->load_credentials_state());
-
-  EXPECT_TRUE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
-}
-
-// Tests that the migration happened after loading consummer accounts.
-TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
-       DiceMigrationConsummerAccounts) {
-  ASSERT_EQ(AccountTrackerService::MIGRATION_DONE,
-            account_tracker_service_.GetMigrationState());
-  ASSERT_FALSE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
-  InitializeOAuth2ServiceDelegate(
-      signin::AccountConsistencyMethod::kDiceMigration);
-  oauth2_service_delegate_->RevokeAllCredentials();
-
-  // Add account info to the account tracker.
-  AccountInfo primary_account = CreateTestAccountInfo(
-      "primary_account", false /* is_hosted_domain*/, true /* is_valid*/);
-  AccountInfo secondary_account = CreateTestAccountInfo(
-      "secondary_account", false /* is_hosted_domain*/, true /* is_valid*/);
-  account_tracker_service_.SeedAccountInfo(primary_account);
-  account_tracker_service_.SeedAccountInfo(secondary_account);
-
-  ResetObserverCounts();
-  AddAuthTokenManually("AccountId-" + primary_account.account_id.id,
-                       "refresh_token");
-  AddAuthTokenManually("AccountId-" + secondary_account.account_id.id,
-                       "refresh_token");
-  oauth2_service_delegate_->LoadCredentials(primary_account.account_id);
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(1, tokens_loaded_count_);
-  EXPECT_EQ(2, token_available_count_);
-  EXPECT_EQ(0, token_revoked_count_);
-  EXPECT_EQ(1, end_batch_changes_);
-  EXPECT_EQ(2, auth_error_changed_count_);
-  EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(
-      primary_account.account_id));
-  EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(
-      secondary_account.account_id));
-  EXPECT_EQ(
-      signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
-      oauth2_service_delegate_->load_credentials_state());
-
-  EXPECT_TRUE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
-}
-
-// Tests that the migration revokes the hosted domain tokens.
-TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
-       DiceMigrationHostedDomainAccounts) {
-  ASSERT_EQ(AccountTrackerService::MIGRATION_DONE,
-            account_tracker_service_.GetMigrationState());
-  ASSERT_FALSE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
-  InitializeOAuth2ServiceDelegate(
-      signin::AccountConsistencyMethod::kDiceMigration);
-  oauth2_service_delegate_->RevokeAllCredentials();
-
-  // Add account info to the account tracker.
-  AccountInfo primary_account = CreateTestAccountInfo(
-      "primary_account", false /* is_hosted_domain*/, true /* is_valid*/);
-  AccountInfo secondary_account = CreateTestAccountInfo(
-      "secondary_account", true /* is_hosted_domain*/, true /* is_valid*/);
-  account_tracker_service_.SeedAccountInfo(primary_account);
-  account_tracker_service_.SeedAccountInfo(secondary_account);
-
-  ResetObserverCounts();
-  AddAuthTokenManually("AccountId-" + primary_account.account_id.id,
-                       "refresh_token");
-  AddAuthTokenManually("AccountId-" + secondary_account.account_id.id,
-                       "refresh_token");
-  oauth2_service_delegate_->LoadCredentials(primary_account.account_id);
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(1, tokens_loaded_count_);
-  EXPECT_EQ(1, token_available_count_);
-  EXPECT_EQ(1, token_revoked_count_);
-  EXPECT_EQ(1, end_batch_changes_);
-  EXPECT_EQ(1, auth_error_changed_count_);
-  EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(
-      primary_account.account_id));
-  EXPECT_EQ(
-      signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
-      oauth2_service_delegate_->load_credentials_state());
-
-  EXPECT_TRUE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
-}
-
-// Tests that the migration can revoke the primary token too.
-TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
-       DiceMigrationHostedDomainPrimaryAccount) {
-  ASSERT_EQ(AccountTrackerService::MIGRATION_DONE,
-            account_tracker_service_.GetMigrationState());
-  ASSERT_FALSE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
-  InitializeOAuth2ServiceDelegate(
-      signin::AccountConsistencyMethod::kDiceMigration);
-  oauth2_service_delegate_->RevokeAllCredentials();
-
-  // Add account info to the account tracker.
-  AccountInfo primary_account = CreateTestAccountInfo(
-      "primary_account", true /* is_hosted_domain*/, true /* is_valid*/);
-  account_tracker_service_.SeedAccountInfo(primary_account);
-
-  ResetObserverCounts();
-  AddAuthTokenManually("AccountId-" + primary_account.account_id.id,
-                       "refresh_token");
-  oauth2_service_delegate_->LoadCredentials(primary_account.account_id);
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(1, tokens_loaded_count_);
-  EXPECT_EQ(1, token_revoked_count_);
-  EXPECT_EQ(1, end_batch_changes_);
-  EXPECT_EQ(1, auth_error_changed_count_);
-
-  // After having revoked the primary account's token during loading, the
-  // delegate should have noticed that it had no token for the primary account
-  // when the load was complete and inserted an invalid token for that account.
-  EXPECT_EQ(1, token_available_count_);
-  EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(
-      primary_account.account_id));
-  EXPECT_EQ(
-      GaiaConstants::kInvalidRefreshToken,
-      oauth2_service_delegate_->refresh_tokens_[primary_account.account_id]
-          .refresh_token);
-  EXPECT_EQ(
-      GoogleServiceAuthError::InvalidGaiaCredentialsReason::CREDENTIALS_MISSING,
-      oauth2_service_delegate_->GetAuthError(primary_account.account_id)
-          .GetInvalidGaiaCredentialsReason());
-  EXPECT_EQ(signin::LoadCredentialsState::
-                LOAD_CREDENTIALS_FINISHED_WITH_NO_TOKEN_FOR_PRIMARY_ACCOUNT,
-            oauth2_service_delegate_->load_credentials_state());
-
-  EXPECT_TRUE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
-}
-
 // Checks that tokens are loaded and prefs::kTokenServiceDiceCompatible is set
 // to true if the tokens are loaded after the Dice migration.
 TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, LoadAfterDiceMigration) {
diff --git a/components/signin/public/base/account_consistency_method.cc b/components/signin/public/base/account_consistency_method.cc
index ba77c9a7..c278657e 100644
--- a/components/signin/public/base/account_consistency_method.cc
+++ b/components/signin/public/base/account_consistency_method.cc
@@ -8,23 +8,9 @@
 
 namespace signin {
 
-namespace {
-bool AccountConsistencyMethodGreaterOrEqual(AccountConsistencyMethod a,
-                                            AccountConsistencyMethod b) {
-  return static_cast<int>(a) >= static_cast<int>(b);
-}
-}  // namespace
-
 #if defined(OS_ANDROID)
 const base::Feature kMiceFeature{"MobileIdentityConsistency",
                                  base::FEATURE_DISABLED_BY_DEFAULT};
 #endif
 
-bool DiceMethodGreaterOrEqual(AccountConsistencyMethod a,
-                              AccountConsistencyMethod b) {
-  DCHECK_NE(AccountConsistencyMethod::kMirror, a);
-  DCHECK_NE(AccountConsistencyMethod::kMirror, b);
-  return AccountConsistencyMethodGreaterOrEqual(a, b);
-}
-
 }  // namespace signin
diff --git a/components/signin/public/base/account_consistency_method.h b/components/signin/public/base/account_consistency_method.h
index 5ca1dfea..88786f17 100644
--- a/components/signin/public/base/account_consistency_method.h
+++ b/components/signin/public/base/account_consistency_method.h
@@ -30,21 +30,12 @@
   // Account management UI in the avatar bubble.
   kMirror,
 
-  // Account management UI on Gaia webpages is enabled once the accounts become
-  // consistent.
-  kDiceMigration,
-
   // Account management UI on Gaia webpages is enabled. If accounts are not
   // consistent when this is enabled, the account reconcilor enforces the
   // consistency.
   kDice
 };
 
-// Returns true if the |a| comes after |b| in the AccountConsistencyMethod enum.
-// Should not be used for Mirror.
-bool DiceMethodGreaterOrEqual(AccountConsistencyMethod a,
-                              AccountConsistencyMethod b);
-
 }  // namespace signin
 
 #endif  // COMPONENTS_SIGNIN_PUBLIC_BASE_ACCOUNT_CONSISTENCY_METHOD_H_
diff --git a/components/signin/public/base/signin_metrics.cc b/components/signin/public/base/signin_metrics.cc
index 14e1052..3919085 100644
--- a/components/signin/public/base/signin_metrics.cc
+++ b/components/signin/public/base/signin_metrics.cc
@@ -276,87 +276,6 @@
   }
 }
 
-void RecordSigninNewAccountPreDiceUserActionForAccessPoint(
-    signin_metrics::AccessPoint access_point) {
-  switch (access_point) {
-    case signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_SigninNewAccountPreDice_FromSettings"));
-      break;
-    case AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_SigninNewAccountPreDice_FromExtensionInstallBubble"));
-      break;
-    case AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_SigninNewAccountPreDice_FromBookmarkBubble"));
-      break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_SigninNewAccountPreDice_FromBookmarkManager"));
-      break;
-    case AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_SigninNewAccountPreDice_FromAvatarBubbleSignin"));
-      break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_SigninNewAccountPreDice_FromRecentTabs"));
-      break;
-    case AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_SigninNewAccountPreDice_FromPasswordBubble"));
-      break;
-    case signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_SigninNewAccountPreDice_FromTabSwitcher"));
-      break;
-    case AccessPoint::ACCESS_POINT_NTP_CONTENT_SUGGESTIONS:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_SigninNewAccountPreDice_FromNTPContentSuggestions"));
-      break;
-    case AccessPoint::ACCESS_POINT_SAVE_CARD_BUBBLE:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_SigninNewAccountPreDice_FromSaveCardBubble"));
-      break;
-    case AccessPoint::ACCESS_POINT_MANAGE_CARDS_BUBBLE:
-      base::RecordAction(base::UserMetricsAction(
-          "Signin_SigninNewAccountPreDice_FromManageCardsBubble"));
-      break;
-    case AccessPoint::ACCESS_POINT_START_PAGE:
-    case AccessPoint::ACCESS_POINT_NTP_LINK:
-    case AccessPoint::ACCESS_POINT_MENU:
-    case AccessPoint::ACCESS_POINT_SUPERVISED_USER:
-    case AccessPoint::ACCESS_POINT_EXTENSIONS:
-    case AccessPoint::ACCESS_POINT_APPS_PAGE_LINK:
-    case AccessPoint::ACCESS_POINT_USER_MANAGER:
-    case AccessPoint::ACCESS_POINT_DEVICES_PAGE:
-    case AccessPoint::ACCESS_POINT_CLOUD_PRINT:
-    case AccessPoint::ACCESS_POINT_CONTENT_AREA:
-    case AccessPoint::ACCESS_POINT_SIGNIN_PROMO:
-    case AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN:
-    case AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR:
-    case AccessPoint::ACCESS_POINT_UNKNOWN:
-    case AccessPoint::ACCESS_POINT_MACHINE_LOGON:
-    case AccessPoint::ACCESS_POINT_GOOGLE_SERVICES_SETTINGS:
-      // These access points do not support personalized sign-in promos, so
-      // |Signin_SigninNewAccountPreDice_From*| user actions should not
-      // be recorded for them. Note: To avoid bloating the sign-in APIs, the
-      // sign-in metrics simply ignore if the caller passes
-      // |PROMO_ACTION_NEW_ACCOUNT_PRE_DICE| when a sign-in flow is
-      // started from any access point instead of treating it as an error like
-      // in the other cases (|WithDefault| and |NotDefault|).
-      VLOG(1) << "Signin_SigninNewAccountPreDice_From* user actions"
-              << " are not recorded for access point "
-              << static_cast<int>(access_point)
-              << " as it does not support a personalized sign-in promo.";
-      break;
-    case AccessPoint::ACCESS_POINT_MAX:
-      NOTREACHED();
-      break;
-  }
-}
-
 void RecordSigninNewAccountNoExistingAccountUserActionForAccessPoint(
     signin_metrics::AccessPoint access_point) {
   switch (access_point) {
@@ -591,12 +510,6 @@
           static_cast<int>(access_point),
           static_cast<int>(AccessPoint::ACCESS_POINT_MAX));
       break;
-    case PromoAction::PROMO_ACTION_NEW_ACCOUNT_PRE_DICE:
-      UMA_HISTOGRAM_ENUMERATION(
-          "Signin.SigninStartedAccessPoint.NewAccountPreDice",
-          static_cast<int>(access_point),
-          static_cast<int>(AccessPoint::ACCESS_POINT_MAX));
-      break;
     case PromoAction::PROMO_ACTION_NEW_ACCOUNT_NO_EXISTING_ACCOUNT:
       UMA_HISTOGRAM_ENUMERATION(
           "Signin.SigninStartedAccessPoint.NewAccountNoExistingAccount",
@@ -632,12 +545,6 @@
           static_cast<int>(access_point),
           static_cast<int>(AccessPoint::ACCESS_POINT_MAX));
       break;
-    case PromoAction::PROMO_ACTION_NEW_ACCOUNT_PRE_DICE:
-      UMA_HISTOGRAM_ENUMERATION(
-          "Signin.SigninCompletedAccessPoint.NewAccountPreDice",
-          static_cast<int>(access_point),
-          static_cast<int>(AccessPoint::ACCESS_POINT_MAX));
-      break;
     case PromoAction::PROMO_ACTION_NEW_ACCOUNT_NO_EXISTING_ACCOUNT:
       UMA_HISTOGRAM_ENUMERATION(
           "Signin.SigninCompletedAccessPoint.NewAccountNoExistingAccount",
@@ -819,9 +726,6 @@
     case PromoAction::PROMO_ACTION_NOT_DEFAULT:
       RecordSigninNotDefaultUserActionForAccessPoint(access_point);
       break;
-    case PromoAction::PROMO_ACTION_NEW_ACCOUNT_PRE_DICE:
-      RecordSigninNewAccountPreDiceUserActionForAccessPoint(access_point);
-      break;
     case PromoAction::PROMO_ACTION_NEW_ACCOUNT_NO_EXISTING_ACCOUNT:
       RecordSigninNewAccountNoExistingAccountUserActionForAccessPoint(
           access_point);
diff --git a/components/signin/public/base/signin_metrics.h b/components/signin/public/base/signin_metrics.h
index cfb5122..33f873c 100644
--- a/components/signin/public/base/signin_metrics.h
+++ b/components/signin/public/base/signin_metrics.h
@@ -171,8 +171,6 @@
   // On desktop, the user selected an account that is not the default. On
   // mobile, the user selected the generic "Use another account" button.
   PROMO_ACTION_NOT_DEFAULT,
-  // Non-personalized promo, pre-dice on desktop.
-  PROMO_ACTION_NEW_ACCOUNT_PRE_DICE,
   // Non personalized promo, when there is no account on the device.
   PROMO_ACTION_NEW_ACCOUNT_NO_EXISTING_ACCOUNT,
   // The user clicked on the "Add account" button, when there are already
diff --git a/components/signin/public/base/signin_metrics_unittest.cc b/components/signin/public/base/signin_metrics_unittest.cc
index 3a56f94..ef337bb 100644
--- a/components/signin/public/base/signin_metrics_unittest.cc
+++ b/components/signin/public/base/signin_metrics_unittest.cc
@@ -167,23 +167,6 @@
   }
 }
 
-TEST_F(SigninMetricsTest, RecordSigninUserActionWithNewPreDicePromoAction) {
-  for (const AccessPoint& ap : GetAllAccessPoints()) {
-    base::UserActionTester user_action_tester;
-    RecordSigninUserActionForAccessPoint(
-        ap, signin_metrics::PromoAction::PROMO_ACTION_NEW_ACCOUNT_PRE_DICE);
-    if (AccessPointSupportsPersonalizedPromo(ap)) {
-      EXPECT_EQ(1, user_action_tester.GetActionCount(
-                       "Signin_SigninNewAccountPreDice_From" +
-                       GetAccessPointDescription(ap)));
-    } else {
-      EXPECT_EQ(0, user_action_tester.GetActionCount(
-                       "Signin_SigninNewAccountPreDice_From" +
-                       GetAccessPointDescription(ap)));
-    }
-  }
-}
-
 TEST_F(SigninMetricsTest, RecordSigninUserActionWithNewNoExistingPromoAction) {
   for (const AccessPoint& ap : GetAllAccessPoints()) {
     base::UserActionTester user_action_tester;
diff --git a/components/signin/public/identity_manager/primary_account_mutator_unittest.cc b/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
index a980a49..f56a6d8 100644
--- a/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
+++ b/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
@@ -29,7 +29,6 @@
 const signin::AccountConsistencyMethod kTestedAccountConsistencyMethods[] = {
     signin::AccountConsistencyMethod::kDisabled,
     signin::AccountConsistencyMethod::kMirror,
-    signin::AccountConsistencyMethod::kDiceMigration,
     signin::AccountConsistencyMethod::kDice,
 };
 
diff --git a/components/sync/engine/sync_engine_switches.cc b/components/sync/engine/sync_engine_switches.cc
index c029dc7e..9861111 100644
--- a/components/sync/engine/sync_engine_switches.cc
+++ b/components/sync/engine/sync_engine_switches.cc
@@ -28,4 +28,11 @@
 const base::Feature kSyncSupportTrustedVaultPassphrase{
     "SyncSupportTrustedVaultPassphrase", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// If enabled sync cycle ends by collecting contributions from all datatypes
+// and having less than max_commit_batch_size() entries to commit. If disabled
+// it ends when attempt to collect contributions returned no entries to commit.
+// TODO(crbug.com/1022293): Remove this flag after M82 or so.
+const base::Feature kSyncPreventCommitsBypassingNudgeDelay{
+    "SyncPreventCommitsBypassingNudgeDelay", base::FEATURE_ENABLED_BY_DEFAULT};
+
 }  // namespace switches
diff --git a/components/sync/engine/sync_engine_switches.h b/components/sync/engine/sync_engine_switches.h
index 40dba17..ec5300a 100644
--- a/components/sync/engine/sync_engine_switches.h
+++ b/components/sync/engine/sync_engine_switches.h
@@ -14,6 +14,7 @@
 extern const base::Feature kSyncResetPollIntervalOnStart;
 extern const base::Feature kSyncUseScryptForNewCustomPassphrases;
 extern const base::Feature kSyncSupportTrustedVaultPassphrase;
+extern const base::Feature kSyncPreventCommitsBypassingNudgeDelay;
 
 }  // namespace switches
 
diff --git a/components/sync/engine_impl/commit.cc b/components/sync/engine_impl/commit.cc
index bbab54ec..3c4eaa05 100644
--- a/components/sync/engine_impl/commit.cc
+++ b/components/sync/engine_impl/commit.cc
@@ -51,8 +51,7 @@
 }
 
 // static
-std::unique_ptr<Commit> Commit::Init(ModelTypeSet requested_types,
-                                     ModelTypeSet enabled_types,
+std::unique_ptr<Commit> Commit::Init(ModelTypeSet enabled_types,
                                      size_t max_entries,
                                      const std::string& account_name,
                                      const std::string& cache_guid,
@@ -62,7 +61,7 @@
                                      ExtensionsActivity* extensions_activity) {
   // Gather per-type contributions.
   ContributionMap contributions = commit_processor->GatherCommitContributions(
-      requested_types, max_entries, cookie_jar_mismatch, cookie_jar_empty);
+      max_entries, cookie_jar_mismatch, cookie_jar_empty);
 
   // Give up if no one had anything to commit.
   if (contributions.empty())
diff --git a/components/sync/engine_impl/commit.h b/components/sync/engine_impl/commit.h
index d2925bc5..a7f30a9 100644
--- a/components/sync/engine_impl/commit.h
+++ b/components/sync/engine_impl/commit.h
@@ -47,8 +47,7 @@
   ~Commit();
 
   // |extensions_activity| may be null.
-  static std::unique_ptr<Commit> Init(ModelTypeSet requested_types,
-                                      ModelTypeSet enabled_types,
+  static std::unique_ptr<Commit> Init(ModelTypeSet enabled_types,
                                       size_t max_entries,
                                       const std::string& account_name,
                                       const std::string& cache_guid,
diff --git a/components/sync/engine_impl/commit_processor.cc b/components/sync/engine_impl/commit_processor.cc
index a467576..7f452a3 100644
--- a/components/sync/engine_impl/commit_processor.cc
+++ b/components/sync/engine_impl/commit_processor.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/metrics/histogram_macros.h"
+#include "components/sync/engine/sync_engine_switches.h"
 #include "components/sync/engine_impl/commit_contribution.h"
 #include "components/sync/engine_impl/commit_contributor.h"
 #include "components/sync/protocol/sync.pb.h"
@@ -16,35 +17,48 @@
 
 using TypeToIndexMap = std::map<ModelType, size_t>;
 
-CommitProcessor::CommitProcessor(CommitContributorMap* commit_contributor_map)
-    : commit_contributor_map_(commit_contributor_map) {}
+CommitProcessor::CommitProcessor(ModelTypeSet commit_types,
+                                 CommitContributorMap* commit_contributor_map)
+    : commit_types_(commit_types),
+      commit_contributor_map_(commit_contributor_map),
+      gathered_all_contributions_(false) {
+  // NIGORI contributions must be collected in every commit cycle.
+  DCHECK(commit_types_.Has(NIGORI));
+  DCHECK(commit_contributor_map);
+}
 
 CommitProcessor::~CommitProcessor() {}
 
 Commit::ContributionMap CommitProcessor::GatherCommitContributions(
-    ModelTypeSet commit_types,
     size_t max_entries,
     bool cookie_jar_mismatch,
     bool cookie_jar_empty) {
+  if (gathered_all_contributions_ &&
+      base::FeatureList::IsEnabled(
+          switches::kSyncPreventCommitsBypassingNudgeDelay)) {
+    return Commit::ContributionMap();
+  }
+
+  ModelTypeSet contributing_commit_types = commit_types_;
+
   Commit::ContributionMap contributions;
   size_t num_entries = 0;
 
   // NIGORI should be committed before any other datatype.
-  DCHECK(commit_types.Has(NIGORI));
-
-  commit_types.Remove(NIGORI);
   num_entries +=
       GatherCommitContributionsForType(NIGORI, max_entries, cookie_jar_mismatch,
                                        cookie_jar_empty, &contributions);
+
   if (num_entries != 0) {
     // If the outgoing commit has a NIGORI update, there are some risks if
     // changes from other datatypes are bundled together in the same commit, as
     // long as the datatype is encryptable. Hence, restrict to
     // PriorityUserTypes() which are never encrypted.
-    commit_types.RetainAll(PriorityUserTypes());
+    contributing_commit_types.RetainAll(PriorityUserTypes());
   }
 
-  for (ModelType type : commit_types) {
+  for (ModelType type :
+       Difference(contributing_commit_types, ModelTypeSet(NIGORI))) {
     num_entries += GatherCommitContributionsForType(
         type, max_entries - num_entries, cookie_jar_mismatch, cookie_jar_empty,
         &contributions);
@@ -55,6 +69,15 @@
     }
   }
 
+  if (contributing_commit_types == commit_types_ && num_entries < max_entries) {
+    // Technically |num_entries| == |max_entries| may also mean that all
+    // contributions have been gathered, but it's safe to ignore, since this
+    // will lead to empty contribution in the next call and exiting commit
+    // cycle (or additional commit cycle in rare cases when new contributions
+    // come meanwhile).
+    gathered_all_contributions_ = true;
+  }
+
   return contributions;
 }
 
diff --git a/components/sync/engine_impl/commit_processor.h b/components/sync/engine_impl/commit_processor.h
index c6d3cd4..e8d4e88e 100644
--- a/components/sync/engine_impl/commit_processor.h
+++ b/components/sync/engine_impl/commit_processor.h
@@ -23,14 +23,14 @@
 // This class manages the set of per-type committer objects.
 //
 // It owns these types and hides the details of iterating over all of them.
-// Many methods allow the caller to specify a subset of types on which the
-// operation is to be applied.  It is a logic error if the supplied set of types
-// contains a type which was not previously registered.
+// It is a logic error if the supplied set of types contains a type which was
+// not previously registered.
 class CommitProcessor {
  public:
-  // Contructs a CommitProcessor from a map of CommitContributors.
-  // The CommitProcessor does not own this map.
-  explicit CommitProcessor(CommitContributorMap* commit_contributor_map);
+  // |commit_types| must contain NIGORI. |commit_contributor_map| must be not
+  // null and must outlive this object.
+  CommitProcessor(ModelTypeSet commit_types,
+                  CommitContributorMap* commit_contributor_map);
   ~CommitProcessor();
 
   // Gathers a set of contributions to be used to populate a commit message.
@@ -39,10 +39,11 @@
   // map, gather any entries queued for commit into CommitContributions.  The
   // total number of entries in all the returned CommitContributions shall not
   // exceed |max_entries|.
+  // Returns no contribution if previous call collected them from all datatypes
+  // and total number of collected entries was less than |max_entries|.
   // Note: |cookie_jar_mismatch| and |cookie_jar_empty| are used only for
   // metrics recording purposes specific to the SESSIONS type.
-  Commit::ContributionMap GatherCommitContributions(ModelTypeSet commit_types,
-                                                    size_t max_entries,
+  Commit::ContributionMap GatherCommitContributions(size_t max_entries,
                                                     bool cookie_jar_mismatch,
                                                     bool cookie_jar_empty);
 
@@ -54,8 +55,11 @@
                                        bool cookie_jar_empty,
                                        Commit::ContributionMap* contributions);
 
+  const ModelTypeSet commit_types_;
+
   // A map of 'commit contributors', one for each enabled type.
   CommitContributorMap* commit_contributor_map_;
+  bool gathered_all_contributions_;
 
   DISALLOW_COPY_AND_ASSIGN(CommitProcessor);
 };
diff --git a/components/sync/engine_impl/syncer.cc b/components/sync/engine_impl/syncer.cc
index ca2de93..dd151d5 100644
--- a/components/sync/engine_impl/syncer.cc
+++ b/components/sync/engine_impl/syncer.cc
@@ -61,10 +61,8 @@
     }
   }
 
-  CommitProcessor commit_processor(
-      cycle->context()->model_type_registry()->commit_contributor_map());
-  SyncerError commit_result = BuildAndPostCommits(request_types, nudge_tracker,
-                                                  cycle, &commit_processor);
+  SyncerError commit_result =
+      BuildAndPostCommits(request_types, nudge_tracker, cycle);
   cycle->mutable_status_controller()->set_commit_result(commit_result);
 
   return HandleCycleEnd(cycle, nudge_tracker->GetOrigin());
@@ -147,21 +145,23 @@
 
 SyncerError Syncer::BuildAndPostCommits(const ModelTypeSet& request_types,
                                         NudgeTracker* nudge_tracker,
-                                        SyncCycle* cycle,
-                                        CommitProcessor* commit_processor) {
+                                        SyncCycle* cycle) {
   VLOG(1) << "Committing from types " << ModelTypeSetToString(request_types);
 
+  CommitProcessor commit_processor(
+      request_types,
+      cycle->context()->model_type_registry()->commit_contributor_map());
   // The ExitRequested() check is unnecessary, since we should start getting
   // errors from the ServerConnectionManager if an exist has been requested.
   // However, it doesn't hurt to check it anyway.
   while (!ExitRequested()) {
     std::unique_ptr<Commit> commit(
-        Commit::Init(request_types, cycle->context()->GetEnabledTypes(),
+        Commit::Init(cycle->context()->GetEnabledTypes(),
                      cycle->context()->max_commit_batch_size(),
                      cycle->context()->account_name(),
                      cycle->context()->directory()->cache_guid(),
                      cycle->context()->cookie_jar_mismatch(),
-                     cycle->context()->cookie_jar_empty(), commit_processor,
+                     cycle->context()->cookie_jar_empty(), &commit_processor,
                      cycle->context()->extensions_activity()));
     if (!commit) {
       break;
diff --git a/components/sync/engine_impl/syncer.h b/components/sync/engine_impl/syncer.h
index 23b389e..b48b593 100644
--- a/components/sync/engine_impl/syncer.h
+++ b/components/sync/engine_impl/syncer.h
@@ -18,7 +18,6 @@
 namespace syncer {
 
 class CancelationSignal;
-class CommitProcessor;
 class GetUpdatesDelegate;
 class NudgeTracker;
 class SyncCycle;
@@ -80,8 +79,7 @@
   // abort any blocking operations.
   SyncerError BuildAndPostCommits(const ModelTypeSet& request_types,
                                   NudgeTracker* nudge_tracker,
-                                  SyncCycle* cycle,
-                                  CommitProcessor* commit_processor);
+                                  SyncCycle* cycle);
 
   // Whether an early exist was requested due to a cancelation signal.
   bool ExitRequested();
diff --git a/components/sync/engine_impl/syncer_unittest.cc b/components/sync/engine_impl/syncer_unittest.cc
index 5e023542..f11d77f 100644
--- a/components/sync/engine_impl/syncer_unittest.cc
+++ b/components/sync/engine_impl/syncer_unittest.cc
@@ -2374,7 +2374,10 @@
   mock_server_->SetMidCommitCallback(base::Bind(
       &EntryCreatedInNewFolderTest::CreateFolderInBob, base::Unretained(this)));
   EXPECT_TRUE(SyncShareNudge());
-  // We loop until no unsynced handles remain, so we will commit both ids.
+
+  mock_server_->SetMidCommitCallback(base::DoNothing());
+  EXPECT_TRUE(SyncShareNudge());
+
   EXPECT_EQ(2u, mock_server_->committed_ids().size());
   {
     syncable::ReadTransaction trans(FROM_HERE, directory());
@@ -5102,11 +5105,14 @@
   ExpectUnsyncedCreation();
 
   // In the middle of the initial creation commit, perform a deletion.
-  // This should trigger performing two consecutive commit cycles, resulting
-  // in the bookmark being both deleted and synced.
   mock_server_->SetMidCommitCallback(
       base::Bind(&SyncerBookmarksTest::Delete, base::Unretained(this)));
 
+  // Commits creation.
+  EXPECT_TRUE(SyncShareNudge());
+
+  // Commits deletion.
+  mock_server_->SetMidCommitCallback(base::DoNothing());
   EXPECT_TRUE(SyncShareNudge());
   ExpectSyncedAndDeleted();
 }
@@ -5121,6 +5127,11 @@
   mock_server_->SetMidCommitCallback(base::Bind(
       &SyncerBookmarksTest::UpdateAndDelete, base::Unretained(this)));
 
+  // Commits creation.
+  EXPECT_TRUE(SyncShareNudge());
+
+  // Commits update and deletion.
+  mock_server_->SetMidCommitCallback(base::DoNothing());
   EXPECT_TRUE(SyncShareNudge());
   ExpectSyncedAndDeleted();
 }
@@ -5297,14 +5308,18 @@
   ExpectUnsyncedDeletion();
   mock_server_->SetMidCommitCallback(
       base::Bind(&SyncerUndeletionTest::Undelete, base::Unretained(this)));
+
+  // Commits deletion.
+  EXPECT_TRUE(SyncShareNudge());
+  sync_pb::SyncEntity deletion_update =
+      *mock_server_->AddUpdateFromLastCommit();
+
+  // Commits undeletion.
+  mock_server_->SetMidCommitCallback(base::DoNothing());
   EXPECT_TRUE(SyncShareNudge());
 
-  // We will continue to commit until all nodes are synced, so we expect
-  // that both the delete and following undelete were committed.  We haven't
-  // downloaded any updates, though, so the SERVER fields will be the same
-  // as they were at the start of the cycle.
   EXPECT_EQ(0, cycle_->status_controller().TotalNumConflictingItems());
-  EXPECT_EQ(1, mock_server_->GetAndClearNumGetUpdatesRequests());
+  EXPECT_EQ(2, mock_server_->GetAndClearNumGetUpdatesRequests());
 
   {
     syncable::ReadTransaction trans(FROM_HERE, directory());
@@ -5323,10 +5338,9 @@
   // the server.  The undeletion should prevail again and be committed.
   // None of this should trigger any conflict detection -- it is perfectly
   // normal to recieve updates from our own commits.
-  mock_server_->SetMidCommitCallback(base::Closure());
-  sync_pb::SyncEntity* update = mock_server_->AddUpdateFromLastCommit();
-  update->set_originator_cache_guid(local_cache_guid());
-  update->set_originator_client_item_id(local_id_.GetServerId());
+  deletion_update.set_originator_cache_guid(local_cache_guid());
+  deletion_update.set_originator_client_item_id(local_id_.GetServerId());
+  *mock_server_->AddUpdateFromLastCommit() = deletion_update;
 
   EXPECT_TRUE(SyncShareNudge());
   EXPECT_EQ(0, cycle_->status_controller().TotalNumConflictingItems());
diff --git a/components/sync_bookmarks/bookmark_model_merger.cc b/components/sync_bookmarks/bookmark_model_merger.cc
index 861403d..dfd19a2 100644
--- a/components/sync_bookmarks/bookmark_model_merger.cc
+++ b/components/sync_bookmarks/bookmark_model_merger.cc
@@ -237,9 +237,8 @@
       favicon_service_(favicon_service),
       bookmark_tracker_(bookmark_tracker),
       remote_forest_(BuildRemoteForest(std::move(updates))),
-      guid_to_remote_node_map_(BuildGUIDToRemoteNodeMap(remote_forest_)),
-      guid_to_local_node_map_(
-          BuildGUIDToLocalNodeMap(bookmark_model_, guid_to_remote_node_map_)) {
+      guid_to_match_map_(
+          FindGuidMatchesOrReassignLocal(remote_forest_, bookmark_model_)) {
   DCHECK(bookmark_tracker_->IsEmpty());
   DCHECK(favicon_service);
 }
@@ -307,63 +306,62 @@
 }
 
 // static
-std::unordered_map<std::string, const BookmarkModelMerger::RemoteTreeNode*>
-BookmarkModelMerger::BuildGUIDToRemoteNodeMap(
-    const RemoteForest& remote_forest) {
+std::unordered_map<std::string, BookmarkModelMerger::GuidMatch>
+BookmarkModelMerger::FindGuidMatchesOrReassignLocal(
+    const RemoteForest& remote_forest,
+    bookmarks::BookmarkModel* bookmark_model) {
+  DCHECK(bookmark_model);
+
   // TODO(crbug.com/978430): Handle potential duplicate GUIDs within remote
   // updates.
-  std::unordered_map<std::string, const RemoteTreeNode*>
-      guid_to_remote_node_map;
+
   if (!base::FeatureList::IsEnabled(switches::kMergeBookmarksUsingGUIDs)) {
-    return guid_to_remote_node_map;
+    return {};
   }
 
+  // Build a temporary lookup table for remote GUIDs.
+  std::unordered_map<std::string, const RemoteTreeNode*>
+      guid_to_remote_node_map;
   for (const auto& tree_tag_and_root : remote_forest) {
     tree_tag_and_root.second.EmplaceSelfAndDescendantsByGUID(
         &guid_to_remote_node_map);
   }
 
-  return guid_to_remote_node_map;
-}
-
-// static
-std::unordered_map<std::string, const bookmarks::BookmarkNode*>
-BookmarkModelMerger::BuildGUIDToLocalNodeMap(
-    bookmarks::BookmarkModel* bookmark_model,
-    const std::unordered_map<std::string, const RemoteTreeNode*>&
-        guid_to_remote_node_map) {
-  DCHECK(bookmark_model);
-
-  std::unordered_map<std::string, const bookmarks::BookmarkNode*>
-      guid_to_local_node_map;
-  if (!base::FeatureList::IsEnabled(switches::kMergeBookmarksUsingGUIDs)) {
-    return guid_to_local_node_map;
-  }
-
+  // Iterate through all local bookmarks to find matches by GUID.
+  std::unordered_map<std::string, BookmarkModelMerger::GuidMatch>
+      guid_to_match_map;
   ui::TreeNodeIterator<const bookmarks::BookmarkNode> iterator(
       bookmark_model->root_node());
   while (iterator.has_next()) {
-    const bookmarks::BookmarkNode* node = iterator.Next();
+    const bookmarks::BookmarkNode* const node = iterator.Next();
     DCHECK(base::IsValidGUID(node->guid()));
+
     if (node->is_permanent_node()) {
       continue;
     }
+
     const auto remote_it = guid_to_remote_node_map.find(node->guid());
     if (remote_it == guid_to_remote_node_map.end()) {
       continue;
     }
-    // If local node and its remote node match are conflicting in node type or
-    // URL, replace local GUID with a random GUID.
-    const syncer::EntityData& remote_entity = remote_it->second->entity();
+
+    const RemoteTreeNode* const remote_node = remote_it->second;
+    const syncer::EntityData& remote_entity = remote_node->entity();
     if (node->is_folder() != remote_entity.is_folder ||
         (node->is_url() &&
          node->url() != remote_entity.specifics.bookmark().url())) {
-      node =
-          ReplaceBookmarkNodeGUID(node, base::GenerateGUID(), bookmark_model);
+      // If local node and its remote node match are conflicting in node type or
+      // URL, replace local GUID with a random GUID.
+      // TODO(crbug.com/978430): Local GUIDs should also be reassigned if they
+      // match a remote originator_item_id.
+      ReplaceBookmarkNodeGUID(node, base::GenerateGUID(), bookmark_model);
+      continue;
     }
-    guid_to_local_node_map.emplace(node->guid(), node);
+
+    guid_to_match_map.emplace(node->guid(), GuidMatch{node, remote_node});
   }
-  return guid_to_local_node_map;
+
+  return guid_to_match_map;
 }
 
 void BookmarkModelMerger::MergeSubtree(
@@ -422,25 +420,27 @@
     const bookmarks::BookmarkNode* local_parent,
     size_t local_child_start_index) const {
   // Try to match child by GUID. If we can't, try to match child by semantics.
-  const bookmarks::BookmarkNode* matching_local_node =
+  const bookmarks::BookmarkNode* matching_local_node_by_guid =
       FindMatchingLocalNodeByGUID(remote_child);
-  if (!matching_local_node) {
-    // All local nodes up to |remote_index-1| have processed already. Look for a
-    // matching local node starting with the local node at position
-    // |local_child_start_index|. FindMatchingChildBySemanticsStartingAt()
-    // returns kInvalidIndex in the case where no semantics match was found or
-    // the semantics match found is GUID-matchable to a different node.
-    const size_t local_index = FindMatchingChildBySemanticsStartingAt(
-        /*remote_node=*/remote_child,
-        /*local_parent=*/local_parent,
-        /*starting_child_index=*/local_child_start_index);
-    if (local_index == kInvalidIndex) {
-      // If no match found, return.
-      return nullptr;
-    }
-    matching_local_node = local_parent->children()[local_index].get();
+  if (matching_local_node_by_guid) {
+    return matching_local_node_by_guid;
   }
-  return matching_local_node;
+
+  // All local nodes up to |remote_index-1| have processed already. Look for a
+  // matching local node starting with the local node at position
+  // |local_child_start_index|. FindMatchingChildBySemanticsStartingAt()
+  // returns kInvalidIndex in the case where no semantics match was found or
+  // the semantics match found is GUID-matchable to a different node.
+  const size_t local_index = FindMatchingChildBySemanticsStartingAt(
+      /*remote_node=*/remote_child,
+      /*local_parent=*/local_parent,
+      /*starting_child_index=*/local_child_start_index);
+  if (local_index == kInvalidIndex) {
+    // If no match found, return.
+    return nullptr;
+  }
+
+  return local_parent->children()[local_index].get();
 }
 
 const bookmarks::BookmarkNode*
@@ -471,8 +471,6 @@
     return local_node;
   }
   DCHECK(base::IsValidGUID(specifics.guid()));
-  // We do not update the GUID maps upon node replacement as per the comment
-  // in bookmark_model_merger.h.
   return ReplaceBookmarkNodeGUID(local_node, specifics.guid(), bookmark_model_);
 }
 
@@ -574,7 +572,7 @@
     if (FindMatchingRemoteNodeByGUID(node->children()[i].get())) {
       continue;
     }
-    ProcessLocalCreation(node, i);
+    ProcessLocalCreation(/*parent=*/node, i);
   }
 }
 
@@ -612,36 +610,25 @@
 BookmarkModelMerger::FindMatchingRemoteNodeByGUID(
     const bookmarks::BookmarkNode* local_node) const {
   DCHECK(local_node);
-  // Ensure matching nodes are of the same type and have the same URL,
-  // guaranteed by BuildGUIDToLocalNodeMap().
-  const auto it = guid_to_remote_node_map_.find(local_node->guid());
-  if (it == guid_to_remote_node_map_.end()) {
+
+  const auto it = guid_to_match_map_.find(local_node->guid());
+  if (it == guid_to_match_map_.end()) {
     return nullptr;
   }
 
-  const RemoteTreeNode* const remote_node = it->second;
-  DCHECK(remote_node);
-  DCHECK_EQ(local_node->is_folder(), remote_node->entity().is_folder);
-  DCHECK_EQ(local_node->url(),
-            remote_node->entity().specifics.bookmark().url());
-  return remote_node;
+  return it->second.remote_node;
 }
 
 const bookmarks::BookmarkNode* BookmarkModelMerger::FindMatchingLocalNodeByGUID(
     const RemoteTreeNode& remote_node) const {
   const syncer::EntityData& remote_entity = remote_node.entity();
   const auto it =
-      guid_to_local_node_map_.find(remote_entity.specifics.bookmark().guid());
-  if (it == guid_to_local_node_map_.end()) {
+      guid_to_match_map_.find(remote_entity.specifics.bookmark().guid());
+  if (it == guid_to_match_map_.end()) {
     return nullptr;
   }
-  DCHECK(!remote_entity.specifics.bookmark().guid().empty());
-  const bookmarks::BookmarkNode* local_node = it->second;
-  // Ensure matching nodes are of the same type and have the same URL,
-  // guaranteed by BuildGUIDToLocalNodeMap().
-  DCHECK_EQ(local_node->is_folder(), remote_entity.is_folder);
-  DCHECK_EQ(local_node->url(), remote_entity.specifics.bookmark().url());
-  return local_node;
+
+  return it->second.local_node;
 }
 
 }  // namespace sync_bookmarks
diff --git a/components/sync_bookmarks/bookmark_model_merger.h b/components/sync_bookmarks/bookmark_model_merger.h
index 1a40fad..1874492 100644
--- a/components/sync_bookmarks/bookmark_model_merger.h
+++ b/components/sync_bookmarks/bookmark_model_merger.h
@@ -56,6 +56,14 @@
   // a permanent node, keyed by server-defined unique tag of the root.
   using RemoteForest = std::unordered_map<std::string, RemoteTreeNode>;
 
+  // Represents a pair of bookmarks, one local and one remote, that have been
+  // matched by GUID. They are guaranteed to have the same type and URL (if
+  // applicable).
+  struct GuidMatch {
+    const bookmarks::BookmarkNode* local_node;
+    const RemoteTreeNode* remote_node;
+  };
+
   // Constructs the remote bookmark tree to be merged. Each entry in the
   // returned map is a permanent node, identified (keyed) by the server-defined
   // tag. All invalid updates are filtered out, including invalid bookmark
@@ -63,22 +71,12 @@
   // sends tombstones as part of the initial download.
   static RemoteForest BuildRemoteForest(syncer::UpdateResponseDataList updates);
 
-  // Constructs a map from GUID to corresponding remote nodes, used in the merge
-  // process to determine GUID-based node matches.
-  static std::unordered_map<std::string, const RemoteTreeNode*>
-  BuildGUIDToRemoteNodeMap(const RemoteForest& remote_forest);
-
-  // Constructs a map from GUID to corresponding local node, used in the merge
-  // process to determine GUID-based node matches. |bookmark_model| must not be
-  // null. |guid_to_remote_node_map| is used to detect conflicting GUID matches
-  // between local and remote bookmarks for the cases where they cannot be
-  // merged (e.g. folder vs non-folder) and in such cases regenerate a random
-  // GUID for the local bookmark.
-  static std::unordered_map<std::string, const bookmarks::BookmarkNode*>
-  BuildGUIDToLocalNodeMap(
-      bookmarks::BookmarkModel* bookmark_model,
-      const std::unordered_map<std::string, const RemoteTreeNode*>&
-          guid_to_remote_node_map);
+  // Computes bookmark pairs that should be matched by GUID. Local bookmark
+  // GUIDs may be regenerated for the case where they collide with a remote GUID
+  // that is not compatible (e.g. folder vs non-folder).
+  static std::unordered_map<std::string, GuidMatch>
+  FindGuidMatchesOrReassignLocal(const RemoteForest& remote_forest,
+                                 bookmarks::BookmarkModel* bookmark_model);
 
   // Merges a local and a remote subtrees. The input nodes are two equivalent
   // local and remote nodes. This method tries to recursively match their
@@ -151,15 +149,7 @@
   // Preprocessed remote nodes in the form a forest where each tree's root is a
   // permanent node. Computed upon construction via BuildRemoteForest().
   const RemoteForest remote_forest_;
-  // Maps GUIDs to their respective remote nodes. Used for GUID-based node
-  // matching and is populated at the beginning of the merge process.
-  const std::unordered_map<std::string, const RemoteTreeNode*>
-      guid_to_remote_node_map_;
-  // Maps GUIDs to their respective local nodes. Used for GUID-based
-  // node matching and is populated at the beginning of the merge process.
-  // Is not updated upon potential changes to the model during merge.
-  const std::unordered_map<std::string, const bookmarks::BookmarkNode*>
-      guid_to_local_node_map_;
+  std::unordered_map<std::string, GuidMatch> guid_to_match_map_;
 
   DISALLOW_COPY_AND_ASSIGN(BookmarkModelMerger);
 };
diff --git a/components/sync_bookmarks/bookmark_specifics_conversions.cc b/components/sync_bookmarks/bookmark_specifics_conversions.cc
index 98725dce..74914f18 100644
--- a/components/sync_bookmarks/bookmark_specifics_conversions.cc
+++ b/components/sync_bookmarks/bookmark_specifics_conversions.cc
@@ -255,6 +255,12 @@
   }
   const bookmarks::BookmarkNode* new_node;
   DCHECK(base::IsValidGUID(guid));
+
+  if (node->guid() == guid) {
+    // Nothing to do.
+    return node;
+  }
+
   if (node->is_folder()) {
     new_node =
         model->AddFolder(node->parent(), node->parent()->GetIndexOf(node),
diff --git a/components/viz/demo/demo_main.cc b/components/viz/demo/demo_main.cc
index 61be4e90..f470f6c 100644
--- a/components/viz/demo/demo_main.cc
+++ b/components/viz/demo/demo_main.cc
@@ -21,7 +21,7 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "ui/events/platform/platform_event_source.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
@@ -114,7 +114,7 @@
   }
 
  private:
-  std::unique_ptr<ui::PlatformWindowBase> CreatePlatformWindow(
+  std::unique_ptr<ui::PlatformWindow> CreatePlatformWindow(
       const gfx::Rect& bounds) {
     ui::PlatformWindowInitProperties props(bounds);
 #if defined(USE_OZONE)
@@ -184,7 +184,7 @@
   std::unique_ptr<demo::DemoHost> host_;
   std::unique_ptr<demo::DemoService> service_;
 
-  std::unique_ptr<ui::PlatformWindowBase> platform_window_;
+  std::unique_ptr<ui::PlatformWindow> platform_window_;
   gfx::AcceleratedWidget widget_;
 
   DISALLOW_COPY_AND_ASSIGN(DemoWindow);
diff --git a/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc b/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc
index e002109..e71d6a9 100644
--- a/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc
+++ b/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc
@@ -21,7 +21,7 @@
 #include "ui/ozone/public/platform_window_surface.h"
 #include "ui/ozone/public/surface_factory_ozone.h"
 #include "ui/ozone/public/surface_ozone_canvas.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc
index 0775522b..3b65afd 100644
--- a/content/browser/back_forward_cache_browsertest.cc
+++ b/content/browser/back_forward_cache_browsertest.cc
@@ -3,8 +3,10 @@
 // found in the LICENSE file.
 
 #include "base/command_line.h"
+#include "base/hash/hash.h"
 #include "base/metrics/metrics_hashes.h"
 #include "base/optional.h"
+#include "base/system/sys_info.h"
 #include "base/task/post_task.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/scoped_feature_list.h"
@@ -47,6 +49,7 @@
 #include "services/service_manager/public/cpp/service_binding.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h"
+#include "unordered_map"
 
 using testing::Each;
 using testing::ElementsAre;
@@ -58,6 +61,20 @@
 
 const char* kDisabledReasonForTest = "DisabledByBackForwardCacheBrowserTest";
 
+// hash for std::unordered_map.
+struct FeatureHash {
+  size_t operator()(base::Feature feature) const {
+    return base::FastHash(feature.name);
+  }
+};
+
+// compare operator for std::unordered_map.
+struct FeatureEqualOperator {
+  bool operator()(base::Feature feature1, base::Feature feature2) const {
+    return std::strcmp(feature1.name, feature2.name) == 0;
+  }
+};
+
 // Test about the BackForwardCache.
 class BackForwardCacheBrowserTest : public ContentBrowserTest {
  public:
@@ -71,18 +88,32 @@
         switches::kIgnoreCertificateErrors);
     base::CommandLine::ForCurrentProcess()->AppendSwitch(
         switches::kEnableExperimentalWebPlatformFeatures);
-    feature_list_.InitWithFeaturesAndParameters(
-        {{features::kBackForwardCache, {GetFeatureParams()}},
-         {features::kServiceWorkerOnUI, {}}},
-        {});
+    // TODO(sreejakshetty): Initialize ScopedFeatureLists from test constructor.
+    EnableFeatureAndSetParams(features::kBackForwardCache,
+                              "TimeToLiveInBackForwardCacheInSeconds", "3600");
+    EnableFeatureAndSetParams(features::kServiceWorkerOnUI, "", "");
+    SetupFeaturesAndParameters();
 
     ContentBrowserTest::SetUpCommandLine(command_line);
   }
 
-  virtual base::FieldTrialParams GetFeatureParams() {
-    // Set a very long TTL before expiration (longer than the test timeout) so
-    // tests that are expecting deletion don't pass when they shouldn't.
-    return {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}};
+  void SetupFeaturesAndParameters() {
+    std::vector<base::test::ScopedFeatureList::FeatureAndParams>
+        enabled_features;
+
+    for (auto feature_param = features_with_params_.begin();
+         feature_param != features_with_params_.end(); feature_param++) {
+      enabled_features.push_back({feature_param->first, feature_param->second});
+    }
+
+    feature_list_.InitWithFeaturesAndParameters(enabled_features,
+                                                /*disabled_features*/ {});
+  }
+
+  void EnableFeatureAndSetParams(base::Feature feature,
+                                 std::string param_name,
+                                 std::string param_value) {
+    features_with_params_[feature][param_name] = param_value;
   }
 
   void SetUpOnMainThread() override {
@@ -256,8 +287,12 @@
   std::vector<base::Bucket> expected_blocklisted_features_;
   std::vector<base::Bucket> expected_disabled_reasons_;
   std::vector<base::Bucket> expected_eviction_after_committing_;
-
   std::unique_ptr<net::EmbeddedTestServer> https_server_;
+  std::unordered_map<base::Feature,
+                     std::map<std::string, std::string>,
+                     FeatureHash,
+                     FeatureEqualOperator>
+      features_with_params_;
 };
 
 // Match RenderFrameHostImpl* that are in the BackForwardCache.
@@ -2593,8 +2628,11 @@
   ~BackForwardCacheBrowserTestWithServiceWorkerEnabled() override {}
 
  protected:
-  base::FieldTrialParams GetFeatureParams() override {
-    return {{"service_worker_supported", "true"}};
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    EnableFeatureAndSetParams(features::kBackForwardCache,
+                              "service_worker_supported", "true");
+
+    BackForwardCacheBrowserTest::SetUpCommandLine(command_line);
   }
 };
 
@@ -2915,8 +2953,11 @@
  protected:
   GeolocationBackForwardCacheBrowserTest() : geo_override_(0.0, 0.0) {}
 
-  base::FieldTrialParams GetFeatureParams() override {
-    return {{"geolocation_supported", "true"}};
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    EnableFeatureAndSetParams(features::kBackForwardCache,
+                              "geolocation_supported", "true");
+
+    BackForwardCacheBrowserTest::SetUpCommandLine(command_line);
   }
 
   device::ScopedGeolocationOverrider geo_override_;
@@ -3058,7 +3099,7 @@
 
   base::TimeDelta time_to_live_in_back_forward_cache =
       BackForwardCacheImpl::GetTimeToLiveInBackForwardCache();
-  // This should match the value we set in GetFeatureParams.
+  // This should match the value we set in EnableFeatureAndSetParams.
   EXPECT_EQ(time_to_live_in_back_forward_cache,
             base::TimeDelta::FromSeconds(3600));
 
@@ -3286,18 +3327,16 @@
 class BackForwardCacheBrowserTestWithDomainControlEnabled
     : public BackForwardCacheBrowserTest {
  protected:
-  base::FieldTrialParams GetFeatureParams() override {
+  void SetUpCommandLine(base::CommandLine* command_line) override {
     // Sets the allowed websites for testing, additionally adding the params
     // used by BackForwardCacheBrowserTest.
-    std::map<std::string, std::string> domain_control_params = {
-        {"allowed_websites",
-         "https://a.allowed/back_forward_cache/, "
-         "https://b.allowed/back_forward_cache/allowed_path.html"}};
-    std::map<std::string, std::string> browser_test_params =
-        BackForwardCacheBrowserTest::GetFeatureParams();
-    domain_control_params.insert(browser_test_params.begin(),
-                                 browser_test_params.end());
-    return domain_control_params;
+    std::string allowed_websites =
+        "https://a.allowed/back_forward_cache/, "
+        "https://b.allowed/back_forward_cache/allowed_path.html";
+    EnableFeatureAndSetParams(features::kBackForwardCache, "allowed_websites",
+                              allowed_websites);
+
+    BackForwardCacheBrowserTest::SetUpCommandLine(command_line);
   }
 };
 
@@ -3986,4 +4025,83 @@
                 FROM_HERE);
 }
 
+// Test for functionality of memory controls in back-forward cache for low
+// memory devices.
+class BackForwardCacheBrowserTestForLowMemoryDevices
+    : public BackForwardCacheBrowserTest {
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    // Set the value of memory threshold more than the physical memory and check
+    // if back-forward cache is disabled or not.
+    std::string memory_threshold =
+        base::NumberToString(base::SysInfo::AmountOfPhysicalMemoryMB() + 1);
+    EnableFeatureAndSetParams(features::kBackForwardCacheMemoryControl,
+                              "memory_threshold_for_back_forward_cache_in_mb",
+                              memory_threshold);
+
+    BackForwardCacheBrowserTest::SetUpCommandLine(command_line);
+  }
+};
+
+// Navigate from A to B and go back.
+IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTestForLowMemoryDevices,
+                       DisableBFCacheForLowEndDevices) {
+  EXPECT_FALSE(IsBackForwardCacheEnabled());
+  ASSERT_TRUE(embedded_test_server()->Start());
+  const GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  const GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
+
+  // 1) Navigate to A.
+  EXPECT_TRUE(NavigateToURL(shell(), url_a));
+  RenderFrameHostImpl* rfh_a = current_frame_host();
+  RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a);
+
+  // 2) Navigate to B.
+  EXPECT_TRUE(NavigateToURL(shell(), url_b));
+
+  // 3) A shouldn't be stored in back-forward cache because the physical
+  // memory is less than the memory threshold.
+  delete_observer_rfh_a.WaitUntilDeleted();
+
+  // Nothing is recorded when the memory is less than the threshold value.
+  ExpectOutcomeDidNotChange(FROM_HERE);
+  ExpectNotRestoredDidNotChange(FROM_HERE);
+}
+
+// Test for functionality of memory controls in back-forward cache for high
+// memory devices.
+class BackForwardCacheBrowserTestForHighMemoryDevices
+    : public BackForwardCacheBrowserTest {
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    // Set the value of memory threshold less than the physical memory and check
+    // if back-forward cache is enabled or not.
+    std::string memory_threshold =
+        base::NumberToString(base::SysInfo::AmountOfPhysicalMemoryMB() - 1);
+    EnableFeatureAndSetParams(features::kBackForwardCacheMemoryControl,
+                              "memory_threshold_for_back_forward_cache_in_mb",
+                              memory_threshold);
+
+    BackForwardCacheBrowserTest::SetUpCommandLine(command_line);
+  }
+};
+
+// Navigate from A to B and go back.
+IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTestForHighMemoryDevices,
+                       EnableBFCacheForHighMemoryDevices) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  const GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  const GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
+
+  // 1) Navigate to A.
+  EXPECT_TRUE(NavigateToURL(shell(), url_a));
+  RenderFrameHostImpl* rfh_a = current_frame_host();
+
+  // 2) Navigate to B.
+  EXPECT_TRUE(NavigateToURL(shell(), url_b));
+
+  // 3) A should be stored in back-forward cache because the physical memory is
+  // greater than the memory threshold.
+  EXPECT_TRUE(rfh_a->is_in_back_forward_cache());
+}
 }  // namespace content
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 8e89e441..112382f 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -2897,12 +2897,6 @@
         rfh, blink::mojom::WebFeature::kDownloadWithoutUserGesture);
   }
 
-  // Log UseCounters for download in sandbox without user activation.
-  if (download_policy.IsType(NavigationDownloadType::kSandboxNoGesture)) {
-    GetContentClient()->browser()->LogWebFeatureForCurrentPage(
-        rfh, blink::mojom::WebFeature::kDownloadInSandboxWithoutUserGesture);
-  }
-
   // Log UseCounters for download in ad frame without user activation.
   if (download_policy.IsType(NavigationDownloadType::kAdFrameNoGesture)) {
     GetContentClient()->browser()->LogWebFeatureForCurrentPage(
diff --git a/content/browser/loader/OWNERS b/content/browser/loader/OWNERS
index 42dffa71..ceb37107 100644
--- a/content/browser/loader/OWNERS
+++ b/content/browser/loader/OWNERS
@@ -1,6 +1,5 @@
 csharrison@chromium.org
 mmenke@chromium.org
-yhirano@chromium.org
 
 # TEAM: net-dev@chromium.org
 # COMPONENT: Internals>Network
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
index ba6df5f..4dcb1247 100644
--- a/content/browser/loader/navigation_url_loader_impl.cc
+++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -35,6 +35,7 @@
 #include "content/browser/loader/prefetch_url_loader_service.h"
 #include "content/browser/loader/single_request_url_loader_factory.h"
 #include "content/browser/navigation_subresource_loader_params.h"
+#include "content/browser/service_worker/service_worker_container_host.h"
 #include "content/browser/service_worker/service_worker_navigation_handle.h"
 #include "content/browser/service_worker/service_worker_navigation_handle_core.h"
 #include "content/browser/service_worker/service_worker_provider_host.h"
@@ -1077,7 +1078,7 @@
                       base::WeakPtr<ServiceWorkerProviderHost> host =
                           core->provider_host();
                       if (host) {
-                        host->SetControllerRegistration(
+                        host->container_host()->SetControllerRegistration(
                             nullptr, false /* notify_controllerchange */);
                         host->UpdateUrls(GURL(), GURL(), base::nullopt);
                       }
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index 2b35a16d..729fa8f 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -42,6 +42,7 @@
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/service_worker/embedded_worker_instance.h"
 #include "content/browser/service_worker/embedded_worker_status.h"
+#include "content/browser/service_worker/service_worker_container_host.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_core_observer.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -719,8 +720,8 @@
         wrapper()->context()->AsWeakPtr(), &remote_endpoints_.back());
     const GURL url = embedded_test_server()->GetURL("/service_worker/host");
     host->UpdateUrls(url, url, url::Origin::Create(url));
-    host->SetControllerRegistration(registration_,
-                                    false /* notify_controllerchange */);
+    host->container_host()->SetControllerRegistration(
+        registration_, false /* notify_controllerchange */);
   }
 
   void AddWaitingWorkerOnCoreThread(const std::string& worker_url) {
diff --git a/content/browser/service_worker/service_worker_cache_writer.cc b/content/browser/service_worker/service_worker_cache_writer.cc
index 6ec47bf..835b800 100644
--- a/content/browser/service_worker/service_worker_cache_writer.cc
+++ b/content/browser/service_worker/service_worker_cache_writer.cc
@@ -8,9 +8,9 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/memory/ptr_util.h"
 #include "content/browser/appcache/appcache_response.h"
 #include "content/browser/service_worker/service_worker_disk_cache.h"
-#include "content/browser/service_worker/service_worker_storage.h"
 
 namespace {
 
diff --git a/content/browser/service_worker/service_worker_client_utils.cc b/content/browser/service_worker/service_worker_client_utils.cc
index 873e08ea..3554ce5 100644
--- a/content/browser/service_worker/service_worker_client_utils.cc
+++ b/content/browser/service_worker/service_worker_client_utils.cc
@@ -330,9 +330,9 @@
   }
   if (!host->container_host()->is_execution_ready())
     return;
-  client_info->push_back(std::make_tuple(host->process_id(), host->frame_id(),
-                                         host->create_time(),
-                                         host->client_uuid()));
+  client_info->push_back(
+      std::make_tuple(host->process_id(), host->frame_id(), host->create_time(),
+                      host->container_host()->client_uuid()));
 }
 
 void AddNonWindowClient(ServiceWorkerProviderHost* host,
@@ -353,8 +353,8 @@
   // DedicatedWorkerHost. crbug.com/968417
   auto client_info = blink::mojom::ServiceWorkerClientInfo::New(
       host->container_host()->url(),
-      network::mojom::RequestContextFrameType::kNone, host->client_uuid(),
-      host_client_type,
+      network::mojom::RequestContextFrameType::kNone,
+      host->container_host()->client_uuid(), host_client_type,
       /*page_hidden=*/true,
       /*is_focused=*/false,
       blink::mojom::ServiceWorkerClientLifecycleState::kActive,
@@ -530,7 +530,8 @@
   if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) {
     blink::mojom::ServiceWorkerClientInfoPtr info = GetWindowClientInfoOnUI(
         provider_host->process_id(), provider_host->frame_id(),
-        provider_host->create_time(), provider_host->client_uuid());
+        provider_host->create_time(),
+        provider_host->container_host()->client_uuid());
     std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk,
                             std::move(info));
 
@@ -539,7 +540,7 @@
         FROM_HERE, {BrowserThread::UI},
         base::BindOnce(&GetWindowClientInfoOnUI, provider_host->process_id(),
                        provider_host->frame_id(), provider_host->create_time(),
-                       provider_host->client_uuid()),
+                       provider_host->container_host()->client_uuid()),
         base::BindOnce(std::move(callback),
                        blink::ServiceWorkerStatusCode::kOk));
   }
@@ -556,14 +557,15 @@
   if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) {
     blink::mojom::ServiceWorkerClientInfoPtr info =
         FocusOnUI(provider_host->process_id(), provider_host->frame_id(),
-                  provider_host->create_time(), provider_host->client_uuid());
+                  provider_host->create_time(),
+                  provider_host->container_host()->client_uuid());
     std::move(callback).Run(std::move(info));
   } else {
     base::PostTaskAndReplyWithResult(
         FROM_HERE, {BrowserThread::UI},
         base::BindOnce(&FocusOnUI, provider_host->process_id(),
                        provider_host->frame_id(), provider_host->create_time(),
-                       provider_host->client_uuid()),
+                       provider_host->container_host()->client_uuid()),
         std::move(callback));
   }
 }
@@ -617,7 +619,8 @@
     if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) {
       blink::mojom::ServiceWorkerClientInfoPtr info = GetWindowClientInfoOnUI(
           provider_host->process_id(), provider_host->frame_id(),
-          provider_host->create_time(), provider_host->client_uuid());
+          provider_host->create_time(),
+          provider_host->container_host()->client_uuid());
       base::ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE, base::BindOnce(std::move(callback), std::move(info)));
       return;
@@ -626,7 +629,7 @@
         FROM_HERE, BrowserThread::UI,
         base::BindOnce(&GetWindowClientInfoOnUI, provider_host->process_id(),
                        provider_host->frame_id(), provider_host->create_time(),
-                       provider_host->client_uuid()),
+                       provider_host->container_host()->client_uuid()),
         std::move(callback));
     return;
   }
@@ -636,7 +639,7 @@
   auto client_info = blink::mojom::ServiceWorkerClientInfo::New(
       provider_host->container_host()->url(),
       network::mojom::RequestContextFrameType::kNone,
-      provider_host->client_uuid(),
+      provider_host->container_host()->client_uuid(),
       provider_host->container_host()->client_type(),
       /*page_hidden=*/true,
       /*is_focused=*/false,
@@ -705,14 +708,16 @@
         provider_host->container_host();
     DCHECK(container_host->is_response_committed());
     if (!container_host->is_execution_ready()) {
-      container_host->AddExecutionReadyCallback(base::BindOnce(
-          &DidGetExecutionReadyClient, context, provider_host->client_uuid(),
-          origin, std::move(callback)));
+      container_host->AddExecutionReadyCallback(
+          base::BindOnce(&DidGetExecutionReadyClient, context,
+                         provider_host->container_host()->client_uuid(), origin,
+                         std::move(callback)));
       return;
     }
 
-    DidGetExecutionReadyClient(context, provider_host->client_uuid(), origin,
-                               std::move(callback));
+    DidGetExecutionReadyClient(context,
+                               provider_host->container_host()->client_uuid(),
+                               origin, std::move(callback));
     return;
   }
 
diff --git a/content/browser/service_worker/service_worker_container_host.cc b/content/browser/service_worker/service_worker_container_host.cc
index 262d2cca..9065291 100644
--- a/content/browser/service_worker/service_worker_container_host.cc
+++ b/content/browser/service_worker/service_worker_container_host.cc
@@ -4,11 +4,13 @@
 
 #include "content/browser/service_worker/service_worker_container_host.h"
 
+#include "base/guid.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_object_host.h"
 #include "content/browser/service_worker/service_worker_registration.h"
 #include "content/browser/service_worker/service_worker_registration_object_host.h"
+#include "content/browser/web_contents/frame_tree_node_id_registry.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/origin_util.h"
@@ -29,12 +31,20 @@
 ServiceWorkerContainerHost::ServiceWorkerContainerHost(
     blink::mojom::ServiceWorkerProviderType type,
     bool is_parent_frame_secure,
+    int frame_tree_node_id,
     mojo::PendingAssociatedRemote<blink::mojom::ServiceWorkerContainer>
         container_remote,
     ServiceWorkerProviderHost* provider_host,
     base::WeakPtr<ServiceWorkerContextCore> context)
     : type_(type),
       is_parent_frame_secure_(is_parent_frame_secure),
+      frame_tree_node_id_(frame_tree_node_id),
+      web_contents_getter_(
+          frame_tree_node_id == FrameTreeNode::kFrameTreeNodeInvalidId
+              ? base::NullCallback()
+              : base::BindRepeating(&WebContents::FromFrameTreeNodeId,
+                                    frame_tree_node_id)),
+      client_uuid_(base::GenerateGUID()),
       provider_host_(provider_host),
       context_(std::move(context)) {
   DCHECK(provider_host_);
@@ -48,10 +58,31 @@
 }
 
 ServiceWorkerContainerHost::~ServiceWorkerContainerHost() {
+  if (fetch_request_window_id_)
+    FrameTreeNodeIdRegistry::GetInstance()->Remove(fetch_request_window_id_);
+
+  if (controller_)
+    controller_->OnControlleeDestroyed(client_uuid_);
+
+  // Remove |provider_host_| as an observer of ServiceWorkerRegistrations.
+  // TODO(falken): Use ScopedObserver instead of this explicit call.
+  controller_.reset();
+  controller_registration_.reset();
+
   // Ensure callbacks awaiting execution ready are notified.
   RunExecutionReadyCallbacks();
 }
 
+void ServiceWorkerContainerHost::OnSkippedWaiting(
+    ServiceWorkerRegistration* registration) {
+  DCHECK(controller_);
+  ServiceWorkerVersion* active = controller_registration_->active_version();
+  DCHECK(active);
+  DCHECK_NE(active, controller_.get());
+  DCHECK_EQ(active->status(), ServiceWorkerVersion::ACTIVATING);
+  UpdateController(true /* notify_controllerchange */);
+}
+
 void ServiceWorkerContainerHost::PostMessageToClient(
     ServiceWorkerVersion* version,
     blink::TransferableMessage message) {
@@ -79,13 +110,71 @@
 }
 
 void ServiceWorkerContainerHost::SendSetControllerServiceWorker(
-    blink::mojom::ControllerServiceWorkerInfoPtr controller_info,
     bool notify_controllerchange) {
   DCHECK(IsContainerForClient());
+
+  auto controller_info = blink::mojom::ControllerServiceWorkerInfo::New();
+  controller_info->client_id = client_uuid_;
+  // Set |fetch_request_window_id| only when |controller_| is available.
+  // Setting |fetch_request_window_id| should not affect correctness, however,
+  // we have the extensions bug, https://crbug.com/963748, which we don't yet
+  // understand.  That is why we don't set |fetch_request_window_id| if there
+  // is no controller, at least, until we can fix the extension bug.
+  if (controller_ && fetch_request_window_id_) {
+    controller_info->fetch_request_window_id =
+        base::make_optional(fetch_request_window_id_);
+  }
+
+  if (!controller_) {
+    container_->SetController(std::move(controller_info),
+                              notify_controllerchange);
+    return;
+  }
+
+  DCHECK(controller_registration());
+  DCHECK_EQ(controller_registration_->active_version(), controller_.get());
+
+  controller_info->mode = GetControllerMode();
+
+  // Pass an endpoint for the client to talk to this controller.
+  mojo::Remote<blink::mojom::ControllerServiceWorker> remote =
+      provider_host_->GetRemoteControllerServiceWorker();
+  if (remote.is_bound()) {
+    controller_info->remote_controller = remote.Unbind();
+  }
+
+  // Set the info for the JavaScript ServiceWorkerContainer#controller object.
+  base::WeakPtr<ServiceWorkerObjectHost> object_host =
+      GetOrCreateServiceWorkerObjectHost(controller_);
+  if (object_host) {
+    controller_info->object_info =
+        object_host->CreateCompleteObjectInfoToSend();
+  }
+
+  // Populate used features for UseCounter purposes.
+  for (const blink::mojom::WebFeature feature : controller_->used_features())
+    controller_info->used_features.push_back(feature);
+
   container_->SetController(std::move(controller_info),
                             notify_controllerchange);
 }
 
+void ServiceWorkerContainerHost::ClaimedByRegistration(
+    scoped_refptr<ServiceWorkerRegistration> registration) {
+  DCHECK(IsContainerForClient());
+  DCHECK(registration->active_version());
+  DCHECK(is_execution_ready());
+
+  // TODO(falken): This should just early return, or DCHECK. claim() should have
+  // no effect on a page that's already using the registration.
+  if (registration == controller_registration_) {
+    UpdateController(true /* notify_controllerchange */);
+    return;
+  }
+
+  SetControllerRegistration(registration, true /* notify_controllerchange */);
+}
+
 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr
 ServiceWorkerContainerHost::CreateServiceWorkerRegistrationObjectInfo(
     scoped_refptr<ServiceWorkerRegistration> registration) {
@@ -185,10 +274,70 @@
     const GURL& url,
     const GURL& site_for_cookies,
     const base::Optional<url::Origin>& top_frame_origin) {
+  GURL previous_url = url_;
+
   DCHECK(!url.has_ref());
   url_ = url;
   site_for_cookies_ = site_for_cookies;
   top_frame_origin_ = top_frame_origin;
+
+  if (previous_url != url) {
+    // Revoke the token on URL change since any service worker holding the token
+    // may no longer be the potential controller of this frame and shouldn't
+    // have the power to display SSL dialogs for it.
+    if (type_ == blink::mojom::ServiceWorkerProviderType::kForWindow) {
+      auto* registry = FrameTreeNodeIdRegistry::GetInstance();
+      registry->Remove(fetch_request_window_id_);
+      fetch_request_window_id_ = base::UnguessableToken::Create();
+      registry->Add(fetch_request_window_id_, frame_tree_node_id_);
+    }
+  }
+
+  auto previous_origin = url::Origin::Create(previous_url);
+  auto new_origin = url::Origin::Create(url);
+  // Update client id on cross origin redirects. This corresponds to the HTML
+  // standard's "process a navigation fetch" algorithm's step for discarding
+  // |reservedEnvironment|.
+  // https://html.spec.whatwg.org/multipage/browsing-the-web.html#process-a-navigate-fetch
+  // "If |reservedEnvironment| is not null and |currentURL|'s origin is not the
+  // same as |reservedEnvironment|'s creation URL's origin, then:
+  //    1. Run the environment discarding steps for |reservedEnvironment|.
+  //    2. Set |reservedEnvironment| to null."
+  if (previous_url.is_valid() &&
+      !new_origin.IsSameOriginWith(previous_origin)) {
+    // Remove old controller since we know the controller is definitely
+    // changed. We need to remove |this| from |controller_|'s controllee before
+    // updating UUID since ServiceWorkerVersion has a map from uuid to provider
+    // hosts.
+    SetControllerRegistration(nullptr, false /* notify_controllerchange */);
+
+    // Set UUID to the new one.
+    if (context_)
+      context_->UnregisterProviderHostByClientID(client_uuid_);
+    client_uuid_ = base::GenerateGUID();
+    if (context_)
+      context_->RegisterProviderHostByClientID(client_uuid_, provider_host_);
+  }
+}
+
+void ServiceWorkerContainerHost::SetControllerRegistration(
+    scoped_refptr<ServiceWorkerRegistration> controller_registration,
+    bool notify_controllerchange) {
+  DCHECK(IsContainerForClient());
+
+  if (controller_registration) {
+    CHECK(IsContextSecureForServiceWorker());
+    DCHECK(controller_registration->active_version());
+#if DCHECK_IS_ON()
+    // TODO(https://crbug.com/931087): Enable this check again after
+    // IsMatchingRegistration() is moved from ServiceWorkerProviderHost to
+    // ServiceWorkerContainerHost.
+    // DCHECK(IsMatchingRegistration(controller_registration.get()));
+#endif  // DCHECK_IS_ON()
+  }
+
+  controller_registration_ = controller_registration;
+  UpdateController(notify_controllerchange);
 }
 
 bool ServiceWorkerContainerHost::AllowServiceWorker(const GURL& scope,
@@ -306,6 +455,40 @@
   return true;
 }
 
+blink::mojom::ControllerServiceWorkerMode
+ServiceWorkerContainerHost::GetControllerMode() const {
+  DCHECK(IsContainerForClient());
+  if (!controller_)
+    return blink::mojom::ControllerServiceWorkerMode::kNoController;
+  switch (controller_->fetch_handler_existence()) {
+    case ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST:
+      return blink::mojom::ControllerServiceWorkerMode::kNoFetchEventHandler;
+    case ServiceWorkerVersion::FetchHandlerExistence::EXISTS:
+      return blink::mojom::ControllerServiceWorkerMode::kControlled;
+    case ServiceWorkerVersion::FetchHandlerExistence::UNKNOWN:
+      // UNKNOWN means the controller is still installing. It's not possible to
+      // have a controller that hasn't finished installing.
+      NOTREACHED();
+  }
+  NOTREACHED();
+  return blink::mojom::ControllerServiceWorkerMode::kNoController;
+}
+
+ServiceWorkerVersion* ServiceWorkerContainerHost::controller() const {
+#if DCHECK_IS_ON()
+  CheckControllerConsistency(false);
+#endif  // DCHECK_IS_ON()
+  return controller_.get();
+}
+
+ServiceWorkerRegistration* ServiceWorkerContainerHost::controller_registration()
+    const {
+#if DCHECK_IS_ON()
+  CheckControllerConsistency(false);
+#endif  // DCHECK_IS_ON()
+  return controller_registration_.get();
+}
+
 void ServiceWorkerContainerHost::RunExecutionReadyCallbacks() {
   std::vector<ExecutionReadyCallback> callbacks;
   execution_ready_callbacks_.swap(callbacks);
@@ -313,4 +496,70 @@
       FROM_HERE, base::BindOnce(&RunCallbacks, std::move(callbacks)));
 }
 
+void ServiceWorkerContainerHost::UpdateController(
+    bool notify_controllerchange) {
+  ServiceWorkerVersion* version =
+      controller_registration_ ? controller_registration_->active_version()
+                               : nullptr;
+  CHECK(!version || IsContextSecureForServiceWorker());
+  if (version == controller_.get())
+    return;
+
+  scoped_refptr<ServiceWorkerVersion> previous_version = controller_;
+  controller_ = version;
+
+  if (version)
+    version->AddControllee(provider_host_);
+  if (previous_version)
+    previous_version->RemoveControllee(client_uuid_);
+
+  // SetController message should be sent only for clients.
+  DCHECK(IsContainerForClient());
+
+  if (!IsControllerDecided())
+    return;
+
+  SendSetControllerServiceWorker(notify_controllerchange);
+}
+
+#if DCHECK_IS_ON()
+void ServiceWorkerContainerHost::CheckControllerConsistency(
+    bool should_crash) const {
+  if (!controller_) {
+    DCHECK(!controller_registration_);
+    return;
+  }
+
+  DCHECK(IsContainerForClient());
+  DCHECK(controller_registration_);
+  DCHECK_EQ(controller_->registration_id(), controller_registration_->id());
+
+  switch (controller_->status()) {
+    case ServiceWorkerVersion::NEW:
+    case ServiceWorkerVersion::INSTALLING:
+    case ServiceWorkerVersion::INSTALLED:
+      if (should_crash) {
+        ServiceWorkerVersion::Status status = controller_->status();
+        base::debug::Alias(&status);
+        CHECK(false) << "Controller service worker has a bad status: "
+                     << ServiceWorkerVersion::VersionStatusToString(status);
+      }
+      break;
+    case ServiceWorkerVersion::REDUNDANT: {
+      if (should_crash) {
+        DEBUG_ALIAS_FOR_CSTR(
+            redundant_callstack_str,
+            controller_->redundant_state_callstack().ToString().c_str(), 1024);
+        CHECK(false);
+      }
+      break;
+    }
+    case ServiceWorkerVersion::ACTIVATING:
+    case ServiceWorkerVersion::ACTIVATED:
+      // Valid status, controller is being activated.
+      break;
+  }
+}
+#endif  // DCHECK_IS_ON()
+
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_container_host.h b/content/browser/service_worker/service_worker_container_host.h
index cf4cf940..aa8ac8d 100644
--- a/content/browser/service_worker/service_worker_container_host.h
+++ b/content/browser/service_worker/service_worker_container_host.h
@@ -12,6 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "content/common/content_export.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_container.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h"
@@ -29,6 +30,7 @@
 class ServiceWorkerRegistration;
 class ServiceWorkerRegistrationObjectHost;
 class ServiceWorkerVersion;
+class WebContents;
 
 // ServiceWorkerContainerHost has a 1:1 correspondence to
 // blink::ServiceWorkerContainer (i.e., navigator.serviceWorker) in the renderer
@@ -54,12 +56,14 @@
 class CONTENT_EXPORT ServiceWorkerContainerHost {
  public:
   using ExecutionReadyCallback = base::OnceClosure;
+  using WebContentsGetter = base::RepeatingCallback<WebContents*()>;
 
   // TODO(https://crbug.com/931087): Rename ServiceWorkerProviderType to
   // ServiceWorkerContainerType.
   ServiceWorkerContainerHost(
       blink::mojom::ServiceWorkerProviderType type,
       bool is_parent_frame_secure,
+      int frame_tree_node_id,
       mojo::PendingAssociatedRemote<blink::mojom::ServiceWorkerContainer>
           container_remote,
       ServiceWorkerProviderHost* provider_host,
@@ -73,6 +77,10 @@
   ServiceWorkerContainerHost& operator=(ServiceWorkerContainerHost&& other) =
       delete;
 
+  // TODO(https://crbug.com/931087): OnSkippedWaiting should be implemented as
+  // ServiceWorkerRegistration::Listener override.
+  void OnSkippedWaiting(ServiceWorkerRegistration* registration);
+
   // Dispatches message event to the client (document, dedicated worker when
   // PlzDedicatedWorker is enabled, or shared worker).
   void PostMessageToClient(ServiceWorkerVersion* version,
@@ -85,9 +93,7 @@
   // Sends information about the controller to the container of the service
   // worker clients in the renderer. If |notify_controllerchange| is true,
   // instructs the renderer to dispatch a 'controllerchange' event.
-  void SendSetControllerServiceWorker(
-      blink::mojom::ControllerServiceWorkerInfoPtr controller_info,
-      bool notify_controllerchange);
+  void SendSetControllerServiceWorker(bool notify_controllerchange);
 
   // Returns an object info representing |registration|. The object info holds a
   // Mojo connection to the ServiceWorkerRegistrationObjectHost for the
@@ -139,6 +145,19 @@
                   const GURL& site_for_cookies,
                   const base::Optional<url::Origin>& top_frame_origin);
 
+  // For service worker clients. Makes this client be controlled by
+  // |registration|'s active worker, or makes this client be not
+  // controlled if |registration| is null. If |notify_controllerchange| is true,
+  // instructs the renderer to dispatch a 'controllerchange' event.
+  void SetControllerRegistration(
+      scoped_refptr<ServiceWorkerRegistration> controller_registration,
+      bool notify_controllerchange);
+
+  // |registration| claims the client (document, dedicated worker when
+  // PlzDedicatedWorker is enabled, or shared worker) to be controlled.
+  void ClaimedByRegistration(
+      scoped_refptr<ServiceWorkerRegistration> registration);
+
   // The URL of this context. For service worker clients, this is the document
   // URL (for documents) or script URL (for workers). For service worker
   // execution contexts, this is the script URL.
@@ -234,6 +253,29 @@
   // section.
   bool IsControllerDecided() const;
 
+  const base::UnguessableToken& fetch_request_window_id() const {
+    return fetch_request_window_id_;
+  }
+
+  int frame_tree_node_id() const { return frame_tree_node_id_; }
+
+  const WebContentsGetter& web_contents_getter() const {
+    return web_contents_getter_;
+  }
+
+  const std::string& client_uuid() const { return client_uuid_; }
+
+  // For service worker clients. Describes whether the client has a controller
+  // and if it has a fetch event handler.
+  blink::mojom::ControllerServiceWorkerMode GetControllerMode() const;
+
+  // For service worker clients. Returns this client's controller.
+  ServiceWorkerVersion* controller() const;
+
+  // For service worker clients. Returns this client's controller's
+  // registration.
+  ServiceWorkerRegistration* controller_registration() const;
+
  private:
   friend class service_worker_object_host_unittest::ServiceWorkerObjectHostTest;
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerJobTest, Unregister);
@@ -245,6 +287,17 @@
 
   void RunExecutionReadyCallbacks();
 
+  // Sets the controller to |controller_registration_->active_version()| or null
+  // if there is no associated registration.
+  //
+  // If |notify_controllerchange| is true, instructs the renderer to dispatch a
+  // 'controller' change event.
+  void UpdateController(bool notify_controllerchange);
+
+#if DCHECK_IS_ON()
+  void CheckControllerConsistency(bool should_crash) const;
+#endif  // DCHECK_IS_ON()
+
   const blink::mojom::ServiceWorkerProviderType type_;
 
   // See comments for the getter functions.
@@ -252,6 +305,16 @@
   GURL site_for_cookies_;
   base::Optional<url::Origin> top_frame_origin_;
 
+  // For window clients. A token used internally to identify this context in
+  // requests. Corresponds to the Fetch specification's concept of a request's
+  // associated window: https://fetch.spec.whatwg.org/#concept-request-window
+  // This gets reset on redirects, unlike |client_uuid_|.
+  //
+  // TODO(falken): Consider using this for |client_uuid_| as well. We can't
+  // right now because this gets reset on redirects, and potentially sites rely
+  // on the GUID format.
+  base::UnguessableToken fetch_request_window_id_;
+
   // |is_parent_frame_secure_| is false if the container host is created for a
   // document whose parent frame is not secure. This doesn't mean the document
   // is necessarily an insecure context, because the document may have a URL
@@ -261,6 +324,17 @@
   // true.
   const bool is_parent_frame_secure_;
 
+  // FrameTreeNode id if this is a service worker window client.
+  // Otherwise, |FrameTreeNode::kFrameTreeNodeInvalidId|.
+  const int frame_tree_node_id_;
+
+  // Only set when this object is pre-created for a navigation. It indicates the
+  // tab where the navigation occurs. Otherwise, a null callback.
+  const WebContentsGetter web_contents_getter_;
+
+  // A GUID that is web-exposed as FetchEvent.clientId.
+  std::string client_uuid_;
+
   // For service worker clients.
   ClientPhase client_phase_ = ClientPhase::kInitial;
 
@@ -268,6 +342,16 @@
   // kExecutionReady.
   std::vector<ExecutionReadyCallback> execution_ready_callbacks_;
 
+  // For service worker clients. The controller service worker (i.e.,
+  // ServiceWorkerContainer#controller) and its registration. The controller is
+  // typically the same as the registration's active version, but during
+  // algorithms such as the update, skipWaiting(), and claim() steps, the active
+  // version and controller may temporarily differ. For example, to perform
+  // skipWaiting(), the registration's active version is updated first and then
+  // the container host's controller is updated to match it.
+  scoped_refptr<ServiceWorkerVersion> controller_;
+  scoped_refptr<ServiceWorkerRegistration> controller_registration_;
+
   // Contains all ServiceWorkerRegistrationObjectHost instances corresponding to
   // the service worker registration JavaScript objects for the hosted execution
   // context (service worker global scope or service worker client) in the
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc
index 277d512..60bad67 100644
--- a/content/browser/service_worker/service_worker_context_core.cc
+++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -32,7 +32,6 @@
 #include "content/browser/service_worker/service_worker_provider_host.h"
 #include "content/browser/service_worker/service_worker_register_job.h"
 #include "content/browser/service_worker/service_worker_registration.h"
-#include "content/browser/service_worker/service_worker_storage.h"
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/browser/storage_partition_impl.h"
 #include "content/browser/url_loader_factory_getter.h"
diff --git a/content/browser/service_worker/service_worker_context_unittest.cc b/content/browser/service_worker/service_worker_context_unittest.cc
index fed80a1..621263c 100644
--- a/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/time/time.h"
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
 #include "content/browser/service_worker/fake_embedded_worker_instance_client.h"
+#include "content/browser/service_worker/service_worker_container_host.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_core_observer.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -414,7 +415,7 @@
 
   TestServiceWorkerContextObserver observer(context_wrapper());
 
-  version->RemoveControllee(host->client_uuid());
+  version->RemoveControllee(host->container_host()->client_uuid());
   base::RunLoop().RunUntilIdle();
 
   ASSERT_EQ(1u, observer.events().size());
diff --git a/content/browser/service_worker/service_worker_context_wrapper_unittest.cc b/content/browser/service_worker/service_worker_context_wrapper_unittest.cc
index 46ca2fd..eb2cc6c 100644
--- a/content/browser/service_worker/service_worker_context_wrapper_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_wrapper_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/run_loop.h"
 #include "base/test/bind_test_util.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
-#include "content/browser/service_worker/service_worker_database.h"
 #include "content/browser/service_worker/service_worker_registration.h"
 #include "content/browser/service_worker/service_worker_test_utils.h"
 #include "content/browser/service_worker/service_worker_version.h"
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc
index 8a351219..b8e77a1 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -90,7 +90,7 @@
 }
 
 void ServiceWorkerControlleeRequestHandler::MaybeScheduleUpdate() {
-  if (!provider_host_ || !provider_host_->controller())
+  if (!provider_host_ || !provider_host_->container_host()->controller())
     return;
 
   // For navigations, the update logic is taken care of
@@ -107,7 +107,7 @@
   if (force_update_started_)
     return;
 
-  provider_host_->controller()->ScheduleUpdate();
+  provider_host_->container_host()->controller()->ScheduleUpdate();
 }
 
 void ServiceWorkerControlleeRequestHandler::MaybeCreateLoader(
@@ -177,14 +177,15 @@
   // ContinueWithRegistration() for the request didn't find a matching service
   // worker for this request, and
   // ServiceWorkerProviderHost::SetControllerRegistration() was not called.
-  if (!provider_host_ || !provider_host_->controller())
+  if (!provider_host_ || !provider_host_->container_host()->controller())
     return base::nullopt;
+  ServiceWorkerContainerHost* container_host = provider_host_->container_host();
 
   // Otherwise let's send the controller service worker information along
   // with the navigation commit.
   SubresourceLoaderParams params;
   auto controller_info = blink::mojom::ControllerServiceWorkerInfo::New();
-  controller_info->mode = provider_host_->GetControllerMode();
+  controller_info->mode = container_host->GetControllerMode();
   // Note that |controller_info->remote_controller| is null if the controller
   // has no fetch event handler. In that case the renderer frame won't get the
   // controller pointer upon the navigation commit, and subresource loading will
@@ -196,19 +197,19 @@
     controller_info->remote_controller = remote.Unbind();
   }
 
-  controller_info->client_id = provider_host_->client_uuid();
-  if (provider_host_->fetch_request_window_id()) {
+  controller_info->client_id = container_host->client_uuid();
+  if (container_host->fetch_request_window_id()) {
     controller_info->fetch_request_window_id =
-        base::make_optional(provider_host_->fetch_request_window_id());
+        base::make_optional(container_host->fetch_request_window_id());
   }
   base::WeakPtr<ServiceWorkerObjectHost> object_host =
-      provider_host_->container_host()->GetOrCreateServiceWorkerObjectHost(
-          provider_host_->controller());
+      container_host->GetOrCreateServiceWorkerObjectHost(
+          container_host->controller());
   if (object_host) {
     params.controller_service_worker_object_host = object_host;
     controller_info->object_info = object_host->CreateIncompleteObjectInfo();
   }
-  for (const auto feature : provider_host_->controller()->used_features()) {
+  for (const auto feature : container_host->controller()->used_features()) {
     controller_info->used_features.push_back(feature);
   }
   params.controller_service_worker_info = std::move(controller_info);
@@ -225,8 +226,9 @@
 
   // Update the provider host with this request, clearing old controller state
   // if this is a redirect.
-  provider_host_->SetControllerRegistration(nullptr,
-                                            /*notify_controllerchange=*/false);
+  provider_host_->container_host()->SetControllerRegistration(
+      nullptr,
+      /*notify_controllerchange=*/false);
   stripped_url_ = net::SimplifyUrlForRequest(tentative_resource_request.url);
   provider_host_->UpdateUrls(
       stripped_url_, tentative_resource_request.site_for_cookies,
@@ -285,13 +287,13 @@
         GetContentClient()->browser()->AllowServiceWorkerOnUI(
             registration->scope(), container_host->site_for_cookies(),
             container_host->top_frame_origin(), /*script_url=*/GURL(),
-            browser_context_, provider_host_->web_contents_getter());
+            browser_context_, container_host->web_contents_getter());
   } else {
     allow_service_worker =
         GetContentClient()->browser()->AllowServiceWorkerOnIO(
             registration->scope(), container_host->site_for_cookies(),
             container_host->top_frame_origin(), /*script_url=*/GURL(),
-            resource_context_, provider_host_->web_contents_getter());
+            resource_context_, container_host->web_contents_getter());
   }
 
   if (!allow_service_worker) {
@@ -432,11 +434,11 @@
     return;
   }
 
-  provider_host_->SetControllerRegistration(
+  provider_host_->container_host()->SetControllerRegistration(
       registration, false /* notify_controllerchange */);
 
   DCHECK_EQ(active_version, registration->active_version());
-  DCHECK_EQ(active_version, provider_host_->controller());
+  DCHECK_EQ(active_version, provider_host_->container_host()->controller());
   DCHECK_NE(active_version->fetch_handler_existence(),
             ServiceWorkerVersion::FetchHandlerExistence::UNKNOWN);
   ServiceWorkerMetrics::CountControlledPageLoad(
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
index 9b57752..6129fb0 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -352,7 +352,7 @@
   // claim().
   EXPECT_FALSE(test_resources.loader());
   EXPECT_FALSE(version_->HasControllee());
-  EXPECT_FALSE(provider_host_->controller());
+  EXPECT_FALSE(provider_host_->container_host()->controller());
   EXPECT_EQ(registration_.get(), provider_host_->MatchRegistration());
 }
 
diff --git a/content/browser/service_worker/service_worker_database.cc b/content/browser/service_worker/service_worker_database.cc
index 34ef33c7..d9ed896 100644
--- a/content/browser/service_worker/service_worker_database.cc
+++ b/content/browser/service_worker/service_worker_database.cc
@@ -202,8 +202,7 @@
                             base::NumberToString(registration_id).c_str());
 }
 
-void PutUniqueOriginToBatch(const GURL& origin,
-                            leveldb::WriteBatch* batch) {
+void PutUniqueOriginToBatch(const GURL& origin, leveldb::WriteBatch* batch) {
   // Value should be empty.
   batch->Put(CreateUniqueOriginKey(origin), "");
 }
@@ -254,7 +253,7 @@
 }  // namespace
 
 const char* ServiceWorkerDatabase::StatusToString(
-  ServiceWorkerDatabase::Status status) {
+    ServiceWorkerDatabase::Status status) {
   switch (status) {
     case ServiceWorkerDatabase::STATUS_OK:
       return "Database OK";
@@ -288,8 +287,7 @@
 ServiceWorkerDatabase::RegistrationData::RegistrationData(
     const RegistrationData& other) = default;
 
-ServiceWorkerDatabase::RegistrationData::~RegistrationData() {
-}
+ServiceWorkerDatabase::RegistrationData::~RegistrationData() = default;
 
 ServiceWorkerDatabase::ServiceWorkerDatabase(const base::FilePath& path)
     : path_(path),
@@ -297,11 +295,11 @@
       next_avail_resource_id_(0),
       next_avail_version_id_(0),
       state_(DATABASE_STATE_UNINITIALIZED) {
-  sequence_checker_.DetachFromSequence();
+  DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
 ServiceWorkerDatabase::~ServiceWorkerDatabase() {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   db_.reset();
 }
 
@@ -309,7 +307,7 @@
     int64_t* next_avail_registration_id,
     int64_t* next_avail_version_id,
     int64_t* next_avail_resource_id) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(next_avail_registration_id);
   DCHECK(next_avail_version_id);
   DCHECK(next_avail_resource_id);
@@ -345,7 +343,7 @@
 
 ServiceWorkerDatabase::Status
 ServiceWorkerDatabase::GetOriginsWithRegistrations(std::set<GURL>* origins) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(origins->empty());
 
   Status status = LazyOpen(false);
@@ -390,7 +388,7 @@
     const GURL& origin,
     std::vector<RegistrationData>* registrations,
     std::vector<std::vector<ResourceRecord>>* opt_resources_list) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(registrations->empty());
 
   Status status = LazyOpen(false);
@@ -459,7 +457,7 @@
 
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetAllRegistrations(
     std::vector<RegistrationData>* registrations) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(registrations->empty());
 
   Status status = LazyOpen(false);
@@ -502,7 +500,7 @@
     const GURL& origin,
     RegistrationData* registration,
     std::vector<ResourceRecord>* resources) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(registration);
   DCHECK(resources);
 
@@ -532,7 +530,7 @@
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistrationOrigin(
     int64_t registration_id,
     GURL* origin) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(origin);
 
   Status status = LazyOpen(true);
@@ -568,7 +566,7 @@
     const std::vector<ResourceRecord>& resources,
     RegistrationData* old_registration,
     std::vector<int64_t>* newly_purgeable_resources) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(old_registration);
   DCHECK(!resources.empty());
   Status status = LazyOpen(true);
@@ -614,15 +612,15 @@
   }
 
   // Retrieve a previous version to sweep purgeable resources.
-  status = ReadRegistrationData(registration.registration_id,
-                                registration.scope.GetOrigin(),
-                                old_registration);
+  status =
+      ReadRegistrationData(registration.registration_id,
+                           registration.scope.GetOrigin(), old_registration);
   if (status != STATUS_OK && status != STATUS_ERROR_NOT_FOUND)
     return status;
   if (status == STATUS_OK) {
     DCHECK_LT(old_registration->version_id, registration.version_id);
-    status = DeleteResourceRecords(
-        old_registration->version_id, newly_purgeable_resources, &batch);
+    status = DeleteResourceRecords(old_registration->version_id,
+                                   newly_purgeable_resources, &batch);
     if (status != STATUS_OK)
       return status;
 
@@ -642,7 +640,7 @@
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateVersionToActive(
     int64_t registration_id,
     const GURL& origin) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   Status status = LazyOpen(false);
   if (IsNewOrNonexistentDatabase(status))
     return STATUS_ERROR_NOT_FOUND;
@@ -667,7 +665,7 @@
     int64_t registration_id,
     const GURL& origin,
     const base::Time& time) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   Status status = LazyOpen(false);
   if (IsNewOrNonexistentDatabase(status))
     return STATUS_ERROR_NOT_FOUND;
@@ -692,7 +690,7 @@
 ServiceWorkerDatabase::UpdateNavigationPreloadEnabled(int64_t registration_id,
                                                       const GURL& origin,
                                                       bool enable) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   Status status = LazyOpen(false);
   if (IsNewOrNonexistentDatabase(status))
     return STATUS_ERROR_NOT_FOUND;
@@ -717,7 +715,7 @@
 ServiceWorkerDatabase::UpdateNavigationPreloadHeader(int64_t registration_id,
                                                      const GURL& origin,
                                                      const std::string& value) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   Status status = LazyOpen(false);
   if (IsNewOrNonexistentDatabase(status))
     return STATUS_ERROR_NOT_FOUND;
@@ -743,7 +741,7 @@
     const GURL& origin,
     RegistrationData* deleted_version,
     std::vector<int64_t>* newly_purgeable_resources) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(deleted_version);
   deleted_version->version_id = blink::mojom::kInvalidServiceWorkerVersionId;
   Status status = LazyOpen(false);
@@ -777,8 +775,8 @@
   for (const auto& registration : registrations) {
     if (registration.registration_id == registration_id) {
       *deleted_version = registration;
-      status = DeleteResourceRecords(
-          registration.version_id, newly_purgeable_resources, &batch);
+      status = DeleteResourceRecords(registration.version_id,
+                                     newly_purgeable_resources, &batch);
       if (status != STATUS_OK)
         return status;
 
@@ -796,7 +794,7 @@
     int64_t registration_id,
     const std::vector<std::string>& user_data_names,
     std::vector<std::string>* user_data_values) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
   DCHECK(!user_data_names.empty());
   DCHECK(user_data_values);
@@ -827,7 +825,7 @@
     int64_t registration_id,
     const std::string& user_data_name_prefix,
     std::vector<std::string>* user_data_values) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
   DCHECK(user_data_values);
 
@@ -873,7 +871,7 @@
     int64_t registration_id,
     const std::string& user_data_name_prefix,
     base::flat_map<std::string, std::string>* user_data_map) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
   DCHECK(user_data_map);
 
@@ -923,7 +921,7 @@
     int64_t registration_id,
     const GURL& origin,
     const std::vector<std::pair<std::string, std::string>>& name_value_pairs) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
   DCHECK(!name_value_pairs.empty());
 
@@ -951,7 +949,7 @@
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteUserData(
     int64_t registration_id,
     const std::vector<std::string>& user_data_names) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
   DCHECK(!user_data_names.empty());
 
@@ -975,7 +973,7 @@
     int64_t registration_id,
     const std::vector<std::string>& user_data_name_prefixes) {
   // Example |user_data_name_prefixes| is {"abc", "xyz"}.
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
 
   Status status = LazyOpen(false);
@@ -1025,7 +1023,7 @@
 }
 
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::RewriteDB() {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   Status status = LazyOpen(false);
   if (IsNewOrNonexistentDatabase(status))
@@ -1049,7 +1047,7 @@
 ServiceWorkerDatabase::ReadUserDataForAllRegistrations(
     const std::string& user_data_name,
     std::vector<std::pair<int64_t, std::string>>* user_data) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(user_data->empty());
 
   Status status = LazyOpen(false);
@@ -1102,7 +1100,7 @@
 ServiceWorkerDatabase::ReadUserDataForAllRegistrationsByKeyPrefix(
     const std::string& user_data_name_prefix,
     std::vector<std::pair<int64_t, std::string>>* user_data) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(user_data->empty());
 
   Status status = LazyOpen(false);
@@ -1169,7 +1167,7 @@
 ServiceWorkerDatabase::Status
 ServiceWorkerDatabase::DeleteUserDataForAllRegistrationsByKeyPrefix(
     const std::string& user_data_name_prefix) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   Status status = LazyOpen(false);
   if (IsNewOrNonexistentDatabase(status))
@@ -1221,7 +1219,7 @@
 
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetUncommittedResourceIds(
     std::set<int64_t>* ids) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return ReadResourceIds(service_worker_internals::kUncommittedResIdKeyPrefix,
                          ids);
 }
@@ -1229,7 +1227,7 @@
 ServiceWorkerDatabase::Status
 ServiceWorkerDatabase::WriteUncommittedResourceIds(
     const std::set<int64_t>& ids) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   leveldb::WriteBatch batch;
   Status status = WriteResourceIdsInBatch(
       service_worker_internals::kUncommittedResIdKeyPrefix, ids, &batch);
@@ -1240,14 +1238,14 @@
 
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetPurgeableResourceIds(
     std::set<int64_t>* ids) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return ReadResourceIds(service_worker_internals::kPurgeableResIdKeyPrefix,
                          ids);
 }
 
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ClearPurgeableResourceIds(
     const std::set<int64_t>& ids) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   Status status = LazyOpen(false);
   if (IsNewOrNonexistentDatabase(status))
     return STATUS_OK;
@@ -1263,7 +1261,7 @@
 ServiceWorkerDatabase::Status
 ServiceWorkerDatabase::PurgeUncommittedResourceIds(
     const std::set<int64_t>& ids) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   Status status = LazyOpen(false);
   if (IsNewOrNonexistentDatabase(status))
     return STATUS_OK;
@@ -1283,7 +1281,7 @@
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteAllDataForOrigins(
     const std::set<GURL>& origins,
     std::vector<int64_t>* newly_purgeable_resources) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   Status status = LazyOpen(false);
   if (IsNewOrNonexistentDatabase(status))
     return STATUS_OK;
@@ -1308,8 +1306,8 @@
       batch.Delete(CreateRegistrationKey(data.registration_id, origin));
       batch.Delete(CreateRegistrationIdToOriginKey(data.registration_id));
 
-      status = DeleteResourceRecords(
-          data.version_id, newly_purgeable_resources, &batch);
+      status = DeleteResourceRecords(data.version_id, newly_purgeable_resources,
+                                     &batch);
       if (status != STATUS_OK)
         return status;
 
@@ -1323,7 +1321,7 @@
 }
 
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DestroyDatabase() {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   Disable(FROM_HERE, STATUS_OK);
 
   if (IsDatabaseInMemory()) {
@@ -1342,7 +1340,7 @@
 
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::LazyOpen(
     bool create_if_missing) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Do not try to open a database if we tried and failed once.
   if (state_ == DATABASE_STATE_DISABLED)
@@ -1404,7 +1402,7 @@
 
 bool ServiceWorkerDatabase::IsNewOrNonexistentDatabase(
     ServiceWorkerDatabase::Status status) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (status == STATUS_ERROR_NOT_FOUND)
     return true;
   if (status == STATUS_OK && state_ == DATABASE_STATE_UNINITIALIZED)
@@ -1415,7 +1413,7 @@
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadNextAvailableId(
     const char* id_key,
     int64_t* next_avail_id) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(id_key);
   DCHECK(next_avail_id);
 
@@ -1441,7 +1439,7 @@
     int64_t registration_id,
     const GURL& origin,
     RegistrationData* registration) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(registration);
 
   const std::string key = CreateRegistrationKey(registration_id, origin);
@@ -1449,9 +1447,8 @@
   Status status = LevelDBStatusToServiceWorkerDBStatus(
       db_->Get(leveldb::ReadOptions(), key, &value));
   if (status != STATUS_OK) {
-    HandleReadResult(
-        FROM_HERE,
-        status == STATUS_ERROR_NOT_FOUND ? STATUS_OK : status);
+    HandleReadResult(FROM_HERE,
+                     status == STATUS_ERROR_NOT_FOUND ? STATUS_OK : status);
     return status;
   }
 
@@ -1463,7 +1460,7 @@
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ParseRegistrationData(
     const std::string& serialized,
     RegistrationData* out) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(out);
   ServiceWorkerRegistrationData data;
   if (!data.ParseFromString(serialized))
@@ -1558,7 +1555,7 @@
 void ServiceWorkerDatabase::WriteRegistrationDataInBatch(
     const RegistrationData& registration,
     leveldb::WriteBatch* batch) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(batch);
 
   // The registration id and version id should be bumped before this.
@@ -1614,7 +1611,7 @@
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceRecords(
     const RegistrationData& registration,
     std::vector<ResourceRecord>* resources) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(resources->empty());
 
   Status status = STATUS_OK;
@@ -1663,7 +1660,7 @@
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ParseResourceRecord(
     const std::string& serialized,
     ServiceWorkerDatabase::ResourceRecord* out) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(out);
   ServiceWorkerResourceRecord record;
   if (!record.ParseFromString(serialized))
@@ -1718,7 +1715,7 @@
     int64_t version_id,
     std::vector<int64_t>* newly_purgeable_resources,
     leveldb::WriteBatch* batch) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(batch);
 
   Status status = STATUS_OK;
@@ -1759,7 +1756,7 @@
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceIds(
     const char* id_key_prefix,
     std::set<int64_t>* ids) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(id_key_prefix);
   DCHECK(ids->empty());
 
@@ -1801,7 +1798,7 @@
     const char* id_key_prefix,
     const std::set<int64_t>& ids,
     leveldb::WriteBatch* batch) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(id_key_prefix);
 
   Status status = LazyOpen(true);
@@ -1823,7 +1820,7 @@
     const char* id_key_prefix,
     const std::set<int64_t>& ids,
     leveldb::WriteBatch* batch) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(id_key_prefix);
 
   Status status = LazyOpen(false);
@@ -1842,7 +1839,7 @@
 ServiceWorkerDatabase::DeleteUserDataForRegistration(
     int64_t registration_id,
     leveldb::WriteBatch* batch) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(batch);
   Status status = STATUS_OK;
   const std::string prefix = CreateUserDataKeyPrefix(registration_id);
@@ -1870,7 +1867,7 @@
 
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadDatabaseVersion(
     int64_t* db_version) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::string value;
   Status status = LevelDBStatusToServiceWorkerDBStatus(
       db_->Get(leveldb::ReadOptions(),
@@ -1903,7 +1900,7 @@
 
 ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteBatch(
     leveldb::WriteBatch* batch) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(batch);
   DCHECK_NE(DATABASE_STATE_DISABLED, state_);
 
@@ -1924,7 +1921,7 @@
 void ServiceWorkerDatabase::BumpNextRegistrationIdIfNeeded(
     int64_t used_id,
     leveldb::WriteBatch* batch) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(batch);
   if (next_avail_registration_id_ <= used_id) {
     next_avail_registration_id_ = used_id + 1;
@@ -1936,7 +1933,7 @@
 void ServiceWorkerDatabase::BumpNextResourceIdIfNeeded(
     int64_t used_id,
     leveldb::WriteBatch* batch) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(batch);
   if (next_avail_resource_id_ <= used_id) {
     next_avail_resource_id_ = used_id + 1;
@@ -1948,7 +1945,7 @@
 void ServiceWorkerDatabase::BumpNextVersionIdIfNeeded(
     int64_t used_id,
     leveldb::WriteBatch* batch) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(batch);
   if (next_avail_version_id_ <= used_id) {
     next_avail_version_id_ = used_id + 1;
@@ -1958,13 +1955,13 @@
 }
 
 bool ServiceWorkerDatabase::IsOpen() {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return db_ != nullptr;
 }
 
 void ServiceWorkerDatabase::Disable(const base::Location& from_here,
                                     Status status) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (status != STATUS_OK) {
     DLOG(ERROR) << "Failed at: " << from_here.ToString()
                 << " with error: " << StatusToString(status);
@@ -1976,7 +1973,7 @@
 
 void ServiceWorkerDatabase::HandleOpenResult(const base::Location& from_here,
                                              Status status) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (status != STATUS_OK)
     Disable(from_here, status);
 
@@ -1986,7 +1983,7 @@
 
 void ServiceWorkerDatabase::HandleReadResult(const base::Location& from_here,
                                              Status status) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (status != STATUS_OK)
     Disable(from_here, status);
 
@@ -1996,7 +1993,7 @@
 
 void ServiceWorkerDatabase::HandleWriteResult(const base::Location& from_here,
                                               Status status) {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (status != STATUS_OK)
     Disable(from_here, status);
 
@@ -2005,7 +2002,7 @@
 }
 
 bool ServiceWorkerDatabase::IsDatabaseInMemory() const {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return path_.empty();
 }
 
diff --git a/content/browser/service_worker/service_worker_database.h b/content/browser/service_worker/service_worker_database.h
index 4ad56c1..9f812f49 100644
--- a/content/browser/service_worker/service_worker_database.h
+++ b/content/browser/service_worker/service_worker_database.h
@@ -435,7 +435,7 @@
 
   bool IsDatabaseInMemory() const;
 
-  base::SequenceChecker sequence_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, OpenDatabase);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, OpenDatabase_InMemory);
diff --git a/content/browser/service_worker/service_worker_database_unittest.cc b/content/browser/service_worker/service_worker_database_unittest.cc
index 4be16df..7f28152 100644
--- a/content/browser/service_worker/service_worker_database_unittest.cc
+++ b/content/browser/service_worker/service_worker_database_unittest.cc
@@ -145,8 +145,8 @@
   ServiceWorkerDatabase::RegistrationData data;
   data.resources_total_size_bytes = 10;
   ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->WriteRegistration(
-                data, resources, &deleted_version, &newly_purgeable_resources));
+            database->WriteRegistration(data, resources, &deleted_version,
+                                        &newly_purgeable_resources));
 
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
             database->ReadDatabaseVersion(&db_version));
@@ -242,15 +242,17 @@
 
   // The database has never been used, so returns initial values.
   AvailableIds ids;
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->GetNextAvailableIds(
-      &ids.reg_id, &ids.ver_id, &ids.res_id));
+  EXPECT_EQ(
+      ServiceWorkerDatabase::STATUS_OK,
+      database->GetNextAvailableIds(&ids.reg_id, &ids.ver_id, &ids.res_id));
   EXPECT_EQ(0, ids.reg_id);
   EXPECT_EQ(0, ids.ver_id);
   EXPECT_EQ(0, ids.res_id);
 
   ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(true));
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->GetNextAvailableIds(
-      &ids.reg_id, &ids.ver_id, &ids.res_id));
+  EXPECT_EQ(
+      ServiceWorkerDatabase::STATUS_OK,
+      database->GetNextAvailableIds(&ids.reg_id, &ids.ver_id, &ids.res_id));
   EXPECT_EQ(0, ids.reg_id);
   EXPECT_EQ(0, ids.ver_id);
   EXPECT_EQ(0, ids.res_id);
@@ -326,8 +328,9 @@
   // Close and reopen the database to verify the stored values.
   database.reset(CreateDatabase(database_dir.GetPath()));
 
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->GetNextAvailableIds(
-      &ids.reg_id, &ids.ver_id, &ids.res_id));
+  EXPECT_EQ(
+      ServiceWorkerDatabase::STATUS_OK,
+      database->GetNextAvailableIds(&ids.reg_id, &ids.ver_id, &ids.res_id));
   EXPECT_EQ(101, ids.reg_id);
   EXPECT_EQ(201, ids.ver_id);
   EXPECT_EQ(21, ids.res_id);
@@ -407,8 +410,7 @@
   // |origin3| has another registration, so should not remove it from the
   // unique origin list.
   ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->DeleteRegistration(data4.registration_id,
-                                         origin3,
+            database->DeleteRegistration(data4.registration_id, origin3,
                                          &deleted_version,
                                          &newly_purgeable_resources));
   EXPECT_EQ(data4.registration_id, deleted_version.registration_id);
@@ -423,8 +425,7 @@
 
   // |origin3| should be removed from the unique origin list.
   ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->DeleteRegistration(data3.registration_id,
-                                         origin3,
+            database->DeleteRegistration(data3.registration_id, origin3,
                                          &deleted_version,
                                          &newly_purgeable_resources));
   EXPECT_EQ(data3.registration_id, deleted_version.registration_id);
@@ -660,8 +661,8 @@
   std::vector<int64_t> newly_purgeable_resources;
 
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->WriteRegistration(
-                data, resources, &deleted_version, &newly_purgeable_resources));
+            database->WriteRegistration(data, resources, &deleted_version,
+                                        &newly_purgeable_resources));
   EXPECT_EQ(blink::mojom::kInvalidServiceWorkerVersionId,
             deleted_version.version_id);
   EXPECT_TRUE(newly_purgeable_resources.empty());
@@ -670,8 +671,8 @@
   RegistrationData data_out;
   std::vector<Resource> resources_out;
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->ReadRegistration(
-                data.registration_id, origin, &data_out, &resources_out));
+            database->ReadRegistration(data.registration_id, origin, &data_out,
+                                       &resources_out));
   VerifyRegistrationData(data, data_out);
   VerifyResourceRecords(resources, resources_out);
   GURL origin_out;
@@ -687,8 +688,7 @@
   EXPECT_TRUE(uncommitted_ids_out.empty());
 
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->DeleteRegistration(data.registration_id,
-                                         origin,
+            database->DeleteRegistration(data.registration_id, origin,
                                          &deleted_version,
                                          &newly_purgeable_resources));
   EXPECT_EQ(data.version_id, deleted_version.version_id);
@@ -699,8 +699,8 @@
   // Make sure that the registration and resource records are gone.
   resources_out.clear();
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
-            database->ReadRegistration(
-                data.registration_id, origin, &data_out, &resources_out));
+            database->ReadRegistration(data.registration_id, origin, &data_out,
+                                       &resources_out));
   EXPECT_TRUE(resources_out.empty());
   EXPECT_EQ(
       ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
@@ -737,8 +737,8 @@
   deleted_version.version_id = kArbitraryVersionId;
   std::vector<int64_t> newly_purgeable_resources;
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->WriteRegistration(
-                data, resources, &deleted_version, &newly_purgeable_resources));
+            database->WriteRegistration(data, resources, &deleted_version,
+                                        &newly_purgeable_resources));
   EXPECT_EQ(blink::mojom::kInvalidServiceWorkerVersionId,
             deleted_version.version_id);
   EXPECT_TRUE(newly_purgeable_resources.empty());
@@ -747,8 +747,7 @@
   deleted_version.version_id = kArbitraryVersionId;
   newly_purgeable_resources.clear();
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->DeleteRegistration(kNonExistentRegistrationId,
-                                         origin,
+            database->DeleteRegistration(kNonExistentRegistrationId, origin,
                                          &deleted_version,
                                          &newly_purgeable_resources));
   EXPECT_EQ(blink::mojom::kInvalidServiceWorkerVersionId,
@@ -789,10 +788,9 @@
   deleted_version.version_id = 222;  // Dummy inital value
   std::vector<int64_t> newly_purgeable_resources;
 
-  EXPECT_EQ(
-      ServiceWorkerDatabase::STATUS_OK,
-      database->WriteRegistration(
-          data, resources1, &deleted_version, &newly_purgeable_resources));
+  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+            database->WriteRegistration(data, resources1, &deleted_version,
+                                        &newly_purgeable_resources));
   EXPECT_EQ(blink::mojom::kInvalidServiceWorkerVersionId,
             deleted_version.version_id);
   EXPECT_TRUE(newly_purgeable_resources.empty());
@@ -800,8 +798,9 @@
   // Make sure that the registration and resource records are stored.
   RegistrationData data_out;
   std::vector<Resource> resources_out;
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration(
-      data.registration_id, origin, &data_out, &resources_out));
+  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+            database->ReadRegistration(data.registration_id, origin, &data_out,
+                                       &resources_out));
   VerifyRegistrationData(data, data_out);
   VerifyResourceRecords(resources1, resources_out);
 
@@ -821,11 +820,10 @@
   resources2.push_back(CreateResource(3, URL(origin, "/resource3"), 12));
   resources2.push_back(CreateResource(4, URL(origin, "/resource4"), 13));
 
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->WriteRegistration(updated_data,
-                                        resources2,
-                                        &deleted_version,
-                                        &newly_purgeable_resources));
+  EXPECT_EQ(
+      ServiceWorkerDatabase::STATUS_OK,
+      database->WriteRegistration(updated_data, resources2, &deleted_version,
+                                  &newly_purgeable_resources));
   EXPECT_EQ(data.version_id, deleted_version.version_id);
   ASSERT_EQ(resources1.size(), newly_purgeable_resources.size());
   for (size_t i = 0; i < resources1.size(); ++i)
@@ -834,8 +832,9 @@
   // Make sure that |updated_data| is stored and resources referred from |data|
   // is moved to the purgeable list.
   resources_out.clear();
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration(
-      updated_data.registration_id, origin, &data_out, &resources_out));
+  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+            database->ReadRegistration(updated_data.registration_id, origin,
+                                       &data_out, &resources_out));
   VerifyRegistrationData(updated_data, data_out);
   VerifyResourceRecords(resources2, resources_out);
 
@@ -865,10 +864,9 @@
   std::vector<Resource> resources1;
   resources1.push_back(CreateResource(1, URL(origin, "/resource1"), 1451));
   resources1.push_back(CreateResource(2, URL(origin, "/resource2"), 15234));
-  EXPECT_EQ(
-      ServiceWorkerDatabase::STATUS_OK,
-      database->WriteRegistration(
-          data1, resources1, &deleted_version, &newly_purgeable_resources));
+  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+            database->WriteRegistration(data1, resources1, &deleted_version,
+                                        &newly_purgeable_resources));
 
   // Add registration2.
   RegistrationData data2;
@@ -881,16 +879,16 @@
   std::vector<Resource> resources2;
   resources2.push_back(CreateResource(3, URL(origin, "/resource3"), 5));
   resources2.push_back(CreateResource(4, URL(origin, "/resource4"), 6));
-  EXPECT_EQ(
-      ServiceWorkerDatabase::STATUS_OK,
-      database->WriteRegistration(
-          data2, resources2, &deleted_version, &newly_purgeable_resources));
+  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+            database->WriteRegistration(data2, resources2, &deleted_version,
+                                        &newly_purgeable_resources));
 
   // Make sure that registration1 is stored.
   RegistrationData data_out;
   std::vector<Resource> resources_out;
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration(
-      data1.registration_id, origin, &data_out, &resources_out));
+  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+            database->ReadRegistration(data1.registration_id, origin, &data_out,
+                                       &resources_out));
   VerifyRegistrationData(data1, data_out);
   VerifyResourceRecords(resources1, resources_out);
   GURL origin_out;
@@ -901,8 +899,9 @@
 
   // Make sure that registration2 is also stored.
   resources_out.clear();
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration(
-      data2.registration_id, origin, &data_out, &resources_out));
+  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+            database->ReadRegistration(data2.registration_id, origin, &data_out,
+                                       &resources_out));
   VerifyRegistrationData(data2, data_out);
   VerifyResourceRecords(resources2, resources_out);
   EXPECT_EQ(
@@ -917,8 +916,7 @@
 
   // Delete registration1.
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->DeleteRegistration(data1.registration_id,
-                                         origin,
+            database->DeleteRegistration(data1.registration_id, origin,
                                          &deleted_version,
                                          &newly_purgeable_resources));
   EXPECT_EQ(data1.registration_id, deleted_version.registration_id);
@@ -926,8 +924,8 @@
   // Make sure that registration1 is gone.
   resources_out.clear();
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
-            database->ReadRegistration(
-                data1.registration_id, origin, &data_out, &resources_out));
+            database->ReadRegistration(data1.registration_id, origin, &data_out,
+                                       &resources_out));
   EXPECT_TRUE(resources_out.empty());
   EXPECT_EQ(
       ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
@@ -942,8 +940,9 @@
 
   // Make sure that registration2 is still alive.
   resources_out.clear();
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration(
-      data2.registration_id, origin, &data_out, &resources_out));
+  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+            database->ReadRegistration(data2.registration_id, origin, &data_out,
+                                       &resources_out));
   VerifyRegistrationData(data2, data_out);
   VerifyResourceRecords(resources2, resources_out);
   EXPECT_EQ(
@@ -960,8 +959,7 @@
   RegistrationData data_out;
   std::vector<Resource> resources_out;
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
-            database->ReadRegistration(
-                100, origin, &data_out, &resources_out));
+            database->ReadRegistration(100, origin, &data_out, &resources_out));
   EXPECT_EQ(blink::mojom::kInvalidServiceWorkerRegistrationId,
             data_out.registration_id);
   EXPECT_TRUE(resources_out.empty());
@@ -973,8 +971,8 @@
   RegistrationData deleted_version;
   std::vector<int64_t> newly_purgeable_resources;
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->DeleteRegistration(
-                100, origin, &deleted_version, &newly_purgeable_resources));
+            database->DeleteRegistration(100, origin, &deleted_version,
+                                         &newly_purgeable_resources));
   EXPECT_EQ(blink::mojom::kInvalidServiceWorkerVersionId,
             deleted_version.version_id);
   EXPECT_TRUE(newly_purgeable_resources.empty());
@@ -986,8 +984,7 @@
   ASSERT_EQ(ServiceWorkerDatabase::DATABASE_STATE_UNINITIALIZED,
             database->state_);
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
-            database->ReadRegistration(
-                100, origin, &data_out, &resources_out));
+            database->ReadRegistration(100, origin, &data_out, &resources_out));
   EXPECT_EQ(blink::mojom::kInvalidServiceWorkerRegistrationId,
             data_out.registration_id);
   EXPECT_TRUE(resources_out.empty());
@@ -996,8 +993,8 @@
 
   // Deleting non-existent registration should succeed.
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->DeleteRegistration(
-                100, origin, &deleted_version, &newly_purgeable_resources));
+            database->DeleteRegistration(100, origin, &deleted_version,
+                                         &newly_purgeable_resources));
   EXPECT_EQ(blink::mojom::kInvalidServiceWorkerVersionId,
             deleted_version.version_id);
   EXPECT_TRUE(newly_purgeable_resources.empty());
@@ -1100,8 +1097,8 @@
   ServiceWorkerDatabase::RegistrationData deleted_version;
   std::vector<int64_t> newly_purgeable_resources;
   ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->WriteRegistration(
-                data, resources, &deleted_version, &newly_purgeable_resources));
+            database->WriteRegistration(data, resources, &deleted_version,
+                                        &newly_purgeable_resources));
 
   // Write user data associated with the stored registration.
   std::vector<std::string> user_data_out;
@@ -1718,9 +1715,9 @@
   // Delete all data associated with the registration1. This shouldn't delete
   // the data associated with registration2.
   ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->DeleteRegistration(
-                data1.registration_id, kOrigin,
-                &deleted_version, &newly_purgeable_resources));
+            database->DeleteRegistration(data1.registration_id, kOrigin,
+                                         &deleted_version,
+                                         &newly_purgeable_resources));
   EXPECT_EQ(
       ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
       database->ReadUserData(data1.registration_id, {"key1"}, &user_data_out));
@@ -1796,8 +1793,8 @@
   RegistrationData data_out;
   std::vector<Resource> resources_out;
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->ReadRegistration(
-                data.registration_id, origin, &data_out, &resources_out));
+            database->ReadRegistration(data.registration_id, origin, &data_out,
+                                       &resources_out));
   VerifyRegistrationData(data, data_out);
   EXPECT_EQ(1u, resources_out.size());
 
@@ -1808,8 +1805,8 @@
   // Make sure that the registration is activated.
   resources_out.clear();
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->ReadRegistration(
-                data.registration_id, origin, &data_out, &resources_out));
+            database->ReadRegistration(data.registration_id, origin, &data_out,
+                                       &resources_out));
   RegistrationData expected_data = data;
   expected_data.is_active = true;
   VerifyRegistrationData(expected_data, data_out);
@@ -1817,8 +1814,7 @@
 
   // Delete the registration.
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->DeleteRegistration(data.registration_id,
-                                         origin,
+            database->DeleteRegistration(data.registration_id, origin,
                                          &deleted_version,
                                          &newly_purgeable_resources));
   EXPECT_EQ(data.registration_id, deleted_version.registration_id);
@@ -1856,22 +1852,22 @@
   RegistrationData data_out;
   std::vector<Resource> resources_out;
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->ReadRegistration(
-                data.registration_id, origin, &data_out, &resources_out));
+            database->ReadRegistration(data.registration_id, origin, &data_out,
+                                       &resources_out));
   VerifyRegistrationData(data, data_out);
   EXPECT_EQ(1u, resources_out.size());
 
   // Update the last check time.
   base::Time updated_time = base::Time::Now();
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->UpdateLastCheckTime(
-                data.registration_id, origin, updated_time));
+            database->UpdateLastCheckTime(data.registration_id, origin,
+                                          updated_time));
 
   // Make sure that the registration is updated.
   resources_out.clear();
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->ReadRegistration(
-                data.registration_id, origin, &data_out, &resources_out));
+            database->ReadRegistration(data.registration_id, origin, &data_out,
+                                       &resources_out));
   RegistrationData expected_data = data;
   expected_data.last_update_check = updated_time;
   VerifyRegistrationData(expected_data, data_out);
@@ -1879,16 +1875,15 @@
 
   // Delete the registration.
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
-            database->DeleteRegistration(data.registration_id,
-                                         origin,
+            database->DeleteRegistration(data.registration_id, origin,
                                          &deleted_version,
                                          &newly_purgeable_resources));
   EXPECT_EQ(data.registration_id, deleted_version.registration_id);
 
   // Should be false because the registration is gone.
   EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
-            database->UpdateLastCheckTime(
-                data.registration_id, origin, base::Time::Now()));
+            database->UpdateLastCheckTime(data.registration_id, origin,
+                                          base::Time::Now()));
 }
 
 TEST(ServiceWorkerDatabaseTest, UncommittedAndPurgeableResourceIds) {
@@ -1964,10 +1959,9 @@
   std::vector<Resource> resources1;
   resources1.push_back(CreateResource(1, URL(origin1, "/resource1"), 2013));
   resources1.push_back(CreateResource(2, URL(origin1, "/resource2"), 512));
-  ASSERT_EQ(
-      ServiceWorkerDatabase::STATUS_OK,
-      database->WriteRegistration(
-          data1, resources1, &deleted_version, &newly_purgeable_resources));
+  ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
+            database->WriteRegistration(data1, resources1, &deleted_version,
+                                        &newly_purgeable_resources));
   ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
             database->WriteUserData(data1.registration_id, origin1,
                                     {{"key1", "data1"}}));
@@ -1985,10 +1979,9 @@
   std::vector<Resource> resources2;
   resources2.push_back(CreateResource(3, URL(origin1, "/resource3"), 4));
   resources2.push_back(CreateResource(4, URL(origin1, "/resource4"), 5));
-  ASSERT_EQ(
-      ServiceWorkerDatabase::STATUS_OK,
-      database->WriteRegistration(
-          data2, resources2, &deleted_version, &newly_purgeable_resources));
+  ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
+            database->WriteRegistration(data2, resources2, &deleted_version,
+                                        &newly_purgeable_resources));
   ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
             database->WriteUserData(data2.registration_id, origin1,
                                     {{"key3", "data3"}}));
@@ -2007,10 +2000,9 @@
   std::vector<Resource> resources3;
   resources3.push_back(CreateResource(5, URL(origin2, "/resource5"), 6));
   resources3.push_back(CreateResource(6, URL(origin2, "/resource6"), 7));
-  ASSERT_EQ(
-      ServiceWorkerDatabase::STATUS_OK,
-      database->WriteRegistration(
-          data3, resources3, &deleted_version, &newly_purgeable_resources));
+  ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
+            database->WriteRegistration(data3, resources3, &deleted_version,
+                                        &newly_purgeable_resources));
   ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
             database->WriteUserData(data3.registration_id, origin2,
                                     {{"key5", "data5"}}));
@@ -2045,8 +2037,9 @@
   // The registration for |origin2| should not be removed.
   RegistrationData data_out;
   std::vector<Resource> resources_out;
-  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration(
-      data3.registration_id, origin2, &data_out, &resources_out));
+  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+            database->ReadRegistration(data3.registration_id, origin2,
+                                       &data_out, &resources_out));
   VerifyRegistrationData(data3, data_out);
   VerifyResourceRecords(resources3, resources_out);
   EXPECT_EQ(
diff --git a/content/browser/service_worker/service_worker_installed_script_loader.cc b/content/browser/service_worker/service_worker_installed_script_loader.cc
index c8413a97..801fa4e 100644
--- a/content/browser/service_worker/service_worker_installed_script_loader.cc
+++ b/content/browser/service_worker/service_worker_installed_script_loader.cc
@@ -9,7 +9,6 @@
 #include <utility>
 #include "content/browser/service_worker/service_worker_cache_writer.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
-#include "content/browser/service_worker/service_worker_storage.h"
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/browser/url_loader_factory_getter.h"
 #include "content/common/service_worker/service_worker_utils.h"
diff --git a/content/browser/service_worker/service_worker_installed_script_loader.h b/content/browser/service_worker/service_worker_installed_script_loader.h
index 25fecdc4..9350e44e 100644
--- a/content/browser/service_worker/service_worker_installed_script_loader.h
+++ b/content/browser/service_worker/service_worker_installed_script_loader.h
@@ -5,7 +5,6 @@
 #ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_INSTALLED_SCRIPT_LOADER_H_
 #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_INSTALLED_SCRIPT_LOADER_H_
 
-#include "content/browser/service_worker/service_worker_disk_cache.h"
 #include "content/browser/service_worker/service_worker_installed_script_reader.h"
 #include "content/common/content_export.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc
index 3e0fdce..8b5e454d 100644
--- a/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -823,7 +823,8 @@
   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
 
-  registration->active_version()->RemoveControllee(host->client_uuid());
+  registration->active_version()->RemoveControllee(
+      host->container_host()->client_uuid());
   WaitForVersionRunningStatus(version, EmbeddedWorkerStatus::STOPPED);
 
   // The version should be stopped since there is no controllee.
@@ -871,7 +872,7 @@
   EXPECT_EQ(ServiceWorkerVersion::INSTALLED, new_version->status());
 
   // Make the old version eligible for eviction.
-  old_version->RemoveControllee(host->client_uuid());
+  old_version->RemoveControllee(host->container_host()->client_uuid());
   RequestTermination(&initial_client->host());
 
   // Wait for activated.
@@ -930,7 +931,7 @@
   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
   EXPECT_EQ(ServiceWorkerVersion::INSTALLED, new_version->status());
 
-  old_version->RemoveControllee(host->client_uuid());
+  old_version->RemoveControllee(host->container_host()->client_uuid());
 
   WaitForVersionRunningStatus(old_version, EmbeddedWorkerStatus::STOPPED);
   WaitForVersionRunningStatus(new_version, EmbeddedWorkerStatus::STOPPED);
@@ -984,7 +985,7 @@
   EXPECT_FALSE(registration->is_uninstalling());
   EXPECT_EQ(new_version, registration->waiting_version());
 
-  old_version->RemoveControllee(host->client_uuid());
+  old_version->RemoveControllee(host->container_host()->client_uuid());
   RequestTermination(&initial_client->host());
 
   // Wait for activated.
@@ -1935,7 +1936,7 @@
   EXPECT_FALSE(registration->is_uninstalling());
   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, second_version->status());
 
-  first_version->RemoveControllee(host->client_uuid());
+  first_version->RemoveControllee(host->container_host()->client_uuid());
   RequestTermination(&initial_client->host());
 
   // Wait for activated.
@@ -2050,7 +2051,7 @@
 
   // Remove the controllee. The new version should be activating, and delayed
   // until the runner runs again.
-  first_version->RemoveControllee(host->client_uuid());
+  first_version->RemoveControllee(host->container_host()->client_uuid());
   base::RunLoop().RunUntilIdle();
 
   // Activating the new version won't happen until
diff --git a/content/browser/service_worker/service_worker_navigation_loader.cc b/content/browser/service_worker/service_worker_navigation_loader.cc
index b1e19ce..752cefdc 100644
--- a/content/browser/service_worker/service_worker_navigation_loader.cc
+++ b/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -15,6 +15,7 @@
 #include "base/optional.h"
 #include "base/strings/strcat.h"
 #include "base/trace_event/trace_event.h"
+#include "content/browser/service_worker/service_worker_container_host.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_metrics.h"
@@ -124,9 +125,10 @@
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
 
   resource_request_ = resource_request;
-  if (provider_host_ && provider_host_->fetch_request_window_id()) {
-    resource_request_.fetch_window_id =
-        base::make_optional(provider_host_->fetch_request_window_id());
+  if (provider_host_ &&
+      provider_host_->container_host()->fetch_request_window_id()) {
+    resource_request_.fetch_window_id = base::make_optional(
+        provider_host_->container_host()->fetch_request_window_id());
   }
 
   DCHECK(!receiver_.is_bound());
@@ -147,7 +149,7 @@
   }
 
   scoped_refptr<ServiceWorkerVersion> active_worker =
-      provider_host_->controller();
+      provider_host_->container_host()->controller();
   if (!active_worker) {
     CommitCompleted(net::ERR_FAILED, "No active worker");
     return;
@@ -165,7 +167,7 @@
   fetch_dispatcher_ = std::make_unique<ServiceWorkerFetchDispatcher>(
       blink::mojom::FetchAPIRequest::From(resource_request_),
       static_cast<ResourceType>(resource_request_.resource_type),
-      provider_host_->client_uuid(), active_worker,
+      provider_host_->container_host()->client_uuid(), active_worker,
       base::BindOnce(&ServiceWorkerNavigationLoader::DidPrepareFetchEvent,
                      weak_factory_.GetWeakPtr(), active_worker,
                      active_worker->running_status()),
@@ -173,7 +175,7 @@
                      weak_factory_.GetWeakPtr()));
   did_navigation_preload_ = fetch_dispatcher_->MaybeStartNavigationPreload(
       resource_request_, url_loader_factory_getter_.get(), std::move(context),
-      provider_host_->frame_tree_node_id());
+      provider_host_->container_host()->frame_tree_node_id());
 
   // Record worker start time here as |fetch_dispatcher_| will start a service
   // worker if there is no running service worker.
diff --git a/content/browser/service_worker/service_worker_navigation_loader.h b/content/browser/service_worker/service_worker_navigation_loader.h
index a0ea42c..dc97f4e 100644
--- a/content/browser/service_worker/service_worker_navigation_loader.h
+++ b/content/browser/service_worker/service_worker_navigation_loader.h
@@ -158,7 +158,11 @@
   NavigationLoaderInterceptor::FallbackCallback fallback_callback_;
 
   network::ResourceRequest resource_request_;
+
+  // TODO(https://crbug.com/931087): Replace this with
+  // ServiceWorkerContainerHost.
   base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+
   scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter_;
   std::unique_ptr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
   std::unique_ptr<StreamWaiter> stream_waiter_;
diff --git a/content/browser/service_worker/service_worker_navigation_loader_unittest.cc b/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
index eddb64d5..7d66f2c 100644
--- a/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
+++ b/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
@@ -17,6 +17,7 @@
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
 #include "content/browser/service_worker/fake_embedded_worker_instance_client.h"
 #include "content/browser/service_worker/fake_service_worker.h"
+#include "content/browser/service_worker/service_worker_container_host.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_registration.h"
 #include "content/browser/service_worker/service_worker_test_utils.h"
@@ -396,7 +397,7 @@
       provider_host_->UpdateUrls(request->url, request->url,
                                  url::Origin::Create(request->url));
       provider_host_->AddMatchingRegistration(registration_.get());
-      provider_host_->SetControllerRegistration(
+      provider_host_->container_host()->SetControllerRegistration(
           registration_, /*notify_controllerchange=*/false);
     }
 
@@ -804,7 +805,7 @@
 
   // The request should not be handled by the loader, but it shouldn't be a
   // failure.
-  EXPECT_TRUE(provider_host_->controller());
+  EXPECT_TRUE(provider_host_->container_host()->controller());
   histogram_tester.ExpectUniqueSample(kHistogramMainResourceFetchEvent,
                                       blink::ServiceWorkerStatusCode::kOk, 1);
 
@@ -846,7 +847,7 @@
   // The fallback callback should be called.
   RunUntilFallbackCallback();
   EXPECT_TRUE(reset_subresource_loader_params_);
-  EXPECT_FALSE(provider_host_->controller());
+  EXPECT_FALSE(provider_host_->container_host()->controller());
 
   histogram_tester.ExpectUniqueSample(
       kHistogramMainResourceFetchEvent,
diff --git a/content/browser/service_worker/service_worker_object_host_unittest.cc b/content/browser/service_worker/service_worker_object_host_unittest.cc
index cfe3b715..5bf79f5 100644
--- a/content/browser/service_worker/service_worker_object_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_object_host_unittest.cc
@@ -267,8 +267,8 @@
   // object for the service worker, inside the service worker's own
   // execution context (e.g., self.registration.active inside the active
   // worker and self.serviceWorker).
-  ServiceWorkerProviderHost* provider_host = version_->provider_host();
-  ServiceWorkerContainerHost* container_host = provider_host->container_host();
+  ServiceWorkerContainerHost* container_host =
+      version_->provider_host()->container_host();
   blink::mojom::ServiceWorkerObjectInfoPtr info =
       container_host->GetOrCreateServiceWorkerObjectHost(version_)
           ->CreateCompleteObjectInfoToSend();
@@ -395,13 +395,13 @@
   EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
 
   // The worker should have received an ExtendableMessageEvent whose
-  // source is |provider_host|.
+  // source is |container_host|.
   const std::vector<blink::mojom::ExtendableMessageEventPtr>& events =
       worker->events();
   EXPECT_EQ(1u, events.size());
   EXPECT_FALSE(events[0]->source_info_for_service_worker);
   EXPECT_TRUE(events[0]->source_info_for_client);
-  EXPECT_EQ(provider_host->client_uuid(),
+  EXPECT_EQ(container_host->client_uuid(),
             events[0]->source_info_for_client->client_uuid);
   EXPECT_EQ(container_host->client_type(),
             events[0]->source_info_for_client->client_type);
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index a932043..7e4158a1b 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/debug/alias.h"
-#include "base/guid.h"
 #include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -30,7 +29,6 @@
 #include "content/browser/service_worker/service_worker_type_converters.h"
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/browser/url_loader_factory_getter.h"
-#include "content/browser/web_contents/frame_tree_node_id_registry.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/browser/webtransport/quic_transport_connector_impl.h"
 #include "content/common/service_worker/service_worker_utils.h"
@@ -239,16 +237,9 @@
     scoped_refptr<ServiceWorkerVersion> running_hosted_version,
     base::WeakPtr<ServiceWorkerContextCore> context)
     : provider_id_(NextProviderId()),
-      client_uuid_(base::GenerateGUID()),
       create_time_(base::TimeTicks::Now()),
       render_process_id_(ChildProcessHost::kInvalidUniqueID),
       frame_id_(MSG_ROUTING_NONE),
-      frame_tree_node_id_(frame_tree_node_id),
-      web_contents_getter_(
-          frame_tree_node_id == FrameTreeNode::kFrameTreeNodeInvalidId
-              ? base::NullCallback()
-              : base::BindRepeating(&WebContents::FromFrameTreeNodeId,
-                                    frame_tree_node_id_)),
       running_hosted_version_(std::move(running_hosted_version)),
       context_(context),
       interface_provider_binding_(this),
@@ -256,6 +247,7 @@
       container_host_(std::make_unique<content::ServiceWorkerContainerHost>(
           type,
           is_parent_frame_secure,
+          frame_tree_node_id,
           std::move(container_remote),
           this,
           context)) {
@@ -270,7 +262,8 @@
   // For service worker clients, ServiceWorkerProviderHost::UpdateUrls() will
   // be called later.
 
-  context_->RegisterProviderHostByClientID(client_uuid_, this);
+  context_->RegisterProviderHostByClientID(container_host_->client_uuid(),
+                                           this);
 
   DCHECK(host_receiver.is_valid());
   receiver_.Bind(std::move(host_receiver));
@@ -288,17 +281,7 @@
   }
 
   if (context_)
-    context_->UnregisterProviderHostByClientID(client_uuid_);
-  if (controller_)
-    controller_->OnControlleeDestroyed(client_uuid_);
-  if (fetch_request_window_id_)
-    FrameTreeNodeIdRegistry::GetInstance()->Remove(fetch_request_window_id_);
-
-  // Remove |this| as an observer of ServiceWorkerRegistrations.
-  // TODO(falken): Use ScopedObserver instead of this explicit call.
-  controller_.reset();
-  controller_registration_.reset();
-  RemoveAllMatchingRegistrations();
+    context_->UnregisterProviderHostByClientID(container_host_->client_uuid());
 
   // Explicitly destroy the ServiceWorkerContainerHost to release
   // ServiceWorkerObjectHosts and ServiceWorkerRegistrationObjectHosts owned by
@@ -308,31 +291,8 @@
   // destroyed while in this destructor (|running_hosted_version_|'s
   // |event_dispatcher_|). See https://crbug.com/854993.
   container_host_.reset();
-}
 
-ServiceWorkerVersion* ServiceWorkerProviderHost::controller() const {
-#if DCHECK_IS_ON()
-  CheckControllerConsistency(false);
-#endif  // DCHECK_IS_ON()
-  return controller_.get();
-}
-
-blink::mojom::ControllerServiceWorkerMode
-ServiceWorkerProviderHost::GetControllerMode() const {
-  if (!controller_)
-    return blink::mojom::ControllerServiceWorkerMode::kNoController;
-  switch (controller_->fetch_handler_existence()) {
-    case ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST:
-      return blink::mojom::ControllerServiceWorkerMode::kNoFetchEventHandler;
-    case ServiceWorkerVersion::FetchHandlerExistence::EXISTS:
-      return blink::mojom::ControllerServiceWorkerMode::kControlled;
-    case ServiceWorkerVersion::FetchHandlerExistence::UNKNOWN:
-      // UNKNOWN means the controller is still installing. It's not possible to
-      // have a controller that hasn't finished installing.
-      NOTREACHED();
-  }
-  NOTREACHED();
-  return blink::mojom::ControllerServiceWorkerMode::kNoController;
+  RemoveAllMatchingRegistrations();
 }
 
 void ServiceWorkerProviderHost::OnVersionAttributesChanged(
@@ -362,7 +322,7 @@
 
 void ServiceWorkerProviderHost::OnSkippedWaiting(
     ServiceWorkerRegistration* registration) {
-  if (controller_registration_ != registration)
+  if (container_host_->controller_registration() != registration)
     return;
 
   if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled() &&
@@ -377,12 +337,7 @@
     return;
   }
 
-  DCHECK(controller_);
-  ServiceWorkerVersion* active = controller_registration_->active_version();
-  DCHECK(active);
-  DCHECK_NE(active, controller_.get());
-  DCHECK_EQ(active->status(), ServiceWorkerVersion::ACTIVATING);
-  UpdateController(true /* notify_controllerchange */);
+  container_host_->OnSkippedWaiting(registration);
 }
 
 ServiceWorkerVersion* ServiceWorkerProviderHost::running_hosted_version()
@@ -394,8 +349,8 @@
 
 mojo::Remote<blink::mojom::ControllerServiceWorker>
 ServiceWorkerProviderHost::GetRemoteControllerServiceWorker() {
-  DCHECK(controller_);
-  if (controller_->fetch_handler_existence() ==
+  DCHECK(container_host_->controller());
+  if (container_host_->controller()->fetch_handler_existence() ==
       ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST) {
     return mojo::Remote<blink::mojom::ControllerServiceWorker>();
   }
@@ -410,7 +365,7 @@
     pending_controller_receiver_ =
         remote_controller.BindNewPipeAndPassReceiver();
   } else {
-    controller_->controller()->Clone(
+    container_host_->controller()->controller()->Clone(
         remote_controller.BindNewPipeAndPassReceiver(),
         cross_origin_embedder_policy_.value());
   }
@@ -423,50 +378,10 @@
     const base::Optional<url::Origin>& top_frame_origin) {
   DCHECK(IsProviderForClient());
 
-  GURL previous_url = container_host_->url();
   container_host_->UpdateUrls(url, site_for_cookies, top_frame_origin);
   // TODO(https://crbug.com/931087): Move the remaining part to
   // ServiceWorkerContainerHost::UpdateUrls().
 
-  if (previous_url != url) {
-    // Revoke the token on URL change since any service worker holding the token
-    // may no longer be the potential controller of this frame and shouldn't
-    // have the power to display SSL dialogs for it.
-    if (provider_type() ==
-        blink::mojom::ServiceWorkerProviderType::kForWindow) {
-      auto* registry = FrameTreeNodeIdRegistry::GetInstance();
-      registry->Remove(fetch_request_window_id_);
-      fetch_request_window_id_ = base::UnguessableToken::Create();
-      registry->Add(fetch_request_window_id_, frame_tree_node_id_);
-    }
-  }
-
-  auto previous_origin = url::Origin::Create(previous_url);
-  auto new_origin = url::Origin::Create(url);
-  // Update client id on cross origin redirects. This corresponds to the HTML
-  // standard's "process a navigation fetch" algorithm's step for discarding
-  // |reservedEnvironment|.
-  // https://html.spec.whatwg.org/multipage/browsing-the-web.html#process-a-navigate-fetch
-  // "If |reservedEnvironment| is not null and |currentURL|'s origin is not the
-  // same as |reservedEnvironment|'s creation URL's origin, then:
-  //    1. Run the environment discarding steps for |reservedEnvironment|.
-  //    2. Set |reservedEnvironment| to null."
-  if (previous_url.is_valid() &&
-      !new_origin.IsSameOriginWith(previous_origin)) {
-    // Remove old controller since we know the controller is definitely
-    // changed. We need to remove |this| from |controller_|'s controllee before
-    // updating UUID since ServiceWorkerVersion has a map from uuid to provider
-    // hosts.
-    SetControllerRegistration(nullptr, false /* notify_controllerchange */);
-
-    // Set UUID to the new one.
-    if (context_)
-      context_->UnregisterProviderHostByClientID(client_uuid_);
-    client_uuid_ = base::GenerateGUID();
-    if (context_)
-      context_->RegisterProviderHostByClientID(client_uuid_, this);
-  }
-
   SyncMatchingRegistrations();
 }
 
@@ -475,31 +390,6 @@
   return container_host_->type();
 }
 
-void ServiceWorkerProviderHost::UpdateController(bool notify_controllerchange) {
-  ServiceWorkerVersion* version =
-      controller_registration_ ? controller_registration_->active_version()
-                               : nullptr;
-  CHECK(!version || container_host_->IsContextSecureForServiceWorker());
-  if (version == controller_.get())
-    return;
-
-  scoped_refptr<ServiceWorkerVersion> previous_version = controller_;
-  controller_ = version;
-
-  if (version)
-    version->AddControllee(this);
-  if (previous_version)
-    previous_version->RemoveControllee(client_uuid_);
-
-  // SetController message should be sent only for clients.
-  DCHECK(IsProviderForClient());
-
-  if (!container_host_->IsControllerDecided())
-    return;
-
-  SendSetControllerServiceWorker(notify_controllerchange);
-}
-
 bool ServiceWorkerProviderHost::IsProviderForServiceWorker() const {
   return container_host_->IsContainerForServiceWorker();
 }
@@ -508,23 +398,6 @@
   return container_host_->IsContainerForClient();
 }
 
-void ServiceWorkerProviderHost::SetControllerRegistration(
-    scoped_refptr<ServiceWorkerRegistration> controller_registration,
-    bool notify_controllerchange) {
-  DCHECK(IsProviderForClient());
-
-  if (controller_registration) {
-    CHECK(container_host_->IsContextSecureForServiceWorker());
-    DCHECK(controller_registration->active_version());
-#if DCHECK_IS_ON()
-    DCHECK(IsMatchingRegistration(controller_registration.get()));
-#endif  // DCHECK_IS_ON()
-  }
-
-  controller_registration_ = controller_registration;
-  UpdateController(notify_controllerchange);
-}
-
 void ServiceWorkerProviderHost::AddMatchingRegistration(
     ServiceWorkerRegistration* registration) {
   DCHECK(ServiceWorkerUtils::ScopeMatches(registration->scope(),
@@ -541,7 +414,7 @@
 
 void ServiceWorkerProviderHost::RemoveMatchingRegistration(
     ServiceWorkerRegistration* registration) {
-  DCHECK_NE(controller_registration_, registration);
+  DCHECK_NE(container_host_->controller_registration(), registration);
 #if DCHECK_IS_ON()
   DCHECK(IsMatchingRegistration(registration));
 #endif  // DCHECK_IS_ON()
@@ -573,7 +446,8 @@
 }
 
 void ServiceWorkerProviderHost::NotifyControllerLost() {
-  SetControllerRegistration(nullptr, true /* notify_controllerchange */);
+  container_host_->SetControllerRegistration(
+      nullptr, true /* notify_controllerchange */);
 }
 
 void ServiceWorkerProviderHost::AddServiceWorkerToUpdate(
@@ -586,21 +460,6 @@
   versions_to_update_.emplace(std::move(version));
 }
 
-void ServiceWorkerProviderHost::ClaimedByRegistration(
-    scoped_refptr<ServiceWorkerRegistration> registration) {
-  DCHECK(registration->active_version());
-  DCHECK(container_host_->is_execution_ready());
-
-  // TODO(falken): This should just early return, or DCHECK. claim() should have
-  // no effect on a page that's already using the registration.
-  if (registration == controller_registration_) {
-    UpdateController(true /* notify_controllerchange */);
-    return;
-  }
-
-  SetControllerRegistration(registration, true /* notify_controllerchange */);
-}
-
 void ServiceWorkerProviderHost::OnBeginNavigationCommit(
     int render_process_id,
     int render_frame_id,
@@ -619,11 +478,13 @@
 
   DCHECK(!cross_origin_embedder_policy_.has_value());
   cross_origin_embedder_policy_ = cross_origin_embedder_policy;
-  if (controller_ && controller_->fetch_handler_existence() ==
-                         ServiceWorkerVersion::FetchHandlerExistence::EXISTS) {
+  if (container_host_->controller() &&
+      container_host_->controller()->fetch_handler_existence() ==
+          ServiceWorkerVersion::FetchHandlerExistence::EXISTS) {
     DCHECK(pending_controller_receiver_);
-    controller_->controller()->Clone(std::move(pending_controller_receiver_),
-                                     cross_origin_embedder_policy_.value());
+    container_host_->controller()->controller()->Clone(
+        std::move(pending_controller_receiver_),
+        cross_origin_embedder_policy_.value());
   }
 
   if (IsBackForwardCacheEnabled() &&
@@ -666,11 +527,13 @@
 
   DCHECK(!cross_origin_embedder_policy_.has_value());
   cross_origin_embedder_policy_ = cross_origin_embedder_policy;
-  if (controller_ && controller_->fetch_handler_existence() ==
-                         ServiceWorkerVersion::FetchHandlerExistence::EXISTS) {
+  if (container_host_->controller() &&
+      container_host_->controller()->fetch_handler_existence() ==
+          ServiceWorkerVersion::FetchHandlerExistence::EXISTS) {
     DCHECK(pending_controller_receiver_);
-    controller_->controller()->Clone(std::move(pending_controller_receiver_),
-                                     cross_origin_embedder_policy_.value());
+    container_host_->controller()->controller()->Clone(
+        std::move(pending_controller_receiver_),
+        cross_origin_embedder_policy_.value());
   }
 
   container_host_->TransitionToClientPhase(
@@ -679,7 +542,7 @@
 }
 
 void ServiceWorkerProviderHost::SyncMatchingRegistrations() {
-  DCHECK(!controller_registration());
+  DCHECK(!container_host_->controller_registration());
 
   RemoveAllMatchingRegistrations();
   if (!context_)
@@ -711,7 +574,7 @@
 #endif  // DCHECK_IS_ON()
 
 void ServiceWorkerProviderHost::RemoveAllMatchingRegistrations() {
-  DCHECK(!controller_registration());
+  DCHECK(!container_host_ || !container_host_->controller_registration());
   for (const auto& it : matching_registrations_) {
     ServiceWorkerRegistration* registration = it.second.get();
     registration->RemoveListener(this);
@@ -739,95 +602,6 @@
           scoped_refptr<ServiceWorkerRegistration>(registration)));
 }
 
-void ServiceWorkerProviderHost::SendSetControllerServiceWorker(
-    bool notify_controllerchange) {
-  DCHECK(IsProviderForClient());
-
-  auto controller_info = blink::mojom::ControllerServiceWorkerInfo::New();
-  controller_info->client_id = client_uuid();
-  // Set fetch_request_window_id only when |controller_| is available.  Setting
-  // |fetch_request_window_id| should not affect correctness, however, we have
-  // the extensions bug, https://crbug.com/963748, which we don't yet
-  // understand.  That is why we don't set |fetch_request_window_id| if there
-  // is no controller, at least, until we can fix the extension bug.
-  if (controller_ && fetch_request_window_id_) {
-    controller_info->fetch_request_window_id =
-        base::make_optional(fetch_request_window_id_);
-  }
-
-  if (!controller_) {
-    container_host_->SendSetControllerServiceWorker(std::move(controller_info),
-                                                    notify_controllerchange);
-    return;
-  }
-
-  DCHECK(controller_registration());
-  DCHECK_EQ(controller_registration_->active_version(), controller_.get());
-
-  controller_info->mode = GetControllerMode();
-
-  // Pass an endpoint for the client to talk to this controller.
-  mojo::Remote<blink::mojom::ControllerServiceWorker> remote =
-      GetRemoteControllerServiceWorker();
-  if (remote.is_bound()) {
-    controller_info->remote_controller = remote.Unbind();
-  }
-
-  // Set the info for the JavaScript ServiceWorkerContainer#controller object.
-  base::WeakPtr<ServiceWorkerObjectHost> object_host =
-      container_host_->GetOrCreateServiceWorkerObjectHost(controller_);
-  if (object_host)
-    controller_info->object_info =
-        object_host->CreateCompleteObjectInfoToSend();
-
-  // Populate used features for UseCounter purposes.
-  for (const blink::mojom::WebFeature feature : controller_->used_features())
-    controller_info->used_features.push_back(feature);
-
-  container_host_->SendSetControllerServiceWorker(std::move(controller_info),
-                                                  notify_controllerchange);
-}
-
-#if DCHECK_IS_ON()
-void ServiceWorkerProviderHost::CheckControllerConsistency(
-    bool should_crash) const {
-  if (!controller_) {
-    DCHECK(!controller_registration_);
-    return;
-  }
-
-  DCHECK(IsProviderForClient());
-  DCHECK(controller_registration_);
-  DCHECK_EQ(controller_->registration_id(), controller_registration_->id());
-
-  switch (controller_->status()) {
-    case ServiceWorkerVersion::NEW:
-    case ServiceWorkerVersion::INSTALLING:
-    case ServiceWorkerVersion::INSTALLED:
-      if (should_crash) {
-        ServiceWorkerVersion::Status status = controller_->status();
-        base::debug::Alias(&status);
-        CHECK(false) << "Controller service worker has a bad status: "
-                     << ServiceWorkerVersion::VersionStatusToString(status);
-      }
-      break;
-    case ServiceWorkerVersion::REDUNDANT: {
-      if (should_crash) {
-        DEBUG_ALIAS_FOR_CSTR(
-            redundant_callstack_str,
-            controller_->redundant_state_callstack().ToString().c_str(), 1024);
-        CHECK(false);
-      }
-      break;
-    }
-    case ServiceWorkerVersion::ACTIVATING:
-    case ServiceWorkerVersion::ACTIVATED:
-      // Valid status, controller is being activated.
-      break;
-  }
-}
-#endif  // DCHECK_IS_ON()
-
 void ServiceWorkerProviderHost::Register(
     const GURL& script_url,
     blink::mojom::ServiceWorkerRegistrationOptionsPtr options,
@@ -1124,8 +898,8 @@
     blink::ServiceWorkerStatusCode status) {
   if (status == blink::ServiceWorkerStatusCode::kOk) {
     DCHECK(container_host_->is_response_committed());
-    controller_->controller()->Clone(std::move(receiver),
-                                     cross_origin_embedder_policy_.value());
+    container_host_->controller()->controller()->Clone(
+        std::move(receiver), cross_origin_embedder_policy_.value());
   }
 }
 
@@ -1133,10 +907,10 @@
     mojo::PendingReceiver<blink::mojom::ControllerServiceWorker> receiver,
     blink::mojom::ControllerServiceWorkerPurpose purpose) {
   // TODO(kinuko): Log the reasons we drop the request.
-  if (!context_ || !controller_)
+  if (!context_ || !container_host_->controller())
     return;
 
-  controller_->RunAfterStartWorker(
+  container_host_->controller()->RunAfterStartWorker(
       PurposeToEventType(purpose),
       base::BindOnce(&ServiceWorkerProviderHost::StartControllerComplete,
                      AsWeakPtr(), std::move(receiver)));
@@ -1175,7 +949,8 @@
   // to false ServiceWorkerContainerHost::IsControllerDecided().
   // TODO(leonhsl): Create some layout tests covering the above case 1), in
   // which case we may also need to set |notify_controllerchange| correctly.
-  SendSetControllerServiceWorker(false /* notify_controllerchange */);
+  container_host_->SendSetControllerServiceWorker(
+      false /* notify_controllerchange */);
 
   container_host_->SetExecutionReady();
 }
@@ -1321,8 +1096,9 @@
   DCHECK(IsBackForwardCacheEnabled());
   DCHECK_EQ(provider_type(),
             blink::mojom::ServiceWorkerProviderType::kForWindow);
-  if (controller_)
-    controller_->MoveControlleeToBackForwardCacheMap(client_uuid_);
+  if (container_host_->controller())
+    container_host_->controller()->MoveControlleeToBackForwardCacheMap(
+        container_host_->client_uuid());
   is_in_back_forward_cache_ = true;
 }
 
@@ -1331,15 +1107,16 @@
   DCHECK(IsBackForwardCacheEnabled());
   DCHECK_EQ(provider_type(),
             blink::mojom::ServiceWorkerProviderType::kForWindow);
-  if (controller_)
-    controller_->RestoreControlleeFromBackForwardCacheMap(client_uuid_);
+  if (container_host_->controller())
+    container_host_->controller()->RestoreControlleeFromBackForwardCacheMap(
+        container_host_->client_uuid());
   is_in_back_forward_cache_ = false;
 }
 
 void ServiceWorkerProviderHost::SetRenderProcessId(int process_id) {
   render_process_id_ = process_id;
-  if (controller_)
-    controller_->UpdateForegroundPriority();
+  if (container_host_->controller())
+    container_host_->controller()->UpdateForegroundPriority();
 }
 
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index 1eb53e3..124034b 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -34,7 +34,6 @@
 #include "mojo/public/cpp/bindings/pending_associated_remote.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
-#include "mojo/public/cpp/bindings/remote.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
@@ -59,7 +58,6 @@
 class ServiceWorkerContainerHost;
 class ServiceWorkerContextCore;
 class ServiceWorkerVersion;
-class WebContents;
 
 // ServiceWorkerProviderHost is the browser-process representation of a
 // renderer-process entity that can involve service workers. Currently, these
@@ -118,8 +116,6 @@
       public blink::mojom::ServiceWorkerContainerHost,
       public service_manager::mojom::InterfaceProvider {
  public:
-  using WebContentsGetter = base::RepeatingCallback<WebContents*()>;
-
   // Used to pre-create a ServiceWorkerProviderHost for a navigation. The
   // ServiceWorkerProviderContext will later be created in the renderer, should
   // the navigation succeed. |are_ancestors_secure| should be true for main
@@ -170,33 +166,10 @@
     return RenderProcessHost::FromID(render_process_id_);
   }
 
-  const std::string& client_uuid() const { return client_uuid_; }
-  const base::UnguessableToken& fetch_request_window_id() const {
-    return fetch_request_window_id_;
-  }
   base::TimeTicks create_time() const { return create_time_; }
   int process_id() const { return render_process_id_; }
   int provider_id() const { return provider_id_; }
   int frame_id() const { return frame_id_; }
-  const WebContentsGetter& web_contents_getter() const {
-    return web_contents_getter_;
-  }
-  int frame_tree_node_id() const { return frame_tree_node_id_; }
-
-  // For service worker clients. Describes whether the client has a controller
-  // and if it has a fetch event handler.
-  blink::mojom::ControllerServiceWorkerMode GetControllerMode() const;
-
-  // For service worker clients. Returns this client's controller.
-  ServiceWorkerVersion* controller() const;
-
-  ServiceWorkerRegistration* controller_registration() const {
-#if DCHECK_IS_ON()
-    CheckControllerConsistency(false);
-#endif  // DCHECK_IS_ON()
-
-    return controller_registration_.get();
-  }
 
   // For service worker execution contexts. The version of the service worker.
   // This is nullptr when the worker is still starting up (until
@@ -254,21 +227,9 @@
   bool IsProviderForServiceWorker() const;
   bool IsProviderForClient() const;
 
-  // For service worker clients. Makes this client be controlled by
-  // |registration|'s active worker, or makes this client be not
-  // controlled if |registration| is null. If |notify_controllerchange| is true,
-  // instructs the renderer to dispatch a 'controllerchange' event.
-  void SetControllerRegistration(
-      scoped_refptr<ServiceWorkerRegistration> controller_registration,
-      bool notify_controllerchange);
-
   // May return nullptr if the context has shut down.
   base::WeakPtr<ServiceWorkerContextCore> context() { return context_; }
 
-  // |registration| claims the document to be controlled.
-  void ClaimedByRegistration(
-      scoped_refptr<ServiceWorkerRegistration> registration);
-
   // For service worker window clients. Called when the navigation is ready to
   // commit. Updates this host with information about the frame committed to.
   // After this is called, is_response_committed() and is_execution_ready()
@@ -381,6 +342,8 @@
       base::WeakPtr<ServiceWorkerContextCore> context);
 
   // ServiceWorkerRegistration::Listener overrides.
+  // TODO(https://crbug.com/931087): Move these overrides to
+  // ServiceWorkerContainerHost.
   void OnVersionAttributesChanged(
       ServiceWorkerRegistration* registration,
       blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,
@@ -390,13 +353,6 @@
       ServiceWorkerRegistration* registration) override;
   void OnSkippedWaiting(ServiceWorkerRegistration* registration) override;
 
-  // Sets the controller to |controller_registration_->active_version()| or null
-  // if there is no associated registration.
-  //
-  // If |notify_controllerchange| is true, instructs the renderer to dispatch a
-  // 'controller' change event.
-  void UpdateController(bool notify_controllerchange);
-
   // Syncs matching registrations with live registrations.
   void SyncMatchingRegistrations();
 
@@ -409,15 +365,6 @@
 
   void ReturnRegistrationForReadyIfNeeded();
 
-  // Sends information about the controller to the providers of the service
-  // worker clients in the renderer. If |notify_controllerchange| is true,
-  // instructs the renderer to dispatch a 'controllerchange' event.
-  void SendSetControllerServiceWorker(bool notify_controllerchange);
-
-#if DCHECK_IS_ON()
-  void CheckControllerConsistency(bool should_crash) const;
-#endif  // DCHECK_IS_ON()
-
   // Implements blink::mojom::ServiceWorkerContainerHost.
   void Register(const GURL& script_url,
                 blink::mojom::ServiceWorkerRegistrationOptionsPtr options,
@@ -499,19 +446,6 @@
   // Unique among all provider hosts.
   const int provider_id_;
 
-  // A GUID that is web-exposed as FetchEvent.clientId.
-  std::string client_uuid_;
-
-  // For window clients. A token used internally to identify this context in
-  // requests. Corresponds to the Fetch specification's concept of a request's
-  // associated window: https://fetch.spec.whatwg.org/#concept-request-window
-  // This gets reset on redirects, unlike |client_uuid_|.
-  //
-  // TODO(falken): Consider using this for |client_uuid_| as well. We can't
-  // right now because this gets reset on redirects, and potentially sites rely
-  // on the GUID format.
-  base::UnguessableToken fetch_request_window_id_;
-
   const base::TimeTicks create_time_;
   int render_process_id_;
 
@@ -519,14 +453,6 @@
   // Otherwise, |MSG_ROUTING_NONE|.
   int frame_id_;
 
-  // FrameTreeNode id if this is a service worker window client.
-  // Otherwise, |FrameTreeNode::kFrameTreeNodeInvalidId|.
-  const int frame_tree_node_id_;
-
-  // Only set when this object is pre-created for a navigation. It indicates the
-  // tab where the navigation occurs. Otherwise, a null callback.
-  const WebContentsGetter web_contents_getter_;
-
   // Keyed by registration scope URL length.
   using ServiceWorkerRegistrationMap =
       std::map<size_t, scoped_refptr<ServiceWorkerRegistration>>;
@@ -545,16 +471,6 @@
   //    been run.
   std::unique_ptr<GetRegistrationForReadyCallback> get_ready_callback_;
 
-  // For service worker clients. The controller service worker (i.e.,
-  // ServiceWorkerContainer#controller) and its registration. The controller is
-  // typically the same as the registration's active version, but during
-  // algorithms such as the update, skipWaiting(), and claim() steps, the active
-  // version and controller may temporarily differ. For example, to perform
-  // skipWaiting(), the registration's active version is updated first and then
-  // the provider host's controller is updated to match it.
-  scoped_refptr<ServiceWorkerVersion> controller_;
-  scoped_refptr<ServiceWorkerRegistration> controller_registration_;
-
   // For service worker execution contexts. The ServiceWorkerVersion of the
   // service worker this is a provider for.
   const scoped_refptr<ServiceWorkerVersion> running_hosted_version_;
diff --git a/content/browser/service_worker/service_worker_provider_host_unittest.cc b/content/browser/service_worker/service_worker_provider_host_unittest.cc
index 95e43114..2f079d46 100644
--- a/content/browser/service_worker/service_worker_provider_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_provider_host_unittest.cc
@@ -435,16 +435,17 @@
 
   ServiceWorkerProviderHost* host = CreateProviderHost(url1);
   ServiceWorkerContainerHost* container_host = host->container_host();
-  const std::string uuid1 = host->client_uuid();
+  const std::string uuid1 = container_host->client_uuid();
   EXPECT_EQ(url1, container_host->url());
   EXPECT_EQ(url1, container_host->site_for_cookies());
 
   host->UpdateUrls(url2, url2, url::Origin::Create(url2));
   EXPECT_EQ(url2, container_host->url());
   EXPECT_EQ(url2, container_host->site_for_cookies());
-  EXPECT_EQ(uuid1, host->client_uuid());
+  EXPECT_EQ(uuid1, container_host->client_uuid());
 
-  EXPECT_EQ(host, context_->GetProviderHostByClientID(host->client_uuid()));
+  EXPECT_EQ(host,
+            context_->GetProviderHostByClientID(container_host->client_uuid()));
 }
 
 TEST_F(ServiceWorkerProviderHostTest, UpdateUrls_CrossOriginRedirect) {
@@ -453,17 +454,18 @@
 
   ServiceWorkerProviderHost* host = CreateProviderHost(url1);
   ServiceWorkerContainerHost* container_host = host->container_host();
-  const std::string uuid1 = host->client_uuid();
+  const std::string uuid1 = container_host->client_uuid();
   EXPECT_EQ(url1, container_host->url());
   EXPECT_EQ(url1, container_host->site_for_cookies());
 
   host->UpdateUrls(url2, url2, url::Origin::Create(url2));
   EXPECT_EQ(url2, container_host->url());
   EXPECT_EQ(url2, container_host->site_for_cookies());
-  EXPECT_NE(uuid1, host->client_uuid());
+  EXPECT_NE(uuid1, container_host->client_uuid());
 
   EXPECT_FALSE(context_->GetProviderHostByClientID(uuid1));
-  EXPECT_EQ(host, context_->GetProviderHostByClientID(host->client_uuid()));
+  EXPECT_EQ(host, context_->GetProviderHostByClientID(
+                      host->container_host()->client_uuid()));
 }
 
 class MockServiceWorkerRegistration : public ServiceWorkerRegistration {
@@ -554,16 +556,18 @@
   version->SetStatus(ServiceWorkerVersion::ACTIVATED);
   registration1_->SetActiveVersion(version);
 
+  ServiceWorkerContainerHost* container_host = host->container_host();
+
   // Finish the navigation.
-  FinishNavigation(host->container_host());
-  host->SetControllerRegistration(registration1_,
-                                  false /* notify_controllerchange */);
+  FinishNavigation(container_host);
+  container_host->SetControllerRegistration(
+      registration1_, false /* notify_controllerchange */);
   remote_endpoints_.back().host_remote()->get()->OnExecutionReady();
   base::RunLoop().RunUntilIdle();
 
   // The page should be controlled since there was an active version at the
   // time navigation started. The SetController IPC should have been sent.
-  EXPECT_TRUE(host->controller());
+  EXPECT_TRUE(container_host->controller());
   EXPECT_TRUE(container->was_set_controller_called());
   EXPECT_EQ(registration1_.get(), host->MatchRegistration());
 }
@@ -587,8 +591,10 @@
       helper_->context()->AsWeakPtr());
   registration1_->SetInstallingVersion(version);
 
+  ServiceWorkerContainerHost* container_host = host->container_host();
+
   // Finish the navigation.
-  FinishNavigation(host->container_host());
+  FinishNavigation(container_host);
   // Promote the worker to active while navigation is still happening.
   registration1_->SetActiveVersion(version);
   base::RunLoop().RunUntilIdle();
@@ -596,7 +602,7 @@
   // The page should not be controlled since there was no active version at the
   // time navigation started. Furthermore, no SetController IPC should have been
   // sent.
-  EXPECT_FALSE(host->controller());
+  EXPECT_FALSE(container_host->controller());
   EXPECT_FALSE(container->was_set_controller_called());
   // However, the host should know the registration is its best match, for
   // .ready and claim().
diff --git a/content/browser/service_worker/service_worker_registration.cc b/content/browser/service_worker/service_worker_registration.cc
index 4702ae2..788399a 100644
--- a/content/browser/service_worker/service_worker_registration.cc
+++ b/content/browser/service_worker/service_worker_registration.cc
@@ -270,7 +270,7 @@
 
     // This is part of step 5 but performed here as an optimization. Do nothing
     // if this version is already the controller.
-    if (host->controller() == active_version())
+    if (host->container_host()->controller() == active_version())
       continue;
 
     // "2. If client is not a secure context, continue."
@@ -285,7 +285,7 @@
       continue;
 
     // The remaining steps are performed here:
-    host->ClaimedByRegistration(this);
+    host->container_host()->ClaimedByRegistration(this);
   }
 }
 
diff --git a/content/browser/service_worker/service_worker_registration_unittest.cc b/content/browser/service_worker/service_worker_registration_unittest.cc
index c3973cd..0019858 100644
--- a/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -26,6 +26,7 @@
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
 #include "content/browser/service_worker/fake_embedded_worker_instance_client.h"
 #include "content/browser/service_worker/fake_service_worker.h"
+#include "content/browser/service_worker/service_worker_container_host.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_core_observer.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -430,8 +431,8 @@
     DCHECK(remote_endpoint_.client_receiver()->is_valid());
     DCHECK(remote_endpoint_.host_remote()->is_bound());
     host_->UpdateUrls(kUrl, kUrl, url::Origin::Create(kUrl));
-    host_->SetControllerRegistration(registration_,
-                                     false /* notify_controllerchange */);
+    host_->container_host()->SetControllerRegistration(
+        registration_, false /* notify_controllerchange */);
 
     // Setup the Mojo implementation fakes for the renderer-side service worker.
     // These will be bound once the service worker starts.
@@ -499,12 +500,12 @@
   int inflight_request_id() const { return inflight_request_id_; }
 
   void AddControllee() {
-    controllee()->SetControllerRegistration(
+    controllee()->container_host()->SetControllerRegistration(
         registration(), false /* notify_controllerchange */);
   }
 
   void RemoveControllee() {
-    controllee()->SetControllerRegistration(
+    controllee()->container_host()->SetControllerRegistration(
         nullptr, false /* notify_controllerchange */);
   }
 
diff --git a/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc b/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc
index e354fa0..4577b8f 100644
--- a/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc
+++ b/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/test/scoped_feature_list.h"
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_storage.h"
 #include "content/browser/service_worker/service_worker_test_utils.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_browser_context.h"
diff --git a/content/browser/service_worker/service_worker_storage_unittest.cc b/content/browser/service_worker/service_worker_storage_unittest.cc
index 5c3bb2e..6860767 100644
--- a/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -22,6 +22,7 @@
 #include "build/build_config.h"
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
 #include "content/browser/service_worker/service_worker_consts.h"
+#include "content/browser/service_worker/service_worker_container_host.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_disk_cache.h"
 #include "content/browser/service_worker/service_worker_registration.h"
@@ -1389,7 +1390,8 @@
   // Dooming the version should cause the resources to be deleted.
   base::RunLoop loop;
   storage()->SetPurgingCompleteCallbackForTest(loop.QuitClosure());
-  registration_->active_version()->RemoveControllee(host->client_uuid());
+  registration_->active_version()->RemoveControllee(
+      host->container_host()->client_uuid());
   registration_->active_version()->Doom();
   loop.Run();
   EXPECT_TRUE(GetPurgeableResourceIdsFromDB().empty());
@@ -1572,7 +1574,7 @@
   storage()->SetPurgingCompleteCallbackForTest(loop.QuitClosure());
   scoped_refptr<ServiceWorkerVersion> old_version(
       registration_->active_version());
-  old_version->RemoveControllee(host->client_uuid());
+  old_version->RemoveControllee(host->container_host()->client_uuid());
   registration_->ActivateWaitingVersionWhenReady();
   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status());
 
diff --git a/content/browser/service_worker/service_worker_updated_script_loader.cc b/content/browser/service_worker/service_worker_updated_script_loader.cc
index 0618a77..37af5ec6 100644
--- a/content/browser/service_worker/service_worker_updated_script_loader.cc
+++ b/content/browser/service_worker/service_worker_updated_script_loader.cc
@@ -17,7 +17,6 @@
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_disk_cache.h"
 #include "content/browser/service_worker/service_worker_loader_helpers.h"
-#include "content/browser/service_worker/service_worker_storage.h"
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/browser/url_loader_factory_getter.h"
 #include "content/common/service_worker/service_worker_utils.h"
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 7537703c..6f61228 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -375,11 +375,11 @@
       embedded_worker()->process_id(), embedded_worker()->thread_id(),
       embedded_worker()->worker_devtools_agent_route_id());
   for (const auto& controllee : controllee_map_) {
-    const ServiceWorkerProviderHost* host = controllee.second;
+    ServiceWorkerProviderHost* host = controllee.second;
     info.clients.insert(std::make_pair(
-        host->client_uuid(),
+        host->container_host()->client_uuid(),
         ServiceWorkerClientInfo(host->process_id(), host->frame_id(),
-                                host->web_contents_getter(),
+                                host->container_host()->web_contents_getter(),
                                 host->provider_type())));
   }
 
@@ -715,8 +715,8 @@
   // TODO(crbug.com/1021718): Remove this CHECK once we figure out the cause of
   // crash.
   CHECK(provider_host);
-  const std::string& uuid = provider_host->client_uuid();
-  CHECK(!provider_host->client_uuid().empty());
+  const std::string& uuid = provider_host->container_host()->client_uuid();
+  CHECK(!provider_host->container_host()->client_uuid().empty());
   // TODO(crbug.com/1021718): Change to DCHECK once we figure out the cause of
   // crash.
   CHECK(!base::Contains(controllee_map_, uuid));
@@ -741,7 +741,7 @@
                      weak_factory_.GetWeakPtr(), uuid,
                      ServiceWorkerClientInfo(
                          provider_host->process_id(), provider_host->frame_id(),
-                         provider_host->web_contents_getter(),
+                         provider_host->container_host()->web_contents_getter(),
                          provider_host->provider_type())));
 }
 
@@ -809,7 +809,8 @@
   while (!bfcached_controllee_map_.empty()) {
     auto controllee = bfcached_controllee_map_.begin();
     controllee->second->EvictFromBackForwardCache();
-    RemoveControlleeFromBackForwardCacheMap(controllee->second->client_uuid());
+    RemoveControlleeFromBackForwardCacheMap(
+        controllee->second->container_host()->client_uuid());
   }
 }
 
@@ -1396,7 +1397,7 @@
     receiver_.reset();
     return;
   }
-  if (provider_host->controller() != this) {
+  if (container_host->controller() != this) {
     std::move(callback).Run(
         false /* success */, nullptr /* client */,
         std::string(
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc
index c859ef9..fc3a0b1 100644
--- a/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/content/browser/service_worker/service_worker_version_unittest.cc
@@ -23,6 +23,7 @@
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
 #include "content/browser/service_worker/fake_embedded_worker_instance_client.h"
 #include "content/browser/service_worker/fake_service_worker.h"
+#include "content/browser/service_worker/service_worker_container_host.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_ping_controller.h"
 #include "content/browser/service_worker/service_worker_registration.h"
@@ -178,10 +179,10 @@
         helper_->context()->AsWeakPtr(), &remote_endpoint);
     host->UpdateUrls(registration_->scope(), registration_->scope(),
                      url::Origin::Create(registration_->scope()));
-    host->SetControllerRegistration(registration_,
-                                    false /* notify_controllerchange */);
+    host->container_host()->SetControllerRegistration(
+        registration_, false /* notify_controllerchange */);
     EXPECT_TRUE(version_->HasControllee());
-    EXPECT_TRUE(host->controller());
+    EXPECT_TRUE(host->container_host()->controller());
     return remote_endpoint;
   }
 
@@ -428,9 +429,9 @@
       helper_->context()->AsWeakPtr(), &remote_endpoint);
   host->UpdateUrls(registration_->scope(), registration_->scope(),
                    url::Origin::Create(registration_->scope()));
-  host->SetControllerRegistration(registration_, false);
+  host->container_host()->SetControllerRegistration(registration_, false);
   EXPECT_TRUE(version_->HasControllee());
-  EXPECT_TRUE(host->controller());
+  EXPECT_TRUE(host->container_host()->controller());
 
   // Doom the version.
   version_->Doom();
@@ -438,7 +439,7 @@
   // The controllee should have been removed.
   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version_->status());
   EXPECT_FALSE(version_->HasControllee());
-  EXPECT_FALSE(host->controller());
+  EXPECT_FALSE(host->container_host()->controller());
 }
 
 TEST_F(ServiceWorkerVersionTest, SetDevToolsAttached) {
@@ -1195,10 +1196,10 @@
   remote_endpoint.BindForWindow(std::move(host_and_info->info));
   host->UpdateUrls(registration_->scope(), registration_->scope(),
                    url::Origin::Create(registration_->scope()));
-  host->SetControllerRegistration(registration_,
-                                  false /* notify_controllerchange */);
+  host->container_host()->SetControllerRegistration(
+      registration_, false /* notify_controllerchange */);
   EXPECT_TRUE(version_->HasControllee());
-  EXPECT_TRUE(host->controller());
+  EXPECT_TRUE(host->container_host()->controller());
 
   // RenderProcessHost should be notified of foreground worker.
   base::RunLoop().RunUntilIdle();
diff --git a/content/browser/web_package/web_bundle_browsertest.cc b/content/browser/web_package/web_bundle_browsertest.cc
index 6754de2a..0577b6c3 100644
--- a/content/browser/web_package/web_bundle_browsertest.cc
+++ b/content/browser/web_package/web_bundle_browsertest.cc
@@ -398,7 +398,7 @@
   EXPECT_FALSE(NavigateToURL(web_contents, test_data_url()));
   run_loop.Run();
   ASSERT_TRUE(finish_navigation_observer.error_code());
-  EXPECT_EQ(net::ERR_INVALID_BUNDLED_EXCHANGES,
+  EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
             *finish_navigation_observer.error_code());
   if (console_delegate.messages().empty())
     console_delegate.Wait();
@@ -519,7 +519,7 @@
   EXPECT_FALSE(NavigateToURL(web_contents, test_data_url));
   run_loop.Run();
   ASSERT_TRUE(finish_navigation_observer.error_code());
-  EXPECT_EQ(net::ERR_INVALID_BUNDLED_EXCHANGES,
+  EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
             *finish_navigation_observer.error_code());
 
   if (console_delegate.messages().empty())
@@ -545,7 +545,7 @@
   EXPECT_FALSE(NavigateToURL(web_contents, test_data_url));
   run_loop.Run();
   ASSERT_TRUE(finish_navigation_observer.error_code());
-  EXPECT_EQ(net::ERR_INVALID_BUNDLED_EXCHANGES,
+  EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
             *finish_navigation_observer.error_code());
 
   if (console_delegate.messages().empty())
@@ -676,7 +676,7 @@
     EXPECT_FALSE(NavigateToURL(web_contents, url));
     run_loop.Run();
     ASSERT_TRUE(finish_navigation_observer.error_code());
-    EXPECT_EQ(net::ERR_INVALID_BUNDLED_EXCHANGES,
+    EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
               *finish_navigation_observer.error_code());
     if (console_delegate.messages().empty())
       console_delegate.Wait();
diff --git a/content/browser/web_package/web_bundle_handle.cc b/content/browser/web_package/web_bundle_handle.cc
index be362e22a..2d9acf1 100644
--- a/content/browser/web_package/web_bundle_handle.cc
+++ b/content/browser/web_package/web_bundle_handle.cc
@@ -218,8 +218,8 @@
       AddMetadataParseErrorMessageToConsole(frame_tree_node_id_,
                                             metadata_error);
       std::move(forwarding_client_)
-          ->OnComplete(network::URLLoaderCompletionStatus(
-              net::ERR_INVALID_BUNDLED_EXCHANGES));
+          ->OnComplete(
+              network::URLLoaderCompletionStatus(net::ERR_INVALID_WEB_BUNDLE));
       return;
     }
     DCHECK(reader_);
@@ -273,7 +273,7 @@
 //     - If OnMetadataReady() has not been called yet:
 //         Wait for OnMetadataReady() to be called.
 //     - If OnMetadataReady() was called with an error:
-//         Completes the request with ERR_INVALID_BUNDLED_EXCHANGES.
+//         Completes the request with ERR_INVALID_WEB_BUNDLE.
 //     - If OnMetadataReady() was called whthout errors:
 //         A redirect loader is created to redirect the navigation request to
 //         the Bundle's primary URL ("https://example.com/a.html").
@@ -315,8 +315,8 @@
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     if (metadata_error_) {
       mojo::Remote<network::mojom::URLLoaderClient>(std::move(client))
-          ->OnComplete(network::URLLoaderCompletionStatus(
-              net::ERR_INVALID_BUNDLED_EXCHANGES));
+          ->OnComplete(
+              network::URLLoaderCompletionStatus(net::ERR_INVALID_WEB_BUNDLE));
       return;
     }
 
@@ -403,7 +403,7 @@
 //       Content-Disposition header is set, returns false.
 //     - If the URL isn't HTTPS nor localhost HTTP, or the Content-Length header
 //       is not a positive value, completes the requests with
-//       ERR_INVALID_BUNDLED_EXCHANGES and returns true.
+//       ERR_INVALID_WEB_BUNDLE and returns true.
 //     - Otherwise starts reading the metadata and returns true. Once the
 //       metadata is read, OnMetadataReady() is called, and a redirect loader is
 //       created to redirect the navigation request to the Bundle's primary URL
@@ -467,8 +467,8 @@
           "Web Bundle response must be served from HTTPS or localhost HTTP.");
       *client_receiver = forwarding_client_.BindNewPipeAndPassReceiver();
       std::move(forwarding_client_)
-          ->OnComplete(network::URLLoaderCompletionStatus(
-              net::ERR_INVALID_BUNDLED_EXCHANGES));
+          ->OnComplete(
+              network::URLLoaderCompletionStatus(net::ERR_INVALID_WEB_BUNDLE));
       return true;
     }
 
@@ -478,8 +478,8 @@
           "Web Bundle response must have valid Content-Length header.");
       *client_receiver = forwarding_client_.BindNewPipeAndPassReceiver();
       std::move(forwarding_client_)
-          ->OnComplete(network::URLLoaderCompletionStatus(
-              net::ERR_INVALID_BUNDLED_EXCHANGES));
+          ->OnComplete(
+              network::URLLoaderCompletionStatus(net::ERR_INVALID_WEB_BUNDLE));
       return true;
     }
 
@@ -502,8 +502,8 @@
     if (error) {
       AddMetadataParseErrorMessageToConsole(frame_tree_node_id_, error);
       std::move(forwarding_client_)
-          ->OnComplete(network::URLLoaderCompletionStatus(
-              net::ERR_INVALID_BUNDLED_EXCHANGES));
+          ->OnComplete(
+              network::URLLoaderCompletionStatus(net::ERR_INVALID_WEB_BUNDLE));
       return;
     }
     primary_url_ = reader_->GetPrimaryURL();
@@ -512,8 +512,8 @@
           frame_tree_node_id_,
           "The primary URL resource is not found in the web bundle.");
       std::move(forwarding_client_)
-          ->OnComplete(network::URLLoaderCompletionStatus(
-              net::ERR_INVALID_BUNDLED_EXCHANGES));
+          ->OnComplete(
+              network::URLLoaderCompletionStatus(net::ERR_INVALID_WEB_BUNDLE));
       return;
     }
 
@@ -524,8 +524,8 @@
                                "The origin of primary URL doesn't match with "
                                "the origin of the web bundle.");
       std::move(forwarding_client_)
-          ->OnComplete(network::URLLoaderCompletionStatus(
-              net::ERR_INVALID_BUNDLED_EXCHANGES));
+          ->OnComplete(
+              network::URLLoaderCompletionStatus(net::ERR_INVALID_WEB_BUNDLE));
       return;
     }
     url_loader_factory_ = std::make_unique<WebBundleURLLoaderFactory>(
@@ -720,7 +720,7 @@
 //   - If OnMetadataReady() has not been called yet:
 //       Wait for OnMetadataReady() to be called.
 //   - If OnMetadataReady() was called with an error:
-//       Completes the request with ERR_INVALID_BUNDLED_EXCHANGES.
+//       Completes the request with ERR_INVALID_WEB_BUNDLE.
 //   - If OnMetadataReady() was called whthout errors:
 //       Creates the loader for the main resource.
 class InterceptorForNavigationInfo final : public NavigationLoaderInterceptor {
@@ -761,8 +761,8 @@
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     if (metadata_error_) {
       mojo::Remote<network::mojom::URLLoaderClient>(std::move(client))
-          ->OnComplete(network::URLLoaderCompletionStatus(
-              net::ERR_INVALID_BUNDLED_EXCHANGES));
+          ->OnComplete(
+              network::URLLoaderCompletionStatus(net::ERR_INVALID_WEB_BUNDLE));
       return;
     }
 
diff --git a/content/browser/web_package/web_bundle_url_loader_factory.cc b/content/browser/web_package/web_bundle_url_loader_factory.cc
index b8cc344..a7d4007 100644
--- a/content/browser/web_package/web_bundle_url_loader_factory.cc
+++ b/content/browser/web_package/web_bundle_url_loader_factory.cc
@@ -125,8 +125,8 @@
     if (!response || response->response_code != net::HTTP_OK) {
       if (error)
         AddResponseParseErrorMessageToConsole(frame_tree_node_id_, error);
-      loader_client_->OnComplete(network::URLLoaderCompletionStatus(
-          net::ERR_INVALID_BUNDLED_EXCHANGES));
+      loader_client_->OnComplete(
+          network::URLLoaderCompletionStatus(net::ERR_INVALID_WEB_BUNDLE));
       return;
     }
 
diff --git a/content/browser/web_package/web_bundle_url_loader_factory_unittest.cc b/content/browser/web_package/web_bundle_url_loader_factory_unittest.cc
index bc2f587..c6c5ae3 100644
--- a/content/browser/web_package/web_bundle_url_loader_factory_unittest.cc
+++ b/content/browser/web_package/web_bundle_url_loader_factory_unittest.cc
@@ -233,7 +233,7 @@
 TEST_F(WebBundleURLLoaderFactoryTest, CreateEntryLoaderAndFailToReadResponse) {
   auto loader = CreateLoaderAndStart(/*response=*/nullptr);
 
-  RunAndCheckFailure(net::ERR_INVALID_BUNDLED_EXCHANGES);
+  RunAndCheckFailure(net::ERR_INVALID_WEB_BUNDLE);
 }
 
 TEST_F(WebBundleURLLoaderFactoryTest, CreateLoaderForPost) {
diff --git a/content/child/child_process_sandbox_support_impl_linux.cc b/content/child/child_process_sandbox_support_impl_linux.cc
index 437fbe99..693ead7f 100644
--- a/content/child/child_process_sandbox_support_impl_linux.cc
+++ b/content/child/child_process_sandbox_support_impl_linux.cc
@@ -27,7 +27,7 @@
 
 WebSandboxSupportLinux::~WebSandboxSupportLinux() = default;
 
-void WebSandboxSupportLinux::GetFallbackFontForCharacter(
+bool WebSandboxSupportLinux::GetFallbackFontForCharacter(
     blink::WebUChar32 character,
     const char* preferred_locale,
     gfx::FallbackFontData* fallback_font) {
@@ -38,7 +38,7 @@
     const auto iter = unicode_font_families_.find(character);
     if (iter != unicode_font_families_.end()) {
       *fallback_font = iter->second;
-      return;
+      return true;
     }
   }
 
@@ -49,7 +49,7 @@
   if (!font_loader_->FallbackFontForCharacter(character, preferred_locale,
                                               &font_identity, &family_name,
                                               &is_bold, &is_italic))
-    return;
+    return false;
 
   // mojom::FontIdentityPtr cannot be exposed on the blink/public interface.
   // Use gfx::FallbackFontData as the container to pass this to blink.
@@ -62,9 +62,10 @@
 
   base::AutoLock lock(lock_);
   unicode_font_families_.emplace(character, *fallback_font);
+  return true;
 }
 
-void WebSandboxSupportLinux::MatchFontByPostscriptNameOrFullFontName(
+bool WebSandboxSupportLinux::MatchFontByPostscriptNameOrFullFontName(
     const char* font_unique_name,
     gfx::FallbackFontData* fallback_font) {
   TRACE_EVENT0(
@@ -77,12 +78,13 @@
                                                              &font_identity)) {
     LOG(ERROR) << "FontService unique font name matching request did not "
                   "receive a response.";
-    return;
+    return false;
   }
 
   fallback_font->fontconfig_interface_id = font_identity->id;
   fallback_font->filepath = font_identity->filepath;
   fallback_font->ttc_index = font_identity->ttc_index;
+  return true;
 }
 
 void WebSandboxSupportLinux::GetWebFontRenderStyleForStrike(
diff --git a/content/child/child_process_sandbox_support_impl_linux.h b/content/child/child_process_sandbox_support_impl_linux.h
index d88b1d382..99eb3ef 100644
--- a/content/child/child_process_sandbox_support_impl_linux.h
+++ b/content/child/child_process_sandbox_support_impl_linux.h
@@ -31,22 +31,23 @@
   explicit WebSandboxSupportLinux(sk_sp<font_service::FontLoader> font_loader);
   ~WebSandboxSupportLinux() override;
 
-  // Returns a font family which provides glyphs for the Unicode code point
-  // specified by |character|, a UTF-32 character. |preferred_locale| contains
-  // the preferred locale identifier for |character|. The instance has an empty
-  // font name if the request could not be satisfied.
-  void GetFallbackFontForCharacter(blink::WebUChar32 character,
-                                   const char* preferred_locale,
-                                   gfx::FallbackFontData* font) override;
+  // |fallback_font| will be filled with a font family which provides glyphs for
+  // the Unicode code point specified by |character|, a UTF-32 character.
+  // |preferred_locale| contains the preferred locale identifier for
+  // |character|. Returns false if the request could not be satisfied.
+  bool GetFallbackFontForCharacter(
+      blink::WebUChar32 character,
+      const char* preferred_locale,
+      gfx::FallbackFontData* fallback_font) override;
 
   // Matches a font uniquely by postscript name or full font name.  Used in
   // Blink for @font-face { src: local(arg) } matching.  Provide full font name
-  // or postscript name as argument font_unique_name in UTF-8. fallback_font
-  // contains a filename and fontconfig interface id if a match was found. The
-  // filename is empty and the interface id is zero if no match is found.
-  void MatchFontByPostscriptNameOrFullFontName(
+  // or postscript name as argument font_unique_name in UTF-8. |fallback_font|
+  // contains a filename and fontconfig interface id if a match was found.
+  // Returns false, otherwise.
+  bool MatchFontByPostscriptNameOrFullFontName(
       const char* font_unique_name,
-      gfx::FallbackFontData* font) override;
+      gfx::FallbackFontData* fallback_font) override;
 
   // Returns rendering settings for a provided font family, size, and style.
   // |size_and_style| stores the bold setting in its least-significant bit, the
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 1c00cb6d..501176e 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -287,7 +287,7 @@
 IPC_STRUCT_TRAITS_BEGIN(blink::FramePolicy)
   IPC_STRUCT_TRAITS_MEMBER(sandbox_flags)
   IPC_STRUCT_TRAITS_MEMBER(container_policy)
-  IPC_STRUCT_TRAITS_MEMBER(allowed_to_download_without_user_activation)
+  IPC_STRUCT_TRAITS_MEMBER(allowed_to_download)
 IPC_STRUCT_TRAITS_END()
 
 IPC_STRUCT_TRAITS_BEGIN(blink::ViewportIntersectionState)
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 9806b382..1946510 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -63,6 +63,16 @@
 const base::Feature kBackForwardCache{"BackForwardCache",
                                       base::FEATURE_DISABLED_BY_DEFAULT};
 
+// BackForwardCache is disabled on low memory devices. The threshold is defined
+// via a field trial param: "memory_threshold_for_back_forward_cache_in_mb"
+// It is compared against base::SysInfo::AmountOfPhysicalMemoryMB().
+
+// "BackForwardCacheMemoryControls" is checked before "BackForwardCache". It
+// means the low memory devices will activate neither the control group nor the
+// experimental group of the BackForwardCache field trial.
+const base::Feature kBackForwardCacheMemoryControl{
+    "BackForwardCacheMemoryControls", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Allows swipe left/right from touchpad change browser navigation. Currently
 // only enabled by default on CrOS.
 const base::Feature kTouchpadOverscrollHistoryNavigation {
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index ee31ec1..f2664bad 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -26,6 +26,7 @@
 CONTENT_EXPORT extern const base::Feature kAudioServiceOutOfProcess;
 CONTENT_EXPORT extern const base::Feature kBackgroundFetch;
 CONTENT_EXPORT extern const base::Feature kBackForwardCache;
+CONTENT_EXPORT extern const base::Feature kBackForwardCacheMemoryControl;
 CONTENT_EXPORT extern const base::Feature kBlockCredentialedSubresources;
 CONTENT_EXPORT extern const base::Feature kBrowserVerifiedUserActivation;
 CONTENT_EXPORT extern const base::Feature kCacheInlineScriptCode;
diff --git a/content/public/common/navigation_policy.cc b/content/public/common/navigation_policy.cc
index 74ea8dd..e7167ad8 100644
--- a/content/public/common/navigation_policy.cc
+++ b/content/public/common/navigation_policy.cc
@@ -6,6 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/system/sys_info.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "services/network/public/cpp/features.h"
@@ -24,9 +25,32 @@
       "Navigation.DownloadPolicy.LogArbitraryPolicyPerDownload", type);
 }
 
+bool DeviceHasEnoughMemoryForBackForwardCache() {
+  // This method make sure that the physical memory of device is greater than
+  // the allowed threshold and enables back-forward cache if the feature
+  // kBackForwardCacheMemoryControl is enabled.
+  // It is important to check the base::FeatureList to avoid activating any
+  // field trial groups if BFCache is disabled due to memory threshold.
+  if (base::FeatureList::IsEnabled(features::kBackForwardCacheMemoryControl)) {
+    int memory_threshold_mb = base::GetFieldTrialParamByFeatureAsInt(
+        features::kBackForwardCacheMemoryControl,
+        "memory_threshold_for_back_forward_cache_in_mb", 0);
+    return base::SysInfo::AmountOfPhysicalMemoryMB() > memory_threshold_mb;
+  }
+
+  // If the feature kBackForwardCacheMemoryControl is not enabled, all the
+  // devices are included by default.
+  return true;
+}
+
 }  // namespace
 
 bool IsBackForwardCacheEnabled() {
+  if (!DeviceHasEnoughMemoryForBackForwardCache())
+    return false;
+  // The feature needs to be checked last, because checking the feature
+  // activates the field trial and assigns the client either to a control or an
+  // experiment group - such assignment should be final.
   return base::FeatureList::IsEnabled(features::kBackForwardCache);
 }
 
@@ -62,8 +86,6 @@
   if (disallowed_types.test(
           static_cast<size_t>(NavigationDownloadType::kSandbox)) ||
       disallowed_types.test(
-          static_cast<size_t>(NavigationDownloadType::kSandboxNoGesture)) ||
-      disallowed_types.test(
           static_cast<size_t>(NavigationDownloadType::kOpenerCrossOrigin)) ||
       disallowed_types.test(
           static_cast<size_t>(NavigationDownloadType::kAdFrame)) ||
diff --git a/content/public/common/navigation_policy.h b/content/public/common/navigation_policy.h
index 89860b6..930eb0f 100644
--- a/content/public/common/navigation_policy.h
+++ b/content/public/common/navigation_policy.h
@@ -35,10 +35,6 @@
   // The navigation was initiated on a x-origin opener.
   kOpenerCrossOrigin = 5,
 
-  // The navigation was initiated from or occurred in an iframe with
-  // |WebSandboxFlags::kDownloads| flag set and without user activation.
-  kSandboxNoGesture = 7,
-
   // The navigation was initiated from or occurred in an ad frame without user
   // activation.
   kAdFrameNoGesture = 8,
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 91123d9..306d9b0b 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -575,8 +575,7 @@
   NavigationDownloadPolicy download_policy;
   RenderFrameImpl::MaybeSetDownloadFramePolicy(
       info->is_opener_navigation, info->url_request, current_origin,
-      has_download_sandbox_flag,
-      info->blocking_downloads_in_sandbox_without_user_activation_enabled,
+      has_download_sandbox_flag, info->blocking_downloads_in_sandbox_enabled,
       from_ad, &download_policy);
 
   return mojom::CommonNavigationParams::New(
@@ -1730,7 +1729,7 @@
     const blink::WebURLRequest& request,
     const blink::WebSecurityOrigin& current_origin,
     bool has_download_sandbox_flag,
-    bool blocking_downloads_in_sandbox_without_user_activation_enabled,
+    bool blocking_downloads_in_sandbox_enabled,
     bool from_ad,
     NavigationDownloadPolicy* download_policy) {
   bool has_gesture = request.HasUserGesture();
@@ -1746,14 +1745,10 @@
   }
 
   if (has_download_sandbox_flag) {
-    download_policy->SetAllowed(NavigationDownloadType::kSandbox);
-    if (!has_gesture) {
-      if (blocking_downloads_in_sandbox_without_user_activation_enabled) {
-        download_policy->SetDisallowed(
-            NavigationDownloadType::kSandboxNoGesture);
-      } else {
-        download_policy->SetAllowed(NavigationDownloadType::kSandboxNoGesture);
-      }
+    if (blocking_downloads_in_sandbox_enabled) {
+      download_policy->SetDisallowed(NavigationDownloadType::kSandbox);
+    } else {
+      download_policy->SetAllowed(NavigationDownloadType::kSandbox);
     }
   }
 
@@ -6389,18 +6384,17 @@
 
   params.href_translate = info->href_translate.Latin1();
 
-  bool current_frame_has_download_sandbox_flag =
-      !frame_->IsAllowedToDownloadWithoutUserActivation();
+  bool current_frame_has_download_sandbox_flag = !frame_->IsAllowedToDownload();
   bool has_download_sandbox_flag =
       info->initiator_frame_has_download_sandbox_flag ||
       current_frame_has_download_sandbox_flag;
   bool from_ad = info->initiator_frame_is_ad || frame_->IsAdSubframe();
 
-  MaybeSetDownloadFramePolicy(
-      info->is_opener_navigation, info->url_request,
-      frame_->GetSecurityOrigin(), has_download_sandbox_flag,
-      info->blocking_downloads_in_sandbox_without_user_activation_enabled,
-      from_ad, &params.download_policy);
+  MaybeSetDownloadFramePolicy(info->is_opener_navigation, info->url_request,
+                              frame_->GetSecurityOrigin(),
+                              has_download_sandbox_flag,
+                              info->blocking_downloads_in_sandbox_enabled,
+                              from_ad, &params.download_policy);
 
   Send(new FrameHostMsg_OpenURL(routing_id_, params));
 }
@@ -6701,8 +6695,7 @@
   mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator(
       std::move(info->navigation_initiator_handle), 0);
 
-  bool current_frame_has_download_sandbox_flag =
-      !frame_->IsAllowedToDownloadWithoutUserActivation();
+  bool current_frame_has_download_sandbox_flag = !frame_->IsAllowedToDownload();
   bool has_download_sandbox_flag =
       info->initiator_frame_has_download_sandbox_flag ||
       current_frame_has_download_sandbox_flag;
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index beb939f4..8171c74 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -276,7 +276,7 @@
       const blink::WebURLRequest& request,
       const blink::WebSecurityOrigin& current_origin,
       bool has_download_sandbox_flag,
-      bool blocking_downloads_in_sandbox_without_user_activation_enabled,
+      bool blocking_downloads_in_sandbox_enabled,
       bool from_ad,
       NavigationDownloadPolicy* download_policy);
 
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc
index e83cf3e..a15b618 100644
--- a/content/renderer/render_frame_proxy.cc
+++ b/content/renderer/render_frame_proxy.cc
@@ -752,14 +752,13 @@
   Send(new FrameHostMsg_RouteMessageEvent(routing_id_, params));
 }
 
-void RenderFrameProxy::Navigate(
-    const blink::WebURLRequest& request,
-    bool should_replace_current_entry,
-    bool is_opener_navigation,
-    bool has_download_sandbox_flag,
-    bool blocking_downloads_in_sandbox_without_user_activation_enabled,
-    bool initiator_frame_is_ad,
-    mojo::ScopedMessagePipeHandle blob_url_token) {
+void RenderFrameProxy::Navigate(const blink::WebURLRequest& request,
+                                bool should_replace_current_entry,
+                                bool is_opener_navigation,
+                                bool has_download_sandbox_flag,
+                                bool blocking_downloads_in_sandbox_enabled,
+                                bool initiator_frame_is_ad,
+                                mojo::ScopedMessagePipeHandle blob_url_token) {
   // The request must always have a valid initiator origin.
   DCHECK(!request.RequestorOrigin().IsNull());
 
@@ -785,8 +784,7 @@
   // augmented in RenderFrameProxyHost::OnOpenURL if the navigating frame is ad.
   RenderFrameImpl::MaybeSetDownloadFramePolicy(
       is_opener_navigation, request, web_frame_->GetSecurityOrigin(),
-      has_download_sandbox_flag,
-      blocking_downloads_in_sandbox_without_user_activation_enabled,
+      has_download_sandbox_flag, blocking_downloads_in_sandbox_enabled,
       initiator_frame_is_ad, &params.download_policy);
 
   Send(new FrameHostMsg_OpenURL(routing_id_, params));
diff --git a/content/renderer/render_frame_proxy.h b/content/renderer/render_frame_proxy.h
index 7681c39..73daa12 100644
--- a/content/renderer/render_frame_proxy.h
+++ b/content/renderer/render_frame_proxy.h
@@ -180,14 +180,13 @@
                           blink::WebRemoteFrame* targetFrame,
                           blink::WebSecurityOrigin target,
                           blink::WebDOMMessageEvent event) override;
-  void Navigate(
-      const blink::WebURLRequest& request,
-      bool should_replace_current_entry,
-      bool is_opener_navigation,
-      bool has_download_sandbox_flag,
-      bool blocking_downloads_in_sandbox_without_user_activation_enabled,
-      bool initiator_frame_is_ad,
-      mojo::ScopedMessagePipeHandle blob_url_token) override;
+  void Navigate(const blink::WebURLRequest& request,
+                bool should_replace_current_entry,
+                bool is_opener_navigation,
+                bool has_download_sandbox_flag,
+                bool blocking_downloads_in_sandbox_enabled,
+                bool initiator_frame_is_ad,
+                mojo::ScopedMessagePipeHandle blob_url_token) override;
   void FrameRectsChanged(const blink::WebRect& local_frame_rect,
                          const blink::WebRect& screen_space_rect) override;
   void UpdateRemoteViewportIntersection(
diff --git a/extensions/browser/api/file_handlers/app_file_handler_util.cc b/extensions/browser/api/file_handlers/app_file_handler_util.cc
index 21b2dec..f657d53b 100644
--- a/extensions/browser/api/file_handlers/app_file_handler_util.cc
+++ b/extensions/browser/api/file_handlers/app_file_handler_util.cc
@@ -108,8 +108,8 @@
       const std::vector<base::FilePath>& paths,
       content::BrowserContext* context,
       const std::set<base::FilePath>& directory_paths,
-      const base::Closure& on_success,
-      const base::Callback<void(const base::FilePath&)>& on_failure);
+      base::OnceClosure on_success,
+      base::OnceCallback<void(const base::FilePath&)> on_failure);
 
   void Check();
 
@@ -136,22 +136,22 @@
   const std::set<base::FilePath> directory_paths_;
   size_t outstanding_tasks_;
   base::FilePath error_path_;
-  base::Closure on_success_;
-  base::Callback<void(const base::FilePath&)> on_failure_;
+  base::OnceClosure on_success_;
+  base::OnceCallback<void(const base::FilePath&)> on_failure_;
 };
 
 WritableFileChecker::WritableFileChecker(
     const std::vector<base::FilePath>& paths,
     content::BrowserContext* context,
     const std::set<base::FilePath>& directory_paths,
-    const base::Closure& on_success,
-    const base::Callback<void(const base::FilePath&)>& on_failure)
+    base::OnceClosure on_success,
+    base::OnceCallback<void(const base::FilePath&)> on_failure)
     : paths_(paths),
       context_(context),
       directory_paths_(directory_paths),
       outstanding_tasks_(1),
-      on_success_(on_success),
-      on_failure_(on_failure) {}
+      on_success_(std::move(on_success)),
+      on_failure_(std::move(on_failure)) {}
 
 void WritableFileChecker::Check() {
   outstanding_tasks_ = paths_.size();
@@ -164,11 +164,13 @@
       if (is_directory) {
         delegate->IsNonNativeLocalPathDirectory(
             context_, path,
-            base::Bind(&WritableFileChecker::OnPrepareFileDone, this, path));
+            base::BindOnce(&WritableFileChecker::OnPrepareFileDone, this,
+                           path));
       } else {
         delegate->PrepareNonNativeLocalFileForWritableApp(
             context_, path,
-            base::Bind(&WritableFileChecker::OnPrepareFileDone, this, path));
+            base::BindOnce(&WritableFileChecker::OnPrepareFileDone, this,
+                           path));
       }
       continue;
     }
@@ -177,8 +179,9 @@
         FROM_HERE,
         {base::ThreadPool(), base::TaskPriority::USER_BLOCKING,
          base::MayBlock()},
-        base::Bind(&PrepareNativeLocalFileForWritableApp, path, is_directory),
-        base::Bind(&WritableFileChecker::OnPrepareFileDone, this, path));
+        base::BindOnce(&PrepareNativeLocalFileForWritableApp, path,
+                       is_directory),
+        base::BindOnce(&WritableFileChecker::OnPrepareFileDone, this, path));
   }
 }
 
@@ -188,9 +191,11 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (--outstanding_tasks_ == 0) {
     if (error_path_.empty())
-      on_success_.Run();
+      std::move(on_success_).Run();
     else
-      on_failure_.Run(error_path_);
+      std::move(on_failure_).Run(error_path_);
+    on_success_.Reset();
+    on_failure_.Reset();
   }
 }
 
@@ -324,10 +329,11 @@
     const std::vector<base::FilePath>& paths,
     content::BrowserContext* context,
     const std::set<base::FilePath>& directory_paths,
-    const base::Closure& on_success,
-    const base::Callback<void(const base::FilePath&)>& on_failure) {
+    base::OnceClosure on_success,
+    base::OnceCallback<void(const base::FilePath&)> on_failure) {
   auto checker = base::MakeRefCounted<WritableFileChecker>(
-      paths, context, directory_paths, on_success, on_failure);
+      paths, context, directory_paths, std::move(on_success),
+      std::move(on_failure));
   checker->Check();
 }
 
diff --git a/extensions/browser/api/file_handlers/app_file_handler_util.h b/extensions/browser/api/file_handlers/app_file_handler_util.h
index c969402..2c653fdab 100644
--- a/extensions/browser/api/file_handlers/app_file_handler_util.h
+++ b/extensions/browser/api/file_handlers/app_file_handler_util.h
@@ -72,8 +72,8 @@
     const std::vector<base::FilePath>& paths,
     content::BrowserContext* context,
     const std::set<base::FilePath>& directory_paths,
-    const base::Closure& on_success,
-    const base::Callback<void(const base::FilePath&)>& on_failure);
+    base::OnceClosure on_success,
+    base::OnceCallback<void(const base::FilePath&)> on_failure);
 
 // Returns whether |extension| has the fileSystem.write permission.
 bool HasFileSystemWritePermission(const Extension* extension);
diff --git a/extensions/browser/api/file_handlers/directory_util.cc b/extensions/browser/api/file_handlers/directory_util.cc
index ed92449..72370500 100644
--- a/extensions/browser/api/file_handlers/directory_util.cc
+++ b/extensions/browser/api/file_handlers/directory_util.cc
@@ -33,19 +33,19 @@
 // path directories for the IsNonNativeLocalPathDirectory API.
 void EntryIsDirectory(content::BrowserContext* context,
                       const base::FilePath& path,
-                      const base::Callback<void(bool)>& callback) {
+                      base::OnceCallback<void(bool)> callback) {
 #if defined(OS_CHROMEOS)
   NonNativeFileSystemDelegate* delegate =
       ExtensionsAPIClient::Get()->GetNonNativeFileSystemDelegate();
   if (delegate && delegate->IsUnderNonNativeLocalPath(context, path)) {
-    delegate->IsNonNativeLocalPathDirectory(context, path, callback);
+    delegate->IsNonNativeLocalPathDirectory(context, path, std::move(callback));
     return;
   }
 #endif
 
   base::PostTaskAndReplyWithResult(
       FROM_HERE, {base::ThreadPool(), base::MayBlock()},
-      base::Bind(&GetIsDirectoryFromFileInfo, path), callback);
+      base::BindOnce(&GetIsDirectoryFromFileInfo, path), std::move(callback));
 }
 
 }  // namespace
@@ -57,10 +57,10 @@
 
 void IsDirectoryCollector::CollectForEntriesPaths(
     const std::vector<base::FilePath>& paths,
-    const CompletionCallback& callback) {
+    CompletionCallback callback) {
   DCHECK(!callback.is_null());
   paths_ = paths;
-  callback_ = callback;
+  callback_ = std::move(callback);
 
   DCHECK(!result_.get());
   result_.reset(new std::set<base::FilePath>());
@@ -69,15 +69,16 @@
   if (!left_) {
     // Nothing to process.
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(callback_, std::move(result_)));
-    callback_ = CompletionCallback();
+        FROM_HERE, base::BindOnce(std::move(callback_), std::move(result_)));
+    callback_.Reset();
     return;
   }
 
   for (size_t i = 0; i < paths.size(); ++i) {
-    EntryIsDirectory(context_, paths[i],
-                     base::Bind(&IsDirectoryCollector::OnIsDirectoryCollected,
-                                weak_ptr_factory_.GetWeakPtr(), i));
+    EntryIsDirectory(
+        context_, paths[i],
+        base::BindOnce(&IsDirectoryCollector::OnIsDirectoryCollected,
+                       weak_ptr_factory_.GetWeakPtr(), i));
   }
 }
 
@@ -87,11 +88,11 @@
     result_->insert(paths_[index]);
   if (!--left_) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(callback_, std::move(result_)));
+        FROM_HERE, base::BindOnce(std::move(callback_), std::move(result_)));
     // Release the callback to avoid a circullar reference in case an instance
     // of this class is a member of a ref counted class, which instance is bound
     // to this callback.
-    callback_ = CompletionCallback();
+    callback_.Reset();
   }
 }
 
diff --git a/extensions/browser/api/file_handlers/directory_util.h b/extensions/browser/api/file_handlers/directory_util.h
index f620eaf..d95407e 100644
--- a/extensions/browser/api/file_handlers/directory_util.h
+++ b/extensions/browser/api/file_handlers/directory_util.h
@@ -27,8 +27,8 @@
 
 class IsDirectoryCollector {
  public:
-  typedef base::Callback<void(std::unique_ptr<std::set<base::FilePath>>)>
-      CompletionCallback;
+  using CompletionCallback =
+      base::OnceCallback<void(std::unique_ptr<std::set<base::FilePath>>)>;
 
   explicit IsDirectoryCollector(content::BrowserContext* context);
   virtual ~IsDirectoryCollector();
@@ -36,7 +36,7 @@
   // For the given paths obtains a set with which of them are directories.
   // The collector does not support virtual files if OS != CHROMEOS.
   void CollectForEntriesPaths(const std::vector<base::FilePath>& paths,
-                              const CompletionCallback& callback);
+                              CompletionCallback callback);
 
  private:
   void OnIsDirectoryCollected(size_t index, bool directory);
diff --git a/extensions/browser/api/file_handlers/directory_util_unittest.cc b/extensions/browser/api/file_handlers/directory_util_unittest.cc
index 25b96ff..37d51b7 100644
--- a/extensions/browser/api/file_handlers/directory_util_unittest.cc
+++ b/extensions/browser/api/file_handlers/directory_util_unittest.cc
@@ -61,7 +61,7 @@
   IsDirectoryCollector collector(&context_);
   std::set<base::FilePath> result;
   collector.CollectForEntriesPaths(
-      paths, base::Bind(&OnCollectForEntriesPath, &result));
+      paths, base::BindOnce(&OnCollectForEntriesPath, &result));
   content::RunAllTasksUntilIdle();
 
   ASSERT_EQ(1u, result.size());
diff --git a/extensions/browser/api/file_handlers/mime_util.cc b/extensions/browser/api/file_handlers/mime_util.cc
index 8c406f38..0860a08 100644
--- a/extensions/browser/api/file_handlers/mime_util.cc
+++ b/extensions/browser/api/file_handlers/mime_util.cc
@@ -63,8 +63,8 @@
 // to |callback|.
 void OnGetMimeTypeFromFileForNonNativeLocalPathCompleted(
     std::unique_ptr<std::string> mime_type,
-    const base::Callback<void(const std::string&)>& callback) {
-  callback.Run(*mime_type);
+    base::OnceCallback<void(const std::string&)> callback) {
+  std::move(callback).Run(*mime_type);
 }
 
 // Called when fetching MIME type for a non-native local path is completed.
@@ -72,10 +72,10 @@
 // file name.
 void OnGetMimeTypeFromMetadataForNonNativeLocalPathCompleted(
     const base::FilePath& local_path,
-    const base::Callback<void(const std::string&)>& callback,
+    base::OnceCallback<void(const std::string&)> callback,
     const base::Optional<std::string>& mime_type) {
   if (mime_type) {
-    callback.Run(mime_type.value());
+    std::move(callback).Run(mime_type.value());
     return;
   }
 
@@ -86,27 +86,27 @@
       mime_type_from_extension.get();
   base::PostTaskAndReply(
       FROM_HERE, {base::ThreadPool(), base::MayBlock()},
-      base::Bind(base::IgnoreResult(&net::GetMimeTypeFromFile), local_path,
-                 mime_type_from_extension_ptr),
-      base::Bind(&OnGetMimeTypeFromFileForNonNativeLocalPathCompleted,
-                 base::Passed(&mime_type_from_extension), callback));
+      base::BindOnce(base::IgnoreResult(&net::GetMimeTypeFromFile), local_path,
+                     mime_type_from_extension_ptr),
+      base::BindOnce(&OnGetMimeTypeFromFileForNonNativeLocalPathCompleted,
+                     std::move(mime_type_from_extension), std::move(callback)));
 }
 #endif
 
 // Called when sniffing for MIME type in the native local file is completed.
 void OnSniffMimeTypeForNativeLocalPathCompleted(
     std::unique_ptr<std::string> mime_type,
-    const base::Callback<void(const std::string&)>& callback) {
+    base::OnceCallback<void(const std::string&)> callback) {
   // Do not return application/zip as sniffed result. If the file has .zip
   // extension, it should be already returned as application/zip. If the file
   // does not have .zip extension and couldn't find mime type from the
   // extension, it might be unknown internally zipped file.
   if (*mime_type == "application/zip") {
-    callback.Run(kMimeTypeApplicationOctetStream);
+    std::move(callback).Run(kMimeTypeApplicationOctetStream);
     return;
   }
 
-  callback.Run(*mime_type);
+  std::move(callback).Run(*mime_type);
 }
 
 }  // namespace
@@ -117,9 +117,9 @@
 void OnGetMimeTypeFromFileForNativeLocalPathCompleted(
     const base::FilePath& local_path,
     std::unique_ptr<std::string> mime_type,
-    const base::Callback<void(const std::string&)>& callback) {
+    base::OnceCallback<void(const std::string&)> callback) {
   if (!mime_type->empty()) {
-    callback.Run(*mime_type);
+    std::move(callback).Run(*mime_type);
     return;
   }
 
@@ -128,16 +128,16 @@
   std::string* const sniffed_mime_type_ptr = sniffed_mime_type.get();
   base::PostTaskAndReply(
       FROM_HERE, {base::ThreadPool(), base::MayBlock()},
-      base::Bind(&SniffMimeType, local_path, sniffed_mime_type_ptr),
-      base::Bind(&OnSniffMimeTypeForNativeLocalPathCompleted,
-                 base::Passed(&sniffed_mime_type), callback));
+      base::BindOnce(&SniffMimeType, local_path, sniffed_mime_type_ptr),
+      base::BindOnce(&OnSniffMimeTypeForNativeLocalPathCompleted,
+                     std::move(sniffed_mime_type), std::move(callback)));
 }
 
 // Fetches MIME type for a local path and returns it with a |callback|.
 void GetMimeTypeForLocalPath(
     content::BrowserContext* context,
     const base::FilePath& local_path,
-    const base::Callback<void(const std::string&)>& callback) {
+    base::OnceCallback<void(const std::string&)> callback) {
 #if defined(OS_CHROMEOS)
   NonNativeFileSystemDelegate* delegate =
       ExtensionsAPIClient::Get()->GetNonNativeFileSystemDelegate();
@@ -148,7 +148,7 @@
     delegate->GetNonNativeLocalPathMimeType(
         context, local_path,
         base::BindOnce(&OnGetMimeTypeFromMetadataForNonNativeLocalPathCompleted,
-                       local_path, callback));
+                       local_path, std::move(callback)));
     return;
   }
 #endif
@@ -160,10 +160,11 @@
       mime_type_from_extension.get();
   base::PostTaskAndReply(
       FROM_HERE, {base::ThreadPool(), base::MayBlock()},
-      base::Bind(base::IgnoreResult(&net::GetMimeTypeFromFile), local_path,
-                 mime_type_from_extension_ptr),
-      base::Bind(&OnGetMimeTypeFromFileForNativeLocalPathCompleted, local_path,
-                 base::Passed(&mime_type_from_extension), callback));
+      base::BindOnce(base::IgnoreResult(&net::GetMimeTypeFromFile), local_path,
+                     mime_type_from_extension_ptr),
+      base::BindOnce(&OnGetMimeTypeFromFileForNativeLocalPathCompleted,
+                     local_path, std::move(mime_type_from_extension),
+                     std::move(callback)));
 }
 
 MimeTypeCollector::MimeTypeCollector(content::BrowserContext* context)
@@ -173,20 +174,20 @@
 
 void MimeTypeCollector::CollectForURLs(
     const std::vector<storage::FileSystemURL>& urls,
-    const CompletionCallback& callback) {
+    CompletionCallback callback) {
   std::vector<base::FilePath> local_paths;
   for (size_t i = 0; i < urls.size(); ++i) {
     local_paths.push_back(urls[i].path());
   }
 
-  CollectForLocalPaths(local_paths, callback);
+  CollectForLocalPaths(local_paths, std::move(callback));
 }
 
 void MimeTypeCollector::CollectForLocalPaths(
     const std::vector<base::FilePath>& local_paths,
-    const CompletionCallback& callback) {
+    CompletionCallback callback) {
   DCHECK(!callback.is_null());
-  callback_ = callback;
+  callback_ = std::move(callback);
 
   DCHECK(!result_.get());
   result_.reset(new std::vector<std::string>(local_paths.size()));
@@ -195,15 +196,16 @@
   if (!left_) {
     // Nothing to process.
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(callback_, std::move(result_)));
-    callback_ = CompletionCallback();
+        FROM_HERE, base::BindOnce(std::move(callback_), std::move(result_)));
+    callback_.Reset();
     return;
   }
 
   for (size_t i = 0; i < local_paths.size(); ++i) {
-    GetMimeTypeForLocalPath(context_, local_paths[i],
-                            base::Bind(&MimeTypeCollector::OnMimeTypeCollected,
-                                       weak_ptr_factory_.GetWeakPtr(), i));
+    GetMimeTypeForLocalPath(
+        context_, local_paths[i],
+        base::BindOnce(&MimeTypeCollector::OnMimeTypeCollected,
+                       weak_ptr_factory_.GetWeakPtr(), i));
   }
 }
 
@@ -212,11 +214,11 @@
   (*result_)[index] = mime_type;
   if (!--left_) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(callback_, std::move(result_)));
+        FROM_HERE, base::BindOnce(std::move(callback_), std::move(result_)));
     // Release the callback to avoid a circullar reference in case an instance
     // of this class is a member of a ref counted class, which instance is bound
     // to this callback.
-    callback_ = CompletionCallback();
+    callback_.Reset();
   }
 }
 
diff --git a/extensions/browser/api/file_handlers/mime_util.h b/extensions/browser/api/file_handlers/mime_util.h
index 7765c95..7218dfa 100644
--- a/extensions/browser/api/file_handlers/mime_util.h
+++ b/extensions/browser/api/file_handlers/mime_util.h
@@ -37,7 +37,7 @@
 void GetMimeTypeForLocalPath(
     content::BrowserContext* context,
     const base::FilePath& local_path,
-    const base::Callback<void(const std::string&)>& callback);
+    base::OnceCallback<void(const std::string&)> callback);
 
 // Collects MIME types for files passed in the input vector. For non-native
 // file systems tries to fetch the MIME type from metadata. For native ones,
@@ -45,8 +45,8 @@
 // available, then an empty string is returned in the result vector.
 class MimeTypeCollector {
  public:
-  typedef base::Callback<void(std::unique_ptr<std::vector<std::string>>)>
-      CompletionCallback;
+  using CompletionCallback =
+      base::OnceCallback<void(std::unique_ptr<std::vector<std::string>>)>;
 
   explicit MimeTypeCollector(content::BrowserContext* context);
   virtual ~MimeTypeCollector();
@@ -54,12 +54,12 @@
   // Collects all mime types asynchronously for a vector of URLs and upon
   // completion, calls the |callback|. It can be called only once.
   void CollectForURLs(const std::vector<storage::FileSystemURL>& urls,
-                      const CompletionCallback& callback);
+                      CompletionCallback callback);
 
   // Collects all mime types asynchronously for a vector of local file paths and
   // upon completion, calls the |callback|. It can be called only once.
   void CollectForLocalPaths(const std::vector<base::FilePath>& local_paths,
-                            const CompletionCallback& callback);
+                            CompletionCallback callback);
 
  private:
   // Called, when the |index|-th input file (or URL) got processed.
diff --git a/extensions/browser/api/file_handlers/mime_util_unittest.cc b/extensions/browser/api/file_handlers/mime_util_unittest.cc
index 1e8e5f4..01581785 100644
--- a/extensions/browser/api/file_handlers/mime_util_unittest.cc
+++ b/extensions/browser/api/file_handlers/mime_util_unittest.cc
@@ -94,9 +94,10 @@
 TEST_F(FileHandlersMimeUtilTest, GetMimeTypeForLocalPath) {
   {
     std::string result;
-    GetMimeTypeForLocalPath(browser_context(), base::FilePath::FromUTF8Unsafe(
-                                                   kJPEGExtensionFilePath),
-                            base::Bind(&OnMimeTypeResult, &result));
+    GetMimeTypeForLocalPath(
+        browser_context(),
+        base::FilePath::FromUTF8Unsafe(kJPEGExtensionFilePath),
+        base::BindOnce(&OnMimeTypeResult, &result));
     content::RunAllTasksUntilIdle();
     EXPECT_EQ("image/jpeg", result);
   }
@@ -106,7 +107,7 @@
     GetMimeTypeForLocalPath(
         browser_context(),
         base::FilePath::FromUTF8Unsafe(kJPEGExtensionUpperCaseFilePath),
-        base::Bind(&OnMimeTypeResult, &result));
+        base::BindOnce(&OnMimeTypeResult, &result));
     content::RunAllTasksUntilIdle();
     EXPECT_EQ("image/jpeg", result);
   }
@@ -114,7 +115,7 @@
   {
     std::string result;
     GetMimeTypeForLocalPath(browser_context(), html_mime_file_path_,
-                            base::Bind(&OnMimeTypeResult, &result));
+                            base::BindOnce(&OnMimeTypeResult, &result));
     content::RunAllTasksUntilIdle();
     EXPECT_EQ("text/html", result);
   }
@@ -145,7 +146,8 @@
                                                 html_mime_file_path_));
 
   std::vector<std::string> result;
-  collector.CollectForURLs(urls, base::Bind(&OnMimeTypesCollected, &result));
+  collector.CollectForURLs(urls,
+                           base::BindOnce(&OnMimeTypesCollected, &result));
   content::RunAllTasksUntilIdle();
 
   ASSERT_EQ(3u, result.size());
@@ -164,8 +166,8 @@
   local_paths.push_back(html_mime_file_path_);
 
   std::vector<std::string> result;
-  collector.CollectForLocalPaths(local_paths,
-                                 base::Bind(&OnMimeTypesCollected, &result));
+  collector.CollectForLocalPaths(
+      local_paths, base::BindOnce(&OnMimeTypesCollected, &result));
   content::RunAllTasksUntilIdle();
 
   ASSERT_EQ(3u, result.size());
diff --git a/extensions/browser/api/file_handlers/non_native_file_system_delegate.h b/extensions/browser/api/file_handlers/non_native_file_system_delegate.h
index f430b849..e05fabd 100644
--- a/extensions/browser/api/file_handlers/non_native_file_system_delegate.h
+++ b/extensions/browser/api/file_handlers/non_native_file_system_delegate.h
@@ -46,7 +46,7 @@
   virtual void IsNonNativeLocalPathDirectory(
       content::BrowserContext* context,
       const base::FilePath& path,
-      const base::Callback<void(bool)>& callback) = 0;
+      base::OnceCallback<void(bool)> callback) = 0;
 
   // Ensures a non-local file exists at |path|, i.e., it does nothing if a file
   // is already present, or creates a file there if it isn't. Asynchronously
@@ -54,7 +54,7 @@
   virtual void PrepareNonNativeLocalFileForWritableApp(
       content::BrowserContext* context,
       const base::FilePath& path,
-      const base::Callback<void(bool)>& callback) = 0;
+      base::OnceCallback<void(bool)> callback) = 0;
 };
 
 }  // namespace extensions
diff --git a/fuchsia/engine/context_provider_impl.cc b/fuchsia/engine/context_provider_impl.cc
index f28ab685..e1759ff 100644
--- a/fuchsia/engine/context_provider_impl.cc
+++ b/fuchsia/engine/context_provider_impl.cc
@@ -147,6 +147,7 @@
     return true;
 
   static const base::StringPiece kAllowedArgs[] = {
+      switches::kEnableBlinkFeatures,
       switches::kRendererProcessLimit,
       switches::kMinHeightForGpuRasterTile,
   };
diff --git a/gpu/vulkan/demo/vulkan_demo.h b/gpu/vulkan/demo/vulkan_demo.h
index e1ca7307..3d8cd19 100644
--- a/gpu/vulkan/demo/vulkan_demo.h
+++ b/gpu/vulkan/demo/vulkan_demo.h
@@ -12,7 +12,7 @@
 #include "gpu/vulkan/vulkan_swap_chain.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
 #include "ui/gfx/geometry/size.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_delegate.h"
 
 class SkCanvas;
@@ -66,7 +66,7 @@
   scoped_refptr<viz::VulkanContextProvider> vulkan_context_provider_;
   gfx::AcceleratedWidget accelerated_widget_ = gfx::kNullAcceleratedWidget;
   std::unique_ptr<ui::PlatformEventSource> event_source_;
-  std::unique_ptr<ui::PlatformWindowBase> window_;
+  std::unique_ptr<ui::PlatformWindow> window_;
   std::unique_ptr<VulkanSurface> vulkan_surface_;
   base::Optional<VulkanSwapChain::ScopedWrite> scoped_write_;
   sk_sp<SkSurface> sk_surface_;
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index e52cd3cd..ac7254c3 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -854,8 +854,8 @@
 // An error occurred while handling a signed exchange.
 NET_ERROR(INVALID_SIGNED_EXCHANGE, -504)
 
-// An error occurred while handling a bundled-exchanges source.
-NET_ERROR(INVALID_BUNDLED_EXCHANGES, -505)
+// An error occurred while handling a Web Bundle source.
+NET_ERROR(INVALID_WEB_BUNDLE, -505)
 
 // *** Code -600 is reserved (was FTP_PASV_COMMAND_FAILED). ***
 
diff --git a/third_party/blink/common/feature_policy/feature_policy.cc b/third_party/blink/common/feature_policy/feature_policy.cc
index ed48d46..51db470 100644
--- a/third_party/blink/common/feature_policy/feature_policy.cc
+++ b/third_party/blink/common/feature_policy/feature_policy.cc
@@ -340,7 +340,7 @@
     case WebSandboxFlags::kPresentationController:
       return mojom::FeaturePolicyFeature::kPresentation;
     case WebSandboxFlags::kDownloads:
-      return mojom::FeaturePolicyFeature::kDownloadsWithoutUserActivation;
+      return mojom::FeaturePolicyFeature::kDownloads;
     // Other flags fall through to the bitmask test below. They are named
     // specifically here so that authors introducing new flags must consider
     // this method when adding them.
@@ -425,7 +425,7 @@
        {mojom::FeaturePolicyFeature::kDocumentWrite,
         FeatureDefaultValue(FeaturePolicy::FeatureDefault::EnableForAll,
                             mojom::PolicyValueType::kBool)},
-       {mojom::FeaturePolicyFeature::kDownloadsWithoutUserActivation,
+       {mojom::FeaturePolicyFeature::kDownloads,
         FeatureDefaultValue(FeaturePolicy::FeatureDefault::EnableForAll,
                             mojom::PolicyValueType::kBool)},
        {mojom::FeaturePolicyFeature::kEncryptedMedia,
diff --git a/third_party/blink/common/frame/frame_policy.cc b/third_party/blink/common/frame/frame_policy.cc
index 086fd6a..2f0e020 100644
--- a/third_party/blink/common/frame/frame_policy.cc
+++ b/third_party/blink/common/frame/frame_policy.cc
@@ -9,15 +9,14 @@
 FramePolicy::FramePolicy()
     : sandbox_flags(WebSandboxFlags::kNone),
       container_policy({}),
-      allowed_to_download_without_user_activation(true) {}
+      allowed_to_download(true) {}
 
 FramePolicy::FramePolicy(WebSandboxFlags sandbox_flags,
                          const ParsedFeaturePolicy& container_policy,
-                         bool allowed_to_download_without_user_activation)
+                         bool allowed_to_download)
     : sandbox_flags(sandbox_flags),
       container_policy(container_policy),
-      allowed_to_download_without_user_activation(
-          allowed_to_download_without_user_activation) {}
+      allowed_to_download(allowed_to_download) {}
 
 FramePolicy::FramePolicy(const FramePolicy& lhs) = default;
 
diff --git a/third_party/blink/common/frame/frame_policy_mojom_traits.cc b/third_party/blink/common/frame/frame_policy_mojom_traits.cc
index fdc90788..8526cbe 100644
--- a/third_party/blink/common/frame/frame_policy_mojom_traits.cc
+++ b/third_party/blink/common/frame/frame_policy_mojom_traits.cc
@@ -9,8 +9,7 @@
 bool StructTraits<blink::mojom::FramePolicyDataView, blink::FramePolicy>::Read(
     blink::mojom::FramePolicyDataView in,
     blink::FramePolicy* out) {
-  out->allowed_to_download_without_user_activation =
-      in.allowed_to_download_without_user_activation();
+  out->allowed_to_download = in.allowed_to_download();
 
   return in.ReadSandboxFlags(&out->sandbox_flags) &&
          in.ReadContainerPolicy(&out->container_policy);
diff --git a/third_party/blink/common/frame/frame_policy_mojom_traits.h b/third_party/blink/common/frame/frame_policy_mojom_traits.h
index afe109a..e4009769 100644
--- a/third_party/blink/common/frame/frame_policy_mojom_traits.h
+++ b/third_party/blink/common/frame/frame_policy_mojom_traits.h
@@ -15,9 +15,8 @@
 class BLINK_COMMON_EXPORT
     StructTraits<blink::mojom::FramePolicyDataView, blink::FramePolicy> {
  public:
-  static bool allowed_to_download_without_user_activation(
-      const blink::FramePolicy& frame_policy) {
-    return frame_policy.allowed_to_download_without_user_activation;
+  static bool allowed_to_download(const blink::FramePolicy& frame_policy) {
+    return frame_policy.allowed_to_download;
   }
 
   static const std::vector<blink::ParsedFeaturePolicyDeclaration>&
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index b7708841..ee87e73 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -273,7 +273,6 @@
     "platform/web_rtc_rtp_transceiver.h",
     "platform/web_rtc_stats.h",
     "platform/web_rtc_stats_request.h",
-    "platform/web_rtc_stats_response.h",
     "platform/web_runtime_features.h",
     "platform/web_scoped_page_pauser.h",
     "platform/web_screen_info.h",
diff --git a/third_party/blink/public/common/frame/frame_policy.h b/third_party/blink/public/common/frame/frame_policy.h
index a604241b..8807517 100644
--- a/third_party/blink/public/common/frame/frame_policy.h
+++ b/third_party/blink/public/common/frame/frame_policy.h
@@ -26,20 +26,20 @@
   FramePolicy();
   FramePolicy(WebSandboxFlags sandbox_flags,
               const ParsedFeaturePolicy& container_policy,
-              bool allowed_to_download_without_user_activation = true);
+              bool allowed_to_download = true);
   FramePolicy(const FramePolicy& lhs);
   ~FramePolicy();
 
   WebSandboxFlags sandbox_flags;
   ParsedFeaturePolicy container_policy;
   // With FeaturePolicyForSandbox, as a policy affecting the document,
-  // "downloads-without-user-activation" is included in |container_policy|.
+  // "downloads" is included in |container_policy|.
   // However, in certain cases where the initiator of the navigation is not the
   // document itself (e.g., a parent document), the FrameOwner element should be
   // checked for "downloads" flag. If this boolean is false then navigations
   // leading to downloads should be blocked unless they have user gesture. Note:
   // this flag is currently only set if the frame is sandboxed for downloads.
-  bool allowed_to_download_without_user_activation;
+  bool allowed_to_download;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/common/loader/throttling_url_loader.h b/third_party/blink/public/common/loader/throttling_url_loader.h
index 86f2214..6d1de571 100644
--- a/third_party/blink/public/common/loader/throttling_url_loader.h
+++ b/third_party/blink/public/common/loader/throttling_url_loader.h
@@ -215,7 +215,7 @@
     uint32_t options;
 
     network::ResourceRequest url_request;
-    // |task_runner_| is used to set up |client_binding_|.
+    // |task_runner| is used to set up |client_receiver_|.
     scoped_refptr<base::SingleThreadTaskRunner> task_runner;
   };
   // Holds any info needed to start or restart the request. Used when start is
diff --git a/third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom b/third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom
index 42ea361d..47fcb8ae 100644
--- a/third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom
+++ b/third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom
@@ -104,8 +104,8 @@
   // Loading policies.
   kLoadingFrameDefaultEager = 48,
 
-  // Implements sandbox flag: allow-downloads-without-user-activation.
-  kDownloadsWithoutUserActivation = 49,
+  // Implements sandbox flag: allow-downloads.
+  kDownloads = 49,
 
   // Allow execution while not in the viewport.
   kExecutionWhileOutOfViewport = 50,
diff --git a/third_party/blink/public/mojom/frame/frame_policy.mojom b/third_party/blink/public/mojom/frame/frame_policy.mojom
index 6f93e66..34fcf40 100644
--- a/third_party/blink/public/mojom/frame/frame_policy.mojom
+++ b/third_party/blink/public/mojom/frame/frame_policy.mojom
@@ -13,5 +13,5 @@
 struct FramePolicy {
   blink.mojom.WebSandboxFlags sandbox_flags;
   array<blink.mojom.ParsedFeaturePolicyDeclaration> container_policy;
-  bool allowed_to_download_without_user_activation = true;
+  bool allowed_to_download = true;
 };
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index c82ebd2..add0585 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2217,7 +2217,6 @@
   kSandboxBackForwardAffectsFramesOutsideSubtree = 2837,
   kDownloadPrePolicyCheck = 2838,
   kDownloadPostPolicyCheck = 2839,
-  kDownloadInSandboxWithoutUserGesture = 2840,
   kReadableStreamGetReader = 2841,
   kReadableStreamPipeThrough = 2842,
   kReadableStreamPipeTo = 2843,
diff --git a/third_party/blink/public/platform/linux/web_sandbox_support.h b/third_party/blink/public/platform/linux/web_sandbox_support.h
index 35da478..3aa803b 100644
--- a/third_party/blink/public/platform/linux/web_sandbox_support.h
+++ b/third_party/blink/public/platform/linux/web_sandbox_support.h
@@ -52,14 +52,15 @@
   // Get information to instantiate a font which contains glyphs for the given
   // Unicode code-point.
   //   character: a UTF-32 codepoint
-  //   preferredLocale: preferred locale identifier for the |characters|
-  //                    (e.g. "en", "ja", "zh-CN")
+  //   preferred_locale: preferred locale identifier for the |characters|
+  //                     (e.g. "en", "ja", "zh-CN")
   //
-  // Returns a FallbackFontData instance. If the request cannot be satisfied,
-  // the font name will be empty.
-  virtual void GetFallbackFontForCharacter(WebUChar32,
-                                           const char* preferred_locale,
-                                           gfx::FallbackFontData*) = 0;
+  // fallback_font will be filled with the font name and filename, among other
+  // data. Returns false if the request could not be satisfied.
+  virtual bool GetFallbackFontForCharacter(
+      WebUChar32 character,
+      const char* preferred_locale,
+      gfx::FallbackFontData* fallback_font) = 0;
 
   // Get a FallbackFontData specification for a font uniquely identified by full
   // font name or postscript name.  Specify full font name or postscript name as
@@ -67,8 +68,8 @@
   //
   // The FallbackFontData out parameter will contain a filename, ttc index and
   // fontconfig interface id, with the italic and bold members set always
-  // initialised to false.
-  virtual void MatchFontByPostscriptNameOrFullFontName(
+  // initialised to false. If a match is not found, return false.
+  virtual bool MatchFontByPostscriptNameOrFullFontName(
       const char* font_unique_name,
       gfx::FallbackFontData*) = 0;
 
diff --git a/third_party/blink/public/platform/web_rtc_stats_request.h b/third_party/blink/public/platform/web_rtc_stats_request.h
index 21049be..54d1a9c 100644
--- a/third_party/blink/public/platform/web_rtc_stats_request.h
+++ b/third_party/blink/public/platform/web_rtc_stats_request.h
@@ -39,17 +39,17 @@
 
 class RTCStatsRequest;
 class WebMediaStreamTrack;
-class WebRTCStatsResponse;
+class RTCStatsResponseBase;
 
 // The WebRTCStatsRequest class represents a JavaScript call on
 // RTCPeerConnection.getStats(). The user of this API will use
-// the calls on this class and WebRTCStatsResponse to fill in the
+// the calls on this class and RTCStatsResponseBase to fill in the
 // data that will be returned via a callback to the user in an
 // RTCStatsResponse structure.
 //
 // The typical usage pattern is:
 // WebRTCStatsRequest request = <from somewhere>
-// WebRTCStatsResponse response = request.CreateResponse();
+// RTCStatsResponseBase* response = request.CreateResponse();
 //
 // For each item on which statistics are going to be reported:
 //   WebRTCLegacyStats stats(...);
@@ -81,9 +81,9 @@
   // It is only useful to call it when HasSelector() returns true.
   BLINK_PLATFORM_EXPORT const WebMediaStreamTrack Component() const;
 
-  BLINK_PLATFORM_EXPORT void RequestSucceeded(const WebRTCStatsResponse&) const;
+  BLINK_PLATFORM_EXPORT void RequestSucceeded(RTCStatsResponseBase*) const;
 
-  BLINK_PLATFORM_EXPORT WebRTCStatsResponse CreateResponse() const;
+  BLINK_PLATFORM_EXPORT RTCStatsResponseBase* CreateResponse() const;
 
 #if INSIDE_BLINK
   BLINK_PLATFORM_EXPORT WebRTCStatsRequest(RTCStatsRequest*);
diff --git a/third_party/blink/public/platform/web_rtc_stats_response.h b/third_party/blink/public/platform/web_rtc_stats_response.h
deleted file mode 100644
index 5898276..0000000
--- a/third_party/blink/public/platform/web_rtc_stats_response.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_STATS_RESPONSE_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_STATS_RESPONSE_H_
-
-#include "third_party/blink/public/platform/web_common.h"
-#include "third_party/blink/public/platform/web_private_ptr.h"
-#include "third_party/blink/public/platform/web_rtc_legacy_stats.h"
-#include "third_party/blink/public/platform/web_string.h"
-
-namespace blink {
-
-class RTCStatsResponseBase;
-
-class WebRTCStatsResponse {
- public:
-  WebRTCStatsResponse(const WebRTCStatsResponse& other) { Assign(other); }
-  WebRTCStatsResponse() = default;
-  ~WebRTCStatsResponse() { Reset(); }
-
-  WebRTCStatsResponse& operator=(const WebRTCStatsResponse& other) {
-    Assign(other);
-    return *this;
-  }
-  BLINK_PLATFORM_EXPORT void Assign(const WebRTCStatsResponse&);
-  BLINK_PLATFORM_EXPORT void Reset();
-
-  BLINK_PLATFORM_EXPORT void AddStats(const WebRTCLegacyStats&);
-
-#if INSIDE_BLINK
-  BLINK_PLATFORM_EXPORT WebRTCStatsResponse(RTCStatsResponseBase*);
-  BLINK_PLATFORM_EXPORT operator RTCStatsResponseBase*() const;
-#endif
-
- private:
-  WebPrivatePtr<RTCStatsResponseBase> private_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_STATS_RESPONSE_H_
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h
index bac8761..05a33b9 100644
--- a/third_party/blink/public/web/web_local_frame.h
+++ b/third_party/blink/public/web/web_local_frame.h
@@ -543,8 +543,8 @@
   virtual WebSandboxFlags EffectiveSandboxFlagsForTesting() const = 0;
 
   // Returns false if this frame, or any parent frame is sandboxed and does not
-  // have the flag "allow-downloads-without-user-activation" set.
-  virtual bool IsAllowedToDownloadWithoutUserActivation() const = 0;
+  // have the flag "allow-downloads" set.
+  virtual bool IsAllowedToDownload() const = 0;
 
   // Find-in-page -----------------------------------------------------------
 
diff --git a/third_party/blink/public/web/web_navigation_params.h b/third_party/blink/public/web/web_navigation_params.h
index 9da5b78b..4ed133a 100644
--- a/third_party/blink/public/web/web_navigation_params.h
+++ b/third_party/blink/public/web/web_navigation_params.h
@@ -96,9 +96,8 @@
   // by the window.open'd frame.
   bool is_opener_navigation = false;
 
-  // Whether the runtime feature
-  // |BlockingDownloadsInSandboxWithoutUserActivation| is enabled.
-  bool blocking_downloads_in_sandbox_without_user_activation_enabled = false;
+  // Whether the runtime feature |BlockingDownloadsInSandbox| is enabled.
+  bool blocking_downloads_in_sandbox_enabled = false;
 
   // Event information. See TriggeringEventInfo.
   TriggeringEventInfo triggering_event_info = TriggeringEventInfo::kUnknown;
diff --git a/third_party/blink/public/web/web_remote_frame_client.h b/third_party/blink/public/web/web_remote_frame_client.h
index 02f38d1f..9d0b537 100644
--- a/third_party/blink/public/web/web_remote_frame_client.h
+++ b/third_party/blink/public/web/web_remote_frame_client.h
@@ -38,14 +38,13 @@
                                   WebDOMMessageEvent) {}
 
   // A remote frame was asked to start a navigation.
-  virtual void Navigate(
-      const WebURLRequest& request,
-      bool should_replace_current_entry,
-      bool is_opener_navigation,
-      bool has_download_sandbox_flag,
-      bool blocking_downloads_in_sandbox_without_user_activation_enabled,
-      bool initiator_frame_is_ad,
-      mojo::ScopedMessagePipeHandle blob_url_token) {}
+  virtual void Navigate(const WebURLRequest& request,
+                        bool should_replace_current_entry,
+                        bool is_opener_navigation,
+                        bool has_download_sandbox_flag,
+                        bool blocking_downloads_in_sandbox_enabled,
+                        bool initiator_frame_is_ad,
+                        mojo::ScopedMessagePipeHandle blob_url_token) {}
 
   virtual void FrameRectsChanged(const WebRect& local_frame_rect,
                                  const WebRect& screen_space_rect) {}
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py
new file mode 100644
index 0000000..0507f827
--- /dev/null
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py
@@ -0,0 +1,177 @@
+# Copyright 2019 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 web_idl
+
+
+class _Expr(object):
+    """
+    Represents an expression which is composable to produce another expression.
+
+    This is designed primarily to represent conditional expressions and basic
+    logical operators (expr_not, expr_and, expr_or) come along with.
+    """
+
+    def __init__(self, expr, is_compound=False):
+        assert isinstance(expr, (bool, str))
+        assert isinstance(is_compound, bool)
+
+        if isinstance(expr, bool):
+            self._text = "true" if expr else "false"
+        else:
+            self._text = expr
+        self._is_compound = is_compound
+        self._is_always_false = expr is False
+        self._is_always_true = expr is True
+
+    def __str__(self):
+        """
+        __str__ is designed to be used when composing another expression.  If
+        you'd only like to have a string representation, |to_text| works better.
+        """
+        if self._is_compound:
+            return "({})".format(self.to_text())
+        return self.to_text()
+
+    def to_text(self):
+        return self._text
+
+    @property
+    def is_always_false(self):
+        """
+        The expression is always False, and code generators have chances of
+        optimizations.
+        """
+        return self._is_always_false
+
+    @property
+    def is_always_true(self):
+        """
+        The expression is always True, and code generators have chances of
+        optimizations.
+        """
+        return self._is_always_true
+
+
+def _unary_op(op, term):
+    assert isinstance(op, str)
+    assert isinstance(term, _Expr)
+
+    return _Expr("{}{}".format(op, term), is_compound=True)
+
+
+def _binary_op(op, terms):
+    assert isinstance(op, str)
+    assert isinstance(terms, (list, tuple))
+    assert all(isinstance(term, _Expr) for term in terms)
+    assert all(
+        not (term.is_always_false or term.is_always_true) for term in terms)
+
+    return _Expr(op.join(map(str, terms)), is_compound=True)
+
+
+def expr_not(term):
+    assert isinstance(term, _Expr)
+
+    if term.is_always_false:
+        return _Expr(True)
+    if term.is_always_true:
+        return _Expr(False)
+    return _unary_op("!", term)
+
+
+def expr_and(terms):
+    assert isinstance(terms, (list, tuple))
+    assert all(isinstance(term, _Expr) for term in terms)
+    assert terms
+
+    if any(term.is_always_false for term in terms):
+        return _Expr(False)
+    terms = filter(lambda x: not x.is_always_true, terms)
+    if not terms:
+        return _Expr(True)
+    if len(terms) == 1:
+        return terms[0]
+    return _binary_op(" && ", terms)
+
+
+def expr_or(terms):
+    assert isinstance(terms, (list, tuple))
+    assert all(isinstance(term, _Expr) for term in terms)
+    assert terms
+
+    if any(term.is_always_true for term in terms):
+        return _Expr(True)
+    terms = filter(lambda x: not x.is_always_false, terms)
+    if not terms:
+        return _Expr(False)
+    if len(terms) == 1:
+        return terms[0]
+    return _binary_op(" || ", terms)
+
+
+def expr_from_exposure(exposure, in_global=None):
+    """
+    Args:
+        exposure: web_idl.Exposure
+        in_global: A global name of [Exposed] that the ExecutionContext is
+            supposed to be / represent.
+    """
+    assert isinstance(exposure, web_idl.Exposure)
+    assert in_global is None or isinstance(in_global, str)
+
+    def ref_enabled(feature):
+        return _Expr("RuntimeEnabledFeatures::{}Enabled()".format(feature))
+
+    top_terms = [_Expr(True)]
+
+    # [Exposed]
+    GLOBAL_NAME_TO_EXECUTION_CONTEXT_TEST = {
+        "AnimationWorklet": "IsAnimationWorkletGlobalScope",
+        "AudioWorklet": "IsAudioWorkletGlobalScope",
+        "DedicatedWorker": "IsDedicatedWorkerGlobalScope",
+        "LayoutWorklet": "IsLayoutWorkletGlobalScope",
+        "PaintWorklet": "IsPaintWorkletGlobalScope",
+        "ServiceWorker": "IsServiceWorkerGlobalScope",
+        "SharedWorker": "IsSharedWorkerGlobalScope",
+        "Window": "IsDocument",
+        "Worker": "IsWorkerGlobalScope",
+        "Worklet": "IsWorkletGlobalScope",
+    }
+    in_globals = set()
+    if in_global:
+        in_globals.add(in_global)
+        for category_name in ("Worker", "Worklet"):
+            if in_global.endswith(category_name):
+                in_globals.add(category_name)
+    exposed_terms = []
+    for entry in exposure.global_names_and_features:
+        terms = []
+        if entry.global_name not in in_globals:
+            pred = GLOBAL_NAME_TO_EXECUTION_CONTEXT_TEST[entry.global_name]
+            terms.append(_Expr("${{execution_context}}->{}()".format(pred)))
+        if entry.feature:
+            terms.append(ref_enabled(entry.feature))
+        if terms:
+            exposed_terms.append(expr_and(terms))
+    if exposed_terms:
+        top_terms.append(expr_or(exposed_terms))
+
+    # [RuntimeEnabled]
+    if exposure.runtime_enabled_features:
+        terms = map(ref_enabled, exposure.runtime_enabled_features)
+        top_terms.append(expr_or(terms))
+
+    # [SecureContext]
+    if exposure.only_in_secure_contexts is True:
+        top_terms.append(_Expr("${in_secure_context}"))
+    elif exposure.only_in_secure_contexts is False:
+        top_terms.append(_Expr(True))
+    else:
+        terms = map(ref_enabled, exposure.only_in_secure_contexts)
+        top_terms.append(
+            expr_or([_Expr("${in_secure_context}"),
+                     expr_not(expr_and(terms))]))
+
+    return expr_and(top_terms)
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py b/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
index d970272..9705d7a 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
@@ -93,7 +93,7 @@
     return func_def
 
 
-def make_dict_fill_with_members_def(cg_context):
+def make_fill_with_dict_members_def(cg_context):
     assert isinstance(cg_context, CodeGenContext)
 
     T = TextNode
@@ -128,7 +128,7 @@
     return func_def
 
 
-def make_dict_fill_with_own_members_def(cg_context):
+def make_fill_with_own_dict_members_def(cg_context):
     assert isinstance(cg_context, CodeGenContext)
 
     T = TextNode
@@ -190,8 +190,8 @@
 
     code_node = SymbolScopeNode()
 
-    code_node.append(make_dict_fill_with_members_def(cg_context))
-    code_node.append(make_dict_fill_with_own_members_def(cg_context))
+    code_node.append(make_fill_with_dict_members_def(cg_context))
+    code_node.append(make_fill_with_own_dict_members_def(cg_context))
     for member in sorted(dictionary.own_members, key=lambda x: x.identifier):
         code_node.extend([
             make_dict_member_get_def(cg_context.make_copy(dict_member=member)),
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
index e73ff46..4185916b 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -225,14 +225,15 @@
     _1 = "V8SetReturnValue"
     _2 = ["${info}", "${return_value}"]
 
-    if cg_context.return_type.unwrap().is_void:
+    return_type = cg_context.return_type.unwrap(nullable=True, typedef=True)
+    if return_type.is_void:
         # Render a SymbolNode |return_value| discarding the content text, and
         # let a symbol definition be added.
         pattern = "<% str(return_value) %>"
     elif (cg_context.for_world == cg_context.MAIN_WORLD
-          and cg_context.return_type.unwrap().is_interface):
+          and return_type.is_interface):
         _1 = "V8SetReturnValueForMainWorld"
-    elif cg_context.return_type.unwrap().is_interface:
+    elif return_type.is_interface:
         _2.append("${creation_context_object}")
 
     text = _format(pattern, _1=_1, _2=", ".join(_2))
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py b/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py
index a36af10..027b2a5 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py
@@ -30,16 +30,26 @@
 
 
 from .ast_group import AstGroup
+from .attribute import Attribute
 from .callback_function import CallbackFunction
 from .callback_interface import CallbackInterface
 from .composition_parts import Component
+from .constant import Constant
+from .constructor import Constructor
+from .constructor import ConstructorGroup
 from .database import Database
 from .database_builder import build_database
 from .dictionary import Dictionary
+from .dictionary import DictionaryMember
 from .enumeration import Enumeration
+from .exposure import Exposure
+from .function_like import FunctionLike
 from .idl_type import IdlType
 from .interface import Interface
 from .namespace import Namespace
+from .operation import Operation
+from .operation import OperationGroup
+from .overload_group import OverloadGroup
 from .runtime_enabled_features import RuntimeEnabledFeatures
 from .typedef import Typedef
 from .union import Union
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py b/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
index 78d98d8..c0e47648 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
@@ -152,9 +152,13 @@
 
     class Optionality(object):
         """https://heycam.github.io/webidl/#dfn-optionality-value"""
-        REQUIRED = 0
-        OPTIONAL = 1
-        VARIADIC = 2
+
+        class Type(str):
+            pass
+
+        REQUIRED = Type('required')
+        OPTIONAL = Type('optional')
+        VARIADIC = Type('variadic')
 
     def __init__(self,
                  is_optional=False,
@@ -219,7 +223,7 @@
         """
         callback(self)
 
-    def unwrap(self, nullable=None, typedef=None):
+    def unwrap(self, nullable=None, typedef=None, variadic=None):
         """
         Returns the body part of the actual type, i.e. returns the interesting
         part of this type.
@@ -237,6 +241,7 @@
         switches = {
             'nullable': nullable,
             'typedef': typedef,
+            'variadic': variadic,
         }
 
         value_counts = {None: 0, False: 0, True: 0}
@@ -886,6 +891,11 @@
     def is_variadic(self):
         return True
 
+    def _unwrap(self, switches):
+        if switches['variadic']:
+            return self.element_type._unwrap(switches)
+        return self
+
 
 class RecordType(IdlType):
     """https://heycam.github.io/webidl/#idl-record"""
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/overload_group.py b/third_party/blink/renderer/bindings/scripts/web_idl/overload_group.py
index dd87ed65..d7baba28 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/overload_group.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/overload_group.py
@@ -29,6 +29,38 @@
         def __len__(self):
             return len(self.functions)
 
+    class EffectiveOverloadItem(object):
+        """
+        Represents an item in an effective overload set.
+        https://heycam.github.io/webidl/#dfn-effective-overload-set
+        """
+
+        def __init__(self, function_like, type_list, opt_list):
+            assert len(type_list) == len(opt_list)
+            assert isinstance(function_like, FunctionLike)
+            assert isinstance(type_list, (list, tuple))
+            assert all(isinstance(idl_type, IdlType) for idl_type in type_list)
+            assert isinstance(opt_list, (list, tuple))
+            assert all(
+                isinstance(optionality, IdlType.Optionality.Type)
+                for optionality in opt_list)
+
+            self._function_like = function_like
+            self._type_list = tuple(type_list)
+            self._opt_list = tuple(opt_list)
+
+        @property
+        def function_like(self):
+            return self._function_like
+
+        @property
+        def type_list(self):
+            return self._type_list
+
+        @property
+        def opt_list(self):
+            return self._opt_list
+
     def __init__(self, functions):
         assert isinstance(functions, (list, tuple))
         assert all(
@@ -46,6 +78,9 @@
     def __len__(self):
         return len(self._functions)
 
+    def index(self, value):
+        return self._functions.index(value)
+
     @property
     def is_static(self):
         return self._is_static
@@ -61,27 +96,27 @@
     def effective_overload_set(self, argument_count=None):
         """
         Returns the effective overload set.
-
-        Returns:
-            List of (FunctionLike, (IdlType...), (IdlType.Optionality...)).
+        https://heycam.github.io/webidl/#compute-the-effective-overload-set
         """
         assert argument_count is None or isinstance(argument_count,
                                                     (int, long))
 
-        # https://heycam.github.io/webidl/#compute-the-effective-overload-set
         N = argument_count
         S = []
         F = self
 
         maxarg = max(map(lambda X: len(X.arguments), F))
         if N is None:
-            N = 1 + max([len(X.arguments) for X in F if not X.is_variadic])
+            arg_sizes = [len(X.arguments) for X in F if not X.is_variadic]
+            N = 1 + (max(arg_sizes) if arg_sizes else 0)
 
         for X in F:
             n = len(X.arguments)
 
-            S.append((X, map(lambda arg: arg.idl_type, X.arguments),
-                      map(lambda arg: arg.optionality, X.arguments)))
+            S.append(
+                OverloadGroup.EffectiveOverloadItem(
+                    X, map(lambda arg: arg.idl_type, X.arguments),
+                    map(lambda arg: arg.optionality, X.arguments)))
 
             if X.is_variadic:
                 for i in xrange(n, max(maxarg, N)):
@@ -90,24 +125,47 @@
                     for _ in xrange(n, i + 1):
                         t.append(X.arguments[-1].idl_type)
                         o.append(X.arguments[-1].optionality)
-                    S.append((X, t, o))
+                    S.append(OverloadGroup.EffectiveOverloadItem(X, t, o))
 
             t = map(lambda arg: arg.idl_type, X.arguments)
             o = map(lambda arg: arg.optionality, X.arguments)
             for i in xrange(n - 1, -1, -1):
                 if X.arguments[i].optionality == IdlType.Optionality.REQUIRED:
                     break
-                S.append((X, t[:i], o[:i]))
+                S.append(OverloadGroup.EffectiveOverloadItem(X, t[:i], o[:i]))
 
         return S
 
     @staticmethod
+    def distinguishing_argument_index(items_of_effective_overload_set):
+        """
+        Returns the distinguishing argument index.
+        https://heycam.github.io/webidl/#dfn-distinguishing-argument-index
+        """
+        items = items_of_effective_overload_set
+        assert isinstance(items, (list, tuple))
+        assert all(
+            isinstance(item, OverloadGroup.EffectiveOverloadItem)
+            for item in items)
+        assert len(items) > 1
+
+        for index in xrange(len(items[0].type_list)):
+            # Assume that the given items are valid, and we only need to test
+            # the two types.
+            if OverloadGroup.are_distinguishable_types(
+                    items[0].type_list[index], items[1].type_list[index]):
+                return index
+        assert False
+
+    @staticmethod
     def are_distinguishable_types(idl_type1, idl_type2):
-        """Returns True if the two given types are distinguishable."""
+        """
+        Returns True if the two given types are distinguishable.
+        https://heycam.github.io/webidl/#dfn-distinguishable
+        """
         assert isinstance(idl_type1, IdlType)
         assert isinstance(idl_type2, IdlType)
 
-        # https://heycam.github.io/webidl/#dfn-distinguishable
         # step 1. If one type includes a nullable type and the other type either
         #   includes a nullable type, is a union type with flattened member
         #   types including a dictionary type, or is a dictionary type, ...
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc
index a6e8c68..e83b708 100644
--- a/third_party/blink/renderer/core/animation/animation.cc
+++ b/third_party/blink/renderer/core/animation/animation.cc
@@ -77,13 +77,6 @@
   return milliseconds / 1000;
 }
 
-bool AreEqualOrNull(double a, double b) {
-  // Null values are represented as NaNs, which have the property NaN != NaN.
-  if (IsNull(a) && IsNull(b))
-    return true;
-  return a == b;
-}
-
 double Max(base::Optional<double> a, double b) {
   if (a.has_value())
     return std::max(a.value(), b);
@@ -262,7 +255,7 @@
 
   if (is_null) {
     // If the current time is resolved, then throw a TypeError.
-    if (!IsNull(CurrentTimeInternal())) {
+    if (CurrentTimeInternal()) {
       exception_state.ThrowTypeError(
           "currentTime may not be changed from resolved to unresolved");
     }
@@ -437,8 +430,8 @@
   return SecondsToMilliseconds(current_time);
 }
 
-double Animation::CurrentTimeInternal() const {
-  return hold_time_.value_or(CalculateCurrentTime().value_or(NullValue()));
+base::Optional<double> Animation::CurrentTimeInternal() const {
+  return hold_time_ ? hold_time_ : CalculateCurrentTime();
 }
 
 base::Optional<double> Animation::UnlimitedCurrentTimeInternal() const {
@@ -446,7 +439,7 @@
   CurrentTimeInternal();
 #endif
   return PlayStateInternal() == kPaused || !start_time_
-             ? ValueOrUnresolved(CurrentTimeInternal())
+             ? CurrentTimeInternal()
              : CalculateCurrentTime();
 }
 
@@ -718,7 +711,7 @@
     hold_time_ = base::nullopt;
 
   // 3. Let previous current time be animation’s current time.
-  double previous_current_time = CurrentTimeInternal();
+  base::Optional<double> previous_current_time = CurrentTimeInternal();
 
   // 4. Apply any pending playback rate on animation.
   ApplyPendingPlaybackRate();
@@ -741,7 +734,7 @@
     if (playback_rate_ != 0)
       hold_time_ = base::nullopt;
   } else {
-    hold_time_ = ValueOrUnresolved(previous_current_time);
+    hold_time_ = previous_current_time;
   }
 
   // TODO(crbug.com/960944): prune use of legacy flags.
@@ -769,8 +762,8 @@
   animation_play_state_ = CalculateAnimationPlayState();
 
   // Update user agent.
-  double new_current_time = CurrentTimeInternal();
-  if (!AreEqualOrNull(previous_current_time, new_current_time)) {
+  base::Optional<double> new_current_time = CurrentTimeInternal();
+  if (previous_current_time != new_current_time) {
     SetOutdated();
   } else if (!had_start_time && start_time_) {
     // Even though this animation is not outdated, time to effect change is
@@ -788,7 +781,7 @@
   PlayStateUpdateScope update_scope(*this, kTimingUpdateOnDemand,
                                     kSetCompositorPendingWithEffectChanged);
 
-  double stored_current_time = CurrentTimeInternal();
+  base::Optional<double> stored_current_time = CurrentTimeInternal();
   if (content_)
     content_->Detach();
   content_ = new_effect;
@@ -801,8 +794,8 @@
     new_effect->Attach(this);
     SetOutdated();
   }
-  if (!IsNull(stored_current_time))
-    SetCurrentTimeInternal(stored_current_time, kTimingUpdateOnDemand);
+  if (stored_current_time)
+    SetCurrentTimeInternal(stored_current_time.value(), kTimingUpdateOnDemand);
 }
 
 const char* Animation::PlayStateString(AnimationPlayState play_state) {
@@ -852,7 +845,7 @@
   //    * animation does not have either a pending play task or a pending pause
   //      task,
   //    then idle.
-  if (IsNull(CurrentTimeInternal()) && !pending())
+  if (!CurrentTimeInternal() && !pending())
     return kIdle;
 
   // 2. Either of the following conditions are true:
@@ -916,8 +909,8 @@
   //       If associated effect end for animation is positive infinity, throw an
   //       "InvalidStateError" DOMException and abort these steps. Otherwise,
   //       let animation’s hold time be associated effect end.
-  double current_time = CurrentTimeInternal();
-  if (IsNull(current_time)) {
+  base::Optional<double> current_time = CurrentTimeInternal();
+  if (!current_time) {
     if (playback_rate_ >= 0) {
       hold_time_ = 0;
     } else {
@@ -1017,14 +1010,13 @@
   //    is unresolved,
   //    Set animation’s hold time to zero.
   double effective_playback_rate = EffectivePlaybackRate();
-  double current_time = CurrentTimeInternal();
+  base::Optional<double> current_time = CurrentTimeInternal();
   if (effective_playback_rate > 0 && auto_rewind == AutoRewind::kEnabled &&
-      (IsNull(current_time) || current_time < 0 ||
-       current_time >= EffectEnd())) {
+      (!current_time || current_time < 0 || current_time >= EffectEnd())) {
     hold_time_ = 0;
   } else if (effective_playback_rate < 0 &&
              auto_rewind == AutoRewind::kEnabled &&
-             (IsNull(current_time) || current_time <= 0 ||
+             (!current_time || current_time <= 0 ||
               current_time > EffectEnd())) {
     if (EffectEnd() == std::numeric_limits<double>::infinity()) {
       exception_state.ThrowDOMException(
@@ -1033,7 +1025,7 @@
       return;
     }
     hold_time_ = EffectEnd();
-  } else if (effective_playback_rate == 0 && IsNull(current_time)) {
+  } else if (effective_playback_rate == 0 && !current_time) {
     hold_time_ = 0;
   }
 
@@ -1193,12 +1185,11 @@
   // required to accommodate timelines that may change direction. Without this
   // distinction, a once-finished animation would remain finished even when its
   // timeline progresses in the opposite direction.
-  double unconstrained_current_time =
-      did_seek ? CurrentTimeInternal()
-               : CalculateCurrentTime().value_or(NullValue());
+  base::Optional<double> unconstrained_current_time =
+      did_seek ? CurrentTimeInternal() : CalculateCurrentTime();
 
   // 2. Conditionally update the hold time.
-  if (!IsNull(unconstrained_current_time) && start_time_ && !pending_play_ &&
+  if (unconstrained_current_time && start_time_ && !pending_play_ &&
       !pending_pause_) {
     // Can seek outside the bounds of the active effect. Set the hold time to
     // the unconstrained value of the current time in the even that this update
@@ -1226,7 +1217,7 @@
   }
 
   // 3. Set the previous current time.
-  previous_current_time_ = ValueOrUnresolved(CurrentTimeInternal());
+  previous_current_time_ = CurrentTimeInternal();
 
   // 4. Set the current finished state.
   AnimationPlayState play_state = CalculateAnimationPlayState();
@@ -1595,9 +1586,14 @@
           start_time.value() - (EffectEnd() / fabs(EffectivePlaybackRate()));
     }
   } else {
-    time_offset =
-        reversed ? EffectEnd() - CurrentTimeInternal() : CurrentTimeInternal();
-    time_offset = time_offset / fabs(EffectivePlaybackRate());
+    base::Optional<double> current_time = CurrentTimeInternal();
+    if (current_time) {
+      time_offset =
+          reversed ? EffectEnd() - current_time.value() : current_time.value();
+      time_offset = time_offset / fabs(EffectivePlaybackRate());
+    } else {
+      time_offset = NullValue();
+    }
   }
 
   DCHECK(!start_time || !IsNull(start_time.value()));
@@ -1684,10 +1680,9 @@
   bool idle = PlayStateInternal() == kIdle;
 
   if (content_) {
-    base::Optional<double> inherited_time =
-        idle || !timeline_->CurrentTime()
-            ? base::nullopt
-            : ValueOrUnresolved(CurrentTimeInternal());
+    base::Optional<double> inherited_time = idle || !timeline_->CurrentTime()
+                                                ? base::nullopt
+                                                : CurrentTimeInternal();
 
     // Special case for end-exclusivity when playing backwards.
     if (inherited_time == 0 && EffectivePlaybackRate() < 0)
@@ -1717,7 +1712,8 @@
 void Animation::QueueFinishedEvent() {
   const AtomicString& event_type = event_type_names::kFinish;
   if (GetExecutionContext() && HasEventListeners(event_type)) {
-    double event_current_time = CurrentTimeInternal() * 1000;
+    double event_current_time =
+        SecondsToMilliseconds(CurrentTimeInternal().value_or(NullValue()));
     // TODO(crbug.com/916117): Handle NaN values for scroll-linked animations.
     pending_finished_event_ = MakeGarbageCollected<AnimationPlaybackEvent>(
         event_type, event_current_time, TimelineTime());
@@ -1751,11 +1747,13 @@
 
 base::Optional<AnimationTimeDelta> Animation::TimeToEffectChange() {
   DCHECK(!outdated_);
-  if (!start_time_ || hold_time_)
+  if (!start_time_ || hold_time_ || !playback_rate_)
     return base::nullopt;
 
   if (!content_) {
-    return AnimationTimeDelta::FromSecondsD(-CurrentTimeInternal() /
+    base::Optional<double> current_time = CurrentTimeInternal();
+    DCHECK(current_time);
+    return AnimationTimeDelta::FromSecondsD(-current_time.value() /
                                             playback_rate_);
   }
 
@@ -1992,8 +1990,10 @@
 void Animation::PauseForTesting(double pause_time) {
   SetCurrentTimeInternal(pause_time, kTimingUpdateOnDemand);
   if (HasActiveAnimationsOnCompositor()) {
+    base::Optional<double> current_time = CurrentTimeInternal();
+    DCHECK(current_time);
     ToKeyframeEffect(content_.Get())
-        ->PauseAnimationForTestingOnCompositor(CurrentTimeInternal());
+        ->PauseAnimationForTestingOnCompositor(current_time.value());
   }
 
   // Do not wait for animation ready to lock in the hold time. Otherwise,
diff --git a/third_party/blink/renderer/core/animation/animation.h b/third_party/blink/renderer/core/animation/animation.h
index c39d83e5..13c40ae 100644
--- a/third_party/blink/renderer/core/animation/animation.h
+++ b/third_party/blink/renderer/core/animation/animation.h
@@ -257,7 +257,7 @@
   // is pending is separate from the actual play state.
   AnimationPlayState PlayStateInternal() const;
 
-  double CurrentTimeInternal() const;
+  base::Optional<double> CurrentTimeInternal() const;
   void SetCurrentTimeInternal(double new_current_time);
   void SetCurrentTimeInternal(double new_current_time, TimingUpdateReason);
 
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index c873daf..9ecc1519 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -2880,6 +2880,7 @@
   }
   children_context.use_previous_in_flow = true;
 
+  AttachPseudoElement(kPseudoIdMarker, children_context);
   AttachPseudoElement(kPseudoIdBefore, children_context);
 
   if (ShadowRoot* shadow_root = GetShadowRoot()) {
@@ -2933,6 +2934,7 @@
     }
   }
 
+  DetachPseudoElement(kPseudoIdMarker, performing_reattach);
   DetachPseudoElement(kPseudoIdBefore, performing_reattach);
 
   // TODO(futhark): We need to traverse into IsUserActionElement() subtrees,
@@ -3078,6 +3080,7 @@
 
   if (child_change.TraversePseudoElements(*this)) {
     UpdatePseudoElement(kPseudoIdBackdrop, child_change);
+    UpdatePseudoElement(kPseudoIdMarker, child_change);
     UpdatePseudoElement(kPseudoIdBefore, child_change);
   }
 
@@ -3358,6 +3361,7 @@
     else
       RebuildChildrenLayoutTrees(*child_attacher);
     RebuildPseudoElementLayoutTree(kPseudoIdBefore, *child_attacher);
+    RebuildPseudoElementLayoutTree(kPseudoIdMarker, *child_attacher);
     RebuildPseudoElementLayoutTree(kPseudoIdBackdrop, *child_attacher);
     RebuildFirstLetterLayoutTree();
     ClearChildNeedsReattachLayoutTree();
diff --git a/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc b/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
index 50fef4d..d2571c6 100644
--- a/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
+++ b/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
@@ -116,10 +116,6 @@
       !parent_layout_object->BehavesLikeBlockContainer())
     return nullptr;
 
-  LayoutObject* marker =
-      parent_layout_object->IsLayoutNGListItem()
-          ? ToLayoutNGListItem(parent_layout_object)->Marker()
-          : nullptr;
   // Drill down into our children and look for our first text child.
   LayoutObject* first_letter_text_layout_object =
       parent_layout_object->SlowFirstChild();
@@ -146,8 +142,8 @@
         break;
       first_letter_text_layout_object =
           first_letter_text_layout_object->NextSibling();
-    } else if (first_letter_text_layout_object->IsListMarker() ||
-               first_letter_text_layout_object == marker) {
+    } else if (first_letter_text_layout_object
+                   ->IsListMarkerIncludingNGInside()) {
       // The list item marker may have out-of-flow siblings inside an anonymous
       // block. Skip them to make sure we leave the anonymous block before
       // continuing looking for the first letter text.
@@ -186,9 +182,6 @@
       // setting up the first letter then.
       return nullptr;
     } else {
-      if (first_letter_text_layout_object->IsLayoutNGListItem())
-        marker = ToLayoutNGListItem(first_letter_text_layout_object)->Marker();
-
       first_letter_text_layout_object =
           first_letter_text_layout_object->SlowFirstChild();
     }
diff --git a/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc b/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc
index ef14740..031c54abae 100644
--- a/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc
+++ b/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc
@@ -88,40 +88,74 @@
 }
 
 Node* LayoutTreeBuilderTraversal::NextSibling(const Node& node) {
-  if (node.IsBeforePseudoElement()) {
+  PseudoId pseudo_id = node.GetPseudoId();
+  Element* parent_element;
+  if (pseudo_id != kPseudoIdNone) {
     AssertPseudoElementParent(To<PseudoElement>(node));
-    if (Node* next = FlatTreeTraversal::FirstChild(*node.parentNode()))
-      return next;
-  } else {
-    if (node.IsAfterPseudoElement())
-      return nullptr;
-    if (Node* next = FlatTreeTraversal::NextSibling(node))
-      return next;
+    parent_element = DynamicTo<Element>(*node.parentNode());
   }
-
-  if (auto* parent_element =
-          DynamicTo<Element>(FlatTreeTraversal::Parent(node)))
-    return parent_element->GetPseudoElement(kPseudoIdAfter);
-
+  switch (pseudo_id) {
+    case kPseudoIdMarker:
+      if (Node* next = parent_element->GetPseudoElement(kPseudoIdBefore))
+        return next;
+      FALLTHROUGH;
+    case kPseudoIdBefore:
+      if (Node* next = FlatTreeTraversal::FirstChild(*parent_element))
+        return next;
+      FALLTHROUGH;
+    case kPseudoIdNone:
+      if (pseudo_id == kPseudoIdNone) {  // Not falling through
+        if (Node* next = FlatTreeTraversal::NextSibling(node))
+          return next;
+        parent_element = DynamicTo<Element>(FlatTreeTraversal::Parent(node));
+      }
+      if (parent_element) {
+        if (Node* next = parent_element->GetPseudoElement(kPseudoIdAfter))
+          return next;
+      }
+      FALLTHROUGH;
+    case kPseudoIdAfter:
+      break;
+    default:
+      NOTREACHED();
+  }
   return nullptr;
 }
 
 Node* LayoutTreeBuilderTraversal::PreviousSibling(const Node& node) {
-  if (node.IsAfterPseudoElement()) {
+  PseudoId pseudo_id = node.GetPseudoId();
+  Element* parent_element;
+  if (pseudo_id != kPseudoIdNone) {
     AssertPseudoElementParent(To<PseudoElement>(node));
-    if (Node* previous = FlatTreeTraversal::LastChild(*node.parentNode()))
-      return previous;
-  } else {
-    if (node.IsBeforePseudoElement())
-      return nullptr;
-    if (Node* previous = FlatTreeTraversal::PreviousSibling(node))
-      return previous;
+    parent_element = DynamicTo<Element>(*node.parentNode());
   }
-
-  if (auto* parent_element =
-          DynamicTo<Element>(FlatTreeTraversal::Parent(node)))
-    return parent_element->GetPseudoElement(kPseudoIdBefore);
-
+  switch (pseudo_id) {
+    case kPseudoIdAfter:
+      if (Node* previous = FlatTreeTraversal::LastChild(*parent_element))
+        return previous;
+      FALLTHROUGH;
+    case kPseudoIdNone:
+      if (pseudo_id == kPseudoIdNone) {  // Not falling through
+        if (Node* previous = FlatTreeTraversal::PreviousSibling(node))
+          return previous;
+        parent_element = DynamicTo<Element>(FlatTreeTraversal::Parent(node));
+      }
+      if (parent_element) {
+        if (Node* previous = parent_element->GetPseudoElement(kPseudoIdBefore))
+          return previous;
+      }
+      FALLTHROUGH;
+    case kPseudoIdBefore:
+      if (parent_element) {
+        if (Node* previous = parent_element->GetPseudoElement(kPseudoIdMarker))
+          return previous;
+      }
+      FALLTHROUGH;
+    case kPseudoIdMarker:
+      break;
+    default:
+      NOTREACHED();
+  }
   return nullptr;
 }
 
@@ -130,13 +164,13 @@
   if (!current_element)
     return FlatTreeTraversal::LastChild(node);
 
-  Node* last = current_element->GetPseudoElement(kPseudoIdAfter);
-  if (last)
+  if (Node* last = current_element->GetPseudoElement(kPseudoIdAfter))
     return last;
-  last = FlatTreeTraversal::LastChild(*current_element);
-  if (!last)
-    last = current_element->GetPseudoElement(kPseudoIdBefore);
-  return last;
+  if (Node* last = FlatTreeTraversal::LastChild(*current_element))
+    return last;
+  if (Node* last = current_element->GetPseudoElement(kPseudoIdBefore))
+    return last;
+  return current_element->GetPseudoElement(kPseudoIdMarker);
 }
 
 Node* LayoutTreeBuilderTraversal::Previous(const Node& node,
@@ -157,13 +191,13 @@
   if (!current_element)
     return FlatTreeTraversal::FirstChild(node);
 
-  Node* first = current_element->GetPseudoElement(kPseudoIdBefore);
-  if (first)
+  if (Node* first = current_element->GetPseudoElement(kPseudoIdMarker))
     return first;
-  first = FlatTreeTraversal::FirstChild(node);
-  if (!first)
-    first = current_element->GetPseudoElement(kPseudoIdAfter);
-  return first;
+  if (Node* first = current_element->GetPseudoElement(kPseudoIdBefore))
+    return first;
+  if (Node* first = FlatTreeTraversal::FirstChild(node))
+    return first;
+  return current_element->GetPseudoElement(kPseudoIdAfter);
 }
 
 static Node* NextAncestorSibling(const Node& node, const Node* stay_within) {
diff --git a/third_party/blink/renderer/core/dom/layout_tree_builder_traversal_test.cc b/third_party/blink/renderer/core/dom/layout_tree_builder_traversal_test.cc
index ad34ed77..ae5c6fb 100644
--- a/third_party/blink/renderer/core/dom/layout_tree_builder_traversal_test.cc
+++ b/third_party/blink/renderer/core/dom/layout_tree_builder_traversal_test.cc
@@ -39,6 +39,8 @@
 TEST_F(LayoutTreeBuilderTraversalTest, pseudos) {
   const char* const kHtml =
       "<style>"
+      "#top { display: list-item; }"
+      "#top::marker { content: \"baz\"; }"
       "#top::before { content: \"foo\"; }"
       "#top::after { content: \"bar\"; }"
       "</style>"
@@ -46,14 +48,17 @@
   SetupSampleHTML(kHtml);
 
   Element* top = GetDocument().QuerySelector("#top");
+  Element* marker = top->GetPseudoElement(kPseudoIdMarker);
   Element* before = top->GetPseudoElement(kPseudoIdBefore);
   Element* after = top->GetPseudoElement(kPseudoIdAfter);
-  EXPECT_EQ(before, LayoutTreeBuilderTraversal::Next(*top, nullptr));
+  EXPECT_EQ(marker, LayoutTreeBuilderTraversal::Next(*top, nullptr));
+  EXPECT_EQ(before, LayoutTreeBuilderTraversal::NextSibling(*marker));
   EXPECT_EQ(after, LayoutTreeBuilderTraversal::NextSibling(*before));
-  EXPECT_EQ(nullptr, LayoutTreeBuilderTraversal::PreviousSibling(*before));
   EXPECT_EQ(nullptr, LayoutTreeBuilderTraversal::NextSibling(*after));
   EXPECT_EQ(before, LayoutTreeBuilderTraversal::PreviousSibling(*after));
-  EXPECT_EQ(before, LayoutTreeBuilderTraversal::FirstChild(*top));
+  EXPECT_EQ(marker, LayoutTreeBuilderTraversal::PreviousSibling(*before));
+  EXPECT_EQ(nullptr, LayoutTreeBuilderTraversal::PreviousSibling(*marker));
+  EXPECT_EQ(marker, LayoutTreeBuilderTraversal::FirstChild(*top));
   EXPECT_EQ(after, LayoutTreeBuilderTraversal::LastChild(*top));
 }
 
diff --git a/third_party/blink/renderer/core/dom/node.h b/third_party/blink/renderer/core/dom/node.h
index b713f855..66a9719 100644
--- a/third_party/blink/renderer/core/dom/node.h
+++ b/third_party/blink/renderer/core/dom/node.h
@@ -286,6 +286,9 @@
   DISABLE_CFI_PERF bool IsAfterPseudoElement() const {
     return GetPseudoId() == kPseudoIdAfter;
   }
+  DISABLE_CFI_PERF bool IsMarkerPseudoElement() const {
+    return GetPseudoId() == kPseudoIdMarker;
+  }
   DISABLE_CFI_PERF bool IsFirstLetterPseudoElement() const {
     return GetPseudoId() == kPseudoIdFirstLetter;
   }
diff --git a/third_party/blink/renderer/core/dom/pseudo_element.cc b/third_party/blink/renderer/core/dom/pseudo_element.cc
index 248de8e..e90fa42 100644
--- a/third_party/blink/renderer/core/dom/pseudo_element.cc
+++ b/third_party/blink/renderer/core/dom/pseudo_element.cc
@@ -70,6 +70,11 @@
                           (g_null_atom, "<pseudo:first-letter>", g_null_atom));
       return first_letter;
     }
+    case kPseudoIdMarker: {
+      DEFINE_STATIC_LOCAL(QualifiedName, marker,
+                          (g_null_atom, "<pseudo:marker>", g_null_atom));
+      return marker;
+    }
     default:
       NOTREACHED();
   }
@@ -81,11 +86,14 @@
 String PseudoElement::PseudoElementNameForEvents(PseudoId pseudo_id) {
   DEFINE_STATIC_LOCAL(const String, after, ("::after"));
   DEFINE_STATIC_LOCAL(const String, before, ("::before"));
+  DEFINE_STATIC_LOCAL(const String, marker, ("::marker"));
   switch (pseudo_id) {
     case kPseudoIdAfter:
       return after;
     case kPseudoIdBefore:
       return before;
+    case kPseudoIdMarker:
+      return marker;
     default:
       return g_empty_string;
   }
@@ -175,7 +183,8 @@
 
   const ComputedStyle& style = layout_object->StyleRef();
   if (style.StyleType() != kPseudoIdBefore &&
-      style.StyleType() != kPseudoIdAfter)
+      style.StyleType() != kPseudoIdAfter &&
+      style.StyleType() != kPseudoIdMarker)
     return;
   DCHECK(style.GetContentData());
 
diff --git a/third_party/blink/renderer/core/dom/pseudo_element_data.h b/third_party/blink/renderer/core/dom/pseudo_element_data.h
index a86bd42..a94702a 100644
--- a/third_party/blink/renderer/core/dom/pseudo_element_data.h
+++ b/third_party/blink/renderer/core/dom/pseudo_element_data.h
@@ -22,6 +22,7 @@
   void Trace(Visitor* visitor) {
     visitor->Trace(generated_before_);
     visitor->Trace(generated_after_);
+    visitor->Trace(generated_marker_);
     visitor->Trace(generated_first_letter_);
     visitor->Trace(backdrop_);
   }
@@ -29,19 +30,21 @@
  private:
   Member<PseudoElement> generated_before_;
   Member<PseudoElement> generated_after_;
+  Member<PseudoElement> generated_marker_;
   Member<PseudoElement> generated_first_letter_;
   Member<PseudoElement> backdrop_;
   DISALLOW_COPY_AND_ASSIGN(PseudoElementData);
 };
 
 inline bool PseudoElementData::HasPseudoElements() const {
-  return generated_before_ || generated_after_ || backdrop_ ||
-         generated_first_letter_;
+  return generated_before_ || generated_after_ || generated_marker_ ||
+         backdrop_ || generated_first_letter_;
 }
 
 inline void PseudoElementData::ClearPseudoElements() {
   SetPseudoElement(kPseudoIdBefore, nullptr);
   SetPseudoElement(kPseudoIdAfter, nullptr);
+  SetPseudoElement(kPseudoIdMarker, nullptr);
   SetPseudoElement(kPseudoIdBackdrop, nullptr);
   SetPseudoElement(kPseudoIdFirstLetter, nullptr);
 }
@@ -59,6 +62,11 @@
         generated_after_->Dispose();
       generated_after_ = element;
       break;
+    case kPseudoIdMarker:
+      if (generated_marker_)
+        generated_marker_->Dispose();
+      generated_marker_ = element;
+      break;
     case kPseudoIdBackdrop:
       if (backdrop_)
         backdrop_->Dispose();
@@ -80,6 +88,8 @@
     return generated_before_;
   if (kPseudoIdAfter == pseudo_id)
     return generated_after_;
+  if (kPseudoIdMarker == pseudo_id)
+    return generated_marker_;
 // Workaround for CPU bug. This avoids compiler optimizing
 // this group of if conditions into switch. See http://crbug.com/855390.
 #if defined(ARCH_CPU_ARMEL)
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
index 6823f05..abbf6f7bd 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -540,10 +540,8 @@
     navigation_info->initiator_frame_is_ad = frame->IsAdSubframe();
   }
 
-  navigation_info
-      ->blocking_downloads_in_sandbox_without_user_activation_enabled =
-      RuntimeEnabledFeatures::
-          BlockingDownloadsInSandboxWithoutUserActivationEnabled();
+  navigation_info->blocking_downloads_in_sandbox_enabled =
+      RuntimeEnabledFeatures::BlockingDownloadsInSandboxEnabled();
 
   // The frame has navigated either by itself or by the action of the
   // |origin_document| when it is defined. |source_location| represents the
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index 263fd11..859b162 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -9506,14 +9506,13 @@
   ~RemoteNavigationClient() override = default;
 
   // frame_test_helpers::TestWebRemoteFrameClient:
-  void Navigate(
-      const WebURLRequest& request,
-      bool should_replace_current_entry,
-      bool is_opener_navigation,
-      bool has_download_sandbox_flag,
-      bool blocking_downloads_in_sandbox_without_user_activation_enabled,
-      bool initiator_frame_is_ad,
-      mojo::ScopedMessagePipeHandle) override {
+  void Navigate(const WebURLRequest& request,
+                bool should_replace_current_entry,
+                bool is_opener_navigation,
+                bool has_download_sandbox_flag,
+                bool blocking_downloads_in_sandbox_enabled,
+                bool initiator_frame_is_ad,
+                mojo::ScopedMessagePipeHandle) override {
     last_request_ = request;
   }
 
diff --git a/third_party/blink/renderer/core/exported/web_node_test.cc b/third_party/blink/renderer/core/exported/web_node_test.cc
index 641e40a..a839796 100644
--- a/third_party/blink/renderer/core/exported/web_node_test.cc
+++ b/third_party/blink/renderer/core/exported/web_node_test.cc
@@ -14,6 +14,7 @@
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_test.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 
 namespace blink {
 
@@ -76,13 +77,20 @@
 
   css_resource.Start();
 
-  EXPECT_TRUE(GetDocument().GetStyleEngine().HasPendingRenderBlockingSheets());
-
   WebNode input_node(GetDocument().getElementById("focusable"));
   EXPECT_FALSE(input_node.IsFocusable());
+  EXPECT_EQ(!RuntimeEnabledFeatures::BlockHTMLParserOnStyleSheetsEnabled(),
+            GetDocument().GetStyleEngine().HasPendingRenderBlockingSheets());
 
   main_resource.Finish();
   css_resource.Complete("dummy {}");
+  test::RunPendingTasks();
+
+  if (RuntimeEnabledFeatures::BlockHTMLParserOnStyleSheetsEnabled()) {
+    // Need to re-initialize the WebNode since it was null on construction.
+    EXPECT_TRUE(input_node.IsNull());
+    input_node = GetDocument().getElementById("focusable");
+  }
   EXPECT_TRUE(input_node.IsFocusable());
 }
 
diff --git a/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5 b/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5
index 0a45c28..c3b821b 100644
--- a/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5
+++ b/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5
@@ -118,8 +118,8 @@
       depends_on: ["ExperimentalProductivityFeatures"],
     },
     {
-      name: "DownloadsWithoutUserActivation",
-      feature_policy_name: "downloads-without-user-activation",
+      name: "Downloads",
+      feature_policy_name: "downloads",
       depends_on: ["FeaturePolicyForSandbox"],
     },
     {
diff --git a/third_party/blink/renderer/core/fetch/body_stream_buffer.cc b/third_party/blink/renderer/core/fetch/body_stream_buffer.cc
index 911f152..8fdac05 100644
--- a/third_party/blink/renderer/core/fetch/body_stream_buffer.cc
+++ b/third_party/blink/renderer/core/fetch/body_stream_buffer.cc
@@ -107,18 +107,19 @@
       consumer_(consumer),
       signal_(signal),
       made_from_readable_stream_(false) {
-  // This CHECK is temporary to track down the cause of
+  // inside_create_stream_ is set to track down the cause of the crash in
   // https://crbug.com/1007162.
-  // TODO(ricea): Remove it once we know whether it crashes or not.
+  // TODO(ricea): Remove it and the CHECK once the cause is found.
+  inside_create_stream_ = true;
   CHECK(consumer_);
 
   stream_ =
       ReadableStream::CreateWithCountQueueingStrategy(script_state_, this, 0);
   stream_broken_ = !stream_;
 
-  // This CHECK is temporary to track down the cause of
-  // https://crbug.com/1007162.
-  // TODO(ricea): Remove it once we know whether it crashes or not.
+  // TODO(ricea): Remove this and the CHECK once https://crbug.com/1007162 is
+  // fixed.
+  inside_create_stream_ = false;
   CHECK(consumer_);
 
   consumer_->SetClient(this);
@@ -426,6 +427,9 @@
 
 void BodyStreamBuffer::CancelConsumer() {
   if (consumer_) {
+    // TODO(ricea): Remove this CHECK once the cause of
+    // https://crbug.com/1007162 is found.
+    CHECK(!inside_create_stream_);
     consumer_->Cancel();
     consumer_ = nullptr;
   }
@@ -539,6 +543,9 @@
   if (exception_state.HadException())
     return nullptr;
 
+  // TODO(ricea): Remove this CHECK once the cause of https://crbug.com/1007162
+  // is found.
+  CHECK(!inside_create_stream_);
   BytesConsumer* consumer = consumer_.Release();
 
   CloseAndLockAndDisturb(exception_state);
diff --git a/third_party/blink/renderer/core/fetch/body_stream_buffer.h b/third_party/blink/renderer/core/fetch/body_stream_buffer.h
index a4789ada..e38a66a69 100644
--- a/third_party/blink/renderer/core/fetch/body_stream_buffer.h
+++ b/third_party/blink/renderer/core/fetch/body_stream_buffer.h
@@ -108,6 +108,11 @@
   bool made_from_readable_stream_;
   bool in_process_data_ = false;
   bool stream_broken_ = false;
+
+  // TODO(ricea): Remove this once the cause of https://crbug.com/1007162 has
+  // been established.
+  bool inside_create_stream_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(BodyStreamBuffer);
 };
 
diff --git a/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc b/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc
index 4978de5b9..2e0089d 100644
--- a/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc
@@ -105,15 +105,14 @@
     bool has_download_sandbox_flag,
     bool initiator_frame_is_ad,
     mojo::PendingRemote<mojom::blink::BlobURLToken> blob_url_token) {
-  bool blocking_downloads_in_sandbox_without_user_activation_enabled =
-      RuntimeEnabledFeatures::
-          BlockingDownloadsInSandboxWithoutUserActivationEnabled();
+  bool blocking_downloads_in_sandbox_enabled =
+      RuntimeEnabledFeatures::BlockingDownloadsInSandboxEnabled();
   if (web_frame_->Client()) {
     web_frame_->Client()->Navigate(
         WrappedResourceRequest(request), should_replace_current_entry,
         is_opener_navigation, has_download_sandbox_flag,
-        blocking_downloads_in_sandbox_without_user_activation_enabled,
-        initiator_frame_is_ad, blob_url_token.PassPipe());
+        blocking_downloads_in_sandbox_enabled, initiator_frame_is_ad,
+        blob_url_token.PassPipe());
   }
 }
 
diff --git a/third_party/blink/renderer/core/frame/sandbox_flags.cc b/third_party/blink/renderer/core/frame/sandbox_flags.cc
index bed022e..ef0979b 100644
--- a/third_party/blink/renderer/core/frame/sandbox_flags.cc
+++ b/third_party/blink/renderer/core/frame/sandbox_flags.cc
@@ -54,7 +54,7 @@
         {WebSandboxFlags::kPresentationController,
          mojom::FeaturePolicyFeature::kPresentation},
         {WebSandboxFlags::kDownloads,
-         mojom::FeaturePolicyFeature::kDownloadsWithoutUserActivation}}));
+         mojom::FeaturePolicyFeature::kDownloads}}));
   return array;
 }
 
@@ -109,8 +109,7 @@
     } else if (EqualIgnoringASCIICase(
                    sandbox_token, "allow-top-navigation-by-user-activation")) {
       flags = flags & ~WebSandboxFlags::kTopNavigationByUserActivation;
-    } else if (EqualIgnoringASCIICase(
-                   sandbox_token, "allow-downloads-without-user-activation")) {
+    } else if (EqualIgnoringASCIICase(sandbox_token, "allow-downloads")) {
       flags = flags & ~WebSandboxFlags::kDownloads;
     } else if (RuntimeEnabledFeatures::StorageAccessAPIEnabled() &&
                EqualIgnoringASCIICase(
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index e8ec4867..7159b6a 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -2416,7 +2416,7 @@
     // part of sandbox converted to FeaturePolicies. That said, with
     // FeaturePolicyForSandbox all such flags should be part of the document's
     // FeaturePolicy. For certain flags such as "downloads", dedicated API
-    // should be used (see IsAllowedToDownloadWithoutUserActivation()).
+    // should be used (see IsAllowedToDownload()).
     auto* local_owner = GetFrame()->DeprecatedLocalOwner();
     if (local_owner &&
         local_owner->OwnerType() == FrameOwnerElementType::kIframe) {
@@ -2427,23 +2427,20 @@
   return static_cast<WebSandboxFlags>(flags);
 }
 
-bool WebLocalFrameImpl::IsAllowedToDownloadWithoutUserActivation() const {
+bool WebLocalFrameImpl::IsAllowedToDownload() const {
   if (!GetFrame())
     return true;
 
   if (RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled()) {
     // Downloads could be disabled if the parent frame's FeaturePolicy does not
-    // allow "downloads-without-user-activation".
+    // allow downloads.
     if (GetFrame()->Tree().Parent() &&
         !GetFrame()->Tree().Parent()->GetSecurityContext()->IsFeatureEnabled(
-            mojom::FeaturePolicyFeature::kDownloadsWithoutUserActivation)) {
+            mojom::FeaturePolicyFeature::kDownloads)) {
       return false;
     }
     return !GetFrame()->Owner() ||
-           GetFrame()
-               ->Owner()
-               ->GetFramePolicy()
-               .allowed_to_download_without_user_activation;
+           GetFrame()->Owner()->GetFramePolicy().allowed_to_download;
   } else {
     return (GetFrame()->Loader().EffectiveSandboxFlags() &
             WebSandboxFlags::kDownloads) == WebSandboxFlags::kNone;
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index f70d370..e3d4a36 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -255,7 +255,7 @@
   void DidCallAddSearchProvider() override;
   void DidCallIsSearchProviderInstalled() override;
   WebSandboxFlags EffectiveSandboxFlagsForTesting() const override;
-  bool IsAllowedToDownloadWithoutUserActivation() const override;
+  bool IsAllowedToDownload() const override;
   bool FindForTesting(int identifier,
                       const WebString& search_text,
                       bool match_case,
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc
index 8f1ef31..c4f5f24 100644
--- a/third_party/blink/renderer/core/html/html_anchor_element.cc
+++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -80,13 +80,8 @@
   }
   if (document.IsSandboxed(WebSandboxFlags::kDownloads)) {
     UseCounter::Count(document, WebFeature::kDownloadInSandbox);
-    if (!has_gesture) {
-      UseCounter::Count(document,
-                        WebFeature::kDownloadInSandboxWithoutUserGesture);
-      if (RuntimeEnabledFeatures::
-              BlockingDownloadsInSandboxWithoutUserActivationEnabled())
-        should_intervene_download = true;
-    }
+    if (RuntimeEnabledFeatures::BlockingDownloadsInSandboxEnabled())
+      should_intervene_download = true;
   }
   if (!should_intervene_download)
     UseCounter::Count(document, WebFeature::kDownloadPostPolicyCheck);
@@ -188,9 +183,10 @@
       DispatchSimulatedClick(&event);
       return;
     }
-
-    if (IsLinkClick(event) && IsLiveLink()) {
-      HandleClick(event);
+    Event* click_event = GetClickEventOrNull(event);
+    if (click_event && IsLiveLink()) {
+      HandleClick(*click_event);
+      event.SetDefaultHandled();
       return;
     }
   }
@@ -463,17 +459,24 @@
          !ToKeyboardEvent(event).repeat();
 }
 
-bool IsLinkClick(Event& event) {
-  if ((event.type() != event_type_names::kClick &&
-       event.type() != event_type_names::kAuxclick) ||
-      !event.IsMouseEvent()) {
-    return false;
+Event* GetClickEventOrNull(Event& event) {
+  // HTMLElement embedded in anchor tag dispatches a DOMActivate event when
+  // clicked on. The original click event is set as underlying event.
+  bool use_underlying_event =
+      event.type() == event_type_names::kDOMActivate && event.UnderlyingEvent();
+  Event* process_event =
+      use_underlying_event ? event.UnderlyingEvent() : &event;
+  if ((process_event->type() != event_type_names::kClick &&
+       process_event->type() != event_type_names::kAuxclick) ||
+      !process_event->IsMouseEvent()) {
+    return nullptr;
   }
-  auto& mouse_event = ToMouseEvent(event);
+  auto& mouse_event = ToMouseEvent(*process_event);
   int16_t button = mouse_event.button();
   return (button == static_cast<int16_t>(WebPointerProperties::Button::kLeft) ||
-          button ==
-              static_cast<int16_t>(WebPointerProperties::Button::kMiddle));
+          button == static_cast<int16_t>(WebPointerProperties::Button::kMiddle))
+             ? process_event
+             : nullptr;
 }
 
 bool HTMLAnchorElement::WillRespondToMouseClickEvents() {
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.h b/third_party/blink/renderer/core/html/html_anchor_element.h
index 64a4e63..6a782ba 100644
--- a/third_party/blink/renderer/core/html/html_anchor_element.h
+++ b/third_party/blink/renderer/core/html/html_anchor_element.h
@@ -132,7 +132,7 @@
 // Functions shared with the other anchor elements (i.e., SVG).
 
 bool IsEnterKeyKeydownEvent(Event&);
-bool IsLinkClick(Event&);
+Event* GetClickEventOrNull(Event&);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.h b/third_party/blink/renderer/core/html/html_frame_owner_element.h
index aed28471..2cbbb312 100644
--- a/third_party/blink/renderer/core/html/html_frame_owner_element.h
+++ b/third_party/blink/renderer/core/html/html_frame_owner_element.h
@@ -129,8 +129,8 @@
   HTMLFrameOwnerElement(const QualifiedName& tag_name, Document&);
 
   void SetSandboxFlags(WebSandboxFlags);
-  void SetAllowedToDownloadWithoutUserActivation(bool allowed) {
-    frame_policy_.allowed_to_download_without_user_activation = allowed;
+  void SetAllowedToDownload(bool allowed) {
+    frame_policy_.allowed_to_download = allowed;
   }
 
   bool LoadOrRedirectSubframe(const KURL&,
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc
index 731fcd53..2ada299 100644
--- a/third_party/blink/renderer/core/html/html_iframe_element.cc
+++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -151,9 +151,8 @@
         value.IsNull()
             ? WebSandboxFlags::kNone
             : ParseSandboxPolicy(sandbox_->TokenSet(), invalid_tokens);
-    SetAllowedToDownloadWithoutUserActivation(
-        (current_flags & WebSandboxFlags::kDownloads) ==
-        WebSandboxFlags::kNone);
+    SetAllowedToDownload((current_flags & WebSandboxFlags::kDownloads) ==
+                         WebSandboxFlags::kNone);
     // With FeaturePolicyForSandbox, sandbox flags are represented as part of
     // the container policies. However, not all sandbox flags are yet converted
     // and for now the residue will stay around in the stored flags.
diff --git a/third_party/blink/renderer/core/html/html_iframe_element_sandbox.cc b/third_party/blink/renderer/core/html/html_iframe_element_sandbox.cc
index e56d3104..c5ccb99 100644
--- a/third_party/blink/renderer/core/html/html_iframe_element_sandbox.cc
+++ b/third_party/blink/renderer/core/html/html_iframe_element_sandbox.cc
@@ -26,7 +26,7 @@
     "allow-scripts",
     "allow-top-navigation",
     "allow-top-navigation-by-user-activation",
-    "allow-downloads-without-user-activation"};
+    "allow-downloads"};
 
 // TODO (http://crbug.com/989663) move this into |kSupportedSandboxTokens| when
 // feature flag is enabled by default.
diff --git a/third_party/blink/renderer/core/layout/layout_counter.cc b/third_party/blink/renderer/core/layout/layout_counter.cc
index 3f4cd4af..ceb6d30 100644
--- a/third_party/blink/renderer/core/layout/layout_counter.cc
+++ b/third_party/blink/renderer/core/layout/layout_counter.cc
@@ -161,6 +161,7 @@
       break;
     case kPseudoIdBefore:
     case kPseudoIdAfter:
+    case kPseudoIdMarker:
       break;
     default:
       return false;  // Counters are forbidden from all other pseudo elements.
@@ -483,7 +484,8 @@
                          // pseudo elements
       PseudoId container_style = before_after_container->StyleRef().StyleType();
       if ((container_style == kPseudoIdBefore) ||
-          (container_style == kPseudoIdAfter))
+          (container_style == kPseudoIdAfter) ||
+          (container_style == kPseudoIdMarker))
         break;
       before_after_container = before_after_container->Parent();
     }
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc
index aea0e46..14e1ffe 100644
--- a/third_party/blink/renderer/core/layout/layout_inline.cc
+++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -1708,7 +1708,7 @@
     PaintInvalidationReason invalidation_reason) const {
   ObjectPaintInvalidator paint_invalidator(*this);
 
-  if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
+  if (RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled()) {
     auto fragments = NGPaintFragment::InlineFragmentsFor(this);
     if (fragments.IsInLayoutNGInlineFormattingContext()) {
       for (NGPaintFragment* fragment : fragments) {
@@ -1719,6 +1719,18 @@
     }
   }
 
+  if (IsInLayoutNGInlineFormattingContext()) {
+    if (!ShouldCreateBoxFragment())
+      return;
+    NGInlineCursor cursor;
+    for (cursor.MoveTo(*this); cursor; cursor.MoveToNextForSameLayoutObject()) {
+      DCHECK_EQ(cursor.CurrentLayoutObject(), this);
+      paint_invalidator.InvalidateDisplayItemClient(
+          *cursor.CurrentDisplayItemClient(), invalidation_reason);
+    }
+    return;
+  }
+
   paint_invalidator.InvalidateDisplayItemClient(*this, invalidation_reason);
 
   for (InlineFlowBox* box : *LineBoxes())
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index 889954a..ef2fc8c 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -223,6 +223,8 @@
     }
     image->SetStyleInternal(nullptr);
     return image;
+  } else if (element->GetPseudoId() == kPseudoIdMarker) {
+    return LayoutObjectFactory::CreateListMarker(*element, style, legacy);
   }
 
   switch (style.Display()) {
diff --git a/third_party/blink/renderer/core/layout/layout_object_factory.cc b/third_party/blink/renderer/core/layout/layout_object_factory.cc
index c23306d..00524e1 100644
--- a/third_party/blink/renderer/core/layout/layout_object_factory.cc
+++ b/third_party/blink/renderer/core/layout/layout_object_factory.cc
@@ -22,7 +22,9 @@
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_progress.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_table_caption.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.h"
+#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h"
 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
+#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
@@ -90,6 +92,23 @@
       node, style, legacy);
 }
 
+LayoutObject* LayoutObjectFactory::CreateListMarker(Node& node,
+                                                    const ComputedStyle& style,
+                                                    LegacyLayout legacy) {
+  // TODO(obrufau): allow ::marker pseudo-elements to generate legacy layout.
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled() ||
+      legacy == LegacyLayout::kForce)
+    return nullptr;
+  // TODO(obrufau): markers may be forced to be inside despite having
+  // `list-style-position: outside`.
+  if (style.ListStylePosition() == EListStylePosition::kInside) {
+    return CreateObject<LayoutObject, LayoutNGInsideListMarker,
+                        LayoutNGInsideListMarker>(node, style, legacy);
+  }
+  return CreateObject<LayoutObject, LayoutNGListMarker, LayoutNGListMarker>(
+      node, style, legacy);
+}
+
 LayoutTableCaption* LayoutObjectFactory::CreateTableCaption(
     Node& node,
     const ComputedStyle& style,
diff --git a/third_party/blink/renderer/core/layout/layout_object_factory.h b/third_party/blink/renderer/core/layout/layout_object_factory.h
index 3fbd47b..4fc7ac0f 100644
--- a/third_party/blink/renderer/core/layout/layout_object_factory.h
+++ b/third_party/blink/renderer/core/layout/layout_object_factory.h
@@ -14,6 +14,7 @@
 class ComputedStyle;
 class LayoutBlock;
 class LayoutBlockFlow;
+class LayoutObject;
 enum class LegacyLayout;
 class LayoutProgress;
 class LayoutTableCaption;
@@ -43,6 +44,9 @@
   static LayoutBlockFlow* CreateListItem(Node&,
                                          const ComputedStyle&,
                                          LegacyLayout);
+  static LayoutObject* CreateListMarker(Node&,
+                                        const ComputedStyle&,
+                                        LegacyLayout);
   static LayoutTableCaption* CreateTableCaption(Node&,
                                                 const ComputedStyle&,
                                                 LegacyLayout);
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h b/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h
index ec19ee3..0ce5f75 100644
--- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h
+++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h
@@ -22,8 +22,8 @@
 
 #if DCHECK_IS_ON()
   void AddChild(LayoutObject* new_child, LayoutObject* before_child) override {
-    // List marker should have at most one child.
-    DCHECK(!FirstChild());
+    // Anonymous list marker should have at most one child.
+    DCHECK(GetNode() || !FirstChild());
     LayoutInline::AddChild(new_child, before_child);
   }
 #endif
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
index f3107a3..a5c7387b 100644
--- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
+++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
@@ -159,6 +159,14 @@
     marker_style = ComputedStyle::Create();
     marker_style->InheritFrom(style);
   }
+  if (marker_style->GetContentData()) {
+    // Don't create an anonymous layout for the marker, it will be generated
+    // by the ::marker pseudo-element.
+    DestroyMarker();
+    marker_type_ = kStatic;
+    is_marker_text_updated_ = true;
+    return;
+  }
   if (IsInside()) {
     if (marker_ && !marker_->IsLayoutInline())
       DestroyMarker();
@@ -205,7 +213,16 @@
   for (LayoutObject* parent = marker.Parent(); parent;
        parent = parent->Parent()) {
     if (parent->IsLayoutNGListItem()) {
-      DCHECK(ToLayoutNGListItem(parent)->Marker() == &marker);
+#if DCHECK_IS_ON()
+      LayoutObject* parent_marker = ToLayoutNGListItem(parent)->Marker();
+      if (parent_marker) {
+        DCHECK(!marker.GetNode());
+        DCHECK_EQ(ToLayoutNGListItem(parent)->Marker(), &marker);
+      } else {
+        DCHECK(marker.GetNode()->IsMarkerPseudoElement());
+        DCHECK_EQ(marker.GetNode()->parentElement()->GetLayoutBox(), parent);
+      }
+#endif
       return ToLayoutNGListItem(parent);
     }
     // These DCHECKs are not critical but to ensure we cover all cases we know.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
index 083c0dd..f0b180a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -976,6 +976,16 @@
   DCHECK(!IsResumingLayout(child_break_token) ||
          container_builder_.BfcBlockOffset());
 
+  if (broke_before_float_) {
+    // We have already broken before a float. This means that we cannot place
+    // any more floats now, as a float isn't allowed to start before any
+    // preceding float.
+    DCHECK(!child_break_token);
+    container_builder_.AddBreakBeforeChild(child, base::nullopt,
+                                           /* is_forced_break */ false);
+    return;
+  }
+
   // If we don't have a BFC block-offset yet, the "expected" BFC block-offset
   // is used to optimistically place floats.
   NGBfcOffset origin_bfc_offset = {
@@ -1005,8 +1015,40 @@
   NGPositionedFloat positioned_float =
       PositionFloat(&unpositioned_float, &exclusion_space_);
 
-  const auto& physical_fragment =
-      positioned_float.layout_result->PhysicalFragment();
+  const NGLayoutResult& layout_result = *positioned_float.layout_result;
+  const auto& physical_fragment = layout_result.PhysicalFragment();
+  if (const NGBreakToken* token = physical_fragment.BreakToken()) {
+    DCHECK(ConstraintSpace().HasBlockFragmentation());
+    if (!child_break_token && token->BreakAppeal() != kBreakAppealPerfect) {
+      LayoutUnit fragmentainer_block_offset =
+          ConstraintSpace().FragmentainerOffsetAtBfc() +
+          positioned_float.bfc_offset.block_offset;
+      if (fragmentainer_block_offset > LayoutUnit()) {
+        // The float broke inside, and not at an ideal breakpoint. Break before
+        // the float instead. Note that we don't check if we're at a valid class
+        // A or C breakpoint (we only check that we're not at the start of the
+        // fragmentainer (in which case breaking typically wouldn't eliminate
+        // the unappealing break inside the float)). While no other browsers do
+        // this either, we should consider doing this in the future. For now,
+        // don't let the float affect the appeal of breaking inside this
+        // container.
+        BreakBeforeChild(ConstraintSpace(), child, layout_result,
+                         fragmentainer_block_offset,
+                         /* appeal */ base::nullopt,
+                         /* is_forced_break */ false, &container_builder_);
+
+        // Then carry on with layout of this container. The float constitutes a
+        // parallel flow, and there may be siblings that could still fit in the
+        // current fragmentainer.
+        broke_before_float_ = true;
+        return;
+      }
+    }
+  }
+
+  // TODO(mstensho): There should be a class A breakpoint between a float and
+  // another float, and also between a float and an in-flow block.
+
   LayoutUnit float_inline_size =
       NGFragment(ConstraintSpace().GetWritingMode(), physical_fragment)
           .InlineSize();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
index 131df36..8274b1d 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
@@ -386,6 +386,12 @@
   // A or B breakpoint (between block-level siblings or line box siblings).
   bool has_processed_first_child_ = false;
 
+  // Set once we've inserted a break before a float. We need to know this, so
+  // that we don't attempt to lay out any more floats in the current
+  // fragmentainer. Floats aren't allowed have an earlier block-start offset
+  // than earlier floats.
+  bool broke_before_float_ = false;
+
   bool did_break_before_child_ = false;
 
   NGExclusionSpace exclusion_space_;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
index 5e52494..990d5a5 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
@@ -79,15 +79,17 @@
 
 }  // namespace
 
-void NGBoxFragmentBuilder::AddBreakBeforeChild(NGLayoutInputNode child,
-                                               NGBreakAppeal appeal,
-                                               bool is_forced_break) {
-  break_appeal_ = appeal;
+void NGBoxFragmentBuilder::AddBreakBeforeChild(
+    NGLayoutInputNode child,
+    base::Optional<NGBreakAppeal> appeal,
+    bool is_forced_break) {
+  if (appeal)
+    break_appeal_ = *appeal;
   if (is_forced_break) {
     SetHasForcedBreak();
     // A forced break is considered to always have perfect appeal; they should
     // never be weighed against other potential breakpoints.
-    DCHECK_EQ(appeal, kBreakAppealPerfect);
+    DCHECK(!appeal || *appeal == kBreakAppealPerfect);
   }
 
   DCHECK(has_block_fragmentation_);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
index d0dd84a..0544b7aa 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
@@ -95,9 +95,12 @@
 
   // Add a break token for a child that doesn't yet have any fragments, because
   // its first fragment is to be produced in the next fragmentainer. This will
-  // add a break token for the child, but no fragment.
+  // add a break token for the child, but no fragment. Break appeal should
+  // always be provided for regular in-flow children. For other types of
+  // children it may be omitted, if the break shouldn't affect the appeal of
+  // breaking inside this container.
   void AddBreakBeforeChild(NGLayoutInputNode child,
-                           NGBreakAppeal,
+                           base::Optional<NGBreakAppeal> appeal,
                            bool is_forced_break);
 
   // Add a layout result. This involves appending the fragment and its relative
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
index 9decf5d8..85c973e 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
@@ -752,6 +752,167 @@
   EXPECT_EQ(expectation, dump);
 }
 
+TEST_F(NGColumnLayoutAlgorithmTest, FloatWithLastResortBreak) {
+  // Breaking inside the line is not possible, and breaking between the
+  // block-start content edge and the first child should be avoided.
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      #parent {
+        columns: 3;
+        column-fill: auto;
+        column-gap: 10px;
+        width: 320px;
+        height: 100px;
+        line-height: 20px;
+        orphans: 1;
+        widows: 1;
+      }
+    </style>
+    <div id="container">
+      <div id="parent">
+        <div style="width:99px; height:90px;"></div>
+        <div style="float:left; width:88px;">
+          <br>
+        </div>
+      </div>
+    </div>
+  )HTML");
+
+  String dump = DumpFragmentTree(GetElementById("container"));
+  String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+  offset:unplaced size:1000x100
+    offset:0,0 size:320x100
+      offset:0,0 size:100x100
+        offset:0,0 size:99x90
+      offset:110,0 size:100x20
+        offset:0,0 size:88x20
+          offset:0,0 size:0x20
+            offset:0,9 size:0x1
+)DUMP";
+  EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, FloatWithAvoidBreak) {
+  // We want to avoid breaking inside the float child, and breaking before it
+  // should be avoided (not a valid breakpoint).
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      #parent {
+        columns: 3;
+        column-fill: auto;
+        column-gap: 10px;
+        width: 320px;
+        height: 100px;
+      }
+      .content { break-inside:avoid; height:20px; }
+    </style>
+    <div id="container">
+      <div id="parent">
+        <div style="width:99px; height:90px;"></div>
+        <div style="float:left; width:88px;">
+          <div class="content" style="width:77px;"></div>
+        </div>
+      </div>
+    </div>
+  )HTML");
+
+  String dump = DumpFragmentTree(GetElementById("container"));
+  String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+  offset:unplaced size:1000x100
+    offset:0,0 size:320x100
+      offset:0,0 size:100x100
+        offset:0,0 size:99x90
+      offset:110,0 size:100x20
+        offset:0,0 size:88x20
+          offset:0,0 size:77x20
+)DUMP";
+  EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, FloatWithMarginAndAvoidBreak) {
+  // We want to avoid breaking inside the float child, and breaking before it
+  // should be avoided (not a valid breakpoint). The top margin should be kept
+  // in the next column.
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      #parent {
+        columns: 3;
+        column-fill: auto;
+        column-gap: 10px;
+        width: 320px;
+        height: 100px;
+      }
+      .content { break-inside:avoid; height:20px; }
+    </style>
+    <div id="container">
+      <div id="parent">
+        <div style="width:99px; height:90px;"></div>
+        <div style="float:left; width:88px; margin-top:5px;">
+          <div class="content" style="width:77px;"></div>
+        </div>
+      </div>
+    </div>
+  )HTML");
+
+  String dump = DumpFragmentTree(GetElementById("container"));
+  String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+  offset:unplaced size:1000x100
+    offset:0,0 size:320x100
+      offset:0,0 size:100x100
+        offset:0,0 size:99x90
+      offset:110,0 size:100x25
+        offset:0,5 size:88x20
+          offset:0,0 size:77x20
+)DUMP";
+  EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, UnbreakableFloatBeforeBreakable) {
+  // https://www.w3.org/TR/CSS22/visuren.html#float-position
+  //
+  // "The outer top of a floating box may not be higher than the outer top of
+  // any block or floated box generated by an element earlier in the source
+  // document."
+  //
+  // This means that if we decide to break before one float, we also need to
+  // break before all subsequent floats, even if such floats don't require that
+  // on their own.
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      #parent {
+        columns: 3;
+        column-fill: auto;
+        column-gap: 10px;
+        width: 320px;
+        height: 100px;
+      }
+      .content { break-inside:avoid; height:20px; }
+    </style>
+    <div id="container">
+      <div id="parent">
+        <div style="width:99px; height:90px;"></div>
+        <div style="float:left; width:22px; height:50px;">
+          <div class="content" style="width:11px;"></div>
+        </div>
+        <div style="float:left; width:33px; height:50px;"></div>
+      </div>
+    </div>
+  )HTML");
+
+  String dump = DumpFragmentTree(GetElementById("container"));
+  String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+  offset:unplaced size:1000x100
+    offset:0,0 size:320x100
+      offset:0,0 size:100x100
+        offset:0,0 size:99x90
+      offset:110,0 size:100x50
+        offset:0,0 size:22x50
+          offset:0,0 size:11x20
+        offset:22,0 size:33x50
+)DUMP";
+  EXPECT_EQ(expectation, dump);
+}
+
 TEST_F(NGColumnLayoutAlgorithmTest, BlockWithTopMarginInThreeColumns) {
   SetBodyInnerHTML(R"HTML(
     <style>
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
index 376fa64..6ce523d 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
@@ -267,7 +267,7 @@
                       NGLayoutInputNode child,
                       const NGLayoutResult& layout_result,
                       LayoutUnit fragmentainer_block_offset,
-                      NGBreakAppeal appeal,
+                      base::Optional<NGBreakAppeal> appeal,
                       bool is_forced_break,
                       NGBoxFragmentBuilder* builder) {
 #if DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
index c75aae90..3f0f844 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
@@ -152,7 +152,7 @@
                       NGLayoutInputNode child,
                       const NGLayoutResult&,
                       LayoutUnit fragmentainer_block_offset,
-                      NGBreakAppeal,
+                      base::Optional<NGBreakAppeal> appeal,
                       bool is_forced_break,
                       NGBoxFragmentBuilder*);
 
diff --git a/third_party/blink/renderer/core/layout/scroll_anchor.cc b/third_party/blink/renderer/core/layout/scroll_anchor.cc
index b1a6b09..0d86a6fc 100644
--- a/third_party/blink/renderer/core/layout/scroll_anchor.cc
+++ b/third_party/blink/renderer/core/layout/scroll_anchor.cc
@@ -156,7 +156,7 @@
     if (sibling_element->HasClass() && sibling_element != element) {
       const SpaceSplitString& class_names = sibling_element->ClassNames();
       for (wtf_size_t i = 0; i < class_names.size(); ++i) {
-        classname_filter->Add(class_names[i]);
+        classname_filter->Add(class_names[i].Impl()->ExistingHash());
       }
     }
   }
@@ -166,7 +166,7 @@
     // MayContain allows for false positives, but a false positive is relatively
     // harmless; it just means we have to choose a different classname, or in
     // the worst case a different selector.
-    if (!classname_filter->MayContain(class_names[i])) {
+    if (!classname_filter->MayContain(class_names[i].Impl()->ExistingHash())) {
       return class_names[i];
     }
   }
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index f616d43..e84d5e4 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2511,6 +2511,8 @@
       return false;
     if (IsEnsuredInDisplayNone())
       return false;
+    if (pseudo == kPseudoIdMarker)
+      return Display() == EDisplay::kListItem;
     if (Display() != EDisplay::kContents)
       return true;
     // For display: contents elements, we still need to generate ::before and
diff --git a/third_party/blink/renderer/core/svg/svg_a_element.cc b/third_party/blink/renderer/core/svg/svg_a_element.cc
index 0626fca..2b8e565 100644
--- a/third_party/blink/renderer/core/svg/svg_a_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_a_element.cc
@@ -112,7 +112,9 @@
       return;
     }
 
-    if (IsLinkClick(event)) {
+    if (Event* click_event = GetClickEventOrNull(event)) {
+      click_event->SetDefaultHandled();
+      event.SetDefaultHandled();
       String url = StripLeadingAndTrailingHTMLSpaces(HrefString());
 
       if (url[0] == '#') {
@@ -121,7 +123,6 @@
         if (auto* svg_smil_element =
                 DynamicTo<SVGSMILElement>(target_element)) {
           svg_smil_element->BeginByLinkActivation();
-          event.SetDefaultHandled();
           return;
         }
       }
@@ -129,17 +130,15 @@
       AtomicString target(svg_target_->CurrentValue()->Value());
       if (target.IsEmpty() && FastGetAttribute(xlink_names::kShowAttr) == "new")
         target = AtomicString("_blank");
-      event.SetDefaultHandled();
-
       if (!GetDocument().GetFrame())
         return;
 
       FrameLoadRequest frame_request(
           &GetDocument(), ResourceRequest(GetDocument().CompleteURL(url)));
-      frame_request.SetNavigationPolicy(NavigationPolicyFromEvent(&event));
+      frame_request.SetNavigationPolicy(NavigationPolicyFromEvent(click_event));
       frame_request.SetTriggeringEventInfo(
-          event.isTrusted() ? TriggeringEventInfo::kFromTrustedEvent
-                            : TriggeringEventInfo::kFromUntrustedEvent);
+          click_event->isTrusted() ? TriggeringEventInfo::kFromTrustedEvent
+                                   : TriggeringEventInfo::kFromUntrustedEvent);
       frame_request.GetResourceRequest().SetHasUserGesture(
           LocalFrame::HasTransientUserActivation(GetDocument().GetFrame()));
 
diff --git a/third_party/blink/renderer/modules/compression/inflate_transformer.cc b/third_party/blink/renderer/modules/compression/inflate_transformer.cc
index fa873be..4c9536ef 100644
--- a/third_party/blink/renderer/modules/compression/inflate_transformer.cc
+++ b/third_party/blink/renderer/modules/compression/inflate_transformer.cc
@@ -19,6 +19,7 @@
 #include "third_party/blink/renderer/modules/compression/zlib_partition_alloc.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/to_v8.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "v8/include/v8.h"
 
 namespace blink {
@@ -85,6 +86,10 @@
   was_flush_called_ = true;
   out_buffer_.clear();
 
+  if (!reached_end_) {
+    exception_state.ThrowTypeError("Compressed input was truncated.");
+  }
+
   return ScriptPromise::CastUndefined(script_state_);
 }
 
@@ -94,6 +99,13 @@
     IsFinished finished,
     TransformStreamDefaultControllerInterface* controller,
     ExceptionState& exception_state) {
+  if (reached_end_ && length != 0) {
+    // zlib will ignore data after the end of the stream, so we have to
+    // explicitly throw an error.
+    exception_state.ThrowTypeError("Junk found after end of compressed data.");
+    return;
+  }
+
   stream_.avail_in = length;
   // Zlib treats this pointer as const, so this cast is safe.
   stream_.next_in = const_cast<uint8_t*>(start);
@@ -101,9 +113,15 @@
   do {
     stream_.avail_out = out_buffer_.size();
     stream_.next_out = out_buffer_.data();
-    int err = inflate(&stream_, finished ? Z_FINISH : Z_NO_FLUSH);
+    const int err = inflate(&stream_, finished ? Z_FINISH : Z_NO_FLUSH);
     if (err != Z_OK && err != Z_STREAM_END && err != Z_BUF_ERROR) {
-      exception_state.ThrowTypeError("The compressed data was not valid.");
+      DCHECK_NE(err, Z_STREAM_ERROR);
+      if (err == Z_DATA_ERROR) {
+        exception_state.ThrowTypeError(
+            String("The compressed data was not valid: ") + stream_.msg + ".");
+      } else {
+        exception_state.ThrowTypeError("The compressed data was not valid.");
+      }
       return;
     }
 
@@ -116,6 +134,15 @@
         return;
       }
     }
+
+    if (err == Z_STREAM_END) {
+      reached_end_ = true;
+      if (stream_.next_in < start + length) {
+        exception_state.ThrowTypeError(
+            "Junk found after end of compressed data.");
+      }
+      return;
+    }
   } while (stream_.avail_out == 0);
 }
 
diff --git a/third_party/blink/renderer/modules/compression/inflate_transformer.h b/third_party/blink/renderer/modules/compression/inflate_transformer.h
index 2aca1c6..9ced4373 100644
--- a/third_party/blink/renderer/modules/compression/inflate_transformer.h
+++ b/third_party/blink/renderer/modules/compression/inflate_transformer.h
@@ -48,6 +48,7 @@
   Vector<uint8_t> out_buffer_;
 
   bool was_flush_called_ = false;
+  bool reached_end_ = false;
 
   // This buffer size has been experimentally verified to be optimal.
   static constexpr wtf_size_t kBufferSize = 65536;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
index 88d2681..5943137 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
@@ -647,12 +647,12 @@
 }
 
 // Implementation of LocalRTCStatsResponse.
-blink::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const {
+RTCStatsResponseBase* LocalRTCStatsResponse::webKitStatsResponse() const {
   return impl_;
 }
 
 void LocalRTCStatsResponse::addStats(const blink::WebRTCLegacyStats& stats) {
-  impl_.AddStats(stats);
+  impl_->AddStats(stats);
 }
 
 // Processes the resulting state changes of a SetLocalDescription() or
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
index a31a33f..29850d74 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
@@ -21,13 +21,13 @@
 #include "third_party/blink/public/platform/web_rtc_peer_connection_handler_client.h"
 #include "third_party/blink/public/platform/web_rtc_stats.h"
 #include "third_party/blink/public/platform/web_rtc_stats_request.h"
-#include "third_party/blink/public/platform/web_rtc_stats_response.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/modules/peerconnection/media_stream_track_metrics.h"
 #include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl.h"
 #include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.h"
 #include "third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer.h"
 #include "third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_stats_response_base.h"
 #include "third_party/webrtc/api/stats/rtc_stats.h"
 #include "third_party/webrtc/api/stats/rtc_stats_collector_callback.h"
 
@@ -42,13 +42,12 @@
 class WebRTCLegacyStats;
 class WebRTCPeerConnectionHandlerClient;
 
-// Mockable wrapper for blink::WebRTCStatsResponse
+// Mockable wrapper for blink::RTCStatsResponseBase
 class MODULES_EXPORT LocalRTCStatsResponse : public rtc::RefCountInterface {
  public:
-  explicit LocalRTCStatsResponse(const blink::WebRTCStatsResponse& impl)
-      : impl_(impl) {}
+  explicit LocalRTCStatsResponse(RTCStatsResponseBase* impl) : impl_(impl) {}
 
-  virtual blink::WebRTCStatsResponse webKitStatsResponse() const;
+  virtual RTCStatsResponseBase* webKitStatsResponse() const;
   virtual void addStats(const blink::WebRTCLegacyStats& stats);
 
  protected:
@@ -57,7 +56,7 @@
   LocalRTCStatsResponse() {}
 
  private:
-  blink::WebRTCStatsResponse impl_;
+  Persistent<RTCStatsResponseBase> impl_;
 };
 
 // Mockable wrapper for blink::WebRTCStatsRequest
diff --git a/third_party/blink/renderer/modules/webtransport/quic_transport.cc b/third_party/blink/renderer/modules/webtransport/quic_transport.cc
index 829cb6e..6829c59 100644
--- a/third_party/blink/renderer/modules/webtransport/quic_transport.cc
+++ b/third_party/blink/renderer/modules/webtransport/quic_transport.cc
@@ -34,7 +34,7 @@
   DVLOG(1) << "QuicTransport::Create() url=" << url;
   auto* transport =
       MakeGarbageCollected<QuicTransport>(PassKey(), script_state, url);
-  transport->Init(exception_state);
+  transport->Init(url, exception_state);
   return transport;
 }
 
@@ -92,12 +92,11 @@
   ScriptWrappable::Trace(visitor);
 }
 
-void QuicTransport::Init(ExceptionState& exception_state) {
-  DVLOG(1) << "QuicTransport::Init() url=" << url_ << " this=" << this;
+void QuicTransport::Init(const String& url, ExceptionState& exception_state) {
+  DVLOG(1) << "QuicTransport::Init() url=" << url << " this=" << this;
   if (!url_.IsValid()) {
-    exception_state.ThrowDOMException(
-        DOMExceptionCode::kSyntaxError,
-        "The URL '" + url_.ElidedString() + "' is invalid.");
+    exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+                                      "The URL '" + url + "' is invalid.");
     return;
   }
 
diff --git a/third_party/blink/renderer/modules/webtransport/quic_transport.h b/third_party/blink/renderer/modules/webtransport/quic_transport.h
index 690e2d50..39a3554 100644
--- a/third_party/blink/renderer/modules/webtransport/quic_transport.h
+++ b/third_party/blink/renderer/modules/webtransport/quic_transport.h
@@ -64,7 +64,7 @@
   void Trace(Visitor* visitor) override;
 
  private:
-  void Init(ExceptionState&);
+  void Init(const String& url, ExceptionState&);
   void Dispose();
   void OnConnectionError();
 
diff --git a/third_party/blink/renderer/modules/webtransport/quic_transport_test.cc b/third_party/blink/renderer/modules/webtransport/quic_transport_test.cc
index 8baa7e7..8788e37f 100644
--- a/third_party/blink/renderer/modules/webtransport/quic_transport_test.cc
+++ b/third_party/blink/renderer/modules/webtransport/quic_transport_test.cc
@@ -159,6 +159,17 @@
   EXPECT_EQ("The URL '' is invalid.", exception_state.Message());
 }
 
+TEST_F(QuicTransportTest, FailWithNoScheme) {
+  V8TestingScope scope;
+  auto& exception_state = scope.GetExceptionState();
+  QuicTransport::Create(scope.GetScriptState(), String("no-scheme"),
+                        exception_state);
+  EXPECT_TRUE(exception_state.HadException());
+  EXPECT_EQ(static_cast<int>(DOMExceptionCode::kSyntaxError),
+            exception_state.Code());
+  EXPECT_EQ("The URL 'no-scheme' is invalid.", exception_state.Message());
+}
+
 TEST_F(QuicTransportTest, FailWithHttpsURL) {
   V8TestingScope scope;
   auto& exception_state = scope.GetExceptionState();
@@ -180,7 +191,8 @@
   EXPECT_TRUE(exception_state.HadException());
   EXPECT_EQ(static_cast<int>(DOMExceptionCode::kSyntaxError),
             exception_state.Code());
-  EXPECT_EQ("The URL 'quic-transport:' is invalid.", exception_state.Message());
+  EXPECT_EQ("The URL 'quic-transport:///' is invalid.",
+            exception_state.Message());
 }
 
 TEST_F(QuicTransportTest, FailWithURLFragment) {
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 0a93bb52..3df9675 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -535,7 +535,6 @@
     "exported/web_rtc_rtp_transceiver.cc",
     "exported/web_rtc_stats.cc",
     "exported/web_rtc_stats_request.cc",
-    "exported/web_rtc_stats_response.cc",
     "exported/web_runtime_features.cc",
     "exported/web_security_origin.cc",
     "exported/web_string.cc",
diff --git a/third_party/blink/renderer/platform/exported/web_rtc_stats_request.cc b/third_party/blink/renderer/platform/exported/web_rtc_stats_request.cc
index 809050f..036af1b 100644
--- a/third_party/blink/renderer/platform/exported/web_rtc_stats_request.cc
+++ b/third_party/blink/renderer/platform/exported/web_rtc_stats_request.cc
@@ -32,7 +32,6 @@
 
 #include "third_party/blink/public/platform/web_media_stream.h"
 #include "third_party/blink/public/platform/web_media_stream_track.h"
-#include "third_party/blink/public/platform/web_rtc_stats_response.h"
 #include "third_party/blink/renderer/platform/peerconnection/rtc_stats_request.h"
 #include "third_party/blink/renderer/platform/peerconnection/rtc_stats_response_base.h"
 
@@ -49,8 +48,8 @@
   private_.Reset();
 }
 
-WebRTCStatsResponse WebRTCStatsRequest::CreateResponse() const {
-  return WebRTCStatsResponse(private_->CreateResponse());
+RTCStatsResponseBase* WebRTCStatsRequest::CreateResponse() const {
+  return private_->CreateResponse();
 }
 
 bool WebRTCStatsRequest::HasSelector() const {
@@ -62,7 +61,7 @@
 }
 
 void WebRTCStatsRequest::RequestSucceeded(
-    const WebRTCStatsResponse& response) const {
+    RTCStatsResponseBase* response) const {
   private_->RequestSucceeded(response);
 }
 
diff --git a/third_party/blink/renderer/platform/exported/web_rtc_stats_response.cc b/third_party/blink/renderer/platform/exported/web_rtc_stats_response.cc
deleted file mode 100644
index 2c7d842b..0000000
--- a/third_party/blink/renderer/platform/exported/web_rtc_stats_response.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/public/platform/web_rtc_stats_response.h"
-
-#include "third_party/blink/renderer/platform/peerconnection/rtc_stats_response_base.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-WebRTCStatsResponse::WebRTCStatsResponse(RTCStatsResponseBase* request)
-    : private_(request) {}
-
-void WebRTCStatsResponse::Assign(const WebRTCStatsResponse& other) {
-  private_ = other.private_;
-}
-
-void WebRTCStatsResponse::Reset() {
-  private_.Reset();
-}
-
-WebRTCStatsResponse::operator RTCStatsResponseBase*() const {
-  return private_.Get();
-}
-
-void WebRTCStatsResponse::AddStats(const WebRTCLegacyStats& stats) {
-  DCHECK(!private_.IsNull());
-  private_->AddStats(stats);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/font_cache.h b/third_party/blink/renderer/platform/fonts/font_cache.h
index 2615b2e2..08c723b 100644
--- a/third_party/blink/renderer/platform/fonts/font_cache.h
+++ b/third_party/blink/renderer/platform/fonts/font_cache.h
@@ -242,7 +242,7 @@
 #endif  // defined(OS_ANDROID)
 
 #if defined(OS_LINUX)
-  static void GetFontForCharacter(UChar32,
+  static bool GetFontForCharacter(UChar32,
                                   const char* preferred_locale,
                                   gfx::FallbackFontData*);
 #endif  // defined(OS_LINUX)
diff --git a/third_party/blink/renderer/platform/fonts/linux/font_cache_linux.cc b/third_party/blink/renderer/platform/fonts/linux/font_cache_linux.cc
index 88bf948..39edc68 100644
--- a/third_party/blink/renderer/platform/fonts/linux/font_cache_linux.cc
+++ b/third_party/blink/renderer/platform/fonts/linux/font_cache_linux.cc
@@ -49,15 +49,16 @@
   MutableSystemFontFamily() = family_name;
 }
 
-void FontCache::GetFontForCharacter(UChar32 c,
+bool FontCache::GetFontForCharacter(UChar32 c,
                                     const char* preferred_locale,
                                     gfx::FallbackFontData* fallback_font) {
   if (Platform::Current()->GetSandboxSupport()) {
-    Platform::Current()->GetSandboxSupport()->GetFallbackFontForCharacter(
-        c, preferred_locale, fallback_font);
+    return Platform::Current()
+        ->GetSandboxSupport()
+        ->GetFallbackFontForCharacter(c, preferred_locale, fallback_font);
   } else {
     std::string locale = preferred_locale ? preferred_locale : std::string();
-    *fallback_font = gfx::GetFallbackFontForChar(c, locale);
+    return gfx::GetFallbackFontForChar(c, locale, fallback_font);
   }
 }
 
@@ -102,9 +103,9 @@
   }
 
   gfx::FallbackFontData fallback_font;
-  FontCache::GetFontForCharacter(
-      c, font_description.LocaleOrDefault().Ascii().c_str(), &fallback_font);
-  if (fallback_font.name.empty())
+  if (!FontCache::GetFontForCharacter(
+          c, font_description.LocaleOrDefault().Ascii().c_str(),
+          &fallback_font))
     return nullptr;
 
   FontFaceCreationParams creation_params;
diff --git a/third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.cc b/third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.cc
index e94864e..62d92b7 100644
--- a/third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.cc
+++ b/third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.cc
@@ -23,12 +23,11 @@
     return nullptr;
   }
 
-  Platform::Current()
-      ->GetSandboxSupport()
-      ->MatchFontByPostscriptNameOrFullFontName(
-          font_unique_name.Utf8(WTF::kStrictUTF8Conversion).c_str(),
-          &uniquely_matched_font);
-  if (uniquely_matched_font.filepath.empty())
+  if (!Platform::Current()
+           ->GetSandboxSupport()
+           ->MatchFontByPostscriptNameOrFullFontName(
+               font_unique_name.Utf8(WTF::kStrictUTF8Conversion).c_str(),
+               &uniquely_matched_font))
     return nullptr;
 
   return SkTypeface_Factory::FromFontConfigInterfaceIdAndTtcIndex(
diff --git a/third_party/blink/renderer/platform/heap/BUILD.gn b/third_party/blink/renderer/platform/heap/BUILD.gn
index 66438e05..cce51f6 100644
--- a/third_party/blink/renderer/platform/heap/BUILD.gn
+++ b/third_party/blink/renderer/platform/heap/BUILD.gn
@@ -21,8 +21,6 @@
 
 blink_platform_sources("heap") {
   sources = [
-    "address_cache.cc",
-    "address_cache.h",
     "atomic_entry_flag.h",
     "blink_gc.cc",
     "blink_gc.h",
@@ -55,6 +53,7 @@
     "marking_visitor.h",
     "member.h",
     "name_traits.h",
+    "page_bloom_filter.h",
     "page_memory.cc",
     "page_memory.h",
     "page_pool.cc",
@@ -123,7 +122,6 @@
   testonly = true
   sources = [
     "../testing/run_all_tests.cc",
-    "address_cache_test.cc",
     "blink_gc_memory_dump_provider_test.cc",
     "cancelable_task_scheduler_test.cc",
     "gc_info_test.cc",
diff --git a/third_party/blink/renderer/platform/heap/address_cache.cc b/third_party/blink/renderer/platform/heap/address_cache.cc
deleted file mode 100644
index fb93fbc..0000000
--- a/third_party/blink/renderer/platform/heap/address_cache.cc
+++ /dev/null
@@ -1,68 +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 "third_party/blink/renderer/platform/heap/address_cache.h"
-
-#include "third_party/blink/renderer/platform/heap/heap_page.h"
-
-namespace blink {
-
-AddressCache::EnabledScope::EnabledScope(AddressCache* address_cache)
-    : address_cache_(address_cache) {
-  address_cache_->FlushIfDirty();
-  address_cache_->EnableLookup();
-}
-
-AddressCache::EnabledScope::~EnabledScope() {
-  address_cache_->DisableLookup();
-}
-
-void AddressCache::Flush() {
-  if (has_entries_) {
-    for (size_t i = 0; i < kNumberOfEntries; ++i)
-      entries_[i] = nullptr;
-    has_entries_ = false;
-  }
-  dirty_ = false;
-}
-
-void AddressCache::FlushIfDirty() {
-  if (dirty_) {
-    Flush();
-    dirty_ = false;
-  }
-}
-
-size_t AddressCache::GetHash(Address address) {
-  size_t value = (reinterpret_cast<size_t>(address) >> kBlinkPageSizeLog2);
-  value ^= value >> kNumberOfEntriesLog2;
-  value ^= value >> (kNumberOfEntriesLog2 * 2);
-  value &= kNumberOfEntries - 1;
-  return value & ~1;  // Returns only even number.
-}
-
-bool AddressCache::Lookup(Address address) {
-  DCHECK(enabled_);
-  DCHECK(!dirty_);
-
-  size_t index = GetHash(address);
-  DCHECK(!(index & 1));
-  Address cache_page = RoundToBlinkPageStart(address);
-  if (entries_[index] == cache_page)
-    return entries_[index];
-  if (entries_[index + 1] == cache_page)
-    return entries_[index + 1];
-  return false;
-}
-
-void AddressCache::AddEntry(Address address) {
-  has_entries_ = true;
-  size_t index = GetHash(address);
-  DCHECK(!(index & 1));
-  Address cache_page = RoundToBlinkPageStart(address);
-  entries_[index + 1] = entries_[index];
-  entries_[index] = cache_page;
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/address_cache.h b/third_party/blink/renderer/platform/heap/address_cache.h
deleted file mode 100644
index 5ccea41..0000000
--- a/third_party/blink/renderer/platform/heap/address_cache.h
+++ /dev/null
@@ -1,63 +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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_ADDRESS_CACHE_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_ADDRESS_CACHE_H_
-
-#include "third_party/blink/renderer/platform/heap/blink_gc.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-// Negative cache for addresses outside of Blink's garbage collected heap.
-// - Internally maps to pages (NormalPage) to cover a larger range of addresses.
-// - Requires flushing when adding new addresses.
-class PLATFORM_EXPORT AddressCache {
-  USING_FAST_MALLOC(AddressCache);
-
- public:
-  class PLATFORM_EXPORT EnabledScope {
-    STACK_ALLOCATED();
-
-   public:
-    explicit EnabledScope(AddressCache*);
-    ~EnabledScope();
-
-   private:
-    AddressCache* const address_cache_;
-  };
-
-  AddressCache()
-      : entries_{}, enabled_(false), has_entries_(false), dirty_(false) {}
-
-  void EnableLookup() { enabled_ = true; }
-  void DisableLookup() { enabled_ = false; }
-
-  void MarkDirty() { dirty_ = true; }
-  void Flush();
-  void FlushIfDirty();
-  bool IsEmpty() const { return !has_entries_; }
-
-  // Perform a lookup in the cache. Returns true if the address is guaranteed
-  // to not in Blink's heap and false otherwise.
-  bool Lookup(Address);
-
-  // Add an entry to the cache.
-  void AddEntry(Address);
-
- private:
-  static constexpr size_t kNumberOfEntriesLog2 = 12;
-  static constexpr size_t kNumberOfEntries = 1 << kNumberOfEntriesLog2;
-
-  static size_t GetHash(Address);
-
-  Address entries_[kNumberOfEntries];
-  bool enabled_ : 1;
-  bool has_entries_ : 1;
-  bool dirty_ : 1;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_ADDRESS_CACHE_H_
diff --git a/third_party/blink/renderer/platform/heap/address_cache_test.cc b/third_party/blink/renderer/platform/heap/address_cache_test.cc
deleted file mode 100644
index 280920d..0000000
--- a/third_party/blink/renderer/platform/heap/address_cache_test.cc
+++ /dev/null
@@ -1,80 +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 "third_party/blink/renderer/platform/heap/address_cache.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/heap/heap_page.h"
-
-namespace blink {
-
-namespace {
-
-const Address kObjectAddress = reinterpret_cast<Address>(kBlinkPageSize);
-
-}  // namespace
-
-TEST(AddressCacheTest, Scope) {
-  AddressCache cache;
-  AddressCache::EnabledScope scope(&cache);
-  EXPECT_FALSE(cache.Lookup(kObjectAddress));
-}
-
-TEST(AddressCacheTest, InitialIsEmpty) {
-  AddressCache cache;
-  cache.EnableLookup();
-  EXPECT_TRUE(cache.IsEmpty());
-}
-
-TEST(AddressCacheTest, LookupOnEmpty) {
-  AddressCache cache;
-  cache.EnableLookup();
-  EXPECT_FALSE(cache.Lookup(kObjectAddress));
-}
-
-TEST(AddressCacheTest, LookupAfterAddEntry) {
-  AddressCache cache;
-  cache.EnableLookup();
-  cache.AddEntry(kObjectAddress);
-  EXPECT_TRUE(cache.Lookup(kObjectAddress));
-}
-
-TEST(AddressCacheTest, AddEntryAddsWholePage) {
-  AddressCache cache;
-  cache.EnableLookup();
-  cache.AddEntry(kObjectAddress);
-  for (Address current = kObjectAddress;
-       current < (kObjectAddress + kBlinkPageSize); current++) {
-    EXPECT_TRUE(cache.Lookup(current));
-  }
-}
-
-TEST(AddressCacheTest, AddEntryOnlyAddsPageForGivenAddress) {
-  AddressCache cache;
-  cache.EnableLookup();
-  cache.AddEntry(kObjectAddress);
-  EXPECT_FALSE(cache.Lookup(kObjectAddress - 1));
-  EXPECT_FALSE(cache.Lookup(kObjectAddress + kBlinkPageSize + 1));
-}
-
-TEST(AddressCacheTest, FlushIfDirtyIgnoresNonDirty) {
-  AddressCache cache;
-  cache.EnableLookup();
-  cache.AddEntry(kObjectAddress);
-  cache.FlushIfDirty();
-  // Cannot do lookup in dirty cache.
-  EXPECT_FALSE(cache.IsEmpty());
-}
-
-TEST(AddressCacheTest, FlushIfDirtyHandlesDirty) {
-  AddressCache cache;
-  cache.EnableLookup();
-  cache.AddEntry(kObjectAddress);
-  cache.MarkDirty();
-  cache.FlushIfDirty();
-  // Cannot do lookup in dirty cache.
-  EXPECT_TRUE(cache.IsEmpty());
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/heap.cc b/third_party/blink/renderer/platform/heap/heap.cc
index aff6115..6f4ce3f 100644
--- a/third_party/blink/renderer/platform/heap/heap.cc
+++ b/third_party/blink/renderer/platform/heap/heap.cc
@@ -39,11 +39,11 @@
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
 #include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
-#include "third_party/blink/renderer/platform/heap/address_cache.h"
 #include "third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h"
 #include "third_party/blink/renderer/platform/heap/heap_compact.h"
 #include "third_party/blink/renderer/platform/heap/heap_stats_collector.h"
 #include "third_party/blink/renderer/platform/heap/marking_visitor.h"
+#include "third_party/blink/renderer/platform/heap/page_bloom_filter.h"
 #include "third_party/blink/renderer/platform/heap/page_memory.h"
 #include "third_party/blink/renderer/platform/heap/page_pool.h"
 #include "third_party/blink/renderer/platform/heap/thread_state_scopes.h"
@@ -95,7 +95,7 @@
     : thread_state_(thread_state),
       heap_stats_collector_(std::make_unique<ThreadHeapStatsCollector>()),
       region_tree_(std::make_unique<RegionTree>()),
-      address_cache_(std::make_unique<AddressCache>()),
+      page_bloom_filter_(std::make_unique<PageBloomFilter>()),
       free_page_pool_(std::make_unique<PagePool>()),
       process_heap_reporter_(std::make_unique<ProcessHeapReporter>()) {
   if (ThreadState::Current()->IsMainThread())
@@ -120,26 +120,21 @@
   DCHECK(thread_state_->InAtomicMarkingPause());
 
 #if !DCHECK_IS_ON()
-  if (address_cache_->Lookup(address))
+  if (!page_bloom_filter_->MayContain(address)) {
     return nullptr;
+  }
 #endif
 
   if (BasePage* page = LookupPageForAddress(address)) {
 #if DCHECK_IS_ON()
     DCHECK(page->Contains(address));
 #endif
-    DCHECK(!address_cache_->Lookup(address));
+    DCHECK(page_bloom_filter_->MayContain(address));
     DCHECK(&visitor->Heap() == &page->Arena()->GetThreadState()->Heap());
     visitor->ConservativelyMarkAddress(page, address);
     return address;
   }
 
-#if !DCHECK_IS_ON()
-  address_cache_->AddEntry(address);
-#else
-  if (!address_cache_->Lookup(address))
-    address_cache_->AddEntry(address);
-#endif
   return nullptr;
 }
 
diff --git a/third_party/blink/renderer/platform/heap/heap.h b/third_party/blink/renderer/platform/heap/heap.h
index 841ba4f9..5fa69d9 100644
--- a/third_party/blink/renderer/platform/heap/heap.h
+++ b/third_party/blink/renderer/platform/heap/heap.h
@@ -60,9 +60,9 @@
 class EphemeronCallbacksCounter;
 }  // namespace weakness_marking_test
 
-class AddressCache;
 class ConcurrentMarkingVisitor;
 class ThreadHeapStatsCollector;
+class PageBloomFilter;
 class PagePool;
 class ProcessHeapReporter;
 class RegionTree;
@@ -312,8 +312,6 @@
   size_t ObjectPayloadSizeForTesting();
   void ResetAllocationPointForTesting();
 
-  AddressCache* address_cache() const { return address_cache_.get(); }
-
   PagePool* GetFreePagePool() { return free_page_pool_.get(); }
 
   // This look-up uses the region search tree and a negative contains cache to
@@ -374,6 +372,8 @@
   }
 #endif
 
+  PageBloomFilter* page_bloom_filter() { return page_bloom_filter_.get(); }
+
  private:
   static int ArenaIndexForObjectSize(size_t);
 
@@ -388,7 +388,7 @@
   ThreadState* thread_state_;
   std::unique_ptr<ThreadHeapStatsCollector> heap_stats_collector_;
   std::unique_ptr<RegionTree> region_tree_;
-  std::unique_ptr<AddressCache> address_cache_;
+  std::unique_ptr<PageBloomFilter> page_bloom_filter_;
   std::unique_ptr<PagePool> free_page_pool_;
   std::unique_ptr<ProcessHeapReporter> process_heap_reporter_;
 
diff --git a/third_party/blink/renderer/platform/heap/heap_page.cc b/third_party/blink/renderer/platform/heap/heap_page.cc
index 16e45f7..968254e 100644
--- a/third_party/blink/renderer/platform/heap/heap_page.cc
+++ b/third_party/blink/renderer/platform/heap/heap_page.cc
@@ -35,11 +35,11 @@
 #include "base/trace_event/process_memory_dump.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
-#include "third_party/blink/renderer/platform/heap/address_cache.h"
 #include "third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h"
 #include "third_party/blink/renderer/platform/heap/heap_compact.h"
 #include "third_party/blink/renderer/platform/heap/heap_stats_collector.h"
 #include "third_party/blink/renderer/platform/heap/marking_verifier.h"
+#include "third_party/blink/renderer/platform/heap/page_bloom_filter.h"
 #include "third_party/blink/renderer/platform/heap/page_memory.h"
 #include "third_party/blink/renderer/platform/heap/page_pool.h"
 #include "third_party/blink/renderer/platform/heap/thread_state.h"
@@ -631,7 +631,6 @@
 #endif
 
 void NormalPageArena::AllocatePage() {
-  GetThreadState()->Heap().address_cache()->MarkDirty();
   PageMemory* page_memory =
       GetThreadState()->Heap().GetFreePagePool()->Take(ArenaIndex());
 
@@ -668,8 +667,9 @@
       new (page_memory->WritableStart()) NormalPage(page_memory, this);
   swept_pages_.PushLocked(page);
 
-  GetThreadState()->Heap().stats_collector()->IncreaseAllocatedSpace(
-      page->size());
+  ThreadHeap& heap = GetThreadState()->Heap();
+  heap.stats_collector()->IncreaseAllocatedSpace(page->size());
+  heap.page_bloom_filter()->Add(page->GetAddress());
 #if DCHECK_IS_ON() || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)
   // Allow the following addToFreeList() to add the newly allocated memory
   // to the free list.
@@ -683,8 +683,9 @@
 }
 
 void NormalPageArena::FreePage(NormalPage* page) {
-  GetThreadState()->Heap().stats_collector()->DecreaseAllocatedSpace(
-      page->size());
+  ThreadHeap& heap = GetThreadState()->Heap();
+  heap.stats_collector()->DecreaseAllocatedSpace(page->size());
+  heap.page_bloom_filter()->Remove(page->GetAddress());
 
   PageMemory* memory = page->Storage();
   page->~NormalPage();
@@ -971,7 +972,6 @@
   large_object_size += kAllocationGranularity;
 #endif
 
-  GetThreadState()->Heap().address_cache()->MarkDirty();
   PageMemory* page_memory = PageMemory::Allocate(
       large_object_size, GetThreadState()->Heap().GetRegionTree());
   Address large_object_address = page_memory->WritableStart();
@@ -997,6 +997,14 @@
 
   swept_pages_.PushLocked(large_object);
 
+  // Add all segments of kBlinkPageSize to the bloom filter so that the large
+  // object can be kept by derived pointers on stack. An alternative might be to
+  // prohibit derived pointers to large objects, but that is dangerous since the
+  // compiler is free to optimize on-stack base pointers away.
+  for (Address page_begin = RoundToBlinkPageStart(large_object->GetAddress());
+       page_begin < large_object->PayloadEnd(); page_begin += kBlinkPageSize) {
+    GetThreadState()->Heap().page_bloom_filter()->Add(page_begin);
+  }
   GetThreadState()->Heap().stats_collector()->IncreaseAllocatedSpace(
       large_object->size());
   GetThreadState()->Heap().stats_collector()->IncreaseAllocatedObjectSize(
@@ -1007,8 +1015,9 @@
 void LargeObjectArena::FreeLargeObjectPage(LargeObjectPage* object) {
   ASAN_UNPOISON_MEMORY_REGION(object->Payload(), object->PayloadSize());
   object->ObjectHeader()->Finalize(object->Payload(), object->PayloadSize());
-  GetThreadState()->Heap().stats_collector()->DecreaseAllocatedSpace(
-      object->size());
+  ThreadHeap& heap = GetThreadState()->Heap();
+  heap.stats_collector()->DecreaseAllocatedSpace(object->size());
+  heap.page_bloom_filter()->Remove(object->GetAddress());
 
   // Unpoison the object header and allocationGranularity bytes after the
   // object before freeing.
diff --git a/third_party/blink/renderer/platform/heap/heap_test.cc b/third_party/blink/renderer/platform/heap/heap_test.cc
index 6b3bd5fd..b9bf108 100644
--- a/third_party/blink/renderer/platform/heap/heap_test.cc
+++ b/third_party/blink/renderer/platform/heap/heap_test.cc
@@ -45,7 +45,6 @@
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/platform/bindings/buildflags.h"
 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
-#include "third_party/blink/renderer/platform/heap/address_cache.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/heap/heap_linked_stack.h"
@@ -3882,8 +3881,6 @@
     ThreadHeapStatsCollector::Scope stats_scope(
         heap.stats_collector(),
         ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure);
-    heap.address_cache()->EnableLookup();
-    heap.address_cache()->Flush();
 
     // Conservative marker should find the interesting objects by using anything
     // between object start and end.
@@ -3915,8 +3912,6 @@
     ThreadHeapStatsCollector::Scope stats_scope(
         heap.stats_collector(),
         ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure);
-    heap.address_cache()->EnableLookup();
-    heap.address_cache()->Flush();
 
     // After collecting all interesting objects the conservative marker should
     // not find them anymore.
diff --git a/third_party/blink/renderer/platform/heap/page_bloom_filter.h b/third_party/blink/renderer/platform/heap/page_bloom_filter.h
new file mode 100644
index 0000000..5e881212
--- /dev/null
+++ b/third_party/blink/renderer/platform/heap/page_bloom_filter.h
@@ -0,0 +1,48 @@
+// Copyright 2019 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PAGE_BLOOM_FILTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PAGE_BLOOM_FILTER_H_
+
+#include "third_party/blink/renderer/platform/heap/heap_page.h"
+#include "third_party/blink/renderer/platform/wtf/bloom_filter.h"
+
+namespace blink {
+
+// Bloom filter for Oilpan pages. Use counting to support correct deletion. This
+// is needed for stack scanning to quickly check if an arbitrary address doesn't
+// point inside Oilpan pages. May return false positives but never false
+// negatives.
+class PageBloomFilter {
+ public:
+  void Add(Address address) {
+    filter_.Add(Hash(RoundToBlinkPageStart(address)));
+  }
+
+  void Remove(Address address) {
+    filter_.Remove(Hash(RoundToBlinkPageStart(address)));
+  }
+
+  bool MayContain(Address address) const {
+    return filter_.MayContain(Hash(RoundToBlinkPageStart(address)));
+  }
+
+ private:
+  static constexpr size_t kNumberOfEntriesLog2 = 12;
+  static constexpr size_t kNumberOfEntries = 1 << kNumberOfEntriesLog2;
+
+  static unsigned Hash(Address address) {
+    size_t value = reinterpret_cast<size_t>(address) >> kBlinkPageSizeLog2;
+    value ^= value >> kNumberOfEntriesLog2;
+    value ^= value >> (kNumberOfEntriesLog2 * 2);
+    value &= kNumberOfEntries - 1;
+    return static_cast<unsigned>(value);
+  }
+
+  WTF::BloomFilter<kNumberOfEntriesLog2> filter_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PAGE_BLOOM_FILTER_H_
diff --git a/third_party/blink/renderer/platform/heap/thread_state.cc b/third_party/blink/renderer/platform/heap/thread_state.cc
index 252a80da..45cb6b33 100644
--- a/third_party/blink/renderer/platform/heap/thread_state.cc
+++ b/third_party/blink/renderer/platform/heap/thread_state.cc
@@ -48,7 +48,6 @@
 #include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
 #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
-#include "third_party/blink/renderer/platform/heap/address_cache.h"
 #include "third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h"
 #include "third_party/blink/renderer/platform/heap/cancelable_task_scheduler.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
@@ -1642,7 +1641,6 @@
   if (current_gc_data_.stack_state == BlinkGC::kHeapPointersOnStack) {
     ThreadHeapStatsCollector::Scope stats_scope(
         Heap().stats_collector(), ThreadHeapStatsCollector::kVisitStackRoots);
-    AddressCache::EnabledScope address_cache_scope(Heap().address_cache());
     PushRegistersAndVisitStack();
   }
 }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index f981d74..be91f44 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -235,7 +235,7 @@
       name: "BlockHTMLParserOnStyleSheets",
     },
     {
-      name: "BlockingDownloadsInSandboxWithoutUserActivation",
+      name: "BlockingDownloadsInSandbox",
       status: "test",
     },
     {
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc b/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc
index b79d3be..3b70bd9 100644
--- a/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc
@@ -185,7 +185,7 @@
   DISALLOW_COPY_AND_ASSIGN(TaskQueueThrottlerWithAutoAdvancingTimeTest);
 };
 
-INSTANTIATE_TEST_SUITE_P(,
+INSTANTIATE_TEST_SUITE_P(All,
                          TaskQueueThrottlerWithAutoAdvancingTimeTest,
                          testing::Bool());
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
index 40701df..18f4199 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
@@ -334,15 +334,15 @@
     public FrameTaskQueueControllerTest,
     public testing::WithParamInterface<QueueTraits::PrioritisationType> {};
 
-INSTANTIATE_TEST_SUITE_P(,
-                         TaskQueueCreationFromQueueTraitsTest,
-                         ::testing::Values(
-                            QueueTraits::PrioritisationType::kVeryHigh,
-                            QueueTraits::PrioritisationType::kHigh,
-                            QueueTraits::PrioritisationType::kBestEffort,
-                            QueueTraits::PrioritisationType::kRegular,
-                            QueueTraits::PrioritisationType::kLoading,
-                            QueueTraits::PrioritisationType::kLoadingControl));
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    TaskQueueCreationFromQueueTraitsTest,
+    ::testing::Values(QueueTraits::PrioritisationType::kVeryHigh,
+                      QueueTraits::PrioritisationType::kHigh,
+                      QueueTraits::PrioritisationType::kBestEffort,
+                      QueueTraits::PrioritisationType::kRegular,
+                      QueueTraits::PrioritisationType::kLoading,
+                      QueueTraits::PrioritisationType::kLoadingControl));
 
 TEST_P(TaskQueueCreationFromQueueTraitsTest,
         AddAndRetrieveAllTaskQueues) {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
index a6afaa1..ada71f20 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
@@ -862,7 +862,7 @@
   DISALLOW_COPY_AND_ASSIGN(MainThreadSchedulerImplTest);
 };
 
-INSTANTIATE_TEST_SUITE_P(,
+INSTANTIATE_TEST_SUITE_P(All,
                          MainThreadSchedulerImplTest,
                          testing::Values(AntiStarvationLogic::kEnabled,
                                          AntiStarvationLogic::kDisabled),
@@ -1337,7 +1337,7 @@
   }
 };
 
-INSTANTIATE_TEST_SUITE_P(,
+INSTANTIATE_TEST_SUITE_P(All,
                          DefaultUseCaseTest,
                          testing::Values(AntiStarvationLogic::kEnabled,
                                          AntiStarvationLogic::kDisabled),
@@ -2199,7 +2199,7 @@
   DISALLOW_COPY_AND_ASSIGN(MainThreadSchedulerImplWithMessageLoopTest);
 };
 
-INSTANTIATE_TEST_SUITE_P(,
+INSTANTIATE_TEST_SUITE_P(All,
                          MainThreadSchedulerImplWithMessageLoopTest,
                          testing::Values(AntiStarvationLogic::kEnabled,
                                          AntiStarvationLogic::kDisabled),
@@ -3535,7 +3535,7 @@
   }
 };
 
-INSTANTIATE_TEST_SUITE_P(,
+INSTANTIATE_TEST_SUITE_P(All,
                          MainThreadSchedulerImplWithInitalVirtualTimeTest,
                          testing::Values(AntiStarvationLogic::kEnabled,
                                          AntiStarvationLogic::kDisabled),
@@ -3559,7 +3559,7 @@
             {}) {}
 };
 
-INSTANTIATE_TEST_SUITE_P(,
+INSTANTIATE_TEST_SUITE_P(All,
                          CompositingExperimentWithExplicitSignalsTest,
                          testing::Values(AntiStarvationLogic::kEnabled,
                                          AntiStarvationLogic::kDisabled),
@@ -3601,7 +3601,7 @@
              kUseWillBeginMainFrameForCompositingPrioritization}) {}
 };
 
-INSTANTIATE_TEST_SUITE_P(,
+INSTANTIATE_TEST_SUITE_P(All,
                          CompositingExperimentWithImplicitSignalsTest,
                          testing::Values(AntiStarvationLogic::kEnabled,
                                          AntiStarvationLogic::kDisabled),
@@ -3726,7 +3726,7 @@
                                     {}) {}
 };
 
-INSTANTIATE_TEST_SUITE_P(,
+INSTANTIATE_TEST_SUITE_P(All,
                          VeryHighPriorityForCompositingAlwaysExperimentTest,
                          testing::Values(AntiStarvationLogic::kEnabled,
                                          AntiStarvationLogic::kDisabled),
@@ -3752,7 +3752,7 @@
                                     {}) {}
 };
 
-INSTANTIATE_TEST_SUITE_P(,
+INSTANTIATE_TEST_SUITE_P(All,
                          VeryHighPriorityForCompositingWhenFastExperimentTest,
                          testing::Values(AntiStarvationLogic::kEnabled,
                                          AntiStarvationLogic::kDisabled),
@@ -3808,7 +3808,7 @@
 };
 
 INSTANTIATE_TEST_SUITE_P(
-    ,
+    All,
     VeryHighPriorityForCompositingAlternatingExperimentTest,
     testing::Values(AntiStarvationLogic::kEnabled,
                     AntiStarvationLogic::kDisabled),
@@ -3849,7 +3849,7 @@
                                     {}) {}
 };
 
-INSTANTIATE_TEST_SUITE_P(,
+INSTANTIATE_TEST_SUITE_P(All,
                          VeryHighPriorityForCompositingAfterDelayExperimentTest,
                          testing::Values(AntiStarvationLogic::kEnabled,
                                          AntiStarvationLogic::kDisabled),
@@ -3905,7 +3905,7 @@
                                     {}) {}
 };
 
-INSTANTIATE_TEST_SUITE_P(,
+INSTANTIATE_TEST_SUITE_P(All,
                          VeryHighPriorityForCompositingBudgetExperimentTest,
                          testing::Values(AntiStarvationLogic::kEnabled,
                                          AntiStarvationLogic::kDisabled),
diff --git a/third_party/blink/renderer/platform/wtf/bloom_filter.h b/third_party/blink/renderer/platform/wtf/bloom_filter.h
index 1a839a2..c97ff23 100644
--- a/third_party/blink/renderer/platform/wtf/bloom_filter.h
+++ b/third_party/blink/renderer/platform/wtf/bloom_filter.h
@@ -27,7 +27,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BLOOM_FILTER_H_
 
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 
 namespace WTF {
 
@@ -60,20 +59,6 @@
   // Otherwise overflowed keys will stick around.
   void Clear();
 
-  void Add(const AtomicString& string) { Add(string.Impl()->ExistingHash()); }
-  void Add(const String& string) { Add(string.Impl()->GetHash()); }
-  void Remove(const AtomicString& string) {
-    Remove(string.Impl()->ExistingHash());
-  }
-  void Remove(const String& string) { Remove(string.Impl()->GetHash()); }
-
-  bool MayContain(const AtomicString& string) const {
-    return MayContain(string.Impl()->ExistingHash());
-  }
-  bool MayContain(const String& string) const {
-    return MayContain(string.Impl()->GetHash());
-  }
-
 #if DCHECK_IS_ON()
   // Slow.
   bool LikelyEmpty() const;
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
index a998db0..b44b390 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
+++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -60,6 +60,12 @@
 crbug.com/591099 external/wpt/css/css-position/static-position/vrl-rtl-ltr.tentative.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-position/static-position/vrl-rtl-rtl.html [ Failure ]
 
+### external/wpt/css/css-pseudo/
+crbug.com/457718 external/wpt/css/css-pseudo/marker-content-003.html [ Failure ]
+crbug.com/457718 external/wpt/css/css-pseudo/marker-content-003b.html [ Failure ]
+crbug.com/457718 external/wpt/css/css-pseudo/marker-content-004.html [ Failure ]
+crbug.com/457718 external/wpt/css/css-pseudo/marker-content-006.html [ Failure ]
+
 ### external/wpt/css/css-shapes/shape-outside/supported-shapes/polygon/
 crbug.com/591099 external/wpt/css/css-shapes/shape-outside/supported-shapes/polygon/shape-outside-polygon-017.html [ Failure ]
 
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index ec843fc..6116404 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1046,7 +1046,6 @@
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/abspos-new-width-rebalance.html [ Crash Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/balance-float-after-forced-break.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/balance-float-in-inline.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/balance-floats.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/balance-float-with-margin-top-and-line-after-break-2.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/balance-float-with-margin-top-and-line-after-break-3.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/balance-float-with-margin-top-and-line-after-break.html [ Crash Failure ]
@@ -1111,8 +1110,6 @@
 crbug.com/874506 virtual/layout_ng_block_frag/fast/multicol/event-offset.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/event-offset-in-nested.html [ Failure ]
 crbug.com/874506 virtual/layout_ng_block_frag/fast/multicol/filter-in-second-column.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/first-line-in-float-below-next-column-top.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/first-line-in-float-with-margin.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/fixedpos-child-becomes-static.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/float-after-break-after.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/float-avoidance.html [ Failure ]
@@ -1129,7 +1126,6 @@
 crbug.com/954171 virtual/layout_ng_block_frag/fast/multicol/float-with-margin-moved-by-child-block.html [ Failure Crash ]
 crbug.com/954171 virtual/layout_ng_block_frag/fast/multicol/float-with-margin-moved-by-child-line-and-unbreakable.html [ Failure Crash ]
 crbug.com/954171 virtual/layout_ng_block_frag/fast/multicol/float-with-margin-moved-by-child-line.html [ Failure Crash ]
-crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/float-with-margin-moved-unbreakable.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/forced-break-after-block-with-spanner.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/forced-break-after-empty-block-after-spanner.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/forced-break-after-last-block-before-spanner.html [ Failure ]
@@ -1138,7 +1134,6 @@
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/hit-test-above-or-below.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/hit-test-end-of-column.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/hit-test-end-of-column-with-line-height.html [ Crash Failure ]
-crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/image-inside-nested-blocks-with-border.html [ Failure ]
 crbug.com/829181 virtual/layout_ng_block_frag/fast/multicol/infinitely-tall-content-in-outer-crash.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/inline-block-baseline.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/inline-getclientrects.html [ Failure ]
@@ -1271,7 +1266,6 @@
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-lr/float-content-break.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-lr/float-edge.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-lr/float-paginate.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-lr/image-inside-nested-blocks-with-border.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-lr/nested-columns.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-lr/offset-top-and-left-at-boundaries.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-lr/offset-top-and-left-at-boundaries-nested.html [ Failure ]
@@ -1294,7 +1288,6 @@
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-rl/float-content-break.html [ Crash Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-rl/float-edge.html [ Crash Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-rl/float-paginate.html [ Crash Failure ]
-crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-rl/image-inside-nested-blocks-with-border.html [ Failure ]
 crbug.com/467477 virtual/layout_ng_block_frag/fast/multicol/vertical-rl/nested-columns.html [ Crash Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-rl/offset-top-and-left-at-boundaries.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-rl/offset-top-and-left-at-boundaries-nested.html [ Failure ]
@@ -1307,14 +1300,11 @@
 crbug.com/591099 virtual/layout_ng_block_frag/fragmentation/become-unfragmented-with-lines.html [ Crash Pass ]
 crbug.com/591099 virtual/layout_ng_block_frag/fragmentation/become-unfragmented-with-unbreakable-blocks.html [ Crash Pass ]
 crbug.com/591099 virtual/layout_ng_block_frag/fragmentation/block-after-float-first-child.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_block_frag/fragmentation/change-fragmentainer-height-block-float-2.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_block_frag/fragmentation/change-fragmentainer-height-block-float.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fragmentation/change-fragmentainer-height-inline-float.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fragmentation/change-fragmentainer-height-line-float.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fragmentation/content-preceding-first-fragmentainer.html [ Crash ]
 crbug.com/591099 virtual/layout_ng_block_frag/fragmentation/float-after-forced-break.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fragmentation/float-margin-top.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_block_frag/fragmentation/float-pushed-to-next-fragmentainer-by-floats.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fragmentation/forced-break-clearance-unsplittable-content.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fragmentation/overflow-crossing-boundary.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_block_frag/fragmentation/relayout-abspos.html [ Failure ]
@@ -2389,6 +2379,20 @@
 crbug.com/492511 [ Mac ] virtual/text-antialias/atsui-negative-spacing-features.html [ Failure ]
 crbug.com/492511 [ Mac ] virtual/text-antialias/international/arabic-justify.html [ Failure ]
 
+# Temporarily disable top-level await tests as the implementation moves
+# from the DevTools frontend to native V8
+crbug.com/1021921 http/tests/devtools/console/console-top-level-await.js [ Skip ]
+crbug.com/1021921 http/tests/devtools/unit/preprocess-top-level-awaits.js [ Skip ]
+crbug.com/1021921 http/tests/devtools/console/console-eval-exception-report.js [ Skip ]
+crbug.com/1021921 http/tests/devtools/console/console-eval-object-literal.js [ Skip ]
+crbug.com/1021921 http/tests/devtools/console/console-eval-throw.js [ Skip ]
+crbug.com/1021921 http/tests/devtools/console/console-eval-undefined-override.js [ Skip ]
+crbug.com/1021921 http/tests/devtools/console/console-group-similar.js [ Skip ]
+crbug.com/1021921 http/tests/devtools/console/console-xpath.js [ Skip ]
+crbug.com/1021921 http/tests/devtools/console/exception-objects.js [ Skip ]
+crbug.com/1021921 http/tests/devtools/console/nested-worker-eval-contains-stack.js [ Skip ]
+crbug.com/1021921 http/tests/devtools/console/worker-eval-contains-stack.js [ Skip ]
+
 # Ref tests that fail due to differences in inline box structure, even though they contain the same text.
 # This happens because inline box layout uses fixed-point measurements, which can cause rounding differences.
 crbug.com/321237 [ Mac ] fast/selectors/007a.html [ Failure ]
@@ -2720,6 +2724,9 @@
 crbug.com/1012627 [ Win7 ] external/wpt/css/css-text/line-breaking/line-breaking-021.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Linux ] external/wpt/mathml/presentation-markup/tokens/ms-001.html [ Failure ]
+crbug.com/626703 [ Mac ] external/wpt/mathml/presentation-markup/tokens/ms-001.html [ Failure ]
+crbug.com/626703 [ Win ] external/wpt/mathml/presentation-markup/tokens/ms-001.html [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/quirks/percentage-height-quirk-excludes-flex-grid-001.html [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/quirks/percentage-height-quirk-excludes-flex-grid-001.html [ Failure ]
 crbug.com/626703 [ Win ] external/wpt/quirks/percentage-height-quirk-excludes-flex-grid-001.html [ Failure ]
@@ -3881,12 +3888,8 @@
 crbug.com/792446 external/wpt/css/css-multicol/multicol-span-float-001.xht [ Failure ]
 crbug.com/964183 external/wpt/css/css-multicol/multicol-width-005.html [ Failure ]
 
-crbug.com/457718 external/wpt/css/css-pseudo/marker-content-002.html [ Failure ]
-crbug.com/457718 external/wpt/css/css-pseudo/marker-content-003.html [ Failure ]
-crbug.com/457718 external/wpt/css/css-pseudo/marker-content-003b.html [ Failure ]
-crbug.com/457718 external/wpt/css/css-pseudo/marker-content-004.html [ Failure ]
-crbug.com/457718 external/wpt/css/css-pseudo/marker-content-005.html [ Failure ]
-crbug.com/457718 external/wpt/css/css-pseudo/marker-content-006.html [ Failure ]
+crbug.com/796961 external/wpt/css/css-pseudo/marker-content-002.html [ Failure ]
+crbug.com/796961 external/wpt/css/css-pseudo/marker-content-005.html [ Failure ]
 crbug.com/457718 external/wpt/css/css-pseudo/marker-content-007.html [ Failure ]
 crbug.com/457718 external/wpt/css/css-pseudo/marker-content-008.html [ Failure ]
 crbug.com/457718 external/wpt/css/css-pseudo/marker-content-009.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
index 2711d246..f6f59c1 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -118099,18 +118099,6 @@
      {}
     ]
    ],
-   "mathml/presentation-markup/direction/direction-009.html": [
-    [
-     "mathml/presentation-markup/direction/direction-009.html",
-     [
-      [
-       "/mathml/presentation-markup/direction/direction-009-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "mathml/presentation-markup/direction/direction-010.html": [
     [
      "mathml/presentation-markup/direction/direction-010.html",
@@ -118615,6 +118603,18 @@
      {}
     ]
    ],
+   "mathml/presentation-markup/tokens/ms-001.html": [
+    [
+     "mathml/presentation-markup/tokens/ms-001.html",
+     [
+      [
+       "/mathml/presentation-markup/tokens/ms-001-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "mathml/relations/css-styling/color-001.html": [
     [
      "mathml/relations/css-styling/color-001.html",
@@ -153556,6 +153556,9 @@
    "dom/events/Event-dispatch-listener-order.window-expected.txt": [
     []
    ],
+   "dom/events/Event-dispatch-order-at-target-expected.txt": [
+    []
+   ],
    "dom/events/EventListener-handleEvent-expected.txt": [
     []
    ],
@@ -161401,6 +161404,12 @@
    "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/serviceworker-failure.js.headers": [
     []
    ],
+   "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/serviceworker-success.js": [
+    []
+   ],
+   "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/serviceworker-success.js.headers": [
+    []
+   ],
    "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/sharedworker-failure.js": [
     []
    ],
@@ -161437,6 +161446,9 @@
    "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-serviceworker-failure.https.html.headers": [
     []
    ],
+   "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-serviceworker-success.https.html.headers": [
+    []
+   ],
    "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.https.html.headers": [
     []
    ],
@@ -165805,9 +165817,6 @@
    "mathml/presentation-markup/direction/direction-008-ref.html": [
     []
    ],
-   "mathml/presentation-markup/direction/direction-009-ref.html": [
-    []
-   ],
    "mathml/presentation-markup/direction/direction-010-ref.html": [
     []
    ],
@@ -165940,6 +165949,9 @@
    "mathml/presentation-markup/spaces/space-2-ref.html": [
     []
    ],
+   "mathml/presentation-markup/tokens/ms-001-ref.html": [
+    []
+   ],
    "mathml/relations/css-styling/attribute-mapping-001-expected.txt": [
     []
    ],
@@ -178744,6 +178756,9 @@
    "wasm/serialization/module/resources/serviceworker-failure.js": [
     []
    ],
+   "wasm/serialization/module/resources/serviceworker-success.js": [
+    []
+   ],
    "wasm/serialization/module/resources/sharedworker-failure.js": [
     []
    ],
@@ -202369,6 +202384,16 @@
      }
     ]
    ],
+   "compression/decompression-corrupt-input.any.js": [
+    [
+     "compression/decompression-corrupt-input.any.html",
+     {}
+    ],
+    [
+     "compression/decompression-corrupt-input.any.worker.html",
+     {}
+    ]
+   ],
    "compression/decompression-empty-input.tentative.any.js": [
     [
      "compression/decompression-empty-input.tentative.any.html",
@@ -226854,6 +226879,12 @@
      }
     ]
    ],
+   "dom/events/Event-dispatch-order-at-target.html": [
+    [
+     "dom/events/Event-dispatch-order-at-target.html",
+     {}
+    ]
+   ],
    "dom/events/Event-dispatch-order.html": [
     [
      "dom/events/Event-dispatch-order.html",
@@ -247608,6 +247639,12 @@
      {}
     ]
    ],
+   "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-serviceworker-success.https.html": [
+    [
+     "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-serviceworker-success.https.html",
+     {}
+    ]
+   ],
    "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.https.html": [
     [
      "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.https.html",
@@ -251241,15 +251278,15 @@
      {}
     ]
    ],
-   "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_allow_downloads_without_user_activation.sub.tentative.html": [
+   "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_allow_downloads.sub.tentative.html": [
     [
-     "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_allow_downloads_without_user_activation.sub.tentative.html",
+     "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_allow_downloads.sub.tentative.html",
      {}
     ]
    ],
-   "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_block_downloads_without_user_activation.sub.tentative.html": [
+   "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_block_downloads.sub.tentative.html": [
     [
-     "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_block_downloads_without_user_activation.sub.tentative.html",
+     "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_block_downloads.sub.tentative.html",
      {}
     ]
    ],
@@ -251319,17 +251356,17 @@
      {}
     ]
    ],
-   "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads_without_user_activation.sub.tentative.html": [
+   "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.html": [
     [
-     "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads_without_user_activation.sub.tentative.html",
+     "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.html",
      {
       "timeout": "long"
      }
     ]
    ],
-   "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_block_downloads_without_user_activation.sub.tentative.html": [
+   "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_block_downloads.sub.tentative.html": [
     [
-     "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_block_downloads_without_user_activation.sub.tentative.html",
+     "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_block_downloads.sub.tentative.html",
      {}
     ]
    ],
@@ -253361,6 +253398,12 @@
      {}
     ]
    ],
+   "html/semantics/interactive-elements/the-summary-element/anchor-with-inline-element.html": [
+    [
+     "html/semantics/interactive-elements/the-summary-element/anchor-with-inline-element.html",
+     {}
+    ]
+   ],
    "html/semantics/interactive-elements/the-summary-element/display-table-with-rt-crash.html": [
     [
      "html/semantics/interactive-elements/the-summary-element/display-table-with-rt-crash.html",
@@ -305593,9 +305636,9 @@
      {}
     ]
    ],
-   "trusted-types/idlharness.window.js": [
+   "trusted-types/idlharness.tentative.window.js": [
     [
-     "trusted-types/idlharness.window.html",
+     "trusted-types/idlharness.tentative.window.html",
      {
       "script_metadata": [
        [
@@ -312207,6 +312250,12 @@
      {}
     ]
    ],
+   "wasm/serialization/module/window-serviceworker-success.https.html": [
+    [
+     "wasm/serialization/module/window-serviceworker-success.https.html",
+     {}
+    ]
+   ],
    "wasm/serialization/module/window-sharedworker-failure.html": [
     [
      "wasm/serialization/module/window-sharedworker-failure.html",
@@ -344776,6 +344825,10 @@
    "11d8736cb225d6ce575677dcdb70b0a19dd4f65f",
    "testharness"
   ],
+  "compression/decompression-corrupt-input.any.js": [
+   "95e91b662ee47f545167cd05dc4d06b85cb74b00",
+   "testharness"
+  ],
   "compression/decompression-empty-input.tentative.any.js": [
    "ff4cff522a4a7ba0ba3eedb79c4d39b0752c9caf",
    "testharness"
@@ -387881,11 +387934,11 @@
    "testharness"
   ],
   "css/css-grid/parsing/grid-area-valid-expected.txt": [
-   "bbf2aea23dc66eca69a03c45fc3d67ffe8da0da0",
+   "d19e955085e3672be9ad1e55274dad1dc6f3f18a",
    "support"
   ],
   "css/css-grid/parsing/grid-area-valid.html": [
-   "abe58951efeb7b7cd343009d45af04cc1ad9574a",
+   "9f93e6325b1b3cb2fff53f1c9e8b4963ac875e09",
    "testharness"
   ],
   "css/css-grid/parsing/grid-auto-columns-computed.html": [
@@ -437192,6 +437245,14 @@
    "361006a7240496e9be747faca5056fe2a62a2cff",
    "testharness"
   ],
+  "dom/events/Event-dispatch-order-at-target-expected.txt": [
+   "3db500ef25e94bb74030a5f6a995632410577253",
+   "support"
+  ],
+  "dom/events/Event-dispatch-order-at-target.html": [
+   "79673c32564cbe785858266d4737de6bd5f7bade",
+   "testharness"
+  ],
   "dom/events/Event-dispatch-order.html": [
    "ca94434595c6ee19fb0f6982f56da0d005b4586c",
    "testharness"
@@ -442929,7 +442990,7 @@
    "testharness"
   ],
   "feature-policy/feature-policy-for-sandbox/resources/helper.js": [
-   "9de8416535613fc1d46396953750cc9ab6a7990b",
+   "eec189871ff82d18c6e8a3cc86ccf9c08597ca42",
    "support"
   ],
   "feature-policy/feature-policy-for-sandbox/resources/opened_window.html": [
@@ -455272,6 +455333,14 @@
    "6604450991a122e3e241e40b1b9e0516c525389d",
    "support"
   ],
+  "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/serviceworker-success.js": [
+   "34add843ecaaff85b5d50b6eab31a616226f9234",
+   "support"
+  ],
+  "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/serviceworker-success.js.headers": [
+   "20319c1b02dda1ca0d40a0cae6bf6b460f5562f1",
+   "support"
+  ],
   "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/sharedworker-failure.js": [
    "8472318abd53207ec56b3f5988fb0a49d0c006a4",
    "support"
@@ -455352,6 +455421,14 @@
    "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8",
    "support"
   ],
+  "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-serviceworker-success.https.html": [
+   "3d5ced9760625793950bf27934c182f48420a487",
+   "testharness"
+  ],
+  "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-serviceworker-success.https.html.headers": [
+   "4fff9d9fba4c81f953826ffea010a75be626b95d",
+   "support"
+  ],
   "html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.https.html": [
    "023cb5acdef1c144dbad4ebefd0af23fc6c17d79",
    "testharness"
@@ -459924,11 +460001,11 @@
    "042851bbb492365e9d176aff8d678feb645f1d18",
    "testharness"
   ],
-  "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_allow_downloads_without_user_activation.sub.tentative.html": [
-   "32409f220f0a273f165741e2d79ca60846d61648",
+  "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_allow_downloads.sub.tentative.html": [
+   "1e93cb5997df5c85a6b67d3b486ae441adfb33fd",
    "testharness"
   ],
-  "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_block_downloads_without_user_activation.sub.tentative.html": [
+  "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_block_downloads.sub.tentative.html": [
    "abd4d7c5e0d76d04cd678b00a153d5a8f10bddf7",
    "testharness"
   ],
@@ -459976,11 +460053,11 @@
    "12c4e0ca50236caacae89c76da3b81effd7b44be",
    "testharness"
   ],
-  "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads_without_user_activation.sub.tentative.html": [
-   "6af49b8d78ddf2acbad9e8fb875e8250c825cd33",
+  "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.html": [
+   "50e28f650c74ca734f63f970e61dfea77e7ab0bd",
    "testharness"
   ],
-  "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_block_downloads_without_user_activation.sub.tentative.html": [
+  "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_block_downloads.sub.tentative.html": [
    "9b9246c393ec9b4ee3b9762d6d06ea65ff0ff5d1",
    "testharness"
   ],
@@ -462424,6 +462501,10 @@
    "4a3693bd2dafe710b82054bfadd8bcaa97b16db5",
    "testharness"
   ],
+  "html/semantics/interactive-elements/the-summary-element/anchor-with-inline-element.html": [
+   "ab200020b4f05321d4ee7c17c4a8f11c6f5931db",
+   "testharness"
+  ],
   "html/semantics/interactive-elements/the-summary-element/display-table-with-rt-crash.html": [
    "57cc45478e03ce1cdbb755281b2f434b38582563",
    "testharness"
@@ -470340,14 +470421,6 @@
    "d94a036be00f404bd4d51350a85f70c180e9c776",
    "reftest"
   ],
-  "mathml/presentation-markup/direction/direction-009-ref.html": [
-   "8b80b7e6bead29d97540896d5ac1ae14b46881f1",
-   "support"
-  ],
-  "mathml/presentation-markup/direction/direction-009.html": [
-   "c0ca31d40a82e5af2e23a4c5dee83f9e2bb593cb",
-   "reftest"
-  ],
   "mathml/presentation-markup/direction/direction-010-ref.html": [
    "4f595ed49f698a7a70392edb5e72dd1df8471368",
    "support"
@@ -470856,6 +470929,14 @@
    "f9354266a7c6c42a75519e9771eb2c61536ad8e5",
    "testharness"
   ],
+  "mathml/presentation-markup/tokens/ms-001-ref.html": [
+   "bbd42a93eedbbabb7aff8fa1aa60f5c954e48210",
+   "support"
+  ],
+  "mathml/presentation-markup/tokens/ms-001.html": [
+   "b0b03f225525ffacf1d8f73da03a3848b39e96f8",
+   "reftest"
+  ],
   "mathml/relations/css-styling/attribute-mapping-001-expected.txt": [
    "5c64785af046109797f9980ec7da6db6f4b3acb1",
    "support"
@@ -512852,8 +512933,8 @@
    "074fe79dc93fee6563bcb9ce2db3fa708bf4ad4f",
    "testharness"
   ],
-  "trusted-types/idlharness.window.js": [
-   "7be9615ce67ca1582c3b82ed849d7019a61e4cdd",
+  "trusted-types/idlharness.tentative.window.js": [
+   "5a854a12b78026a3318dad70ffa0d6a690e39f55",
    "testharness"
   ],
   "trusted-types/support/WorkerGlobalScope-importScripts.https.js": [
@@ -517456,6 +517537,10 @@
    "39796f9d94a39d2a13ed832544ce781373a20655",
    "support"
   ],
+  "wasm/serialization/module/resources/serviceworker-success.js": [
+   "89dd8a3831b138cb6c4eb2a5578b95bb711cd189",
+   "support"
+  ],
   "wasm/serialization/module/resources/sharedworker-failure.js": [
    "854c70b9e84e6e6fb1c59f64a06a79646a122576",
    "support"
@@ -517488,6 +517573,10 @@
    "97c5a1decdb85317930508ece8f306fb80880ca2",
    "testharness"
   ],
+  "wasm/serialization/module/window-serviceworker-success.https.html": [
+   "a479b37e5e227e4961f59e09554c137041528124",
+   "testharness"
+  ],
   "wasm/serialization/module/window-sharedworker-failure.html": [
    "667e985a30b53c0ecadfd4c68f6217b87a7a5b98",
    "testharness"
diff --git a/third_party/blink/web_tests/external/wpt/compression/decompression-corrupt-input.any.js b/third_party/blink/web_tests/external/wpt/compression/decompression-corrupt-input.any.js
new file mode 100644
index 0000000..95e91b6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/compression/decompression-corrupt-input.any.js
@@ -0,0 +1,299 @@
+// META global=worker
+
+// This test checks that DecompressionStream behaves according to the standard
+// when the input is corrupted. To avoid a combinatorial explosion in the
+// number of tests, we only mutate one field at a time, and we only test
+// "interesting" values.
+
+'use strict';
+
+// The many different cases are summarised in this data structure.
+const expectations = [
+  {
+    format: 'deflate',
+
+    // Decompresses to 'expected output'.
+    baseInput: [120, 156, 75, 173, 40, 72, 77, 46, 73, 77, 81, 200, 47, 45, 41,
+                40, 45, 1, 0, 48, 173, 6, 36],
+
+    // See RFC1950 for the definition of the various fields used by deflate:
+    // https://tools.ietf.org/html/rfc1950.
+    fields: [
+      {
+        // The function of this field. This matches the name used in the RFC.
+        name: 'CMF',
+
+        // The offset of the field in bytes from the start of the input.
+        offset: 0,
+
+        // The length of the field in bytes.
+        length: 1,
+
+        cases: [
+          {
+            // The value to set the field to. If the field contains multiple
+            // bytes, all the bytes will be set to this value.
+            value: 0,
+
+            // The expected result. 'success' means the input is decoded
+            // successfully. 'error' means that the stream will be errored.
+            result: 'error'
+          }
+        ]
+      },
+      {
+        name: 'FLG',
+        offset: 1,
+        length: 1,
+
+        // FLG contains a 4-bit checksum (FCHECK) which is calculated in such a
+        // way that there are 4 valid values for this field.
+        cases: [
+          {
+            value: 218,
+            result: 'success'
+          },
+          {
+            value: 1,
+            result: 'success'
+          },
+          {
+            value: 94,
+            result: 'success'
+          },
+          {
+            // The remaining 252 values cause an error.
+            value: 157,
+            result: 'error'
+          }
+        ]
+      },
+      {
+        name: 'DATA',
+        // In general, changing any bit of the data will trigger a checksum
+        // error. Only the last byte does anything else.
+        offset: 18,
+        length: 1,
+        cases: [
+          {
+            value: 4,
+            result: 'success'
+          },
+          {
+            value: 5,
+            result: 'error'
+          }
+        ]
+      },
+      {
+        name: 'ADLER',
+        offset: -4,
+        length: 4,
+        cases: [
+          {
+            value: 255,
+            result: 'error'
+          }
+        ]
+      }
+    ]
+  },
+  {
+    format: 'gzip',
+
+    // Decompresses to 'expected output'.
+    baseInput: [31, 139, 8, 0, 0, 0, 0, 0, 0, 3, 75, 173, 40, 72, 77, 46, 73,
+                77, 81, 200, 47, 45, 41, 40, 45, 1, 0, 176, 1, 57, 179, 15, 0,
+                0, 0],
+
+    // See RFC1952 for the definition of the various fields used by gzip:
+    // https://tools.ietf.org/html/rfc1952.
+    fields: [
+      {
+        name: 'ID',
+        offset: 0,
+        length: 2,
+        cases: [
+          {
+            value: 255,
+            result: 'error'
+          }
+        ]
+      },
+      {
+        name: 'CM',
+        offset: 2,
+        length: 1,
+        cases: [
+          {
+            value: 0,
+            result: 'error'
+          }
+        ]
+      },
+      {
+        name: 'FLG',
+        offset: 3,
+        length: 1,
+        cases: [
+          {
+            value: 1, // FTEXT
+            result: 'success'
+          },
+          {
+            value: 2, // FHCRC
+            result: 'error'
+          }
+        ]
+      },
+      {
+        name: 'MTIME',
+        offset: 4,
+        length: 4,
+        cases: [
+          {
+            // Any value is valid for this field.
+            value: 255,
+            result: 'success'
+          }
+        ]
+      },
+      {
+        name: 'XFL',
+        offset: 8,
+        length: 1,
+        cases: [
+          {
+            // Any value is accepted.
+            value: 255,
+            result: 'success'
+          }
+        ]
+      },
+      {
+        name: 'OS',
+        offset: 9,
+        length: 1,
+        cases: [
+          {
+            // Any value is accepted.
+            value: 128,
+            result: 'success'
+          }
+        ]
+      },
+      {
+        name: 'DATA',
+
+        // The last byte of the data is the most interesting.
+        offset: 26,
+        length: 1,
+        cases: [
+          {
+            value: 3,
+            result: 'error'
+          },
+          {
+            value: 4,
+            result: 'success'
+          }
+        ]
+      },
+      {
+        name: 'CRC',
+        offset: -8,
+        length: 4,
+        cases: [
+          {
+            // Any change will error the stream.
+            value: 0,
+            result: 'error'
+          }
+        ]
+      },
+      {
+        name: 'ISIZE',
+        offset: -4,
+        length: 4,
+        cases: [
+          {
+            // A mismatch will error the stream.
+            value: 1,
+            result: 'error'
+          }
+        ]
+      }
+    ]
+  }
+];
+
+async function tryDecompress(input, format) {
+  const ds = new DecompressionStream(format);
+  const reader = ds.readable.getReader();
+  const writer = ds.writable.getWriter();
+  writer.write(input).catch(() => {});
+  writer.close().catch(() => {});
+  let out = [];
+  while (true) {
+    try {
+      const { value, done } = await reader.read();
+      if (done) {
+        break;
+      }
+      out = out.concat(Array.from(value));
+    } catch (e) {
+      return { result: 'error' };
+    }
+  }
+  const expectedOutput = 'expected output';
+  if (out.length !== expectedOutput.length) {
+    return { result: 'corrupt' };
+  }
+  for (let i = 0; i < out.length; ++i) {
+    if (out[i] !== expectedOutput.charCodeAt(i)) {
+      return { result: 'corrupt' };
+    }
+  }
+  return { result: 'success' };
+}
+
+function corruptInput(input, offset, length, value) {
+  const output = new Uint8Array(input);
+  if (offset < 0) {
+    offset += input.length;
+  }
+  for (let i = offset; i < offset + length; ++i) {
+    output[i] = value;
+  }
+  return output;
+}
+
+for (const { format, baseInput, fields } of expectations) {
+  promise_test(async () => {
+    const { result } = await tryDecompress(new Uint8Array(baseInput), format);
+    assert_equals(result, 'success', 'decompression should succeed');
+  }, `the unchanged input for '${format}' should decompress successfully`);
+
+  promise_test(async () => {
+    const truncatedInput = new Uint8Array(baseInput.slice(0, -1));
+    const { result } = await tryDecompress(truncatedInput, format);
+    assert_equals(result, 'error', 'decompression should fail');
+  }, `truncating the input for '${format}' should give an error`);
+
+  promise_test(async () => {
+    const extendedInput = new Uint8Array(baseInput.concat([0]));
+    const { result } = await tryDecompress(extendedInput, format);
+    assert_equals(result, 'error', 'decompression should fail');
+  }, `trailing junk for '${format}' should give an error`);
+
+  for (const { name, offset, length, cases } of fields) {
+    for (const { value, result } of cases) {
+      promise_test(async () => {
+        const corruptedInput = corruptInput(baseInput, offset, length, value);
+        const { result: actual } =
+              await tryDecompress(corruptedInput, format);
+        assert_equals(actual, result, 'result should match');
+      }, `format '${format}' field ${name} should be ${result} for ${value}`);
+    }
+  }
+}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-valid-expected.txt
index bbf2aea..d19e955 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-valid-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-valid-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 55 tests; 24 PASS, 31 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 56 tests; 24 PASS, 32 FAIL, 0 TIMEOUT, 0 NOTRUN.
 FAIL e.style['grid-area'] = "auto" should set the property value assert_equals: serialization should be canonical expected "auto" but got "auto / auto / auto / auto"
 FAIL e.style['grid-area'] = "auto / auto" should set the property value assert_equals: serialization should be canonical expected "auto" but got "auto / auto / auto / auto"
 FAIL e.style['grid-area'] = "auto / auto / auto" should set the property value assert_equals: serialization should be canonical expected "auto" but got "auto / auto / auto / auto"
@@ -55,5 +55,6 @@
 PASS e.style['grid-column'] = "2 j / span 3 k" should set the property value
 PASS e.style['grid-column-end'] = "\\31st" should set the property value
 PASS e.style['grid-column-end'] = "\\31 st" should set the property value
+FAIL e.style['grid-column'] = "\\31st / \\31 st" should set the property value assert_in_array: serialization should be sound value "\\31 st / \31 st" not in array ["\\31 st", "\\31st"]
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-valid.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-valid.html
index abe5895..9f93e63 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-valid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-valid.html
@@ -76,11 +76,12 @@
 test_valid_value("grid-row", "1 / auto", "1");
 test_valid_value("grid-column", "2 j / span 3 k");
 
-
 // https://github.com/w3c/csswg-drafts/issues/2858
-// '\\31 st' in Blink, Firefox, '1st' in Edge, '"1st"' in Safari.
-test_valid_value("grid-column-end",  "\\31st", ["\\31 st", "1st", '"1st"']);
-test_valid_value("grid-column-end",  "\\31 st", ["\\31 st", "1st", '"1st"']);
+// '\\31 st' in Blink, Firefox, EdgeHTML and Safari serialize invalid values.
+test_valid_value("grid-column-end", "\\31st", ["\\31 st", "\\31st"]);
+test_valid_value("grid-column-end", "\\31 st", ["\\31 st", "\\31st"]);
+test_valid_value("grid-column", "\\31st / \\31 st", ["\\31 st", "\\31st"]);
+
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/Event-dispatch-order-at-target-expected.txt b/third_party/blink/web_tests/external/wpt/dom/events/Event-dispatch-order-at-target-expected.txt
new file mode 100644
index 0000000..3db500e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/events/Event-dispatch-order-at-target-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Listeners are invoked in correct order (AT_TARGET phase) assert_array_equals: bubbles: true property 0, expected "capturing" but got "bubbling"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/Event-dispatch-order-at-target.html b/third_party/blink/web_tests/external/wpt/dom/events/Event-dispatch-order-at-target.html
new file mode 100644
index 0000000..79673c3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/events/Event-dispatch-order-at-target.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Listeners are invoked in correct order (AT_TARGET phase)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+"use strict";
+
+test(() => {
+    const el = document.createElement("div");
+    const expectedOrder = ["capturing", "bubbling"];
+
+    let actualOrder = [];
+    el.addEventListener("click", evt => {
+        assert_equals(evt.eventPhase, Event.AT_TARGET);
+        actualOrder.push("bubbling");
+    }, false);
+    el.addEventListener("click", evt => {
+        assert_equals(evt.eventPhase, Event.AT_TARGET);
+        actualOrder.push("capturing");
+    }, true);
+
+    el.dispatchEvent(new Event("click", {bubbles: true}));
+    assert_array_equals(actualOrder, expectedOrder, "bubbles: true");
+
+    actualOrder = [];
+    el.dispatchEvent(new Event("click", {bubbles: false}));
+    assert_array_equals(actualOrder, expectedOrder, "bubbles: false");
+}, "Listeners are invoked in correct order (AT_TARGET phase)");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/feature-policy-for-sandbox/resources/helper.js b/third_party/blink/web_tests/external/wpt/feature-policy/feature-policy-for-sandbox/resources/helper.js
index 9de84165..eec1898 100644
--- a/third_party/blink/web_tests/external/wpt/feature-policy/feature-policy-for-sandbox/resources/helper.js
+++ b/third_party/blink/web_tests/external/wpt/feature-policy/feature-policy-for-sandbox/resources/helper.js
@@ -7,7 +7,7 @@
 
 // Feature-policies that represent specific sandbox flags.
 const sandbox_features = [
-    "downloads-without-user-activation", "forms", "modals", "orientation-lock",
+    "downloads", "forms", "modals", "orientation-lock",
     "pointer-lock", "popups", "presentation", "scripts", "top-navigation"];
 
 // TODO(ekaramad): Figure out different inheritance requirements for different
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_allow_downloads_without_user_activation.sub.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_allow_downloads.sub.tentative.html
similarity index 86%
rename from third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_allow_downloads_without_user_activation.sub.tentative.html
rename to third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_allow_downloads.sub.tentative.html
index 32409f2..1e93cb59 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_allow_downloads_without_user_activation.sub.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_allow_downloads.sub.tentative.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
-<title>&lt;a download&gt; triggered download in sandbox is allowed by allow-downloads-without-user-activation.</title>
+<title>&lt;a download&gt; triggered download in sandbox is allowed by allow-downloads.</title>
 <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-iframe-sandbox">
 <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-iframe-element">
 <script src="/resources/testharness.js"></script>
@@ -14,7 +14,7 @@
     const token = "{{$id:uuid()}}";
     var iframe = document.createElement("iframe");
     iframe.srcdoc = "<a>Download</a>";
-    iframe.sandbox = "allow-same-origin allow-downloads-without-user-activation";
+    iframe.sandbox = "allow-same-origin allow-downloads";
     iframe.onload = t.step_func(function () {
         iframe.contentWindow.addEventListener(
             "unload", t.unreached_func("Unexpected navigation."));
@@ -26,6 +26,6 @@
     });
 
     document.body.appendChild(iframe);
-}, "<a download> triggered download in sandbox is allowed by allow-downloads-without-user-activation.");
+}, "<a download> triggered download in sandbox is allowed by allow-downloads.");
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_block_downloads_without_user_activation.sub.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_block_downloads.sub.tentative.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_block_downloads_without_user_activation.sub.tentative.html
rename to third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_block_downloads.sub.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads_without_user_activation.sub.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.html
similarity index 89%
rename from third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads_without_user_activation.sub.tentative.html
rename to third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.html
index 6af49b8d..50e28f650 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads_without_user_activation.sub.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
-<title>Navigation resulted download in sandbox is allowed by allow-downloads-without-user-activation.</title>
+<title>Navigation resulted download in sandbox is allowed by allow-downloads.</title>
 <meta name="timeout" content="long" />
 <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-iframe-sandbox">
 <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-iframe-element">
@@ -15,7 +15,7 @@
     const token = "{{$id:uuid()}}";
     var iframe = document.createElement("iframe");
     iframe.srcdoc = "<a>Download</a>";
-    iframe.sandbox = "allow-same-origin allow-downloads-without-user-activation";
+    iframe.sandbox = "allow-same-origin allow-downloads";
     iframe.onload = t.step_func(function () {
         iframe.contentWindow.addEventListener(
             "unload", t.unreached_func("Unexpected navigation."));
@@ -29,6 +29,6 @@
     });
 
     document.body.appendChild(iframe);
-}, "Navigation resulted download in sandbox is allowed by allow-downloads-without-user-activation.");
+}, "Navigation resulted download in sandbox is allowed by allow-downloads.");
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_block_downloads_without_user_activation.sub.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_block_downloads.sub.tentative.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_block_downloads_without_user_activation.sub.tentative.html
rename to third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_block_downloads.sub.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-summary-element/anchor-with-inline-element.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-summary-element/anchor-with-inline-element.html
new file mode 100644
index 0000000..ab20002
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-summary-element/anchor-with-inline-element.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>summary element: clicking on anchor containing inline element</title>
+<link rel="author" title="Yu Han" href="mailto:yuzhehan@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/C/#the-summary-element">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-a-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<details id="details_i">
+  <summary>Anchor text is wrapped with &lt;i&gt; tag <a href="#with_i_tag"><i id="with_i">permalink</i></a></summary>
+  <p>asdf</p>
+</details>
+
+<details id="details_span">
+  <summary>This one uses &lt;span&gt;. <a href="#with_span_tag"><span id="with_span">permalink</span></a></summary>
+  <p>asdf</p>
+</details>
+
+<details id="details_svg">
+  <summary>
+    <svg style="width: 100px;" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
+      <a href="#inside_svg_w_circle">
+        <circle id="svg_circle" cx="50" cy="40" r="35"/>
+      </a>
+      <a href="#inside_svg_w_text">
+        <text id="svg_text" x="50" y="90" text-anchor="middle">
+          &lt;circle&gt;
+        </text>
+      </a>
+    </svg>
+  </summary>
+  <p>asdf</p>
+</details>
+
+<script>
+function testClickingOnInlineElement(detailsId, targetId, expected, testName) {
+  const details = document.getElementById(detailsId);
+  const target = document.getElementById(targetId);
+  const test = async_test(testName);
+
+  const promise = new Promise((resolve, reject) => {
+    window.onhashchange = test.step_func_done(() => {
+      assert_false(details.open);
+      assert_true(location.hash === expected);
+      resolve();
+    });
+  });
+
+  if (target.click) {
+    target.click();
+  }
+  else {
+    // svg element don't have click method
+    target.dispatchEvent(new MouseEvent('click', {
+      view: window,
+      bubbles: true,
+      cancelable: true
+    }));
+  }
+  return promise;
+};
+
+async function testAll() {
+  try {
+    await testClickingOnInlineElement("details_i", "with_i", "#with_i_tag", "Expected <a> containing <i> to navigate");
+    await testClickingOnInlineElement("details_span", "with_span", "#with_span_tag", "Expected <a> containing <span> to navigate");
+    await testClickingOnInlineElement("details_svg", "svg_circle", "#inside_svg_w_circle", "Expected <a>, inside svg, containing <circle> to navigate");
+    await testClickingOnInlineElement("details_svg", "svg_text", "#inside_svg_w_text", "Expected <a>, inside svg, containing <text> to navigate");
+  } catch (exception) {
+    assert_unreached("should NOT-THROW exception");
+  }
+};
+
+var allTests = async_test("Clicking on anchor with embedded inline element should navigate instead of opening details");
+testAll().then(()=>{ allTests.done(); });
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/direction/direction-009-ref.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/tokens/ms-001-ref.html
similarity index 75%
rename from third_party/blink/web_tests/external/wpt/mathml/presentation-markup/direction/direction-009-ref.html
rename to third_party/blink/web_tests/external/wpt/mathml/presentation-markup/tokens/ms-001-ref.html
index 8b80b7e..bbd42a93 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/direction/direction-009-ref.html
+++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/tokens/ms-001-ref.html
@@ -2,7 +2,7 @@
 <html>
   <head>
     <meta charset="utf-8"/>
-    <title>RTL ms lquote="X" rquote="p"</title>
+    <title>ms legacy lquote and rquote attributes (reference)</title>
     <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
     <style>
       math {
@@ -14,7 +14,7 @@
 
     <p>
       <math>
-        <ms lquote="p" rquote="X">É</ms>
+        <ms>X</ms>
       </math>
     </p>
 
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/direction/direction-009.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/tokens/ms-001.html
similarity index 69%
rename from third_party/blink/web_tests/external/wpt/mathml/presentation-markup/direction/direction-009.html
rename to third_party/blink/web_tests/external/wpt/mathml/presentation-markup/tokens/ms-001.html
index c0ca31d..b0b03f2 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/direction/direction-009.html
+++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/tokens/ms-001.html
@@ -2,12 +2,12 @@
 <html>
   <head>
     <meta charset="utf-8"/>
-    <title>RTL ms lquote="X" rquote="p"</title>
+    <title>ms legacy lquote and rquote attributes</title>
     <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#attributes-common-to-html-and-mathml-elements">
     <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#css-styling">
     <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#string-literal-ms">
-    <meta name="assert" content="Verify that a RTL ms element renders the same as if its left and right quotes were switched.">
-    <link rel="match" href="direction-009-ref.html">
+    <meta name="assert" content="Verify that legacy lquote and rquote attributes are ignored on the ms element.">
+    <link rel="match" href="ms-001-ref.html">
     <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
     <style>
       math {
@@ -18,13 +18,13 @@
   <body>
 
     <p>
-      <math dir="rtl">
-        <ms lquote="X" rquote="p">É</ms>
+      <math>
+        <ms lquote="É" rquote="p">X</ms>
       </math>
     </p>
 
    <script src="/mathml/support/feature-detection.js"></script>
-   <script>MathMLFeatureDetection.ensure_for_match_reftest("has_dir");</script>
+   <script>MathMLFeatureDetection.ensure_for_match_reftest("has_ms");</script>
 
   </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/idlharness.window.js b/third_party/blink/web_tests/external/wpt/trusted-types/idlharness.tentative.window.js
similarity index 96%
rename from third_party/blink/web_tests/external/wpt/trusted-types/idlharness.window.js
rename to third_party/blink/web_tests/external/wpt/trusted-types/idlharness.tentative.window.js
index 7be9615..5a854a1 100644
--- a/third_party/blink/web_tests/external/wpt/trusted-types/idlharness.window.js
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/idlharness.tentative.window.js
@@ -12,6 +12,5 @@
         TrustedScript: ['window.trustedTypes.createPolicy("SomeName2", { createScript: s => s }).createScript("A string")'],
         TrustedScriptURL: ['window.trustedTypes.createPolicy("SomeName3", { createScriptURL: s => s }).createScriptURL("A string")'],
       });
-    },
-    'Trusted Types'
+    }
 );
diff --git a/third_party/blink/web_tests/fast/dom/HTMLIFrameElement/sandbox-feature-detection.html b/third_party/blink/web_tests/fast/dom/HTMLIFrameElement/sandbox-feature-detection.html
index 61e3359..55239d9 100644
--- a/third_party/blink/web_tests/fast/dom/HTMLIFrameElement/sandbox-feature-detection.html
+++ b/third_party/blink/web_tests/fast/dom/HTMLIFrameElement/sandbox-feature-detection.html
@@ -27,7 +27,7 @@
         assert_true(iframe.sandbox.supports("allow-scripts"));
         assert_true(iframe.sandbox.supports("allow-top-navigation"));
         assert_true(iframe.sandbox.supports("allow-top-navigation-by-user-activation"));
-        assert_true(iframe.sandbox.supports("allow-downloads-without-user-activation"));
+        assert_true(iframe.sandbox.supports("allow-downloads"));
         // Test that "supports()" does a case-insensitive comparison
         assert_true(iframe.sandbox.supports("ALLOW-FORMS"));
         assert_true(iframe.sandbox.supports("Allow-Forms"));
diff --git a/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt b/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt
index 91bfdbf..4cc065f 100644
--- a/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt
+++ b/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt
@@ -20,7 +20,7 @@
 document-access
 document-domain
 document-write
-downloads-without-user-activation
+downloads
 encrypted-media
 execution-while-not-rendered
 execution-while-out-of-viewport
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index ea23018a..a3147a1 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -20007,6 +20007,7 @@
 </action>
 
 <action name="Signin_SigninNewAccountPreDice_FromAvatarBubbleSignin">
+  <obsolete>Removed M80</obsolete>
   <owner>bsazonov@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
   <description>
@@ -20017,6 +20018,7 @@
 </action>
 
 <action name="Signin_SigninNewAccountPreDice_FromBookmarkBubble">
+  <obsolete>Removed M80</obsolete>
   <owner>bsazonov@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
   <description>
@@ -20027,6 +20029,7 @@
 </action>
 
 <action name="Signin_SigninNewAccountPreDice_FromBookmarkManager">
+  <obsolete>Removed M80</obsolete>
   <owner>bsazonov@chromium.org</owner>
   <owner>jlebel@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
@@ -20038,6 +20041,7 @@
 </action>
 
 <action name="Signin_SigninNewAccountPreDice_FromExtensionInstallBubble">
+  <obsolete>Removed M80</obsolete>
   <owner>bsazonov@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
   <description>
@@ -20048,6 +20052,7 @@
 </action>
 
 <action name="Signin_SigninNewAccountPreDice_FromManageCardsBubble">
+  <obsolete>Removed M80</obsolete>
   <owner>bsazonov@chromium.org</owner>
   <owner>jsaul@chromium.org</owner>
   <owner>manasverma@google.com</owner>
@@ -20061,6 +20066,7 @@
 </action>
 
 <action name="Signin_SigninNewAccountPreDice_FromNTPContentSuggestions">
+  <obsolete>Removed M80</obsolete>
   <owner>bsazonov@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
   <description>
@@ -20071,6 +20077,7 @@
 </action>
 
 <action name="Signin_SigninNewAccountPreDice_FromPasswordBubble">
+  <obsolete>Removed M80</obsolete>
   <owner>bsazonov@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
   <description>
@@ -20081,6 +20088,7 @@
 </action>
 
 <action name="Signin_SigninNewAccountPreDice_FromRecentTabs">
+  <obsolete>Removed M80</obsolete>
   <owner>bsazonov@chromium.org</owner>
   <owner>jlebel@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
@@ -20092,6 +20100,7 @@
 </action>
 
 <action name="Signin_SigninNewAccountPreDice_FromSaveCardBubble">
+  <obsolete>Removed M80</obsolete>
   <owner>bsazonov@chromium.org</owner>
   <owner>jsaul@chromium.org</owner>
   <owner>manasverma@google.com</owner>
@@ -20105,6 +20114,7 @@
 </action>
 
 <action name="Signin_SigninNewAccountPreDice_FromSettings">
+  <obsolete>Removed M80</obsolete>
   <owner>bsazonov@chromium.org</owner>
   <owner>jlebel@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
@@ -20116,6 +20126,7 @@
 </action>
 
 <action name="Signin_SigninNewAccountPreDice_FromTabSwitcher">
+  <obsolete>Removed M80</obsolete>
   <owner>bsazonov@chromium.org</owner>
   <owner>jlebel@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 115a312..82530c8 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -9447,7 +9447,7 @@
   <int value="-603" label="FTP_TRANSFER_ABORTED"/>
   <int value="-602" label="FTP_SERVICE_UNAVAILABLE"/>
   <int value="-601" label="FTP_FAILED"/>
-  <int value="-505" label="INVALID_BUNDLED_EXCHANGES"/>
+  <int value="-505" label="INVALID_WEB_BUNDLE"/>
   <int value="-504" label="INVALID_SIGNED_EXCHANGE"/>
   <int value="-503" label="ADD_USER_CERT_FAILED"/>
   <int value="-502" label="NO_PRIVATE_KEY_FOR_CERT"/>
@@ -25292,7 +25292,7 @@
   <int value="2837" label="SandboxBackForwardAffectsFramesOutsideSubtree"/>
   <int value="2838" label="DownloadPrePolicyCheck"/>
   <int value="2839" label="DownloadPostPolicyCheck"/>
-  <int value="2840" label="DownloadInSandboxWithoutUserGesture"/>
+  <int value="2840" label="OBSOLETE_DownloadInSandboxWithoutUserGesture"/>
   <int value="2841" label="ReadableStreamGetReader"/>
   <int value="2842" label="ReadableStreamPipeThrough"/>
   <int value="2843" label="ReadableStreamPipeTo"/>
@@ -25633,7 +25633,7 @@
   <int value="46" label="UnoptimizedLosslessImages"/>
   <int value="47" label="UnoptimizedLosslessImagesStrict"/>
   <int value="48" label="LoadingFrameDefaultEager"/>
-  <int value="49" label="DownloadsWithoutUserActivation"/>
+  <int value="49" label="Downloads"/>
   <int value="50" label="ExecutionWhileOutOfViewport"/>
   <int value="51" label="ExecutionWhileNotRendered"/>
   <int value="52" label="FocusWithoutUserActivation"/>
@@ -43126,7 +43126,7 @@
   <int value="502" label="NO_PRIVATE_KEY_FOR_CERT"/>
   <int value="503" label="ADD_USER_CERT_FAILED"/>
   <int value="504" label="INVALID_SIGNED_EXCHANGE"/>
-  <int value="505" label="INVALID_BUNDLED_EXCHANGES"/>
+  <int value="505" label="INVALID_WEB_BUNDLE"/>
   <int value="601" label="FTP_FAILED"/>
   <int value="602" label="FTP_SERVICE_UNAVAILABLE"/>
   <int value="603" label="FTP_TRANSFER_ABORTED"/>
@@ -61679,6 +61679,12 @@
   <int value="3" label="CLIENT_NO_CHANNEL_ID_SERVICE"/>
 </enum>
 
+<enum name="TokenStateOnRegistrationRequest">
+  <int value="0" label="Token was empty"/>
+  <int value="1" label="Token stayed unchanged"/>
+  <int value="2" label="Token has changed"/>
+</enum>
+
 <enum name="TouchActions">
   <int value="0" label="NONE"/>
   <int value="1" label="PAN_LEFT"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 62a6e3b..af18065 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -28642,7 +28642,7 @@
 </histogram>
 
 <histogram name="Cryptohome.ParallelTasks" units="count"
-    expires_after="2020-01-01">
+    expires_after="2021-01-01">
   <owner>zuan@chromium.org</owner>
   <owner>cros-hwsec+uma@chromium.org</owner>
   <summary>
@@ -50798,6 +50798,19 @@
   </summary>
 </histogram>
 
+<histogram name="FCMInvalidations.TokenStateOnRegistrationRequest"
+    enum="TokenStateOnRegistrationRequest" expires_after="never">
+<!-- expires-never: For monitoring FCM based invalidations. -->
+
+  <owner>melandory@chromium.org</owner>
+  <owner>treib@chromium.org</owner>
+  <summary>
+    Records the outcome of instance ID token requests (i.e. whether the token
+    changed). Such requests are made when invalidations are first enabled (e.g.
+    on sign-in), and then periodically every 24 hours.
+  </summary>
+</histogram>
+
 <histogram name="FCMInvalidations.UnsubscriptionRequestStatus"
     enum="FCMInvalidationSubscriptionStatus" expires_after="never">
 <!-- expires-never: For monitoring FCM based invalidations. -->
@@ -93260,8 +93273,9 @@
 </histogram>
 
 <histogram name="NewTabPage.RecentTabsPage.TimeVisibleAndroid" units="ms"
-    expires_after="M77">
+    expires_after="M82">
   <owner>pkotwicz@chromium.org</owner>
+  <owner>treib@chromium.org</owner>
   <summary>
     Records the amount of time that the &quot;Recent Tabs&quot; page is visible
     and Chrome is in the foreground on Android. The metric is recorded whenever
@@ -139280,6 +139294,9 @@
 
 <histogram base="true" name="Signin.DiceMigrationNotReady.Reason"
     enum="AccountReconcilorInconsistencyReason" expires_after="2020-04-19">
+  <obsolete>
+    Deprecated M80. Dice migration is complete.
+  </obsolete>
   <owner>msalama@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
   <summary>
@@ -169607,6 +169624,9 @@
 </histogram_suffixes>
 
 <histogram_suffixes name="AccountReconcilorExecution" separator=".">
+  <obsolete>
+    Deprecated M80. Only affects one histogram, which is deprecated.
+  </obsolete>
   <owner>msalama@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
   <suffix name="FirstExecution" label="The first Reconcilor execution"/>
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index 86cc933..aa1120db 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -452,6 +452,7 @@
 crbug.com/1002640 [ android-pixel-2 ] v8.browsing_mobile/browse:chrome:newtab [ Skip ]
 crbug.com/1002665 [ android-pixel-2 ] v8.browsing_mobile/browse:chrome:omnibox [ Skip ]
 crbug.com/1014655 [ android-webview ] v8.browsing_mobile/browse:social:instagram:2019 [ Skip ]
+crbug.com/1028072 [ android ] v8.browsing_mobile/browse:media:youtube:2019 [ Skip ]
 
 # Benchmark: v8.browsing_mobile-future
 # Disabled v8.browsing_mobile-future for capacity reasons while we update
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn
index 7e45231..8dcb06a 100644
--- a/ui/android/BUILD.gn
+++ b/ui/android/BUILD.gn
@@ -387,6 +387,7 @@
     "junit/src/org/chromium/ui/base/EventOffsetHandlerTest.java",
     "junit/src/org/chromium/ui/base/LocalizationUtilsTest.java",
     "junit/src/org/chromium/ui/base/SelectFileDialogTest.java",
+    "junit/src/org/chromium/ui/drawable/AnimationLooperTest.java",
     "junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java",
     "junit/src/org/chromium/ui/modaldialog/ModalDialogManagerTest.java",
     "junit/src/org/chromium/ui/modelutil/LazyConstructionPropertyMcpTest.java",
diff --git a/ui/android/java/src/org/chromium/ui/drawable/AnimationLooper.java b/ui/android/java/src/org/chromium/ui/drawable/AnimationLooper.java
index 964923f3..8472f6f 100644
--- a/ui/android/java/src/org/chromium/ui/drawable/AnimationLooper.java
+++ b/ui/android/java/src/org/chromium/ui/drawable/AnimationLooper.java
@@ -4,120 +4,83 @@
 
 package org.chromium.ui.drawable;
 
-import android.annotation.TargetApi;
-import android.graphics.drawable.Animatable2;
+import android.animation.ValueAnimator;
+import android.graphics.drawable.Animatable;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
+import android.os.Handler;
+import android.provider.Settings;
 import android.support.graphics.drawable.Animatable2Compat;
+import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
 
-import org.chromium.base.ThreadUtils;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.base.ContextUtils;
 
 /**
- * Encapsulates the logic to loop animated drawables from both Android Framework (using Animatable2)
- * and Support Library (using Animatable2Compat). Should be instantiated by {@link #create}. The
- * animation should be started and stopped using {@link #start()} and {@link #stop()}.
+ * Encapsulates the logic to loop animated drawables from both Android Framework.
+ * The animation should be started and stopped using {@link #start()} and {@link #stop()}.
  */
-public interface AnimationLooper {
-    /** Starts the animation of the associated drawable. */
-    void start();
+public class AnimationLooper {
+    private static @Nullable Boolean sAreAnimatorsEnabledForTests;
 
-    /** Stops the animation of the associated drawable. */
-    void stop();
+    private final Handler mHandler;
+    private final Animatable mAnimatable;
+    private final Animatable2Compat.AnimationCallback mAnimationCallback;
+
+    private boolean mIsRunning;
 
     /**
-     * Instantiates proper implementation of AnimationLooper for the drawable.
-     * @param drawable The drawable to be animated. Created AnimationLooper instance will be
-     *         associated with this drawable. The drawable should implement either
-     *         {@link Animatable2} or {@link Animatable2Compat}.
-     * @return The new AnimationLooper.
+     * @param drawable The drawable should be drawable and animatable at the same time.
      */
-    static AnimationLooper create(Drawable drawable) {
-        // Animatable2 was added in API level 23 (Android M).
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
-            return new Animatable2CompatImpl((Animatable2Compat) drawable);
-        }
-        if (drawable instanceof Animatable2Compat) {
-            return new Animatable2CompatImpl((Animatable2Compat) drawable);
-        }
-        return new Animatable2Impl((Animatable2) drawable);
+    public AnimationLooper(Drawable drawable) {
+        mHandler = new Handler();
+        mAnimatable = (Animatable) drawable;
+        mAnimationCallback = new Animatable2Compat.AnimationCallback() {
+            @Override
+            public void onAnimationEnd(Drawable drawable) {
+                mHandler.post(mAnimatable::start);
+            }
+        };
     }
 
-    /** Used with drawables that implement {@link Animatable2Compat}. */
-    class Animatable2CompatImpl implements AnimationLooper {
-        private final Animatable2Compat mAnimatable;
-        private final Animatable2Compat.AnimationCallback mAnimationCallback;
-        private boolean mRunning;
-
-        Animatable2CompatImpl(Animatable2Compat animatable) {
-            mAnimatable = animatable;
-            mAnimationCallback = new Animatable2Compat.AnimationCallback() {
-                @Override
-                public void onAnimationEnd(Drawable drawable) {
-                    restartAnimation(animatable);
-                }
-            };
-        }
-
-        @Override
-        public void start() {
-            assert !mRunning : "The animation is already running!";
-            mRunning = true;
-            mAnimatable.registerAnimationCallback(mAnimationCallback);
+    /** Starts the animation of the associated drawable. */
+    public void start() {
+        if (areAnimatorsEnabled()) {
+            assert !mIsRunning : "Animation is already running!";
+            AnimatedVectorDrawableCompat.registerAnimationCallback(
+                    (Drawable) mAnimatable, mAnimationCallback);
             mAnimatable.start();
-        }
-
-        @Override
-        public void stop() {
-            assert mRunning : "The animation isn't running!";
-            mRunning = false;
-            mAnimatable.unregisterAnimationCallback(mAnimationCallback);
-            mAnimatable.stop();
-        }
-
-        private void restartAnimation(Animatable2Compat animatable) {
-            ThreadUtils.postOnUiThread(() -> {
-                if (mRunning) animatable.start();
-            });
+            mIsRunning = true;
         }
     }
 
-    /** Used with drawables that implement {@link Animatable2}. */
-    @TargetApi(Build.VERSION_CODES.M)
-    class Animatable2Impl implements AnimationLooper {
-        private final Animatable2 mAnimatable;
-        private final Animatable2.AnimationCallback mAnimationCallback;
-        private boolean mRunning;
-
-        Animatable2Impl(Animatable2 animatable) {
-            mAnimatable = animatable;
-            mAnimationCallback = new Animatable2.AnimationCallback() {
-                @Override
-                public void onAnimationEnd(Drawable drawable) {
-                    restartAnimation(animatable);
-                }
-            };
-        }
-
-        @Override
-        public void start() {
-            assert !mRunning : "The animation is already running!";
-            mRunning = true;
-            mAnimatable.registerAnimationCallback(mAnimationCallback);
-            mAnimatable.start();
-        }
-
-        @Override
-        public void stop() {
-            assert mRunning : "The animation isn't running!";
-            mRunning = false;
-            mAnimatable.unregisterAnimationCallback(mAnimationCallback);
+    /** Stops the animation of the associated drawable. */
+    public void stop() {
+        if (mIsRunning) {
+            AnimatedVectorDrawableCompat.unregisterAnimationCallback(
+                    (Drawable) mAnimatable, mAnimationCallback);
             mAnimatable.stop();
+            mIsRunning = false;
         }
+    }
 
-        private void restartAnimation(Animatable2 animatable) {
-            ThreadUtils.postOnUiThread(() -> {
-                if (mRunning) animatable.start();
-            });
+    private static boolean areAnimatorsEnabled() {
+        if (sAreAnimatorsEnabledForTests != null) return sAreAnimatorsEnabledForTests;
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            return ValueAnimator.areAnimatorsEnabled();
+        } else {
+            return Settings.Global.getFloat(
+                           ContextUtils.getApplicationContext().getContentResolver(),
+                           Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f)
+                    != 0.0f;
         }
     }
+
+    @VisibleForTesting
+    static void setAreAnimatorsEnabledForTests(@Nullable Boolean areAnimatorsEnabled) {
+        sAreAnimatorsEnabledForTests = areAnimatorsEnabled;
+    }
 }
diff --git a/ui/android/junit/src/org/chromium/ui/drawable/AnimationLooperTest.java b/ui/android/junit/src/org/chromium/ui/drawable/AnimationLooperTest.java
new file mode 100644
index 0000000..775a569
--- /dev/null
+++ b/ui/android/junit/src/org/chromium/ui/drawable/AnimationLooperTest.java
@@ -0,0 +1,81 @@
+// Copyright 2019 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.ui.drawable;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.graphics.drawable.Animatable2;
+import android.graphics.drawable.AnimatedVectorDrawable;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+/**
+ * Test AnimationLooper class.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+public class AnimationLooperTest {
+    @Mock
+    private AnimatedVectorDrawable mAnimatableMock;
+
+    private AnimationLooper mAnimationLooper;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mAnimationLooper = new AnimationLooper(mAnimatableMock);
+    }
+
+    @After
+    public void tearDown() {
+        AnimationLooper.setAreAnimatorsEnabledForTests(null);
+    }
+
+    @Test
+    public void testAnimationNeverInvokedWhenAnimatorsDisabledAtStart() {
+        AnimationLooper.setAreAnimatorsEnabledForTests(false);
+        mAnimationLooper.start();
+        verify(mAnimatableMock, never()).start();
+
+        AnimationLooper.setAreAnimatorsEnabledForTests(true);
+        mAnimationLooper.stop();
+        verify(mAnimatableMock, never()).stop();
+    }
+
+    @Test
+    public void testAnimationLoopsWhenAnimatorsEnabled() {
+        final ArgumentCaptor<Animatable2.AnimationCallback> captor =
+                ArgumentCaptor.forClass(Animatable2.AnimationCallback.class);
+        AnimationLooper.setAreAnimatorsEnabledForTests(true);
+
+        mAnimationLooper.start();
+        verify(mAnimatableMock).start();
+        verify(mAnimatableMock).registerAnimationCallback(captor.capture());
+        final Animatable2.AnimationCallback callback = captor.getValue();
+
+        callback.onAnimationEnd(mAnimatableMock);
+        verify(mAnimatableMock, times(2)).start();
+
+        mAnimationLooper.stop();
+        verify(mAnimatableMock).unregisterAnimationCallback(callback);
+        verify(mAnimatableMock).stop();
+    }
+
+    @Test(expected = AssertionError.class)
+    public void testAnimationThrowsErrorWhenStartedTwiceConsecutively() {
+        AnimationLooper.setAreAnimatorsEnabledForTests(true);
+        mAnimationLooper.start();
+        mAnimationLooper.start();
+    }
+}
diff --git a/ui/aura/window_tree_host_platform.cc b/ui/aura/window_tree_host_platform.cc
index 40f337b..3e0c642 100644
--- a/ui/aura/window_tree_host_platform.cc
+++ b/ui/aura/window_tree_host_platform.cc
@@ -23,7 +23,7 @@
 #include "ui/events/event.h"
 #include "ui/events/keyboard_hook.h"
 #include "ui/events/keycodes/dom/dom_code.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
 #if defined(USE_OZONE)
@@ -86,7 +86,7 @@
 }
 
 void WindowTreeHostPlatform::SetPlatformWindow(
-    std::unique_ptr<ui::PlatformWindowBase> window) {
+    std::unique_ptr<ui::PlatformWindow> window) {
   platform_window_ = std::move(window);
 }
 
diff --git a/ui/aura/window_tree_host_platform.h b/ui/aura/window_tree_host_platform.h
index ced5708..56fbb0f 100644
--- a/ui/aura/window_tree_host_platform.h
+++ b/ui/aura/window_tree_host_platform.h
@@ -18,7 +18,7 @@
 
 namespace ui {
 enum class DomCode;
-class PlatformWindowBase;
+class PlatformWindow;
 class KeyboardHook;
 struct PlatformWindowInitProperties;
 }  // namespace ui
@@ -62,9 +62,9 @@
   // installs it at as the PlatformWindow for this WindowTreeHostPlatform.
   void CreateAndSetPlatformWindow(ui::PlatformWindowInitProperties properties);
 
-  void SetPlatformWindow(std::unique_ptr<ui::PlatformWindowBase> window);
-  ui::PlatformWindowBase* platform_window() { return platform_window_.get(); }
-  const ui::PlatformWindowBase* platform_window() const {
+  void SetPlatformWindow(std::unique_ptr<ui::PlatformWindow> window);
+  ui::PlatformWindow* platform_window() { return platform_window_.get(); }
+  const ui::PlatformWindow* platform_window() const {
     return platform_window_.get();
   }
 
@@ -90,7 +90,7 @@
 
  private:
   gfx::AcceleratedWidget widget_;
-  std::unique_ptr<ui::PlatformWindowBase> platform_window_;
+  std::unique_ptr<ui::PlatformWindow> platform_window_;
   gfx::NativeCursor current_cursor_;
   gfx::Rect bounds_in_pixels_;
 
diff --git a/ui/aura/window_tree_host_platform_unittest.cc b/ui/aura/window_tree_host_platform_unittest.cc
index 677e569..eda14e2 100644
--- a/ui/aura/window_tree_host_platform_unittest.cc
+++ b/ui/aura/window_tree_host_platform_unittest.cc
@@ -22,7 +22,7 @@
     CreateCompositor();
   }
 
-  ui::PlatformWindowBase* platform_window() {
+  ui::PlatformWindow* platform_window() {
     return WindowTreeHostPlatform::platform_window();
   }
 
@@ -37,7 +37,7 @@
 class TestWindowTreeHostObserver : public aura::WindowTreeHostObserver {
  public:
   TestWindowTreeHostObserver(WindowTreeHostPlatform* host,
-                             ui::PlatformWindowBase* platform_window)
+                             ui::PlatformWindow* platform_window)
       : host_(host), platform_window_(platform_window) {
     host_->AddObserver(this);
   }
@@ -70,7 +70,7 @@
 
  private:
   WindowTreeHostPlatform* host_;
-  ui::PlatformWindowBase* platform_window_;
+  ui::PlatformWindow* platform_window_;
   bool should_change_bounds_in_on_resized_ = true;
   int on_host_will_process_bounds_change_count_ = 0;
   int on_host_did_process_bounds_change_count_ = 0;
diff --git a/ui/base/idle/BUILD.gn b/ui/base/idle/BUILD.gn
index 530d02a..e87d38c2 100644
--- a/ui/base/idle/BUILD.gn
+++ b/ui/base/idle/BUILD.gn
@@ -8,6 +8,12 @@
   import("//build/config/mac/rules.gni")
 }
 
+# Reset sources_assignment_filter for the BUILD.gn file to prevent
+# regression during the migration of Chromium away from the feature.
+# See build/no_sources_assignment_filter.md for more information.
+# TODO(crbug.com/1018739): remove this when migration is done.
+set_sources_assignment_filter([])
+
 component("idle") {
   output_name = "ui_base_idle"
 
@@ -32,13 +38,22 @@
   sources = [
     "idle.cc",
     "idle.h",
-    "idle_chromeos.cc",
     "idle_internal.cc",
     "idle_internal.h",
-    "idle_mac.mm",
-    "idle_win.cc",
   ]
 
+  if (is_chromeos) {
+    sources += [ "idle_chromeos.cc" ]
+  }
+
+  if (is_mac) {
+    sources += [ "idle_mac.mm" ]
+  }
+
+  if (is_win) {
+    sources += [ "idle_win.cc" ]
+  }
+
   if (is_fuchsia) {
     sources += [ "idle_fuchsia.cc" ]
   }
diff --git a/ui/chromeos/ime/candidate_view.cc b/ui/chromeos/ime/candidate_view.cc
index 807ffb8..d635397b 100644
--- a/ui/chromeos/ime/candidate_view.cc
+++ b/ui/chromeos/ime/candidate_view.cc
@@ -123,8 +123,8 @@
   // Change the font size and color.
   annotation_label->SetFontList(
       annotation_label->font_list().DeriveWithSizeDelta(kFontSizeDelta));
-  annotation_label->SetEnabledColor(theme.GetSystemColor(
-      ui::NativeTheme::kColorId_LabelDisabledColor));
+  annotation_label->SetEnabledColor(
+      theme.GetSystemColor(ui::NativeTheme::kColorId_LabelSecondaryColor));
   annotation_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   annotation_label->SetElideBehavior(gfx::NO_ELIDE);
 
diff --git a/ui/color/color_id.h b/ui/color/color_id.h
index d3502ca7..29ecf72 100644
--- a/ui/color/color_id.h
+++ b/ui/color/color_id.h
@@ -7,6 +7,7 @@
 
 #include "build/build_config.h"
 
+// clang-format off
 #define CROSS_PLATFORM_COLOR_IDS \
   /* Core color concepts */ \
   E(kColorAccent, kUiColorsStart), \
@@ -42,6 +43,7 @@
   E(kColorIcon), \
   E(kColorLabelDisabledForeground), \
   E(kColorLabelForeground), \
+  E(kColorLabelSecondaryForeground), \
   E(kColorLabelSelectionBackground), \
   E(kColorLabelSelectionForeground), \
   E(kColorLinkDisabledForeground), \
@@ -130,6 +132,7 @@
 #else
 #define COLOR_IDS CROSS_PLATFORM_COLOR_IDS
 #endif
+// clang-format on
 
 namespace ui {
 
diff --git a/ui/color/ui_color_mixer.cc b/ui/color/ui_color_mixer.cc
index 4a0490f..ab7ea31 100644
--- a/ui/color/ui_color_mixer.cc
+++ b/ui/color/ui_color_mixer.cc
@@ -37,6 +37,7 @@
   mixer[kColorIcon] = {kColorSecondaryForeground};
   mixer[kColorLabelDisabledForeground] = {kColorDisabledForeground};
   mixer[kColorLabelForeground] = {kColorPrimaryForeground};
+  mixer[kColorLabelSecondaryForeground] = {kColorSecondaryForeground};
   mixer[kColorLabelSelectionBackground] = {kColorTextSelectionBackground};
   mixer[kColorLabelSelectionForeground] = {kColorLabelForeground};
   mixer[kColorLinkDisabledForeground] = {kColorDisabledForeground};
diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn
index c88c59d7..eb6e55c1 100644
--- a/ui/compositor/BUILD.gn
+++ b/ui/compositor/BUILD.gn
@@ -6,6 +6,12 @@
 import("//build/config/ui.gni")
 import("//testing/test.gni")
 
+# Reset sources_assignment_filter for the BUILD.gn file to prevent
+# regression during the migration of Chromium away from the feature.
+# See build/no_sources_assignment_filter.md for more information.
+# TODO(crbug.com/1018739): remove this when migration is done.
+set_sources_assignment_filter([])
+
 jumbo_component("compositor") {
   sources = [
     "callback_layer_animation_observer.cc",
@@ -63,8 +69,6 @@
     "paint_recorder.cc",
     "paint_recorder.h",
     "property_change_reason.h",
-    "recyclable_compositor_mac.cc",
-    "recyclable_compositor_mac.h",
     "reflector.cc",
     "reflector.h",
     "scoped_animation_duration_scale_mode.cc",
@@ -77,6 +81,13 @@
     "transform_recorder.h",
   ]
 
+  if (is_mac) {
+    sources += [
+      "recyclable_compositor_mac.cc",
+      "recyclable_compositor_mac.h",
+    ]
+  }
+
   defines = [ "COMPOSITOR_IMPLEMENTATION" ]
 
   public_deps = [
@@ -130,9 +141,6 @@
     "test/multi_layer_animator_test_controller.h",
     "test/multi_layer_animator_test_controller_delegate.h",
     "test/test_compositor_host.h",
-    "test/test_compositor_host_android.cc",
-    "test/test_compositor_host_mac.mm",
-    "test/test_compositor_host_win.cc",
     "test/test_context_factories.cc",
     "test/test_context_factories.h",
     "test/test_layer_animation_delegate.cc",
@@ -147,6 +155,18 @@
     "test/test_utils.h",
   ]
 
+  if (is_android) {
+    sources += [ "test/test_compositor_host_android.cc" ]
+  }
+
+  if (is_mac) {
+    sources += [ "test/test_compositor_host_mac.mm" ]
+  }
+
+  if (is_win) {
+    sources += [ "test/test_compositor_host_win.cc" ]
+  }
+
   public_deps = [
     ":compositor",
   ]
diff --git a/ui/compositor/test/test_compositor_host_ozone.cc b/ui/compositor/test/test_compositor_host_ozone.cc
index 66f8b74..7dbbe5c 100644
--- a/ui/compositor/test/test_compositor_host_ozone.cc
+++ b/ui/compositor/test/test_compositor_host_ozone.cc
@@ -18,7 +18,7 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/ozone/public/ozone_platform.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
@@ -72,7 +72,7 @@
 
   gfx::Rect bounds_;
   ui::Compositor compositor_;
-  std::unique_ptr<PlatformWindowBase> window_;
+  std::unique_ptr<PlatformWindow> window_;
   StubPlatformWindowDelegate window_delegate_;
   viz::ParentLocalSurfaceIdAllocator allocator_;
 
diff --git a/ui/display/BUILD.gn b/ui/display/BUILD.gn
index ffb7da2..bdabe14 100644
--- a/ui/display/BUILD.gn
+++ b/ui/display/BUILD.gn
@@ -7,6 +7,12 @@
 import("//testing/test.gni")
 import("//ui/display/display.gni")
 
+# Reset sources_assignment_filter for the BUILD.gn file to prevent
+# regression during the migration of Chromium away from the feature.
+# See build/no_sources_assignment_filter.md for more information.
+# TODO(crbug.com/1018739): remove this when migration is done.
+set_sources_assignment_filter([])
+
 jumbo_component("display") {
   sources = [
     "display.cc",
@@ -28,34 +34,49 @@
     "display_observer.h",
     "display_switches.cc",
     "display_switches.h",
-    "ios/screen_ios.mm",
-    "mac/display_link_mac.cc",
-    "mac/display_link_mac.h",
-    "mac/screen_mac.mm",
     "screen.cc",
     "screen.h",
-    "screen_android.cc",
-    "screen_aura.cc",
     "screen_base.cc",
     "screen_base.h",
     "unified_desktop_utils.cc",
     "unified_desktop_utils.h",
-    "win/color_profile_reader.cc",
-    "win/color_profile_reader.h",
-    "win/display_info.cc",
-    "win/display_info.h",
-    "win/dpi.cc",
-    "win/dpi.h",
-    "win/scaling_util.cc",
-    "win/scaling_util.h",
-    "win/screen_win.cc",
-    "win/screen_win.h",
-    "win/screen_win_display.cc",
-    "win/screen_win_display.h",
-    "win/uwp_text_scale_factor.cc",
-    "win/uwp_text_scale_factor.h",
   ]
 
+  if (is_android) {
+    sources += [ "screen_android.cc" ]
+  }
+
+  if (is_mac) {
+    sources += [
+      "mac/display_link_mac.cc",
+      "mac/display_link_mac.h",
+      "mac/screen_mac.mm",
+    ]
+  }
+
+  if (is_win) {
+    sources += [
+      "win/color_profile_reader.cc",
+      "win/color_profile_reader.h",
+      "win/display_info.cc",
+      "win/display_info.h",
+      "win/dpi.cc",
+      "win/dpi.h",
+      "win/scaling_util.cc",
+      "win/scaling_util.h",
+      "win/screen_win.cc",
+      "win/screen_win.h",
+      "win/screen_win_display.cc",
+      "win/screen_win_display.h",
+      "win/uwp_text_scale_factor.cc",
+      "win/uwp_text_scale_factor.h",
+    ]
+  }
+
+  if (is_ios) {
+    sources += [ "ios/screen_ios.mm" ]
+  }
+
   defines = [ "DISPLAY_IMPLEMENTATION" ]
 
   public_deps = [
@@ -77,8 +98,8 @@
     output_name = "ui_display"
   }
 
-  if (!use_aura) {
-    sources -= [ "screen_aura.cc" ]
+  if (use_aura) {
+    sources += [ "screen_aura.cc" ]
   }
 
   if (is_mac) {
@@ -120,10 +141,15 @@
     "test/scoped_screen_override.h",
     "test/test_screen.cc",
     "test/test_screen.h",
-    "win/test/screen_util_win.cc",
-    "win/test/screen_util_win.h",
   ]
 
+  if (is_win) {
+    sources += [
+      "win/test/screen_util_win.cc",
+      "win/test/screen_util_win.h",
+    ]
+  }
+
   if (build_display_configuration) {
     sources += [
       "manager/test/action_logger.cc",
@@ -159,7 +185,6 @@
 # This test covers all testable components in display.
 test("display_unittests") {
   sources = [
-    "display_change_notifier_unittest.cc",
     "display_layout_builder_unittest.cc",
     "display_layout_unittest.cc",
     "display_list_unittest.cc",
@@ -173,10 +198,15 @@
     "unified_desktop_utils_unittests.cc",
     "util/display_util_unittest.cc",
     "util/edid_parser_unittest.cc",
-    "win/scaling_util_unittest.cc",
-    "win/screen_win_unittest.cc",
   ]
 
+  if (is_win) {
+    sources += [
+      "win/scaling_util_unittest.cc",
+      "win/screen_win_unittest.cc",
+    ]
+  }
+
   if (build_display_configuration) {
     sources += [
       "manager/apply_content_protection_task_unittest.cc",
@@ -213,10 +243,10 @@
     "//ui/gfx/geometry",
   ]
 
-  if (is_android) {
+  if (!is_android) {
     # Do not run display_change_notifier_unittest.cc on Android because it
     # does not compile display_observer.cc
-    sources -= [ "display_change_notifier_unittest.cc" ]
+    sources += [ "display_change_notifier_unittest.cc" ]
   }
 
   if (is_chromeos) {
diff --git a/ui/events/devices/BUILD.gn b/ui/events/devices/BUILD.gn
index ec58431..1c76106 100644
--- a/ui/events/devices/BUILD.gn
+++ b/ui/events/devices/BUILD.gn
@@ -9,23 +9,23 @@
   import("//build/config/android/rules.gni")
 }
 
+# Reset sources_assignment_filter for the BUILD.gn file to prevent
+# regression during the migration of Chromium away from the feature.
+# See build/no_sources_assignment_filter.md for more information.
+# TODO(crbug.com/1018739): remove this when migration is done.
+set_sources_assignment_filter([])
+
 jumbo_component("devices") {
   sources = [
     "device_data_manager.cc",
     "device_data_manager.h",
     "device_hotplug_event_observer.h",
-    "device_util_linux.cc",
-    "device_util_linux.h",
     "events_devices_export.h",
     "gamepad_device.cc",
     "gamepad_device.h",
     "input_device.cc",
     "input_device.h",
     "input_device_event_observer.h",
-    "input_device_observer_android.cc",
-    "input_device_observer_android.h",
-    "input_device_observer_win.cc",
-    "input_device_observer_win.h",
     "stylus_state.h",
     "touch_device_transform.cc",
     "touch_device_transform.h",
@@ -33,6 +33,27 @@
     "touchscreen_device.h",
   ]
 
+  if (is_linux) {
+    sources += [
+      "device_util_linux.cc",
+      "device_util_linux.h",
+    ]
+  }
+
+  if (is_android) {
+    sources += [
+      "input_device_observer_android.cc",
+      "input_device_observer_android.h",
+    ]
+  }
+
+  if (is_win) {
+    sources += [
+      "input_device_observer_win.cc",
+      "input_device_observer_win.h",
+    ]
+  }
+
   defines = [ "EVENTS_DEVICES_IMPLEMENTATION" ]
 
   public_deps = [
diff --git a/ui/file_manager/file_manager/foreground/elements/files_quick_view.html b/ui/file_manager/file_manager/foreground/elements/files_quick_view.html
index b1af9ae..7330d37 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_quick_view.html
+++ b/ui/file_manager/file_manager/foreground/elements/files_quick_view.html
@@ -36,7 +36,7 @@
           <div id="innerContentPanel" type$="[[type]]">
             <!-- PDF, Text -->
             <template is="dom-if" if="[[browsable]]">
-              <webview on-loadstart='applyTextCss' class="content text-content" src="[[contentUrl]]"></webview>
+              <webview style="color: transparent; background: transparent;" on-contentload='applyTextCss' class="content text-content" src="[[contentUrl]]"></webview>
             </template>
             <!-- document/HTML -->
             <template is="dom-if" if="[[isHtml_(type, subtype)]]">
diff --git a/ui/file_manager/file_manager/foreground/elements/files_quick_view.js b/ui/file_manager/file_manager/foreground/elements/files_quick_view.js
index 8bbb2f32..593c69584 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_quick_view.js
+++ b/ui/file_manager/file_manager/foreground/elements/files_quick_view.js
@@ -50,9 +50,15 @@
    * @param {!Event} e
    */
   applyTextCss: function(e) {
+    // Don't override the Chrome PDF viewer's CSS: crbug.com/1001034.
+    if (this.subtype === 'PDF') {
+      return;
+    }
+
     const webview = /** @type {WebView} */ (e.target);
-    webview.insertCSS(
-        {'file': 'foreground/elements/files_safe_text_webview_content.css'});
+    webview.insertCSS({
+      'file': 'foreground/elements/files_safe_text_webview_content.css',
+    });
   },
 
   // Clears fields.
diff --git a/ui/file_manager/file_manager/foreground/images/volumes/plugin_vm.svg b/ui/file_manager/file_manager/foreground/images/volumes/plugin_vm.svg
index 7cdd3608..eed6c31 100644
--- a/ui/file_manager/file_manager/foreground/images/volumes/plugin_vm.svg
+++ b/ui/file_manager/file_manager/foreground/images/volumes/plugin_vm.svg
@@ -1,3 +1,3 @@
-<svg xmlns="http://www.w3.org/2000/svg" fill="rgb(90,90,90)">
-  <path d="M7 12v4H4V4a1 1 0 0 1 1-1h8a3 3 0 0 1 3 3v3a3 3 0 0 1-3 3H7zm0-6v3h5a1 1 0 0 0 1-1V7a1 1 0 0 0-1-1H7z"/>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 20 20">
+  <path fill="rgb(90,90,90)" transform="translate(0,1)" d="M7 12v4H4V4a1 1 0 0 1 1-1h8a3 3 0 0 1 3 3v3a3 3 0 0 1-3 3H7zm0-6v3h5a1 1 0 0 0 1-1V7a1 1 0 0 0-1-1H7z"/>
 </svg>
diff --git a/ui/file_manager/file_manager/foreground/images/volumes/plugin_vm_active.svg b/ui/file_manager/file_manager/foreground/images/volumes/plugin_vm_active.svg
index 66d714c..abfc6d9 100644
--- a/ui/file_manager/file_manager/foreground/images/volumes/plugin_vm_active.svg
+++ b/ui/file_manager/file_manager/foreground/images/volumes/plugin_vm_active.svg
@@ -1,3 +1,3 @@
-<svg xmlns="http://www.w3.org/2000/svg" fill="rgb(51,103,214)">
-  <path d="M7 12v4H4V4a1 1 0 0 1 1-1h8a3 3 0 0 1 3 3v3a3 3 0 0 1-3 3H7zm0-6v3h5a1 1 0 0 0 1-1V7a1 1 0 0 0-1-1H7z"/>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 20 20">
+  <path fill="rgb(51,103,214)" transform="translate(0,1)" d="M7 12v4H4V4a1 1 0 0 1 1-1h8a3 3 0 0 1 3 3v3a3 3 0 0 1-3 3H7zm0-6v3h5a1 1 0 0 0 1-1V7a1 1 0 0 0-1-1H7z"/>
 </svg>
diff --git a/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js b/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js
index 36de11e..dab15c0 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js
@@ -177,12 +177,8 @@
       // allows the menu height to grow crbug/934207
       style.maxHeight =
           (viewportHeight - itemRect.top - this.menuEndGap_) + 'px';
-      if ((itemRect.top + childRect.height + this.menuEndGap_) >
-          viewportHeight) {
-        style.overflowY = 'scroll';
-      } else {
-        style.overflowY = 'auto';
-      }
+      // Let the browser deal with scroll bar generation.
+      style.overflowY = 'auto';
     }
 
     /**
diff --git a/ui/file_manager/integration_tests/file_manager/quick_view.js b/ui/file_manager/integration_tests/file_manager/quick_view.js
index aa6fad8..262da9c 100644
--- a/ui/file_manager/integration_tests/file_manager/quick_view.js
+++ b/ui/file_manager/integration_tests/file_manager/quick_view.js
@@ -461,7 +461,7 @@
 
   /**
    * Tests opening Quick View on a text document to verify that the background
-   * color of the <webview> root (html) element is solid white.
+   * color of the <webview> root (html) element.
    */
   testcase.openQuickViewBackgroundColorText = async () => {
     const caller = getCaller();
@@ -501,8 +501,8 @@
     const backgroundColor = await remoteCall.callRemoteTestUtil(
         'deepExecuteScriptInWebView', appId, [webView, getBackgroundStyle]);
 
-    // Check: the <webview> root backgroundColor should be solid white.
-    chrome.test.assertEq('rgb(255, 255, 255)', backgroundColor[0]);
+    // Check: the <webview> root backgroundColor should be transparent.
+    chrome.test.assertEq('rgba(0, 0, 0, 0)', backgroundColor[0]);
   };
 
   /**
diff --git a/ui/gfx/font_fallback_linux.cc b/ui/gfx/font_fallback_linux.cc
index d736dc03..19a3a81 100644
--- a/ui/gfx/font_fallback_linux.cc
+++ b/ui/gfx/font_fallback_linux.cc
@@ -426,17 +426,16 @@
     FcFontSetDestroy(font_set_);
   }
 
-  FallbackFontData GetFallbackFontForChar(UChar32 c) {
+  bool GetFallbackFontForChar(UChar32 c, FallbackFontData* fallback_font) {
     TRACE_EVENT0("fonts", "gfx::CachedFontSet::GetFallbackFontForChar");
 
     for (const auto& cached_font : fallback_list_) {
-      if (cached_font.HasGlyphForCharacter(c))
-        return cached_font.fallback_font();
+      if (cached_font.HasGlyphForCharacter(c)) {
+        *fallback_font = cached_font.fallback_font();
+        return true;
+      }
     }
-    // The previous code just returned garbage if the user didn't
-    // have the necessary fonts, this seems better than garbage.
-    // Current callers happen to ignore any values with an empty family string.
-    return FallbackFontData();
+    return false;
   }
 
  private:
@@ -512,11 +511,13 @@
 FallbackFontData::FallbackFontData() = default;
 FallbackFontData::FallbackFontData(const FallbackFontData& other) = default;
 
-FallbackFontData GetFallbackFontForChar(UChar32 c, const std::string& locale) {
+bool GetFallbackFontForChar(UChar32 c,
+                            const std::string& locale,
+                            FallbackFontData* fallback_font) {
   auto& cached_font_set = g_font_sets_by_locale.Get()[locale];
   if (!cached_font_set)
     cached_font_set = CachedFontSet::CreateForLocale(locale);
-  return cached_font_set->GetFallbackFontForChar(c);
+  return cached_font_set->GetFallbackFontForChar(c, fallback_font);
 }
 
 }  // namespace gfx
diff --git a/ui/gfx/font_fallback_linux.h b/ui/gfx/font_fallback_linux.h
index 1153bb1..6e418b7 100644
--- a/ui/gfx/font_fallback_linux.h
+++ b/ui/gfx/font_fallback_linux.h
@@ -18,16 +18,6 @@
 GFX_EXPORT size_t GetFallbackFontListCacheSizeForTesting();
 GFX_EXPORT void ClearAllFontFallbackCachesForTesting();
 
-// Return a font family which provides a glyph for the Unicode code point
-// specified by character.
-//   c: a UTF-32 code point
-//   preferred_locale: preferred locale identifier for the |characters|
-//                     (e.g. "en", "ja", "zh-CN")
-//
-// Returns: the font family instance. The instance has an empty font name if the
-// request could not be satisfied.
-//
-// Previously blink::WebFontInfo::fallbackFontForChar.
 struct GFX_EXPORT FallbackFontData {
   std::string name;
   base::FilePath filepath;
@@ -40,8 +30,16 @@
   FallbackFontData(const FallbackFontData& other);
 };
 
-GFX_EXPORT FallbackFontData
-GetFallbackFontForChar(UChar32 c, const std::string& preferred_locale);
+// Return a font family which provides a glyph for the Unicode code point
+// specified by character.
+//   c: an UTF-32 code point
+//   preferred_locale: preferred locale identifier for |c|
+//                     (e.g. "en", "ja", "zh-CN")
+//
+// Return whether the request was successful or not.
+GFX_EXPORT bool GetFallbackFontForChar(UChar32 c,
+                                       const std::string& preferred_locale,
+                                       FallbackFontData* fallback_font);
 
 }  // namespace gfx
 
diff --git a/ui/gfx/font_fallback_linux_unittest.cc b/ui/gfx/font_fallback_linux_unittest.cc
index 31226a5..a7c582d 100644
--- a/ui/gfx/font_fallback_linux_unittest.cc
+++ b/ui/gfx/font_fallback_linux_unittest.cc
@@ -29,13 +29,11 @@
 // for the PUA character 0xf6db. This test ensures we're not returning Type 1
 // fonts as fallback.
 TEST_F(FontFallbackLinuxTest, NoType1InFallbackFonts) {
-  FallbackFontData font_fallback_data =
-      GetFallbackFontForChar(0xf6db, std::string());
-  std::string extension = font_fallback_data.filepath.Extension();
-  if (!extension.empty()) {
-    EXPECT_NE(extension, ".pfb");
-  } else {
-    EXPECT_TRUE(font_fallback_data.filepath.empty());
+  FallbackFontData font_fallback_data;
+  if (GetFallbackFontForChar(0xf6db, std::string(), &font_fallback_data)) {
+    std::string extension = font_fallback_data.filepath.Extension();
+    if (!extension.empty())
+      EXPECT_NE(extension, ".pfb");
   }
 }
 
diff --git a/ui/gfx/range/BUILD.gn b/ui/gfx/range/BUILD.gn
index 2a2568a2..67e6fb0 100644
--- a/ui/gfx/range/BUILD.gn
+++ b/ui/gfx/range/BUILD.gn
@@ -4,6 +4,12 @@
 
 import("//build/config/jumbo.gni")
 
+# Reset sources_assignment_filter for the BUILD.gn file to prevent
+# regression during the migration of Chromium away from the feature.
+# See build/no_sources_assignment_filter.md for more information.
+# TODO(crbug.com/1018739): remove this when migration is done.
+set_sources_assignment_filter([])
+
 jumbo_component("range") {
   sources = [
     "gfx_range_export.h",
@@ -11,14 +17,14 @@
     "range.h",
     "range_f.cc",
     "range_f.h",
-    "range_mac.mm",
-    "range_win.cc",
   ]
 
-  if (is_ios) {
-    set_sources_assignment_filter([])
+  if (is_win) {
+    sources += [ "range_win.cc" ]
+  }
+
+  if (is_ios || is_mac) {
     sources += [ "range_mac.mm" ]
-    set_sources_assignment_filter(sources_assignment_filter)
   }
 
   configs += [
diff --git a/ui/gl/direct_composition_surface_win_unittest.cc b/ui/gl/direct_composition_surface_win_unittest.cc
index 1588a6c..53c96c8 100644
--- a/ui/gl/direct_composition_surface_win_unittest.cc
+++ b/ui/gl/direct_composition_surface_win_unittest.cc
@@ -589,7 +589,7 @@
 
  protected:
   void SetUp() override {
-    static_cast<ui::PlatformWindowBase*>(&window_)->Show();
+    static_cast<ui::PlatformWindow*>(&window_)->Show();
     DirectCompositionSurfaceTest::SetUp();
   }
 
diff --git a/ui/native_theme/common_theme.cc b/ui/native_theme/common_theme.cc
index 17f76d7e..14e8da1 100644
--- a/ui/native_theme/common_theme.cc
+++ b/ui/native_theme/common_theme.cc
@@ -97,6 +97,8 @@
       case NativeTheme::kColorId_LabelEnabledColor:
       case NativeTheme::kColorId_LabelTextSelectionColor:
         return gfx::kGoogleGrey200;
+      case NativeTheme::kColorId_LabelSecondaryColor:
+        return gfx::kGoogleGrey500;
       case NativeTheme::kColorId_LabelTextSelectionBackgroundFocused:
         return gfx::kGoogleBlue800;
 
@@ -256,6 +258,8 @@
       return color_utils::BlendForMinContrast(gfx::kGoogleGrey600, bg, fg)
           .color;
     }
+    case NativeTheme::kColorId_LabelSecondaryColor:
+      return gfx::kGoogleGrey700;
     case NativeTheme::kColorId_LabelTextSelectionBackgroundFocused:
       return gfx::kGoogleBlue200;
 
diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h
index 8678d60..fd4d19f 100644
--- a/ui/native_theme/native_theme.h
+++ b/ui/native_theme/native_theme.h
@@ -348,6 +348,7 @@
     // Label
     kColorId_LabelEnabledColor,
     kColorId_LabelDisabledColor,
+    kColorId_LabelSecondaryColor,
     kColorId_LabelTextSelectionColor,
     kColorId_LabelTextSelectionBackgroundFocused,
     // Link
diff --git a/ui/native_theme/native_theme_win.cc b/ui/native_theme/native_theme_win.cc
index 60facaf..a7c06b8a 100644
--- a/ui/native_theme/native_theme_win.cc
+++ b/ui/native_theme/native_theme_win.cc
@@ -591,6 +591,7 @@
     case kColorId_DefaultIconColor:
     case kColorId_DialogForeground:
     case kColorId_LabelEnabledColor:
+    case kColorId_LabelSecondaryColor:
     case kColorId_TreeText:
     case kColorId_TableText:
     case kColorId_TableHeaderText:
diff --git a/ui/ozone/demo/demo_window.cc b/ui/ozone/demo/demo_window.cc
index f85f908..caf78c2 100644
--- a/ui/ozone/demo/demo_window.cc
+++ b/ui/ozone/demo/demo_window.cc
@@ -13,7 +13,7 @@
 #include "ui/ozone/demo/renderer_factory.h"
 #include "ui/ozone/demo/window_manager.h"
 #include "ui/ozone/public/ozone_platform.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
 #if defined(OS_FUCHSIA)
diff --git a/ui/ozone/demo/demo_window.h b/ui/ozone/demo/demo_window.h
index e502ff26..e0e7871 100644
--- a/ui/ozone/demo/demo_window.h
+++ b/ui/ozone/demo/demo_window.h
@@ -10,7 +10,7 @@
 #include "base/memory/weak_ptr.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_delegate.h"
 
 namespace ui {
@@ -58,7 +58,7 @@
   std::unique_ptr<Renderer> renderer_;
 
   // Window-related state.
-  std::unique_ptr<PlatformWindowBase> platform_window_;
+  std::unique_ptr<PlatformWindow> platform_window_;
   gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
 
   base::WeakPtrFactory<DemoWindow> weak_ptr_factory_{this};
diff --git a/ui/ozone/platform/cast/ozone_platform_cast.cc b/ui/ozone/platform/cast/ozone_platform_cast.cc
index dbcfba7..834b278 100644
--- a/ui/ozone/platform/cast/ozone_platform_cast.cc
+++ b/ui/ozone/platform/cast/ozone_platform_cast.cc
@@ -98,7 +98,7 @@
   std::unique_ptr<SystemInputInjector> CreateSystemInputInjector() override {
     return event_factory_ozone_->CreateSystemInputInjector();
   }
-  std::unique_ptr<PlatformWindowBase> CreatePlatformWindow(
+  std::unique_ptr<PlatformWindow> CreatePlatformWindow(
       PlatformWindowDelegate* delegate,
       PlatformWindowInitProperties properties) override {
     return std::make_unique<PlatformWindowCast>(delegate, properties.bounds);
diff --git a/ui/ozone/platform/drm/host/drm_window_host.h b/ui/ozone/platform/drm/host/drm_window_host.h
index bb315da..3b70802e0 100644
--- a/ui/ozone/platform/drm/host/drm_window_host.h
+++ b/ui/ozone/platform/drm/host/drm_window_host.h
@@ -15,7 +15,7 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/ozone/platform/drm/host/gpu_thread_observer.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_delegate.h"
 
 namespace ui {
@@ -37,7 +37,7 @@
 // State propagation needs to happen before the state change is acknowledged to
 // |delegate_| as |delegate_| is responsible for initializing the surface
 // associated with the window (the surface is created on the GPU process).
-class DrmWindowHost : public PlatformWindowBase,
+class DrmWindowHost : public PlatformWindow,
                       public PlatformEventDispatcher,
                       public GpuThreadObserver {
  public:
diff --git a/ui/ozone/platform/drm/ozone_platform_gbm.cc b/ui/ozone/platform/drm/ozone_platform_gbm.cc
index 83a17f4..b70e15a 100644
--- a/ui/ozone/platform/drm/ozone_platform_gbm.cc
+++ b/ui/ozone/platform/drm/ozone_platform_gbm.cc
@@ -150,7 +150,7 @@
     drm_thread_started_ = true;
   }
 
-  std::unique_ptr<PlatformWindowBase> CreatePlatformWindow(
+  std::unique_ptr<PlatformWindow> CreatePlatformWindow(
       PlatformWindowDelegate* delegate,
       PlatformWindowInitProperties properties) override {
     GpuThreadAdapter* adapter = gpu_platform_support_host_.get();
diff --git a/ui/ozone/platform/headless/ozone_platform_headless.cc b/ui/ozone/platform/headless/ozone_platform_headless.cc
index 2cff46c6..85bfcb43 100644
--- a/ui/ozone/platform/headless/ozone_platform_headless.cc
+++ b/ui/ozone/platform/headless/ozone_platform_headless.cc
@@ -75,7 +75,7 @@
   std::unique_ptr<SystemInputInjector> CreateSystemInputInjector() override {
     return nullptr;  // no input injection support.
   }
-  std::unique_ptr<PlatformWindowBase> CreatePlatformWindow(
+  std::unique_ptr<PlatformWindow> CreatePlatformWindow(
       PlatformWindowDelegate* delegate,
       PlatformWindowInitProperties properties) override {
     return std::make_unique<HeadlessWindow>(delegate, window_manager_.get(),
diff --git a/ui/ozone/platform/scenic/ozone_platform_scenic.cc b/ui/ozone/platform/scenic/ozone_platform_scenic.cc
index 1d532c0..b4fc7c1 100644
--- a/ui/ozone/platform/scenic/ozone_platform_scenic.cc
+++ b/ui/ozone/platform/scenic/ozone_platform_scenic.cc
@@ -91,7 +91,7 @@
     return nullptr;
   }
 
-  std::unique_ptr<PlatformWindowBase> CreatePlatformWindow(
+  std::unique_ptr<PlatformWindow> CreatePlatformWindow(
       PlatformWindowDelegate* delegate,
       PlatformWindowInitProperties properties) override {
     if (!properties.view_token.value) {
diff --git a/ui/ozone/platform/scenic/scenic_window.h b/ui/ozone/platform/scenic/scenic_window.h
index 7277075..7a32a91 100644
--- a/ui/ozone/platform/scenic/scenic_window.h
+++ b/ui/ozone/platform/scenic/scenic_window.h
@@ -21,7 +21,7 @@
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/geometry/size_f.h"
 #include "ui/gfx/native_widget_types.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_delegate.h"
 
 namespace ui {
@@ -29,7 +29,7 @@
 class ScenicWindowManager;
 
 class COMPONENT_EXPORT(OZONE) ScenicWindow
-    : public PlatformWindowBase,
+    : public PlatformWindow,
       public InputEventDispatcherDelegate {
  public:
   // Both |window_manager| and |delegate| must outlive the ScenicWindow.
diff --git a/ui/ozone/platform/wayland/host/wayland_window.h b/ui/ozone/platform/wayland/host/wayland_window.h
index bbf18091..7d08584 100644
--- a/ui/ozone/platform/wayland/host/wayland_window.h
+++ b/ui/ozone/platform/wayland/host/wayland_window.h
@@ -17,11 +17,11 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/ozone/platform/wayland/common/wayland_object.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/platform_window_handler/wm_drag_handler.h"
 #include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
 #include "ui/platform_window/platform_window_init_properties.h"
-#include "ui/platform_window/platform_window_linux.h"
 
 namespace gfx {
 class PointF;
@@ -39,7 +39,7 @@
 class XDGShellObjectFactory;
 }  // namespace
 
-class WaylandWindow : public PlatformWindowLinux,
+class WaylandWindow : public PlatformWindow,
                       public PlatformEventDispatcher,
                       public WmMoveResizeHandler,
                       public WmDragHandler {
diff --git a/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
index 77c181a..8dcaf2f 100644
--- a/ui/ozone/platform/wayland/ozone_platform_wayland.cc
+++ b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -104,7 +104,7 @@
     return nullptr;
   }
 
-  std::unique_ptr<PlatformWindowBase> CreatePlatformWindow(
+  std::unique_ptr<PlatformWindow> CreatePlatformWindow(
       PlatformWindowDelegate* delegate,
       PlatformWindowInitProperties properties) override {
     auto window = std::make_unique<WaylandWindow>(delegate, connection_.get());
diff --git a/ui/ozone/platform/windows/ozone_platform_windows.cc b/ui/ozone/platform/windows/ozone_platform_windows.cc
index 912645f6..702dcb9 100644
--- a/ui/ozone/platform/windows/ozone_platform_windows.cc
+++ b/ui/ozone/platform/windows/ozone_platform_windows.cc
@@ -67,7 +67,7 @@
   std::unique_ptr<SystemInputInjector> CreateSystemInputInjector() override {
     return nullptr;  // no input injection support.
   }
-  std::unique_ptr<PlatformWindowBase> CreatePlatformWindow(
+  std::unique_ptr<PlatformWindow> CreatePlatformWindow(
       PlatformWindowDelegate* delegate,
       PlatformWindowInitProperties properties) override {
     return std::make_unique<WindowsWindow>(delegate, properties.bounds);
diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc
index 6970636..beb74b09 100644
--- a/ui/ozone/platform/x11/ozone_platform_x11.cc
+++ b/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -25,7 +25,7 @@
 #include "ui/ozone/public/input_controller.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/ozone/public/system_input_injector.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
 #if defined(OS_CHROMEOS)
@@ -80,7 +80,7 @@
     return gpu_platform_support_host_.get();
   }
 
-  std::unique_ptr<PlatformWindowBase> CreatePlatformWindow(
+  std::unique_ptr<PlatformWindow> CreatePlatformWindow(
       PlatformWindowDelegate* delegate,
       PlatformWindowInitProperties properties) override {
     std::unique_ptr<X11WindowOzone> window =
diff --git a/ui/ozone/platform/x11/x11_window_ozone_unittest.cc b/ui/ozone/platform/x11/x11_window_ozone_unittest.cc
index 0784a303..099e88b8 100644
--- a/ui/ozone/platform/x11/x11_window_ozone_unittest.cc
+++ b/ui/ozone/platform/x11/x11_window_ozone_unittest.cc
@@ -100,7 +100,7 @@
   }
 
  protected:
-  std::unique_ptr<PlatformWindowBase> CreatePlatformWindow(
+  std::unique_ptr<PlatformWindow> CreatePlatformWindow(
       MockPlatformWindowDelegate* delegate,
       const gfx::Rect& bounds,
       gfx::AcceleratedWidget* widget) {
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h
index 5a0189d4..8024569 100644
--- a/ui/ozone/public/ozone_platform.h
+++ b/ui/ozone/public/ozone_platform.h
@@ -14,7 +14,7 @@
 #include "base/message_loop/message_pump_type.h"
 #include "mojo/public/cpp/bindings/binder_map.h"
 #include "ui/gfx/buffer_types.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_delegate.h"
 
 namespace display {
@@ -150,7 +150,7 @@
   virtual IPC::MessageFilter* GetGpuMessageFilter();
   virtual ui::GpuPlatformSupportHost* GetGpuPlatformSupportHost() = 0;
   virtual std::unique_ptr<SystemInputInjector> CreateSystemInputInjector() = 0;
-  virtual std::unique_ptr<PlatformWindowBase> CreatePlatformWindow(
+  virtual std::unique_ptr<PlatformWindow> CreatePlatformWindow(
       PlatformWindowDelegate* delegate,
       PlatformWindowInitProperties properties) = 0;
   virtual std::unique_ptr<display::NativeDisplayDelegate>
diff --git a/ui/platform_window/BUILD.gn b/ui/platform_window/BUILD.gn
index b44b87b..258f596 100644
--- a/ui/platform_window/BUILD.gn
+++ b/ui/platform_window/BUILD.gn
@@ -6,11 +6,10 @@
 
 component("platform_window") {
   sources = [
-    "platform_window_base.cc",
-    "platform_window_base.h",
+    "platform_window.cc",
+    "platform_window.h",
+    "platform_window_delegate.cc",
     "platform_window_delegate.h",
-    "platform_window_delegate_base.cc",
-    "platform_window_delegate_base.h",
     "platform_window_init_properties.cc",
     "platform_window_init_properties.h",
   ]
@@ -36,19 +35,6 @@
       "//third_party/fuchsia-sdk/sdk:ui_views",
     ]
   }
-
-  if (is_linux) {
-    sources += [
-      "platform_window_delegate_linux.cc",
-      "platform_window_delegate_linux.h",
-      "platform_window_linux.cc",
-      "platform_window_linux.h",
-    ]
-  }
-
-  if (is_win) {
-    sources += [ "platform_window_win.h" ]
-  }
 }
 
 group("platform_impls") {
diff --git a/ui/platform_window/extensions/BUILD.gn b/ui/platform_window/extensions/BUILD.gn
index 11569ef..5da275d 100644
--- a/ui/platform_window/extensions/BUILD.gn
+++ b/ui/platform_window/extensions/BUILD.gn
@@ -18,4 +18,12 @@
     "//ui/base",
     "//ui/platform_window",
   ]
+
+  if (is_linux) {
+    sources += [
+      "x11_extension.cc",
+      "x11_extension.h",
+      "x11_extension_delegate.h",
+    ]
+  }
 }
diff --git a/ui/platform_window/extensions/workspace_extension.cc b/ui/platform_window/extensions/workspace_extension.cc
index 5fd7a6d..b4e21e0 100644
--- a/ui/platform_window/extensions/workspace_extension.cc
+++ b/ui/platform_window/extensions/workspace_extension.cc
@@ -5,7 +5,7 @@
 #include "ui/platform_window/extensions/workspace_extension.h"
 
 #include "ui/base/class_property.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 
 DEFINE_UI_CLASS_PROPERTY_TYPE(ui::WorkspaceExtension*)
 
@@ -18,13 +18,13 @@
 WorkspaceExtension::~WorkspaceExtension() = default;
 
 void WorkspaceExtension::SetWorkspaceExtension(
-    PlatformWindowBase* platform_window,
+    PlatformWindow* platform_window,
     WorkspaceExtension* workspace_extension) {
   platform_window->SetProperty(kWorkspaceExtensionKey, workspace_extension);
 }
 
 WorkspaceExtension* GetWorkspaceExtension(
-    const PlatformWindowBase& platform_window) {
+    const PlatformWindow& platform_window) {
   return platform_window.GetProperty(kWorkspaceExtensionKey);
 }
 
diff --git a/ui/platform_window/extensions/workspace_extension.h b/ui/platform_window/extensions/workspace_extension.h
index 309e08d..e36b1464 100644
--- a/ui/platform_window/extensions/workspace_extension.h
+++ b/ui/platform_window/extensions/workspace_extension.h
@@ -11,7 +11,7 @@
 
 namespace ui {
 
-class PlatformWindowBase;
+class PlatformWindow;
 class WorkspaceExtensionDelegate;
 
 // A workspace extension that platforms can use to add support for workspaces.
@@ -40,13 +40,13 @@
   virtual ~WorkspaceExtension();
 
   // Sets the pointer to the extension as a property of the PlatformWindow.
-  void SetWorkspaceExtension(PlatformWindowBase* platform_window,
+  void SetWorkspaceExtension(PlatformWindow* platform_window,
                              WorkspaceExtension* workspace_extension);
 };
 
 COMPONENT_EXPORT(EXTENSIONS)
 WorkspaceExtension* GetWorkspaceExtension(
-    const PlatformWindowBase& platform_window);
+    const PlatformWindow& platform_window);
 
 }  // namespace ui
 
diff --git a/ui/platform_window/extensions/x11_extension.cc b/ui/platform_window/extensions/x11_extension.cc
new file mode 100644
index 0000000..6f302fe
--- /dev/null
+++ b/ui/platform_window/extensions/x11_extension.cc
@@ -0,0 +1,27 @@
+// Copyright 2019 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 "ui/platform_window/extensions/x11_extension.h"
+
+#include "ui/base/class_property.h"
+#include "ui/platform_window/platform_window.h"
+
+DEFINE_UI_CLASS_PROPERTY_TYPE(ui::X11Extension*)
+
+namespace ui {
+
+DEFINE_UI_CLASS_PROPERTY_KEY(X11Extension*, kX11ExtensionKey, nullptr)
+
+X11Extension::~X11Extension() = default;
+
+void X11Extension::SetX11Extension(PlatformWindow* platform_window,
+                                   X11Extension* x11_extension) {
+  platform_window->SetProperty(kX11ExtensionKey, x11_extension);
+}
+
+X11Extension* GetX11Extension(const PlatformWindow& platform_window) {
+  return platform_window.GetProperty(kX11ExtensionKey);
+}
+
+}  // namespace ui
diff --git a/ui/platform_window/extensions/x11_extension.h b/ui/platform_window/extensions/x11_extension.h
new file mode 100644
index 0000000..326d6f21
--- /dev/null
+++ b/ui/platform_window/extensions/x11_extension.h
@@ -0,0 +1,55 @@
+// Copyright 2019 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 UI_PLATFORM_WINDOW_EXTENSIONS_X11_EXTENSION_H_
+#define UI_PLATFORM_WINDOW_EXTENSIONS_X11_EXTENSION_H_
+
+#include "base/component_export.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace ui {
+
+class PlatformWindow;
+class X11ExtensionDelegate;
+
+// Linux extensions that linux platforms can use to extend the platform windows
+// APIs. Please refer to README for more details.
+class COMPONENT_EXPORT(EXTENSIONS) X11Extension {
+ public:
+  // X11-specific.  Returns whether an XSync extension is available at the
+  // current platform.
+  virtual bool IsSyncExtensionAvailable() const = 0;
+
+  // X11-specific.  Handles CompleteSwapAfterResize event coming from the
+  // compositor observer.
+  virtual void OnCompleteSwapAfterResize() = 0;
+
+  // X11-specific.  Returns the current bounds in terms of the X11 Root Window
+  // including the borders provided by the window manager (if any).
+  virtual gfx::Rect GetXRootWindowOuterBounds() const = 0;
+
+  // X11-specific.  Says if the X11 Root Window contains the point within its
+  // set shape. If shape is not set, returns true.
+  virtual bool ContainsPointInXRegion(const gfx::Point& point) const = 0;
+
+  // X11-specific.  Asks X11 to lower the Xwindow down the stack so that it does
+  // not obscure any sibling windows.
+  virtual void LowerXWindow() = 0;
+
+  virtual void SetX11ExtensionDelegate(X11ExtensionDelegate* delegate) = 0;
+
+ protected:
+  virtual ~X11Extension();
+
+  // Sets the pointer to the extension as a property of the PlatformWindow.
+  void SetX11Extension(PlatformWindow* platform_window,
+                       X11Extension* x11_extensions);
+};
+
+COMPONENT_EXPORT(EXTENSIONS)
+X11Extension* GetX11Extension(const PlatformWindow& platform_window);
+
+}  // namespace ui
+
+#endif  // UI_PLATFORM_WINDOW_EXTENSIONS_X11_EXTENSION_H_
diff --git a/ui/platform_window/extensions/x11_extension_delegate.h b/ui/platform_window/extensions/x11_extension_delegate.h
new file mode 100644
index 0000000..0bf123c
--- /dev/null
+++ b/ui/platform_window/extensions/x11_extension_delegate.h
@@ -0,0 +1,52 @@
+// Copyright 2019 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 UI_PLATFORM_WINDOW_EXTENSIONS_X11_EXTENSION_DELEGATE_H_
+#define UI_PLATFORM_WINDOW_EXTENSIONS_X11_EXTENSION_DELEGATE_H_
+
+#include "base/component_export.h"
+#include "ui/base/buildflags.h"
+
+#if BUILDFLAG(USE_ATK)
+using AtkKeyEventStruct = struct _AtkKeyEventStruct;
+#endif
+
+class SkPath;
+
+namespace gfx {
+class Size;
+}
+
+namespace ui {
+
+class COMPONENT_EXPORT(EXTENSIONS) X11ExtensionDelegate {
+ public:
+  // Notifies the delegate that the window got mapped in the X server. Wayland
+  // does not support this interface.
+  virtual void OnXWindowMapped() = 0;
+  virtual void OnXWindowUnmapped() = 0;
+
+  // Notifies if the PlatformWindow looses a mouse grab. This can be useful
+  // for Wayland or X11. Both of them provide pointer enter and leave
+  // notifications, which non-ozone X11 (just an example) use to be using to
+  // notify about lost pointer grab along with explicit grabs. Wayland also
+  // has this technique. However, explicit grab is available only for popup
+  // (menu) windows.
+  virtual void OnLostMouseGrab() = 0;
+
+  // Returns a mask to be used to clip the window for the given
+  // size. This is used to create the non-rectangular window shape.
+  virtual void GetWindowMask(const gfx::Size& size, SkPath* window_mask) = 0;
+
+#if BUILDFLAG(USE_ATK)
+  virtual bool OnAtkKeyEvent(AtkKeyEventStruct* atk_key_event) = 0;
+#endif
+
+ protected:
+  virtual ~X11ExtensionDelegate() = default;
+};
+
+}  // namespace ui
+
+#endif  // UI_PLATFORM_WINDOW_EXTENSIONS_X11_EXTENSION_DELEGATE_H_
diff --git a/ui/platform_window/platform_window.cc b/ui/platform_window/platform_window.cc
new file mode 100644
index 0000000..42e9997
--- /dev/null
+++ b/ui/platform_window/platform_window.cc
@@ -0,0 +1,51 @@
+// Copyright 2019 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 "ui/platform_window/platform_window.h"
+
+#include "ui/gfx/geometry/rect.h"
+
+namespace ui {
+
+PlatformWindow::PlatformWindow() = default;
+
+PlatformWindow::~PlatformWindow() = default;
+
+bool PlatformWindow::ShouldWindowContentsBeTransparent() const {
+  return false;
+}
+
+void PlatformWindow::SetZOrderLevel(ZOrderLevel order) {}
+
+ZOrderLevel PlatformWindow::GetZOrderLevel() const {
+  return ZOrderLevel::kNormal;
+}
+
+void PlatformWindow::StackAbove(gfx::AcceleratedWidget widget) {}
+
+void PlatformWindow::StackAtTop() {}
+
+void PlatformWindow::FlashFrame(bool flash_frame) {}
+
+void PlatformWindow::SetShape(std::unique_ptr<ShapeRects> native_shape,
+                              const gfx::Transform& transform) {}
+
+void PlatformWindow::SetAspectRatio(const gfx::SizeF& aspect_ratio) {}
+
+void PlatformWindow::SetWindowIcons(const gfx::ImageSkia& window_icon,
+                                    const gfx::ImageSkia& app_icon) {}
+
+bool PlatformWindow::IsAnimatingClosed() const {
+  return false;
+}
+
+bool PlatformWindow::IsTranslucentWindowOpacitySupported() const {
+  return false;
+}
+
+void PlatformWindow::SetOpacity(float opacity) {}
+
+void PlatformWindow::SetVisibilityChangedAnimationsEnabled(bool enabled) {}
+
+}  // namespace ui
diff --git a/ui/platform_window/platform_window_base.h b/ui/platform_window/platform_window.h
similarity index 89%
rename from ui/platform_window/platform_window_base.h
rename to ui/platform_window/platform_window.h
index 496b149..96b7690 100644
--- a/ui/platform_window/platform_window_base.h
+++ b/ui/platform_window/platform_window.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 UI_PLATFORM_WINDOW_PLATFORM_WINDOW_BASE_H_
-#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_BASE_H_
+#ifndef UI_PLATFORM_WINDOW_PLATFORM_WINDOW_H_
+#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_H_
 
 #include <memory>
 
@@ -25,15 +25,12 @@
 
 namespace ui {
 
-// Platform window.
-//
-// Each instance of PlatformWindowBase represents a single window in the
-// underlying platform windowing system (i.e. X11/Win/OSX).
-class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindowBase
+// Generic PlatformWindow interface.
+class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindow
     : public PropertyHandler {
  public:
-  PlatformWindowBase();
-  ~PlatformWindowBase() override;
+  PlatformWindow();
+  ~PlatformWindow() override;
 
   // PlatformWindow may be called with the |inactive| set to true in some cases.
   // That means that the Window Manager must not activate the window when it is
@@ -136,8 +133,15 @@
 
   // Returns true if the window supports translucency.
   virtual bool IsTranslucentWindowOpacitySupported() const;
+
+  // Sets opacity of the platform window.
+  virtual void SetOpacity(float opacity);
+
+  // Enables or disables platform provided animations of the PlatformWindow.
+  // If |enabled| is set to false, animations are disabled.
+  virtual void SetVisibilityChangedAnimationsEnabled(bool enabled);
 };
 
 }  // namespace ui
 
-#endif  // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_BASE_H_
+#endif  // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_H_
diff --git a/ui/platform_window/platform_window_base.cc b/ui/platform_window/platform_window_base.cc
deleted file mode 100644
index 6ddea33..0000000
--- a/ui/platform_window/platform_window_base.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2019 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 "ui/platform_window/platform_window_base.h"
-
-#include "ui/gfx/geometry/rect.h"
-
-namespace ui {
-
-PlatformWindowBase::PlatformWindowBase() = default;
-
-PlatformWindowBase::~PlatformWindowBase() = default;
-
-bool PlatformWindowBase::ShouldWindowContentsBeTransparent() const {
-  return false;
-}
-
-void PlatformWindowBase::SetZOrderLevel(ZOrderLevel order) {}
-
-ZOrderLevel PlatformWindowBase::GetZOrderLevel() const {
-  return ZOrderLevel::kNormal;
-}
-
-void PlatformWindowBase::StackAbove(gfx::AcceleratedWidget widget) {}
-
-void PlatformWindowBase::StackAtTop() {}
-
-void PlatformWindowBase::FlashFrame(bool flash_frame) {}
-
-void PlatformWindowBase::SetShape(std::unique_ptr<ShapeRects> native_shape,
-                                  const gfx::Transform& transform) {}
-
-void PlatformWindowBase::SetAspectRatio(const gfx::SizeF& aspect_ratio) {}
-
-void PlatformWindowBase::SetWindowIcons(const gfx::ImageSkia& window_icon,
-                                        const gfx::ImageSkia& app_icon) {}
-
-bool PlatformWindowBase::IsAnimatingClosed() const {
-  return false;
-}
-
-bool PlatformWindowBase::IsTranslucentWindowOpacitySupported() const {
-  return false;
-}
-
-}  // namespace ui
diff --git a/ui/platform_window/platform_window_delegate.cc b/ui/platform_window/platform_window_delegate.cc
new file mode 100644
index 0000000..fb685b3
--- /dev/null
+++ b/ui/platform_window/platform_window_delegate.cc
@@ -0,0 +1,23 @@
+// Copyright 2019 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 "ui/platform_window/platform_window_delegate.h"
+
+#include "ui/gfx/geometry/size.h"
+
+namespace ui {
+
+PlatformWindowDelegate::PlatformWindowDelegate() = default;
+
+PlatformWindowDelegate::~PlatformWindowDelegate() = default;
+
+base::Optional<gfx::Size> PlatformWindowDelegate::GetMinimumSizeForWindow() {
+  return base::nullopt;
+}
+
+base::Optional<gfx::Size> PlatformWindowDelegate::GetMaximumSizeForWindow() {
+  return base::nullopt;
+}
+
+}  // namespace ui
diff --git a/ui/platform_window/platform_window_delegate.h b/ui/platform_window/platform_window_delegate.h
index fe4059ff..88b791cf 100644
--- a/ui/platform_window/platform_window_delegate.h
+++ b/ui/platform_window/platform_window_delegate.h
@@ -1,27 +1,70 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2019 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 UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_H_
 #define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_H_
 
-#include "build/build_config.h"
+#include "base/component_export.h"
+#include "base/optional.h"
+#include "ui/gfx/native_widget_types.h"
 
-// By default, PlatformWindowDelegateBase is used. However, different platforms
-// should specify what delegate they would like to use if needed.
-#if defined(OS_LINUX)
-#include "ui/platform_window/platform_window_delegate_linux.h"
-#else
-#include "ui/platform_window/platform_window_delegate_base.h"
-#endif
+namespace gfx {
+class Rect;
+class Size;
+}  // namespace gfx
 
 namespace ui {
 
-#if defined(OS_LINUX)
-using PlatformWindowDelegate = PlatformWindowDelegateLinux;
-#else
-using PlatformWindowDelegate = PlatformWindowDelegateBase;
-#endif
+class Event;
+
+enum class PlatformWindowState {
+  kUnknown,
+  kMaximized,
+  kMinimized,
+  kNormal,
+  kFullScreen,
+};
+
+class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindowDelegate {
+ public:
+  PlatformWindowDelegate();
+  virtual ~PlatformWindowDelegate();
+
+  // Note that |new_bounds| is in physical screen coordinates.
+  virtual void OnBoundsChanged(const gfx::Rect& new_bounds) = 0;
+
+  // Note that |damaged_region| is in the platform-window's coordinates, in
+  // physical pixels.
+  virtual void OnDamageRect(const gfx::Rect& damaged_region) = 0;
+
+  virtual void DispatchEvent(Event* event) = 0;
+
+  virtual void OnCloseRequest() = 0;
+  virtual void OnClosed() = 0;
+
+  virtual void OnWindowStateChanged(PlatformWindowState new_state) = 0;
+
+  virtual void OnLostCapture() = 0;
+
+  virtual void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) = 0;
+
+  // Notifies the delegate that the widget cannot be used anymore until
+  // a new widget is made available through OnAcceleratedWidgetAvailable().
+  // Must not be called when the PlatformWindow is being destroyed.
+  virtual void OnAcceleratedWidgetDestroyed() = 0;
+
+  virtual void OnActivationChanged(bool active) = 0;
+
+  // Requests size constraints for the PlatformWindow.
+  virtual base::Optional<gfx::Size> GetMinimumSizeForWindow();
+  virtual base::Optional<gfx::Size> GetMaximumSizeForWindow();
+
+  // Called when the location of mouse pointer entered the window.  This is
+  // different from ui::ET_MOUSE_ENTERED which may not be generated when mouse
+  // is captured either by implicitly or explicitly.
+  virtual void OnMouseEnter() = 0;
+};
 
 }  // namespace ui
 
diff --git a/ui/platform_window/platform_window_delegate_base.cc b/ui/platform_window/platform_window_delegate_base.cc
deleted file mode 100644
index cb3a992..0000000
--- a/ui/platform_window/platform_window_delegate_base.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2019 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 "ui/platform_window/platform_window_delegate_base.h"
-
-#include "ui/gfx/geometry/size.h"
-
-namespace ui {
-
-PlatformWindowDelegateBase::PlatformWindowDelegateBase() = default;
-
-PlatformWindowDelegateBase::~PlatformWindowDelegateBase() = default;
-
-base::Optional<gfx::Size>
-PlatformWindowDelegateBase::GetMinimumSizeForWindow() {
-  return base::nullopt;
-}
-
-base::Optional<gfx::Size>
-PlatformWindowDelegateBase::GetMaximumSizeForWindow() {
-  return base::nullopt;
-}
-
-}  // namespace ui
diff --git a/ui/platform_window/platform_window_delegate_base.h b/ui/platform_window/platform_window_delegate_base.h
deleted file mode 100644
index 9dc2990..0000000
--- a/ui/platform_window/platform_window_delegate_base.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2019 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 UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_BASE_H_
-#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_BASE_H_
-
-#include "base/component_export.h"
-#include "base/optional.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace gfx {
-class Rect;
-class Size;
-}  // namespace gfx
-
-namespace ui {
-
-class Event;
-
-enum class PlatformWindowState {
-  kUnknown,
-  kMaximized,
-  kMinimized,
-  kNormal,
-  kFullScreen,
-};
-
-// This is the bare minimum for PlatformWindowDeelegate, but some platforms may
-// require more, and should do so in a subclass. Please refer to
-// PlatformWindowDelegateLinux for an example.
-class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindowDelegateBase {
- public:
-  PlatformWindowDelegateBase();
-  virtual ~PlatformWindowDelegateBase();
-
-  // Note that |new_bounds| is in physical screen coordinates.
-  virtual void OnBoundsChanged(const gfx::Rect& new_bounds) = 0;
-
-  // Note that |damaged_region| is in the platform-window's coordinates, in
-  // physical pixels.
-  virtual void OnDamageRect(const gfx::Rect& damaged_region) = 0;
-
-  virtual void DispatchEvent(Event* event) = 0;
-
-  virtual void OnCloseRequest() = 0;
-  virtual void OnClosed() = 0;
-
-  virtual void OnWindowStateChanged(PlatformWindowState new_state) = 0;
-
-  virtual void OnLostCapture() = 0;
-
-  virtual void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) = 0;
-
-  // Notifies the delegate that the widget cannot be used anymore until
-  // a new widget is made available through OnAcceleratedWidgetAvailable().
-  // Must not be called when the PlatformWindow is being destroyed.
-  virtual void OnAcceleratedWidgetDestroyed() = 0;
-
-  virtual void OnActivationChanged(bool active) = 0;
-
-  // Requests size constraints for the PlatformWindow.
-  virtual base::Optional<gfx::Size> GetMinimumSizeForWindow();
-  virtual base::Optional<gfx::Size> GetMaximumSizeForWindow();
-
-  // Called when the location of mouse pointer entered the window.  This is
-  // different from ui::ET_MOUSE_ENTERED which may not be generated when mouse
-  // is captured either by implicitly or explicitly.
-  virtual void OnMouseEnter() = 0;
-};
-
-}  // namespace ui
-
-#endif  // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_BASE_H_
diff --git a/ui/platform_window/platform_window_delegate_linux.cc b/ui/platform_window/platform_window_delegate_linux.cc
deleted file mode 100644
index c15b995..0000000
--- a/ui/platform_window/platform_window_delegate_linux.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2019 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 "ui/platform_window/platform_window_delegate_linux.h"
-
-#include "base/logging.h"
-
-namespace ui {
-
-PlatformWindowDelegateLinux::PlatformWindowDelegateLinux() = default;
-
-PlatformWindowDelegateLinux::~PlatformWindowDelegateLinux() = default;
-
-void PlatformWindowDelegateLinux::OnXWindowMapped() {
-  NOTIMPLEMENTED_LOG_ONCE();
-}
-
-void PlatformWindowDelegateLinux::OnXWindowUnmapped() {
-  NOTIMPLEMENTED_LOG_ONCE();
-}
-
-void PlatformWindowDelegateLinux::OnLostMouseGrab() {
-  NOTIMPLEMENTED_LOG_ONCE();
-}
-
-void PlatformWindowDelegateLinux::GetWindowMask(const gfx::Size& size,
-                                                SkPath* window_mask) {
-  NOTIMPLEMENTED_LOG_ONCE();
-}
-
-#if BUILDFLAG(USE_ATK)
-bool PlatformWindowDelegateLinux::OnAtkKeyEvent(AtkKeyEventStruct* atk_event) {
-  NOTIMPLEMENTED_LOG_ONCE();
-  return false;
-}
-#endif
-
-}  // namespace ui
diff --git a/ui/platform_window/platform_window_delegate_linux.h b/ui/platform_window/platform_window_delegate_linux.h
deleted file mode 100644
index 53a3c1c..0000000
--- a/ui/platform_window/platform_window_delegate_linux.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2019 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 UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_LINUX_H_
-#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_LINUX_H_
-
-#include "base/component_export.h"
-#include "ui/base/buildflags.h"
-#include "ui/platform_window/platform_window_delegate_base.h"
-
-#if BUILDFLAG(USE_ATK)
-using AtkKeyEventStruct = struct _AtkKeyEventStruct;
-#endif
-
-class SkPath;
-
-namespace gfx {
-class Size;
-}
-
-namespace ui {
-
-// This is an optional linux delegate interface, which should be implemented by
-// linux-based platforms. It contains both Wayland and X11 specific and common
-// interfaces.
-class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindowDelegateLinux
-    : public PlatformWindowDelegateBase {
- public:
-  PlatformWindowDelegateLinux();
-  ~PlatformWindowDelegateLinux() override;
-
-  // Notifies the delegate that the window got mapped in the X server. Wayland
-  // does not support this interface.
-  virtual void OnXWindowMapped();
-  virtual void OnXWindowUnmapped();
-
-  // Notifies if the PlatformWindow looses a mouse grab. This can be useful for
-  // Wayland or X11. Both of them provide pointer enter and leave notifications,
-  // which non-ozone X11 (just an example) use to be using to notify about lost
-  // pointer grab along with explicit grabs. Wayland also has this technique.
-  // However, explicit grab is available only for popup (menu) windows.
-  virtual void OnLostMouseGrab();
-
-  // Returns a mask to be used to clip the window for the given
-  // size. This is used to create the non-rectangular window shape.
-  virtual void GetWindowMask(const gfx::Size& size, SkPath* window_mask);
-
-#if BUILDFLAG(USE_ATK)
-  virtual bool OnAtkKeyEvent(AtkKeyEventStruct* atk_key_event);
-#endif
-};
-
-}  // namespace ui
-
-#endif  // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_LINUX_H_
diff --git a/ui/platform_window/platform_window_handler/DEPS b/ui/platform_window/platform_window_handler/DEPS
index d55936f36..381a2e478 100644
--- a/ui/platform_window/platform_window_handler/DEPS
+++ b/ui/platform_window/platform_window_handler/DEPS
@@ -1,4 +1,4 @@
 include_rules = [
   "+ui/base/class_property.h",
-  "+ui/platform_window/platform_window_base.h",
+  "+ui/platform_window/platform_window.h",
 ]
diff --git a/ui/platform_window/platform_window_handler/wm_drag_handler.cc b/ui/platform_window/platform_window_handler/wm_drag_handler.cc
index 27e05a5..f559d42 100644
--- a/ui/platform_window/platform_window_handler/wm_drag_handler.cc
+++ b/ui/platform_window/platform_window_handler/wm_drag_handler.cc
@@ -5,7 +5,7 @@
 #include "ui/platform_window/platform_window_handler/wm_drag_handler.h"
 
 #include "ui/base/class_property.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 
 DEFINE_UI_CLASS_PROPERTY_TYPE(ui::WmDragHandler*)
 
@@ -13,12 +13,12 @@
 
 DEFINE_UI_CLASS_PROPERTY_KEY(WmDragHandler*, kWmDragHandlerKey, nullptr)
 
-void SetWmDragHandler(PlatformWindowBase* platform_window,
+void SetWmDragHandler(PlatformWindow* platform_window,
                       WmDragHandler* drag_handler) {
   platform_window->SetProperty(kWmDragHandlerKey, drag_handler);
 }
 
-WmDragHandler* GetWmDragHandler(const PlatformWindowBase& platform_window) {
+WmDragHandler* GetWmDragHandler(const PlatformWindow& platform_window) {
   return platform_window.GetProperty(kWmDragHandlerKey);
 }
 
diff --git a/ui/platform_window/platform_window_handler/wm_drag_handler.h b/ui/platform_window/platform_window_handler/wm_drag_handler.h
index 87604ca4..7f7d793 100644
--- a/ui/platform_window/platform_window_handler/wm_drag_handler.h
+++ b/ui/platform_window/platform_window_handler/wm_drag_handler.h
@@ -10,7 +10,7 @@
 #include "ui/platform_window/platform_window_handler/wm_platform_export.h"
 
 namespace ui {
-class PlatformWindowBase;
+class PlatformWindow;
 class OSExchangeData;
 
 class WM_PLATFORM_EXPORT WmDragHandler {
@@ -29,10 +29,10 @@
   virtual ~WmDragHandler() {}
 };
 
-WM_PLATFORM_EXPORT void SetWmDragHandler(PlatformWindowBase* platform_window,
+WM_PLATFORM_EXPORT void SetWmDragHandler(PlatformWindow* platform_window,
                                          WmDragHandler* drag_handler);
 WM_PLATFORM_EXPORT WmDragHandler* GetWmDragHandler(
-    const PlatformWindowBase& platform_window);
+    const PlatformWindow& platform_window);
 
 }  // namespace ui
 
diff --git a/ui/platform_window/platform_window_handler/wm_drop_handler.cc b/ui/platform_window/platform_window_handler/wm_drop_handler.cc
index 11f23479..64ff6bd 100644
--- a/ui/platform_window/platform_window_handler/wm_drop_handler.cc
+++ b/ui/platform_window/platform_window_handler/wm_drop_handler.cc
@@ -5,7 +5,7 @@
 #include "ui/platform_window/platform_window_handler/wm_drop_handler.h"
 
 #include "ui/base/class_property.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 
 DEFINE_UI_CLASS_PROPERTY_TYPE(ui::WmDropHandler*)
 
@@ -13,12 +13,12 @@
 
 DEFINE_UI_CLASS_PROPERTY_KEY(WmDropHandler*, kWmDropHandlerKey, nullptr)
 
-void SetWmDropHandler(PlatformWindowBase* platform_window,
+void SetWmDropHandler(PlatformWindow* platform_window,
                       WmDropHandler* drop_handler) {
   platform_window->SetProperty(kWmDropHandlerKey, drop_handler);
 }
 
-WmDropHandler* GetWmDropHandler(const PlatformWindowBase& platform_window) {
+WmDropHandler* GetWmDropHandler(const PlatformWindow& platform_window) {
   return platform_window.GetProperty(kWmDropHandlerKey);
 }
 
diff --git a/ui/platform_window/platform_window_handler/wm_drop_handler.h b/ui/platform_window/platform_window_handler/wm_drop_handler.h
index e4844c0..26745af 100644
--- a/ui/platform_window/platform_window_handler/wm_drop_handler.h
+++ b/ui/platform_window/platform_window_handler/wm_drop_handler.h
@@ -15,7 +15,7 @@
 }
 
 namespace ui {
-class PlatformWindowBase;
+class PlatformWindow;
 class OSExchangeData;
 
 class WM_PLATFORM_EXPORT WmDropHandler {
@@ -45,10 +45,10 @@
   virtual ~WmDropHandler() {}
 };
 
-WM_PLATFORM_EXPORT void SetWmDropHandler(PlatformWindowBase* platform_window,
+WM_PLATFORM_EXPORT void SetWmDropHandler(PlatformWindow* platform_window,
                                          WmDropHandler* drop_handler);
 WM_PLATFORM_EXPORT WmDropHandler* GetWmDropHandler(
-    const PlatformWindowBase& platform_window);
+    const PlatformWindow& platform_window);
 
 }  // namespace ui
 
diff --git a/ui/platform_window/platform_window_handler/wm_move_resize_handler.cc b/ui/platform_window/platform_window_handler/wm_move_resize_handler.cc
index d9303cc..a79ad70a 100644
--- a/ui/platform_window/platform_window_handler/wm_move_resize_handler.cc
+++ b/ui/platform_window/platform_window_handler/wm_move_resize_handler.cc
@@ -5,7 +5,7 @@
 #include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
 
 #include "ui/base/class_property.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 
 DEFINE_UI_CLASS_PROPERTY_TYPE(WmMoveResizeHandler*)
 
@@ -15,13 +15,13 @@
                              kWmMoveResizeHandlerKey,
                              nullptr)
 
-void SetWmMoveResizeHandler(PlatformWindowBase* platform_window,
+void SetWmMoveResizeHandler(PlatformWindow* platform_window,
                             WmMoveResizeHandler* move_resize_handler) {
   platform_window->SetProperty(kWmMoveResizeHandlerKey, move_resize_handler);
 }
 
 WmMoveResizeHandler* GetWmMoveResizeHandler(
-    const PlatformWindowBase& platform_window) {
+    const PlatformWindow& platform_window) {
   return platform_window.GetProperty(kWmMoveResizeHandlerKey);
 }
 
diff --git a/ui/platform_window/platform_window_handler/wm_move_resize_handler.h b/ui/platform_window/platform_window_handler/wm_move_resize_handler.h
index 57e5a622..ac30160 100644
--- a/ui/platform_window/platform_window_handler/wm_move_resize_handler.h
+++ b/ui/platform_window/platform_window_handler/wm_move_resize_handler.h
@@ -13,7 +13,7 @@
 
 namespace ui {
 
-class PlatformWindowBase;
+class PlatformWindow;
 
 class WmMoveResizeHandler {
  public:
@@ -53,10 +53,10 @@
 };
 
 WM_PLATFORM_EXPORT void SetWmMoveResizeHandler(
-    PlatformWindowBase* platform_window,
+    PlatformWindow* platform_window,
     WmMoveResizeHandler* move_resize_handler);
 WM_PLATFORM_EXPORT WmMoveResizeHandler* GetWmMoveResizeHandler(
-    const PlatformWindowBase& platform_window);
+    const PlatformWindow& platform_window);
 
 }  // namespace ui
 
diff --git a/ui/platform_window/platform_window_init_properties.h b/ui/platform_window/platform_window_init_properties.h
index cdd7b13..3e16eae 100644
--- a/ui/platform_window/platform_window_init_properties.h
+++ b/ui/platform_window/platform_window_init_properties.h
@@ -41,6 +41,10 @@
 
 class WorkspaceExtensionDelegate;
 
+#if defined(OS_LINUX)
+class X11ExtensionDelegate;
+#endif
+
 // Initial properties which are passed to PlatformWindow to be initialized
 // with a desired set of properties.
 struct COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindowInitProperties {
@@ -92,6 +96,8 @@
 
   // Stores visual id for the system tray in X11.
   base::Optional<int> x_visual_id;
+
+  X11ExtensionDelegate* x11_extension_delegate = nullptr;
 #endif
 };
 
diff --git a/ui/platform_window/platform_window_linux.cc b/ui/platform_window/platform_window_linux.cc
deleted file mode 100644
index 556753a..0000000
--- a/ui/platform_window/platform_window_linux.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2019 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 "ui/platform_window/platform_window_linux.h"
-
-namespace ui {
-
-PlatformWindowLinux::PlatformWindowLinux() = default;
-
-PlatformWindowLinux::~PlatformWindowLinux() = default;
-
-bool PlatformWindowLinux::IsSyncExtensionAvailable() const {
-  return false;
-}
-
-void PlatformWindowLinux::OnCompleteSwapAfterResize() {}
-
-gfx::Rect PlatformWindowLinux::GetXRootWindowOuterBounds() const {
-  return {};
-}
-
-bool PlatformWindowLinux::ContainsPointInXRegion(
-    const gfx::Point& point) const {
-  return false;
-}
-
-void PlatformWindowLinux::SetOpacityForXWindow(float opacity) {}
-
-void PlatformWindowLinux::LowerXWindow() {}
-
-}  // namespace ui
diff --git a/ui/platform_window/platform_window_linux.h b/ui/platform_window/platform_window_linux.h
deleted file mode 100644
index 7515f2a4..0000000
--- a/ui/platform_window/platform_window_linux.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2019 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 UI_PLATFORM_WINDOW_PLATFORM_WINDOW_LINUX_H_
-#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_LINUX_H_
-
-#include "base/component_export.h"
-#include "base/optional.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/platform_window/platform_window_base.h"
-
-namespace ui {
-
-// Linux extensions to the PlatformWindowBase.
-class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindowLinux
-    : public PlatformWindowBase {
- public:
-  PlatformWindowLinux();
-  ~PlatformWindowLinux() override;
-
-  // X11-specific.  Returns whether an XSync extension is available at the
-  // current platform.
-  virtual bool IsSyncExtensionAvailable() const;
-  // X11-specific.  Handles CompleteSwapAfterResize event coming from the
-  // compositor observer.
-  virtual void OnCompleteSwapAfterResize();
-
-  // X11-specific.  Returns the current bounds in terms of the X11 Root Window
-  // including the borders provided by the window manager (if any).
-  virtual gfx::Rect GetXRootWindowOuterBounds() const;
-
-  // X11-specific.  Says if the X11 Root Window contains the point within its
-  // set shape. If shape is not set, returns true.
-  virtual bool ContainsPointInXRegion(const gfx::Point& point) const;
-
-  // X11-specific.  Asks X11 to set transparency of the X11 Root Window. Not
-  // used for Wayland as it uses alpha channel to blend a window instead.
-  virtual void SetOpacityForXWindow(float opacity);
-
-  // X11-specific.  Asks X11 to lower the Xwindow down the stack so that it does
-  // not obscure any sibling windows.
-  virtual void LowerXWindow();
-};
-
-}  // namespace ui
-
-#endif  // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_LINUX_H_
diff --git a/ui/platform_window/platform_window_win.h b/ui/platform_window/platform_window_win.h
deleted file mode 100644
index 12f43be..0000000
--- a/ui/platform_window/platform_window_win.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2019 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 UI_PLATFORM_WINDOW_PLATFORM_WINDOW_WIN_H_
-#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_WIN_H_
-
-#include "base/component_export.h"
-#include "ui/platform_window/platform_window_base.h"
-
-namespace ui {
-
-// Windows extensions to the PlatformWindowBase.
-class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindowWin
-    : public PlatformWindowBase {
- public:
-  PlatformWindowWin() = default;
-  ~PlatformWindowWin() override = default;
-
-  // Enables or disables platform provided animations of the PlatformWindow.
-  // If |enabled| is set to false, animations must be disabled.
-  virtual void SetVisibilityChangedAnimationsEnabled(bool enabled) = 0;
-};
-
-}  // namespace ui
-
-#endif  // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_WIN_H_
diff --git a/ui/platform_window/stub/stub_window.h b/ui/platform_window/stub/stub_window.h
index 0c548ea9..7d8a0a0 100644
--- a/ui/platform_window/stub/stub_window.h
+++ b/ui/platform_window/stub/stub_window.h
@@ -8,7 +8,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "ui/gfx/geometry/rect.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/stub/stub_window_export.h"
 
@@ -16,7 +16,7 @@
 
 // StubWindow is useful for tests, as well as implementations that only care
 // about bounds.
-class STUB_WINDOW_EXPORT StubWindow : public PlatformWindowBase {
+class STUB_WINDOW_EXPORT StubWindow : public PlatformWindow {
  public:
   explicit StubWindow(PlatformWindowDelegate* delegate,
                       bool use_default_accelerated_widget = true,
diff --git a/ui/platform_window/win/win_window.h b/ui/platform_window/win/win_window.h
index b073cfd..ab2910c 100644
--- a/ui/platform_window/win/win_window.h
+++ b/ui/platform_window/win/win_window.h
@@ -9,15 +9,15 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "ui/gfx/win/window_impl.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_delegate.h"
-#include "ui/platform_window/platform_window_win.h"
 #include "ui/platform_window/win/win_window_export.h"
 
 #include <windows.h>
 
 namespace ui {
 
-class WIN_WINDOW_EXPORT WinWindow : public PlatformWindowWin,
+class WIN_WINDOW_EXPORT WinWindow : public PlatformWindow,
                                     public gfx::WindowImpl {
  public:
   WinWindow(PlatformWindowDelegate* delegate, const gfx::Rect& bounds);
diff --git a/ui/platform_window/x11/x11_window.cc b/ui/platform_window/x11/x11_window.cc
index 72bb953..d6e17cde 100644
--- a/ui/platform_window/x11/x11_window.cc
+++ b/ui/platform_window/x11/x11_window.cc
@@ -18,7 +18,7 @@
 #include "ui/gfx/x/x11.h"
 #include "ui/platform_window/common/platform_window_defaults.h"
 #include "ui/platform_window/extensions/workspace_extension_delegate.h"
-#include "ui/platform_window/platform_window_delegate_linux.h"
+#include "ui/platform_window/extensions/x11_extension_delegate.h"
 #include "ui/platform_window/x11/x11_window_manager.h"
 
 #if defined(USE_OZONE)
@@ -91,7 +91,7 @@
 
 }  // namespace
 
-X11Window::X11Window(PlatformWindowDelegateLinux* platform_window_delegate)
+X11Window::X11Window(PlatformWindowDelegate* platform_window_delegate)
     : platform_window_delegate_(platform_window_delegate) {
   // Set a class property key, which allows |this| to be used for interactive
   // events, e.g. move or resize.
@@ -100,6 +100,7 @@
   // Set extensions property key that extends the interface of this platform
   // implementation.
   SetWorkspaceExtension(this, static_cast<WorkspaceExtension*>(this));
+  SetX11Extension(this, static_cast<X11Extension*>(this));
 }
 
 X11Window::~X11Window() {
@@ -116,6 +117,7 @@
   config.bounds.set_size(adjusted_size_in_pixels);
 
   workspace_extension_delegate_ = properties.workspace_extension_delegate;
+  x11_extension_delegate_ = properties.x11_extension_delegate;
 
   Init(config);
 }
@@ -325,14 +327,6 @@
   XWindow::Deactivate();
 }
 
-bool X11Window::IsSyncExtensionAvailable() const {
-  return ui::IsSyncExtensionAvailable();
-}
-
-void X11Window::OnCompleteSwapAfterResize() {
-  XWindow::NotifySwapAfterResize();
-}
-
 void X11Window::SetUseNativeFrame(bool use_native_frame) {
   XWindow::SetUseNativeFrame(use_native_frame);
 }
@@ -404,23 +398,11 @@
   XWindow::SetFlashFrameHint(flash_frame);
 }
 
-gfx::Rect X11Window::GetXRootWindowOuterBounds() const {
-  return XWindow::GetOutterBounds();
-}
-
-bool X11Window::ContainsPointInXRegion(const gfx::Point& point) const {
-  return XWindow::ContainsPointInRegion(point);
-}
-
 void X11Window::SetShape(std::unique_ptr<ShapeRects> native_shape,
                          const gfx::Transform& transform) {
   return XWindow::SetXWindowShape(std::move(native_shape), transform);
 }
 
-void X11Window::SetOpacityForXWindow(float opacity) {
-  XWindow::SetXWindowOpacity(opacity);
-}
-
 void X11Window::SetAspectRatio(const gfx::SizeF& aspect_ratio) {
   XWindow::SetXWindowAspectRatio(aspect_ratio);
 }
@@ -441,8 +423,8 @@
   return ui::XVisualManager::GetInstance()->ArgbVisualAvailable();
 }
 
-void X11Window::LowerXWindow() {
-  XWindow::LowerWindow();
+void X11Window::SetOpacity(float opacity) {
+  XWindow::SetXWindowOpacity(opacity);
 }
 
 std::string X11Window::GetWorkspace() const {
@@ -464,6 +446,30 @@
   workspace_extension_delegate_ = delegate;
 }
 
+bool X11Window::IsSyncExtensionAvailable() const {
+  return ui::IsSyncExtensionAvailable();
+}
+
+void X11Window::OnCompleteSwapAfterResize() {
+  XWindow::NotifySwapAfterResize();
+}
+
+gfx::Rect X11Window::GetXRootWindowOuterBounds() const {
+  return XWindow::GetOutterBounds();
+}
+
+bool X11Window::ContainsPointInXRegion(const gfx::Point& point) const {
+  return XWindow::ContainsPointInRegion(point);
+}
+
+void X11Window::LowerXWindow() {
+  XWindow::LowerWindow();
+}
+
+void X11Window::SetX11ExtensionDelegate(X11ExtensionDelegate* delegate) {
+  x11_extension_delegate_ = delegate;
+}
+
 bool X11Window::HandleAsAtkEvent(XEvent* xev) {
 #if !BUILDFLAG(USE_ATK)
   // TODO(crbug.com/1014934): Support ATK in Ozone/X11.
@@ -471,10 +477,11 @@
   return false;
 #else
   DCHECK(xev);
-  if (xev->type != KeyPress && xev->type != KeyRelease)
+  if (!x11_extension_delegate_ ||
+      (xev->type != KeyPress && xev->type != KeyRelease))
     return false;
   auto atk_key_event = AtkKeyEventFromXEvent(xev);
-  return platform_window_delegate_->OnAtkKeyEvent(atk_key_event.get());
+  return x11_extension_delegate_->OnAtkKeyEvent(atk_key_event.get());
 #endif
 }
 
@@ -553,11 +560,13 @@
 }
 
 void X11Window::OnXWindowMapped() {
-  platform_window_delegate_->OnXWindowMapped();
+  if (x11_extension_delegate_)
+    x11_extension_delegate_->OnXWindowMapped();
 }
 
 void X11Window::OnXWindowUnmapped() {
-  platform_window_delegate_->OnXWindowUnmapped();
+  if (x11_extension_delegate_)
+    x11_extension_delegate_->OnXWindowUnmapped();
 }
 
 void X11Window::OnXWindowWorkspaceChanged() {
@@ -566,7 +575,8 @@
 }
 
 void X11Window::OnXWindowLostPointerGrab() {
-  platform_window_delegate_->OnLostMouseGrab();
+  if (x11_extension_delegate_)
+    x11_extension_delegate_->OnLostMouseGrab();
 }
 
 void X11Window::OnXWindowEvent(ui::Event* event) {
@@ -623,7 +633,8 @@
 
 void X11Window::GetWindowMaskForXWindow(const gfx::Size& size,
                                         SkPath* window_mask) {
-  platform_window_delegate_->GetWindowMask(size, window_mask);
+  if (x11_extension_delegate_)
+    x11_extension_delegate_->GetWindowMask(size, window_mask);
 }
 
 void X11Window::DispatchHostWindowDragMovement(
diff --git a/ui/platform_window/x11/x11_window.h b/ui/platform_window/x11/x11_window.h
index 3300bfd..63e2adc 100644
--- a/ui/platform_window/x11/x11_window.h
+++ b/ui/platform_window/x11/x11_window.h
@@ -9,13 +9,15 @@
 #include "ui/base/x/x11_window.h"
 #include "ui/events/platform/platform_event_dispatcher.h"
 #include "ui/platform_window/extensions/workspace_extension.h"
+#include "ui/platform_window/extensions/x11_extension.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
 #include "ui/platform_window/platform_window_init_properties.h"
-#include "ui/platform_window/platform_window_linux.h"
 #include "ui/platform_window/x11/x11_window_export.h"
 
 namespace ui {
 
+class X11ExtensionDelegate;
 class LocatedEvent;
 class WorkspaceExtensionDelegate;
 
@@ -32,13 +34,14 @@
 };
 
 // PlatformWindow implementation for X11. PlatformEvents are XEvents.
-class X11_WINDOW_EXPORT X11Window : public PlatformWindowLinux,
+class X11_WINDOW_EXPORT X11Window : public PlatformWindow,
                                     public WmMoveResizeHandler,
                                     public XWindow,
                                     public PlatformEventDispatcher,
-                                    public WorkspaceExtension {
+                                    public WorkspaceExtension,
+                                    public X11Extension {
  public:
-  explicit X11Window(PlatformWindowDelegateLinux* platform_window_delegate);
+  explicit X11Window(PlatformWindowDelegate* platform_window_delegate);
   ~X11Window() override;
 
   void Initialize(PlatformWindowInitProperties properties);
@@ -72,8 +75,6 @@
   PlatformWindowState GetPlatformWindowState() const override;
   void Activate() override;
   void Deactivate() override;
-  bool IsSyncExtensionAvailable() const override;
-  void OnCompleteSwapAfterResize() override;
   void SetUseNativeFrame(bool use_native_frame) override;
   bool ShouldUseNativeFrame() const override;
   void SetCursor(PlatformCursor cursor) override;
@@ -87,17 +88,14 @@
   void StackAbove(gfx::AcceleratedWidget widget) override;
   void StackAtTop() override;
   void FlashFrame(bool flash_frame) override;
-  gfx::Rect GetXRootWindowOuterBounds() const override;
-  bool ContainsPointInXRegion(const gfx::Point& point) const override;
   void SetShape(std::unique_ptr<ShapeRects> native_shape,
                 const gfx::Transform& transform) override;
-  void SetOpacityForXWindow(float opacity) override;
   void SetAspectRatio(const gfx::SizeF& aspect_ratio) override;
   void SetWindowIcons(const gfx::ImageSkia& window_icon,
                       const gfx::ImageSkia& app_icon) override;
   void SizeConstraintsChanged() override;
   bool IsTranslucentWindowOpacitySupported() const override;
-  void LowerXWindow() override;
+  void SetOpacity(float opacity) override;
 
   // WorkspaceExtension:
   std::string GetWorkspace() const override;
@@ -106,8 +104,16 @@
   void SetWorkspaceExtensionDelegate(
       WorkspaceExtensionDelegate* delegate) override;
 
+  // X11Extension:
+  bool IsSyncExtensionAvailable() const override;
+  void OnCompleteSwapAfterResize() override;
+  gfx::Rect GetXRootWindowOuterBounds() const override;
+  bool ContainsPointInXRegion(const gfx::Point& point) const override;
+  void LowerXWindow() override;
+  void SetX11ExtensionDelegate(X11ExtensionDelegate* delegate) override;
+
  protected:
-  PlatformWindowDelegateLinux* platform_window_delegate() const {
+  PlatformWindowDelegate* platform_window_delegate() const {
     return platform_window_delegate_;
   }
 
@@ -164,12 +170,14 @@
   // Stores current state of this window.
   PlatformWindowState state_ = PlatformWindowState::kUnknown;
 
-  PlatformWindowDelegateLinux* const platform_window_delegate_;
+  PlatformWindowDelegate* const platform_window_delegate_;
 
   XEventDelegate* x_event_delegate_ = nullptr;
 
   WorkspaceExtensionDelegate* workspace_extension_delegate_ = nullptr;
 
+  X11ExtensionDelegate* x11_extension_delegate_ = nullptr;
+
   // Tells if the window got a ::Close call.
   bool is_shutting_down_ = false;
 
diff --git a/ui/shell_dialogs/BUILD.gn b/ui/shell_dialogs/BUILD.gn
index 999ca8b..6501b6ea 100644
--- a/ui/shell_dialogs/BUILD.gn
+++ b/ui/shell_dialogs/BUILD.gn
@@ -12,31 +12,52 @@
   import("//build/config/mac/rules.gni")
 }
 
+# Reset sources_assignment_filter for the BUILD.gn file to prevent
+# regression during the migration of Chromium away from the feature.
+# See build/no_sources_assignment_filter.md for more information.
+# TODO(crbug.com/1018739): remove this when migration is done.
+set_sources_assignment_filter([])
+
 jumbo_component("shell_dialogs") {
   sources = [
     "base_shell_dialog.cc",
     "base_shell_dialog.h",
-    "base_shell_dialog_win.cc",
-    "base_shell_dialog_win.h",
-    "execute_select_file_win.cc",
-    "execute_select_file_win.h",
     "select_file_dialog.cc",
     "select_file_dialog.h",
     "select_file_dialog_factory.cc",
     "select_file_dialog_factory.h",
-    "select_file_dialog_mac.h",
-    "select_file_dialog_mac.mm",
-    "select_file_dialog_win.cc",
-    "select_file_dialog_win.h",
     "select_file_policy.cc",
     "select_file_policy.h",
     "selected_file_info.cc",
     "selected_file_info.h",
-    "shell_dialog_linux.cc",
-    "shell_dialog_linux.h",
     "shell_dialogs_export.h",
   ]
 
+  if (is_linux) {
+    sources += [
+      "shell_dialog_linux.cc",
+      "shell_dialog_linux.h",
+    ]
+  }
+
+  if (is_mac) {
+    sources += [
+      "select_file_dialog_mac.h",
+      "select_file_dialog_mac.mm",
+    ]
+  }
+
+  if (is_win) {
+    sources += [
+      "base_shell_dialog_win.cc",
+      "base_shell_dialog_win.h",
+      "execute_select_file_win.cc",
+      "execute_select_file_win.h",
+      "select_file_dialog_win.cc",
+      "select_file_dialog_win.h",
+    ]
+  }
+
   defines = [ "SHELL_DIALOGS_IMPLEMENTATION" ]
 
   deps = [
@@ -90,13 +111,21 @@
 test("shell_dialogs_unittests") {
   testonly = true
   sources = [
-    "execute_select_file_win_unittest.cc",
     "run_all_unittests.cc",
-    "select_file_dialog_mac_unittest.mm",
     "select_file_dialog_unittest.cc",
-    "select_file_dialog_win_unittest.cc",
   ]
 
+  if (is_mac) {
+    sources += [ "select_file_dialog_mac_unittest.mm" ]
+  }
+
+  if (is_win) {
+    sources += [
+      "execute_select_file_win_unittest.cc",
+      "select_file_dialog_win_unittest.cc",
+    ]
+  }
+
   deps = [
     ":shell_dialogs",
     "//base",
diff --git a/ui/snapshot/BUILD.gn b/ui/snapshot/BUILD.gn
index 5ceaabcb..03728fa 100644
--- a/ui/snapshot/BUILD.gn
+++ b/ui/snapshot/BUILD.gn
@@ -6,27 +6,43 @@
 import("//build/config/ui.gni")
 import("//testing/test.gni")
 
+# Reset sources_assignment_filter for the BUILD.gn file to prevent
+# regression during the migration of Chromium away from the feature.
+# See build/no_sources_assignment_filter.md for more information.
+# TODO(crbug.com/1018739): remove this when migration is done.
+set_sources_assignment_filter([])
+
 jumbo_component("snapshot") {
   sources = [
     "screenshot_grabber.cc",
     "screenshot_grabber.h",
     "snapshot.cc",
     "snapshot.h",
-    "snapshot_android.cc",
-    "snapshot_async.cc",
-    "snapshot_async.h",
-    "snapshot_aura.cc",
-    "snapshot_aura.h",
-    "snapshot_ios.mm",
-    "snapshot_mac.mm",
-    "snapshot_win.cc",
   ]
 
+  if (is_android) {
+    sources += [ "snapshot_android.cc" ]
+  }
+
+  if (is_mac) {
+    sources += [ "snapshot_mac.mm" ]
+  }
+
+  if (is_win) {
+    sources += [
+      "snapshot_win.cc",
+      "snapshot_win.h",
+    ]
+  }
+
+  if (is_ios) {
+    sources += [ "snapshot_ios.mm" ]
+  }
+
   defines = [ "SNAPSHOT_IMPLEMENTATION" ]
 
   deps = [
     ":snapshot_export",
-    ":snapshot_win",
     "//base",
     "//components/viz/common",
     "//skia",
@@ -41,27 +57,25 @@
   }
 
   if (use_aura || is_android) {
+    sources += [
+      "snapshot_async.cc",
+      "snapshot_async.h",
+    ]
     deps += [
       "//cc",
       "//gpu/command_buffer/common",
     ]
-  } else {
-    sources -= [
-      "snapshot_async.cc",
-      "snapshot_async.h",
-    ]
   }
 
   if (use_aura) {
+    sources += [
+      "snapshot_aura.cc",
+      "snapshot_aura.h",
+    ]
     deps += [
       "//ui/aura",
       "//ui/compositor",
     ]
-  } else {
-    sources -= [
-      "snapshot_aura.cc",
-      "snapshot_aura.h",
-    ]
   }
 
   if (is_mac) {
@@ -72,16 +86,6 @@
   }
 }
 
-jumbo_source_set("snapshot_win") {
-  sources = [
-    "snapshot_win.h",
-  ]
-  deps = [
-    ":snapshot_export",
-  ]
-  visibility = [ ":*" ]
-}
-
 jumbo_source_set("snapshot_export") {
   sources = [
     "snapshot_export.h",
@@ -91,11 +95,13 @@
 
 test("snapshot_unittests") {
   sources = [
-    "snapshot_aura_unittest.cc",
-    "snapshot_mac_unittest.mm",
     "test/run_all_unittests.cc",
   ]
 
+  if (is_mac) {
+    sources += [ "snapshot_mac_unittest.mm" ]
+  }
+
   deps = [
     ":snapshot",
     "//base",
@@ -112,13 +118,12 @@
   ]
 
   if (use_aura) {
+    sources += [ "snapshot_aura_unittest.cc" ]
     deps += [
       "//ui/aura:test_support",
       "//ui/compositor",
       "//ui/compositor:test_support",
       "//ui/wm",
     ]
-  } else {
-    sources -= [ "snapshot_aura_unittest.cc" ]
   }
 }
diff --git a/ui/views/controls/webview/BUILD.gn b/ui/views/controls/webview/BUILD.gn
index 51f3e4d..7316d518 100644
--- a/ui/views/controls/webview/BUILD.gn
+++ b/ui/views/controls/webview/BUILD.gn
@@ -4,12 +4,16 @@
 
 import("//build/config/jumbo.gni")
 
+# Reset sources_assignment_filter for the BUILD.gn file to prevent
+# regression during the migration of Chromium away from the feature.
+# See build/no_sources_assignment_filter.md for more information.
+# TODO(crbug.com/1018739): remove this when migration is done.
+set_sources_assignment_filter([])
+
 jumbo_component("webview") {
   sources = [
     "unhandled_keyboard_event_handler.cc",
     "unhandled_keyboard_event_handler.h",
-    "unhandled_keyboard_event_handler_mac.mm",
-    "unhandled_keyboard_event_handler_win.cc",
     "web_contents_set_background_color.cc",
     "web_contents_set_background_color.h",
     "web_dialog_view.cc",
@@ -19,6 +23,14 @@
     "webview_export.h",
   ]
 
+  if (is_mac) {
+    sources += [ "unhandled_keyboard_event_handler_mac.mm" ]
+  }
+
+  if (is_win) {
+    sources += [ "unhandled_keyboard_event_handler_win.cc" ]
+  }
+
   defines = [ "WEBVIEW_IMPLEMENTATION" ]
 
   if (is_mac) {
diff --git a/ui/views/examples/native_theme_example.cc b/ui/views/examples/native_theme_example.cc
index 6eb436c..3476aa98 100644
--- a/ui/views/examples/native_theme_example.cc
+++ b/ui/views/examples/native_theme_example.cc
@@ -107,6 +107,7 @@
                  COLOR_LABEL_ARGS(kColorId_MenuItemAlertBackgroundColor));
   InsertColorRow(layout, COLOR_LABEL_ARGS(kColorId_LabelEnabledColor));
   InsertColorRow(layout, COLOR_LABEL_ARGS(kColorId_LabelDisabledColor));
+  InsertColorRow(layout, COLOR_LABEL_ARGS(kColorId_LabelSecondaryColor));
   InsertColorRow(layout, COLOR_LABEL_ARGS(kColorId_LabelTextSelectionColor));
   InsertColorRow(
       layout, COLOR_LABEL_ARGS(kColorId_LabelTextSelectionBackgroundFocused));
diff --git a/ui/views/style/typography_provider.cc b/ui/views/style/typography_provider.cc
index 44bf269..cd9417d 100644
--- a/ui/views/style/typography_provider.cc
+++ b/ui/views/style/typography_provider.cc
@@ -106,6 +106,8 @@
     return ui::NativeTheme::kColorId_LinkEnabled;
   if (context == style::CONTEXT_BUTTON_MD)
     return ui::NativeTheme::kColorId_ButtonEnabledColor;
+  if (context == style::CONTEXT_LABEL && style == style::STYLE_SECONDARY)
+    return ui::NativeTheme::kColorId_LabelSecondaryColor;
   if (context == style::CONTEXT_MESSAGE_BOX_BODY_TEXT &&
       (style == style::STYLE_PRIMARY || style == style::STYLE_SECONDARY))
     return ui::NativeTheme::kColorId_DialogForeground;
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
index 2b58b0f..d159e51 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
@@ -13,7 +13,7 @@
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_handler/wm_drag_handler.h"
 #include "ui/platform_window/platform_window_handler/wm_drop_handler.h"
 #include "ui/views/test/views_test_base.h"
@@ -25,8 +25,7 @@
 namespace views {
 
 namespace {
-class FakePlatformWindow : public ui::PlatformWindowBase,
-                           public ui::WmDragHandler {
+class FakePlatformWindow : public ui::PlatformWindow, public ui::WmDragHandler {
  public:
   FakePlatformWindow() { SetWmDragHandler(this, this); }
   ~FakePlatformWindow() override = default;
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
index fef0b065..81640f5e 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
@@ -11,9 +11,9 @@
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 #include "ui/events/event.h"
+#include "ui/platform_window/extensions/x11_extension.h"
 #include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
 #include "ui/platform_window/platform_window_init_properties.h"
-#include "ui/platform_window/platform_window_linux.h"
 #include "ui/views/linux_ui/linux_ui.h"
 #include "ui/views/views_delegate.h"
 #include "ui/views/widget/desktop_aura/window_event_filter_linux.h"
@@ -124,16 +124,25 @@
 }
 
 gfx::Rect DesktopWindowTreeHostLinux::GetXRootWindowOuterBounds() const {
-  return GetPlatformWindowLinux()->GetXRootWindowOuterBounds();
+  // TODO(msisov): must be removed as soon as all X11 low-level bits are moved
+  // to Ozone.
+  DCHECK(GetX11Extension());
+  return GetX11Extension()->GetXRootWindowOuterBounds();
 }
 
 bool DesktopWindowTreeHostLinux::ContainsPointInXRegion(
     const gfx::Point& point) const {
-  return GetPlatformWindowLinux()->ContainsPointInXRegion(point);
+  // TODO(msisov): must be removed as soon as all X11 low-level bits are moved
+  // to Ozone.
+  DCHECK(GetX11Extension());
+  return GetX11Extension()->ContainsPointInXRegion(point);
 }
 
 void DesktopWindowTreeHostLinux::LowerXWindow() {
-  GetPlatformWindowLinux()->LowerXWindow();
+  // TODO(msisov): must be removed as soon as all X11 low-level bits are moved
+  // to Ozone.
+  DCHECK(GetX11Extension());
+  GetX11Extension()->LowerXWindow();
 }
 
 base::OnceClosure DesktopWindowTreeHostLinux::DisableEventListening() {
@@ -153,7 +162,7 @@
 void DesktopWindowTreeHostLinux::Init(const Widget::InitParams& params) {
   DesktopWindowTreeHostPlatform::Init(params);
 
-  if (GetPlatformWindowLinux()->IsSyncExtensionAvailable()) {
+  if (GetX11Extension() && GetX11Extension()->IsSyncExtensionAvailable()) {
     compositor_observer_ = std::make_unique<SwapWithNewSizeObserverHelper>(
         compositor(),
         base::BindRepeating(
@@ -170,12 +179,6 @@
   DesktopWindowTreeHostPlatform::OnNativeWidgetCreated(params);
 }
 
-void DesktopWindowTreeHostLinux::SetOpacity(float opacity) {
-  DesktopWindowTreeHostPlatform::SetOpacity(opacity);
-  // Note that this is no-op for Wayland.
-  GetPlatformWindowLinux()->SetOpacityForXWindow(opacity);
-}
-
 base::flat_map<std::string, std::string>
 DesktopWindowTreeHostLinux::GetKeyboardLayoutMap() {
   if (views::LinuxUI::instance())
@@ -338,23 +341,31 @@
   properties->wm_role_name = params.wm_role_name;
 
   properties->x_visual_id = pending_x_visual_id_;
+
+  DCHECK(!properties->x11_extension_delegate);
+  properties->x11_extension_delegate = this;
 }
 
 void DesktopWindowTreeHostLinux::OnCompleteSwapWithNewSize(
     const gfx::Size& size) {
-  GetPlatformWindowLinux()->OnCompleteSwapAfterResize();
+  if (GetX11Extension())
+    GetX11Extension()->OnCompleteSwapAfterResize();
 }
 
 void DesktopWindowTreeHostLinux::CreateNonClientEventFilter() {
   DCHECK(!non_client_window_event_filter_);
   non_client_window_event_filter_ = std::make_unique<WindowEventFilterLinux>(
-      this, GetWmMoveResizeHandler(*GetPlatformWindowLinux()));
+      this, GetWmMoveResizeHandler(*platform_window()));
 }
 
 void DesktopWindowTreeHostLinux::DestroyNonClientEventFilter() {
   non_client_window_event_filter_.reset();
 }
 
+void DesktopWindowTreeHostLinux::OnXWindowMapped() {}
+
+void DesktopWindowTreeHostLinux::OnXWindowUnmapped() {}
+
 void DesktopWindowTreeHostLinux::GetWindowMask(const gfx::Size& size,
                                                SkPath* window_mask) {
   DCHECK(window_mask);
@@ -376,13 +387,12 @@
     targeter_for_modal_.reset();
 }
 
-const ui::PlatformWindowLinux*
-DesktopWindowTreeHostLinux::GetPlatformWindowLinux() const {
-  return static_cast<const ui::PlatformWindowLinux*>(platform_window());
+ui::X11Extension* DesktopWindowTreeHostLinux::GetX11Extension() {
+  return ui::GetX11Extension(*(platform_window()));
 }
 
-ui::PlatformWindowLinux* DesktopWindowTreeHostLinux::GetPlatformWindowLinux() {
-  return static_cast<ui::PlatformWindowLinux*>(platform_window());
+const ui::X11Extension* DesktopWindowTreeHostLinux::GetX11Extension() const {
+  return ui::GetX11Extension(*(platform_window()));
 }
 
 std::list<gfx::AcceleratedWidget>& DesktopWindowTreeHostLinux::open_windows() {
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
index be4cf274..99cc4190 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
@@ -10,6 +10,7 @@
 #include "ui/aura/scoped_window_targeter.h"
 #include "ui/base/buildflags.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/platform_window/extensions/x11_extension_delegate.h"
 #include "ui/views/views_export.h"
 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h"
 
@@ -20,7 +21,7 @@
 }  // namespace aura
 
 namespace ui {
-class PlatformWindowLinux;
+class X11Extension;
 }  // namespace ui
 
 namespace views {
@@ -29,7 +30,8 @@
 
 // Contains Linux specific implementation.
 class VIEWS_EXPORT DesktopWindowTreeHostLinux
-    : public DesktopWindowTreeHostPlatform {
+    : public DesktopWindowTreeHostPlatform,
+      public ui::X11ExtensionDelegate {
  public:
   DesktopWindowTreeHostLinux(
       internal::NativeWidgetDelegate* native_widget_delegate,
@@ -77,18 +79,14 @@
   // Overridden from DesktopWindowTreeHost:
   void Init(const Widget::InitParams& params) override;
   void OnNativeWidgetCreated(const Widget::InitParams& params) override;
-  void SetOpacity(float opacity) override;
   base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
   void InitModalType(ui::ModalType modal_type) override;
 
-  // PlatformWindowDelegateBase:
+  // PlatformWindowDelegate:
   void DispatchEvent(ui::Event* event) override;
   void OnClosed() override;
   void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override;
   void OnActivationChanged(bool active) override;
-#if BUILDFLAG(USE_ATK)
-  bool OnAtkKeyEvent(AtkKeyEventStruct* atk_key_event) override;
-#endif
 
  private:
   FRIEND_TEST_ALL_PREFIXES(DesktopWindowTreeHostLinuxTest, HitTest);
@@ -108,15 +106,20 @@
   void CreateNonClientEventFilter();
   void DestroyNonClientEventFilter();
 
-  // PlatformWindowDelegateLinux overrides:
+  // X11ExtensionDelegate overrides:
+  void OnXWindowMapped() override;
+  void OnXWindowUnmapped() override;
   void GetWindowMask(const gfx::Size& size, SkPath* window_mask) override;
   void OnLostMouseGrab() override;
+#if BUILDFLAG(USE_ATK)
+  bool OnAtkKeyEvent(AtkKeyEventStruct* atk_key_event) override;
+#endif
 
   // Enables event listening after closing |dialog|.
   void EnableEventListening();
 
-  const ui::PlatformWindowLinux* GetPlatformWindowLinux() const;
-  ui::PlatformWindowLinux* GetPlatformWindowLinux();
+  ui::X11Extension* GetX11Extension();
+  const ui::X11Extension* GetX11Extension() const;
 
   // See comment for variable open_windows_.
   static std::list<gfx::AcceleratedWidget>& open_windows();
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc
index ae0e0f2..2eb29b2 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc
@@ -7,7 +7,7 @@
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window_tree_host_platform.h"
 #include "ui/base/hit_test.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
 #include "ui/views/test/views_interactive_ui_test_base.h"
 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
@@ -41,7 +41,7 @@
 class FakeWmMoveResizeHandler : public ui::WmMoveResizeHandler {
  public:
   using SetBoundsCallback = base::RepeatingCallback<void(gfx::Rect)>;
-  explicit FakeWmMoveResizeHandler(ui::PlatformWindowBase* window)
+  explicit FakeWmMoveResizeHandler(ui::PlatformWindow* window)
       : platform_window_(window), hittest_(-1) {}
   ~FakeWmMoveResizeHandler() override = default;
 
@@ -66,7 +66,7 @@
   }
 
  private:
-  ui::PlatformWindowBase* platform_window_;
+  ui::PlatformWindow* platform_window_;
   gfx::Rect bounds_;
 
   int hittest_ = -1;
@@ -157,7 +157,7 @@
                                    desktop_native_widget_aura) {}
   ~TestDesktopWindowTreeHostLinux() override = default;
 
-  // PlatformWindowDelegateBase:
+  // PlatformWindowDelegate:
   // Instead of making these tests friends of the host, override the dispatch
   // method to make it public and nothing else.
   void DispatchEvent(ui::Event* event) override {
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
index 58bdda41..a0424e9 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
@@ -16,7 +16,7 @@
 #include "ui/display/screen.h"
 #include "ui/gfx/geometry/dip_util.h"
 #include "ui/platform_window/extensions/workspace_extension.h"
-#include "ui/platform_window/platform_window_base.h"
+#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 #include "ui/views/corewm/tooltip_aura.h"
 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h"
@@ -516,9 +516,7 @@
 
 void DesktopWindowTreeHostPlatform::SetVisibilityChangedAnimationsEnabled(
     bool value) {
-#if defined(OS_WIN)
   platform_window()->SetVisibilityChangedAnimationsEnabled(value);
-#endif
 }
 
 NonClientFrameView* DesktopWindowTreeHostPlatform::CreateNonClientFrameView() {
@@ -574,6 +572,7 @@
 
 void DesktopWindowTreeHostPlatform::SetOpacity(float opacity) {
   GetContentWindow()->layer()->SetOpacity(opacity);
+  platform_window()->SetOpacity(opacity);
 }
 
 void DesktopWindowTreeHostPlatform::SetAspectRatio(
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
index 1c599a46..89beb8d 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
@@ -102,7 +102,7 @@
   void ShowImpl() override;
   void HideImpl() override;
 
-  // PlatformWindowDelegateBase:
+  // PlatformWindowDelegate:
   void OnClosed() override;
   void OnWindowStateChanged(ui::PlatformWindowState new_state) override;
   void OnCloseRequest() override;
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
index 47fc170..9db2bb9 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
@@ -51,11 +51,11 @@
  private:
   friend class DesktopWindowTreeHostX11HighDPITest;
 
-  // PlatformWindowDelegate overrides:
+  // X11ExtensionDelegate overrides:
   //
-  // DWTHX11 temporarily overrides the PlatformWindowDelegate methods instead of
-  // underlying DWTHPlatform and WTHPlatform. Eventually, these will be removed
-  // from here as we progress in https://crbug.com/990756.
+  // DWTHX11 temporarily overrides the X11ExtensionDelegate
+  // methods instead of underlying DWTHPlatform and WTHPlatform. Eventually,
+  // these will be removed from here as we progress in https://crbug.com/990756.
   void OnXWindowMapped() override;
   void OnXWindowUnmapped() override;
 
diff --git a/weblayer/BUILD.gn b/weblayer/BUILD.gn
index f2ce21a8..ec0ebf5b 100644
--- a/weblayer/BUILD.gn
+++ b/weblayer/BUILD.gn
@@ -153,6 +153,8 @@
     "browser/profile_impl.h",
     "browser/ssl_blocking_page.cc",
     "browser/ssl_blocking_page.h",
+    "browser/ssl_error_controller_client.cc",
+    "browser/ssl_error_controller_client.h",
     "browser/ssl_error_handler.cc",
     "browser/ssl_error_handler.h",
     "browser/ssl_host_state_delegate_impl.cc",
diff --git a/weblayer/browser/ssl_blocking_page.cc b/weblayer/browser/ssl_blocking_page.cc
index 45253c9..038afd1 100644
--- a/weblayer/browser/ssl_blocking_page.cc
+++ b/weblayer/browser/ssl_blocking_page.cc
@@ -7,81 +7,18 @@
 #include <memory>
 #include <utility>
 
-#include "components/security_interstitials/content/security_interstitial_controller_client.h"
+#include "base/strings/string_number_conversions.h"
 #include "components/security_interstitials/core/metrics_helper.h"
 #include "components/security_interstitials/core/ssl_error_options_mask.h"
 #include "components/security_interstitials/core/ssl_error_ui.h"
-#include "content/public/browser/browser_context.h"
 #include "content/public/browser/interstitial_page.h"
 #include "content/public/browser/interstitial_page_delegate.h"
 #include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/ssl_host_state_delegate.h"
 #include "content/public/browser/ssl_status.h"
-#include "content/public/browser/web_contents.h"
-#include "net/base/net_errors.h"
-#include "weblayer/browser/i18n_util.h"
-#include "weblayer/browser/tab_impl.h"
-#include "weblayer/public/error_page_delegate.h"
+#include "weblayer/browser/ssl_error_controller_client.h"
 
 namespace weblayer {
 
-namespace {
-
-// A stripped-down version of the class by the same name in
-// //chrome/browser/ssl, which provides basic functionality for interacting with
-// the SSL interstitial.
-class SSLErrorControllerClient
-    : public security_interstitials::SecurityInterstitialControllerClient {
- public:
-  SSLErrorControllerClient(
-      content::WebContents* web_contents,
-      int cert_error,
-      const net::SSLInfo& ssl_info,
-      const GURL& request_url,
-      std::unique_ptr<security_interstitials::MetricsHelper> metrics_helper)
-      : security_interstitials::SecurityInterstitialControllerClient(
-            web_contents,
-            std::move(metrics_helper),
-            nullptr /*prefs*/,
-            i18n::GetApplicationLocale(),
-            GURL("about:blank") /*default_safe_page*/),
-        cert_error_(cert_error),
-        ssl_info_(ssl_info),
-        request_url_(request_url) {}
-
-  ~SSLErrorControllerClient() override = default;
-
-  void GoBack() override {
-    ErrorPageDelegate* delegate =
-        TabImpl::FromWebContents(web_contents_)->error_page_delegate();
-    if (delegate && delegate->OnBackToSafety())
-      return;
-
-    SecurityInterstitialControllerClient::GoBackAfterNavigationCommitted();
-  }
-
-  void Proceed() override {
-    web_contents_->GetBrowserContext()->GetSSLHostStateDelegate()->AllowCert(
-        request_url_.host(), *ssl_info_.cert.get(), cert_error_);
-    Reload();
-  }
-
-  void OpenUrlInNewForegroundTab(const GURL& url) override {
-    // For now WebLayer doesn't support multiple tabs, so just open the Learn
-    // More link in the current tab.
-    OpenUrlInCurrentTab(url);
-  }
-
- private:
-  const int cert_error_;
-  const net::SSLInfo ssl_info_;
-  const GURL request_url_;
-
-  DISALLOW_COPY_AND_ASSIGN(SSLErrorControllerClient);
-};
-
-}  // namespace
-
 // static
 const content::InterstitialPageDelegate::TypeID
     SSLBlockingPage::kTypeForTesting = &SSLBlockingPage::kTypeForTesting;
diff --git a/weblayer/browser/ssl_error_controller_client.cc b/weblayer/browser/ssl_error_controller_client.cc
new file mode 100644
index 0000000..e8575d1
--- /dev/null
+++ b/weblayer/browser/ssl_error_controller_client.cc
@@ -0,0 +1,54 @@
+// Copyright 2019 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 "weblayer/browser/ssl_error_controller_client.h"
+
+#include "components/security_interstitials/core/metrics_helper.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/ssl_host_state_delegate.h"
+#include "content/public/browser/web_contents.h"
+#include "weblayer/browser/i18n_util.h"
+#include "weblayer/browser/tab_impl.h"
+#include "weblayer/public/error_page_delegate.h"
+
+namespace weblayer {
+
+SSLErrorControllerClient::SSLErrorControllerClient(
+    content::WebContents* web_contents,
+    int cert_error,
+    const net::SSLInfo& ssl_info,
+    const GURL& request_url,
+    std::unique_ptr<security_interstitials::MetricsHelper> metrics_helper)
+    : security_interstitials::SecurityInterstitialControllerClient(
+          web_contents,
+          std::move(metrics_helper),
+          nullptr /*prefs*/,
+          i18n::GetApplicationLocale(),
+          GURL("about:blank") /*default_safe_page*/),
+      cert_error_(cert_error),
+      ssl_info_(ssl_info),
+      request_url_(request_url) {}
+
+void SSLErrorControllerClient::GoBack() {
+  ErrorPageDelegate* delegate =
+      TabImpl::FromWebContents(web_contents_)->error_page_delegate();
+  if (delegate && delegate->OnBackToSafety())
+    return;
+
+  SecurityInterstitialControllerClient::GoBackAfterNavigationCommitted();
+}
+
+void SSLErrorControllerClient::Proceed() {
+  web_contents_->GetBrowserContext()->GetSSLHostStateDelegate()->AllowCert(
+      request_url_.host(), *ssl_info_.cert.get(), cert_error_);
+  Reload();
+}
+
+void SSLErrorControllerClient::OpenUrlInNewForegroundTab(const GURL& url) {
+  // For now WebLayer doesn't support multiple tabs, so just open the Learn
+  // More link in the current tab.
+  OpenUrlInCurrentTab(url);
+}
+
+}  // namespace weblayer
diff --git a/weblayer/browser/ssl_error_controller_client.h b/weblayer/browser/ssl_error_controller_client.h
new file mode 100644
index 0000000..17e526d
--- /dev/null
+++ b/weblayer/browser/ssl_error_controller_client.h
@@ -0,0 +1,52 @@
+// Copyright 2019 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 WEBLAYER_BROWSER_SSL_ERROR_CONTROLLER_CLIENT_H_
+#define WEBLAYER_BROWSER_SSL_ERROR_CONTROLLER_CLIENT_H_
+
+#include "components/security_interstitials/content/security_interstitial_controller_client.h"
+#include "net/ssl/ssl_info.h"
+#include "url/gurl.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace security_interstitials {
+class MetricsHelper;
+}
+
+namespace weblayer {
+
+// A stripped-down version of the class by the same name in
+// //chrome/browser/ssl, which provides basic functionality for interacting with
+// the SSL interstitial.
+class SSLErrorControllerClient
+    : public security_interstitials::SecurityInterstitialControllerClient {
+ public:
+  SSLErrorControllerClient(
+      content::WebContents* web_contents,
+      int cert_error,
+      const net::SSLInfo& ssl_info,
+      const GURL& request_url,
+      std::unique_ptr<security_interstitials::MetricsHelper> metrics_helper);
+
+  ~SSLErrorControllerClient() override = default;
+
+  // security_interstitials::SecurityInterstitialControllerClient:
+  void GoBack() override;
+  void Proceed() override;
+  void OpenUrlInNewForegroundTab(const GURL& url) override;
+
+ private:
+  const int cert_error_;
+  const net::SSLInfo ssl_info_;
+  const GURL request_url_;
+
+  DISALLOW_COPY_AND_ASSIGN(SSLErrorControllerClient);
+};
+
+}  // namespace weblayer
+
+#endif  // WEBLAYER_BROWSER_SSL_ERROR_CONTROLLER_CLIENT_H_
diff --git a/weblayer/shell/android/BUILD.gn b/weblayer/shell/android/BUILD.gn
index 7559dd98..7a917d00 100644
--- a/weblayer/shell/android/BUILD.gn
+++ b/weblayer/shell/android/BUILD.gn
@@ -160,6 +160,7 @@
 
   # Transitive dependencies
   deps += [
+    "//components/safe_browsing/android:safe_browsing_java",
     "//components/viz/service:service_java",
     "//media/base/android:media_java",
     "//media/capture/video/android:capture_java",